fix bug in memoize
[bpt/guile.git] / module / language / tree-il.scm
CommitLineData
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
479into a sub-tree, and UP when leaving a sub-tree. Each of these procedures is
480invoked as `(PROC TREE SEED)', where TREE is the sub-tree or leaf considered
481and SEED is the current result, intially seeded with SEED.
482
483This 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)))