From 1e8dc4f05dc5149f682ac16f3d368ec0fc82cf58 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Fri, 22 Jan 2021 07:20:44 -0800 Subject: 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. --- share/txr/stdlib/match.tl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) 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)) @@ -336,10 +337,14 @@ km)) (t (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 -- cgit v1.2.3