src/utilities.lisp (dosequence): Capture SEQ as a variable explicitly.
authorMark Wooding <mdw@distorted.org.uk>
Sat, 3 Aug 2019 23:21:33 +0000 (00:21 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Sat, 3 Aug 2019 23:21:33 +0000 (00:21 +0100)
Previously it used `once-only', but that doesn't actually produce a
binding for constant expressions.

src/utilities.lisp

index cb6f0cc..6e7a592 100644 (file)
    The loop is surrounded by an anonymous BLOCK and the loop body forms an
    implicit TAGBODY, as is usual.  There is no result-form, however."
 
-  (once-only (:environment env seq start end)
-    (with-gensyms ((ivar "INDEX-") (endvar "END-") (bodyfunc "BODY-"))
+  (once-only (:environment env start end)
+    (with-gensyms ((seqvar "SEQ-") (ivar "INDEX-")
+                  (endvar "END-") (bodyfunc "BODY-"))
       (multiple-value-bind (docs decls body) (parse-body body :docp nil)
        (declare (ignore docs))
 
                 (let* ((do-vars nil)
                        (end-condition (if endvar
                                           `(>= ,ivar ,endvar)
-                                          `(endp ,seq)))
+                                          `(endp ,seqvar)))
                        (item (if listp
-                                 `(car ,seq)
-                                 `(aref ,seq ,ivar)))
+                                 `(car ,seqvar)
+                                 `(aref ,seqvar ,ivar)))
                        (body-call `(,bodyfunc ,item)))
                   (when listp
-                    (push `(,seq (nthcdr ,start ,seq) (cdr ,seq))
+                    (push `(,seqvar (nthcdr ,start ,seqvar) (cdr ,seqvar))
                           do-vars))
                   (when indexp
                     (push `(,ivar ,start (1+ ,ivar)) do-vars))
                   `(do ,do-vars (,end-condition) ,body-call))))
 
          `(block nil
-            (flet ((,bodyfunc (,var ,@(and indexvar `(,indexvar)))
-                     ,@decls
-                     (tagbody ,@body)))
-              (etypecase ,seq
-                (vector
-                 (let ((,endvar (or ,end (length ,seq))))
-                   ,(loopguts t nil endvar)))
-                (list
-                 (if ,end
-                     ,(loopguts t t end)
-                     ,(loopguts indexvar t nil)))))))))))
+            (let ((,seqvar ,seq))
+              (flet ((,bodyfunc (,var ,@(and indexvar `(,indexvar)))
+                       ,@decls
+                       (tagbody ,@body)))
+                (etypecase ,seqvar
+                  (vector
+                   (let ((,endvar (or ,end (length ,seqvar))))
+                     ,(loopguts t nil endvar)))
+                  (list
+                   (if ,end
+                       ,(loopguts t t end)
+                       ,(loopguts indexvar t nil))))))))))))
 
 ;;;--------------------------------------------------------------------------
 ;;; Structure accessor hacks.