diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2021-01-21 21:08:28 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2021-01-21 21:08:28 -0800 |
commit | ce6c1ff37c9709b98c464b4b79199b249f6185dc (patch) | |
tree | 941734a49eae8d27f79ef0a2bf3938bf3b947fd8 | |
parent | 49e6d4d9651f706c517c65e14b00b8a233c59aa1 (diff) | |
download | txr-ce6c1ff37c9709b98c464b4b79199b249f6185dc.tar.gz txr-ce6c1ff37c9709b98c464b4b79199b249f6185dc.tar.bz2 txr-ce6c1ff37c9709b98c464b4b79199b249f6185dc.zip |
matcher: first cut at @(hash ...) operator.
* share/txr/stdlib/match.tl (compile-hash-match): New
function.
(compile-match): Hook in hash operator.
(is-pattern): New function: uses match-case, and is used in
the implementation of the hash operator. This works because
the function doesn't use @(hash ...) anywhere.
-rw-r--r-- | share/txr/stdlib/match.tl | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/share/txr/stdlib/match.tl b/share/txr/stdlib/match.tl index 9d7c1ba1..e5e37be2 100644 --- a/share/txr/stdlib/match.tl +++ b/share/txr/stdlib/match.tl @@ -310,6 +310,53 @@ test-expr t vars nil)))) +(defun compile-hash-match (hash-expr obj-var var-list) + (tree-bind (op . pairs) hash-expr + (let* ((hash-alist-var (gensym "hash-alist-")) + (need-alist-p nil) + (hash-matches + (collect-each ((pair pairs)) + (mac-param-bind *match-form* (key val) pair + (let ((key-pat-p (is-pattern key)) + (val-pat-p (is-pattern val))) + (cond + ((and key-pat-p val-pat-p) + (set need-alist-p t) + (compile-match ^@(coll (,key . ,val)) + hash-alist-var var-list)) + (key-pat-p + (let ((km (compile-match key (gensym "keys") + var-list))) + (push + (new match-guard + guard-expr t + vars (list km.obj-var) + var-exprs ^((hash-keys-of ,obj-var ',val))) + km.guard-chain) + km)) + (t + (let ((vm (compile-match val (gensym "val") var-list))) + (push + (new match-guard + guard-expr t + vars (list vm.obj-var) + var-exprs ^((gethash ,obj-var ',key))) + vm.guard-chain) + vm))))))) + (guard (new match-guard + guard-expr ^(hashp ,obj-var) + vars (if need-alist-p + (list hash-alist-var)) + var-exprs (if need-alist-p + (list ^(hash-alist ,obj-var)))))) + (new compiled-match + pattern hash-expr + obj-var obj-var + guard-chain (cons guard (mappend .guard-chain hash-matches)) + test-expr ^(and ,*(mapcar .test-expr hash-matches)) + vars (mappend .vars hash-matches) + var-exprs (mappend .var-exprs hash-matches))))) + (defun compile-match (pat : (obj-var (gensym)) (var-list (new var-list))) (cond ((consp pat) @@ -329,6 +376,7 @@ (and (compile-parallel-match exp obj-var var-list)) (not (compile-not-match exp obj-var var-list)) (op (compile-op-match exp obj-var var-list)) + (hash (compile-hash-match exp obj-var var-list)) (t (compile-predicate-match exp obj-var var-list))) (compile-error *match-form* "unrecognized pattern syntax ~s" pat)))) @@ -388,3 +436,9 @@ (with-gensyms (args) ^(defun ,name (. ,args) (match-case ,args ,*clauses)))) + +(defun is-pattern (syntax) + (match-case syntax + ((@(op eq 'sys:expr) (@(bindable) . @nil)) t) + ((@(op eq 'sys:var) @(bindable) . @nil) t) + (@(some @(is-pattern)) t))) |