X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcode%2Floop.lisp;h=d6e83a9903c3b106f713b6817a45edd69ee7eb99;hb=c7dc5b2a1f56ed0583a0b3ea61b6ceb540c6f89e;hp=3ffe8234cc617905b36e6af0bf06e047025a279f;hpb=18d4de696bc5063aad026ba62be613c7b07f5fc8;p=sbcl.git diff --git a/src/code/loop.lisp b/src/code/loop.lisp index 3ffe823..d6e83a9 100644 --- a/src/code/loop.lisp +++ b/src/code/loop.lisp @@ -93,67 +93,6 @@ ;;;; LOOP-PREFER-POP (not true on CMU CL) and which has since been ;;;; removed. Thus, STEP-FUNCTION stuff could probably be removed too. -;;;; miscellaneous environment things - -(eval-when (:compile-toplevel :load-toplevel :execute) - (defvar *loop-real-data-type* 'real)) - -(eval-when (:compile-toplevel :load-toplevel :execute) - (defvar *loop-gentemp* nil) - (defun loop-gentemp (&optional (pref 'loopvar-)) - (if *loop-gentemp* - (gentemp (string pref)) - (gensym)))) - -;;; @@@@ The following form takes a list of variables and a form which -;;; presumably references those variables, and wraps it somehow so that the -;;; compiler does not consider those variables have been referenced. The intent -;;; of this is that iteration variables can be flagged as unused by the -;;; compiler, e.g. I in (loop for i from 1 to 10 do (print t)), since we will -;;; tell it when a usage of it is "invisible" or "not to be considered". -;;; -;;; We implicitly assume that a setq does not count as a reference. That is, -;;; the kind of form generated for the above loop construct to step I, -;;; simplified, is -;;; `(SETQ I ,(HIDE-VARIABLE-REFERENCES '(I) '(1+ I))). -;;; -;;; FIXME: This is a no-op except for Genera, now obsolete, so it -;;; can be removed. -(defun hide-variable-references (variable-list form) - (declare (ignore variable-list)) - form) - -;;; @@@@ The following function takes a flag, a variable, and a form which -;;; presumably references that variable, and wraps it somehow so that the -;;; compiler does not consider that variable to have been referenced. The -;;; intent of this is that iteration variables can be flagged as unused by the -;;; compiler, e.g. I in (loop for i from 1 to 10 do (print t)), since we will -;;; tell it when a usage of it is "invisible" or "not to be considered". -;;; -;;; We implicitly assume that a setq does not count as a reference. That is, -;;; the kind of form generated for the above loop construct to step I, -;;; simplified, is -;;; `(SETQ I ,(HIDE-VARIABLE-REFERENCES T 'I '(1+ I))). -;;; -;;; Certain cases require that the "invisibility" of the reference be -;;; conditional upon something. This occurs in cases of "named" variables (the -;;; USING clause). For instance, we want IDX in (LOOP FOR E BEING THE -;;; VECTOR-ELEMENTS OF V USING (INDEX IDX) ...) to be "invisible" when it is -;;; stepped, so that the user gets informed if IDX is not referenced. However, -;;; if no USING clause is present, we definitely do not want to be informed -;;; that some gensym or other is not used. -;;; -;;; It is easier for the caller to do this conditionally by passing a flag -;;; (which happens to be the second value of NAMED-VARIABLE, q.v.) to this -;;; function than for all callers to contain the conditional invisibility -;;; construction. -;;; -;;; FIXME: This is a no-op except for Genera, now obsolete, so it -;;; can be removed. -(defun hide-variable-reference (really-hide variable form) - (declare (ignore really-hide variable)) - form) - ;;;; list collection macrology (sb!int:defmacro-mundanely with-loop-list-collection-head @@ -252,9 +191,9 @@ constructed. (make-loop-minimax-internal :answer-variable answer-variable :type type - :temp-variable (loop-gentemp 'loop-maxmin-temp-) + :temp-variable (gensym "LOOP-MAXMIN-TEMP-") :flag-variable (and (not infinity-data) - (loop-gentemp 'loop-maxmin-flag-)) + (gensym "LOOP-MAXMIN-FLAG-")) :operations nil :infinity-data infinity-data))) @@ -263,7 +202,7 @@ constructed. (when (and (cdr (loop-minimax-operations minimax)) (not (loop-minimax-flag-variable minimax))) (setf (loop-minimax-flag-variable minimax) - (loop-gentemp 'loop-maxmin-flag-))) + (gensym "LOOP-MAXMIN-FLAG-"))) operation) (sb!int:defmacro-mundanely with-minimax-value (lm &body body) @@ -289,13 +228,10 @@ constructed. (let* ((answer-var (loop-minimax-answer-variable lm)) (temp-var (loop-minimax-temp-variable lm)) (flag-var (loop-minimax-flag-variable lm)) - (test - (hide-variable-reference - t (loop-minimax-answer-variable lm) - `(,(ecase operation - (min '<) - (max '>)) - ,temp-var ,answer-var)))) + (test `(,(ecase operation + (min '<) + (max '>)) + ,temp-var ,answer-var))) `(progn (setq ,temp-var ,form) (when ,(if flag-var `(or (not ,flag-var) ,test) test) @@ -390,13 +326,7 @@ code to be loaded. (setf (gethash (car x) ht) (cadr x)))) ht)))) -;;;; SETQ hackery - -(defvar *loop-destructuring-hooks* - nil - #!+sb-doc - "If not NIL, this must be a list of two things: -a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring.") +;;;; SETQ hackery, including destructuring ("DESETQ") (defun loop-make-psetq (frobs) (and frobs @@ -409,19 +339,16 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. (defun loop-make-desetq (var-val-pairs) (if (null var-val-pairs) nil - (cons (if *loop-destructuring-hooks* - (cadr *loop-destructuring-hooks*) - 'loop-really-desetq) - var-val-pairs))) + (cons 'loop-really-desetq var-val-pairs))) (defvar *loop-desetq-temporary* (make-symbol "LOOP-DESETQ-TEMP")) (sb!int:defmacro-mundanely loop-really-desetq (&environment env - &rest var-val-pairs) + &rest var-val-pairs) (labels ((find-non-null (var) - ;; see whether there's any non-null thing here - ;; recurse if the list element is itself a list + ;; 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) @@ -429,17 +356,17 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. (typecase var (null (when (consp val) - ;; don't lose possible side-effects + ;; 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))) + ;; 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 @@ -463,7 +390,7 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. ,@body) `((let ((,temp ,val)) ,@body)))) - ;; no cdring to do + ;; no CDRing to do (loop-desetq-internal car `(car ,val) temp))))) (otherwise (unless (eq var val) @@ -496,36 +423,36 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. (defvar *loop-macro-environment*) ;;; This holds variable names specified with the USING clause. -;;; See LOOP-NAMED-VARIABLE. -(defvar *loop-named-variables*) +;;; See LOOP-NAMED-VAR. +(defvar *loop-named-vars*) ;;; LETlist-like list being accumulated for one group of parallel bindings. -(defvar *loop-variables*) +(defvar *loop-vars*) -;;; list of declarations being accumulated in parallel with *LOOP-VARIABLES* +;;; list of declarations being accumulated in parallel with *LOOP-VARS* (defvar *loop-declarations*) ;;; This is used by LOOP for destructuring binding, if it is doing -;;; that itself. See LOOP-MAKE-VARIABLE. +;;; that itself. See LOOP-MAKE-VAR. (defvar *loop-desetq-crocks*) ;;; list of wrapping forms, innermost first, which go immediately ;;; inside the current set of parallel bindings being accumulated in -;;; *LOOP-VARIABLES*. The wrappers are appended onto a body. E.g., +;;; *LOOP-VARS*. The wrappers are appended onto a body. E.g., ;;; this list could conceivably have as its value ;;; ((WITH-OPEN-FILE (G0001 G0002 ...))), -;;; with G0002 being one of the bindings in *LOOP-VARIABLES* (This is +;;; with G0002 being one of the bindings in *LOOP-VARS* (This is ;;; why the wrappers go inside of the variable bindings). (defvar *loop-wrappers*) -;;; This accumulates lists of previous values of *LOOP-VARIABLES* and +;;; This accumulates lists of previous values of *LOOP-VARS* and ;;; the other lists above, for each new nesting of bindings. See ;;; LOOP-BIND-BLOCK. (defvar *loop-bind-stack*) ;;; This is simply a list of LOOP iteration variables, used for ;;; checking for duplications. -(defvar *loop-iteration-variables*) +(defvar *loop-iteration-vars*) ;;; list of prologue forms of the loop, accumulated in reverse order (defvar *loop-prologue*) @@ -563,14 +490,14 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. ;;; If not NIL, this is a temporary bound around the loop for holding ;;; the temporary value for "it" in things like "when (f) collect it". ;;; It may be used as a supertemporary by some other things. -(defvar *loop-when-it-variable*) +(defvar *loop-when-it-var*) ;;; Sometimes we decide we need to fold together parts of the loop, ;;; but some part of the generated iteration code is different for the ;;; first and remaining iterations. This variable will be the ;;; temporary which is the flag used in the loop to tell whether we ;;; are in the first or remaining iterations. -(defvar *loop-never-stepped-variable*) +(defvar *loop-never-stepped-var*) ;;; list of all the value-accumulation descriptor structures in the ;;; loop. See LOOP-GET-COLLECTION-INFO. @@ -597,7 +524,7 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. (defvar *loop-duplicate-code* nil) -(defvar *loop-iteration-flag-variable* +(defvar *loop-iteration-flag-var* (make-symbol "LOOP-NOT-FIRST-TIME")) (defun loop-code-duplication-threshold (env) @@ -645,26 +572,27 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. (when (or *loop-duplicate-code* (not rbefore)) (return-from loop-body (makebody))) ;; This outer loop iterates once for each not-first-time flag test - ;; generated plus once more for the forms that don't need a flag test + ;; generated plus once more for the forms that don't need a flag test. (do ((threshold (loop-code-duplication-threshold env))) (nil) (declare (fixnum threshold)) - ;; Go backwards from the ends of before-loop and after-loop merging all - ;; the equivalent forms into the body. + ;; Go backwards from the ends of before-loop and after-loop + ;; merging all the equivalent forms into the body. (do () ((or (null rbefore) (not (equal (car rbefore) (car rafter))))) (push (pop rbefore) main-body) (pop rafter)) (unless rbefore (return (makebody))) - ;; The first forms in RBEFORE & RAFTER (which are the chronologically - ;; last forms in the list) differ, therefore they cannot be moved - ;; into the main body. If everything that chronologically precedes - ;; them either differs or is equal but is okay to duplicate, we can - ;; just put all of rbefore in the prologue and all of rafter after - ;; the body. Otherwise, there is something that is not okay to - ;; duplicate, so it and everything chronologically after it in - ;; rbefore and rafter must go into the body, with a flag test to - ;; distinguish the first time around the loop from later times. - ;; What chronologically precedes the non-duplicatable form will - ;; be handled the next time around the outer loop. + ;; The first forms in RBEFORE & RAFTER (which are the + ;; chronologically last forms in the list) differ, therefore + ;; they cannot be moved into the main body. If everything that + ;; chronologically precedes them either differs or is equal but + ;; is okay to duplicate, we can just put all of rbefore in the + ;; prologue and all of rafter after the body. Otherwise, there + ;; is something that is not okay to duplicate, so it and + ;; everything chronologically after it in rbefore and rafter + ;; must go into the body, with a flag test to distinguish the + ;; first time around the loop from later times. What + ;; chronologically precedes the non-duplicatable form will be + ;; handled the next time around the outer loop. (do ((bb rbefore (cdr bb)) (aa rafter (cdr aa)) (lastdiff nil) @@ -685,7 +613,7 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. (push (pop rafter) then) (when (eq rbefore (cdr lastdiff)) (return))) (unless flagvar - (push `(setq ,(setq flagvar *loop-iteration-flag-variable*) + (push `(setq ,(setq flagvar *loop-iteration-flag-var*) t) else)) (push `(if ,flagvar ,(pify (psimp then)) ,(pify (psimp else))) @@ -703,9 +631,9 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. (if (null expr) 0 (let ((ans (estimate-code-size expr env))) (declare (fixnum ans)) - ;; @@@@ Use (DECLARATION-INFORMATION 'OPTIMIZE ENV) here to get an - ;; alist of optimize quantities back to help quantify how much code we - ;; are willing to duplicate. + ;; @@@@ Use (DECLARATION-INFORMATION 'OPTIMIZE ENV) here to + ;; get an alist of optimize quantities back to help quantify + ;; how much code we are willing to duplicate. ans))) (defvar *special-code-sizes* @@ -809,10 +737,9 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. ((eq l (cdr *loop-source-code*)) (nreverse new)))) (defun loop-error (format-string &rest format-args) - (error "~?~%current LOOP context:~{ ~S~}." - format-string - format-args - (loop-context))) + (error 'sb!int:simple-program-error + :format-control "~?~%current LOOP context:~{ ~S~}." + :format-arguments (list format-string format-args (loop-context)))) (defun loop-warn (format-string &rest format-args) (warn "~?~%current LOOP context:~{ ~S~}." @@ -833,14 +760,20 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. specified-type required-type))) specified-type))) +(defun loop-build-destructuring-bindings (crocks forms) + (if crocks + `((destructuring-bind ,(car crocks) ,(cadr crocks) + ,@(loop-build-destructuring-bindings (cddr crocks) forms))) + forms)) + (defun loop-translate (*loop-source-code* *loop-macro-environment* *loop-universe*) (let ((*loop-original-source-code* *loop-source-code*) (*loop-source-context* nil) - (*loop-iteration-variables* nil) - (*loop-variables* nil) - (*loop-named-variables* nil) + (*loop-iteration-vars* nil) + (*loop-vars* nil) + (*loop-named-vars* nil) (*loop-declarations* nil) (*loop-desetq-crocks* nil) (*loop-bind-stack* nil) @@ -854,8 +787,8 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. (*loop-after-epilogue* nil) (*loop-final-value-culprit* nil) (*loop-inside-conditional* nil) - (*loop-when-it-variable* nil) - (*loop-never-stepped-variable* nil) + (*loop-when-it-var* nil) + (*loop-never-stepped-var* nil) (*loop-names* nil) (*loop-collection-cruft* nil)) (loop-iteration-driver) @@ -881,16 +814,10 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. (let ((forms (list answer))) ;;(when crocks (push crocks forms)) (when dcls (push `(declare ,@dcls) forms)) - (setq answer `(,(cond ((not vars) 'locally) - (*loop-destructuring-hooks* - (first *loop-destructuring-hooks*)) - (t - 'let)) + (setq answer `(,(if vars 'let 'locally) ,vars - ,@(if crocks - `((destructuring-bind ,@crocks - ,@forms)) - forms))))))) + ,@(loop-build-destructuring-bindings crocks + forms))))))) answer))) (defun loop-iteration-driver () @@ -925,17 +852,25 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. (pop *loop-source-code*) (loop-error "LOOP source code ran out when another token was expected."))) -(defun loop-get-progn () - (do ((forms (list (loop-pop-source)) (cons (loop-pop-source) forms)) - (nextform (car *loop-source-code*) (car *loop-source-code*))) - ((atom nextform) - (if (null (cdr forms)) (car forms) (cons 'progn (nreverse forms)))))) - (defun loop-get-form () (if *loop-source-code* (loop-pop-source) (loop-error "LOOP code ran out where a form was expected."))) +(defun loop-get-compound-form () + (let ((form (loop-get-form))) + (unless (consp form) + (loop-error "A compound form was expected, but ~S found." form)) + form)) + +(defun loop-get-progn () + (do ((forms (list (loop-get-compound-form)) + (cons (loop-get-compound-form) forms)) + (nextform (car *loop-source-code*) + (car *loop-source-code*))) + ((atom nextform) + (if (null (cdr forms)) (car forms) (cons 'progn (nreverse forms)))))) + (defun loop-construct-return (form) `(return-from ,(car *loop-names*) ,form)) @@ -974,17 +909,18 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. (and *loop-source-code* ; Don't get confused by NILs.. (let ((z (car *loop-source-code*))) (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. + ;; 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. + ;; 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*)) @@ -995,11 +931,12 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. (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 + ;; 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) @@ -1038,60 +975,57 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. ;;;; loop variables (defun loop-bind-block () - (when (or *loop-variables* *loop-declarations* *loop-wrappers*) - (push (list (nreverse *loop-variables*) + (when (or *loop-vars* *loop-declarations* *loop-wrappers*) + (push (list (nreverse *loop-vars*) *loop-declarations* *loop-desetq-crocks* *loop-wrappers*) *loop-bind-stack*) - (setq *loop-variables* nil + (setq *loop-vars* nil *loop-declarations* nil *loop-desetq-crocks* nil *loop-wrappers* nil))) -(defun loop-make-variable (name initialization dtype - &optional iteration-variable-p) +(defun loop-make-var (name initialization dtype &optional iteration-var-p) (cond ((null name) (cond ((not (null initialization)) - (push (list (setq name (loop-gentemp 'loop-ignore-)) + (push (list (setq name (gensym "LOOP-IGNORE-")) initialization) - *loop-variables*) + *loop-vars*) (push `(ignore ,name) *loop-declarations*)))) ((atom name) - (cond (iteration-variable-p - (if (member name *loop-iteration-variables*) + (cond (iteration-var-p + (if (member name *loop-iteration-vars*) (loop-error "duplicated LOOP iteration variable ~S" name) - (push name *loop-iteration-variables*))) - ((assoc name *loop-variables*) + (push name *loop-iteration-vars*))) + ((assoc name *loop-vars*) (loop-error "duplicated variable ~S in LOOP parallel binding" name))) (unless (symbolp name) (loop-error "bad variable ~S somewhere in LOOP" name)) - (loop-declare-variable name dtype) + (loop-declare-var name dtype) ;; 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))) - *loop-variables*)) + *loop-vars*)) (initialization - (cond (*loop-destructuring-hooks* - (loop-declare-variable name dtype) - (push (list name initialization) *loop-variables*)) - (t (let ((newvar (loop-gentemp 'loop-destructure-))) - (push (list newvar initialization) *loop-variables*) - ;; *LOOP-DESETQ-CROCKS* gathered in reverse order. - (setq *loop-desetq-crocks* - (list* name newvar *loop-desetq-crocks*)))))) + (let ((newvar (gensym "LOOP-DESTRUCTURE-"))) + (loop-declare-var name dtype) + (push (list newvar initialization) *loop-vars*) + ;; *LOOP-DESETQ-CROCKS* gathered in reverse order. + (setq *loop-desetq-crocks* + (list* name newvar *loop-desetq-crocks*)))) (t (let ((tcar nil) (tcdr nil)) (if (atom dtype) (setq tcar (setq tcdr dtype)) (setq tcar (car dtype) tcdr (cdr dtype))) - (loop-make-variable (car name) nil tcar iteration-variable-p) - (loop-make-variable (cdr name) nil tcdr iteration-variable-p)))) + (loop-make-var (car name) nil tcar iteration-var-p) + (loop-make-var (cdr name) nil tcdr iteration-var-p)))) name) -(defun loop-make-iteration-variable (name initialization dtype) - (loop-make-variable name initialization dtype t)) +(defun loop-make-iteration-var (name initialization dtype) + (loop-make-var name initialization dtype t)) -(defun loop-declare-variable (name dtype) +(defun loop-declare-var (name dtype) (cond ((or (null name) (null dtype) (eq dtype t)) nil) ((symbolp name) (unless (sb!xc:subtypep t dtype) @@ -1102,16 +1036,16 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. (push `(type ,dtype ,name) *loop-declarations*)))) ((consp name) (cond ((consp dtype) - (loop-declare-variable (car name) (car dtype)) - (loop-declare-variable (cdr name) (cdr dtype))) - (t (loop-declare-variable (car name) dtype) - (loop-declare-variable (cdr name) 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)))) (defun loop-maybe-bind-form (form data-type) (if (loop-constantp form) form - (loop-make-variable (loop-gentemp 'loop-bind-) form data-type))) + (loop-make-var (gensym "LOOP-BIND-") form data-type))) (defun loop-do-if (for negatep) (let ((form (loop-get-form)) (*loop-inside-conditional* t) (it-p nil)) @@ -1128,7 +1062,7 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. (setq *loop-source-code* (cons (or it-p (setq it-p - (loop-when-it-variable))) + (loop-when-it-var))) (cdr *loop-source-code*)))) (cond ((or (not (setq data (loop-lookup-keyword key (loop-universe-keywords *loop-universe*)))) @@ -1231,8 +1165,8 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. (let ((tempvars (loop-collector-tempvars lc))) (unless tempvars (setf (loop-collector-tempvars lc) - (setq tempvars (list* (loop-gentemp 'loop-list-head-) - (loop-gentemp 'loop-list-tail-) + (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*) @@ -1255,9 +1189,9 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. (let ((tempvars (loop-collector-tempvars lc))) (unless tempvars (setf (loop-collector-tempvars lc) - (setq tempvars (list (loop-make-variable + (setq tempvars (list (loop-make-var (or (loop-collector-name lc) - (loop-gentemp 'loop-sum-)) + (gensym "LOOP-SUM-")) nil (loop-collector-dtype lc))))) (unless (loop-collector-name lc) (loop-emit-final-value (car (loop-collector-tempvars lc))))) @@ -1265,25 +1199,21 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. (if (eq specifically 'count) `(when ,form (setq ,(car tempvars) - ,(hide-variable-reference t - (car tempvars) - `(1+ ,(car tempvars))))) + (1+ ,(car tempvars)))) `(setq ,(car tempvars) - (+ ,(hide-variable-reference t - (car tempvars) - (car tempvars)) + (+ ,(car tempvars) ,form))))))) (defun loop-maxmin-collection (specifically) (multiple-value-bind (lc form) - (loop-get-collection-info specifically 'maxmin *loop-real-data-type*) - (loop-check-data-type (loop-collector-dtype lc) *loop-real-data-type*) + (loop-get-collection-info specifically 'maxmin 'real) + (loop-check-data-type (loop-collector-dtype lc) 'real) (let ((data (loop-collector-data lc))) (unless data (setf (loop-collector-data lc) (setq data (make-loop-minimax (or (loop-collector-name lc) - (loop-gentemp 'loop-maxmin-)) + (gensym "LOOP-MAXMIN-")) (loop-collector-dtype lc)))) (unless (loop-collector-name lc) (loop-emit-final-value (loop-minimax-answer-variable data)))) @@ -1310,8 +1240,8 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. ;;; Under ANSI this is not permitted to appear under conditionalization. (defun loop-do-thereis (restrictive) (when restrictive (loop-disallow-conditional)) - (loop-emit-body `(when (setq ,(loop-when-it-variable) ,(loop-get-form)) - ,(loop-construct-return *loop-when-it-variable*)))) + (loop-emit-body `(when (setq ,(loop-when-it-var) ,(loop-get-form)) + ,(loop-construct-return *loop-when-it-var*)))) (defun loop-do-while (negate kwd &aux (form (loop-get-form))) (loop-disallow-conditional kwd) @@ -1326,7 +1256,7 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. (loop-pop-source) (loop-get-form)) (t nil))) - (loop-make-variable var val dtype) + (loop-make-var var val dtype) (if (loop-tequal (car *loop-source-code*) :and) (loop-pop-source) (return (loop-bind-block))))) @@ -1421,7 +1351,7 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. (defun loop-do-repeat () (let ((form (loop-get-form)) (type (loop-check-data-type (loop-optional-type) - *loop-real-data-type*))) + 'real))) (when (and (consp form) (eq (car form) 'the) (sb!xc:subtypep (second form) type)) @@ -1429,29 +1359,27 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. (multiple-value-bind (number constantp value) (loop-constant-fold-if-possible form type) (cond ((and constantp (<= value 1)) `(t () () () ,(<= value 0) () () ())) - (t (let ((var (loop-make-variable (loop-gentemp 'loop-repeat-) - number - type))) + (t (let ((var (loop-make-var (gensym "LOOP-REPEAT-") number type))) (if constantp `((not (plusp (setq ,var (1- ,var)))) () () () () () () ()) `((minusp (setq ,var (1- ,var))) () () ())))))))) -(defun loop-when-it-variable () - (or *loop-when-it-variable* - (setq *loop-when-it-variable* - (loop-make-variable (loop-gentemp 'loop-it-) nil nil)))) +(defun loop-when-it-var () + (or *loop-when-it-var* + (setq *loop-when-it-var* + (loop-make-var (gensym "LOOP-IT-") nil nil)))) ;;;; various FOR/AS subdispatches -;;; ANSI "FOR x = y [THEN z]" is sort of like the old Genera one when the THEN -;;; is omitted (other than being more stringent in its placement), and like the -;;; old "FOR x FIRST y THEN z" when the THEN is present. I.e., the first -;;; initialization occurs in the loop body (first-step), not in the variable -;;; binding phase. +;;; ANSI "FOR x = y [THEN z]" is sort of like the old Genera one when +;;; the THEN is omitted (other than being more stringent in its +;;; placement), and like the old "FOR x FIRST y THEN z" when the THEN +;;; is present. I.e., the first initialization occurs in the loop body +;;; (first-step), not in the variable binding phase. (defun loop-ansi-for-equals (var val data-type) - (loop-make-iteration-variable var nil data-type) + (loop-make-iteration-var var nil data-type) (cond ((loop-tequal (car *loop-source-code*) :then) ;; Then we are the same as "FOR x FIRST y THEN z". (loop-pop-source) @@ -1461,23 +1389,23 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. `(() (,var ,val) () ())))) (defun loop-for-across (var val data-type) - (loop-make-iteration-variable var nil data-type) - (let ((vector-var (loop-gentemp 'loop-across-vector-)) - (index-var (loop-gentemp 'loop-across-index-))) + (loop-make-iteration-var var nil data-type) + (let ((vector-var (gensym "LOOP-ACROSS-VECTOR-")) + (index-var (gensym "LOOP-ACROSS-INDEX-"))) (multiple-value-bind (vector-form constantp vector-value) (loop-constant-fold-if-possible val 'vector) - (loop-make-variable + (loop-make-var vector-var vector-form (if (and (consp vector-form) (eq (car vector-form) 'the)) (cadr vector-form) 'vector)) - (loop-make-variable index-var 0 'fixnum) + (loop-make-var index-var 0 'fixnum) (let* ((length 0) (length-form (cond ((not constantp) - (let ((v (loop-gentemp 'loop-across-limit-))) + (let ((v (gensym "LOOP-ACROSS-LIMIT-"))) (push `(setq ,v (length ,vector-var)) *loop-prologue*) - (loop-make-variable v 0 'fixnum))) + (loop-make-var v 0 'fixnum))) (t (setq length (length vector-value))))) (first-test `(>= ,index-var ,length-form)) (other-test first-test) @@ -1495,9 +1423,9 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. ;;;; list iteration (defun loop-list-step (listvar) - ;; We are not equipped to analyze whether 'FOO is the same as #'FOO here in - ;; any sensible fashion, so let's give an obnoxious warning whenever 'FOO is - ;; used as the stepping function. + ;; We are not equipped to analyze whether 'FOO is the same as #'FOO + ;; here in any sensible fashion, so let's give an obnoxious warning + ;; whenever 'FOO is used as the stepping function. ;; ;; While a Discerning Compiler may deal intelligently with ;; (FUNCALL 'FOO ...), not recognizing FOO may defeat some LOOP @@ -1512,9 +1440,7 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. ((and (consp stepper) (eq (car stepper) 'function)) (list (cadr stepper) listvar)) (t - `(funcall ,(loop-make-variable (loop-gentemp 'loop-fn-) - stepper - 'function) + `(funcall ,(loop-make-var (gensym "LOOP-FN-") stepper 'function) ,listvar))))) (defun loop-for-on (var val data-type) @@ -1522,24 +1448,22 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. (loop-constant-fold-if-possible val) (let ((listvar var)) (cond ((and var (symbolp var)) - (loop-make-iteration-variable var list data-type)) - (t (loop-make-variable (setq listvar (loop-gentemp)) list 'list) - (loop-make-iteration-variable var nil data-type))) + (loop-make-iteration-var var list data-type)) + (t (loop-make-var (setq listvar (gensym)) list 'list) + (loop-make-iteration-var var nil data-type))) (let ((list-step (loop-list-step listvar))) (let* ((first-endtest - (hide-variable-reference - (eq var listvar) - listvar - ;; the following should use `atom' instead of `endp', per - ;; [bug2428] - `(atom ,listvar))) + ;; 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) - ;; Contour of the loop is different because we use the user's - ;; variable... - `(() (,listvar ,(hide-variable-reference t listvar list-step)) + ;; 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))) @@ -1550,9 +1474,9 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. (defun loop-for-in (var val data-type) (multiple-value-bind (list constantp list-value) (loop-constant-fold-if-possible val) - (let ((listvar (loop-gentemp 'loop-list-))) - (loop-make-iteration-variable var nil data-type) - (loop-make-variable listvar list 'list) + (let ((listvar (gensym "LOOP-LIST-"))) + (loop-make-iteration-var var nil data-type) + (loop-make-var listvar list 'list) (let ((list-step (loop-list-step listvar))) (let* ((first-endtest `(endp ,listvar)) (other-endtest first-endtest) @@ -1593,7 +1517,7 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. (setf (gethash (symbol-name name) ht) lp)) lp)) -;;; Note: path functions are allowed to use loop-make-variable, hack +;;; Note: Path functions are allowed to use LOOP-MAKE-VAR, hack ;;; the prologue, etc. (defun loop-for-being (var val data-type) ;; FOR var BEING each/the pathname prep-phrases using-stuff... each/the = @@ -1633,30 +1557,30 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. (setq stuff (if inclusive (apply fun var data-type preps :inclusive t user-data) (apply fun var data-type preps user-data)))) - (when *loop-named-variables* - (loop-error "Unused USING variables: ~S." *loop-named-variables*)) - ;; STUFF is now (bindings prologue-forms . stuff-to-pass-back). Protect the - ;; system from the user and the user from himself. + (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." path)) (do ((l (car stuff) (cdr l)) (x)) ((null l)) (if (atom (setq x (car l))) - (loop-make-iteration-variable x nil nil) - (loop-make-iteration-variable (car x) (cadr x) (caddr x)))) + (loop-make-iteration-var x nil nil) + (loop-make-iteration-var (car x) (cadr x) (caddr x)))) (setq *loop-prologue* (nconc (reverse (cadr stuff)) *loop-prologue*)) (cddr stuff))) -(defun named-variable (name) - (let ((tem (loop-tassoc name *loop-named-variables*))) +(defun loop-named-var (name) + (let ((tem (loop-tassoc name *loop-named-vars*))) (declare (list tem)) - (cond ((null tem) (values (loop-gentemp) nil)) - (t (setq *loop-named-variables* (delete tem *loop-named-variables*)) + (cond ((null tem) (values (gensym) nil)) + (t (setq *loop-named-vars* (delete tem *loop-named-vars*)) (values (cdr tem) t))))) (defun loop-collect-prepositional-phrases (preposition-groups &optional - USING-allowed + using-allowed initial-phrases) (flet ((in-group-p (x group) (car (loop-tmember x group)))) (do ((token nil) @@ -1664,9 +1588,9 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. (this-group nil nil) (this-prep nil nil) (disallowed-prepositions - (mapcan #'(lambda (x) - (copy-list - (find (car x) preposition-groups :test #'in-group-p))) + (mapcan (lambda (x) + (copy-list + (find (car x) preposition-groups :test #'in-group-p))) initial-phrases)) (used-prepositions (mapcar #'car initial-phrases))) ((null *loop-source-code*) (nreverse prepositional-phrases)) @@ -1687,22 +1611,16 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. (cons this-group used-prepositions))) (loop-pop-source) (push (list this-prep (loop-get-form)) prepositional-phrases)) - ((and USING-allowed (loop-tequal token 'using)) + ((and using-allowed (loop-tequal token 'using)) (loop-pop-source) (do ((z (loop-pop-source) (loop-pop-source)) (tem)) (nil) - (when (or (atom z) - (atom (cdr z)) - (not (null (cddr z))) - (not (symbolp (car z))) - (and (cadr z) (not (symbolp (cadr z))))) - (loop-error "~S bad variable pair in path USING phrase" z)) (when (cadr z) - (if (setq tem (loop-tassoc (car z) *loop-named-variables*)) + (if (setq tem (loop-tassoc (car z) *loop-named-vars*)) (loop-error "The variable substitution for ~S occurs twice in a USING phrase,~@ with ~S and ~S." (car z) (cadr z) (cadr tem)) - (push (cons (car z) (cadr z)) *loop-named-variables*))) + (push (cons (car z) (cadr z)) *loop-named-vars*))) (when (or (null *loop-source-code*) (symbolp (car *loop-source-code*))) (return nil)))) @@ -1710,12 +1628,12 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. ;;;; master sequencer function -(defun loop-sequencer (indexv indexv-type indexv-user-specified-p - variable variable-type - sequence-variable sequence-type - step-hack default-top - prep-phrases) - (let ((endform nil) ; Form (constant or variable) with limit value +(defun loop-sequencer (indexv indexv-type + variable variable-type + sequence-variable sequence-type + step-hack default-top + prep-phrases) + (let ((endform nil) ; form (constant or variable) with limit value (sequencep nil) ; T if sequence arg has been provided (testfn nil) ; endtest function (test nil) ; endtest form @@ -1731,20 +1649,20 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. (limit-constantp nil) (limit-value nil) ) - (when variable (loop-make-iteration-variable variable nil variable-type)) + (when variable (loop-make-iteration-var variable nil variable-type)) (do ((l prep-phrases (cdr l)) (prep) (form) (odir)) ((null l)) (setq prep (caar l) form (cadar l)) (case prep ((:of :in) (setq sequencep t) - (loop-make-variable sequence-variable form sequence-type)) + (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)) - (loop-make-iteration-variable indexv form indexv-type)) + (loop-make-iteration-var indexv form indexv-type)) ((:upto :to :downto :above :below) (cond ((loop-tequal prep :upto) (setq inclusive-iteration (setq dir ':up))) @@ -1758,15 +1676,15 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. (loop-constant-fold-if-possible form indexv-type)) (setq endform (if limit-constantp `',limit-value - (loop-make-variable - (loop-gentemp 'loop-limit-) form indexv-type)))) + (loop-make-var + (gensym "LOOP-LIMIT-") form indexv-type)))) (:by (multiple-value-setq (form stepby-constantp stepby) (loop-constant-fold-if-possible form indexv-type)) (unless stepby-constantp - (loop-make-variable (setq stepby (loop-gentemp 'loop-step-by-)) - form - indexv-type))) + (loop-make-var (setq stepby (gensym "LOOP-STEP-BY-")) + form + indexv-type))) (t (loop-error "~S invalid preposition in sequencing or sequence path;~@ maybe invalid prepositions were specified in iteration path descriptor?" @@ -1778,7 +1696,7 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. (loop-error "missing OF or IN phrase in sequence path")) ;; Now fill in the defaults. (unless start-given - (loop-make-iteration-variable + (loop-make-iteration-var indexv (setq start-constantp t start-value (or (loop-typed-init indexv-type) 0)) @@ -1786,9 +1704,9 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. (cond ((member dir '(nil :up)) (when (or limit-given default-top) (unless limit-given - (loop-make-variable (setq endform - (loop-gentemp 'loop-seq-limit-)) - nil indexv-type) + (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)))) @@ -1804,12 +1722,10 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. (if (eql stepby 1) `(1- ,indexv) `(- ,indexv ,stepby))))) (when testfn (setq test - (hide-variable-reference t indexv `(,testfn ,indexv ,endform)))) + `(,testfn ,indexv ,endform))) (when step-hack (setq step-hack - `(,variable ,(hide-variable-reference indexv-user-specified-p - indexv - step-hack)))) + `(,variable ,step-hack))) (let ((first-test test) (remaining-tests test)) (when (and stepby-constantp start-constantp limit-constantp) (when (setq first-test @@ -1817,18 +1733,18 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. start-value limit-value)) (setq remaining-tests t))) - `(() (,indexv ,(hide-variable-reference t indexv step)) + `(() (,indexv ,step) ,remaining-tests ,step-hack () () ,first-test ,step-hack)))) ;;;; interfaces to the master sequencer (defun loop-for-arithmetic (var val data-type kwd) (loop-sequencer - var (loop-check-data-type data-type *loop-real-data-type*) t - nil nil nil nil nil nil - (loop-collect-prepositional-phrases - '((:from :upfrom :downfrom) (:to :upto :downto :above :below) (:by)) - nil (list (list kwd val))))) + var (loop-check-data-type data-type 'real) + nil nil nil nil nil nil + (loop-collect-prepositional-phrases + '((:from :upfrom :downfrom) (:to :upto :downto :above :below) (:by)) + nil (list (list kwd val))))) (defun loop-sequence-elements-path (variable data-type prep-phrases &key @@ -1836,16 +1752,16 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. size-function sequence-type element-type) - (multiple-value-bind (indexv indexv-user-specified-p) (named-variable 'index) - (let ((sequencev (named-variable 'sequence))) + (multiple-value-bind (indexv) (loop-named-var 'index) + (let ((sequencev (loop-named-var 'sequence))) (list* nil nil ; dummy bindings and prologue (loop-sequencer - indexv 'fixnum indexv-user-specified-p - variable (or data-type element-type) - sequencev sequence-type - `(,fetch-function ,sequencev ,indexv) - `(,size-function ,sequencev) - prep-phrases))))) + indexv 'fixnum + variable (or data-type element-type) + sequencev sequence-type + `(,fetch-function ,sequencev ,indexv) + `(,size-function ,sequencev) + prep-phrases))))) ;;;; builtin LOOP iteration paths @@ -1857,42 +1773,47 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. ||# (defun loop-hash-table-iteration-path (variable data-type prep-phrases - &key (which (required-argument))) + &key (which (sb!int:missing-arg))) (declare (type (member :hash-key :hash-value) which)) (cond ((or (cdr prep-phrases) (not (member (caar prep-phrases) '(:in :of)))) (loop-error "too many prepositions!")) ((null prep-phrases) (loop-error "missing OF or IN in ~S iteration path"))) - (let ((ht-var (loop-gentemp 'loop-hashtab-)) - (next-fn (loop-gentemp 'loop-hashtab-next-)) + (let ((ht-var (gensym "LOOP-HASHTAB-")) + (next-fn (gensym "LOOP-HASHTAB-NEXT-")) (dummy-predicate-var nil) (post-steps nil)) (multiple-value-bind (other-var other-p) - (named-variable (if (eq which 'hash-key) 'hash-value 'hash-key)) - ;; @@@@ named-variable 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. + (loop-named-var (ecase which + (:hash-key 'hash-value) + (:hash-value 'hash-key))) + ;; @@@@ 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 - dummy-predicate-var (loop-when-it-variable)) - (let ((key-var nil) - (val-var nil) - (bindings `((,variable nil ,data-type) - (,ht-var ,(cadar prep-phrases)) - ,@(and other-p other-var `((,other-var nil)))))) - (if (eq which 'hash-key) - (setq key-var variable val-var (and other-p other-var)) - (setq key-var (and other-p other-var) val-var variable)) + dummy-predicate-var (loop-when-it-var)) + (let* ((key-var nil) + (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*) (when (consp key-var) (setq post-steps - `(,key-var ,(setq key-var (loop-gentemp 'loop-hash-key-temp-)) + `(,key-var ,(setq key-var (gensym "LOOP-HASH-KEY-TEMP-")) ,@post-steps)) (push `(,key-var nil) bindings)) (when (consp val-var) (setq post-steps - `(,val-var ,(setq val-var (loop-gentemp 'loop-hash-val-temp-)) + `(,val-var ,(setq val-var (gensym "LOOP-HASH-VAL-TEMP-")) ,@post-steps)) (push `(,val-var nil) bindings)) `(,bindings ;bindings @@ -1905,21 +1826,23 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. (defun loop-package-symbols-iteration-path (variable data-type prep-phrases &key symbol-types) - (cond ((or (cdr prep-phrases) (not (member (caar prep-phrases) '(:in :of)))) + (cond ((and prep-phrases (cdr prep-phrases)) (loop-error "Too many prepositions!")) - ((null prep-phrases) - (loop-error "missing OF or IN in ~S iteration path"))) + ((and prep-phrases (not (member (caar prep-phrases) '(:in :of)))) + (sb!int:bug "Unknown preposition ~S." (caar prep-phrases)))) (unless (symbolp variable) (loop-error "Destructuring is not valid for package symbol iteration.")) - (let ((pkg-var (loop-gentemp 'loop-pkgsym-)) - (next-fn (loop-gentemp 'loop-pkgsym-next-))) + (let ((pkg-var (gensym "LOOP-PKGSYM-")) + (next-fn (gensym "LOOP-PKGSYM-NEXT-")) + (variable (or variable (gensym "LOOP-PKGSYM-VAR-"))) + (package (or (cadar prep-phrases) '*package*))) (push `(with-package-iterator (,next-fn ,pkg-var ,@symbol-types)) *loop-wrappers*) - `(((,variable nil ,data-type) (,pkg-var ,(cadar prep-phrases))) + `(((,variable nil ,data-type) (,pkg-var ,package)) () () () - (not (multiple-value-setq (,(loop-when-it-variable) + (not (multiple-value-setq (,(loop-when-it-var) ,variable) (,next-fn))) ()))) @@ -1928,7 +1851,7 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. (defun make-ansi-loop-universe (extended-p) (let ((w (make-standard-loop-universe - :keywords `((named (loop-do-named)) + :keywords '((named (loop-do-named)) (initially (loop-do-initially)) (finally (loop-do-finally)) (do (loop-do-do)) @@ -1941,10 +1864,10 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. (nconc (loop-list-collection nconc)) (nconcing (loop-list-collection nconc)) (count (loop-sum-collection count - ,*loop-real-data-type* + real fixnum)) (counting (loop-sum-collection count - ,*loop-real-data-type* + real fixnum)) (sum (loop-sum-collection sum number number)) (summing (loop-sum-collection sum number number)) @@ -1969,8 +1892,11 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. (downfrom (loop-for-arithmetic :downfrom)) (upfrom (loop-for-arithmetic :upfrom)) (below (loop-for-arithmetic :below)) + (above (loop-for-arithmetic :above)) (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)) @@ -2009,7 +1935,8 @@ a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring. 'loop-package-symbols-iteration-path w :preposition-groups '((:of :in)) :inclusive-permitted nil - :user-data '(:symbol-types (:internal))) + :user-data '(:symbol-types (:internal + :external))) w)) (defparameter *loop-ansi-universe*