root/lang/scheme/3imp/4.4.scm @ 29859

Revision 29859, 7.4 kB (checked in by mokehehe, 4 years ago)
Line 
1
2(load "./util.scm")
3
4(define extend
5  (lambda (e r)
6    (cons r e)))
7
8(define compile
9  (lambda (x e next)
10    (cond
11     ((symbol? x) (compile-refer x e next))
12     ((pair? x)
13      (record-case x
14                   (quote (obj) (list 'constant obj next))
15                   (lambda (vars body)
16                     (let ((free (find-free body vars)))
17                       (collect-free free e
18                                     (list 'close
19                                           (length free)
20                                           (compile body
21                                                    (cons vars free)
22                                                    (list 'return
23                                                          (length vars)))
24                                           next))))
25                   (if (test then else)
26                       (let ((thenc (compile then e next))
27                             (elsec (compile else e next)))
28                         (compile test e (list 'test thenc elsec))))
29                   (call/cc (x)
30                            (list 'frame
31                                  next
32                                  (list 'conti
33                                        (list 'argument
34                                              (compile x e '(apply))))))
35                   (else
36                    (recur loop ((args (cdr x))
37                                 (c (compile (car x) e '(apply))))
38                           (if (null? args)
39                               (list 'frame next c)
40                             (loop (cdr args)
41                               (compile (car args)
42                                        e
43                                        (list 'argument c))))))))
44     (else
45      (list 'constant x next)))))
46
47(define compile-lookup
48  (lambda (var e return)
49    (recur nxtrib ((e e) (rib 0))
50           (if (null? e)
51               (error "undefined" var)
52             (recur nxtelt ((vars (car e)) (elt 0))
53                    (cond
54                     ((null? vars) (nxtrib (cdr e) (+ rib 1)))
55                     ((eq? (car vars) var) (return rib elt))
56                     (else (nxtelt (cdr vars) (+ elt 1)))))))))
57
58(define find-free
59  (lambda (x b)
60    (cond
61     ((symbol? x) (if (set-member? x b) '() (list x)))
62     ((pair? x)
63      (record-case x
64                   (quote (obj) '())
65                   (lambda (vars body)
66                     (find-free body (set-union vars b)))
67                   (if (test then else)
68                       (set-union (find-free test b)
69                                  (set-union (find-free then b)
70                                             (find-free else b))))
71                   (call/cc (exp) (find-free exp b))
72                   (else
73                    (recur next ((x x))
74                           '()
75                           (set-union (find-free (car x) b)
76                                      (next (cdr x)))))))
77     (else '()))))
78
79(define collect-free
80  (lambda (vars e next)
81    (if (null? vars)
82        next
83      (collect-free (cdr vars) e
84                   (compile-refer (car vars) e
85                                  (list 'argument next))))))
86
87(define compile-refer
88  (lambda (x e next)
89    (compile-lookup x e
90                    (lambda (n) (list 'refer-local n next))
91                    (lambda (n) (list 'refer-free n next)))))
92
93(define compile-lookup
94  (lambda (x e return-local return-free)
95    (recur nxtlocal ((locals (car e)) (n 0))
96           (if (null? locals)
97               (recur nxtfree ((free (cdr e)) (n 0))
98                      (if (eq? (car free) x)
99                          (return-free n)
100                        (nxtfree (cdr free) (+ n 1))))
101             (if (eq? (car locals) x)
102                 (return-local n)
103               (nxtlocal (cdr locals) (+ n 1)))))))
104
105(define set-member?
106  (lambda (x s)
107    (cond
108     ((null? s) #f)
109     ((eq? x (car s)) #t)
110     (else (set-member? x (cdr s))))))
111
112(define set-cons
113  (lambda (x s)
114    (if (set-member? x s)
115        s
116      (cons x s))))
117
118(define set-union
119  (lambda (s1 s2)
120    (if (null? s1)
121        s2
122      (set-union (cdr s1) (set-cons (car s1) s2)))))
123
124(define set-minus
125  (lambda (s1 s2)
126    (if (null? s1)
127        '()
128      (if (set-member? (car s1) s2)
129          (set-minus (cdr s1) s2)
130        (cons (car s1) (set-minus (cdr s1) s2))))))
131
132(define set-intersect
133  (lambda (s1 s2)
134    (if (null? s1)
135        '()
136      (if (set-member? (car s1) s2)
137          (cons (car s1) (set-intersect (cdr s1) s2))
138        (set-intersect (cdr s1) s2)))))
139
140
141;;;; runtime
142
143(define functional
144  (lambda (body e)
145    (list body e)))
146
147(define stack (make-vector 1000))
148
149(define push
150  (lambda (x s)
151    (vector-set! stack s x)
152    (+ s 1)))
153
154(define index
155  (lambda (s i)
156    (vector-ref stack (- (- s i) 1))))
157
158(define index-set!
159  (lambda (s i v)
160    (vector-set! stack (- (- s i) 1) v)))
161
162
163;;;; VM
164
165(define VM
166  (lambda (a x f c s)
167    (record-case x
168                 (halt () a)
169                 (refer-local (n x)
170                              (VM (index f n) x f c s))
171                 (refer-free (n x)
172                             (VM (index-closure c n) x f c s))
173                 (constant (obj x)
174                           (VM obj x f c s))
175                 (close (n body x)
176                        (VM (closure body n s) x f c (- s n)))
177                 (test (then else)
178                       (VM a (if a then else) f c s))
179                 (conti (x)
180                        (VM (continuation s) x f c s))
181                 (nuate (stack x)
182                        (VM a x f c (restore-stack stack)))
183                 (frame (ret x)
184                        (VM a x f c (push ret (push f (push c s)))))
185                 (argument (x)
186                           (VM a x f c (push a s)))
187                 (apply ()
188                        (VM a (closure-body a) s a s))
189                 (return (n)
190                         (let ((s (- s n)))
191                           (VM a (index s 0) (index s 1) (index s 2) (- s 3)))))))
192
193(define continuation
194  (lambda (s)
195    (closure
196     (list 'refer 0 0 (list 'nuate (save-stack s) '(return 0)))
197     '())))
198
199(define closure
200  (lambda (body n s)
201    (let ((v (make-vector (+ n 1))))
202      (vector-set! v 0 body)
203      (recur f ((i 0))
204             (unless (= i n)
205               (vector-set! v (+ i 1) (index s i))
206               (f (+ i 1))))
207      v)))
208
209(define closure-body
210  (lambda (c)
211    (vector-ref c 0)))
212
213(define index-closure
214  (lambda (c n)
215    (vector-ref c (+ n 1))))
216
217(define save-stack
218  (lambda (s)
219    (let ((v (make-vector s)))
220      (recur copy ((i 0))
221             (unless (= i s)
222               (vector-set! v i (vector-ref stack i))
223               (copy (+ i 1))))
224      v)))
225
226(define restore-stack
227  (lambda (v)
228    (let ((s (vector-length v)))
229      (recur copy ((i 0))
230             (unless (= i s)
231               (vector-set! stack i (vector-ref v i))
232               (copy (+ i 1))))
233      s)))
234
235(define lookup
236  (lambda (n m e)
237    (recur nxtrib ((e e) (rib n))
238           (if (= rib 0)
239               (recur nxtelt ((r (car e)) (elt m))
240                      (if (= elt 0)
241                          r
242                        (nxtelt (cdr r) (- elt 1))))
243             (nxtrib (cdr e) (- rib 1))))))
244
245(define find-link
246  (lambda (n e)
247    (if (= n 0)
248        e
249      (find-link (- n 1) (index e -1)))))
250
251
252(define evaluate
253  (lambda (x)
254    (let1 code (compile x '() '(halt))
255      (VM '() code 0 '() 0))))
256
Note: See TracBrowser for help on using the browser.