;; Copyright (C) 2002-2004, Yuji Minejima <ggb01164@nifty.ne.jp>
;; ALL RIGHTS RESERVED.
;;
;; $Id: do.lisp,v 1.11 2004/02/20 07:23:42 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.
(defundo-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)
(split-into-declarations-and-forms body)
`(block nil
(,let-operator (,@(mapcar #'(lambda (x) (if (atom x) x (subseq x 0 2)))
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)))))))
(defmacrodo (var-init-step-list test-and-result-forms &body body)
(do-expand var-init-step-list test-and-result-forms body 'parallel))
(defmacrodo* (var-init-step-list test-and-result-forms &body body)
(do-expand var-init-step-list test-and-result-forms body nil))
(defmacrodotimes ((var count-form &optional result-form) &body body)
(let ((max (gensym)))
`(do* ((,max ,count-form)
(,var 0 (1+ ,var)))
((>= ,var ,max) ,result-form)
,@body)))
(defmacrodolist ((var list-form &optional result-form) &body body)
(let ((top (gensym))
(tag (gensym))
(list (gensym)))
(multiple-value-bind (declarations forms)
(split-into-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)))))