Commit | Line | Data |
---|---|---|
1c297a38 | 1 | ;;;; Copyright (C) 2009, 2010 Free Software Foundation, Inc. |
811d10f5 AW |
2 | ;;;; |
3 | ;;;; This library is free software; you can redistribute it and/or | |
4 | ;;;; modify it under the terms of the GNU Lesser General Public | |
5 | ;;;; License as published by the Free Software Foundation; either | |
53befeb7 | 6 | ;;;; version 3 of the License, or (at your option) any later version. |
811d10f5 AW |
7 | ;;;; |
8 | ;;;; This library is distributed in the hope that it will be useful, | |
9 | ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
11 | ;;;; Lesser General Public License for more details. | |
12 | ;;;; | |
13 | ;;;; You should have received a copy of the GNU Lesser General Public | |
14 | ;;;; License along with this library; if not, write to the Free Software | |
15 | ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
16 | ;;;; | |
17 | \f | |
18 | ||
19 | (define-module (language tree-il) | |
f4aa0f10 | 20 | #:use-module (srfi srfi-1) |
4dcd8499 | 21 | #:use-module (srfi srfi-11) |
811d10f5 AW |
22 | #:use-module (system base pmatch) |
23 | #:use-module (system base syntax) | |
9efc833d | 24 | #:export (tree-il-src |
811d10f5 | 25 | |
cf10678f | 26 | <void> void? make-void void-src |
81fd3152 | 27 | <const> const? make-const const-src const-exp |
cb28c085 AW |
28 | <primitive-ref> primitive-ref? make-primitive-ref primitive-ref-src primitive-ref-name |
29 | <lexical-ref> lexical-ref? make-lexical-ref lexical-ref-src lexical-ref-name lexical-ref-gensym | |
30 | <lexical-set> lexical-set? make-lexical-set lexical-set-src lexical-set-name lexical-set-gensym lexical-set-exp | |
31 | <module-ref> module-ref? make-module-ref module-ref-src module-ref-mod module-ref-name module-ref-public? | |
32 | <module-set> module-set? make-module-set module-set-src module-set-mod module-set-name module-set-public? module-set-exp | |
33 | <toplevel-ref> toplevel-ref? make-toplevel-ref toplevel-ref-src toplevel-ref-name | |
34 | <toplevel-set> toplevel-set? make-toplevel-set toplevel-set-src toplevel-set-name toplevel-set-exp | |
35 | <toplevel-define> toplevel-define? make-toplevel-define toplevel-define-src toplevel-define-name toplevel-define-exp | |
b6d93b11 | 36 | <conditional> conditional? make-conditional conditional-src conditional-test conditional-consequent conditional-alternate |
81fd3152 | 37 | <application> application? make-application application-src application-proc application-args |
cb28c085 | 38 | <sequence> sequence? make-sequence sequence-src sequence-exps |
8a4ca0ea AW |
39 | <lambda> lambda? make-lambda lambda-src lambda-meta lambda-body |
40 | <lambda-case> lambda-case? make-lambda-case lambda-case-src | |
b0c8c187 | 41 | lambda-case-req lambda-case-opt lambda-case-rest lambda-case-kw |
93f63467 | 42 | lambda-case-inits lambda-case-gensyms |
3a88cb3b | 43 | lambda-case-body lambda-case-alternate |
93f63467 AW |
44 | <let> let? make-let let-src let-names let-gensyms let-vals let-body |
45 | <letrec> letrec? make-letrec letrec-src letrec-names letrec-gensyms letrec-vals letrec-body | |
46 | <fix> fix? make-fix fix-src fix-names fix-gensyms fix-vals fix-body | |
8a4ca0ea | 47 | <let-values> let-values? make-let-values let-values-src let-values-exp let-values-body |
8da6ab34 | 48 | <dynwind> dynwind? make-dynwind dynwind-src dynwind-winder dynwind-body dynwind-unwinder |
d7c53a86 | 49 | <dynlet> dynlet? make-dynlet dynlet-src dynlet-fluids dynlet-vals dynlet-body |
706a705e AW |
50 | <dynref> dynref? make-dynref dynref-src dynref-fluid |
51 | <dynset> dynset? make-dynset dynset-src dynset-fluid dynset-exp | |
07a0c7d5 | 52 | <prompt> prompt? make-prompt prompt-src prompt-tag prompt-body prompt-handler |
2d026f04 | 53 | <abort> abort? make-abort abort-src abort-tag abort-args abort-tail |
f4aa0f10 | 54 | |
9efc833d AW |
55 | parse-tree-il |
56 | unparse-tree-il | |
cb28c085 AW |
57 | tree-il->scheme |
58 | ||
f4aa0f10 | 59 | tree-il-fold |
4dcd8499 | 60 | make-tree-il-folder |
cb28c085 AW |
61 | post-order! |
62 | pre-order!)) | |
811d10f5 | 63 | |
4ffa8275 AW |
64 | (define (print-tree-il exp port) |
65 | (format port "#<tree-il ~a>" (unparse-tree-il exp))) | |
66 | ||
f7b61b39 AW |
67 | (define-syntax borrow-core-vtables |
68 | (lambda (x) | |
69 | (syntax-case x () | |
70 | ((_) | |
71 | (let lp ((n 0) (out '())) | |
72 | (if (< n (vector-length %expanded-vtables)) | |
73 | (lp (1+ n) | |
74 | (let* ((vtable (vector-ref %expanded-vtables n)) | |
75 | (stem (struct-ref vtable (+ vtable-offset-user 0))) | |
76 | (fields (struct-ref vtable (+ vtable-offset-user 2))) | |
77 | (sfields (map | |
78 | (lambda (f) (datum->syntax x f)) | |
79 | fields)) | |
80 | (type (datum->syntax x (symbol-append '< stem '>))) | |
81 | (ctor (datum->syntax x (symbol-append 'make- stem))) | |
82 | (pred (datum->syntax x (symbol-append stem '?)))) | |
83 | (let lp ((n 0) (fields fields) | |
84 | (out (cons* | |
85 | #`(define (#,ctor #,@sfields) | |
86 | (make-struct #,type 0 #,@sfields)) | |
87 | #`(define (#,pred x) | |
88 | (and (struct? x) | |
89 | (eq? (struct-vtable x) #,type))) | |
4ffa8275 AW |
90 | #`(struct-set! #,type vtable-index-printer |
91 | print-tree-il) | |
f7b61b39 AW |
92 | #`(define #,type |
93 | (vector-ref %expanded-vtables #,n)) | |
94 | out))) | |
95 | (if (null? fields) | |
96 | out | |
97 | (lp (1+ n) | |
98 | (cdr fields) | |
99 | (let ((acc (datum->syntax | |
100 | x (symbol-append stem '- (car fields))))) | |
101 | (cons #`(define #,acc | |
102 | (make-procedure-with-setter | |
103 | (lambda (x) (struct-ref x #,n)) | |
104 | (lambda (x v) (struct-set! x #,n v)))) | |
105 | out))))))) | |
106 | #`(begin #,@(reverse out)))))))) | |
107 | ||
108 | (borrow-core-vtables) | |
109 | ||
110 | ;; (<void>) | |
111 | ;; (<const> exp) | |
112 | ;; (<primitive-ref> name) | |
113 | ;; (<lexical-ref> name gensym) | |
114 | ;; (<lexical-set> name gensym exp) | |
115 | ;; (<module-ref> mod name public?) | |
116 | ;; (<module-set> mod name public? exp) | |
117 | ;; (<toplevel-ref> name) | |
118 | ;; (<toplevel-set> name exp) | |
119 | ;; (<toplevel-define> name exp) | |
120 | ;; (<conditional> test consequent alternate) | |
121 | ;; (<application> proc args) | |
122 | ;; (<sequence> exps) | |
123 | ;; (<lambda> meta body) | |
124 | ;; (<lambda-case> req opt rest kw inits gensyms body alternate) | |
125 | ;; (<let> names gensyms vals body) | |
126 | ;; (<letrec> names gensyms vals body) | |
127 | ;; (<dynlet> fluids vals body) | |
128 | ||
4ffa8275 | 129 | (define-type (<tree-il> #:common-slots (src) #:printer print-tree-il) |
93f63467 | 130 | (<fix> names gensyms vals body) |
1c297a38 | 131 | (<let-values> exp body) |
8da6ab34 | 132 | (<dynwind> winder body unwinder) |
706a705e AW |
133 | (<dynref> fluid) |
134 | (<dynset> fluid exp) | |
07a0c7d5 | 135 | (<prompt> tag body handler) |
2d026f04 | 136 | (<abort> tag args tail)) |
811d10f5 | 137 | |
811d10f5 AW |
138 | \f |
139 | ||
811d10f5 AW |
140 | (define (location x) |
141 | (and (pair? x) | |
142 | (let ((props (source-properties x))) | |
81fd3152 | 143 | (and (pair? props) props)))) |
811d10f5 | 144 | |
ce09ee19 | 145 | (define (parse-tree-il exp) |
811d10f5 | 146 | (let ((loc (location exp)) |
ce09ee19 | 147 | (retrans (lambda (x) (parse-tree-il x)))) |
811d10f5 | 148 | (pmatch exp |
cf10678f AW |
149 | ((void) |
150 | (make-void loc)) | |
151 | ||
ce09ee19 AW |
152 | ((apply ,proc . ,args) |
153 | (make-application loc (retrans proc) (map retrans args))) | |
811d10f5 | 154 | |
b6d93b11 AW |
155 | ((if ,test ,consequent ,alternate) |
156 | (make-conditional loc (retrans test) (retrans consequent) (retrans alternate))) | |
811d10f5 AW |
157 | |
158 | ((primitive ,name) (guard (symbol? name)) | |
159 | (make-primitive-ref loc name)) | |
160 | ||
161 | ((lexical ,name) (guard (symbol? name)) | |
162 | (make-lexical-ref loc name name)) | |
163 | ||
164 | ((lexical ,name ,sym) (guard (symbol? name) (symbol? sym)) | |
165 | (make-lexical-ref loc name sym)) | |
166 | ||
5c27902e AW |
167 | ((set! (lexical ,name) ,exp) (guard (symbol? name)) |
168 | (make-lexical-set loc name name (retrans exp))) | |
169 | ||
811d10f5 AW |
170 | ((set! (lexical ,name ,sym) ,exp) (guard (symbol? name) (symbol? sym)) |
171 | (make-lexical-set loc name sym (retrans exp))) | |
172 | ||
173 | ((@ ,mod ,name) (guard (and-map symbol? mod) (symbol? name)) | |
174 | (make-module-ref loc mod name #t)) | |
175 | ||
176 | ((set! (@ ,mod ,name) ,exp) (guard (and-map symbol? mod) (symbol? name)) | |
177 | (make-module-set loc mod name #t (retrans exp))) | |
178 | ||
179 | ((@@ ,mod ,name) (guard (and-map symbol? mod) (symbol? name)) | |
180 | (make-module-ref loc mod name #f)) | |
181 | ||
ce09ee19 | 182 | ((set! (@@ ,mod ,name) ,exp) (guard (and-map symbol? mod) (symbol? name)) |
811d10f5 AW |
183 | (make-module-set loc mod name #f (retrans exp))) |
184 | ||
185 | ((toplevel ,name) (guard (symbol? name)) | |
186 | (make-toplevel-ref loc name)) | |
187 | ||
ce09ee19 | 188 | ((set! (toplevel ,name) ,exp) (guard (symbol? name)) |
811d10f5 AW |
189 | (make-toplevel-set loc name (retrans exp))) |
190 | ||
ce09ee19 | 191 | ((define ,name ,exp) (guard (symbol? name)) |
811d10f5 AW |
192 | (make-toplevel-define loc name (retrans exp))) |
193 | ||
8a4ca0ea AW |
194 | ((lambda ,meta ,body) |
195 | (make-lambda loc meta (retrans body))) | |
811d10f5 | 196 | |
93f63467 | 197 | ((lambda-case ((,req ,opt ,rest ,kw ,inits ,gensyms) ,body) ,alternate) |
b0c8c187 | 198 | (make-lambda-case loc req opt rest kw |
93f63467 | 199 | (map retrans inits) gensyms |
8a4ca0ea | 200 | (retrans body) |
3a88cb3b | 201 | (and=> alternate retrans))) |
811d10f5 | 202 | |
93f63467 | 203 | ((lambda-case ((,req ,opt ,rest ,kw ,inits ,gensyms) ,body)) |
b0c8c187 | 204 | (make-lambda-case loc req opt rest kw |
93f63467 | 205 | (map retrans inits) gensyms |
7e01997e AW |
206 | (retrans body) |
207 | #f)) | |
208 | ||
811d10f5 AW |
209 | ((const ,exp) |
210 | (make-const loc exp)) | |
211 | ||
212 | ((begin . ,exps) | |
213 | (make-sequence loc (map retrans exps))) | |
214 | ||
93f63467 AW |
215 | ((let ,names ,gensyms ,vals ,body) |
216 | (make-let loc names gensyms (map retrans vals) (retrans body))) | |
f4aa8d53 | 217 | |
93f63467 AW |
218 | ((letrec ,names ,gensyms ,vals ,body) |
219 | (make-letrec loc names gensyms (map retrans vals) (retrans body))) | |
811d10f5 | 220 | |
93f63467 AW |
221 | ((fix ,names ,gensyms ,vals ,body) |
222 | (make-fix loc names gensyms (map retrans vals) (retrans body))) | |
c21c89b1 | 223 | |
8a4ca0ea AW |
224 | ((let-values ,exp ,body) |
225 | (make-let-values loc (retrans exp) (retrans body))) | |
811d10f5 | 226 | |
8da6ab34 AW |
227 | ((dynwind ,winder ,body ,unwinder) |
228 | (make-dynwind loc (retrans winder) (retrans body) (retrans unwinder))) | |
1c297a38 | 229 | |
d7c53a86 AW |
230 | ((dynlet ,fluids ,vals ,body) |
231 | (make-dynlet loc (map retrans fluids) (map retrans vals) (retrans body))) | |
232 | ||
706a705e AW |
233 | ((dynref ,fluid) |
234 | (make-dynref loc (retrans fluid))) | |
235 | ||
236 | ((dynset ,fluid ,exp) | |
237 | (make-dynset loc (retrans fluid) (retrans exp))) | |
238 | ||
07a0c7d5 AW |
239 | ((prompt ,tag ,body ,handler) |
240 | (make-prompt loc (retrans tag) (retrans body) (retrans handler))) | |
1c297a38 | 241 | |
2d026f04 AW |
242 | ((abort ,tag ,args ,tail) |
243 | (make-abort loc (retrans tag) (map retrans args) (retrans tail))) | |
1c297a38 | 244 | |
811d10f5 AW |
245 | (else |
246 | (error "unrecognized tree-il" exp))))) | |
247 | ||
248 | (define (unparse-tree-il tree-il) | |
249 | (record-case tree-il | |
cf10678f AW |
250 | ((<void>) |
251 | '(void)) | |
252 | ||
811d10f5 | 253 | ((<application> proc args) |
ce09ee19 | 254 | `(apply ,(unparse-tree-il proc) ,@(map unparse-tree-il args))) |
811d10f5 | 255 | |
b6d93b11 AW |
256 | ((<conditional> test consequent alternate) |
257 | `(if ,(unparse-tree-il test) ,(unparse-tree-il consequent) ,(unparse-tree-il alternate))) | |
811d10f5 AW |
258 | |
259 | ((<primitive-ref> name) | |
260 | `(primitive ,name)) | |
261 | ||
262 | ((<lexical-ref> name gensym) | |
263 | `(lexical ,name ,gensym)) | |
264 | ||
265 | ((<lexical-set> name gensym exp) | |
266 | `(set! (lexical ,name ,gensym) ,(unparse-tree-il exp))) | |
267 | ||
268 | ((<module-ref> mod name public?) | |
269 | `(,(if public? '@ '@@) ,mod ,name)) | |
270 | ||
271 | ((<module-set> mod name public? exp) | |
272 | `(set! (,(if public? '@ '@@) ,mod ,name) ,(unparse-tree-il exp))) | |
273 | ||
274 | ((<toplevel-ref> name) | |
275 | `(toplevel ,name)) | |
276 | ||
277 | ((<toplevel-set> name exp) | |
278 | `(set! (toplevel ,name) ,(unparse-tree-il exp))) | |
279 | ||
280 | ((<toplevel-define> name exp) | |
281 | `(define ,name ,(unparse-tree-il exp))) | |
282 | ||
8a4ca0ea AW |
283 | ((<lambda> meta body) |
284 | `(lambda ,meta ,(unparse-tree-il body))) | |
285 | ||
93f63467 AW |
286 | ((<lambda-case> req opt rest kw inits gensyms body alternate) |
287 | `(lambda-case ((,req ,opt ,rest ,kw ,(map unparse-tree-il inits) ,gensyms) | |
8a4ca0ea | 288 | ,(unparse-tree-il body)) |
3a88cb3b | 289 | . ,(if alternate (list (unparse-tree-il alternate)) '()))) |
811d10f5 AW |
290 | |
291 | ((<const> exp) | |
292 | `(const ,exp)) | |
293 | ||
294 | ((<sequence> exps) | |
295 | `(begin ,@(map unparse-tree-il exps))) | |
296 | ||
93f63467 AW |
297 | ((<let> names gensyms vals body) |
298 | `(let ,names ,gensyms ,(map unparse-tree-il vals) ,(unparse-tree-il body))) | |
811d10f5 | 299 | |
93f63467 AW |
300 | ((<letrec> names gensyms vals body) |
301 | `(letrec ,names ,gensyms ,(map unparse-tree-il vals) ,(unparse-tree-il body))) | |
f4aa8d53 | 302 | |
93f63467 AW |
303 | ((<fix> names gensyms vals body) |
304 | `(fix ,names ,gensyms ,(map unparse-tree-il vals) ,(unparse-tree-il body))) | |
c21c89b1 | 305 | |
8a4ca0ea | 306 | ((<let-values> exp body) |
1c297a38 AW |
307 | `(let-values ,(unparse-tree-il exp) ,(unparse-tree-il body))) |
308 | ||
8da6ab34 AW |
309 | ((<dynwind> body winder unwinder) |
310 | `(dynwind ,(unparse-tree-il body) | |
1c297a38 AW |
311 | ,(unparse-tree-il winder) ,(unparse-tree-il unwinder))) |
312 | ||
d7c53a86 AW |
313 | ((<dynlet> fluids vals body) |
314 | `(dynlet ,(map unparse-tree-il fluids) ,(map unparse-tree-il vals) | |
315 | ,(unparse-tree-il body))) | |
316 | ||
706a705e AW |
317 | ((<dynref> fluid) |
318 | `(dynref ,(unparse-tree-il fluid))) | |
319 | ||
320 | ((<dynset> fluid exp) | |
321 | `(dynref ,(unparse-tree-il fluid) ,(unparse-tree-il exp))) | |
322 | ||
07a0c7d5 | 323 | ((<prompt> tag body handler) |
2bcf97a6 | 324 | `(prompt ,(unparse-tree-il tag) ,(unparse-tree-il body) ,(unparse-tree-il handler))) |
1c297a38 | 325 | |
2d026f04 AW |
326 | ((<abort> tag args tail) |
327 | `(abort ,(unparse-tree-il tag) ,(map unparse-tree-il args) | |
328 | ,(unparse-tree-il tail))))) | |
811d10f5 AW |
329 | |
330 | (define (tree-il->scheme e) | |
f4aa8d53 AW |
331 | (record-case e |
332 | ((<void>) | |
333 | '(if #f #f)) | |
334 | ||
335 | ((<application> proc args) | |
336 | `(,(tree-il->scheme proc) ,@(map tree-il->scheme args))) | |
337 | ||
b6d93b11 AW |
338 | ((<conditional> test consequent alternate) |
339 | (if (void? alternate) | |
340 | `(if ,(tree-il->scheme test) ,(tree-il->scheme consequent)) | |
341 | `(if ,(tree-il->scheme test) ,(tree-il->scheme consequent) ,(tree-il->scheme alternate)))) | |
f4aa8d53 AW |
342 | |
343 | ((<primitive-ref> name) | |
344 | name) | |
345 | ||
e5f5113c | 346 | ((<lexical-ref> gensym) |
f4aa8d53 AW |
347 | gensym) |
348 | ||
e5f5113c | 349 | ((<lexical-set> gensym exp) |
f4aa8d53 AW |
350 | `(set! ,gensym ,(tree-il->scheme exp))) |
351 | ||
352 | ((<module-ref> mod name public?) | |
353 | `(,(if public? '@ '@@) ,mod ,name)) | |
354 | ||
355 | ((<module-set> mod name public? exp) | |
356 | `(set! (,(if public? '@ '@@) ,mod ,name) ,(tree-il->scheme exp))) | |
357 | ||
358 | ((<toplevel-ref> name) | |
359 | name) | |
360 | ||
361 | ((<toplevel-set> name exp) | |
362 | `(set! ,name ,(tree-il->scheme exp))) | |
363 | ||
364 | ((<toplevel-define> name exp) | |
365 | `(define ,name ,(tree-il->scheme exp))) | |
366 | ||
8a4ca0ea AW |
367 | ((<lambda> meta body) |
368 | ;; fixme: put in docstring | |
cc63545b | 369 | (tree-il->scheme body)) |
8a4ca0ea | 370 | |
93f63467 | 371 | ((<lambda-case> req opt rest kw inits gensyms body alternate) |
cc63545b AW |
372 | (cond |
373 | ((and (not opt) (not kw) (not alternate)) | |
374 | `(lambda ,(if rest (apply cons* gensyms) gensyms) | |
375 | ,(tree-il->scheme body))) | |
376 | ((and (not opt) (not kw)) | |
377 | (let ((alt-expansion (tree-il->scheme alternate)) | |
378 | (formals (if rest (apply cons* gensyms) gensyms))) | |
379 | (case (car alt-expansion) | |
380 | ((lambda) | |
381 | `(case-lambda (,formals ,(tree-il->scheme body)) | |
382 | ,@(cdr alt-expansion))) | |
383 | ((lambda*) | |
384 | `(case-lambda* (,formals ,(tree-il->scheme body)) | |
385 | ,(cdr alt-expansion))) | |
386 | ((case-lambda) | |
387 | `(case-lambda (,formals ,(tree-il->scheme body)) | |
388 | ,@(cdr alt-expansion))) | |
389 | ((case-lambda*) | |
390 | `(case-lambda* (,formals ,(tree-il->scheme body)) | |
391 | ,@(cdr alt-expansion)))))) | |
392 | (else | |
393 | (let* ((alt-expansion (and alternate (tree-il->scheme alternate))) | |
394 | (nreq (length req)) | |
395 | (nopt (if opt (length opt) 0)) | |
396 | (restargs (if rest (list-ref gensyms (+ nreq nopt)) '())) | |
397 | (reqargs (list-head gensyms nreq)) | |
398 | (optargs (if opt | |
399 | `(#:optional | |
400 | ,@(map list | |
401 | (list-head (list-tail gensyms nreq) nopt) | |
402 | (map tree-il->scheme | |
403 | (list-head inits nopt)))) | |
404 | '())) | |
405 | (kwargs (if kw | |
406 | `(#:key | |
407 | ,@(map list | |
408 | (map caddr (cdr kw)) | |
409 | (map tree-il->scheme | |
410 | (list-tail inits nopt)) | |
411 | (map car (cdr kw))) | |
412 | ,@(if (car kw) | |
413 | '(#:allow-other-keys) | |
414 | '())) | |
415 | '())) | |
416 | (formals `(,@reqargs ,@optargs ,@kwargs . ,restargs))) | |
417 | (if (not alt-expansion) | |
418 | `(lambda* ,formals ,(tree-il->scheme body)) | |
419 | (case (car alt-expansion) | |
420 | ((lambda lambda*) | |
421 | `(case-lambda* (,formals ,(tree-il->scheme body)) | |
422 | ,(cdr alt-expansion))) | |
423 | ((case-lambda case-lambda*) | |
424 | `(case-lambda* (,formals ,(tree-il->scheme body)) | |
425 | ,@(cdr alt-expansion))))))))) | |
426 | ||
f4aa8d53 AW |
427 | ((<const> exp) |
428 | (if (and (self-evaluating? exp) (not (vector? exp))) | |
429 | exp | |
430 | (list 'quote exp))) | |
431 | ||
432 | ((<sequence> exps) | |
433 | `(begin ,@(map tree-il->scheme exps))) | |
434 | ||
93f63467 AW |
435 | ((<let> gensyms vals body) |
436 | `(let ,(map list gensyms (map tree-il->scheme vals)) ,(tree-il->scheme body))) | |
f4aa8d53 | 437 | |
93f63467 AW |
438 | ((<letrec> gensyms vals body) |
439 | `(letrec ,(map list gensyms (map tree-il->scheme vals)) ,(tree-il->scheme body))) | |
f4aa8d53 | 440 | |
93f63467 | 441 | ((<fix> gensyms vals body) |
c21c89b1 | 442 | ;; not a typo, we really do translate back to letrec |
93f63467 | 443 | `(letrec ,(map list gensyms (map tree-il->scheme vals)) ,(tree-il->scheme body))) |
c21c89b1 | 444 | |
1e2a8edb | 445 | ((<let-values> exp body) |
f4aa8d53 | 446 | `(call-with-values (lambda () ,(tree-il->scheme exp)) |
1c297a38 AW |
447 | ,(tree-il->scheme (make-lambda #f '() body)))) |
448 | ||
8da6ab34 | 449 | ((<dynwind> body winder unwinder) |
d69531e2 AW |
450 | `(dynamic-wind ,(tree-il->scheme winder) |
451 | (lambda () ,(tree-il->scheme body)) | |
452 | ,(tree-il->scheme unwinder))) | |
1c297a38 | 453 | |
d7c53a86 AW |
454 | ((<dynlet> fluids vals body) |
455 | `(with-fluids ,(map list | |
456 | (map tree-il->scheme fluids) | |
457 | (map tree-il->scheme vals)) | |
67a78ddd | 458 | ,(tree-il->scheme body))) |
d7c53a86 | 459 | |
706a705e AW |
460 | ((<dynref> fluid) |
461 | `(fluid-ref ,(tree-il->scheme fluid))) | |
462 | ||
463 | ((<dynset> fluid exp) | |
464 | `(fluid-set! ,(tree-il->scheme fluid) ,(tree-il->scheme exp))) | |
465 | ||
07a0c7d5 | 466 | ((<prompt> tag body handler) |
1c297a38 AW |
467 | `((@ (ice-9 control) prompt) |
468 | ,(tree-il->scheme tag) (lambda () ,(tree-il->scheme body)) | |
07a0c7d5 | 469 | ,(tree-il->scheme handler))) |
1c297a38 AW |
470 | |
471 | ||
2d026f04 AW |
472 | ((<abort> tag args tail) |
473 | `(apply abort ,(tree-il->scheme tag) ,@(map tree-il->scheme args) | |
474 | ,(tree-il->scheme tail))))) | |
cb28c085 | 475 | |
f4aa0f10 LC |
476 | \f |
477 | (define (tree-il-fold leaf down up seed tree) | |
478 | "Traverse TREE, calling LEAF on each leaf encountered, DOWN upon descent | |
479 | into a sub-tree, and UP when leaving a sub-tree. Each of these procedures is | |
480 | invoked as `(PROC TREE SEED)', where TREE is the sub-tree or leaf considered | |
481 | and SEED is the current result, intially seeded with SEED. | |
482 | ||
483 | This is an implementation of `foldts' as described by Andy Wingo in | |
484 | ``Applications of fold to XML transformation''." | |
485 | (let loop ((tree tree) | |
486 | (result seed)) | |
487 | (if (or (null? tree) (pair? tree)) | |
488 | (fold loop result tree) | |
489 | (record-case tree | |
490 | ((<lexical-set> exp) | |
491 | (up tree (loop exp (down tree result)))) | |
492 | ((<module-set> exp) | |
493 | (up tree (loop exp (down tree result)))) | |
494 | ((<toplevel-set> exp) | |
495 | (up tree (loop exp (down tree result)))) | |
496 | ((<toplevel-define> exp) | |
497 | (up tree (loop exp (down tree result)))) | |
b6d93b11 AW |
498 | ((<conditional> test consequent alternate) |
499 | (up tree (loop alternate | |
500 | (loop consequent | |
f4aa0f10 LC |
501 | (loop test (down tree result)))))) |
502 | ((<application> proc args) | |
503 | (up tree (loop (cons proc args) (down tree result)))) | |
504 | ((<sequence> exps) | |
505 | (up tree (loop exps (down tree result)))) | |
506 | ((<lambda> body) | |
507 | (up tree (loop body (down tree result)))) | |
3a88cb3b AW |
508 | ((<lambda-case> inits body alternate) |
509 | (up tree (if alternate | |
510 | (loop alternate | |
1e2a8edb AW |
511 | (loop body (loop inits (down tree result)))) |
512 | (loop body (loop inits (down tree result)))))) | |
f4aa0f10 LC |
513 | ((<let> vals body) |
514 | (up tree (loop body | |
515 | (loop vals | |
516 | (down tree result))))) | |
517 | ((<letrec> vals body) | |
518 | (up tree (loop body | |
519 | (loop vals | |
520 | (down tree result))))) | |
c21c89b1 AW |
521 | ((<fix> vals body) |
522 | (up tree (loop body | |
523 | (loop vals | |
524 | (down tree result))))) | |
4dcd8499 AW |
525 | ((<let-values> exp body) |
526 | (up tree (loop body (loop exp (down tree result))))) | |
8da6ab34 | 527 | ((<dynwind> body winder unwinder) |
1c297a38 AW |
528 | (up tree (loop unwinder |
529 | (loop winder | |
530 | (loop body (down tree result)))))) | |
d7c53a86 AW |
531 | ((<dynlet> fluids vals body) |
532 | (up tree (loop body | |
533 | (loop vals | |
534 | (loop fluids (down tree result)))))) | |
706a705e AW |
535 | ((<dynref> fluid) |
536 | (up tree (loop fluid (down tree result)))) | |
537 | ((<dynset> fluid exp) | |
538 | (up tree (loop exp (loop fluid (down tree result))))) | |
07a0c7d5 AW |
539 | ((<prompt> tag body handler) |
540 | (up tree | |
541 | (loop tag (loop body (loop handler | |
542 | (down tree result)))))) | |
2d026f04 AW |
543 | ((<abort> tag args tail) |
544 | (up tree (loop tail (loop args (loop tag (down tree result)))))) | |
f4aa0f10 LC |
545 | (else |
546 | (leaf tree result)))))) | |
547 | ||
4dcd8499 AW |
548 | |
549 | (define-syntax make-tree-il-folder | |
550 | (syntax-rules () | |
551 | ((_ seed ...) | |
80af1168 | 552 | (lambda (tree down up seed ...) |
4dcd8499 AW |
553 | (define (fold-values proc exps seed ...) |
554 | (if (null? exps) | |
555 | (values seed ...) | |
556 | (let-values (((seed ...) (proc (car exps) seed ...))) | |
557 | (fold-values proc (cdr exps) seed ...)))) | |
558 | (let foldts ((tree tree) (seed seed) ...) | |
80af1168 AW |
559 | (let*-values |
560 | (((seed ...) (down tree seed ...)) | |
561 | ((seed ...) | |
562 | (record-case tree | |
563 | ((<lexical-set> exp) | |
564 | (foldts exp seed ...)) | |
565 | ((<module-set> exp) | |
566 | (foldts exp seed ...)) | |
567 | ((<toplevel-set> exp) | |
568 | (foldts exp seed ...)) | |
569 | ((<toplevel-define> exp) | |
570 | (foldts exp seed ...)) | |
b6d93b11 | 571 | ((<conditional> test consequent alternate) |
80af1168 | 572 | (let*-values (((seed ...) (foldts test seed ...)) |
b6d93b11 AW |
573 | ((seed ...) (foldts consequent seed ...))) |
574 | (foldts alternate seed ...))) | |
80af1168 AW |
575 | ((<application> proc args) |
576 | (let-values (((seed ...) (foldts proc seed ...))) | |
577 | (fold-values foldts args seed ...))) | |
578 | ((<sequence> exps) | |
579 | (fold-values foldts exps seed ...)) | |
580 | ((<lambda> body) | |
581 | (foldts body seed ...)) | |
3a88cb3b | 582 | ((<lambda-case> inits body alternate) |
b0c8c187 | 583 | (let-values (((seed ...) (fold-values foldts inits seed ...))) |
3a88cb3b | 584 | (if alternate |
1e2a8edb | 585 | (let-values (((seed ...) (foldts body seed ...))) |
3a88cb3b | 586 | (foldts alternate seed ...)) |
1e2a8edb | 587 | (foldts body seed ...)))) |
80af1168 AW |
588 | ((<let> vals body) |
589 | (let*-values (((seed ...) (fold-values foldts vals seed ...))) | |
590 | (foldts body seed ...))) | |
591 | ((<letrec> vals body) | |
592 | (let*-values (((seed ...) (fold-values foldts vals seed ...))) | |
593 | (foldts body seed ...))) | |
594 | ((<fix> vals body) | |
595 | (let*-values (((seed ...) (fold-values foldts vals seed ...))) | |
596 | (foldts body seed ...))) | |
597 | ((<let-values> exp body) | |
598 | (let*-values (((seed ...) (foldts exp seed ...))) | |
599 | (foldts body seed ...))) | |
8da6ab34 | 600 | ((<dynwind> body winder unwinder) |
1c297a38 AW |
601 | (let*-values (((seed ...) (foldts body seed ...)) |
602 | ((seed ...) (foldts winder seed ...))) | |
603 | (foldts unwinder seed ...))) | |
d7c53a86 AW |
604 | ((<dynlet> fluids vals body) |
605 | (let*-values (((seed ...) (fold-values foldts fluids seed ...)) | |
606 | ((seed ...) (fold-values foldts vals seed ...))) | |
607 | (foldts body seed ...))) | |
706a705e AW |
608 | ((<dynref> fluid) |
609 | (foldts fluid seed ...)) | |
610 | ((<dynset> fluid exp) | |
611 | (let*-values (((seed ...) (foldts fluid seed ...))) | |
612 | (foldts exp seed ...))) | |
07a0c7d5 | 613 | ((<prompt> tag body handler) |
1c297a38 | 614 | (let*-values (((seed ...) (foldts tag seed ...)) |
07a0c7d5 AW |
615 | ((seed ...) (foldts body seed ...))) |
616 | (foldts handler seed ...))) | |
2d026f04 AW |
617 | ((<abort> tag args tail) |
618 | (let*-values (((seed ...) (foldts tag seed ...)) | |
619 | ((seed ...) (fold-values foldts args seed ...))) | |
620 | (foldts tail seed ...))) | |
80af1168 AW |
621 | (else |
622 | (values seed ...))))) | |
623 | (up tree seed ...))))))) | |
4dcd8499 | 624 | |
cb28c085 AW |
625 | (define (post-order! f x) |
626 | (let lp ((x x)) | |
627 | (record-case x | |
628 | ((<application> proc args) | |
629 | (set! (application-proc x) (lp proc)) | |
f4aa8d53 | 630 | (set! (application-args x) (map lp args))) |
cb28c085 | 631 | |
b6d93b11 | 632 | ((<conditional> test consequent alternate) |
cb28c085 | 633 | (set! (conditional-test x) (lp test)) |
b6d93b11 AW |
634 | (set! (conditional-consequent x) (lp consequent)) |
635 | (set! (conditional-alternate x) (lp alternate))) | |
f4aa8d53 | 636 | |
cb28c085 | 637 | ((<lexical-set> name gensym exp) |
f4aa8d53 AW |
638 | (set! (lexical-set-exp x) (lp exp))) |
639 | ||
cb28c085 | 640 | ((<module-set> mod name public? exp) |
f4aa8d53 AW |
641 | (set! (module-set-exp x) (lp exp))) |
642 | ||
cb28c085 | 643 | ((<toplevel-set> name exp) |
f4aa8d53 AW |
644 | (set! (toplevel-set-exp x) (lp exp))) |
645 | ||
cb28c085 | 646 | ((<toplevel-define> name exp) |
f4aa8d53 AW |
647 | (set! (toplevel-define-exp x) (lp exp))) |
648 | ||
8a4ca0ea | 649 | ((<lambda> body) |
f4aa8d53 AW |
650 | (set! (lambda-body x) (lp body))) |
651 | ||
3a88cb3b | 652 | ((<lambda-case> inits body alternate) |
b0c8c187 | 653 | (set! inits (map lp inits)) |
8a4ca0ea | 654 | (set! (lambda-case-body x) (lp body)) |
3a88cb3b AW |
655 | (if alternate |
656 | (set! (lambda-case-alternate x) (lp alternate)))) | |
8a4ca0ea | 657 | |
cb28c085 | 658 | ((<sequence> exps) |
f4aa8d53 AW |
659 | (set! (sequence-exps x) (map lp exps))) |
660 | ||
93f63467 | 661 | ((<let> gensyms vals body) |
cb28c085 | 662 | (set! (let-vals x) (map lp vals)) |
f4aa8d53 AW |
663 | (set! (let-body x) (lp body))) |
664 | ||
93f63467 | 665 | ((<letrec> gensyms vals body) |
cb28c085 | 666 | (set! (letrec-vals x) (map lp vals)) |
f4aa8d53 AW |
667 | (set! (letrec-body x) (lp body))) |
668 | ||
93f63467 | 669 | ((<fix> gensyms vals body) |
c21c89b1 AW |
670 | (set! (fix-vals x) (map lp vals)) |
671 | (set! (fix-body x) (lp body))) | |
672 | ||
8a4ca0ea | 673 | ((<let-values> exp body) |
f4aa8d53 AW |
674 | (set! (let-values-exp x) (lp exp)) |
675 | (set! (let-values-body x) (lp body))) | |
676 | ||
8da6ab34 AW |
677 | ((<dynwind> body winder unwinder) |
678 | (set! (dynwind-body x) (lp body)) | |
679 | (set! (dynwind-winder x) (lp winder)) | |
680 | (set! (dynwind-unwinder x) (lp unwinder))) | |
1c297a38 | 681 | |
d7c53a86 AW |
682 | ((<dynlet> fluids vals body) |
683 | (set! (dynlet-fluids x) (map lp fluids)) | |
684 | (set! (dynlet-vals x) (map lp vals)) | |
685 | (set! (dynlet-body x) (lp body))) | |
686 | ||
706a705e AW |
687 | ((<dynref> fluid) |
688 | (set! (dynref-fluid x) (lp fluid))) | |
689 | ||
690 | ((<dynset> fluid exp) | |
691 | (set! (dynset-fluid x) (lp fluid)) | |
692 | (set! (dynset-exp x) (lp exp))) | |
693 | ||
07a0c7d5 | 694 | ((<prompt> tag body handler) |
1c297a38 AW |
695 | (set! (prompt-tag x) (lp tag)) |
696 | (set! (prompt-body x) (lp body)) | |
07a0c7d5 | 697 | (set! (prompt-handler x) (lp handler))) |
1c297a38 | 698 | |
2d026f04 | 699 | ((<abort> tag args tail) |
6e84cb95 | 700 | (set! (abort-tag x) (lp tag)) |
2d026f04 AW |
701 | (set! (abort-args x) (map lp args)) |
702 | (set! (abort-tail x) (lp tail))) | |
1c297a38 | 703 | |
f4aa8d53 AW |
704 | (else #f)) |
705 | ||
706 | (or (f x) x))) | |
cb28c085 AW |
707 | |
708 | (define (pre-order! f x) | |
709 | (let lp ((x x)) | |
710 | (let ((x (or (f x) x))) | |
711 | (record-case x | |
712 | ((<application> proc args) | |
713 | (set! (application-proc x) (lp proc)) | |
714 | (set! (application-args x) (map lp args))) | |
715 | ||
b6d93b11 | 716 | ((<conditional> test consequent alternate) |
cb28c085 | 717 | (set! (conditional-test x) (lp test)) |
b6d93b11 AW |
718 | (set! (conditional-consequent x) (lp consequent)) |
719 | (set! (conditional-alternate x) (lp alternate))) | |
cb28c085 | 720 | |
e5f5113c | 721 | ((<lexical-set> exp) |
cb28c085 AW |
722 | (set! (lexical-set-exp x) (lp exp))) |
723 | ||
e5f5113c | 724 | ((<module-set> exp) |
cb28c085 AW |
725 | (set! (module-set-exp x) (lp exp))) |
726 | ||
e5f5113c | 727 | ((<toplevel-set> exp) |
cb28c085 AW |
728 | (set! (toplevel-set-exp x) (lp exp))) |
729 | ||
e5f5113c | 730 | ((<toplevel-define> exp) |
cb28c085 AW |
731 | (set! (toplevel-define-exp x) (lp exp))) |
732 | ||
e5f5113c | 733 | ((<lambda> body) |
cb28c085 AW |
734 | (set! (lambda-body x) (lp body))) |
735 | ||
3a88cb3b | 736 | ((<lambda-case> inits body alternate) |
b0c8c187 | 737 | (set! inits (map lp inits)) |
8a4ca0ea | 738 | (set! (lambda-case-body x) (lp body)) |
3a88cb3b | 739 | (if alternate (set! (lambda-case-alternate x) (lp alternate)))) |
8a4ca0ea | 740 | |
cb28c085 AW |
741 | ((<sequence> exps) |
742 | (set! (sequence-exps x) (map lp exps))) | |
743 | ||
e5f5113c | 744 | ((<let> vals body) |
cb28c085 | 745 | (set! (let-vals x) (map lp vals)) |
f4aa8d53 | 746 | (set! (let-body x) (lp body))) |
cb28c085 | 747 | |
e5f5113c | 748 | ((<letrec> vals body) |
cb28c085 | 749 | (set! (letrec-vals x) (map lp vals)) |
f4aa8d53 AW |
750 | (set! (letrec-body x) (lp body))) |
751 | ||
e5f5113c | 752 | ((<fix> vals body) |
c21c89b1 AW |
753 | (set! (fix-vals x) (map lp vals)) |
754 | (set! (fix-body x) (lp body))) | |
755 | ||
e5f5113c | 756 | ((<let-values> exp body) |
f4aa8d53 AW |
757 | (set! (let-values-exp x) (lp exp)) |
758 | (set! (let-values-body x) (lp body))) | |
cb28c085 | 759 | |
8da6ab34 AW |
760 | ((<dynwind> body winder unwinder) |
761 | (set! (dynwind-body x) (lp body)) | |
762 | (set! (dynwind-winder x) (lp winder)) | |
763 | (set! (dynwind-unwinder x) (lp unwinder))) | |
1c297a38 | 764 | |
d7c53a86 AW |
765 | ((<dynlet> fluids vals body) |
766 | (set! (dynlet-fluids x) (map lp fluids)) | |
767 | (set! (dynlet-vals x) (map lp vals)) | |
768 | (set! (dynlet-body x) (lp body))) | |
769 | ||
706a705e AW |
770 | ((<dynref> fluid) |
771 | (set! (dynref-fluid x) (lp fluid))) | |
772 | ||
773 | ((<dynset> fluid exp) | |
774 | (set! (dynset-fluid x) (lp fluid)) | |
775 | (set! (dynset-exp x) (lp exp))) | |
776 | ||
07a0c7d5 | 777 | ((<prompt> tag body handler) |
1c297a38 AW |
778 | (set! (prompt-tag x) (lp tag)) |
779 | (set! (prompt-body x) (lp body)) | |
07a0c7d5 | 780 | (set! (prompt-handler x) (lp handler))) |
1c297a38 | 781 | |
2d026f04 | 782 | ((<abort> tag args tail) |
6e84cb95 | 783 | (set! (abort-tag x) (lp tag)) |
2d026f04 AW |
784 | (set! (abort-args x) (map lp args)) |
785 | (set! (abort-tail x) (lp tail))) | |
1c297a38 | 786 | |
cb28c085 AW |
787 | (else #f)) |
788 | x))) |