1 ;;;; Copyright (C) 2009 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-then conditional-else
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-names lambda-vars lambda-meta lambda-body
40 <let> let? make-let let-src let-names let-vars let-vals let-body
41 <letrec> letrec? make-letrec letrec-src letrec-names letrec-vars letrec-vals letrec-body
42 <fix> fix? make-fix fix-src fix-names fix-vars fix-vals fix-body
43 <let-values> let-values? make-let-values let-values-src let-values-names let-values-vars let-values-exp let-values-body
54 (define-type (<tree-il> #:common-slots (src))
57 (<primitive-ref> name)
58 (<lexical-ref> name gensym)
59 (<lexical-set> name gensym exp)
60 (<module-ref> mod name public?)
61 (<module-set> mod name public? exp)
63 (<toplevel-set> name exp)
64 (<toplevel-define> name exp)
65 (<conditional> test then else)
66 (<application> proc args)
68 (<lambda> names vars meta body)
69 (<let> names vars vals body)
70 (<letrec> names vars vals body)
71 (<fix> names vars vals body)
72 (<let-values> names vars exp body))
78 (let ((props (source-properties x)))
79 (and (pair? props) props))))
81 (define (parse-tree-il exp)
82 (let ((loc (location exp))
83 (retrans (lambda (x) (parse-tree-il x))))
88 ((apply ,proc . ,args)
89 (make-application loc (retrans proc) (map retrans args)))
91 ((if ,test ,then ,else)
92 (make-conditional loc (retrans test) (retrans then) (retrans else)))
94 ((primitive ,name) (guard (symbol? name))
95 (make-primitive-ref loc name))
97 ((lexical ,name) (guard (symbol? name))
98 (make-lexical-ref loc name name))
100 ((lexical ,name ,sym) (guard (symbol? name) (symbol? sym))
101 (make-lexical-ref loc name sym))
103 ((set! (lexical ,name) ,exp) (guard (symbol? name))
104 (make-lexical-set loc name name (retrans exp)))
106 ((set! (lexical ,name ,sym) ,exp) (guard (symbol? name) (symbol? sym))
107 (make-lexical-set loc name sym (retrans exp)))
109 ((@ ,mod ,name) (guard (and-map symbol? mod) (symbol? name))
110 (make-module-ref loc mod name #t))
112 ((set! (@ ,mod ,name) ,exp) (guard (and-map symbol? mod) (symbol? name))
113 (make-module-set loc mod name #t (retrans exp)))
115 ((@@ ,mod ,name) (guard (and-map symbol? mod) (symbol? name))
116 (make-module-ref loc mod name #f))
118 ((set! (@@ ,mod ,name) ,exp) (guard (and-map symbol? mod) (symbol? name))
119 (make-module-set loc mod name #f (retrans exp)))
121 ((toplevel ,name) (guard (symbol? name))
122 (make-toplevel-ref loc name))
124 ((set! (toplevel ,name) ,exp) (guard (symbol? name))
125 (make-toplevel-set loc name (retrans exp)))
127 ((define ,name ,exp) (guard (symbol? name))
128 (make-toplevel-define loc name (retrans exp)))
130 ((lambda ,names ,vars ,exp)
131 (make-lambda loc names vars '() (retrans exp)))
133 ((lambda ,names ,vars ,meta ,exp)
134 (make-lambda loc names vars meta (retrans exp)))
137 (make-const loc exp))
140 (make-sequence loc (map retrans exps)))
142 ((let ,names ,vars ,vals ,body)
143 (make-let loc names vars (map retrans vals) (retrans body)))
145 ((letrec ,names ,vars ,vals ,body)
146 (make-letrec loc names vars (map retrans vals) (retrans body)))
148 ((fix ,names ,vars ,vals ,body)
149 (make-fix loc names vars (map retrans vals) (retrans body)))
151 ((let-values ,names ,vars ,exp ,body)
152 (make-let-values loc names vars (retrans exp) (retrans body)))
155 (error "unrecognized tree-il" exp)))))
157 (define (unparse-tree-il tree-il)
162 ((<application> proc args)
163 `(apply ,(unparse-tree-il proc) ,@(map unparse-tree-il args)))
165 ((<conditional> test then else)
166 `(if ,(unparse-tree-il test) ,(unparse-tree-il then) ,(unparse-tree-il else)))
168 ((<primitive-ref> name)
171 ((<lexical-ref> name gensym)
172 `(lexical ,name ,gensym))
174 ((<lexical-set> name gensym exp)
175 `(set! (lexical ,name ,gensym) ,(unparse-tree-il exp)))
177 ((<module-ref> mod name public?)
178 `(,(if public? '@ '@@) ,mod ,name))
180 ((<module-set> mod name public? exp)
181 `(set! (,(if public? '@ '@@) ,mod ,name) ,(unparse-tree-il exp)))
183 ((<toplevel-ref> name)
186 ((<toplevel-set> name exp)
187 `(set! (toplevel ,name) ,(unparse-tree-il exp)))
189 ((<toplevel-define> name exp)
190 `(define ,name ,(unparse-tree-il exp)))
192 ((<lambda> names vars meta body)
193 `(lambda ,names ,vars ,meta ,(unparse-tree-il body)))
199 `(begin ,@(map unparse-tree-il exps)))
201 ((<let> names vars vals body)
202 `(let ,names ,vars ,(map unparse-tree-il vals) ,(unparse-tree-il body)))
204 ((<letrec> names vars vals body)
205 `(letrec ,names ,vars ,(map unparse-tree-il vals) ,(unparse-tree-il body)))
207 ((<fix> names vars vals body)
208 `(fix ,names ,vars ,(map unparse-tree-il vals) ,(unparse-tree-il body)))
210 ((<let-values> names vars exp body)
211 `(let-values ,names ,vars ,(unparse-tree-il exp) ,(unparse-tree-il body)))))
213 (define (tree-il->scheme e)
218 ((<application> proc args)
219 `(,(tree-il->scheme proc) ,@(map tree-il->scheme args)))
221 ((<conditional> test then else)
223 `(if ,(tree-il->scheme test) ,(tree-il->scheme then))
224 `(if ,(tree-il->scheme test) ,(tree-il->scheme then) ,(tree-il->scheme else))))
226 ((<primitive-ref> name)
229 ((<lexical-ref> name gensym)
232 ((<lexical-set> name gensym exp)
233 `(set! ,gensym ,(tree-il->scheme exp)))
235 ((<module-ref> mod name public?)
236 `(,(if public? '@ '@@) ,mod ,name))
238 ((<module-set> mod name public? exp)
239 `(set! (,(if public? '@ '@@) ,mod ,name) ,(tree-il->scheme exp)))
241 ((<toplevel-ref> name)
244 ((<toplevel-set> name exp)
245 `(set! ,name ,(tree-il->scheme exp)))
247 ((<toplevel-define> name exp)
248 `(define ,name ,(tree-il->scheme exp)))
250 ((<lambda> vars meta body)
252 ,@(cond ((assq-ref meta 'documentation) => list) (else '()))
253 ,(tree-il->scheme body)))
256 (if (and (self-evaluating? exp) (not (vector? exp)))
261 `(begin ,@(map tree-il->scheme exps)))
263 ((<let> vars vals body)
264 `(let ,(map list vars (map tree-il->scheme vals)) ,(tree-il->scheme body)))
266 ((<letrec> vars vals body)
267 `(letrec ,(map list vars (map tree-il->scheme vals)) ,(tree-il->scheme body)))
269 ((<fix> vars vals body)
270 ;; not a typo, we really do translate back to letrec
271 `(letrec ,(map list vars (map tree-il->scheme vals)) ,(tree-il->scheme body)))
273 ((<let-values> vars exp body)
274 `(call-with-values (lambda () ,(tree-il->scheme exp))
275 (lambda ,vars ,(tree-il->scheme body))))))
278 (define (tree-il-fold leaf down up seed tree)
279 "Traverse TREE, calling LEAF on each leaf encountered, DOWN upon descent
280 into a sub-tree, and UP when leaving a sub-tree. Each of these procedures is
281 invoked as `(PROC TREE SEED)', where TREE is the sub-tree or leaf considered
282 and SEED is the current result, intially seeded with SEED.
284 This is an implementation of `foldts' as described by Andy Wingo in
285 ``Applications of fold to XML transformation''."
286 (let loop ((tree tree)
288 (if (or (null? tree) (pair? tree))
289 (fold loop result tree)
292 (up tree (loop exp (down tree result))))
294 (up tree (loop exp (down tree result))))
295 ((<toplevel-set> exp)
296 (up tree (loop exp (down tree result))))
297 ((<toplevel-define> exp)
298 (up tree (loop exp (down tree result))))
299 ((<conditional> test then else)
302 (loop test (down tree result))))))
303 ((<application> proc args)
304 (up tree (loop (cons proc args) (down tree result))))
306 (up tree (loop exps (down tree result))))
308 (up tree (loop body (down tree result))))
312 (down tree result)))))
313 ((<letrec> vals body)
316 (down tree result)))))
320 (down tree result)))))
321 ((<let-values> exp body)
322 (up tree (loop body (loop exp (down tree result)))))
324 (leaf tree result))))))
327 (define-syntax make-tree-il-folder
330 (lambda (tree down up seed ...)
331 (define (fold-values proc exps seed ...)
334 (let-values (((seed ...) (proc (car exps) seed ...)))
335 (fold-values proc (cdr exps) seed ...))))
336 (let foldts ((tree tree) (seed seed) ...)
338 (((seed ...) (down tree seed ...))
342 (foldts exp seed ...))
344 (foldts exp seed ...))
345 ((<toplevel-set> exp)
346 (foldts exp seed ...))
347 ((<toplevel-define> exp)
348 (foldts exp seed ...))
349 ((<conditional> test then else)
350 (let*-values (((seed ...) (foldts test seed ...))
351 ((seed ...) (foldts then seed ...)))
352 (foldts else seed ...)))
353 ((<application> proc args)
354 (let-values (((seed ...) (foldts proc seed ...)))
355 (fold-values foldts args seed ...)))
357 (fold-values foldts exps seed ...))
359 (foldts body seed ...))
361 (let*-values (((seed ...) (fold-values foldts vals seed ...)))
362 (foldts body seed ...)))
363 ((<letrec> vals body)
364 (let*-values (((seed ...) (fold-values foldts vals seed ...)))
365 (foldts body seed ...)))
367 (let*-values (((seed ...) (fold-values foldts vals seed ...)))
368 (foldts body seed ...)))
369 ((<let-values> exp body)
370 (let*-values (((seed ...) (foldts exp seed ...)))
371 (foldts body seed ...)))
373 (values seed ...)))))
374 (up tree seed ...)))))))
376 (define (post-order! f x)
379 ((<application> proc args)
380 (set! (application-proc x) (lp proc))
381 (set! (application-args x) (map lp args)))
383 ((<conditional> test then else)
384 (set! (conditional-test x) (lp test))
385 (set! (conditional-then x) (lp then))
386 (set! (conditional-else x) (lp else)))
388 ((<lexical-set> name gensym exp)
389 (set! (lexical-set-exp x) (lp exp)))
391 ((<module-set> mod name public? exp)
392 (set! (module-set-exp x) (lp exp)))
394 ((<toplevel-set> name exp)
395 (set! (toplevel-set-exp x) (lp exp)))
397 ((<toplevel-define> name exp)
398 (set! (toplevel-define-exp x) (lp exp)))
400 ((<lambda> vars meta body)
401 (set! (lambda-body x) (lp body)))
404 (set! (sequence-exps x) (map lp exps)))
406 ((<let> vars vals body)
407 (set! (let-vals x) (map lp vals))
408 (set! (let-body x) (lp body)))
410 ((<letrec> vars vals body)
411 (set! (letrec-vals x) (map lp vals))
412 (set! (letrec-body x) (lp body)))
414 ((<fix> vars vals body)
415 (set! (fix-vals x) (map lp vals))
416 (set! (fix-body x) (lp body)))
418 ((<let-values> vars exp body)
419 (set! (let-values-exp x) (lp exp))
420 (set! (let-values-body x) (lp body)))
426 (define (pre-order! f x)
428 (let ((x (or (f x) x)))
430 ((<application> proc args)
431 (set! (application-proc x) (lp proc))
432 (set! (application-args x) (map lp args)))
434 ((<conditional> test then else)
435 (set! (conditional-test x) (lp test))
436 (set! (conditional-then x) (lp then))
437 (set! (conditional-else x) (lp else)))
439 ((<lexical-set> name gensym exp)
440 (set! (lexical-set-exp x) (lp exp)))
442 ((<module-set> mod name public? exp)
443 (set! (module-set-exp x) (lp exp)))
445 ((<toplevel-set> name exp)
446 (set! (toplevel-set-exp x) (lp exp)))
448 ((<toplevel-define> name exp)
449 (set! (toplevel-define-exp x) (lp exp)))
451 ((<lambda> vars meta body)
452 (set! (lambda-body x) (lp body)))
455 (set! (sequence-exps x) (map lp exps)))
457 ((<let> vars vals body)
458 (set! (let-vals x) (map lp vals))
459 (set! (let-body x) (lp body)))
461 ((<letrec> vars vals body)
462 (set! (letrec-vals x) (map lp vals))
463 (set! (letrec-body x) (lp body)))
465 ((<fix> vars vals body)
466 (set! (fix-vals x) (map lp vals))
467 (set! (fix-body x) (lp body)))
469 ((<let-values> vars exp body)
470 (set! (let-values-exp x) (lp exp))
471 (set! (let-values-body x) (lp body)))