-
Notifications
You must be signed in to change notification settings - Fork 112
/
Copy pathcps.scm
112 lines (105 loc) · 3.04 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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
(define (cps-top expr)
(T-k expr (lambda (x) x)))
(define (aexpr? expr)
(or (lambda? expr)
(immediate? expr)
(symbol? expr)
(string? expr)
(aexpr-primcall? expr)))
(define (T-k expr k)
(cond
[(aexpr? expr)
(k (M expr))]
[(begin? expr)
(let ([expr (first (begin-seq expr))]
[exprs (rest (begin-seq expr))])
(if (null? exprs)
(T-k expr k)
(T-k expr (lambda (_)
(T-k (cons 'begin exprs) k)))))]
[(if? expr)
(let* ([exprc (if-test expr)]
[exprt (if-conseq expr)]
[exprf (if-altern expr)]
[$rv (unique-name '$rv)]
[cont (list 'lambda (list $rv) (k $rv))])
(T-k exprc (lambda (aexp)
(list 'if aexp
(T-c exprt cont)
(T-c exprf cont)))))]
[(let? expr)
(let ([vars (map lhs (let-bindings expr))]
[vals (map rhs (let-bindings expr))])
(T*-k vals (lambda ($vals)
(make-let
'let
(map bind vars $vals)
(T-k (let-body expr) k)))))]
[(app? expr)
(let* ([$rv (unique-name '$rv)]
[cont (list 'lambda (list $rv) (k $rv))])
(T-c expr cont))]
[else (error 'T-k (format "~s is not an expression" expr))]))
(define (T-c expr c)
(cond
[(aexpr? expr)
(list c (M expr))]
[(begin? expr)
(let ([expr (first (begin-seq expr))]
[exprs (rest (begin-seq expr))])
(if (null? exprs)
(T-c expr c)
(T-k expr (lambda (_)
(T-c (cons 'begin exprs) c)))))]
[(if? expr)
(let ([exprc (if-test expr)]
[exprt (if-conseq expr)]
[exprf (if-altern expr)]
[$k (unique-name '$k)])
(list (list 'lambda (list $k)
(T-k exprc (lambda (aexp)
(list 'if aexp
(T-c exprt $k)
(T-c exprf $k)))))
c))]
[(let? expr)
(let ([vars (map lhs (let-bindings expr))]
[vals (map rhs (let-bindings expr))])
(T*-k vals (lambda ($vals)
(make-let
'let
(map bind vars $vals)
(T-c (let-body expr) c)))))]
[(app? expr)
(let ([f (call-target expr)]
[es (call-args expr)])
(T-k f (lambda ($f)
(T*-k es (lambda ($es)
(let ([app (cons $f (cons c $es))])
(if (call-apply? expr)
(cons 'apply app)
app)))))))]
[else (error 'T-c (format "~s is not an expression" expr))]))
(define (T*-k exprs k)
(cond
[(null? exprs)
(k '())]
[(pair? exprs)
(T-k (car exprs) (lambda (hd)
(T*-k (cdr exprs) (lambda (tl)
(k (cons hd tl))))))]))
(define (M aexpr)
(cond
[(lambda? aexpr)
(let ([$k (unique-name '$k)])
(list 'lambda (cons $k (lambda-formals aexpr))
(T-c (lambda-body aexpr) $k)))]
[(eq? 'call/cc aexpr)
'(lambda (cc f) (f cc (lambda (_ x) (cc x))))]
[else aexpr]))
(set! cps-conversion
(lambda (expr)
(make-let
'labels
(let-bindings expr)
(cps-top (let-body expr)))))