summaryrefslogtreecommitdiff
path: root/Sacla/do.lisp
blob: 77afbf7fe8893e78e2b7fcb0629bf20b11570abb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
;; Copyright (C) 2002-2004, Yuji Minejima <ggb01164@nifty.ne.jp>
;; ALL RIGHTS RESERVED.
;;
;; $Id: do.lisp,v 1.12 2004/05/26 07:57:52 yuji Exp $
;; 
;; Redistribution and use in source and binary forms, with or without
;; modification, are permitted provided that the following conditions
;; are met:
;; 
;;  * Redistributions of source code must retain the above copyright
;;    notice, this list of conditions and the following disclaimer.
;;  * Redistributions in binary form must reproduce the above copyright
;;    notice, this list of conditions and the following disclaimer in
;;    the documentation and/or other materials provided with the
;;    distribution.
;; 
;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
;; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
;; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
;; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
;; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
;; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
;; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
;; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
;; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
;; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
;; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


(defun do-expand (var-init-step-list test-and-result-forms body parallel-p)
  (let ((top (gensym))
	(test-form (first test-and-result-forms))
	(result-forms (rest test-and-result-forms))
	(let-operator (if parallel-p 'let 'let*))
	(setq-operator (if parallel-p 'psetq 'setq)))
    (multiple-value-bind (declarations forms) (declarations-and-forms body)
      `(block nil
	(,let-operator (,@(mapcar #'(lambda (x) (if (atom x)
                                                    x
                                                    (list (first x) (second x))))
				  var-init-step-list))
	 ,@declarations
	 (tagbody
	    ,top
	    (when ,test-form (return (progn ,@result-forms)))
	    ,@forms
	    (,setq-operator ,@(mapcan #'(lambda (x)
					  (when (and (consp x)
                                                     (= (length x) 3))
					    `(,(first x) ,(third x))))
				      var-init-step-list))
	    (go ,top)))))))

(defmacro do (var-init-step-list test-and-result-forms &body body)
  (do-expand var-init-step-list test-and-result-forms body 'parallel))

(defmacro do* (var-init-step-list test-and-result-forms &body body)
  (do-expand var-init-step-list test-and-result-forms body nil))

(defmacro dotimes ((var count-form &optional result-form) &body body)
  (let ((max (gensym)))
    `(do* ((,max ,count-form)
	   (,var 0 (1+ ,var)))
      ((>= ,var ,max) ,result-form)
      ,@body)))

(defmacro dolist ((var list-form &optional result-form) &body body)
  (let ((top (gensym))
	(tag (gensym))
	(list (gensym)))
    (multiple-value-bind (declarations forms) (declarations-and-forms body)
      `(block nil
	(let ((,list ,list-form)
	      (,var nil))
	  (declare (ignorable ,var))
	  (unless (atom ,list)
	    (let ((,var (car ,list)))
	      ,@declarations
	      (block ,tag
		(tagbody
		   ,top
		   ,@forms
		   (setq ,list (cdr ,list))
		   (when (atom ,list) (return-from ,tag))
		   (setq ,var (car ,list))
		   (go ,top)))))
	  ,result-form)))))