forked from nobutaka/nanopass
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcps.scm
67 lines (62 loc) · 2.18 KB
/
cps.scm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
(use util.match)
(define cps-form
(lambda (exp)
`((lambda (call/cc primordial-continuation)
,(cps exp 'primordial-continuation))
(lambda (k f)
(f k (lambda (dummy-k result)
(k result))))
(lambda (r) r))))
(define cps
(lambda (exp cont-exp)
(if (not (pair? exp))
`(,cont-exp ,exp)
(match exp
[('quote obj)
`(,cont-exp ,exp)]
[('begin a b)
(let ([b-exp (cps b cont-exp)]
[r (new-var 'R)])
(cps a `(lambda (,r) ,b-exp)))]
[('if t c a)
(let ([r (new-var 'R)]
[c-exp (cps c cont-exp)]
[a-exp (cps a cont-exp)])
(cps t
`(lambda (,r)
(if ,r ,c-exp ,a-exp))))]
[('set! v e)
(let ([r (new-var 'R)])
(cps e
`(lambda (,r)
(,cont-exp (set! ,v ,r)))))]
[('lambda formals body)
(let ([k (new-var 'K)])
`(,cont-exp (lambda ,(cons k formals) ,(cps body k))))]
[else
(let ([rator (car exp)]
[rands (cdr exp)])
(if (and (symbol? rator)
(memq rator *prim-names*)) ; It may not necessary to refer to env. Primitives seem terminator of CPS conversion.
(cps-list rands (lambda (args)
(if (eq? rator '%apply)
`(,rator ,cont-exp ,@args)
`(,cont-exp (,rator ,@args)))))
(cps-list exp (lambda (args)
(cons (car args)
(cons cont-exp
(cdr args)))))))]))))
(define cps-list
(lambda (exp inner)
(cps-list-body exp inner '())))
(define cps-list-body
(lambda (exp inner args)
(if (null? exp)
(inner (reverse args))
(cps (car exp)
(let ([r (new-var 'R)])
`(lambda (,r)
,(cps-list-body (cdr exp) inner (cons r args))))))))
(define new-var
(lambda (id)
(gensym (symbol->string id))))