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