summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--stdlib/match.tl72
1 files changed, 40 insertions, 32 deletions
diff --git a/stdlib/match.tl b/stdlib/match.tl
index f389d81b..674e3aa6 100644
--- a/stdlib/match.tl
+++ b/stdlib/match.tl
@@ -791,29 +791,30 @@
,*(mapcar (ret ^(,(car @1) ,*(cdr @1) t)) clauses)))
()))
-(defmacro when-exprs-match (:form *match-form* :env e pats exprs . forms)
- (let ((em (compile-match ^@(exprs ,*pats) exprs (get-var-list e))))
- ^(let* (,*em.(get-vars))
- ,em.(wrap-guards . forms))))
-
(defstruct lambda-clause ()
orig-syntax
fixed-patterns
variadic-pattern
nfixed
forms
+ require-conds
(:postinit (me)
(set me.nfixed (len me.fixed-patterns))))
(defun parse-lambda-match-clause (clause)
(mac-param-bind *match-form* (args . body) clause
- (cond
- ((atom args) (new lambda-clause
- orig-syntax args
- variadic-pattern args
- forms body))
- ((proper-list-p args)
+ (match-case args
+ (@(atom)
+ (new lambda-clause
+ orig-syntax args
+ variadic-pattern args
+ forms body))
+ ((@(eq 'sys:expr) (require @inargs . @conditions))
+ (let ((pc (parse-lambda-match-clause ^(,inargs ,*body))))
+ (set pc.require-conds (append conditions pc.require-conds))
+ pc))
+ (@(proper-list-p)
(let* ((vpos (pos-if (lop meq 'sys:expr 'sys:var 'sys:quasi) args)))
(tree-bind (fixed-pats . variadic-pat) (split args vpos)
(new lambda-clause
@@ -821,13 +822,14 @@
fixed-patterns fixed-pats
variadic-pattern (car variadic-pat)
forms body))))
- (t (new lambda-clause
- orig-syntax args
- fixed-patterns (butlast args 0)
- variadic-pattern (last args 0)
- forms body)))))
-
-(defun expand-lambda-match (clauses)
+ (@nil
+ (new lambda-clause
+ orig-syntax args
+ fixed-patterns (butlast args 0)
+ variadic-pattern (last args 0)
+ forms body)))))
+
+(defun expand-lambda-match (clauses env)
(let* ((parsed-clauses [mapcar parse-lambda-match-clause clauses])
(max-args (or [find-max parsed-clauses : .nfixed].?nfixed 0))
(min-args (or [find-min parsed-clauses : .nfixed].?nfixed 0))
@@ -845,15 +847,21 @@
(result-temp (gensym "result"))
(ex-clauses (collect-each ((pc parsed-clauses))
(let* ((vp pc.variadic-pattern)
- (exp ^(when-exprs-match
- (,*pc.fixed-patterns
- ,*(if vp (list vp)))
- (,*[arg-temps 0..pc.nfixed]
- ,*(if vp
- ^((list* ,*[arg-temps pc.nfixed..:]
- ,rest-temp))))
- (set ,result-temp (progn ,*pc.forms))
- t)))
+ (em (compile-match
+ ^@(exprs ,*pc.fixed-patterns ,*(if vp (list vp)))
+ ^(,*[arg-temps 0..pc.nfixed]
+ ,*(if vp
+ ^((list* ,*[arg-temps pc.nfixed..:]
+ ,rest-temp))))
+ (get-var-list env)))
+ (exp (progn
+ (iflet ((conds pc.require-conds))
+ em.(add-guards-post (new match-guard
+ guard-expr ^(and ,*conds))))
+ ^(let* (,*em.(get-vars))
+ ,em.(wrap-guards ^(set ,result-temp
+ (progn ,*pc.forms))
+ t)))))
(sys:set-macro-ancestor exp pc.orig-syntax)
(when (> pc.nfixed min-args)
(set exp ^(when ,[present-vec (pred pc.nfixed)]
@@ -874,11 +882,11 @@
(or ,*ex-clauses)
,result-temp))))
-(defmacro lambda-match (:form *match-form* . clauses)
- (expand-lambda-match clauses))
+(defmacro lambda-match (:env e :form *match-form* . clauses)
+ (expand-lambda-match clauses e))
-(defmacro defun-match (:form *match-form* name . clauses)
- (tree-bind (t args . body) (expand-lambda-match clauses)
+(defmacro defun-match (:form *match-form* :env e name . clauses)
+ (tree-bind (t args . body) (expand-lambda-match clauses e)
^(defun ,name ,args . ,body)))
(defmacro match-tuple-case (args . clauses)
@@ -895,7 +903,7 @@
(compile-error form
"~s is incompatible with optional parameters"
:match))
- (tree-bind (t lparams . body) (expand-lambda-match clauses)
+ (tree-bind (t lparams . body) (expand-lambda-match clauses menv)
(let ((dashdash (member '-- params)))
(cons (append (ldiff params dashdash)
(butlastn 0 lparams)