1 ;;;; Copyright (C) 2009, 2010 Free Software Foundation, Inc.
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.
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.
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
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)
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 <application> application? make-application application-src application-proc application-args
38 <sequence> sequence? make-sequence sequence-src sequence-exps
39 <lambda> lambda? make-lambda lambda-src lambda-meta lambda-body
40 <lambda-case> lambda-case? make-lambda-case lambda-case-src
41 lambda-case-req lambda-case-opt lambda-case-rest lambda-case-kw
42 lambda-case-inits lambda-case-vars
43 lambda-case-body lambda-case-alternate
44 <let> let? make-let let-src let-names let-vars let-vals let-body
45 <letrec> letrec? make-letrec letrec-src letrec-names letrec-vars letrec-vals letrec-body
46 <fix> fix? make-fix fix-src fix-names fix-vars fix-vals fix-body
47 <let-values> let-values? make-let-values let-values-src let-values-exp let-values-body
48 <dynwind> dynwind? make-dynwind dynwind-src dynwind-winder dynwind-body dynwind-unwinder
49 <dynlet> dynlet? make-dynlet dynlet-src dynlet-fluids dynlet-vals dynlet-body
50 <prompt> prompt? make-prompt prompt-src prompt-tag prompt-body prompt-handler
51 <control> control? make-control control-src control-tag control-type control-args
62 (define-type (<tree-il> #:common-slots (src))
65 (<primitive-ref> name)
66 (<lexical-ref> name gensym)
67 (<lexical-set> name gensym exp)
68 (<module-ref> mod name public?)
69 (<module-set> mod name public? exp)
71 (<toplevel-set> name exp)
72 (<toplevel-define> name exp)
73 (<conditional> test consequent alternate)
74 (<application> proc args)
77 (<lambda-case> req opt rest kw inits vars body alternate)
78 (<let> names vars vals body)
79 (<letrec> names vars vals body)
80 (<fix> names vars vals body)
81 (<let-values> exp body)
82 (<dynwind> winder body unwinder)
83 (<dynlet> fluids vals body)
84 (<prompt> tag body handler)
85 (<control> tag type args))
91 (let ((props (source-properties x)))
92 (and (pair? props) props))))
94 (define (parse-tree-il exp)
95 (let ((loc (location exp))
96 (retrans (lambda (x) (parse-tree-il x))))
101 ((apply ,proc . ,args)
102 (make-application loc (retrans proc) (map retrans args)))
104 ((if ,test ,consequent ,alternate)
105 (make-conditional loc (retrans test) (retrans consequent) (retrans alternate)))
107 ((primitive ,name) (guard (symbol? name))
108 (make-primitive-ref loc name))
110 ((lexical ,name) (guard (symbol? name))
111 (make-lexical-ref loc name name))
113 ((lexical ,name ,sym) (guard (symbol? name) (symbol? sym))
114 (make-lexical-ref loc name sym))
116 ((set! (lexical ,name) ,exp) (guard (symbol? name))
117 (make-lexical-set loc name name (retrans exp)))
119 ((set! (lexical ,name ,sym) ,exp) (guard (symbol? name) (symbol? sym))
120 (make-lexical-set loc name sym (retrans exp)))
122 ((@ ,mod ,name) (guard (and-map symbol? mod) (symbol? name))
123 (make-module-ref loc mod name #t))
125 ((set! (@ ,mod ,name) ,exp) (guard (and-map symbol? mod) (symbol? name))
126 (make-module-set loc mod name #t (retrans exp)))
128 ((@@ ,mod ,name) (guard (and-map symbol? mod) (symbol? name))
129 (make-module-ref loc mod name #f))
131 ((set! (@@ ,mod ,name) ,exp) (guard (and-map symbol? mod) (symbol? name))
132 (make-module-set loc mod name #f (retrans exp)))
134 ((toplevel ,name) (guard (symbol? name))
135 (make-toplevel-ref loc name))
137 ((set! (toplevel ,name) ,exp) (guard (symbol? name))
138 (make-toplevel-set loc name (retrans exp)))
140 ((define ,name ,exp) (guard (symbol? name))
141 (make-toplevel-define loc name (retrans exp)))
143 ((lambda ,meta ,body)
144 (make-lambda loc meta (retrans body)))
146 ((lambda-case ((,req ,opt ,rest ,kw ,inits ,vars) ,body) ,alternate)
147 (make-lambda-case loc req opt rest kw
148 (map retrans inits) vars
150 (and=> alternate retrans)))
152 ((lambda-case ((,req ,opt ,rest ,kw ,inits ,vars) ,body))
153 (make-lambda-case loc req opt rest kw
154 (map retrans inits) vars
159 (make-const loc exp))
162 (make-sequence loc (map retrans exps)))
164 ((let ,names ,vars ,vals ,body)
165 (make-let loc names vars (map retrans vals) (retrans body)))
167 ((letrec ,names ,vars ,vals ,body)
168 (make-letrec loc names vars (map retrans vals) (retrans body)))
170 ((fix ,names ,vars ,vals ,body)
171 (make-fix loc names vars (map retrans vals) (retrans body)))
173 ((let-values ,exp ,body)
174 (make-let-values loc (retrans exp) (retrans body)))
176 ((dynwind ,winder ,body ,unwinder)
177 (make-dynwind loc (retrans winder) (retrans body) (retrans unwinder)))
179 ((dynlet ,fluids ,vals ,body)
180 (make-dynlet loc (map retrans fluids) (map retrans vals) (retrans body)))
182 ((prompt ,tag ,body ,handler)
183 (make-prompt loc (retrans tag) (retrans body) (retrans handler)))
185 ((control ,tag ,type ,args)
186 (make-control loc (retrans tag) type (map retrans args)))
189 (error "unrecognized tree-il" exp)))))
191 (define (unparse-tree-il tree-il)
196 ((<application> proc args)
197 `(apply ,(unparse-tree-il proc) ,@(map unparse-tree-il args)))
199 ((<conditional> test consequent alternate)
200 `(if ,(unparse-tree-il test) ,(unparse-tree-il consequent) ,(unparse-tree-il alternate)))
202 ((<primitive-ref> name)
205 ((<lexical-ref> name gensym)
206 `(lexical ,name ,gensym))
208 ((<lexical-set> name gensym exp)
209 `(set! (lexical ,name ,gensym) ,(unparse-tree-il exp)))
211 ((<module-ref> mod name public?)
212 `(,(if public? '@ '@@) ,mod ,name))
214 ((<module-set> mod name public? exp)
215 `(set! (,(if public? '@ '@@) ,mod ,name) ,(unparse-tree-il exp)))
217 ((<toplevel-ref> name)
220 ((<toplevel-set> name exp)
221 `(set! (toplevel ,name) ,(unparse-tree-il exp)))
223 ((<toplevel-define> name exp)
224 `(define ,name ,(unparse-tree-il exp)))
226 ((<lambda> meta body)
227 `(lambda ,meta ,(unparse-tree-il body)))
229 ((<lambda-case> req opt rest kw inits vars body alternate)
230 `(lambda-case ((,req ,opt ,rest ,kw ,(map unparse-tree-il inits) ,vars)
231 ,(unparse-tree-il body))
232 . ,(if alternate (list (unparse-tree-il alternate)) '())))
238 `(begin ,@(map unparse-tree-il exps)))
240 ((<let> names vars vals body)
241 `(let ,names ,vars ,(map unparse-tree-il vals) ,(unparse-tree-il body)))
243 ((<letrec> names vars vals body)
244 `(letrec ,names ,vars ,(map unparse-tree-il vals) ,(unparse-tree-il body)))
246 ((<fix> names vars vals body)
247 `(fix ,names ,vars ,(map unparse-tree-il vals) ,(unparse-tree-il body)))
249 ((<let-values> exp body)
250 `(let-values ,(unparse-tree-il exp) ,(unparse-tree-il body)))
252 ((<dynwind> body winder unwinder)
253 `(dynwind ,(unparse-tree-il body)
254 ,(unparse-tree-il winder) ,(unparse-tree-il unwinder)))
256 ((<dynlet> fluids vals body)
257 `(dynlet ,(map unparse-tree-il fluids) ,(map unparse-tree-il vals)
258 ,(unparse-tree-il body)))
260 ((<prompt> tag body handler)
261 `(prompt ,tag ,(unparse-tree-il body) ,(unparse-tree-il handler)))
263 ((<control> tag type args)
264 `(control ,(unparse-tree-il tag) ,type ,(map unparse-tree-il args)))))
266 (define (tree-il->scheme e)
271 ((<application> proc args)
272 `(,(tree-il->scheme proc) ,@(map tree-il->scheme args)))
274 ((<conditional> test consequent alternate)
275 (if (void? alternate)
276 `(if ,(tree-il->scheme test) ,(tree-il->scheme consequent))
277 `(if ,(tree-il->scheme test) ,(tree-il->scheme consequent) ,(tree-il->scheme alternate))))
279 ((<primitive-ref> name)
282 ((<lexical-ref> gensym)
285 ((<lexical-set> gensym exp)
286 `(set! ,gensym ,(tree-il->scheme exp)))
288 ((<module-ref> mod name public?)
289 `(,(if public? '@ '@@) ,mod ,name))
291 ((<module-set> mod name public? exp)
292 `(set! (,(if public? '@ '@@) ,mod ,name) ,(tree-il->scheme exp)))
294 ((<toplevel-ref> name)
297 ((<toplevel-set> name exp)
298 `(set! ,name ,(tree-il->scheme exp)))
300 ((<toplevel-define> name exp)
301 `(define ,name ,(tree-il->scheme exp)))
303 ((<lambda> meta body)
304 ;; fixme: put in docstring
305 (if (and (lambda-case? body)
306 (not (lambda-case-alternate body)))
307 `(lambda ,@(car (tree-il->scheme body)))
308 `(case-lambda ,@(tree-il->scheme body))))
310 ((<lambda-case> req opt rest kw inits vars body alternate)
311 ;; FIXME! use parse-lambda-case?
312 `((,(if rest (apply cons* vars) vars)
313 ,(tree-il->scheme body))
314 ,@(if alternate (tree-il->scheme alternate) '())))
317 (if (and (self-evaluating? exp) (not (vector? exp)))
322 `(begin ,@(map tree-il->scheme exps)))
324 ((<let> vars vals body)
325 `(let ,(map list vars (map tree-il->scheme vals)) ,(tree-il->scheme body)))
327 ((<letrec> vars vals body)
328 `(letrec ,(map list vars (map tree-il->scheme vals)) ,(tree-il->scheme body)))
330 ((<fix> vars vals body)
331 ;; not a typo, we really do translate back to letrec
332 `(letrec ,(map list vars (map tree-il->scheme vals)) ,(tree-il->scheme body)))
334 ((<let-values> exp body)
335 `(call-with-values (lambda () ,(tree-il->scheme exp))
336 ,(tree-il->scheme (make-lambda #f '() body))))
338 ((<dynwind> body winder unwinder)
339 `(dynamic-wind ,(tree-il->scheme winder)
340 (lambda () ,(tree-il->scheme body))
341 ,(tree-il->scheme unwinder)))
343 ((<dynlet> fluids vals body)
344 `(with-fluids ,(map list
345 (map tree-il->scheme fluids)
346 (map tree-il->scheme vals))
347 ,(tree-il->scheme body)))
349 ((<prompt> tag body handler)
350 `((@ (ice-9 control) prompt)
351 ,(tree-il->scheme tag) (lambda () ,(tree-il->scheme body))
352 ,(tree-il->scheme handler)))
355 ((<control> tag type args)
357 ((throw) `(throw ,(tree-il->scheme tag) ,@(map tree-il->scheme args)))
358 (else (error "bad control type" type))))))
361 (define (tree-il-fold leaf down up seed tree)
362 "Traverse TREE, calling LEAF on each leaf encountered, DOWN upon descent
363 into a sub-tree, and UP when leaving a sub-tree. Each of these procedures is
364 invoked as `(PROC TREE SEED)', where TREE is the sub-tree or leaf considered
365 and SEED is the current result, intially seeded with SEED.
367 This is an implementation of `foldts' as described by Andy Wingo in
368 ``Applications of fold to XML transformation''."
369 (let loop ((tree tree)
371 (if (or (null? tree) (pair? tree))
372 (fold loop result tree)
375 (up tree (loop exp (down tree result))))
377 (up tree (loop exp (down tree result))))
378 ((<toplevel-set> exp)
379 (up tree (loop exp (down tree result))))
380 ((<toplevel-define> exp)
381 (up tree (loop exp (down tree result))))
382 ((<conditional> test consequent alternate)
383 (up tree (loop alternate
385 (loop test (down tree result))))))
386 ((<application> proc args)
387 (up tree (loop (cons proc args) (down tree result))))
389 (up tree (loop exps (down tree result))))
391 (up tree (loop body (down tree result))))
392 ((<lambda-case> inits body alternate)
393 (up tree (if alternate
395 (loop body (loop inits (down tree result))))
396 (loop body (loop inits (down tree result))))))
400 (down tree result)))))
401 ((<letrec> vals body)
404 (down tree result)))))
408 (down tree result)))))
409 ((<let-values> exp body)
410 (up tree (loop body (loop exp (down tree result)))))
411 ((<dynwind> body winder unwinder)
412 (up tree (loop unwinder
414 (loop body (down tree result))))))
415 ((<dynlet> fluids vals body)
418 (loop fluids (down tree result))))))
419 ((<prompt> tag body handler)
421 (loop tag (loop body (loop handler
422 (down tree result))))))
423 ((<control> tag type args)
424 (up tree (loop tag (loop args (down tree result)))))
426 (leaf tree result))))))
429 (define-syntax make-tree-il-folder
432 (lambda (tree down up seed ...)
433 (define (fold-values proc exps seed ...)
436 (let-values (((seed ...) (proc (car exps) seed ...)))
437 (fold-values proc (cdr exps) seed ...))))
438 (let foldts ((tree tree) (seed seed) ...)
440 (((seed ...) (down tree seed ...))
444 (foldts exp seed ...))
446 (foldts exp seed ...))
447 ((<toplevel-set> exp)
448 (foldts exp seed ...))
449 ((<toplevel-define> exp)
450 (foldts exp seed ...))
451 ((<conditional> test consequent alternate)
452 (let*-values (((seed ...) (foldts test seed ...))
453 ((seed ...) (foldts consequent seed ...)))
454 (foldts alternate seed ...)))
455 ((<application> proc args)
456 (let-values (((seed ...) (foldts proc seed ...)))
457 (fold-values foldts args seed ...)))
459 (fold-values foldts exps seed ...))
461 (foldts body seed ...))
462 ((<lambda-case> inits body alternate)
463 (let-values (((seed ...) (fold-values foldts inits seed ...)))
465 (let-values (((seed ...) (foldts body seed ...)))
466 (foldts alternate seed ...))
467 (foldts body seed ...))))
469 (let*-values (((seed ...) (fold-values foldts vals seed ...)))
470 (foldts body seed ...)))
471 ((<letrec> vals body)
472 (let*-values (((seed ...) (fold-values foldts vals seed ...)))
473 (foldts body seed ...)))
475 (let*-values (((seed ...) (fold-values foldts vals seed ...)))
476 (foldts body seed ...)))
477 ((<let-values> exp body)
478 (let*-values (((seed ...) (foldts exp seed ...)))
479 (foldts body seed ...)))
480 ((<dynwind> body winder unwinder)
481 (let*-values (((seed ...) (foldts body seed ...))
482 ((seed ...) (foldts winder seed ...)))
483 (foldts unwinder seed ...)))
484 ((<dynlet> fluids vals body)
485 (let*-values (((seed ...) (fold-values foldts fluids seed ...))
486 ((seed ...) (fold-values foldts vals seed ...)))
487 (foldts body seed ...)))
488 ((<prompt> tag body handler)
489 (let*-values (((seed ...) (foldts tag seed ...))
490 ((seed ...) (foldts body seed ...)))
491 (foldts handler seed ...)))
492 ((<control> tag args)
493 (let*-values (((seed ...) (foldts tag seed ...)))
494 (fold-values foldts args seed ...)))
496 (values seed ...)))))
497 (up tree seed ...)))))))
499 (define (post-order! f x)
502 ((<application> proc args)
503 (set! (application-proc x) (lp proc))
504 (set! (application-args x) (map lp args)))
506 ((<conditional> test consequent alternate)
507 (set! (conditional-test x) (lp test))
508 (set! (conditional-consequent x) (lp consequent))
509 (set! (conditional-alternate x) (lp alternate)))
511 ((<lexical-set> name gensym exp)
512 (set! (lexical-set-exp x) (lp exp)))
514 ((<module-set> mod name public? exp)
515 (set! (module-set-exp x) (lp exp)))
517 ((<toplevel-set> name exp)
518 (set! (toplevel-set-exp x) (lp exp)))
520 ((<toplevel-define> name exp)
521 (set! (toplevel-define-exp x) (lp exp)))
524 (set! (lambda-body x) (lp body)))
526 ((<lambda-case> inits body alternate)
527 (set! inits (map lp inits))
528 (set! (lambda-case-body x) (lp body))
530 (set! (lambda-case-alternate x) (lp alternate))))
533 (set! (sequence-exps x) (map lp exps)))
535 ((<let> vars vals body)
536 (set! (let-vals x) (map lp vals))
537 (set! (let-body x) (lp body)))
539 ((<letrec> vars vals body)
540 (set! (letrec-vals x) (map lp vals))
541 (set! (letrec-body x) (lp body)))
543 ((<fix> vars vals body)
544 (set! (fix-vals x) (map lp vals))
545 (set! (fix-body x) (lp body)))
547 ((<let-values> exp body)
548 (set! (let-values-exp x) (lp exp))
549 (set! (let-values-body x) (lp body)))
551 ((<dynwind> body winder unwinder)
552 (set! (dynwind-body x) (lp body))
553 (set! (dynwind-winder x) (lp winder))
554 (set! (dynwind-unwinder x) (lp unwinder)))
556 ((<dynlet> fluids vals body)
557 (set! (dynlet-fluids x) (map lp fluids))
558 (set! (dynlet-vals x) (map lp vals))
559 (set! (dynlet-body x) (lp body)))
561 ((<prompt> tag body handler)
562 (set! (prompt-tag x) (lp tag))
563 (set! (prompt-body x) (lp body))
564 (set! (prompt-handler x) (lp handler)))
566 ((<control> tag args)
567 (set! (control-tag x) (lp tag))
568 (set! (control-args x) (map lp args)))
574 (define (pre-order! f x)
576 (let ((x (or (f x) x)))
578 ((<application> proc args)
579 (set! (application-proc x) (lp proc))
580 (set! (application-args x) (map lp args)))
582 ((<conditional> test consequent alternate)
583 (set! (conditional-test x) (lp test))
584 (set! (conditional-consequent x) (lp consequent))
585 (set! (conditional-alternate x) (lp alternate)))
588 (set! (lexical-set-exp x) (lp exp)))
591 (set! (module-set-exp x) (lp exp)))
593 ((<toplevel-set> exp)
594 (set! (toplevel-set-exp x) (lp exp)))
596 ((<toplevel-define> exp)
597 (set! (toplevel-define-exp x) (lp exp)))
600 (set! (lambda-body x) (lp body)))
602 ((<lambda-case> inits body alternate)
603 (set! inits (map lp inits))
604 (set! (lambda-case-body x) (lp body))
605 (if alternate (set! (lambda-case-alternate x) (lp alternate))))
608 (set! (sequence-exps x) (map lp exps)))
611 (set! (let-vals x) (map lp vals))
612 (set! (let-body x) (lp body)))
614 ((<letrec> vals body)
615 (set! (letrec-vals x) (map lp vals))
616 (set! (letrec-body x) (lp body)))
619 (set! (fix-vals x) (map lp vals))
620 (set! (fix-body x) (lp body)))
622 ((<let-values> exp body)
623 (set! (let-values-exp x) (lp exp))
624 (set! (let-values-body x) (lp body)))
626 ((<dynwind> body winder unwinder)
627 (set! (dynwind-body x) (lp body))
628 (set! (dynwind-winder x) (lp winder))
629 (set! (dynwind-unwinder x) (lp unwinder)))
631 ((<dynlet> fluids vals body)
632 (set! (dynlet-fluids x) (map lp fluids))
633 (set! (dynlet-vals x) (map lp vals))
634 (set! (dynlet-body x) (lp body)))
636 ((<prompt> tag body handler)
637 (set! (prompt-tag x) (lp tag))
638 (set! (prompt-body x) (lp body))
639 (set! (prompt-handler x) (lp handler)))
641 ((<control> tag args)
642 (set! (control-tag x) (lp tag))
643 (set! (control-args x) (map lp args)))