-
Notifications
You must be signed in to change notification settings - Fork 1
/
uncurry.sml
137 lines (124 loc) · 3.82 KB
/
uncurry.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
132
133
134
135
136
137
(* uncurry.sml
*
* ...
*
* Copyright (c) 2005 Matthias Blume (blume@tti-c.org)
*)
(*
FIX ([(f0, vl0,
FIX ([(f1, vl1,
FIX ([(f2, vl2,
...
FIX ([(fk, vlk,
e)],
fk) ...)],
f2))],
f1)),
...],
...)
=>
FIX ([(f, vl0 @ vl1 @ vl2 @ ... @ vlk,
FIX ([header(1..k)],
FIX ([header(2..k)],
...
FIX ([header(k..k)],
e) ...))),
header(0..k),
...],
...)
where
header(i..k) =
(fi, vli',
FIX ([(f{i+1}', vl{i+1}',
...
FIX ([(fk', vlk',
f (vl0 @ ... @ vl{i-1} @
vli' @ vl{i+1}' @ ... @ vlk'))],
fk') ...)],
f{i+1}'))
*)
structure Uncurry : sig
val transform : ANF.function -> ANF.function
end = struct
structure A = ANF
(* We don't attempt to uncurry exception handlers. *)
fun transform { f = (f, vl, e), inl, hdlr } =
let fun function ({ f = (f0, vl0, e0), inl = inl0, hdlr = false }, fl) =
let fun build (rl, (f0, vl0, inl0), e) =
let val l = rev rl
val f0' = LVar.clone f0
val inl0' = inl0 andalso List.all #3 l
val vl0_k =
vl0 @ foldr (fn ((_, vl, _), avl) => vl @ avl)
[] l
fun header (pfx, (f, vl, inl), l) =
let fun gen (pfx, []) =
A.JUMP (Purity.Impure,
(A.VAR f0', map A.VAR pfx))
| gen (pfx, (f, vl, inl) :: l) =
let val f' = LVar.clone f
val vl' = map LVar.clone vl
val h = gen (pfx @ vl', l)
in A.FIX ([{ f = (f', vl', h),
inl = true,
hdlr = false }],
A.VALUES [A.VAR f'])
end
val vl' = map LVar.clone vl
in { f = (f, vl', gen (pfx @ vl', l)),
inl = true, hdlr = false }
end
fun withHeaders (pfx, []) = e
| withHeaders (pfx, h :: t) =
A.FIX ([header (pfx, h, t)],
withHeaders (pfx @ #2 h, t))
val fu0' = { f = (f0', vl0_k, withHeaders (vl0, l)),
inl = inl0', hdlr = false }
val h0 = header ([], (f0, vl0, inl0), l)
in fu0' :: h0 :: fl
end
fun dump ([], (f0, vl0, inl0), e) =
{ f = (f0, vl0, e), inl = inl0, hdlr = false } :: fl
| dump ((f, vl, inl) :: rl, i0, e) =
dump (rl, i0,
A.FIX ([{ f = (f, vl, e),
inl = inl,
hdlr = false }],
A.VALUES [A.VAR f]))
fun uncurry (rl, i0,
e as A.FIX ([{ f = (f, vl, b), inl, hdlr }],
A.VALUES [A.VAR v])) =
if not hdlr andalso f = v then
uncurry ((f, vl, inl) :: rl, i0, b)
else build (rl, i0, exp e)
| uncurry (rl, i0, e as (A.VALUES _ | A.JUMP _)) =
dump (rl, i0, e)
| uncurry (rl, i0, e) =
build (rl, i0, exp e)
in case e0 of
A.FIX ([{ f = (f1, vl1, e1), inl = inl1, hdlr = false }],
A.VALUES [A.VAR v]) =>
if f1 = v then
uncurry ([(f1, vl1, inl1)], (f0, vl0, inl0), e1)
else { f = (f0, vl0, exp e0),
inl = inl0, hdlr = false } :: fl
| _ => { f = (f0, vl0, exp e0),
inl = inl0, hdlr = false } :: fl
end
| function (f, fl) = f :: fl
and exp (e as A.VALUES _) = e
| exp (A.BIND (v, x, e)) = A.BIND (v, x, exp e)
| exp (A.CALL (p, vl, xxl, e)) = A.CALL (p, vl, xxl, exp e)
| exp (A.FIX (fl, e)) = A.FIX (foldr function [] fl, exp e)
| exp (A.ARITH (a, x, y, v, e)) = A.ARITH (a, x, y, v, exp e)
| exp (A.RECORD (p, x, sl, v, e)) = A.RECORD (p, x, sl, v, exp e)
| exp (A.SELECT (x, y, p, v, e)) = A.SELECT (x, y, p, v, exp e)
| exp (A.UPDATE (x, y, z, e)) = A.UPDATE (x, y, z, exp e)
| exp (A.CMP (c, x, y, et, ef)) = A.CMP (c, x, y, exp et, exp ef)
| exp (A.GETSP (v, e)) = A.GETSP (v, exp e)
| exp (A.SETSP (x, e)) = A.SETSP (x, exp e)
| exp (A.MAYJUMP (v, e)) = A.MAYJUMP (v, exp e)
| exp (e as A.JUMP _) = e
in { f = (f, vl, exp e), inl = inl, hdlr = hdlr }
end
end