diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2021-07-19 06:17:49 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2021-07-19 06:17:49 -0700 |
commit | ed2a61da442ac22f8433c06634f749fbda4b1972 (patch) | |
tree | 5a9b1af78c3fe0340a3e4f3b9ecd98cffa6a7991 /tests/012/op.tl | |
parent | d9c7016e2fb69ddc2d3be21c5ba566aa6c53d98f (diff) | |
download | txr-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.tl | 8 |
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)) |