diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2021-02-05 19:30:28 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2021-02-05 19:30:28 -0800 |
commit | d02854155e915e28740605a7302faaaff1128622 (patch) | |
tree | cf078bfe40a321df8450b6b9c2ab512f35ae6d86 | |
parent | 00a793530e0386cfbe29670a8224f5e82897b283 (diff) | |
download | txr-d02854155e915e28740605a7302faaaff1128622.tar.gz txr-d02854155e915e28740605a7302faaaff1128622.tar.bz2 txr-d02854155e915e28740605a7302faaaff1128622.zip |
matcher: rearrange match order of @(with).
The @(with side-pat expr main-pat) syntax becomes
@(with main-pat side-pat expr), which is more useful.
Also, the main-pat can be omitted.
* share/txr/stdlib/match.tl (compile-with-match): Recognize
two forms of the syntax: two argument form with main-pat
omitted and the full form. In the full form, main-pat is
on the left now and processed first, so we have to rearrange
the compilation and integration order.
* tests/011/patmatch.tl: Existing tests updated. Two-argument
test added.
* txr.1: Updated.
-rw-r--r-- | share/txr/stdlib/match.tl | 36 | ||||
-rw-r--r-- | tests/011/patmatch.tl | 9 | ||||
-rw-r--r-- | txr.1 | 32 |
3 files changed, 49 insertions, 28 deletions
diff --git a/share/txr/stdlib/match.tl b/share/txr/stdlib/match.tl index 38d0b821..e269ecc1 100644 --- a/share/txr/stdlib/match.tl +++ b/share/txr/stdlib/match.tl @@ -331,22 +331,26 @@ pat-match.guard-chain))))) (defun compile-with-match (exp obj-var var-list) - (mac-param-bind *match-form* (op side-pat-var side-expr main-pat) exp - (let* ((side-var (gensym)) - (side-pat (if (or (null side-pat-var) (bindable side-pat-var)) - ^(sys:var ,side-pat-var) - side-pat-var)) - (side-match (compile-match side-pat side-var var-list)) - (main-match (compile-match main-pat obj-var var-list)) - (guard (new match-guard - pure-temps (list side-var) - pure-temp-exprs (list side-expr)))) - (new compiled-match - pattern exp - obj-var obj-var - guard-chain (append (list guard) - side-match.guard-chain - main-match.guard-chain))))) + (tree-case exp + ((op main-pat side-pat-var side-expr) + (let* ((side-var (gensym)) + (side-pat (if (or (null side-pat-var) (bindable side-pat-var)) + ^(sys:var ,side-pat-var) + side-pat-var)) + (main-match (compile-match main-pat obj-var var-list)) + (side-match (compile-match side-pat side-var var-list)) + (guard (new match-guard + pure-temps (list side-var) + pure-temp-exprs (list side-expr)))) + (new compiled-match + pattern exp + obj-var obj-var + guard-chain (append main-match.guard-chain + (list guard) + side-match.guard-chain)))) + ((op side-pat-var side-expr) + (compile-with-match ^(,op @nil ,side-pat-var ,side-expr) obj-var var-list)) + (x (compile-error *match-form* "bad syntax: ~s" exp)))) (defun compile-loop-match (exp obj-var var-list) (mac-param-bind *match-form* (op match) exp diff --git a/tests/011/patmatch.tl b/tests/011/patmatch.tl index 5dd735b9..fe82d28c 100644 --- a/tests/011/patmatch.tl +++ b/tests/011/patmatch.tl @@ -120,14 +120,19 @@ (test (when-match (@a @(as a @(or x @a))) '(#1=(1 2 #1# 3) #1#) :yes) :yes) -(test (when-match (@(with x 42 @a) @b @c) '(1 2 3) (list a b c x)) +(test (when-match (@(with @a x 42) @b @c) '(1 2 3) (list a b c x)) (1 2 3 42)) (test (let ((o 3)) - (when-match (@(evenp x) @(with @(oddp y) o @z)) '(4 6) + (when-match (@(evenp x) @(with @z @(oddp y) o)) '(4 6) (list x y z))) (4 3 6)) +(test (let ((o 3)) + (when-match (@(evenp x) @(with @(oddp y) o)) '(4 6) + (list x y))) + (4 3)) + (defstruct node () left right) @@ -40288,12 +40288,12 @@ as its value. .coNP Pattern operator @ with .synb -.mets @(with >> [ side-pattern | << name ] < expr << main-pattern ) +.mets @(with <> [ main-pattern ] >> { side-pattern | << name } << expr ) .syne .desc The .code with -pattern operator matches the +pattern operator matches the optional .meta main-pattern against a corresponding object, while matching a .meta side-pattern @@ -40303,15 +40303,27 @@ against the value of the expression .meta expr which is embedded in the syntax. +First, if +.meta main-pattern +is present in the syntax, +it is matched its corresponding object. This match must +succeed, or else the +.code with +operator fails to match. -First, +Next, .meta expr -is evaluated in the scope of earlier pattern variables. It is unspecified -whether later pattern variables are visible. The matching of +is evaluated in the scope of earlier pattern variables, including any +which that emanate from +.metn main-pattern . +It is unspecified +whether later pattern variables are visible. + +Finally, .meta side-pattern -follows, and if that succeeds, then the matching of -.meta main-pattern -against the corresponding object takes place. +is matched against the value of +.metn expr . +If that succeeds, then the operator has successfully matched. If a .meta name @@ -40323,11 +40335,11 @@ it must be a bindable symbol or else .TP* Examples: .verb - (when-match (@(with x 42 @a) @b @c) '(1 2 3) (list a b c x)) + (when-match (@(with @a x 42) @b @c) '(1 2 3) (list a b c x)) --> (1 2 3 42) (let ((o 3)) - (when-match (@(evenp x) @(with @(oddp y) o @z)) '(4 6) + (when-match (@(evenp x) @(with @z @(oddp y) o)) '(4 6) (list x y z))) --> (4 3 6) .brev |