-
Notifications
You must be signed in to change notification settings - Fork 0
/
init.scm
184 lines (144 loc) · 4.52 KB
/
init.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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; simple pattern matching, tested with Kawa 1.9.1
;;; Mariusz Nowostawski <[email protected]>
;;;
;;; 2007-06-18
;;;
;;; use:
;;; ;; define some data
;;; (define data '(person (name Marcos) (surname Oliveira) (age 33)))
;;; ;; perform the matching-unification, and keep the binding in b
;;; (define b
;;; (match '(person (name ?name) (surname ?surname) (age ?age)) data))
;;; ;; get appropriate binding values
;;; (var '?age b)
;;; (var '?name b)
;;; (var '?surname b)
;;;
;;; for multiple datum and multiple bindings use mmatch and mvar accordingly.
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; lets define boolean constants
(define false '#f)
(define true '#t)
;;; query syntax extensions
(define (tagged-list? exp tag)
(if (pair? exp)
(eq? (car exp) tag)
false))
(define (var? exp) (tagged-list? exp '?))
(define (query-syntax-process exp)
(map-over-symbols expand-question-mark exp))
(define (map-over-symbols proc exp)
(cond ((pair? exp)
(cons (map-over-symbols proc (car exp))
(map-over-symbols proc (cdr exp))))
((symbol? exp) (proc exp))
(else exp)))
(define (expand-question-mark symbol)
(let ((chars (symbol->string symbol)))
(if (string=? (substring chars 0 1) "?")
(list '?
(string->symbol
(substring chars 1 (string-length chars))))
symbol)))
;;; bindings
(define (make-binding variable value)
(cons variable value))
(define (binding-variable binding)
(car binding))
(define (binding-value binding)
(cdr binding))
(define (binding-in-frame variable frame)
(assoc variable frame))
(define (extend variable value frame)
(cons (make-binding variable value) frame))
;;; Unification and patterns
(define (unify-match p1 p2 frame)
(cond ((eq? frame false) false)
((equal? p1 p2) frame)
((var? p1) (extend-if-possible p1 p2 frame))
((var? p2) (extend-if-possible p2 p1 frame))
((and (pair? p1) (pair? p2))
(unify-match (cdr p1)
(cdr p2)
(unify-match (car p1)
(car p2)
frame)))
(else false)))
(define (extend-if-possible var val frame)
(let ((binding (binding-in-frame var frame)))
(cond (binding
(unify-match
(binding-value binding) val frame))
((var? val)
(let ((binding (binding-in-frame val frame)))
(if binding
(unify-match
var (binding-value binding) frame)
(extend var val frame))))
((depends-on? val var frame) ; {\em ; ***}
'failed)
(else (extend var val frame)))))
(define (depends-on? exp var frame)
(define (tree-walk e)
(cond ((var? e)
(if (equal? var e)
true
(let ((b (binding-in-frame e frame)))
(if b
(tree-walk (binding-value b))
false))))
((pair? e)
(or (tree-walk (car e))
(tree-walk (cdr e))))
(else false)))
(tree-walk exp))
(define (pattern-match pat dat frame)
(cond ((eq? frame 'failed) 'failed)
((equal? pat dat) frame)
((var? pat) (extend-if-consistent pat dat frame))
((and (pair? pat) (pair? dat))
(pattern-match (cdr pat)
(cdr dat)
(pattern-match (car pat)
(car dat)
frame)))
(else 'failed)))
(define (extend-if-consistent var dat frame)
(let ((binding (binding-in-frame var frame)))
(if binding
(pattern-match (binding-value binding) dat frame)
(extend var dat frame))))
;; single pattern single data matching
(define match
(lambda (pat dat)
(let ((f '()))
(unify-match (query-syntax-process pat) dat f))))
(define var
(lambda (variable f)
(cdr (assoc (expand-question-mark variable) f))))
;; single pattern, multiple data matching
(define mmatch
(lambda (pat dats)
(if (null? dats)
'()
(let ((f (match pat (car dats))))
(if (eq? f false)
(mmatch pat (cdr dats))
(let ((g (mmatch pat (cdr dats))))
(if (null? g)
f
(list f g))))))))
(define mvar
(lambda (variable mf)
(if (null? mf)
'()
(let ((b (var variable (car mf))))
(if (eq? b false)
(mvar variable (cdr mf))
(let ((g (mvar variable (cdr mf))))
(if (null? g)
b
(list b g))))))))