diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2021-01-22 07:20:44 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2021-01-22 07:20:44 -0800 |
commit | 1e8dc4f05dc5149f682ac16f3d368ec0fc82cf58 (patch) | |
tree | 523a98f2a7c79253578ce39295a65644f11f2f32 | |
parent | 2df5586aebf988091508e5bc8b50a090b153c8e7 (diff) | |
download | txr-1e8dc4f05dc5149f682ac16f3d368ec0fc82cf58.tar.gz txr-1e8dc4f05dc5149f682ac16f3d368ec0fc82cf58.tar.bz2 txr-1e8dc4f05dc5149f682ac16f3d368ec0fc82cf58.zip |
matcher: fix null value ambiguity in hash match.
Hash pattern matching must not assume that if gethash returns
nil, the item is not found. That's just a convenience that can
be coded in some situations, not in a general mechanism.
* share/txr/stdlib/match.tl (compile-hash-match): Allocate a
gensym that serves as a unique object. Pass this to gethash
as the alt argument, and then check whether gethash has
returned this value to indicate failure.
-rw-r--r-- | share/txr/stdlib/match.tl | 7 |
1 files changed, 6 insertions, 1 deletions
diff --git a/share/txr/stdlib/match.tl b/share/txr/stdlib/match.tl index b6dcd442..32f8b7ca 100644 --- a/share/txr/stdlib/match.tl +++ b/share/txr/stdlib/match.tl @@ -314,6 +314,7 @@ (defun compile-hash-match (hash-expr obj-var var-list) (tree-bind (op . pairs) hash-expr (let* ((hash-alist-var (gensym "hash-alist-")) + (hash-alt-val ^',(gensym "alt")) (need-alist-p nil) (hash-matches (collect-each ((pair pairs)) @@ -338,8 +339,12 @@ (let ((vm (compile-match val (gensym "val") var-list))) (push (new match-guard + guard-expr ^(neq ,vm.obj-var ,hash-alt-val)) + vm.guard-chain) + (push + (new match-guard vars (list vm.obj-var) - var-exprs ^((gethash ,obj-var ',key))) + var-exprs ^((gethash ,obj-var ',key, hash-alt-val))) vm.guard-chain) vm))))))) (guard (new match-guard |