- (cond ((null ncdrs)
- `(when (setf (cdr ,tail-var) ,tail-form)
- (setq ,tail-var (last (cdr ,tail-var)))))
- ((< ncdrs 0) (return-from loop-collect-rplacd nil))
- ((= ncdrs 0)
- ;; @@@@ Here we have a choice of two idioms:
- ;; (RPLACD TAIL (SETQ TAIL TAIL-FORM))
- ;; (SETQ TAIL (SETF (CDR TAIL) TAIL-FORM)).
- ;; Genera and most others I have seen do better with the
- ;; former.
- `(rplacd ,tail-var (setq ,tail-var ,tail-form)))
- (t `(setq ,tail-var ,(cdr-wrap `(setf (cdr ,tail-var)
- ,tail-form)
- ncdrs))))))
- ;; If not using locatives or something similar to update the
- ;; user's head variable, we've got to set it... It's harmless
- ;; to repeatedly set it unconditionally, and probably faster
- ;; than checking.
- (when user-head-var
- (setq answer
- `(progn ,answer
- (setq ,user-head-var (cdr ,head-var)))))
- answer))))
+ (cond ((null ncdrs)
+ `(when (setf (cdr ,tail-var) ,tail-form)
+ (setq ,tail-var (last (cdr ,tail-var)))))
+ ((< ncdrs 0) (return-from loop-collect-rplacd nil))
+ ((= ncdrs 0)
+ ;; @@@@ Here we have a choice of two idioms:
+ ;; (RPLACD TAIL (SETQ TAIL TAIL-FORM))
+ ;; (SETQ TAIL (SETF (CDR TAIL) TAIL-FORM)).
+ ;; Genera and most others I have seen do better with the
+ ;; former.
+ `(rplacd ,tail-var (setq ,tail-var ,tail-form)))
+ (t `(setq ,tail-var ,(cdr-wrap `(setf (cdr ,tail-var)
+ ,tail-form)
+ ncdrs))))))
+ ;; If not using locatives or something similar to update the
+ ;; user's head variable, we've got to set it... It's harmless
+ ;; to repeatedly set it unconditionally, and probably faster
+ ;; than checking.
+ (when user-head-var
+ (setq answer
+ `(progn ,answer
+ (setq ,user-head-var (cdr ,head-var)))))
+ answer))))
- (which (car (loop-minimax-operations lm)))
- (infinity-data (loop-minimax-infinity-data lm))
- (answer-var (loop-minimax-answer-variable lm))
- (temp-var (loop-minimax-temp-variable lm))
- (flag-var (loop-minimax-flag-variable lm))
- (type (loop-minimax-type lm)))
+ (which (car (loop-minimax-operations lm)))
+ (infinity-data (loop-minimax-infinity-data lm))
+ (answer-var (loop-minimax-answer-variable lm))
+ (temp-var (loop-minimax-temp-variable lm))
+ (flag-var (loop-minimax-flag-variable lm))
+ (type (loop-minimax-type lm)))
- `(let ((,answer-var ,init) (,temp-var ,init) (,flag-var nil))
- (declare (type ,type ,answer-var ,temp-var))
- ,@body)
- `(let ((,answer-var ,(if (eq which 'min)
- (first infinity-data)
- (second infinity-data)))
- (,temp-var ,init))
- (declare (type ,type ,answer-var ,temp-var))
- ,@body))))
+ `(let ((,answer-var ,init) (,temp-var ,init) (,flag-var nil))
+ (declare (type ,type ,answer-var ,temp-var))
+ ,@body)
+ `(let ((,answer-var ,(if (eq which 'min)
+ (first infinity-data)
+ (second infinity-data)))
+ (,temp-var ,init))
+ (declare (type ,type ,answer-var ,temp-var))
+ ,@body))))
- ;; See whether there's any non-null thing here. Recurse
- ;; if the list element is itself a list.
- (do ((tail var)) ((not (consp tail)) tail)
- (when (find-non-null (pop tail)) (return t))))
- (loop-desetq-internal (var val &optional temp)
- ;; returns a list of actions to be performed
- (typecase var
- (null
- (when (consp val)
- ;; Don't lose possible side effects.
- (if (eq (car val) 'prog1)
- ;; These can come from PSETQ or DESETQ below.
- ;; Throw away the value, keep the side effects.
- ;; Special case is for handling an expanded POP.
- (mapcan (lambda (x)
- (and (consp x)
- (or (not (eq (car x) 'car))
- (not (symbolp (cadr x)))
- (not (symbolp (setq x (sb!xc:macroexpand x env)))))
- (cons x nil)))
- (cdr val))
- `(,val))))
- (cons
- (let* ((car (car var))
- (cdr (cdr var))
- (car-non-null (find-non-null car))
- (cdr-non-null (find-non-null cdr)))
- (when (or car-non-null cdr-non-null)
- (if cdr-non-null
- (let* ((temp-p temp)
- (temp (or temp *loop-desetq-temporary*))
- (body `(,@(loop-desetq-internal car
- `(car ,temp))
- (setq ,temp (cdr ,temp))
- ,@(loop-desetq-internal cdr
- temp
- temp))))
- (if temp-p
- `(,@(unless (eq temp val)
- `((setq ,temp ,val)))
- ,@body)
- `((let ((,temp ,val))
- ,@body))))
- ;; no CDRing to do
- (loop-desetq-internal car `(car ,val) temp)))))
- (otherwise
- (unless (eq var val)
- `((setq ,var ,val)))))))
+ ;; See whether there's any non-null thing here. Recurse
+ ;; if the list element is itself a list.
+ (do ((tail var)) ((not (consp tail)) tail)
+ (when (find-non-null (pop tail)) (return t))))
+ (loop-desetq-internal (var val &optional temp)
+ ;; returns a list of actions to be performed
+ (typecase var
+ (null
+ (when (consp val)
+ ;; Don't lose possible side effects.
+ (if (eq (car val) 'prog1)
+ ;; These can come from PSETQ or DESETQ below.
+ ;; Throw away the value, keep the side effects.
+ ;; Special case is for handling an expanded POP.
+ (mapcan (lambda (x)
+ (and (consp x)
+ (or (not (eq (car x) 'car))
+ (not (symbolp (cadr x)))
+ (not (symbolp (setq x (sb!xc:macroexpand x env)))))
+ (cons x nil)))
+ (cdr val))
+ `(,val))))
+ (cons
+ (let* ((car (car var))
+ (cdr (cdr var))
+ (car-non-null (find-non-null car))
+ (cdr-non-null (find-non-null cdr)))
+ (when (or car-non-null cdr-non-null)
+ (if cdr-non-null
+ (let* ((temp-p temp)
+ (temp (or temp *loop-desetq-temporary*))
+ (body `(,@(loop-desetq-internal car
+ `(car ,temp))
+ (setq ,temp (cdr ,temp))
+ ,@(loop-desetq-internal cdr
+ temp
+ temp))))
+ (if temp-p
+ `(,@(unless (eq temp val)
+ `((setq ,temp ,val)))
+ ,@body)
+ `((let ((,temp ,val))
+ ,@body))))
+ ;; no CDRing to do
+ (loop-desetq-internal car `(car ,val) temp)))))
+ (otherwise
+ (unless (eq var val)
+ `((setq ,var ,val)))))))
- ;; with the DECLARATION-INFORMATION function (present in
- ;; CLTL2, removed from ANSI standard) we could set these
- ;; values flexibly. Without DECLARATION-INFORMATION, we have
- ;; to set them to constants.
- ;;
- ;; except FIXME: we've lost all pretence of portability,
- ;; considering this instead an internal implementation, so
- ;; we're free to couple to our own representation of the
- ;; environment.
- (speed 1)
- (space 1))
+ ;; with the DECLARATION-INFORMATION function (present in
+ ;; CLTL2, removed from ANSI standard) we could set these
+ ;; values flexibly. Without DECLARATION-INFORMATION, we have
+ ;; to set them to constants.
+ ;;
+ ;; except FIXME: we've lost all pretence of portability,
+ ;; considering this instead an internal implementation, so
+ ;; we're free to couple to our own representation of the
+ ;; environment.
+ (speed 1)
+ (space 1))
- (let ((ans nil))
- (dolist (x l)
- (when x
- (push x ans)
- (when (and (consp x)
- (member (car x) '(go return return-from)))
- (return nil))))
- (nreverse ans)))
- (pify (l) (if (null (cdr l)) (car l) `(progn ,@l)))
- (makebody ()
- (let ((form `(tagbody
- ,@(psimp (append prologue (nreverse rbefore)))
- next-loop
- ,@(psimp (append main-body
- (nreconc rafter
- `((go next-loop)))))
- end-loop
- ,@(psimp epilogue))))
- (if flagvar `(let ((,flagvar nil)) ,form) form))))
+ (let ((ans nil))
+ (dolist (x l)
+ (when x
+ (push x ans)
+ (when (and (consp x)
+ (member (car x) '(go return return-from)))
+ (return nil))))
+ (nreverse ans)))
+ (pify (l) (if (null (cdr l)) (car l) `(progn ,@l)))
+ (makebody ()
+ (let ((form `(tagbody
+ ,@(psimp (append prologue (nreverse rbefore)))
+ next-loop
+ ,@(psimp (append main-body
+ (nreconc rafter
+ `((go next-loop)))))
+ end-loop
+ ,@(psimp epilogue))))
+ (if flagvar `(let ((,flagvar nil)) ,form) form))))
- (aa rafter (cdr aa))
- (lastdiff nil)
- (count 0)
- (inc nil))
- ((null bb) (return-from loop-body (makebody))) ; Did it.
- (cond ((not (equal (car bb) (car aa))) (setq lastdiff bb count 0))
- ((or (not (setq inc (estimate-code-size (car bb) env)))
- (> (incf count inc) threshold))
- ;; Ok, we have found a non-duplicatable piece of code.
- ;; Everything chronologically after it must be in the
- ;; central body. Everything chronologically at and
- ;; after LASTDIFF goes into the central body under a
- ;; flag test.
- (let ((then nil) (else nil))
- (do () (nil)
- (push (pop rbefore) else)
- (push (pop rafter) then)
- (when (eq rbefore (cdr lastdiff)) (return)))
- (unless flagvar
- (push `(setq ,(setq flagvar *loop-iteration-flag-var*)
- t)
- else))
- (push `(if ,flagvar ,(pify (psimp then)) ,(pify (psimp else)))
- main-body))
- ;; Everything chronologically before lastdiff until the
- ;; non-duplicatable form (CAR BB) is the same in
- ;; RBEFORE and RAFTER, so just copy it into the body.
- (do () (nil)
- (pop rafter)
- (push (pop rbefore) main-body)
- (when (eq rbefore (cdr bb)) (return)))
- (return)))))))
+ (aa rafter (cdr aa))
+ (lastdiff nil)
+ (count 0)
+ (inc nil))
+ ((null bb) (return-from loop-body (makebody))) ; Did it.
+ (cond ((not (equal (car bb) (car aa))) (setq lastdiff bb count 0))
+ ((or (not (setq inc (estimate-code-size (car bb) env)))
+ (> (incf count inc) threshold))
+ ;; Ok, we have found a non-duplicatable piece of code.
+ ;; Everything chronologically after it must be in the
+ ;; central body. Everything chronologically at and
+ ;; after LASTDIFF goes into the central body under a
+ ;; flag test.
+ (let ((then nil) (else nil))
+ (do () (nil)
+ (push (pop rbefore) else)
+ (push (pop rafter) then)
+ (when (eq rbefore (cdr lastdiff)) (return)))
+ (unless flagvar
+ (push `(setq ,(setq flagvar *loop-iteration-flag-var*)
+ t)
+ else))
+ (push `(if ,flagvar ,(pify (psimp then)) ,(pify (psimp else)))
+ main-body))
+ ;; Everything chronologically before lastdiff until the
+ ;; non-duplicatable form (CAR BB) is the same in
+ ;; RBEFORE and RAFTER, so just copy it into the body.
+ (do () (nil)
+ (pop rafter)
+ (push (pop rbefore) main-body)
+ (when (eq rbefore (cdr bb)) (return)))
+ (return)))))))
- '((return 0) (progn 0)
- (null 1) (not 1) (eq 1) (car 1) (cdr 1)
- (when 1) (unless 1) (if 1)
- (caar 2) (cadr 2) (cdar 2) (cddr 2)
- (caaar 3) (caadr 3) (cadar 3) (caddr 3)
- (cdaar 3) (cdadr 3) (cddar 3) (cdddr 3)
- (caaaar 4) (caaadr 4) (caadar 4) (caaddr 4)
- (cadaar 4) (cadadr 4) (caddar 4) (cadddr 4)
- (cdaaar 4) (cdaadr 4) (cdadar 4) (cdaddr 4)
- (cddaar 4) (cddadr 4) (cdddar 4) (cddddr 4)))
+ '((return 0) (progn 0)
+ (null 1) (not 1) (eq 1) (car 1) (cdr 1)
+ (when 1) (unless 1) (if 1)
+ (caar 2) (cadr 2) (cdar 2) (cddr 2)
+ (caaar 3) (caadr 3) (cadar 3) (caddr 3)
+ (cdaar 3) (cdadr 3) (cddar 3) (cdddr 3)
+ (caaaar 4) (caaadr 4) (caadar 4) (caaddr 4)
+ (cadaar 4) (cadadr 4) (caddar 4) (cadddr 4)
+ (cdaaar 4) (cdaadr 4) (cdadar 4) (cdaddr 4)
+ (cddaar 4) (cddadr 4) (cdddar 4) (cddddr 4)))
- ((symbolp x) (multiple-value-bind (new-form expanded-p)
- (sb!xc:macroexpand-1 x env)
- (if expanded-p
- (estimate-code-size-1 new-form env)
- 1)))
- ((atom x) 1) ;; ??? self-evaluating???
- ((symbolp (car x))
- (let ((fn (car x)) (tem nil) (n 0))
- (declare (symbol fn) (fixnum n))
- (macrolet ((f (overhead &optional (args nil args-p))
- `(the fixnum (+ (the fixnum ,overhead)
- (the fixnum
- (list-size ,(if args-p
- args
- '(cdr x))))))))
- (cond ((setq tem (get fn 'estimate-code-size))
- (typecase tem
- (fixnum (f tem))
- (t (funcall tem x env))))
- ((setq tem (assoc fn *special-code-sizes*))
- (f (second tem)))
- ((eq fn 'cond)
- (dolist (clause (cdr x) n)
- (incf n (list-size clause)) (incf n)))
- ((eq fn 'desetq)
- (do ((l (cdr x) (cdr l))) ((null l) n)
- (setq n (+ n
- (destructuring-size (car l))
- (estimate-code-size-1 (cadr l) env)))))
- ((member fn '(setq psetq))
- (do ((l (cdr x) (cdr l))) ((null l) n)
- (setq n (+ n (estimate-code-size-1 (cadr l) env) 1))))
- ((eq fn 'go) 1)
- ((eq fn 'function)
- (if (sb!int:legal-fun-name-p (cadr x))
- 1
- ;; FIXME: This tag appears not to be present
- ;; anywhere.
- (throw 'duplicatable-code-p nil)))
- ((eq fn 'multiple-value-setq)
- (f (length (second x)) (cddr x)))
- ((eq fn 'return-from)
- (1+ (estimate-code-size-1 (third x) env)))
- ((or (special-operator-p fn)
- (member fn *estimate-code-size-punt*))
- (throw 'estimate-code-size nil))
- (t (multiple-value-bind (new-form expanded-p)
- (sb!xc:macroexpand-1 x env)
- (if expanded-p
- (estimate-code-size-1 new-form env)
- (f 3))))))))
- (t (throw 'estimate-code-size nil)))))
+ ((symbolp x) (multiple-value-bind (new-form expanded-p)
+ (sb!xc:macroexpand-1 x env)
+ (if expanded-p
+ (estimate-code-size-1 new-form env)
+ 1)))
+ ((atom x) 1) ;; ??? self-evaluating???
+ ((symbolp (car x))
+ (let ((fn (car x)) (tem nil) (n 0))
+ (declare (symbol fn) (fixnum n))
+ (macrolet ((f (overhead &optional (args nil args-p))
+ `(the fixnum (+ (the fixnum ,overhead)
+ (the fixnum
+ (list-size ,(if args-p
+ args
+ '(cdr x))))))))
+ (cond ((setq tem (get fn 'estimate-code-size))
+ (typecase tem
+ (fixnum (f tem))
+ (t (funcall tem x env))))
+ ((setq tem (assoc fn *special-code-sizes*))
+ (f (second tem)))
+ ((eq fn 'cond)
+ (dolist (clause (cdr x) n)
+ (incf n (list-size clause)) (incf n)))
+ ((eq fn 'desetq)
+ (do ((l (cdr x) (cdr l))) ((null l) n)
+ (setq n (+ n
+ (destructuring-size (car l))
+ (estimate-code-size-1 (cadr l) env)))))
+ ((member fn '(setq psetq))
+ (do ((l (cdr x) (cdr l))) ((null l) n)
+ (setq n (+ n (estimate-code-size-1 (cadr l) env) 1))))
+ ((eq fn 'go) 1)
+ ((eq fn 'function)
+ (if (sb!int:legal-fun-name-p (cadr x))
+ 1
+ ;; FIXME: This tag appears not to be present
+ ;; anywhere.
+ (throw 'duplicatable-code-p nil)))
+ ((eq fn 'multiple-value-setq)
+ (f (length (second x)) (cddr x)))
+ ((eq fn 'return-from)
+ (1+ (estimate-code-size-1 (third x) env)))
+ ((or (special-operator-p fn)
+ (member fn *estimate-code-size-punt*))
+ (throw 'estimate-code-size nil))
+ (t (multiple-value-bind (new-form expanded-p)
+ (sb!xc:macroexpand-1 x env)
+ (if expanded-p
+ (estimate-code-size-1 new-form env)
+ (f 3))))))))
+ (t (throw 'estimate-code-size nil)))))
(sb!int:defmacro-mundanely loop-destructuring-bind
(lambda-list arg-list &rest body)
(let ((*ignores* nil))
(declare (special *ignores*))
(let ((d-var-lambda-list (subst-gensyms-for-nil lambda-list)))
`(destructuring-bind ,d-var-lambda-list
(sb!int:defmacro-mundanely loop-destructuring-bind
(lambda-list arg-list &rest body)
(let ((*ignores* nil))
(declare (special *ignores*))
(let ((d-var-lambda-list (subst-gensyms-for-nil lambda-list)))
`(destructuring-bind ,d-var-lambda-list
- (*loop-source-context* nil)
- (*loop-vars* nil)
- (*loop-named-vars* nil)
- (*loop-declarations* nil)
- (*loop-desetq-crocks* nil)
- (*loop-bind-stack* nil)
- (*loop-prologue* nil)
- (*loop-wrappers* nil)
- (*loop-before-loop* nil)
- (*loop-body* nil)
- (*loop-emitted-body* nil)
- (*loop-after-body* nil)
- (*loop-epilogue* nil)
- (*loop-after-epilogue* nil)
- (*loop-final-value-culprit* nil)
- (*loop-inside-conditional* nil)
- (*loop-when-it-var* nil)
- (*loop-never-stepped-var* nil)
- (*loop-names* nil)
- (*loop-collection-cruft* nil))
+ (*loop-source-context* nil)
+ (*loop-vars* nil)
+ (*loop-named-vars* nil)
+ (*loop-declarations* nil)
+ (*loop-desetq-crocks* nil)
+ (*loop-bind-stack* nil)
+ (*loop-prologue* nil)
+ (*loop-wrappers* nil)
+ (*loop-before-loop* nil)
+ (*loop-body* nil)
+ (*loop-emitted-body* nil)
+ (*loop-after-body* nil)
+ (*loop-epilogue* nil)
+ (*loop-after-epilogue* nil)
+ (*loop-final-value-culprit* nil)
+ (*loop-inside-conditional* nil)
+ (*loop-when-it-var* nil)
+ (*loop-never-stepped-var* nil)
+ (*loop-names* nil)
+ (*loop-collection-cruft* nil))
- ,(nreverse *loop-prologue*)
- ,(nreverse *loop-before-loop*)
- ,(nreverse *loop-body*)
- ,(nreverse *loop-after-body*)
- ,(nreconc *loop-epilogue*
- (nreverse *loop-after-epilogue*)))))
+ ,(nreverse *loop-prologue*)
+ ,(nreverse *loop-before-loop*)
+ ,(nreverse *loop-body*)
+ ,(nreverse *loop-after-body*)
+ ,(nreconc *loop-epilogue*
+ (nreverse *loop-after-epilogue*)))))
- (let ((vars (first entry))
- (dcls (second entry))
- (crocks (third entry))
- (wrappers (fourth entry)))
- (dolist (w wrappers)
- (setq answer (append w (list answer))))
- (when (or vars dcls crocks)
- (let ((forms (list answer)))
- ;;(when crocks (push crocks forms))
- (when dcls (push `(declare ,@dcls) forms))
- (setq answer `(,(if vars 'let 'locally)
- ,vars
- ,@(loop-build-destructuring-bindings crocks
- forms)))))))
+ (let ((vars (first entry))
+ (dcls (second entry))
+ (crocks (third entry))
+ (wrappers (fourth entry)))
+ (dolist (w wrappers)
+ (setq answer (append w (list answer))))
+ (when (or vars dcls crocks)
+ (let ((forms (list answer)))
+ ;;(when crocks (push crocks forms))
+ (when dcls (push `(declare ,@dcls) forms))
+ (setq answer `(,(if vars 'let 'locally)
+ ,vars
+ ,@(loop-build-destructuring-bindings crocks
+ forms)))))))
- (loop-error "~S found where LOOP keyword expected" keyword))
- (t (setq *loop-source-context* *loop-source-code*)
- (loop-pop-source)
- (cond ((setq tem
- (loop-lookup-keyword keyword
- (loop-universe-keywords
- *loop-universe*)))
- ;; It's a "miscellaneous" toplevel LOOP keyword (DO,
- ;; COLLECT, NAMED, etc.)
- (apply (symbol-function (first tem)) (rest tem)))
- ((setq tem
- (loop-lookup-keyword keyword
- (loop-universe-iteration-keywords *loop-universe*)))
- (loop-hack-iteration tem))
- ((loop-tmember keyword '(and else))
- ;; The alternative is to ignore it, i.e. let it go
- ;; around to the next keyword...
- (loop-error "secondary clause misplaced at top level in LOOP macro: ~S ~S ~S ..."
- keyword
- (car *loop-source-code*)
- (cadr *loop-source-code*)))
- (t (loop-error "unknown LOOP keyword: ~S" keyword))))))))
+ (loop-error "~S found where LOOP keyword expected" keyword))
+ (t (setq *loop-source-context* *loop-source-code*)
+ (loop-pop-source)
+ (cond ((setq tem
+ (loop-lookup-keyword keyword
+ (loop-universe-keywords
+ *loop-universe*)))
+ ;; It's a "miscellaneous" toplevel LOOP keyword (DO,
+ ;; COLLECT, NAMED, etc.)
+ (apply (symbol-function (first tem)) (rest tem)))
+ ((setq tem
+ (loop-lookup-keyword keyword
+ (loop-universe-iteration-keywords *loop-universe*)))
+ (loop-hack-iteration tem))
+ ((loop-tmember keyword '(and else))
+ ;; The alternative is to ignore it, i.e. let it go
+ ;; around to the next keyword...
+ (loop-error "secondary clause misplaced at top level in LOOP macro: ~S ~S ~S ..."
+ keyword
+ (car *loop-source-code*)
+ (cadr *loop-source-code*)))
+ (t (loop-error "unknown LOOP keyword: ~S" keyword))))))))
- (cond ((loop-tequal z 'of-type)
- ;; This is the syntactically unambigous form in that
- ;; the form of the type specifier does not matter.
- ;; Also, it is assumed that the type specifier is
- ;; unambiguously, and without need of translation, a
- ;; common lisp type specifier or pattern (matching the
- ;; variable) thereof.
- (loop-pop-source)
- (loop-pop-source))
-
- ((symbolp z)
- ;; This is the (sort of) "old" syntax, even though we
- ;; didn't used to support all of these type symbols.
- (let ((type-spec (or (gethash z
- (loop-universe-type-symbols
- *loop-universe*))
- (gethash (symbol-name z)
- (loop-universe-type-keywords
- *loop-universe*)))))
- (when type-spec
- (loop-pop-source)
- type-spec)))
- (t
- ;; This is our sort-of old syntax. But this is only
- ;; valid for when we are destructuring, so we will be
- ;; compulsive (should we really be?) and require that
- ;; we in fact be doing variable destructuring here. We
- ;; must translate the old keyword pattern typespec
- ;; into a fully-specified pattern of real type
- ;; specifiers here.
- (if (consp variable)
- (unless (consp z)
- (loop-error
- "~S found where a LOOP keyword, LOOP type keyword, or LOOP type pattern expected"
- z))
- (loop-error "~S found where a LOOP keyword or LOOP type keyword expected" z))
- (loop-pop-source)
- (labels ((translate (k v)
- (cond ((null k) nil)
- ((atom k)
- (replicate
- (or (gethash k
- (loop-universe-type-symbols
- *loop-universe*))
- (gethash (symbol-name k)
- (loop-universe-type-keywords
- *loop-universe*))
- (loop-error
- "The destructuring type pattern ~S contains the unrecognized type keyword ~S."
- z k))
- v))
- ((atom v)
- (loop-error
- "The destructuring type pattern ~S doesn't match the variable pattern ~S."
- z variable))
- (t (cons (translate (car k) (car v))
- (translate (cdr k) (cdr v))))))
- (replicate (typ v)
- (if (atom v)
- typ
- (cons (replicate typ (car v))
- (replicate typ (cdr v))))))
- (translate z variable)))))))
+ (cond ((loop-tequal z 'of-type)
+ ;; This is the syntactically unambigous form in that
+ ;; the form of the type specifier does not matter.
+ ;; Also, it is assumed that the type specifier is
+ ;; unambiguously, and without need of translation, a
+ ;; common lisp type specifier or pattern (matching the
+ ;; variable) thereof.
+ (loop-pop-source)
+ (loop-pop-source))
+
+ ((symbolp z)
+ ;; This is the (sort of) "old" syntax, even though we
+ ;; didn't used to support all of these type symbols.
+ (let ((type-spec (or (gethash z
+ (loop-universe-type-symbols
+ *loop-universe*))
+ (gethash (symbol-name z)
+ (loop-universe-type-keywords
+ *loop-universe*)))))
+ (when type-spec
+ (loop-pop-source)
+ type-spec)))
+ (t
+ ;; This is our sort-of old syntax. But this is only
+ ;; valid for when we are destructuring, so we will be
+ ;; compulsive (should we really be?) and require that
+ ;; we in fact be doing variable destructuring here. We
+ ;; must translate the old keyword pattern typespec
+ ;; into a fully-specified pattern of real type
+ ;; specifiers here.
+ (if (consp variable)
+ (unless (consp z)
+ (loop-error
+ "~S found where a LOOP keyword, LOOP type keyword, or LOOP type pattern expected"
+ z))
+ (loop-error "~S found where a LOOP keyword or LOOP type keyword expected" z))
+ (loop-pop-source)
+ (labels ((translate (k v)
+ (cond ((null k) nil)
+ ((atom k)
+ (replicate
+ (or (gethash k
+ (loop-universe-type-symbols
+ *loop-universe*))
+ (gethash (symbol-name k)
+ (loop-universe-type-keywords
+ *loop-universe*))
+ (loop-error
+ "The destructuring type pattern ~S contains the unrecognized type keyword ~S."
+ z k))
+ v))
+ ((atom v)
+ (loop-error
+ "The destructuring type pattern ~S doesn't match the variable pattern ~S."
+ z variable))
+ (t (cons (translate (car k) (car v))
+ (translate (cdr k) (cdr v))))))
+ (replicate (typ v)
+ (if (atom v)
+ typ
+ (cons (replicate typ (car v))
+ (replicate typ (cdr v))))))
+ (translate z variable)))))))
- (setq name (gensym "LOOP-IGNORE-"))
- (push (list name initialization) *loop-vars*)
- (if (null initialization)
- (push `(ignore ,name) *loop-declarations*)
- (loop-declare-var name dtype)))
- ((atom name)
+ (setq name (gensym "LOOP-IGNORE-"))
+ (push (list name initialization) *loop-vars*)
+ (if (null initialization)
+ (push `(ignore ,name) *loop-declarations*)
+ (loop-declare-var name dtype)))
+ ((atom name)
- (unless (symbolp name)
- (loop-error "bad variable ~S somewhere in LOOP" name))
- (loop-declare-var name dtype step-var-p)
- ;; We use ASSOC on this list to check for duplications (above),
- ;; so don't optimize out this list:
- (push (list name (or initialization (loop-typed-init dtype step-var-p)))
- *loop-vars*))
- (initialization
- (let ((newvar (gensym "LOOP-DESTRUCTURE-")))
+ (unless (symbolp name)
+ (loop-error "bad variable ~S somewhere in LOOP" name))
+ (loop-declare-var name dtype step-var-p)
+ ;; We use ASSOC on this list to check for duplications (above),
+ ;; so don't optimize out this list:
+ (push (list name (or initialization (loop-typed-init dtype step-var-p)))
+ *loop-vars*))
+ (initialization
+ (let ((newvar (gensym "LOOP-DESTRUCTURE-")))
- ((symbolp name)
- (unless (sb!xc:subtypep t dtype)
- (let ((dtype (let ((init (loop-typed-init dtype step-var-p)))
- (if (sb!xc:typep init dtype)
- dtype
- `(or (member ,init) ,dtype)))))
- (push `(type ,dtype ,name) *loop-declarations*))))
- ((consp name)
- (cond ((consp dtype)
- (loop-declare-var (car name) (car dtype))
- (loop-declare-var (cdr name) (cdr dtype)))
- (t (loop-declare-var (car name) dtype)
- (loop-declare-var (cdr name) dtype))))
- (t (error "invalid LOOP variable passed in: ~S" name))))
+ ((symbolp name)
+ (unless (sb!xc:subtypep t dtype)
+ (let ((dtype (let ((init (loop-typed-init dtype step-var-p)))
+ (if (sb!xc:typep init dtype)
+ dtype
+ `(or (member ,init) ,dtype)))))
+ (push `(type ,dtype ,name) *loop-declarations*))))
+ ((consp name)
+ (cond ((consp dtype)
+ (loop-declare-var (car name) (car dtype))
+ (loop-declare-var (cdr name) (cdr dtype)))
+ (t (loop-declare-var (car name) dtype)
+ (loop-declare-var (cdr name) dtype))))
+ (t (error "invalid LOOP variable passed in: ~S" name))))
- (do ((body nil)) (nil)
- (let ((key (car *loop-source-code*)) (*loop-body* nil) data)
- (cond ((not (symbolp key))
- (loop-error
- "~S found where keyword expected getting LOOP clause after ~S"
- key for))
- (t (setq *loop-source-context* *loop-source-code*)
- (loop-pop-source)
- (when (and (loop-tequal (car *loop-source-code*) 'it)
- first-clause-p)
- (setq *loop-source-code*
- (cons (or it-p
- (setq it-p
- (loop-when-it-var)))
- (cdr *loop-source-code*))))
- (cond ((or (not (setq data (loop-lookup-keyword
- key (loop-universe-keywords *loop-universe*))))
- (progn (apply (symbol-function (car data))
- (cdr data))
- (null *loop-body*)))
- (loop-error
- "~S does not introduce a LOOP clause that can follow ~S."
- key for))
- (t (setq body (nreconc *loop-body* body)))))))
- (setq first-clause-p nil)
- (if (loop-tequal (car *loop-source-code*) :and)
- (loop-pop-source)
- (return (if (cdr body)
- `(progn ,@(nreverse body))
- (car body)))))))
+ (do ((body nil)) (nil)
+ (let ((key (car *loop-source-code*)) (*loop-body* nil) data)
+ (cond ((not (symbolp key))
+ (loop-error
+ "~S found where keyword expected getting LOOP clause after ~S"
+ key for))
+ (t (setq *loop-source-context* *loop-source-code*)
+ (loop-pop-source)
+ (when (and (loop-tequal (car *loop-source-code*) 'it)
+ first-clause-p)
+ (setq *loop-source-code*
+ (cons (or it-p
+ (setq it-p
+ (loop-when-it-var)))
+ (cdr *loop-source-code*))))
+ (cond ((or (not (setq data (loop-lookup-keyword
+ key (loop-universe-keywords *loop-universe*))))
+ (progn (apply (symbol-function (car data))
+ (cdr data))
+ (null *loop-body*)))
+ (loop-error
+ "~S does not introduce a LOOP clause that can follow ~S."
+ key for))
+ (t (setq body (nreconc *loop-body* body)))))))
+ (setq first-clause-p nil)
+ (if (loop-tequal (car *loop-source-code*) :and)
+ (loop-pop-source)
+ (return (if (cdr body)
+ `(progn ,@(nreverse body))
+ (car body)))))))
- (else (when (loop-tequal (car *loop-source-code*) :else)
- (loop-pop-source)
- (list (get-clause :else)))))
- (when (loop-tequal (car *loop-source-code*) :end)
- (loop-pop-source))
- (when it-p (setq form `(setq ,it-p ,form)))
- (loop-pseudo-body
- `(if ,(if negatep `(not ,form) form)
- ,then
- ,@else))))))
+ (else (when (loop-tequal (car *loop-source-code*) :else)
+ (loop-pop-source)
+ (list (get-clause :else)))))
+ (when (loop-tequal (car *loop-source-code*) :end)
+ (loop-pop-source))
+ (when it-p (setq form `(setq ,it-p ,form)))
+ (loop-pseudo-body
+ `(if ,(if negatep `(not ,form) form)
+ ,then
+ ,@else))))))
- (when (and name (loop-var-p name))
- (loop-error "Variable ~S in INTO clause is a duplicate" name))
- (push (setq cruft (make-loop-collector
- :name name :class class
- :history (list collector) :dtype dtype))
- *loop-collection-cruft*))
- (t (unless (eq (loop-collector-class cruft) class)
- (loop-error
- "incompatible kinds of LOOP value accumulation specified for collecting~@
+ (when (and name (loop-var-p name))
+ (loop-error "Variable ~S in INTO clause is a duplicate" name))
+ (push (setq cruft (make-loop-collector
+ :name name :class class
+ :history (list collector) :dtype dtype))
+ *loop-collection-cruft*))
+ (t (unless (eq (loop-collector-class cruft) class)
+ (loop-error
+ "incompatible kinds of LOOP value accumulation specified for collecting~@
- (setf (loop-collector-tempvars lc)
- (setq tempvars (list* (gensym "LOOP-LIST-HEAD-")
- (gensym "LOOP-LIST-TAIL-")
- (and (loop-collector-name lc)
- (list (loop-collector-name lc))))))
- (push `(with-loop-list-collection-head ,tempvars) *loop-wrappers*)
- (unless (loop-collector-name lc)
- (loop-emit-final-value `(loop-collect-answer ,(car tempvars)
- ,@(cddr tempvars)))))
+ (setf (loop-collector-tempvars lc)
+ (setq tempvars (list* (gensym "LOOP-LIST-HEAD-")
+ (gensym "LOOP-LIST-TAIL-")
+ (and (loop-collector-name lc)
+ (list (loop-collector-name lc))))))
+ (push `(with-loop-list-collection-head ,tempvars) *loop-wrappers*)
+ (unless (loop-collector-name lc)
+ (loop-emit-final-value `(loop-collect-answer ,(car tempvars)
+ ,@(cddr tempvars)))))
- (setf (loop-collector-tempvars lc)
- (setq tempvars (list (loop-make-var
- (or (loop-collector-name lc)
- (gensym "LOOP-SUM-"))
- nil (loop-collector-dtype lc)))))
- (unless (loop-collector-name lc)
- (loop-emit-final-value (car (loop-collector-tempvars lc)))))
+ (setf (loop-collector-tempvars lc)
+ (setq tempvars (list (loop-make-var
+ (or (loop-collector-name lc)
+ (gensym "LOOP-SUM-"))
+ nil (loop-collector-dtype lc)))))
+ (unless (loop-collector-name lc)
+ (loop-emit-final-value (car (loop-collector-tempvars lc)))))
- (setf (loop-collector-data lc)
- (setq data (make-loop-minimax
- (or (loop-collector-name lc)
- (gensym "LOOP-MAXMIN-"))
- (loop-collector-dtype lc))))
- (unless (loop-collector-name lc)
- (loop-emit-final-value (loop-minimax-answer-variable data))))
+ (setf (loop-collector-data lc)
+ (setq data (make-loop-minimax
+ (or (loop-collector-name lc)
+ (gensym "LOOP-MAXMIN-"))
+ (loop-collector-dtype lc))))
+ (unless (loop-collector-name lc)
+ (loop-emit-final-value (loop-minimax-answer-variable data))))
(let ((var (loop-make-var (gensym "LOOP-REPEAT-") `(ceiling ,form) type)))
(push `(if (<= ,var 0) (go end-loop) (decf ,var)) *loop-before-loop*)
(push `(if (<= ,var 0) (go end-loop) (decf ,var)) *loop-after-body*)
(let ((var (loop-make-var (gensym "LOOP-REPEAT-") `(ceiling ,form) type)))
(push `(if (<= ,var 0) (go end-loop) (decf ,var)) *loop-before-loop*)
(push `(if (<= ,var 0) (go end-loop) (decf ,var)) *loop-after-body*)
- (cond ((null list-of-forms) nil)
- ((member t list-of-forms) '(go end-loop))
- (t `(when ,(if (null (cdr (setq list-of-forms
- (nreverse list-of-forms))))
- (car list-of-forms)
- (cons 'or list-of-forms))
- (go end-loop))))))
+ (cond ((null list-of-forms) nil)
+ ((member t list-of-forms) '(go end-loop))
+ (t `(when ,(if (null (cdr (setq list-of-forms
+ (nreverse list-of-forms))))
+ (car list-of-forms)
+ (cons 'or list-of-forms))
+ (go end-loop))))))
- (setq *loop-before-loop*
- (list* (loop-make-desetq pre-loop-pseudo-steps)
- (make-endtest pre-loop-post-step-tests)
- (loop-make-psetq pre-loop-steps)
- (make-endtest pre-loop-pre-step-tests)
- *loop-before-loop*))
- (setq *loop-after-body*
- (list* (loop-make-desetq pseudo-steps)
- (make-endtest post-step-tests)
- (loop-make-psetq steps)
- (make-endtest pre-step-tests)
- *loop-after-body*))
- (loop-bind-block)
- (return nil))
- (loop-pop-source) ; Flush the "AND".
+ (setq *loop-before-loop*
+ (list* (loop-make-desetq pre-loop-pseudo-steps)
+ (make-endtest pre-loop-post-step-tests)
+ (loop-make-psetq pre-loop-steps)
+ (make-endtest pre-loop-pre-step-tests)
+ *loop-before-loop*))
+ (setq *loop-after-body*
+ (list* (loop-make-desetq pseudo-steps)
+ (make-endtest post-step-tests)
+ (loop-make-psetq steps)
+ (make-endtest pre-step-tests)
+ *loop-after-body*))
+ (loop-bind-block)
+ (return nil))
+ (loop-pop-source) ; Flush the "AND".
- ;; Then we are the same as "FOR x FIRST y THEN z".
- (loop-pop-source)
- `(() (,var ,(loop-get-form)) () ()
- () (,var ,val) () ()))
- (t ;; We are the same as "FOR x = y".
- `(() (,var ,val) () ()))))
+ ;; Then we are the same as "FOR x FIRST y THEN z".
+ (loop-pop-source)
+ `(() (,var ,(loop-get-form)) () ()
+ () (,var ,val) () ()))
+ (t ;; We are the same as "FOR x = y".
+ `(() (,var ,val) () ()))))
- (length-form (cond ((not constantp)
- (let ((v (gensym "LOOP-ACROSS-LIMIT-")))
- (push `(setq ,v (length ,vector-var))
- *loop-prologue*)
- (loop-make-var v 0 'fixnum)))
- (t (setq length (length vector-value)))))
- (first-test `(>= ,index-var ,length-form))
- (other-test first-test)
- (step `(,var (aref ,vector-var ,index-var)))
- (pstep `(,index-var (1+ ,index-var))))
- (declare (fixnum length))
- (when constantp
- (setq first-test (= length 0))
- (when (<= length 1)
- (setq other-test t)))
- `(,other-test ,step () ,pstep
- ,@(and (not (eq first-test other-test))
- `(,first-test ,step () ,pstep)))))))
+ (length-form (cond ((not constantp)
+ (let ((v (gensym "LOOP-ACROSS-LIMIT-")))
+ (push `(setq ,v (length ,vector-var))
+ *loop-prologue*)
+ (loop-make-var v 0 'fixnum)))
+ (t (setq length (length vector-value)))))
+ (first-test `(>= ,index-var ,length-form))
+ (other-test first-test)
+ (step `(,var (aref ,vector-var ,index-var)))
+ (pstep `(,index-var (1+ ,index-var))))
+ (declare (fixnum length))
+ (when constantp
+ (setq first-test (= length 0))
+ (when (<= length 1)
+ (setq other-test t)))
+ `(,other-test ,step () ,pstep
+ ,@(and (not (eq first-test other-test))
+ `(,first-test ,step () ,pstep)))))))
- (loop-warn "Use of QUOTE around stepping function in LOOP will be left verbatim.")
- `(funcall ,stepper ,listvar))
- ((and (consp stepper) (eq (car stepper) 'function))
- (list (cadr stepper) listvar))
- (t
- `(funcall ,(loop-make-var (gensym "LOOP-FN-") stepper 'function)
- ,listvar)))))
+ (loop-warn "Use of QUOTE around stepping function in LOOP will be left verbatim.")
+ `(funcall ,stepper ,listvar))
+ ((and (consp stepper) (eq (car stepper) 'function))
+ (list (cadr stepper) listvar))
+ (t
+ `(funcall ,(loop-make-var (gensym "LOOP-FN-") stepper 'function)
+ ,listvar)))))
- (let* ((first-endtest
- ;; mysterious comment from original CMU CL sources:
- ;; the following should use `atom' instead of `endp',
- ;; per [bug2428]
- `(atom ,listvar))
- (other-endtest first-endtest))
- (when (and constantp (listp list-value))
- (setq first-endtest (null list-value)))
- (cond ((eq var listvar)
- ;; The contour of the loop is different because we
- ;; use the user's variable...
- `(() (,listvar ,list-step)
- ,other-endtest () () () ,first-endtest ()))
- (t (let ((step `(,var ,listvar))
- (pseudo `(,listvar ,list-step)))
- `(,other-endtest ,step () ,pseudo
- ,@(and (not (eq first-endtest other-endtest))
- `(,first-endtest ,step () ,pseudo)))))))))))
+ (let* ((first-endtest
+ ;; mysterious comment from original CMU CL sources:
+ ;; the following should use `atom' instead of `endp',
+ ;; per [bug2428]
+ `(atom ,listvar))
+ (other-endtest first-endtest))
+ (when (and constantp (listp list-value))
+ (setq first-endtest (null list-value)))
+ (cond ((eq var listvar)
+ ;; The contour of the loop is different because we
+ ;; use the user's variable...
+ `(() (,listvar ,list-step)
+ ,other-endtest () () () ,first-endtest ()))
+ (t (let ((step `(,var ,listvar))
+ (pseudo `(,listvar ,list-step)))
+ `(,other-endtest ,step () ,pseudo
+ ,@(and (not (eq first-endtest other-endtest))
+ `(,first-endtest ,step () ,pseudo)))))))))))
- (let* ((first-endtest `(endp ,listvar))
- (other-endtest first-endtest)
- (step `(,var (car ,listvar)))
- (pseudo-step `(,listvar ,list-step)))
- (when (and constantp (listp list-value))
- (setq first-endtest (null list-value)))
- `(,other-endtest ,step () ,pseudo-step
- ,@(and (not (eq first-endtest other-endtest))
- `(,first-endtest ,step () ,pseudo-step))))))))
+ (let* ((first-endtest `(endp ,listvar))
+ (other-endtest first-endtest)
+ (step `(,var (car ,listvar)))
+ (pseudo-step `(,listvar ,list-step)))
+ (when (and constantp (listp list-value))
+ (setq first-endtest (null list-value)))
+ `(,other-endtest ,step () ,pseudo-step
+ ,@(and (not (eq first-endtest other-endtest))
+ `(,first-endtest ,step () ,pseudo-step))))))))
- ((loop-tequal (car *loop-source-code*) :and)
- (loop-pop-source)
- (setq inclusive t)
- (unless (loop-tmember (car *loop-source-code*)
- '(:its :each :his :her))
- (loop-error "~S was found where ITS or EACH expected in LOOP iteration path syntax."
- (car *loop-source-code*)))
- (loop-pop-source)
- (setq path (loop-pop-source))
- (setq initial-prepositions `((:in ,val))))
- (t (loop-error "unrecognizable LOOP iteration path syntax: missing EACH or THE?")))
+ ((loop-tequal (car *loop-source-code*) :and)
+ (loop-pop-source)
+ (setq inclusive t)
+ (unless (loop-tmember (car *loop-source-code*)
+ '(:its :each :his :her))
+ (loop-error "~S was found where ITS or EACH expected in LOOP iteration path syntax."
+ (car *loop-source-code*)))
+ (loop-pop-source)
+ (setq path (loop-pop-source))
+ (setq initial-prepositions `((:in ,val))))
+ (t (loop-error "unrecognizable LOOP iteration path syntax: missing EACH or THE?")))
- (loop-error
- "~S was found where a LOOP iteration path name was expected."
- path))
- ((not (setq data (loop-lookup-keyword path (loop-universe-path-keywords *loop-universe*))))
- (loop-error "~S is not the name of a LOOP iteration path." path))
- ((and inclusive (not (loop-path-inclusive-permitted data)))
- (loop-error "\"Inclusive\" iteration is not possible with the ~S LOOP iteration path." path)))
+ (loop-error
+ "~S was found where a LOOP iteration path name was expected."
+ path))
+ ((not (setq data (loop-lookup-keyword path (loop-universe-path-keywords *loop-universe*))))
+ (loop-error "~S is not the name of a LOOP iteration path." path))
+ ((and inclusive (not (loop-path-inclusive-permitted data)))
+ (loop-error "\"Inclusive\" iteration is not possible with the ~S LOOP iteration path." path)))
(when *loop-named-vars*
(loop-error "Unused USING vars: ~S." *loop-named-vars*))
;; STUFF is now (bindings prologue-forms . stuff-to-pass-back).
;; Protect the system from the user and the user from himself.
(unless (member (length stuff) '(6 10))
(loop-error "Value passed back by LOOP iteration path function for path ~S has invalid length."
(when *loop-named-vars*
(loop-error "Unused USING vars: ~S." *loop-named-vars*))
;; STUFF is now (bindings prologue-forms . stuff-to-pass-back).
;; Protect the system from the user and the user from himself.
(unless (member (length stuff) '(6 10))
(loop-error "Value passed back by LOOP iteration path function for path ~S has invalid length."
- (when (member this-prep disallowed-prepositions)
- (loop-error
- (if (member this-prep used-prepositions)
- "A ~S prepositional phrase occurs multiply for some LOOP clause."
- "Preposition ~S was used when some other preposition has subsumed it.")
- token))
- (setq used-prepositions (if (listp this-group)
- (append this-group used-prepositions)
- (cons this-group used-prepositions)))
- (loop-pop-source)
- (push (list this-prep (loop-get-form)) prepositional-phrases))
- ((and using-allowed (loop-tequal token 'using))
- (loop-pop-source)
- (do ((z (loop-pop-source) (loop-pop-source)) (tem)) (nil)
- (when (cadr z)
- (if (setq tem (loop-tassoc (car z) *loop-named-vars*))
- (loop-error
- "The variable substitution for ~S occurs twice in a USING phrase,~@
+ (when (member this-prep disallowed-prepositions)
+ (loop-error
+ (if (member this-prep used-prepositions)
+ "A ~S prepositional phrase occurs multiply for some LOOP clause."
+ "Preposition ~S was used when some other preposition has subsumed it.")
+ token))
+ (setq used-prepositions (if (listp this-group)
+ (append this-group used-prepositions)
+ (cons this-group used-prepositions)))
+ (loop-pop-source)
+ (push (list this-prep (loop-get-form)) prepositional-phrases))
+ ((and using-allowed (loop-tequal token 'using))
+ (loop-pop-source)
+ (do ((z (loop-pop-source) (loop-pop-source)) (tem)) (nil)
+ (when (cadr z)
+ (if (setq tem (loop-tassoc (car z) *loop-named-vars*))
+ (loop-error
+ "The variable substitution for ~S occurs twice in a USING phrase,~@
- (sequencep nil) ; T if sequence arg has been provided
- (testfn nil) ; endtest function
- (test nil) ; endtest form
- (stepby (1+ (or (loop-typed-init indexv-type) 0))) ; our increment
- (stepby-constantp t)
- (step nil) ; step form
- (dir nil) ; direction of stepping: NIL, :UP, :DOWN
- (inclusive-iteration nil) ; T if include last index
- (start-given nil) ; T when prep phrase has specified start
- (start-value nil)
- (start-constantp nil)
- (limit-given nil) ; T when prep phrase has specified end
- (limit-constantp nil)
- (limit-value nil)
- )
+ (sequencep nil) ; T if sequence arg has been provided
+ (testfn nil) ; endtest function
+ (test nil) ; endtest form
+ (stepby (1+ (or (loop-typed-init indexv-type) 0))) ; our increment
+ (stepby-constantp t)
+ (step nil) ; step form
+ (dir nil) ; direction of stepping: NIL, :UP, :DOWN
+ (inclusive-iteration nil) ; T if include last index
+ (start-given nil) ; T when prep phrase has specified start
+ (start-value nil)
+ (start-constantp nil)
+ (limit-given nil) ; T when prep phrase has specified end
+ (limit-constantp nil)
+ (limit-value nil)
+ )
- (setq prep (caar l) form (cadar l))
- (case prep
- ((:of :in)
- (setq sequencep t)
- (loop-make-var sequence-variable form sequence-type))
- ((:from :downfrom :upfrom)
- (setq start-given t)
- (cond ((eq prep :downfrom) (setq dir ':down))
- ((eq prep :upfrom) (setq dir ':up)))
- (multiple-value-setq (form start-constantp start-value)
- (loop-constant-fold-if-possible form indexv-type))
- (assert-index-for-arithmetic indexv)
- ;; KLUDGE: loop-make-var generates a temporary symbol for
- ;; indexv if it is NIL. We have to use it to have the index
- ;; actually count
- (setq indexv (loop-make-var indexv form indexv-type)))
- ((:upto :to :downto :above :below)
- (cond ((loop-tequal prep :upto) (setq inclusive-iteration
- (setq dir ':up)))
- ((loop-tequal prep :to) (setq inclusive-iteration t))
- ((loop-tequal prep :downto) (setq inclusive-iteration
- (setq dir ':down)))
- ((loop-tequal prep :above) (setq dir ':down))
- ((loop-tequal prep :below) (setq dir ':up)))
- (setq limit-given t)
- (multiple-value-setq (form limit-constantp limit-value)
- (loop-constant-fold-if-possible form `(and ,indexv-type real)))
- (setq endform (if limit-constantp
- `',limit-value
- (loop-make-var
- (gensym "LOOP-LIMIT-") form
- `(and ,indexv-type real)))))
- (:by
- (multiple-value-setq (form stepby-constantp stepby)
- (loop-constant-fold-if-possible form `(and ,indexv-type (real (0)))))
- (unless stepby-constantp
- (loop-make-var (setq stepby (gensym "LOOP-STEP-BY-"))
- form
- `(and ,indexv-type (real (0)))
- t)))
- (t (loop-error
- "~S invalid preposition in sequencing or sequence path;~@
+ (setq prep (caar l) form (cadar l))
+ (case prep
+ ((:of :in)
+ (setq sequencep t)
+ (loop-make-var sequence-variable form sequence-type))
+ ((:from :downfrom :upfrom)
+ (setq start-given t)
+ (cond ((eq prep :downfrom) (setq dir ':down))
+ ((eq prep :upfrom) (setq dir ':up)))
+ (multiple-value-setq (form start-constantp start-value)
+ (loop-constant-fold-if-possible form indexv-type))
+ (assert-index-for-arithmetic indexv)
+ ;; KLUDGE: loop-make-var generates a temporary symbol for
+ ;; indexv if it is NIL. We have to use it to have the index
+ ;; actually count
+ (setq indexv (loop-make-var indexv form indexv-type)))
+ ((:upto :to :downto :above :below)
+ (cond ((loop-tequal prep :upto) (setq inclusive-iteration
+ (setq dir ':up)))
+ ((loop-tequal prep :to) (setq inclusive-iteration t))
+ ((loop-tequal prep :downto) (setq inclusive-iteration
+ (setq dir ':down)))
+ ((loop-tequal prep :above) (setq dir ':down))
+ ((loop-tequal prep :below) (setq dir ':up)))
+ (setq limit-given t)
+ (multiple-value-setq (form limit-constantp limit-value)
+ (loop-constant-fold-if-possible form `(and ,indexv-type real)))
+ (setq endform (if limit-constantp
+ `',limit-value
+ (loop-make-var
+ (gensym "LOOP-LIMIT-") form
+ `(and ,indexv-type real)))))
+ (:by
+ (multiple-value-setq (form stepby-constantp stepby)
+ (loop-constant-fold-if-possible form `(and ,indexv-type (real (0)))))
+ (unless stepby-constantp
+ (loop-make-var (setq stepby (gensym "LOOP-STEP-BY-"))
+ form
+ `(and ,indexv-type (real (0)))
+ t)))
+ (t (loop-error
+ "~S invalid preposition in sequencing or sequence path;~@
- (when limit-given
- ;; if both start and limit are given, they had better both
- ;; be REAL. We already enforce the REALness of LIMIT,
- ;; above; here's the KLUDGE to enforce the type of START.
- (flet ((type-declaration-of (x)
- (and (eq (car x) 'type) (caddr x))))
- (let ((decl (find indexv *loop-declarations*
- :key #'type-declaration-of))
- (%decl (find indexv *loop-declarations*
- :key #'type-declaration-of
- :from-end t)))
- (sb!int:aver (eq decl %decl))
- (setf (cadr decl)
- `(and real ,(cadr decl))))))
- ;; default start
- ;; DUPLICATE KLUDGE: loop-make-var generates a temporary
- ;; symbol for indexv if it is NIL. See also the comment in
- ;; the (:from :downfrom :upfrom) case
- (progn
- (assert-index-for-arithmetic indexv)
- (setq indexv
- (loop-make-var
- indexv
- (setq start-constantp t
- start-value (or (loop-typed-init indexv-type) 0))
- `(and ,indexv-type real)))))
+ (when limit-given
+ ;; if both start and limit are given, they had better both
+ ;; be REAL. We already enforce the REALness of LIMIT,
+ ;; above; here's the KLUDGE to enforce the type of START.
+ (flet ((type-declaration-of (x)
+ (and (eq (car x) 'type) (caddr x))))
+ (let ((decl (find indexv *loop-declarations*
+ :key #'type-declaration-of))
+ (%decl (find indexv *loop-declarations*
+ :key #'type-declaration-of
+ :from-end t)))
+ (sb!int:aver (eq decl %decl))
+ (setf (cadr decl)
+ `(and real ,(cadr decl))))))
+ ;; default start
+ ;; DUPLICATE KLUDGE: loop-make-var generates a temporary
+ ;; symbol for indexv if it is NIL. See also the comment in
+ ;; the (:from :downfrom :upfrom) case
+ (progn
+ (assert-index-for-arithmetic indexv)
+ (setq indexv
+ (loop-make-var
+ indexv
+ (setq start-constantp t
+ start-value (or (loop-typed-init indexv-type) 0))
+ `(and ,indexv-type real)))))
- (when (or limit-given default-top)
- (unless limit-given
- (loop-make-var (setq endform (gensym "LOOP-SEQ-LIMIT-"))
- nil
- indexv-type)
- (push `(setq ,endform ,default-top) *loop-prologue*))
- (setq testfn (if inclusive-iteration '> '>=)))
- (setq step (if (eql stepby 1) `(1+ ,indexv) `(+ ,indexv ,stepby))))
- (t (unless start-given
- (unless default-top
- (loop-error "don't know where to start stepping"))
- (push `(setq ,indexv (1- ,default-top)) *loop-prologue*))
- (when (and default-top (not endform))
- (setq endform (loop-typed-init indexv-type)
- inclusive-iteration t))
- (when endform (setq testfn (if inclusive-iteration '< '<=)))
- (setq step
- (if (eql stepby 1) `(1- ,indexv) `(- ,indexv ,stepby)))))
+ (when (or limit-given default-top)
+ (unless limit-given
+ (loop-make-var (setq endform (gensym "LOOP-SEQ-LIMIT-"))
+ nil
+ indexv-type)
+ (push `(setq ,endform ,default-top) *loop-prologue*))
+ (setq testfn (if inclusive-iteration '> '>=)))
+ (setq step (if (eql stepby 1) `(1+ ,indexv) `(+ ,indexv ,stepby))))
+ (t (unless start-given
+ (unless default-top
+ (loop-error "don't know where to start stepping"))
+ (push `(setq ,indexv (1- ,default-top)) *loop-prologue*))
+ (when (and default-top (not endform))
+ (setq endform (loop-typed-init indexv-type)
+ inclusive-iteration t))
+ (when endform (setq testfn (if inclusive-iteration '< '<=)))
+ (setq step
+ (if (eql stepby 1) `(1- ,indexv) `(- ,indexv ,stepby)))))
- (when (and stepby-constantp start-constantp limit-constantp
- (realp start-value) (realp limit-value))
- (when (setq first-test
- (funcall (symbol-function testfn)
- start-value
- limit-value))
- (setq remaining-tests t)))
- `(() (,indexv ,step)
- ,remaining-tests ,step-hack () () ,first-test ,step-hack)))))
+ (when (and stepby-constantp start-constantp limit-constantp
+ (realp start-value) (realp limit-value))
+ (when (setq first-test
+ (funcall (symbol-function testfn)
+ start-value
+ limit-value))
+ (setq remaining-tests t)))
+ `(() (,indexv ,step)
+ ,remaining-tests ,step-hack () () ,first-test ,step-hack)))))
- (list* nil nil ; dummy bindings and prologue
- (loop-sequencer
- indexv 'fixnum
- variable (or data-type element-type)
- sequencev sequence-type
- `(,fetch-function ,sequencev ,indexv)
- `(,size-function ,sequencev)
- prep-phrases)))))
+ (list* nil nil ; dummy bindings and prologue
+ (loop-sequencer
+ indexv 'fixnum
+ variable (or data-type element-type)
+ sequencev sequence-type
+ `(,fetch-function ,sequencev ,indexv)
+ `(,size-function ,sequencev)
+ prep-phrases)))))
;; @@@@ LOOP-NAMED-VAR returns a second value of T if the name
;; was actually specified, so clever code can throw away the
;; GENSYM'ed-up variable if it isn't really needed. The
;; following is for those implementations in which we cannot put
;; dummy NILs into MULTIPLE-VALUE-SETQ variable lists.
(setq other-p t
;; @@@@ LOOP-NAMED-VAR returns a second value of T if the name
;; was actually specified, so clever code can throw away the
;; GENSYM'ed-up variable if it isn't really needed. The
;; following is for those implementations in which we cannot put
;; dummy NILs into MULTIPLE-VALUE-SETQ variable lists.
(setq other-p t
- (val-var nil)
- (variable (or variable (gensym "LOOP-HASH-VAR-TEMP-")))
- (bindings `((,variable nil ,data-type)
- (,ht-var ,(cadar prep-phrases))
- ,@(and other-p other-var `((,other-var nil))))))
- (ecase which
- (:hash-key (setq key-var variable
- val-var (and other-p other-var)))
- (:hash-value (setq key-var (and other-p other-var)
- val-var variable)))
- (push `(with-hash-table-iterator (,next-fn ,ht-var)) *loop-wrappers*)
+ (val-var nil)
+ (variable (or variable (gensym "LOOP-HASH-VAR-TEMP-")))
+ (bindings `((,variable nil ,data-type)
+ (,ht-var ,(cadar prep-phrases))
+ ,@(and other-p other-var `((,other-var nil))))))
+ (ecase which
+ (:hash-key (setq key-var variable
+ val-var (and other-p other-var)))
+ (:hash-value (setq key-var (and other-p other-var)
+ val-var variable)))
+ (push `(with-hash-table-iterator (,next-fn ,ht-var)) *loop-wrappers*)
- :keywords '((named (loop-do-named))
- (initially (loop-do-initially))
- (finally (loop-do-finally))
- (do (loop-do-do))
- (doing (loop-do-do))
- (return (loop-do-return))
- (collect (loop-list-collection list))
- (collecting (loop-list-collection list))
- (append (loop-list-collection append))
- (appending (loop-list-collection append))
- (nconc (loop-list-collection nconc))
- (nconcing (loop-list-collection nconc))
- (count (loop-sum-collection count
- real
- fixnum))
- (counting (loop-sum-collection count
- real
- fixnum))
- (sum (loop-sum-collection sum number number))
- (summing (loop-sum-collection sum number number))
- (maximize (loop-maxmin-collection max))
- (minimize (loop-maxmin-collection min))
- (maximizing (loop-maxmin-collection max))
- (minimizing (loop-maxmin-collection min))
- (always (loop-do-always t nil)) ; Normal, do always
- (never (loop-do-always t t)) ; Negate test on always.
- (thereis (loop-do-thereis t))
- (while (loop-do-while nil :while)) ; Normal, do while
- (until (loop-do-while t :until)) ;Negate test on while
- (when (loop-do-if when nil)) ; Normal, do when
- (if (loop-do-if if nil)) ; synonymous
- (unless (loop-do-if unless t)) ; Negate test on when
- (with (loop-do-with))
+ :keywords '((named (loop-do-named))
+ (initially (loop-do-initially))
+ (finally (loop-do-finally))
+ (do (loop-do-do))
+ (doing (loop-do-do))
+ (return (loop-do-return))
+ (collect (loop-list-collection list))
+ (collecting (loop-list-collection list))
+ (append (loop-list-collection append))
+ (appending (loop-list-collection append))
+ (nconc (loop-list-collection nconc))
+ (nconcing (loop-list-collection nconc))
+ (count (loop-sum-collection count
+ real
+ fixnum))
+ (counting (loop-sum-collection count
+ real
+ fixnum))
+ (sum (loop-sum-collection sum number number))
+ (summing (loop-sum-collection sum number number))
+ (maximize (loop-maxmin-collection max))
+ (minimize (loop-maxmin-collection min))
+ (maximizing (loop-maxmin-collection max))
+ (minimizing (loop-maxmin-collection min))
+ (always (loop-do-always t nil)) ; Normal, do always
+ (never (loop-do-always t t)) ; Negate test on always.
+ (thereis (loop-do-thereis t))
+ (while (loop-do-while nil :while)) ; Normal, do while
+ (until (loop-do-while t :until)) ;Negate test on while
+ (when (loop-do-if when nil)) ; Normal, do when
+ (if (loop-do-if if nil)) ; synonymous
+ (unless (loop-do-if unless t)) ; Negate test on when
+ (with (loop-do-with))
- :for-keywords '((= (loop-ansi-for-equals))
- (across (loop-for-across))
- (in (loop-for-in))
- (on (loop-for-on))
- (from (loop-for-arithmetic :from))
- (downfrom (loop-for-arithmetic :downfrom))
- (upfrom (loop-for-arithmetic :upfrom))
- (below (loop-for-arithmetic :below))
+ :for-keywords '((= (loop-ansi-for-equals))
+ (across (loop-for-across))
+ (in (loop-for-in))
+ (on (loop-for-on))
+ (from (loop-for-arithmetic :from))
+ (downfrom (loop-for-arithmetic :downfrom))
+ (upfrom (loop-for-arithmetic :upfrom))
+ (below (loop-for-arithmetic :below))
- (to (loop-for-arithmetic :to))
- (upto (loop-for-arithmetic :upto))
- (downto (loop-for-arithmetic :downto))
- (by (loop-for-arithmetic :by))
- (being (loop-for-being)))
- :iteration-keywords '((for (loop-do-for))
- (as (loop-do-for)))
- :type-symbols '(array atom bignum bit bit-vector character
- compiled-function complex cons double-float
- fixnum float function hash-table integer
- keyword list long-float nil null number
- package pathname random-state ratio rational
- readtable sequence short-float simple-array
- simple-bit-vector simple-string simple-vector
- single-float standard-char stream string
- base-char symbol t vector)
- :type-keywords nil
- :ansi (if extended-p :extended t))))
+ (to (loop-for-arithmetic :to))
+ (upto (loop-for-arithmetic :upto))
+ (downto (loop-for-arithmetic :downto))
+ (by (loop-for-arithmetic :by))
+ (being (loop-for-being)))
+ :iteration-keywords '((for (loop-do-for))
+ (as (loop-do-for)))
+ :type-symbols '(array atom bignum bit bit-vector character
+ compiled-function complex cons double-float
+ fixnum float function hash-table integer
+ keyword list long-float nil null number
+ package pathname random-state ratio rational
+ readtable sequence short-float simple-array
+ simple-bit-vector simple-string simple-vector
+ single-float standard-char stream string
+ base-char symbol t vector)
+ :type-keywords nil
+ :ansi (if extended-p :extended t))))