diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2021-12-08 07:16:00 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2021-12-08 07:16:00 -0800 |
commit | 1e4eadfd30f675f80e17e84682dfc88da6be9681 (patch) | |
tree | a1bc89f27d7d4c748f4189f974a95a59f1f933ce | |
parent | a621bb39d04e1f77fc45c24a3ac3fc08291533fa (diff) | |
download | txr-1e4eadfd30f675f80e17e84682dfc88da6be9681.tar.gz txr-1e4eadfd30f675f80e17e84682dfc88da6be9681.tar.bz2 txr-1e4eadfd30f675f80e17e84682dfc88da6be9681.zip |
each-match macro family: missing anon block.
* txr.1: Adding the missing requirement that each-match
and the other macros in that family must have an implicit
anonymous block around the body forms. This is a requirements
bug, effectively: the programmer expects these operators to be
consistent with the each operator, as part of the same family.
* match.tl (each-match-expander): Implement the requirement.
Since we are using mapping functions, we must use temporary
variables: the evaluation of the expressions which produce the
sequence argument values to the mapping functions must be
outside of the anonymous block. The block must surround only
the function call.
* tests/011/patmatch.tl: Add small test case covering this.
-rw-r--r-- | stdlib/match.tl | 7 | ||||
-rw-r--r-- | tests/011/patmatch.tl | 3 | ||||
-rw-r--r-- | txr.1 | 16 |
3 files changed, 22 insertions, 4 deletions
diff --git a/stdlib/match.tl b/stdlib/match.tl index 8d014f11..a38798d6 100644 --- a/stdlib/match.tl +++ b/stdlib/match.tl @@ -1070,8 +1070,11 @@ (eql 2 (length pair))) (compile-error f "invalid pattern-sequence pair ~s" pair))) (let* ((pats [mapcar car pat-seq-pairs]) - (seqs [mapcar cadr pat-seq-pairs])) - ^(,fun (lambda-match ((,*pats) (progn ,*body))) ,*seqs)))) + (seqs [mapcar cadr pat-seq-pairs]) + (gens [mapcar (ret (gensym)) pat-seq-pairs])) + ^(let ,(zip gens seqs) + (block nil + (,fun (lambda-match ((,*pats) (progn ,*body))) ,*gens)))))) (defmacro each-match (:form f pat-seq-pairs . body) (each-match-expander f pat-seq-pairs body 'mapdo)) diff --git a/tests/011/patmatch.tl b/tests/011/patmatch.tl index da2f8de4..fbdd3da0 100644 --- a/tests/011/patmatch.tl +++ b/tests/011/patmatch.tl @@ -470,6 +470,9 @@ (list x y)) ((1 2) (1 4) (3 2) (3 4) (5 2) (5 4))) +(test + (each-match (@a '(1 2 3)) (return 42)) 42) + (mtest (when-match ^(,a ,b) '(1 2) (list a b)) (1 2) (when-match ^(,(oddp @a) ,(evenp @b)) '(1 2) (list a b)) (1 2) @@ -44707,6 +44707,14 @@ The remaining arguments are .metn body-form s to evaluated for successful matches. +The +.metn body-form s +are surrounded by an implicit anonymous block. If any of the forms +.code return +invoke a return out of this block, then the iteration terminates, and +the result value of the block becomes the result value of +the loop. + The processing takes place as follows: .RS .IP 1. @@ -44806,7 +44814,9 @@ The macro .code append-matches is subject to all of the requirements specified for .code each-match -in regard to the argument conventions and semantics. +in regard to the argument conventions and semantics, +and the presence of the implicit anonymous block around the +.metn body-form s. Whereas .code each-match @@ -44873,7 +44883,9 @@ The macro .code keep-matches is subject to all of the requirements specified for .code each-match -in regard to the argument conventions and semantics. +in regard to the argument conventions and semantics, +and the presence of the implicit anonymous block around the +.metn body-form s. Whereas .code each-match |