-
Notifications
You must be signed in to change notification settings - Fork 0
/
match.scm
89 lines (85 loc) · 2.61 KB
/
match.scm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
(define-syntax match
(syntax-rules ()
((_ e . clauses)
(let ((value e))
(match-evaluated value . clauses)))))
(define-syntax match-evaluated
(syntax-rules (guard)
((_ value)
(error 'match 'no-matching-clauses value))
((_ value . ((pattern (guard predicate) . expressions) . clauses))
(match-clause
((pattern value))
(and)
()
expressions
(match-evaluated value . clauses)
predicate))
((_ value . ((pattern . expressions) . clauses))
(match-clause
((pattern value))
(and)
()
expressions
(match-evaluated value . clauses)
#t))))
(define-syntax match-clause
(syntax-rules (unquote)
#;(match-clause pairs condition bindings expressions alternative predicate)
((_ () condition bindings expressions alternative #t)
(if condition
(let bindings . expressions)
alternative))
((_ () condition bindings expressions alternative predicate)
(let ([alter (lambda () alternative)])
(if condition
(let bindings (if predicate (begin . expressions) (alter)))
(alter))))
;;; underscore is reserved for syntax-rules
;;; underscore cannot be used as empty pattern
;;; instead, any non-identifier can be used. ,() is a great choice
((_ ((,() root) . rest) condition bindings expressions alternative predicate)
(match-clause
rest
condition
bindings
expressions
alternative
predicate))
((_ ((,variable root) . rest) condition bindings expressions alternative predicate)
(match-clause
rest
condition
((variable root) . bindings)
expressions
alternative
predicate))
((_ (((left . right) root) . rest) (and condition ...) bindings expressions alternative predicate)
(match-clause
((left (car root)) (right (cdr root)) . rest)
(and condition ... (pair? root))
bindings
expressions
alternative
predicate))
((_ ((literal root) . rest) (and condition ...) bindings expressions alternative predicate)
(match-clause
rest
(and condition ... (equal? (quote literal) root))
bindings
expressions
alternative
predicate))))
#;(begin
'example
(define (interp e)
(match e
(,v (guard (number? v)) v)
((+ ,e1 ,e2) (+ (interp e1) (interp e2)))
((- ,e1 ,e2) (- (interp e1) (interp e2)))
((* ,e1 ,e2) (* (interp e1) (interp e2)))
((/ ,e1 ,e2) (/ (interp e1) (interp e2)))
(,() (error interp 'unmatch:e e))))
(pretty-print (interp '
(+ (* 3 3) (* 4 4))
)))