summaryrefslogtreecommitdiffstats
path: root/share
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2018-03-26 23:09:10 -0700
committerKaz Kylheku <kaz@kylheku.com>2018-03-26 23:09:10 -0700
commitd0b116d378634d1b33d85585afa45a2768d7c972 (patch)
treeb2740c73e8912324e4b744072b751198826fe65a /share
parentf4b162718c85d0b99edc01ae303de90ecdb65ddb (diff)
downloadtxr-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.tl24
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]