diff options
Diffstat (limited to 'lisp/emacs-lisp/generator.el')
-rw-r--r-- | lisp/emacs-lisp/generator.el | 46 |
1 files changed, 25 insertions, 21 deletions
diff --git a/lisp/emacs-lisp/generator.el b/lisp/emacs-lisp/generator.el index 0f4149eacd5..caf5fed154b 100644 --- a/lisp/emacs-lisp/generator.el +++ b/lisp/emacs-lisp/generator.el @@ -213,8 +213,8 @@ don't yield.") ;; Process `and'. - (`(and) ; (and) -> t - (cps--transform-1 t next-state)) + ('(and) ; (and) -> t + (cps--transform-1 t next-state)) (`(and ,condition) ; (and CONDITION) -> CONDITION (cps--transform-1 condition next-state)) (`(and ,condition . ,rest) @@ -246,8 +246,8 @@ don't yield.") ;; Process `cond': transform into `if' or `or' depending on the ;; precise kind of the condition we're looking at. - (`(cond) ; (cond) -> nil - (cps--transform-1 nil next-state)) + ('(cond) ; (cond) -> nil + (cps--transform-1 nil next-state)) (`(cond (,condition) . ,rest) (cps--transform-1 `(or ,condition (cond ,@rest)) next-state)) @@ -281,14 +281,14 @@ don't yield.") ;; Process `progn' and `inline': they are identical except for the ;; name, which has some significance to the byte compiler. - (`(inline) (cps--transform-1 nil next-state)) + ('(inline) (cps--transform-1 nil next-state)) (`(inline ,form) (cps--transform-1 form next-state)) (`(inline ,form . ,rest) (cps--transform-1 form (cps--transform-1 `(inline ,@rest) next-state))) - (`(progn) (cps--transform-1 nil next-state)) + ('(progn) (cps--transform-1 nil next-state)) (`(progn ,form) (cps--transform-1 form next-state)) (`(progn ,form . ,rest) (cps--transform-1 form @@ -345,7 +345,7 @@ don't yield.") ;; Process `or'. - (`(or) (cps--transform-1 nil next-state)) + ('(or) (cps--transform-1 nil next-state)) (`(or ,condition) (cps--transform-1 condition next-state)) (`(or ,condition . ,rest) (cps--transform-1 @@ -374,13 +374,6 @@ don't yield.") `(setf ,cps--value-symbol ,temp-var-symbol ,cps--state-symbol ,next-state)))))))) - ;; Process `prog2'. - - (`(prog2 ,form1 ,form2 . ,body) - (cps--transform-1 - `(progn ,form1 (prog1 ,form2 ,@body)) - next-state)) - ;; Process `unwind-protect': If we're inside an unwind-protect, we ;; have a block of code UNWINDFORMS which we would like to run ;; whenever control flows away from the main piece of code, @@ -567,8 +560,11 @@ modified copy." (unless ,normal-exit-symbol ,@unwind-forms)))))) -(put 'iter-end-of-sequence 'error-conditions '(iter-end-of-sequence)) -(put 'iter-end-of-sequence 'error-message "iteration terminated") +(define-error 'iter-end-of-sequence "Iteration terminated" + ;; FIXME: This was not defined originally as an `error' condition, so + ;; we reproduce this by passing itself as the parent, which avoids the + ;; default `error' parent. Maybe it *should* be in the `error' category? + 'iter-end-of-sequence) (defun cps--make-close-iterator-form (terminal-state) (if cps--cleanup-table-symbol @@ -643,11 +639,11 @@ modified copy." ,(cps--make-close-iterator-form terminal-state))))) (t (error "unknown iterator operation %S" op)))))) ,(when finalizer-symbol - `(funcall iterator - :stash-finalizer - (make-finalizer - (lambda () - (iter-close iterator))))) + '(funcall iterator + :stash-finalizer + (make-finalizer + (lambda () + (iter-close iterator))))) iterator)))) (defun iter-yield (value) @@ -700,6 +696,14 @@ of values. Callers can retrieve each value using `iter-next'." `(lambda ,arglist ,(cps-generate-evaluator body))) +(defmacro iter-make (&rest body) + "Return a new iterator." + (declare (debug t)) + (cps-generate-evaluator body)) + +(defconst iter-empty (lambda (_op _val) (signal 'iter-end-of-sequence nil)) + "Trivial iterator that always signals the end of sequence.") + (defun iter-next (iterator &optional yield-result) "Extract a value from an iterator. YIELD-RESULT becomes the return value of `iter-yield' in the |