+8
−0
+24
−17
Loading
Control flow clauses that return from an iterate form without executing
the epilogue code (e.g. `never` and `leave`) currently do so by
expanding into `(return-from ,*block-name*)`. For iterate forms without
a user-provided name, the block will be named `nil`. This causes
problems when used with other Common Lisp looping constructs such as
`dolist`:
(iterate
(for i :from 0 :below 10)
(dolist (x '(5 10 15))
(never (= i x))))
; => T, but should be NIL
This patch adds a separate `*loop-name*` variable that will be bound to
a gensym for `NIL`-named blocks and makes the various epilogue-skipping
code refer to that instead of `*block-name*`. Iterate forms *without*
an explicit user-provided name will still have a separate `(block nil
...)` wrapping so users can still `(return ...)` as before.
Before (simplified):
(iterate (leave))
; ==> (block nil (return-from nil))
(iterate foo (leave))
; ==> (block foo (return-from nil))
After:
(iterate (leave))
; ==> (block nil (block #:ITERATE123 (return-from #:ITERATE123)))
(iterate foo (leave))
; ==> (block foo (return-from foo))