aboutsummaryrefslogtreecommitdiffstats
path: root/match.csc
diff options
context:
space:
mode:
authorRose Hogenson <rhogenson@posteo.net>2022-01-09 11:16:17 -0800
committerRose Hogenson <rhogenson@posteo.net>2022-01-09 11:16:17 -0800
commite7d0eefb6f766968fe0de26556da1353ec9bd0ab (patch)
treeaf8b4015ddc64690655219e8367da1b7249f8a3a /match.csc
parentUse load to evaluate each library's tests. (diff)
downloadchromatopelma-e7d0eefb6f766968fe0de26556da1353ec9bd0ab.tar.zst
Add a library for pattern matching.
Diffstat (limited to 'match.csc')
-rw-r--r--match.csc60
1 files changed, 60 insertions, 0 deletions
diff --git a/match.csc b/match.csc
new file mode 100644
index 0000000..95b2b32
--- /dev/null
+++ b/match.csc
@@ -0,0 +1,60 @@
+(define-library (csc match)
+ (export match)
+ (import (scheme base))
+ (begin
+
+
+ (define-syntax matches?
+ (syntax-rules (!)
+ ((matches? x '())
+ (null? x))
+ ((matches? x (! bind))
+ #t)
+ ((matches? x ((! bind)))
+ (= 1 (length x)))
+ ((matches? x (lit))
+ (and (= 1 (length x))
+ (eqv? lit (car x))))
+ ((matches? x ((! bind) pattern1 pattern2 ...))
+ (and (pair? x)
+ (matches? (cdr x) (pattern1 pattern2 ...))))
+ ((matches? x (lit pattern1 pattern2 ...))
+ (and (pair? x)
+ (eqv? lit (car x))
+ (matches? (cdr x) (pattern1 pattern2 ...))))
+ ((matches? x lit)
+ (eqv? lit x))))
+
+
+ (define-syntax bind-pattern
+ (syntax-rules (!)
+ ((bind-pattern x '() result1 result2 ...)
+ (begin result1 result2 ...))
+ ((bind-pattern x (! bind) result1 result2 ...)
+ (let ((bind x))
+ result1 result2 ...))
+ ((bind-pattern x ((! bind)) result1 result2 ...)
+ (let ((bind (car x)))
+ result1 result2 ...))
+ ((bind-pattern x (lit) result1 result2 ...)
+ (begin result1 result2 ...))
+ ((bind-pattern x ((! bind) pattern1 pattern2 ...) result1 result2 ...)
+ (let ((bind (car x)))
+ (bind-pattern (cdr x) (pattern1 pattern2 ...) result1 result2 ...)))
+ ((bind-pattern x (lit pattern1 pattern2 ...) result1 result2 ...)
+ (bind-pattern (cdr x) (pattern1 pattern2 ...) result1 result2 ...))
+ ((bind-pattern x lit result1 result2 ...)
+ (begin result1 result2 ...))))
+
+
+ (define-syntax match
+ (syntax-rules (else)
+ ((match x (else result1 result2 ...))
+ (begin result1 result2 ...))
+ ((match x (pattern result1 result2 ...))
+ (if (matches? x pattern)
+ (bind-pattern x pattern result1 result2 ...)))
+ ((match x (pattern result1 result2 ...) clause1 clause2 ...)
+ (if (matches? x pattern)
+ (bind-pattern x pattern result1 result2 ...)
+ (match x clause1 clause2 ...)))))))