summaryrefslogtreecommitdiffstats
path: root/lib.h
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2025-05-10 19:48:30 -0700
committerKaz Kylheku <kaz@kylheku.com>2025-05-10 19:48:30 -0700
commit59da72099d08b1b2573cc80bcd1493033b479e0c (patch)
treeec3d346851e6a0ed5a7bb3f60e2a6db9408c8272 /lib.h
parentf46ff43283a70b77d2c76fd37a415ab506b0f78c (diff)
downloadtxr-59da72099d08b1b2573cc80bcd1493033b479e0c.tar.gz
txr-59da72099d08b1b2573cc80bcd1493033b479e0c.tar.bz2
txr-59da72099d08b1b2573cc80bcd1493033b479e0c.zip
match: make @(require) work over args in lambda-match.
The issue is that in a lambda-match, when we wrap @(require) around an argument match, it becomes a single pattern which matches the variadic arguments as a list. As a result, the function also becomes variadic, and a list is consed up for the match. A nested list is worth a thousand words: Before this change: 1> (expand '(lambda-match (@(require (@a @b) (= 5 (+ a b))) (cons a b)))) (lambda (. #:rest0014) (let (#:result0015) (or (let* (a b) (let ((#:g0017 (list* #:rest0014))) (if (consp #:g0017) (let ((#:g0018 (car #:g0017)) (#:g0019 (cdr #:g0017))) (sys:setq a #:g0018) (if (consp #:g0019) (let ((#:g0020 (car #:g0019)) (#:g0021 (cdr #:g0019))) (sys:setq b #:g0020) (if (equal #:g0021 '()) (if (and (= 5 (+ a b))) (progn (sys:setq #:result0015 (cons a b)) t)))))))))) #:result0015)) After this change: 1> (expand '(lambda-match (@(require (@a @b) (= 5 (+ a b))) (cons a b)))) (lambda (#:arg-00015 #:arg-10016) (let (#:result0017) (or (let* (b a) (sys:setq b #:arg-10016) (sys:setq a #:arg-00015) (if (and (= 5 (+ a b))) (progn (sys:setq #:result0017 (cons a b)) t)))) #:result0017)) @(require (@a @b)) now leads to a two-argument function. The guard condition is applied to the a and b variables extracted from the arguments rather than a list. * stdlib/match.tl (when-exprs-match): Macro removed. (struct lambda-clause): New slot, require-conds. (parse-lambda-match-clause): Recognize @(require ...) syntax, destructure it and recurse into the argument pattern it contains. Because the incoming syntax includes the clause body, for the recursive call we synthesize syntax consisting of the pattern extracted from the @(require), coupled with the clause body. When the recursive call gives us a lambda-clause structure, we then add the require guard expressions to it. So in essence the behavior is that we parse the (@(require argpat cond ...) body) as if it were (argpat body), and decorate the object with the extracted conditions. (expand-lambda-match): This now takes an env argument due to the fact that when-exprs-match was removed. when-exprs-match relied on its :env parameter to get the environment, needed for compile-match. Now expand-lambda-match directly calls compile-match, doing all the work that when-exprs-match helper was doing. Integrating that into expand-lambda-match allows us to add logic to detect that the lambda-clause structure has require conditions, and add the code as a guard to the compiled match using add-guards-post. (lambda-match, defun-match, :match): Pass environment argument to expand-lambda-match.
Diffstat (limited to 'lib.h')
0 files changed, 0 insertions, 0 deletions