diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2018-03-26 23:09:10 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2018-03-26 23:09:10 -0700 |
commit | d0b116d378634d1b33d85585afa45a2768d7c972 (patch) | |
tree | b2740c73e8912324e4b744072b751198826fe65a /share | |
parent | f4b162718c85d0b99edc01ae303de90ecdb65ddb (diff) | |
download | txr-d0b116d378634d1b33d85585afa45a2768d7c972.tar.gz txr-d0b116d378634d1b33d85585afa45a2768d7c972.tar.bz2 txr-d0b116d378634d1b33d85585afa45a2768d7c972.zip |
regression: fix broken tagbody.
commit 87caead8269055b4791de53be0e03afab01f1dd4, subject
"macros: expand declined form in outer env" broke tagbody.
The tagbody implementation uses a dubious trick of setting up
local macros which return the original form, as a way of
prevening an outer scoped macro from expanding the form. The
above commit specifically changes the behavior in such a way
that this strategy is nullified.
However, the macro fallback feature introduced by the above
commit is exactly what tagbody needs!
* share/txr/stdlib/tagbody.tl (tagbody): Simplify the
treatment of (go label) thanks to new behavior in macro
expander. We no longer need an extra sys:expand pass to
allow inner tagbodies to expand their go forms, and intercept
any unexpanded ones. We have a simple go macrolet which
performs the expansiion when the label is recognized, or else
returns the form to decline expansion. The macro expander
will then fall back by trying the macro in the next outer
scope. Thus, every (go label) is resolved in the tagbody
to which label belongs, or else lands into the top-level
go macro which diagnoses undefined labels.
Diffstat (limited to 'share')
-rw-r--r-- | share/txr/stdlib/tagbody.tl | 24 |
1 files changed, 5 insertions, 19 deletions
diff --git a/share/txr/stdlib/tagbody.tl b/share/txr/stdlib/tagbody.tl index a0e41a7c..535c5ea1 100644 --- a/share/txr/stdlib/tagbody.tl +++ b/share/txr/stdlib/tagbody.tl @@ -51,25 +51,11 @@ ((set ,next-var (block* ,tb-id (sys:switch ,next-var #(,*codes)) - nil)))))) - ;; pass one: expand inner forms, including tagbody forms. - ;; if any inner tagbody forms leave (go ...) forms unexpanded, - ;; protect those (go ...)forms from falling victim to the - ;; global macro, by wrapping this with a harmless local go macro. - (pass-one (sys:expand ^(macrolet ((go (:form form label) form)) - ,basic-code) env))) - ;; pass two: now expand the remaining go forms at this level, against - ;; this tagbody. If any go forms remain, they must refer to nonexistent - ;; labels. By calling sys:expand one more time, we flush these out - ;; using the global go macro --- unless we are nested inside the - ;; pass-one expansion of outer tagbody, which protects them! - ;; Thus, the outermost tagbody flushes out the undefined labels. - (sys:expand ^(macrolet ((go (:form form label) - (let ((index (posql label ',lbls))) - (cond - ((null index) form) - (t ^(return* ,',tb-id ,index)))))) - ,pass-one) env))))))) + nil))))))) + ^(macrolet ((go (:form form label) + (let ((index (posql label ',lbls))) + (if index ^(return* ,',tb-id ,index) form)))) + ,basic-code))))))) (defmacro go (label) (if [[orf symbolp integerp chrp] label] |