Simplify dynstack API to only wind one fluid at a time
[bpt/guile.git] / module / language / tree-il.scm
CommitLineData
19113f1c 1;;;; Copyright (C) 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
d26a26f6 2;;;;
811d10f5
AW
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.
d26a26f6 7;;;;
811d10f5
AW
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.
d26a26f6 12;;;;
811d10f5
AW
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
d26a26f6 16;;;;
811d10f5
AW
17\f
18
19(define-module (language tree-il)
f4aa0f10 20 #:use-module (srfi srfi-1)
4dcd8499 21 #:use-module (srfi srfi-11)
99b4da8f 22 #:use-module (ice-9 match)
811d10f5 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
7081d4f9 37 <call> call? make-call call-src call-proc call-args
a881a4ae 38 <primcall> primcall? make-primcall primcall-src primcall-name primcall-args
d019ef92 39 <seq> seq? make-seq seq-src seq-head seq-tail
8a4ca0ea
AW
40 <lambda> lambda? make-lambda lambda-src lambda-meta lambda-body
41 <lambda-case> lambda-case? make-lambda-case lambda-case-src
b0c8c187 42 lambda-case-req lambda-case-opt lambda-case-rest lambda-case-kw
93f63467 43 lambda-case-inits lambda-case-gensyms
3a88cb3b 44 lambda-case-body lambda-case-alternate
93f63467 45 <let> let? make-let let-src let-names let-gensyms let-vals let-body
fb6e61ca 46 <letrec> letrec? make-letrec letrec-src letrec-in-order? letrec-names letrec-gensyms letrec-vals letrec-body
93f63467 47 <fix> fix? make-fix fix-src fix-names fix-gensyms fix-vals fix-body
8a4ca0ea 48 <let-values> let-values? make-let-values let-values-src let-values-exp let-values-body
07a0c7d5 49 <prompt> prompt? make-prompt prompt-src prompt-tag prompt-body prompt-handler
2d026f04 50 <abort> abort? make-abort abort-src abort-tag abort-args abort-tail
f4aa0f10 51
6fc3eae4
AW
52 list->seq
53
9efc833d
AW
54 parse-tree-il
55 unparse-tree-il
cb28c085
AW
56 tree-il->scheme
57
f4aa0f10 58 tree-il-fold
4dcd8499 59 make-tree-il-folder
403d78f9 60 post-order
25450a0d 61 pre-order
1fb39dc5
AW
62
63 tree-il=?
64 tree-il-hash))
811d10f5 65
4ffa8275 66(define (print-tree-il exp port)
7cd6d77c 67 (format port "#<tree-il ~S>" (unparse-tree-il exp)))
4ffa8275 68
f7b61b39
AW
69(define-syntax borrow-core-vtables
70 (lambda (x)
71 (syntax-case x ()
72 ((_)
73 (let lp ((n 0) (out '()))
74 (if (< n (vector-length %expanded-vtables))
75 (lp (1+ n)
76 (let* ((vtable (vector-ref %expanded-vtables n))
77 (stem (struct-ref vtable (+ vtable-offset-user 0)))
78 (fields (struct-ref vtable (+ vtable-offset-user 2)))
79 (sfields (map
80 (lambda (f) (datum->syntax x f))
81 fields))
82 (type (datum->syntax x (symbol-append '< stem '>)))
83 (ctor (datum->syntax x (symbol-append 'make- stem)))
84 (pred (datum->syntax x (symbol-append stem '?))))
85 (let lp ((n 0) (fields fields)
86 (out (cons*
87 #`(define (#,ctor #,@sfields)
88 (make-struct #,type 0 #,@sfields))
89 #`(define (#,pred x)
90 (and (struct? x)
91 (eq? (struct-vtable x) #,type)))
4ffa8275
AW
92 #`(struct-set! #,type vtable-index-printer
93 print-tree-il)
f7b61b39
AW
94 #`(define #,type
95 (vector-ref %expanded-vtables #,n))
96 out)))
97 (if (null? fields)
98 out
99 (lp (1+ n)
100 (cdr fields)
101 (let ((acc (datum->syntax
102 x (symbol-append stem '- (car fields)))))
103 (cons #`(define #,acc
104 (make-procedure-with-setter
105 (lambda (x) (struct-ref x #,n))
106 (lambda (x v) (struct-set! x #,n v))))
107 out)))))))
108 #`(begin #,@(reverse out))))))))
109
110(borrow-core-vtables)
111
112 ;; (<void>)
113 ;; (<const> exp)
114 ;; (<primitive-ref> name)
115 ;; (<lexical-ref> name gensym)
116 ;; (<lexical-set> name gensym exp)
117 ;; (<module-ref> mod name public?)
118 ;; (<module-set> mod name public? exp)
119 ;; (<toplevel-ref> name)
120 ;; (<toplevel-set> name exp)
121 ;; (<toplevel-define> name exp)
122 ;; (<conditional> test consequent alternate)
7081d4f9 123 ;; (<call> proc args)
a881a4ae 124 ;; (<primcall> name args)
6fc3eae4 125 ;; (<seq> head tail)
f7b61b39
AW
126 ;; (<lambda> meta body)
127 ;; (<lambda-case> req opt rest kw inits gensyms body alternate)
128 ;; (<let> names gensyms vals body)
fb6e61ca 129 ;; (<letrec> in-order? names gensyms vals body)
f7b61b39 130
4ffa8275 131(define-type (<tree-il> #:common-slots (src) #:printer print-tree-il)
93f63467 132 (<fix> names gensyms vals body)
1c297a38 133 (<let-values> exp body)
07a0c7d5 134 (<prompt> tag body handler)
2d026f04 135 (<abort> tag args tail))
d26a26f6 136
811d10f5
AW
137\f
138
6fc3eae4
AW
139;; A helper.
140(define (list->seq loc exps)
141 (if (null? (cdr exps))
142 (car exps)
143 (make-seq loc (car exps) (list->seq #f (cdr exps)))))
144
145\f
146
811d10f5
AW
147(define (location x)
148 (and (pair? x)
149 (let ((props (source-properties x)))
81fd3152 150 (and (pair? props) props))))
811d10f5 151
ce09ee19 152(define (parse-tree-il exp)
811d10f5 153 (let ((loc (location exp))
ce09ee19 154 (retrans (lambda (x) (parse-tree-il x))))
f852e05e
AW
155 (match exp
156 (('void)
cf10678f
AW
157 (make-void loc))
158
f852e05e 159 (('call proc . args)
7081d4f9 160 (make-call loc (retrans proc) (map retrans args)))
811d10f5 161
f852e05e 162 (('primcall name . args)
a881a4ae
AW
163 (make-primcall loc name (map retrans args)))
164
f852e05e 165 (('if test consequent alternate)
b6d93b11 166 (make-conditional loc (retrans test) (retrans consequent) (retrans alternate)))
811d10f5 167
f852e05e 168 (('primitive (and name (? symbol?)))
811d10f5
AW
169 (make-primitive-ref loc name))
170
f852e05e 171 (('lexical (and name (? symbol?)))
811d10f5
AW
172 (make-lexical-ref loc name name))
173
f852e05e 174 (('lexical (and name (? symbol?)) (and sym (? symbol?)))
811d10f5
AW
175 (make-lexical-ref loc name sym))
176
f852e05e 177 (('set! ('lexical (and name (? symbol?))) exp)
5c27902e
AW
178 (make-lexical-set loc name name (retrans exp)))
179
f852e05e 180 (('set! ('lexical (and name (? symbol?)) (and sym (? symbol?))) exp)
811d10f5
AW
181 (make-lexical-set loc name sym (retrans exp)))
182
f852e05e 183 (('@ ((and mod (? symbol?)) ...) (and name (? symbol?)))
811d10f5
AW
184 (make-module-ref loc mod name #t))
185
f852e05e 186 (('set! ('@ ((and mod (? symbol?)) ...) (and name (? symbol?))) exp)
811d10f5
AW
187 (make-module-set loc mod name #t (retrans exp)))
188
f852e05e 189 (('@@ ((and mod (? symbol?)) ...) (and name (? symbol?)))
811d10f5
AW
190 (make-module-ref loc mod name #f))
191
f852e05e 192 (('set! ('@@ ((and mod (? symbol?)) ...) (and name (? symbol?))) exp)
811d10f5
AW
193 (make-module-set loc mod name #f (retrans exp)))
194
f852e05e 195 (('toplevel (and name (? symbol?)))
811d10f5
AW
196 (make-toplevel-ref loc name))
197
f852e05e 198 (('set! ('toplevel (and name (? symbol?))) exp)
811d10f5
AW
199 (make-toplevel-set loc name (retrans exp)))
200
f852e05e 201 (('define (and name (? symbol?)) exp)
811d10f5
AW
202 (make-toplevel-define loc name (retrans exp)))
203
f852e05e 204 (('lambda meta body)
8a4ca0ea 205 (make-lambda loc meta (retrans body)))
811d10f5 206
f852e05e 207 (('lambda-case ((req opt rest kw inits gensyms) body) alternate)
d26a26f6 208 (make-lambda-case loc req opt rest kw
93f63467 209 (map retrans inits) gensyms
8a4ca0ea 210 (retrans body)
3a88cb3b 211 (and=> alternate retrans)))
811d10f5 212
f852e05e 213 (('lambda-case ((req opt rest kw inits gensyms) body))
b0c8c187 214 (make-lambda-case loc req opt rest kw
93f63467 215 (map retrans inits) gensyms
7e01997e
AW
216 (retrans body)
217 #f))
218
f852e05e 219 (('const exp)
811d10f5
AW
220 (make-const loc exp))
221
f852e05e 222 (('seq head tail)
6fc3eae4
AW
223 (make-seq loc (retrans head) (retrans tail)))
224
225 ;; Convenience.
f852e05e 226 (('begin . exps)
6fc3eae4 227 (list->seq loc (map retrans exps)))
811d10f5 228
f852e05e 229 (('let names gensyms vals body)
93f63467 230 (make-let loc names gensyms (map retrans vals) (retrans body)))
f4aa8d53 231
f852e05e 232 (('letrec names gensyms vals body)
fb6e61ca
AW
233 (make-letrec loc #f names gensyms (map retrans vals) (retrans body)))
234
f852e05e 235 (('letrec* names gensyms vals body)
fb6e61ca 236 (make-letrec loc #t names gensyms (map retrans vals) (retrans body)))
811d10f5 237
f852e05e 238 (('fix names gensyms vals body)
93f63467 239 (make-fix loc names gensyms (map retrans vals) (retrans body)))
c21c89b1 240
f852e05e 241 (('let-values exp body)
8a4ca0ea 242 (make-let-values loc (retrans exp) (retrans body)))
811d10f5 243
f852e05e 244 (('prompt tag body handler)
07a0c7d5 245 (make-prompt loc (retrans tag) (retrans body) (retrans handler)))
f852e05e
AW
246
247 (('abort tag args tail)
2d026f04 248 (make-abort loc (retrans tag) (map retrans args) (retrans tail)))
1c297a38 249
811d10f5
AW
250 (else
251 (error "unrecognized tree-il" exp)))))
252
253(define (unparse-tree-il tree-il)
98f778ea
AW
254 (match tree-il
255 (($ <void> src)
cf10678f
AW
256 '(void))
257
98f778ea 258 (($ <call> src proc args)
7081d4f9 259 `(call ,(unparse-tree-il proc) ,@(map unparse-tree-il args)))
811d10f5 260
98f778ea 261 (($ <primcall> src name args)
a881a4ae
AW
262 `(primcall ,name ,@(map unparse-tree-il args)))
263
98f778ea
AW
264 (($ <conditional> src test consequent alternate)
265 `(if ,(unparse-tree-il test)
266 ,(unparse-tree-il consequent)
267 ,(unparse-tree-il alternate)))
811d10f5 268
98f778ea 269 (($ <primitive-ref> src name)
811d10f5
AW
270 `(primitive ,name))
271
98f778ea 272 (($ <lexical-ref> src name gensym)
811d10f5
AW
273 `(lexical ,name ,gensym))
274
98f778ea 275 (($ <lexical-set> src name gensym exp)
811d10f5
AW
276 `(set! (lexical ,name ,gensym) ,(unparse-tree-il exp)))
277
98f778ea 278 (($ <module-ref> src mod name public?)
811d10f5
AW
279 `(,(if public? '@ '@@) ,mod ,name))
280
98f778ea 281 (($ <module-set> src mod name public? exp)
811d10f5
AW
282 `(set! (,(if public? '@ '@@) ,mod ,name) ,(unparse-tree-il exp)))
283
98f778ea 284 (($ <toplevel-ref> src name)
811d10f5
AW
285 `(toplevel ,name))
286
98f778ea 287 (($ <toplevel-set> src name exp)
811d10f5
AW
288 `(set! (toplevel ,name) ,(unparse-tree-il exp)))
289
98f778ea 290 (($ <toplevel-define> src name exp)
811d10f5
AW
291 `(define ,name ,(unparse-tree-il exp)))
292
98f778ea 293 (($ <lambda> src meta body)
19113f1c
AW
294 (if body
295 `(lambda ,meta ,(unparse-tree-il body))
296 `(lambda ,meta (lambda-case))))
8a4ca0ea 297
98f778ea 298 (($ <lambda-case> src req opt rest kw inits gensyms body alternate)
93f63467 299 `(lambda-case ((,req ,opt ,rest ,kw ,(map unparse-tree-il inits) ,gensyms)
8a4ca0ea 300 ,(unparse-tree-il body))
3a88cb3b 301 . ,(if alternate (list (unparse-tree-il alternate)) '())))
811d10f5 302
98f778ea 303 (($ <const> src exp)
811d10f5
AW
304 `(const ,exp))
305
98f778ea 306 (($ <seq> src head tail)
6fc3eae4
AW
307 `(seq ,(unparse-tree-il head) ,(unparse-tree-il tail)))
308
98f778ea 309 (($ <let> src names gensyms vals body)
93f63467 310 `(let ,names ,gensyms ,(map unparse-tree-il vals) ,(unparse-tree-il body)))
811d10f5 311
98f778ea 312 (($ <letrec> src in-order? names gensyms vals body)
fb6e61ca
AW
313 `(,(if in-order? 'letrec* 'letrec) ,names ,gensyms
314 ,(map unparse-tree-il vals) ,(unparse-tree-il body)))
f4aa8d53 315
98f778ea 316 (($ <fix> src names gensyms vals body)
93f63467 317 `(fix ,names ,gensyms ,(map unparse-tree-il vals) ,(unparse-tree-il body)))
c21c89b1 318
98f778ea 319 (($ <let-values> src exp body)
1c297a38
AW
320 `(let-values ,(unparse-tree-il exp) ,(unparse-tree-il body)))
321
98f778ea
AW
322 (($ <prompt> src tag body handler)
323 `(prompt ,(unparse-tree-il tag)
324 ,(unparse-tree-il body)
325 ,(unparse-tree-il handler)))
d26a26f6 326
98f778ea 327 (($ <abort> src tag args tail)
2d026f04
AW
328 `(abort ,(unparse-tree-il tag) ,(map unparse-tree-il args)
329 ,(unparse-tree-il tail)))))
811d10f5 330
72ee0ef7
MW
331(define* (tree-il->scheme e #:optional (env #f) (opts '()))
332 (values ((@ (language scheme decompile-tree-il)
333 decompile-tree-il)
334 e env opts)))
cb28c085 335
f4aa0f10 336\f
0c65f52c
AW
337(define-syntax-rule (make-tree-il-folder seed ...)
338 (lambda (tree down up seed ...)
339 (define (fold-values proc exps seed ...)
340 (if (null? exps)
341 (values seed ...)
342 (let-values (((seed ...) (proc (car exps) seed ...)))
343 (fold-values proc (cdr exps) seed ...))))
344 (let foldts ((tree tree) (seed seed) ...)
345 (let*-values
346 (((seed ...) (down tree seed ...))
347 ((seed ...)
b34b66b3
AW
348 (match tree
349 (($ <lexical-set> src name gensym exp)
0c65f52c 350 (foldts exp seed ...))
b34b66b3 351 (($ <module-set> src mod name public? exp)
0c65f52c 352 (foldts exp seed ...))
b34b66b3 353 (($ <toplevel-set> src name exp)
0c65f52c 354 (foldts exp seed ...))
b34b66b3 355 (($ <toplevel-define> src name exp)
0c65f52c 356 (foldts exp seed ...))
b34b66b3 357 (($ <conditional> src test consequent alternate)
0c65f52c
AW
358 (let*-values (((seed ...) (foldts test seed ...))
359 ((seed ...) (foldts consequent seed ...)))
360 (foldts alternate seed ...)))
b34b66b3 361 (($ <call> src proc args)
0c65f52c
AW
362 (let-values (((seed ...) (foldts proc seed ...)))
363 (fold-values foldts args seed ...)))
b34b66b3 364 (($ <primcall> src name args)
ca128245 365 (fold-values foldts args seed ...))
b34b66b3 366 (($ <seq> src head tail)
ca128245
AW
367 (let-values (((seed ...) (foldts head seed ...)))
368 (foldts tail seed ...)))
b34b66b3 369 (($ <lambda> src meta body)
19113f1c
AW
370 (if body
371 (foldts body seed ...)
372 (values seed ...)))
b34b66b3
AW
373 (($ <lambda-case> src req opt rest kw inits gensyms body
374 alternate)
0c65f52c
AW
375 (let-values (((seed ...) (fold-values foldts inits seed ...)))
376 (if alternate
377 (let-values (((seed ...) (foldts body seed ...)))
378 (foldts alternate seed ...))
379 (foldts body seed ...))))
b34b66b3 380 (($ <let> src names gensyms vals body)
0c65f52c
AW
381 (let*-values (((seed ...) (fold-values foldts vals seed ...)))
382 (foldts body seed ...)))
b34b66b3 383 (($ <letrec> src in-order? names gensyms vals body)
0c65f52c
AW
384 (let*-values (((seed ...) (fold-values foldts vals seed ...)))
385 (foldts body seed ...)))
b34b66b3 386 (($ <fix> src names gensyms vals body)
0c65f52c
AW
387 (let*-values (((seed ...) (fold-values foldts vals seed ...)))
388 (foldts body seed ...)))
b34b66b3 389 (($ <let-values> src exp body)
0c65f52c
AW
390 (let*-values (((seed ...) (foldts exp seed ...)))
391 (foldts body seed ...)))
b34b66b3 392 (($ <prompt> src tag body handler)
0c65f52c
AW
393 (let*-values (((seed ...) (foldts tag seed ...))
394 ((seed ...) (foldts body seed ...)))
395 (foldts handler seed ...)))
b34b66b3 396 (($ <abort> src tag args tail)
0c65f52c
AW
397 (let*-values (((seed ...) (foldts tag seed ...))
398 ((seed ...) (fold-values foldts args seed ...)))
399 (foldts tail seed ...)))
b34b66b3 400 (_
0c65f52c
AW
401 (values seed ...)))))
402 (up tree seed ...)))))
4dcd8499 403
007f671a
AW
404(define (tree-il-fold down up seed tree)
405 "Traverse TREE, calling DOWN before visiting a sub-tree, and UP when
406after visiting it. Each of these procedures is invoked as `(PROC TREE
407SEED)', where TREE is the sub-tree considered and SEED is the current
408result, intially seeded with SEED.
409
410This is an implementation of `foldts' as described by Andy Wingo in
411``Applications of fold to XML transformation''."
412 ;; Multi-valued fold naturally puts the seeds at the end, whereas
413 ;; normal fold puts the traversable at the end. Adapt to the expected
414 ;; argument order.
415 ((make-tree-il-folder tree) tree down up seed))
416
403d78f9 417(define (pre-post-order pre post x)
cb28c085 418 (let lp ((x x))
403d78f9 419 (post
99b4da8f
AW
420 (match (pre x)
421 (($ <void> src)
403d78f9 422 (make-void src))
cb28c085 423
99b4da8f 424 (($ <const> src exp)
403d78f9 425 (make-const src exp))
a881a4ae 426
99b4da8f 427 (($ <primitive-ref> src name)
403d78f9 428 (make-primitive-ref src name))
d26a26f6 429
99b4da8f 430 (($ <lexical-ref> src name gensym)
403d78f9 431 (make-lexical-ref src name gensym))
d26a26f6 432
99b4da8f 433 (($ <lexical-set> src name gensym exp)
403d78f9 434 (make-lexical-set src name gensym (lp exp)))
d26a26f6 435
99b4da8f 436 (($ <module-ref> src mod name public?)
403d78f9 437 (make-module-ref src mod name public?))
d26a26f6 438
99b4da8f 439 (($ <module-set> src mod name public? exp)
403d78f9 440 (make-module-set src mod name public? (lp exp)))
d26a26f6 441
99b4da8f 442 (($ <toplevel-ref> src name)
403d78f9 443 (make-toplevel-ref src name))
d26a26f6 444
99b4da8f 445 (($ <toplevel-set> src name exp)
403d78f9 446 (make-toplevel-set src name (lp exp)))
d26a26f6 447
99b4da8f 448 (($ <toplevel-define> src name exp)
403d78f9
AW
449 (make-toplevel-define src name (lp exp)))
450
99b4da8f 451 (($ <conditional> src test consequent alternate)
403d78f9
AW
452 (make-conditional src (lp test) (lp consequent) (lp alternate)))
453
99b4da8f 454 (($ <call> src proc args)
403d78f9
AW
455 (make-call src (lp proc) (map lp args)))
456
99b4da8f 457 (($ <primcall> src name args)
403d78f9
AW
458 (make-primcall src name (map lp args)))
459
99b4da8f 460 (($ <seq> src head tail)
403d78f9 461 (make-seq src (lp head) (lp tail)))
6fc3eae4 462
99b4da8f 463 (($ <lambda> src meta body)
403d78f9
AW
464 (make-lambda src meta (and body (lp body))))
465
99b4da8f 466 (($ <lambda-case> src req opt rest kw inits gensyms body alternate)
403d78f9
AW
467 (make-lambda-case src req opt rest kw (map lp inits) gensyms (lp body)
468 (and alternate (lp alternate))))
469
99b4da8f 470 (($ <let> src names gensyms vals body)
403d78f9
AW
471 (make-let src names gensyms (map lp vals) (lp body)))
472
99b4da8f 473 (($ <letrec> src in-order? names gensyms vals body)
403d78f9
AW
474 (make-letrec src in-order? names gensyms (map lp vals) (lp body)))
475
99b4da8f 476 (($ <fix> src names gensyms vals body)
403d78f9
AW
477 (make-fix src names gensyms (map lp vals) (lp body)))
478
99b4da8f 479 (($ <let-values> src exp body)
403d78f9
AW
480 (make-let-values src (lp exp) (lp body)))
481
99b4da8f 482 (($ <prompt> src tag body handler)
403d78f9
AW
483 (make-prompt src (lp tag) (lp body) (lp handler)))
484
99b4da8f 485 (($ <abort> src tag args tail)
403d78f9
AW
486 (make-abort src (lp tag) (map lp args) (lp tail)))))))
487
488(define (post-order f x)
489 (pre-post-order (lambda (x) x) f x))
cb28c085 490
25450a0d
AW
491(define (pre-order f x)
492 (pre-post-order f (lambda (x) x) x))
1fb39dc5
AW
493
494;; FIXME: We should have a better primitive than this.
495(define (struct-nfields x)
496 (/ (string-length (symbol->string (struct-layout x))) 2))
497
498(define (tree-il=? a b)
499 (cond
500 ((struct? a)
501 (and (struct? b)
502 (eq? (struct-vtable a) (struct-vtable b))
503 ;; Assume that all structs are tree-il, so we skip over the
504 ;; src slot.
505 (let lp ((n (1- (struct-nfields a))))
506 (or (zero? n)
507 (and (tree-il=? (struct-ref a n) (struct-ref b n))
508 (lp (1- n)))))))
509 ((pair? a)
510 (and (pair? b)
511 (tree-il=? (car a) (car b))
512 (tree-il=? (cdr a) (cdr b))))
513 (else
514 (equal? a b))))
515
516(define-syntax hash-bits
517 (make-variable-transformer
518 (lambda (x)
519 (syntax-case x ()
520 (var
521 (identifier? #'var)
522 (logcount most-positive-fixnum))))))
523
524(define (tree-il-hash exp)
525 (let ((hash-depth 4)
526 (hash-width 3))
527 (define (hash-exp exp depth)
528 (define (rotate x bits)
529 (logior (ash x (- bits))
530 (ash (logand x (1- (ash 1 bits))) (- hash-bits bits))))
531 (define (mix h1 h2)
532 (logxor h1 (rotate h2 8)))
533 (define (hash-struct s)
534 (let ((len (struct-nfields s))
535 (h (hashq (struct-vtable s) most-positive-fixnum)))
536 (if (zero? depth)
537 h
538 (let lp ((i (max (- len hash-width) 1)) (h h))
539 (if (< i len)
540 (lp (1+ i) (mix (hash-exp (struct-ref s i) (1+ depth)) h))
541 h)))))
542 (define (hash-list l)
543 (let ((h (hashq 'list most-positive-fixnum)))
544 (if (zero? depth)
545 h
546 (let lp ((l l) (width 0) (h h))
547 (if (< width hash-width)
548 (lp (cdr l) (1+ width)
549 (mix (hash-exp (car l) (1+ depth)) h))
550 h)))))
551 (cond
552 ((struct? exp) (hash-struct exp))
553 ((list? exp) (hash-list exp))
554 (else (hash exp most-positive-fixnum))))
555
556 (hash-exp exp 0)))