-
Notifications
You must be signed in to change notification settings - Fork 0
/
cps-convert.sml
executable file
·132 lines (123 loc) · 4.3 KB
/
cps-convert.sml
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
structure CpsConvert: CPS_CONVERT =
struct
exception NoRule
val counter1 = ref 1
fun freshCont ()=
let val n = !counter1
val _ = counter1 :=(n+1)
in "k_"^(Int.toString (n))
end
val counter2 = ref 1
fun freshVal ()=
let val n = !counter2
val _ = counter2 :=(n+1)
in "x_"^(Int.toString (n))
end
fun transo (option: MLAst.PrimOp.t): Cps.PrimOp.t =
case option
of MLAst.PrimOp.Add => Cps.PrimOp.Add
| MLAst.PrimOp.Sub => Cps.PrimOp.Sub
| MLAst.PrimOp.Times => Cps.PrimOp.Times
| MLAst.PrimOp.Print => Cps.PrimOp.Print
| MLAst.PrimOp.Int2String => Cps.PrimOp.Int2String
fun reverse(strs: string list,res: string list):string list =
case strs
of e::es => reverse(es,e::res)
| [] => res
fun transTuple (ts: MLAst.t list, strs: string list, g: string list -> Cps.t): Cps.t =
case ts
of e::es => trans(e, fn x => transTuple(es,x::strs,g))
| [] => g(reverse(strs,[]))
and trans (x: MLAst.t , k: string -> Cps.t) =
case x of
MLAst.Var v => k(v)
| MLAst.Empty =>
let val f = freshVal()
in Cps.LetVal(f, Cps.Empty , k f)
end
| MLAst.Num i =>
let val f = freshVal()
in Cps.LetVal(f, Cps.Num(i) ,k f)
end
| MLAst.String str =>
let val f = freshVal()
in Cps.LetVal(f, Cps.String(str) , k f)
end
| MLAst.App(t1,t2) =>
let val k1 = freshCont()
val v = freshVal()
val temp = fn z1 => trans(t2, fn z2 => Cps.LetCont(k1, v, k v, Cps.FuncApp(z1, k1, z2)))
in trans(t1, temp)
end
| MLAst.Tuple(t) =>
let val v = freshVal()
in transTuple(t, [], fn l => Cps.LetVal(v, Cps.Tuple(l), k v))
end
| MLAst.Tag(i,t) =>
let val v = freshVal()
in
trans(t, fn z => Cps.LetVal(v, Cps.Tag(i, z), k v))
end
| MLAst.Proj(i,t) =>
let val v = freshVal()
in
trans(t, fn z => Cps.Let(v, i, z, k v))
end
| MLAst.FuncVal(v,e) =>
let val f = freshVal()
val k1 = freshCont()
in Cps.LetVal(f
, Cps.FuncVal(k1, v, trans(e
,fn z =>
Cps.ContApp(k1, z)))
, k f)
end
| MLAst.LetVal(s,t1,t2) =>
let val j = freshCont()
val v = freshVal()
in Cps.LetCont(j, v, trans(t2, k), trans(t1, fn z => Cps.ContApp(j, z)))
end
| MLAst.Case(t1,s1,t2,s2,t3) =>
let val k0 = freshCont()
val x0 = freshVal()
val k1 = freshCont()
val x1 = freshVal()
val k2 = freshCont()
val x2 = freshVal()
in trans(t1, fn z =>
Cps.LetCont(k0, x0, k x0,
Cps.LetCont(k1, x1, trans(t2, fn z2 => Cps.ContApp(k0, z2)),
Cps.LetCont(k2, x2, trans(t3, fn z3 => Cps.ContApp(k0,z3)), Cps.Case(z,k1,k2))
)
)
)
end
| MLAst.Prims(s1,l1) =>
let val l2 = freshVal()
in
transTuple(l1, [], fn l3 => Cps.LetPrim(l2, transo(s1), l3, k l2))
end
| MLAst.LetFix(str1,str2,t1,t2) =>
let val k1 = freshCont()
val x1 = freshVal()
in Cps.LetFix(str1, k1, str2,
trans(t1, fn z => Cps.ContApp(k1,z)),
trans(t2, k))
end
| MLAst.If0(t1,t2,t3) =>
let val k0 = freshCont()
val x0 = freshVal()
val k1 = freshCont()
val x1 = freshVal()
val k2 = freshCont()
val x2 = freshVal()
in trans(t1, fn z0 =>
Cps.LetCont(k0,x0,k x0,
Cps.LetCont(k1,x1,trans(t2, fn z1 => Cps.ContApp(k0,z1)),
Cps.LetCont(k2,x2,trans(t3, fn z2 => Cps.ContApp(k0,z2)),
Cps.If0(z0,k1,k2)
)
)
))
end
end