summaryrefslogtreecommitdiffstats
path: root/share
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2021-02-06 00:18:23 -0800
committerKaz Kylheku <kaz@kylheku.com>2021-02-06 00:18:23 -0800
commit72e321922b438c58285314c5c816b211cdec70ef (patch)
tree29e416ed43ee24f0e87c8e95681afd1d3f6d6cf2 /share
parent9ae3eed9230f44695b87c2a0fc6ea4a3a3a42ed1 (diff)
downloadtxr-72e321922b438c58285314c5c816b211cdec70ef.tar.gz
txr-72e321922b438c58285314c5c816b211cdec70ef.tar.bz2
txr-72e321922b438c58285314c5c816b211cdec70ef.zip
matcher: @(as) must always bind fresh variable.
It is documented that as binds a new variable. Furthermore, it used to be called let. Yet, it back-references. Let's fix it. * share/txr/stdlib/match.tl (compile-new-var-match): New function: like compile-var-match but binds new variable, as if back-referencing didn't exist. (compile-as-match): Use compile-new-var-match. * txr.1: Improve as documentation. Clarify that it binds a fresh variable, and that pattern is processed in its scope. Include an example with circular structure.
Diffstat (limited to 'share')
-rw-r--r--share/txr/stdlib/match.tl17
1 files changed, 16 insertions, 1 deletions
diff --git a/share/txr/stdlib/match.tl b/share/txr/stdlib/match.tl
index ab12ef7d..ea0134fc 100644
--- a/share/txr/stdlib/match.tl
+++ b/share/txr/stdlib/match.tl
@@ -205,6 +205,21 @@
guard-chain (list (new match-guard
guard-expr ^(equal ,obj-var ,sym)))))))
+(defun compile-new-var-match (sym obj-var var-list)
+ (cond
+ ((null sym)
+ (new compiled-match
+ obj-var obj-var))
+ ((not (bindable sym))
+ (compile-error *match-form* "~s is not a bindable symbol" sym))
+ (t var-list.(record sym)
+ (new compiled-match
+ pattern sym
+ obj-var obj-var
+ guard-chain (if sym (list (new match-guard
+ vars (list sym)
+ var-exprs (list obj-var))))))))
+
(defun compile-vec-match (vec-pat obj-var var-list)
(let* ((elem-gensyms (mapcar (op gensym `elem-@1-`) (range* 0 (len vec-pat))))
(elem-exprs (mapcar (ret ^[,obj-var ,@1]) (range* 0 (len vec-pat))))
@@ -327,7 +342,7 @@
(defun compile-as-match (exp obj-var var-list)
(mac-param-bind *match-form* (op sym pat) exp
- (let ((var-match (compile-var-match sym obj-var var-list))
+ (let ((var-match (compile-new-var-match sym obj-var var-list))
(pat-match (compile-match pat obj-var var-list)))
(new compiled-match
pattern exp