Commit | Line | Data |
---|---|---|
7f918cf1 CE |
1 | (* Copyright (C) 1999-2005 Henry Cejtin, Matthew Fluet, Suresh |
2 | * Jagannathan, and Stephen Weeks. | |
3 | * Copyright (C) 1997-2000 NEC Research Institute. | |
4 | * | |
5 | * MLton is released under a BSD-style license. | |
6 | * See the file MLton-LICENSE for details. | |
7 | *) | |
8 | ||
9 | functor SimplifyTypes (S: SIMPLIFY_TYPES_STRUCTS): SIMPLIFY_TYPES = | |
10 | struct | |
11 | ||
12 | open S | |
13 | structure I = Input | |
14 | structure O = Output | |
15 | open I.Atoms | |
16 | ||
17 | structure PowerSetLat = | |
18 | struct | |
19 | datatype t = T of {isIn: bool ref, | |
20 | whenIn: (unit -> unit) list ref} vector | |
21 | ||
22 | fun isIn (T v, i) = | |
23 | ! (#isIn (Vector.sub (v, i))) | |
24 | ||
25 | fun new (size: int) = T (Vector.tabulate (size, fn _ => | |
26 | {isIn = ref false, | |
27 | whenIn = ref []})) | |
28 | ||
29 | fun add (T v, i) = | |
30 | let | |
31 | val {isIn, whenIn, ...} = Vector.sub (v, i) | |
32 | in | |
33 | if !isIn | |
34 | then () | |
35 | else (isIn := true | |
36 | ; List.foreach (!whenIn, fn f => f ())) | |
37 | end | |
38 | ||
39 | fun whenIn (T v, i, f) = | |
40 | let | |
41 | val {isIn, whenIn, ...} = Vector.sub (v, i) | |
42 | in | |
43 | if !isIn | |
44 | then f () | |
45 | else List.push (whenIn, f) | |
46 | end | |
47 | end | |
48 | ||
49 | fun simplifyTypes (I.Program.T {body, datatypes, overflow}) = | |
50 | let | |
51 | val {get = tyconInfo: Tycon.t -> {used: PowerSetLat.t} option, | |
52 | set = setTyconInfo, ...} = | |
53 | Property.getSetOnce (Tycon.plist, Property.initConst NONE) | |
54 | val _ = | |
55 | Vector.foreach | |
56 | (datatypes, fn {tycon, tyvars, ...} => | |
57 | setTyconInfo (tycon, | |
58 | SOME {used = PowerSetLat.new (Vector.length tyvars)})) | |
59 | val _ = | |
60 | Vector.foreach | |
61 | (datatypes, fn {cons, tycon, tyvars} => | |
62 | let | |
63 | val {get = tyvarIndex, set = setTyvarIndex, rem, ...} = | |
64 | Property.getSet | |
65 | (Tyvar.plist, Property.initRaise ("index", Tyvar.layout)) | |
66 | val _ = Vector.foreachi (tyvars, fn (i, a) => setTyvarIndex (a, i)) | |
67 | val {used, ...} = valOf (tyconInfo tycon) | |
68 | val {destroy, hom} = | |
69 | I.Type.makeHom | |
70 | {con = (fn (_, tc, ts) => | |
71 | fn () => | |
72 | case tyconInfo tc of | |
73 | NONE => Vector.foreach (ts, fn t => t ()) | |
74 | | SOME {used, ...} => | |
75 | Vector.foreachi | |
76 | (ts, fn (i, t) => | |
77 | PowerSetLat.whenIn (used, i, t))), | |
78 | var = (fn (_, a) => | |
79 | let | |
80 | val i = tyvarIndex a | |
81 | in | |
82 | fn () => PowerSetLat.add (used, i) | |
83 | end)} | |
84 | val _ = | |
85 | Vector.foreach | |
86 | (cons, fn {arg, ...} => | |
87 | case arg of | |
88 | NONE => () | |
89 | | SOME t => hom t ()) | |
90 | val _ = Vector.foreach (tyvars, rem) | |
91 | val _ = destroy () | |
92 | in | |
93 | () | |
94 | end) | |
95 | val {get = tyconKeep: Tycon.t -> bool vector option, | |
96 | set = setTyconKeep, ...} = | |
97 | Property.getSetOnce (Tycon.plist, Property.initConst NONE) | |
98 | val {get = conKeep: Con.t -> bool vector option, | |
99 | set = setConKeep, ...} = | |
100 | Property.getSetOnce (Con.plist, Property.initConst NONE) | |
101 | val _ = | |
102 | Vector.foreach | |
103 | (datatypes, fn {cons, tycon, tyvars} => | |
104 | let | |
105 | val {used, ...} = valOf (tyconInfo tycon) | |
106 | val v = | |
107 | Vector.tabulate | |
108 | (Vector.length tyvars, fn i => PowerSetLat.isIn (used, i)) | |
109 | val _ = Vector.foreach (cons, fn {con, ...} => | |
110 | setConKeep (con, SOME v)) | |
111 | val u = | |
112 | if Vector.forall (v, fn b => b) | |
113 | then NONE | |
114 | else SOME v | |
115 | val _ = setTyconKeep (tycon, u) | |
116 | in | |
117 | () | |
118 | end) | |
119 | fun keep (v: 'a vector, bv: bool vector): 'a vector = | |
120 | Vector.keepAllMapi (v, fn (i, a) => | |
121 | if Vector.sub (bv, i) | |
122 | then SOME a | |
123 | else NONE) | |
124 | val {get = tyvarIsUsed: Tyvar.t -> bool ref, ...} = | |
125 | Property.get (Tyvar.plist, Property.initFun (fn _ => ref false)) | |
126 | (* There is some mesiness with promises here for two reasons: | |
127 | * 1. The thunk is to make sure that even though we are using a type | |
128 | * homomorphism, a type variable is only marked as used if it appears | |
129 | * in the output. | |
130 | * 2. The promise is do avoid computing the same output multiple times. | |
131 | * This is necessary because the type homomorphism only memoizes the | |
132 | * mapping from type to thunk, *not* the thunk's output. | |
133 | *) | |
134 | val {hom = fixType: I.Type.t -> unit -> O.Type.t, ...} = | |
135 | I.Type.makeHom | |
136 | {con = (fn (_, tc, ts) => | |
137 | Promise.lazy | |
138 | (fn () => | |
139 | let | |
140 | val ts = | |
141 | case tyconKeep tc of | |
142 | NONE => ts | |
143 | | SOME bv => keep (ts, bv) | |
144 | val ts = Vector.map (ts, fn t => t ()) | |
145 | in | |
146 | O.Type.con (tc, ts) | |
147 | end)), | |
148 | var = (fn (_, a) => | |
149 | Promise.lazy | |
150 | (fn () => (tyvarIsUsed a := true; O.Type.var a)))} | |
151 | val fixType = fn t => fixType t () | |
152 | val fixType = | |
153 | Trace.trace | |
154 | ("SimplifyTypes.fixType", I.Type.layout, O.Type.layout) | |
155 | fixType | |
156 | val tyvarIsUsed = ! o tyvarIsUsed | |
157 | val datatypes = | |
158 | Vector.map (datatypes, fn {cons, tycon, tyvars} => | |
159 | {cons = Vector.map (cons, fn {arg, con} => | |
160 | {arg = Option.map (arg, fixType), | |
161 | con = con}), | |
162 | tycon = tycon, | |
163 | tyvars = (case tyconKeep tycon of | |
164 | NONE => tyvars | |
165 | | SOME bv => keep (tyvars, bv))}) | |
166 | val {get = varKeep: Var.t -> bool vector option, | |
167 | set = setVarKeep, ...} = | |
168 | Property.getSetOnce (Var.plist, Property.initConst NONE) | |
169 | fun fixVarExp (I.VarExp.T {targs, var}): O.VarExp.t = | |
170 | let | |
171 | val targs = | |
172 | case varKeep var of | |
173 | NONE => targs | |
174 | | SOME bv => keep (targs, bv) | |
175 | in | |
176 | O.VarExp.T {targs = Vector.map (targs, fixType), | |
177 | var = var} | |
178 | end | |
179 | val fixVarExp = | |
180 | Trace.trace | |
181 | ("SimplifyTypes.fixVarExp", I.VarExp.layout, O.VarExp.layout) | |
182 | fixVarExp | |
183 | fun fixConTargs (con: Con.t, targs: I.Type.t vector): O.Type.t vector = | |
184 | let | |
185 | val targs = | |
186 | case conKeep con of | |
187 | NONE => targs | |
188 | | SOME bv => keep (targs, bv) | |
189 | in | |
190 | Vector.map (targs, fixType) | |
191 | end | |
192 | fun fixPat (I.Pat.T {arg, con, targs}): O.Pat.t = | |
193 | O.Pat.T {arg = Option.map (arg, fn (x, t) => (x, fixType t)), | |
194 | con = con, | |
195 | targs = fixConTargs (con, targs)} | |
196 | fun fixDec (d: I.Dec.t): O.Dec.t = | |
197 | case d of | |
198 | I.Dec.Exception {arg, con} => | |
199 | O.Dec.Exception {arg = Option.map (arg, fixType), | |
200 | con = con} | |
201 | | I.Dec.Fun {decs, tyvars} => | |
202 | let | |
203 | val decs = | |
204 | Vector.map (decs, fn {lambda, ty, var} => | |
205 | {lambda = fixLambda lambda, | |
206 | ty = fixType ty, | |
207 | var = var}) | |
208 | val bv = Vector.map (tyvars, tyvarIsUsed) | |
209 | val tyvars = keep (tyvars, bv) | |
210 | val _ = | |
211 | Vector.foreach | |
212 | (decs, fn {var, ...} => setVarKeep (var, SOME bv)) | |
213 | in | |
214 | O.Dec.Fun {decs = decs, | |
215 | tyvars = tyvars} | |
216 | end | |
217 | | I.Dec.MonoVal {exp, ty, var} => | |
218 | O.Dec.MonoVal {exp = fixPrimExp exp, | |
219 | ty = fixType ty, | |
220 | var = var} | |
221 | | I.Dec.PolyVal {exp, ty, tyvars, var} => | |
222 | let | |
223 | val exp = fixExp exp | |
224 | val ty = fixType ty | |
225 | val bv = Vector.map (tyvars, tyvarIsUsed) | |
226 | val _ = setVarKeep (var, SOME bv) | |
227 | in | |
228 | O.Dec.PolyVal {exp = exp, | |
229 | ty = ty, | |
230 | tyvars = keep (tyvars, bv), | |
231 | var = var} | |
232 | end | |
233 | and fixExp (e: I.Exp.t): O.Exp.t = | |
234 | let | |
235 | val {decs, result} = I.Exp.dest e | |
236 | in | |
237 | O.Exp.make {decs = List.map (decs, fixDec), | |
238 | result = fixVarExp result} | |
239 | end | |
240 | and fixLambda (l: I.Lambda.t): O.Lambda.t = | |
241 | let | |
242 | val {arg, argType, body, mayInline} = I.Lambda.dest l | |
243 | in | |
244 | O.Lambda.make {arg = arg, | |
245 | argType = fixType argType, | |
246 | body = fixExp body, | |
247 | mayInline = mayInline} | |
248 | end | |
249 | and fixPrimExp (e: I.PrimExp.t): O.PrimExp.t = | |
250 | case e of | |
251 | I.PrimExp.App {arg, func} => O.PrimExp.App {arg = fixVarExp arg, | |
252 | func = fixVarExp func} | |
253 | | I.PrimExp.Case {cases, default, test} => | |
254 | let | |
255 | val cases = | |
256 | case cases of | |
257 | I.Cases.Con v => | |
258 | O.Cases.Con (Vector.map (v, fn (p, e) => | |
259 | (fixPat p, fixExp e))) | |
260 | | I.Cases.Word (s, v) => | |
261 | O.Cases.Word | |
262 | (s, Vector.map (v, fn (c, e) => (c, fixExp e))) | |
263 | in | |
264 | O.PrimExp.Case {cases = cases, | |
265 | default = Option.map (default, fn (e, r) => | |
266 | (fixExp e, r)), | |
267 | test = fixVarExp test} | |
268 | end | |
269 | | I.PrimExp.ConApp {arg, con, targs} => | |
270 | O.PrimExp.ConApp {arg = Option.map (arg, fixVarExp), | |
271 | con = con, | |
272 | targs = fixConTargs (con, targs)} | |
273 | | I.PrimExp.Const c => O.PrimExp.Const c | |
274 | | I.PrimExp.Handle {catch = (x, t), handler, try} => | |
275 | O.PrimExp.Handle {catch = (x, fixType t), | |
276 | handler = fixExp handler, | |
277 | try = fixExp try} | |
278 | | I.PrimExp.Lambda l => O.PrimExp.Lambda (fixLambda l) | |
279 | | I.PrimExp.PrimApp {args, prim, targs} => | |
280 | O.PrimExp.PrimApp {args = Vector.map (args, fixVarExp), | |
281 | prim = Prim.map (prim, fixType), | |
282 | targs = Vector.map (targs, fixType)} | |
283 | | I.PrimExp.Profile e => O.PrimExp.Profile e | |
284 | | I.PrimExp.Raise {exn, extend} => | |
285 | O.PrimExp.Raise {exn = fixVarExp exn, | |
286 | extend = extend} | |
287 | | I.PrimExp.Select {offset, tuple} => | |
288 | O.PrimExp.Select {offset = offset, | |
289 | tuple = fixVarExp tuple} | |
290 | | I.PrimExp.Tuple xs => O.PrimExp.Tuple (Vector.map (xs, fixVarExp)) | |
291 | | I.PrimExp.Var x => O.PrimExp.Var (fixVarExp x) | |
292 | val body = fixExp body | |
293 | in | |
294 | O.Program.T {datatypes = datatypes, | |
295 | body = body, | |
296 | overflow = overflow} | |
297 | end | |
298 | ||
299 | end |