* incremented fasl file version number, because of the
SXHASH-related changes in the layout of CLOS data structures
+changes in sbcl-0.7.11 relative to sbcl-0.7.10:
+ * fixed some bugs shown by Paul Dietz' test suite:
+ ** As required by ANSI, LOOP now disallows anonymous collection
+ clauses such as COLLECT I in conjunction with aggregate boolean
+ clauses such as THEREIS (= I 1);
+
planned incompatible changes in 0.7.x:
* (not done yet, but planned:) When the profiling interface settles
down, maybe in 0.7.x, maybe later, it might impact TRACE. They both
(setq *loop-emitted-body* t)
(loop-pseudo-body form))
-(defun loop-emit-final-value (form)
- (push (loop-construct-return form) *loop-after-epilogue*)
+(defun loop-emit-final-value (&optional (form nil form-supplied-p))
+ (when form-supplied-p
+ (push (loop-construct-return form) *loop-after-epilogue*))
(when *loop-final-value-culprit*
- (loop-warn "The LOOP clause is providing a value for the iteration,~@
- however one was already established by a ~S clause."
+ (loop-warn "The LOOP clause is providing a value for the iteration;~@
+ however, one was already established by a ~S clause."
*loop-final-value-culprit*))
(setq *loop-final-value-culprit* (car *loop-source-context*)))
(defun loop-disallow-conditional (&optional kwd)
(when *loop-inside-conditional*
(loop-error "~:[This LOOP~;The LOOP ~:*~S~] clause is not permitted inside a conditional." kwd)))
+
+(defun loop-disallow-anonymous-collectors ()
+ (when (find-if-not 'loop-collector-name *loop-collection-cruft*)
+ (loop-error "This LOOP clause is not permitted with anonymous collectors.")))
+
+(defun loop-disallow-aggregate-booleans ()
+ (when (loop-tmember *loop-final-value-culprit* '(always never thereis))
+ (loop-error "This anonymous collection LOOP clause is not permitted with aggregate booleans.")))
\f
;;;; loop types
(loop-pop-source))))
(when (not (symbolp name))
(loop-error "The value accumulation recipient name, ~S, is not a symbol." name))
+ (unless name
+ (loop-disallow-aggregate-booleans))
(unless dtype
(setq dtype (or (loop-optional-type) default-type)))
(let ((cruft (find (the symbol name) *loop-collection-cruft*
(defun loop-do-always (restrictive negate)
(let ((form (loop-get-form)))
(when restrictive (loop-disallow-conditional))
+ (loop-disallow-anonymous-collectors)
(loop-emit-body `(,(if negate 'when 'unless) ,form
,(loop-construct-return nil)))
(loop-emit-final-value t)))
;;; Under ANSI this is not permitted to appear under conditionalization.
(defun loop-do-thereis (restrictive)
(when restrictive (loop-disallow-conditional))
+ (loop-disallow-anonymous-collectors)
+ (loop-emit-final-value)
(loop-emit-body `(when (setq ,(loop-when-it-var) ,(loop-get-form))
- ,(loop-construct-return *loop-when-it-var*))))
+ ,(loop-construct-return *loop-when-it-var*))))
\f
(defun loop-do-while (negate kwd &aux (form (loop-get-form)))
(loop-disallow-conditional kwd)
(assert (= (loop with (nil a) = '(1 2) return a) 2))
(assert (= (loop with (a . nil) = '(1 2) return a) 1))
(assert (equal (loop with (nil . a) = '(1 2) return a) '(2)))
+
+(multiple-value-bind (result error)
+ (ignore-errors
+ (loop for i in '(1 2 3) collect i always (< i 4)))
+ (assert (null result))
+ (assert (typep error 'program-error)))
+(assert (equal
+ (loop for i in '(1 2 3) collect i into foo always (< i 4)
+ finally (return foo))
+ '(1 2 3)))
+(assert (equal
+ (loop for i in '(1 2 3) collect i into foo always (= i 4)
+ finally (return foo))
+ nil))
+(multiple-value-bind (result error)
+ (ignore-errors
+ (loop for i in '(1 2 3) always (< i 4) collect i))
+ (assert (null result))
+ (assert (typep error 'program-error)))
+(assert (equal
+ (loop for i in '(1 2 3) always (< i 4) collect i into foo
+ finally (return foo))
+ '(1 2 3)))
+(assert (equal
+ (loop for i in '(1 2 3) always (= i 4) collect i into foo
+ finally (return foo))
+ nil))
+(multiple-value-bind (result error)
+ (ignore-errors
+ (loop for i in '(1 2 3) thereis (= i 3) collect i))
+ (assert (null result))
+ (assert (typep error 'program-error)))
\ No newline at end of file