From 3627751339fc70ea779ffdb666565f5b36f11439 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Mon, 26 Mar 2018 23:09:10 -0700 Subject: regression: fix broken tagbody. commit 6a241b9d13e6b55f581a1e5f802b6f43d44a010d, 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. --- share/txr/stdlib/tagbody.tl | 24 +++++------------------- 1 file 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] -- cgit v1.2.3