summaryrefslogtreecommitdiffstats
path: root/tests/012/op.tl
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2021-07-19 06:17:49 -0700
committerKaz Kylheku <kaz@kylheku.com>2021-07-19 06:17:49 -0700
commited2a61da442ac22f8433c06634f749fbda4b1972 (patch)
tree5a9b1af78c3fe0340a3e4f3b9ecd98cffa6a7991 /tests/012/op.tl
parentd9c7016e2fb69ddc2d3be21c5ba566aa6c53d98f (diff)
downloadtxr-ed2a61da442ac22f8433c06634f749fbda4b1972.tar.gz
txr-ed2a61da442ac22f8433c06634f749fbda4b1972.tar.bz2
txr-ed2a61da442ac22f8433c06634f749fbda4b1972.zip
op: fix bug in do.
The June 30 09e70c914ca83b5c7405aa633864db49f27efa05, subject "op: refactor do handling", introduced a regression breaking the tags.tl program. An implicit argument gets inserted twice: [[(do op list @1)] 'x] -> (x x) ;; incorrect/weird This was spotted by Paul A. Patience while working on extending tags.tl for Emacs. It's not exactly a regression because the original behavior is not documented or tested, and has issues; we simply cannot roll back the commit; a proper fix is required. How the above call is now supposed to work is that: - the @1 parameter belongs to the op, not to the do. - the do therefore has no explicitly given parameters of its own. - therefore the do inserts its parameter. In other words (do op list @1) is formally equivalent to (do op list @1 @@1). Both levels of function indirection require an argument: [[(do op list @1) 'x] 'y] -> (y x) [[(do op list @1 @@1) 'x] 'y] -> (y x) * stdlib/op.tl (sys:op-ctx): The structure gets a new slot, nested, which is a flag indicating whether unprocessed nested metas occur. This is critically needed because the sys:op-alpha-rename passes which are called with do-nested-metas being false do not insert nested metas into the gens list; they transform them and leave them in the syntax. Yet we must make decisions based on their presence. Conretely, we must be able to tell that (do op list @@1) has a meta against the outer (do ...), while we are just processing the do. (sys:op-alpha-rename): When replacing a nested meta syntax with the macro invocation, we set the nested flag of the parent context true. (sys:op-expand): Bring back the do-gen; we need it. We cannot simply insert @1 into the syntax, because that is not lexically transparent. If we add @1 to (do op ...) then that @1 is interpreted as belonging to the op, not to the do. We must also check the new Boolean flag nested to properly detect whether we have metas, including unexpanded nested metas. * tests/012/op.tl: New test cases combining (do op ...).
Diffstat (limited to 'tests/012/op.tl')
-rw-r--r--tests/012/op.tl8
1 files changed, 8 insertions, 0 deletions
diff --git a/tests/012/op.tl b/tests/012/op.tl
index 12969dcc..0cdc3e7b 100644
--- a/tests/012/op.tl
+++ b/tests/012/op.tl
@@ -74,3 +74,11 @@
(mtest
(flow 1 (+ 2) [dup *] (let ((x @1)) x)) 9
(flow #S(time year 2021) .year succ) 2022)
+
+(mtest
+ [[(do op list)] 2] :error
+ [[(do op list) 2]] (2)
+ [[(do op list @@1) 1] 2] (1 2)
+ [[(do op list @1)] 2] :error
+ [[(do op list @1) 1] 2] (2 1)
+ [[(do op list @@1 @1) 1] 2] (1 2))