adamc@1180
|
1 (* Copyright (c) 2008-2010, Adam Chlipala
|
adamc@443
|
2 * All rights reserved.
|
adamc@443
|
3 *
|
adamc@443
|
4 * Redistribution and use in source and binary forms, with or without
|
adamc@443
|
5 * modification, are permitted provided that the following conditions are met:
|
adamc@443
|
6 *
|
adamc@443
|
7 * - Redistributions of source code must retain the above copyright notice,
|
adamc@443
|
8 * this list of conditions and the following disclaimer.
|
adamc@443
|
9 * - Redistributions in binary form must reproduce the above copyright notice,
|
adamc@443
|
10 * this list of conditions and the following disclaimer in the documentation
|
adamc@443
|
11 * and/or other materials provided with the distribution.
|
adamc@443
|
12 * - The names of contributors may not be used to endorse or promote products
|
adamc@443
|
13 * derived from this software without specific prior written permission.
|
adamc@443
|
14 *
|
adamc@443
|
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
adamc@443
|
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
adamc@443
|
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
adamc@443
|
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
adamc@443
|
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
adamc@443
|
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
adamc@443
|
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
adamc@443
|
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
adamc@443
|
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
adamc@443
|
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
adamc@443
|
25 * POSSIBILITY OF SUCH DAMAGE.
|
adamc@443
|
26 *)
|
adamc@443
|
27
|
adamc@443
|
28 structure ESpecialize :> ESPECIALIZE = struct
|
adamc@443
|
29
|
adamc@443
|
30 open Core
|
adamc@443
|
31
|
adamc@443
|
32 structure E = CoreEnv
|
adamc@443
|
33 structure U = CoreUtil
|
adamc@443
|
34
|
adamc@479
|
35 type skey = exp
|
adamc@453
|
36
|
adamc@453
|
37 structure K = struct
|
adamc@479
|
38 type ord_key = exp list
|
adamc@479
|
39 val compare = Order.joinL U.Exp.compare
|
adamc@443
|
40 end
|
adamc@443
|
41
|
adamc@453
|
42 structure KM = BinaryMapFn(K)
|
adamc@443
|
43 structure IM = IntBinaryMap
|
adamc@482
|
44 structure IS = IntBinarySet
|
adamc@443
|
45
|
adamc@1181
|
46 val isOpen = U.Exp.exists {kind = fn _ => false,
|
adamc@1181
|
47 con = fn c =>
|
adamc@1181
|
48 case c of
|
adamc@1181
|
49 CRel _ => true
|
adamc@1181
|
50 | _ => false,
|
adamc@1181
|
51 exp = fn _ => false}
|
adamc@1181
|
52
|
adamc@626
|
53 val freeVars = U.Exp.foldB {kind = fn (_, _, xs) => xs,
|
adamc@488
|
54 con = fn (_, _, xs) => xs,
|
adamc@488
|
55 exp = fn (bound, e, xs) =>
|
adamc@488
|
56 case e of
|
adamc@488
|
57 ERel x =>
|
adamc@488
|
58 if x >= bound then
|
adamc@488
|
59 IS.add (xs, x - bound)
|
adamc@488
|
60 else
|
adamc@488
|
61 xs
|
adamc@488
|
62 | _ => xs,
|
adamc@488
|
63 bind = fn (bound, b) =>
|
adamc@488
|
64 case b of
|
adamc@488
|
65 U.Exp.RelE _ => bound + 1
|
adamc@488
|
66 | _ => bound}
|
adamc@488
|
67 0 IS.empty
|
adamc@479
|
68
|
adamc@1120
|
69 fun isPolyT (t, _) =
|
adamc@1120
|
70 case t of
|
adamc@1120
|
71 TFun (_, ran) => isPolyT ran
|
adamc@1120
|
72 | TCFun _ => true
|
adamc@1120
|
73 | TKFun _ => true
|
adamc@1120
|
74 | _ => false
|
adamc@1120
|
75
|
adamc@1120
|
76 fun isPoly (d, _) =
|
adamc@1120
|
77 case d of
|
adamc@1120
|
78 DVal (_, _, t, _, _) => isPolyT t
|
adamc@1120
|
79 | DValRec vis => List.exists (isPolyT o #3) vis
|
adamc@1120
|
80 | _ => false
|
adamc@522
|
81
|
adamc@488
|
82 fun positionOf (v : int, ls) =
|
adamc@488
|
83 let
|
adamc@488
|
84 fun pof (pos, ls) =
|
adamc@488
|
85 case ls of
|
adamc@488
|
86 [] => raise Fail "Defunc.positionOf"
|
adamc@488
|
87 | v' :: ls' =>
|
adamc@488
|
88 if v = v' then
|
adamc@488
|
89 pos
|
adamc@488
|
90 else
|
adamc@488
|
91 pof (pos + 1, ls')
|
adamc@488
|
92 in
|
adamc@488
|
93 pof (0, ls)
|
adamc@488
|
94 end
|
adamc@488
|
95
|
adamc@1079
|
96 fun squish fvs =
|
adamc@626
|
97 U.Exp.mapB {kind = fn _ => fn k => k,
|
adamc@488
|
98 con = fn _ => fn c => c,
|
adamc@488
|
99 exp = fn bound => fn e =>
|
adamc@479
|
100 case e of
|
adamc@488
|
101 ERel x =>
|
adamc@488
|
102 if x >= bound then
|
adamc@1079
|
103 ERel (positionOf (x - bound, fvs) + bound)
|
adamc@488
|
104 else
|
adamc@488
|
105 e
|
adamc@488
|
106 | _ => e,
|
adamc@488
|
107 bind = fn (bound, b) =>
|
adamc@488
|
108 case b of
|
adamc@488
|
109 U.Exp.RelE _ => bound + 1
|
adamc@488
|
110 | _ => bound}
|
adamc@488
|
111 0
|
adamc@453
|
112
|
adamc@443
|
113 type func = {
|
adamc@443
|
114 name : string,
|
adamc@453
|
115 args : int KM.map,
|
adamc@443
|
116 body : exp,
|
adamc@443
|
117 typ : con,
|
adamc@443
|
118 tag : string
|
adamc@443
|
119 }
|
adamc@443
|
120
|
adamc@443
|
121 type state = {
|
adamc@443
|
122 maxName : int,
|
adamc@443
|
123 funcs : func IM.map,
|
adamc@1079
|
124 decls : (string * int * con * exp * string) list,
|
adamc@1080
|
125 specialized : IS.set
|
adamc@443
|
126 }
|
adamc@443
|
127
|
adamc@488
|
128 fun default (_, x, st) = (x, st)
|
adamc@443
|
129
|
adamc@800
|
130 structure SS = BinarySetFn(struct
|
adamc@800
|
131 type ord_key = string
|
adamc@800
|
132 val compare = String.compare
|
adamc@800
|
133 end)
|
adamc@800
|
134
|
adamc@800
|
135 val mayNotSpec = ref SS.empty
|
adamc@800
|
136
|
adamc@1080
|
137 fun specialize' (funcs, specialized) file =
|
adamc@443
|
138 let
|
adamc@1180
|
139 fun functionInside functiony = U.Con.exists {kind = fn _ => false,
|
adamc@1180
|
140 con = fn TFun _ => true
|
adamc@1180
|
141 | CFfi ("Basis", "transaction") => true
|
adamc@1180
|
142 | CFfi ("Basis", "eq") => true
|
adamc@1180
|
143 | CFfi ("Basis", "num") => true
|
adamc@1180
|
144 | CFfi ("Basis", "ord") => true
|
adamc@1180
|
145 | CFfi ("Basis", "show") => true
|
adamc@1180
|
146 | CFfi ("Basis", "read") => true
|
adamc@1180
|
147 | CFfi ("Basis", "sql_injectable_prim") => true
|
adamc@1180
|
148 | CFfi ("Basis", "sql_injectable") => true
|
adamc@1180
|
149 | CNamed n => IS.member (functiony, n)
|
adamc@1180
|
150 | _ => false}
|
adamc@1180
|
151
|
adamc@1180
|
152 val functiony = foldl (fn ((d, _), functiony) =>
|
adamc@1180
|
153 case d of
|
adamc@1180
|
154 DCon (_, n, _, c) =>
|
adamc@1180
|
155 if functionInside functiony c then
|
adamc@1180
|
156 IS.add (functiony, n)
|
adamc@1180
|
157 else
|
adamc@1180
|
158 functiony
|
adamc@1180
|
159 | DDatatype dts =>
|
adamc@1180
|
160 if List.exists (fn (_, _, _, cs) =>
|
adamc@1180
|
161 List.exists (fn (_, _, SOME c) => functionInside functiony c
|
adamc@1180
|
162 | _ => false) cs) dts then
|
adamc@1180
|
163 IS.addList (functiony, map #2 dts)
|
adamc@1180
|
164 else
|
adamc@1180
|
165 functiony
|
adamc@1180
|
166 | _ => functiony) IS.empty file
|
adamc@1180
|
167
|
adamc@1180
|
168 val functionInside = functionInside functiony
|
adamc@1180
|
169
|
adamc@488
|
170 fun bind (env, b) =
|
adamc@488
|
171 case b of
|
adamc@521
|
172 U.Decl.RelE xt => xt :: env
|
adamc@521
|
173 | _ => env
|
adamc@488
|
174
|
adamc@1080
|
175 fun exp (env, e as (_, loc), st : state) =
|
adamc@482
|
176 let
|
adamc@721
|
177 (*val () = Print.prefaces "exp" [("e", CorePrint.p_exp CoreEnv.empty
|
adamc@721
|
178 (e, ErrorMsg.dummySpan))]*)
|
adamc@721
|
179
|
adamc@1080
|
180 fun getApp (e, _) =
|
adamc@482
|
181 case e of
|
adamc@488
|
182 ENamed f => SOME (f, [])
|
adamc@482
|
183 | EApp (e1, e2) =>
|
adamc@1080
|
184 (case getApp e1 of
|
adamc@482
|
185 NONE => NONE
|
adamc@488
|
186 | SOME (f, xs) => SOME (f, xs @ [e2]))
|
adamc@482
|
187 | _ => NONE
|
adamc@1080
|
188
|
adamc@1080
|
189 val getApp = fn e => case getApp e of
|
adamc@1080
|
190 v as SOME (_, _ :: _) => v
|
adamc@1080
|
191 | _ => NONE
|
adamc@1080
|
192
|
adamc@1080
|
193 fun default () =
|
adamc@1080
|
194 case #1 e of
|
adamc@1080
|
195 EPrim _ => (e, st)
|
adamc@1080
|
196 | ERel _ => (e, st)
|
adamc@1080
|
197 | ENamed _ => (e, st)
|
adamc@1080
|
198 | ECon (_, _, _, NONE) => (e, st)
|
adamc@1080
|
199 | ECon (dk, pc, cs, SOME e) =>
|
adamc@1080
|
200 let
|
adamc@1080
|
201 val (e, st) = exp (env, e, st)
|
adamc@1080
|
202 in
|
adamc@1080
|
203 ((ECon (dk, pc, cs, SOME e), loc), st)
|
adamc@1080
|
204 end
|
adamc@1080
|
205 | EFfi _ => (e, st)
|
adamc@1080
|
206 | EFfiApp (m, x, es) =>
|
adamc@1080
|
207 let
|
adamc@1080
|
208 val (es, st) = ListUtil.foldlMap (fn (e, st) => exp (env, e, st)) st es
|
adamc@1080
|
209 in
|
adamc@1080
|
210 ((EFfiApp (m, x, es), loc), st)
|
adamc@1080
|
211 end
|
adamc@1080
|
212 | EApp (e1, e2) =>
|
adamc@1080
|
213 let
|
adamc@1080
|
214 val (e1, st) = exp (env, e1, st)
|
adamc@1080
|
215 val (e2, st) = exp (env, e2, st)
|
adamc@1080
|
216 in
|
adamc@1080
|
217 ((EApp (e1, e2), loc), st)
|
adamc@1080
|
218 end
|
adamc@1080
|
219 | EAbs (x, d, r, e) =>
|
adamc@1080
|
220 let
|
adamc@1080
|
221 val (e, st) = exp ((x, d) :: env, e, st)
|
adamc@1080
|
222 in
|
adamc@1080
|
223 ((EAbs (x, d, r, e), loc), st)
|
adamc@1080
|
224 end
|
adamc@1080
|
225 | ECApp (e, c) =>
|
adamc@1080
|
226 let
|
adamc@1080
|
227 val (e, st) = exp (env, e, st)
|
adamc@1080
|
228 in
|
adamc@1080
|
229 ((ECApp (e, c), loc), st)
|
adamc@1080
|
230 end
|
adamc@1181
|
231 | ECAbs (x, k, e) =>
|
adamc@1181
|
232 let
|
adamc@1181
|
233 val (e, st) = exp (env, e, st)
|
adamc@1181
|
234 in
|
adamc@1181
|
235 ((ECAbs (x, k, e), loc), st)
|
adamc@1181
|
236 end
|
adamc@1120
|
237 | EKAbs _ => (e, st)
|
adamc@1080
|
238 | EKApp (e, k) =>
|
adamc@1080
|
239 let
|
adamc@1080
|
240 val (e, st) = exp (env, e, st)
|
adamc@1080
|
241 in
|
adamc@1080
|
242 ((EKApp (e, k), loc), st)
|
adamc@1080
|
243 end
|
adamc@1080
|
244 | ERecord fs =>
|
adamc@1080
|
245 let
|
adamc@1080
|
246 val (fs, st) = ListUtil.foldlMap (fn ((c1, e, c2), st) =>
|
adamc@1080
|
247 let
|
adamc@1080
|
248 val (e, st) = exp (env, e, st)
|
adamc@1080
|
249 in
|
adamc@1080
|
250 ((c1, e, c2), st)
|
adamc@1080
|
251 end) st fs
|
adamc@1080
|
252 in
|
adamc@1080
|
253 ((ERecord fs, loc), st)
|
adamc@1080
|
254 end
|
adamc@1080
|
255 | EField (e, c, cs) =>
|
adamc@1080
|
256 let
|
adamc@1080
|
257 val (e, st) = exp (env, e, st)
|
adamc@1080
|
258 in
|
adamc@1080
|
259 ((EField (e, c, cs), loc), st)
|
adamc@1080
|
260 end
|
adamc@1080
|
261 | EConcat (e1, c1, e2, c2) =>
|
adamc@1080
|
262 let
|
adamc@1080
|
263 val (e1, st) = exp (env, e1, st)
|
adamc@1080
|
264 val (e2, st) = exp (env, e2, st)
|
adamc@1080
|
265 in
|
adamc@1080
|
266 ((EConcat (e1, c1, e2, c2), loc), st)
|
adamc@1080
|
267 end
|
adamc@1080
|
268 | ECut (e, c, cs) =>
|
adamc@1080
|
269 let
|
adamc@1080
|
270 val (e, st) = exp (env, e, st)
|
adamc@1080
|
271 in
|
adamc@1080
|
272 ((ECut (e, c, cs), loc), st)
|
adamc@1080
|
273 end
|
adamc@1080
|
274 | ECutMulti (e, c, cs) =>
|
adamc@1080
|
275 let
|
adamc@1080
|
276 val (e, st) = exp (env, e, st)
|
adamc@1080
|
277 in
|
adamc@1080
|
278 ((ECutMulti (e, c, cs), loc), st)
|
adamc@1080
|
279 end
|
adamc@1080
|
280
|
adamc@1080
|
281 | ECase (e, pes, cs) =>
|
adamc@1080
|
282 let
|
adamc@1080
|
283 val (e, st) = exp (env, e, st)
|
adamc@1080
|
284 val (pes, st) = ListUtil.foldlMap (fn ((p, e), st) =>
|
adamc@1080
|
285 let
|
adamc@1080
|
286 val (e, st) = exp (E.patBindsL p @ env, e, st)
|
adamc@1080
|
287 in
|
adamc@1080
|
288 ((p, e), st)
|
adamc@1080
|
289 end) st pes
|
adamc@1080
|
290 in
|
adamc@1080
|
291 ((ECase (e, pes, cs), loc), st)
|
adamc@1080
|
292 end
|
adamc@1080
|
293
|
adamc@1080
|
294 | EWrite e =>
|
adamc@1080
|
295 let
|
adamc@1080
|
296 val (e, st) = exp (env, e, st)
|
adamc@1080
|
297 in
|
adamc@1080
|
298 ((EWrite e, loc), st)
|
adamc@1080
|
299 end
|
adamc@1080
|
300 | EClosure (n, es) =>
|
adamc@1080
|
301 let
|
adamc@1080
|
302 val (es, st) = ListUtil.foldlMap (fn (e, st) => exp (env, e, st)) st es
|
adamc@1080
|
303 in
|
adamc@1080
|
304 ((EClosure (n, es), loc), st)
|
adamc@1080
|
305 end
|
adamc@1080
|
306 | ELet (x, t, e1, e2) =>
|
adamc@1080
|
307 let
|
adamc@1080
|
308 val (e1, st) = exp (env, e1, st)
|
adamc@1080
|
309 val (e2, st) = exp ((x, t) :: env, e2, st)
|
adamc@1080
|
310 in
|
adamc@1080
|
311 ((ELet (x, t, e1, e2), loc), st)
|
adamc@1080
|
312 end
|
adamc@1080
|
313 | EServerCall (n, es, t) =>
|
adamc@1080
|
314 let
|
adamc@1080
|
315 val (es, st) = ListUtil.foldlMap (fn (e, st) => exp (env, e, st)) st es
|
adamc@1080
|
316 in
|
adamc@1080
|
317 ((EServerCall (n, es, t), loc), st)
|
adamc@1080
|
318 end
|
adamc@482
|
319 in
|
adamc@482
|
320 case getApp e of
|
adamc@1080
|
321 NONE => default ()
|
adamc@488
|
322 | SOME (f, xs) =>
|
adamc@485
|
323 case IM.find (#funcs st, f) of
|
adamc@1080
|
324 NONE => default ()
|
adamc@485
|
325 | SOME {name, args, body, typ, tag} =>
|
adamc@488
|
326 let
|
adamc@1080
|
327 val (xs, st) = ListUtil.foldlMap (fn (e, st) => exp (env, e, st)) st xs
|
adamc@1080
|
328
|
adamc@721
|
329 (*val () = Print.prefaces "Consider" [("e", CorePrint.p_exp CoreEnv.empty
|
adamc@721
|
330 (e, ErrorMsg.dummySpan))]*)
|
adamc@721
|
331
|
adamc@1180
|
332
|
adamc@488
|
333 val loc = ErrorMsg.dummySpan
|
adamc@488
|
334
|
adamc@1080
|
335 fun findSplit av (xs, typ, fxs, fvs, fin) =
|
adamc@488
|
336 case (#1 typ, xs) of
|
adamc@488
|
337 (TFun (dom, ran), e :: xs') =>
|
adamc@1078
|
338 let
|
adamc@1079
|
339 val av = case #1 e of
|
adamc@1079
|
340 ERel _ => av
|
adamc@1079
|
341 | _ => false
|
adamc@1078
|
342 in
|
adamc@1079
|
343 if functionInside dom orelse (av andalso case #1 e of
|
adamc@1079
|
344 ERel _ => true
|
adamc@1079
|
345 | _ => false) then
|
adamc@1079
|
346 findSplit av (xs',
|
adamc@1079
|
347 ran,
|
adamc@1079
|
348 e :: fxs,
|
adamc@1080
|
349 IS.union (fvs, freeVars e),
|
adamc@1080
|
350 fin orelse functionInside dom)
|
adamc@1078
|
351 else
|
adamc@1080
|
352 (rev fxs, xs, fvs, fin)
|
adamc@1078
|
353 end
|
adamc@1080
|
354 | _ => (rev fxs, xs, fvs, fin)
|
adamc@488
|
355
|
adamc@1080
|
356 val (fxs, xs, fvs, fin) = findSplit true (xs, typ, [], IS.empty, false)
|
adamc@1079
|
357
|
adamc@1079
|
358 val fxs' = map (squish (IS.listItems fvs)) fxs
|
adamc@488
|
359 in
|
adamc@800
|
360 (*Print.preface ("fxs'", Print.p_list (CorePrint.p_exp CoreEnv.empty) fxs');*)
|
adamc@1080
|
361 if not fin
|
adamc@1080
|
362 orelse List.all (fn (ERel _, _) => true
|
adamc@1080
|
363 | _ => false) fxs'
|
adamc@1181
|
364 orelse List.exists isOpen fxs'
|
adamc@1079
|
365 orelse (IS.numItems fvs >= length fxs
|
adamc@1079
|
366 andalso IS.exists (fn n => functionInside (#2 (List.nth (env, n)))) fvs) then
|
adamc@1083
|
367 ((*Print.prefaces "No" [("name", Print.PD.string name),
|
adamc@1120
|
368 ("f", Print.PD.string (Int.toString f)),
|
adamc@1180
|
369 ("xs",
|
adamc@1180
|
370 Print.p_list (CorePrint.p_exp CoreEnv.empty) xs),
|
adamc@1083
|
371 ("fxs'",
|
adamc@1083
|
372 Print.p_list (CorePrint.p_exp CoreEnv.empty) fxs')];*)
|
adamc@1083
|
373 default ())
|
adamc@488
|
374 else
|
adamc@1079
|
375 case (KM.find (args, fxs'),
|
adamc@1083
|
376 SS.member (!mayNotSpec, name) (*orelse IS.member (#specialized st, f)*)) of
|
adamc@800
|
377 (SOME f', _) =>
|
adamc@485
|
378 let
|
adamc@488
|
379 val e = (ENamed f', loc)
|
adamc@488
|
380 val e = IS.foldr (fn (arg, e) => (EApp (e, (ERel arg, loc)), loc))
|
adamc@488
|
381 e fvs
|
adamc@1079
|
382 val e = foldl (fn (arg, e) => (EApp (e, arg), loc))
|
adamc@488
|
383 e xs
|
adamc@488
|
384 in
|
adamc@488
|
385 (*Print.prefaces "Brand new (reuse)"
|
adamc@721
|
386 [("e'", CorePrint.p_exp CoreEnv.empty e)];*)
|
adamc@1080
|
387 (e, st)
|
adamc@488
|
388 end
|
adamc@1083
|
389 | (_, true) => ((*Print.prefaces ("No!(" ^ name ^ ")")
|
adamc@818
|
390 [("fxs'",
|
adamc@818
|
391 Print.p_list (CorePrint.p_exp CoreEnv.empty) fxs')];*)
|
adamc@1080
|
392 default ())
|
adamc@800
|
393 | (NONE, false) =>
|
adamc@488
|
394 let
|
adamc@800
|
395 (*val () = Print.prefaces "New one"
|
adamc@800
|
396 [("f", Print.PD.string (Int.toString f)),
|
adamc@800
|
397 ("mns", Print.p_list Print.PD.string
|
adamc@800
|
398 (SS.listItems (!mayNotSpec)))]*)
|
adamc@800
|
399
|
adamc@818
|
400 (*val () = Print.prefaces ("Yes(" ^ name ^ ")")
|
adamc@818
|
401 [("fxs'",
|
adamc@818
|
402 Print.p_list (CorePrint.p_exp CoreEnv.empty) fxs')]*)
|
adamc@818
|
403
|
adamc@1079
|
404 fun subBody (body, typ, fxs') =
|
adamc@1079
|
405 case (#1 body, #1 typ, fxs') of
|
adamc@488
|
406 (_, _, []) => SOME (body, typ)
|
adamc@1079
|
407 | (EAbs (_, _, _, body'), TFun (_, typ'), x :: fxs'') =>
|
adamc@488
|
408 let
|
adamc@1079
|
409 val body'' = E.subExpInExp (0, x) body'
|
adamc@488
|
410 in
|
adamc@488
|
411 subBody (body'',
|
adamc@488
|
412 typ',
|
adamc@1079
|
413 fxs'')
|
adamc@488
|
414 end
|
adamc@488
|
415 | _ => NONE
|
adamc@488
|
416 in
|
adamc@1079
|
417 case subBody (body, typ, fxs') of
|
adamc@1080
|
418 NONE => default ()
|
adamc@488
|
419 | SOME (body', typ') =>
|
adamc@488
|
420 let
|
adamc@488
|
421 val f' = #maxName st
|
adamc@488
|
422 val args = KM.insert (args, fxs', f')
|
adamc@488
|
423 val funcs = IM.insert (#funcs st, f, {name = name,
|
adamc@488
|
424 args = args,
|
adamc@488
|
425 body = body,
|
adamc@488
|
426 typ = typ,
|
adamc@488
|
427 tag = tag})
|
adamc@1079
|
428
|
adamc@488
|
429 val st = {
|
adamc@488
|
430 maxName = f' + 1,
|
adamc@488
|
431 funcs = funcs,
|
adamc@1079
|
432 decls = #decls st,
|
adamc@1080
|
433 specialized = IS.add (#specialized st, f')
|
adamc@488
|
434 }
|
adamc@487
|
435
|
adamc@488
|
436 (*val () = Print.prefaces "specExp"
|
adamc@488
|
437 [("f", CorePrint.p_exp env (ENamed f, loc)),
|
adamc@488
|
438 ("f'", CorePrint.p_exp env (ENamed f', loc)),
|
adamc@488
|
439 ("xs", Print.p_list (CorePrint.p_exp env) xs),
|
adamc@488
|
440 ("fxs'", Print.p_list
|
adamc@488
|
441 (CorePrint.p_exp E.empty) fxs'),
|
adamc@488
|
442 ("e", CorePrint.p_exp env (e, loc))]*)
|
adamc@488
|
443 val (body', typ') = IS.foldl (fn (n, (body', typ')) =>
|
adamc@488
|
444 let
|
adamc@521
|
445 val (x, xt) = List.nth (env, n)
|
adamc@488
|
446 in
|
adamc@488
|
447 ((EAbs (x, xt, typ', body'),
|
adamc@488
|
448 loc),
|
adamc@488
|
449 (TFun (xt, typ'), loc))
|
adamc@488
|
450 end)
|
adamc@488
|
451 (body', typ') fvs
|
adamc@800
|
452 val mns = !mayNotSpec
|
adamc@1080
|
453 (*val () = mayNotSpec := SS.add (mns, name)*)
|
adamc@1080
|
454 (*val () = Print.preface ("PRE", CorePrint.p_exp CoreEnv.empty body')*)
|
adamc@1080
|
455 val (body', st) = exp (env, body', st)
|
adamc@800
|
456 val () = mayNotSpec := mns
|
adamc@482
|
457
|
adamc@488
|
458 val e' = (ENamed f', loc)
|
adamc@488
|
459 val e' = IS.foldr (fn (arg, e) => (EApp (e, (ERel arg, loc)), loc))
|
adamc@488
|
460 e' fvs
|
adamc@1079
|
461 val e' = foldl (fn (arg, e) => (EApp (e, arg), loc))
|
adamc@488
|
462 e' xs
|
adamc@1120
|
463 (*val () = print ("NEW: " ^ name ^ "__" ^ Int.toString f' ^ "\n");*)
|
adamc@488
|
464 (*val () = Print.prefaces "Brand new"
|
adamc@721
|
465 [("e'", CorePrint.p_exp CoreEnv.empty e'),
|
adamc@1080
|
466 ("e", CorePrint.p_exp CoreEnv.empty e),
|
adamc@721
|
467 ("body'", CorePrint.p_exp CoreEnv.empty body')]*)
|
adamc@488
|
468 in
|
adamc@1080
|
469 (e',
|
adamc@488
|
470 {maxName = #maxName st,
|
adamc@488
|
471 funcs = #funcs st,
|
adamc@1079
|
472 decls = (name, f', typ', body', tag) :: #decls st,
|
adamc@1079
|
473 specialized = #specialized st})
|
adamc@488
|
474 end
|
adamc@485
|
475 end
|
adamc@488
|
476 end
|
adamc@485
|
477 end
|
adamc@482
|
478
|
adamc@521
|
479 fun doDecl (d, (st : state, changed)) =
|
adamc@488
|
480 let
|
adamc@521
|
481 (*val befor = Time.now ()*)
|
adamc@482
|
482
|
adamc@453
|
483 val funcs = #funcs st
|
adamc@453
|
484 val funcs =
|
adamc@453
|
485 case #1 d of
|
adamc@453
|
486 DValRec vis =>
|
adamc@453
|
487 foldl (fn ((x, n, c, e, tag), funcs) =>
|
adamc@453
|
488 IM.insert (funcs, n, {name = x,
|
adamc@453
|
489 args = KM.empty,
|
adamc@453
|
490 body = e,
|
adamc@453
|
491 typ = c,
|
adamc@453
|
492 tag = tag}))
|
adamc@453
|
493 funcs vis
|
adamc@453
|
494 | _ => funcs
|
adamc@453
|
495
|
adamc@453
|
496 val st = {maxName = #maxName st,
|
adamc@453
|
497 funcs = funcs,
|
adamc@1079
|
498 decls = [],
|
adamc@1079
|
499 specialized = #specialized st}
|
adamc@453
|
500
|
adamc@482
|
501 (*val () = Print.prefaces "decl" [("d", CorePrint.p_decl CoreEnv.empty d)]*)
|
adamc@521
|
502
|
adamc@1080
|
503 val () = mayNotSpec := SS.empty
|
adamc@1080
|
504
|
adamc@522
|
505 val (d', st) =
|
adamc@522
|
506 if isPoly d then
|
adamc@522
|
507 (d, st)
|
adamc@522
|
508 else
|
adamc@1080
|
509 case #1 d of
|
adamc@1080
|
510 DVal (x, n, t, e, s) =>
|
adamc@1080
|
511 let
|
adamc@1080
|
512 val (e, st) = exp ([], e, st)
|
adamc@1080
|
513 in
|
adamc@1080
|
514 ((DVal (x, n, t, e, s), #2 d), st)
|
adamc@1080
|
515 end
|
adamc@1080
|
516 | DValRec vis =>
|
adamc@1080
|
517 let
|
adamc@1120
|
518 (*val () = Print.preface ("Visiting", Print.p_list (fn vi =>
|
adamc@1120
|
519 Print.PD.string (#1 vi ^ "__"
|
adamc@1120
|
520 ^ Int.toString
|
adamc@1120
|
521 (#2 vi)))
|
adamc@1120
|
522 vis)*)
|
adamc@1120
|
523
|
adamc@1080
|
524 val (vis, st) = ListUtil.foldlMap (fn ((x, n, t, e, s), st) =>
|
adamc@1080
|
525 let
|
adamc@1120
|
526 val () = mayNotSpec := SS.empty
|
adamc@1080
|
527 val (e, st) = exp ([], e, st)
|
adamc@1080
|
528 in
|
adamc@1080
|
529 ((x, n, t, e, s), st)
|
adamc@1080
|
530 end) st vis
|
adamc@1080
|
531 in
|
adamc@1080
|
532 ((DValRec vis, #2 d), st)
|
adamc@1080
|
533 end
|
adamc@1080
|
534 | DTable (s, n, t, s1, e1, t1, e2, t2) =>
|
adamc@1080
|
535 let
|
adamc@1080
|
536 val (e1, st) = exp ([], e1, st)
|
adamc@1080
|
537 val (e2, st) = exp ([], e2, st)
|
adamc@1080
|
538 in
|
adamc@1080
|
539 ((DTable (s, n, t, s1, e1, t2, e2, t2), #2 d), st)
|
adamc@1080
|
540 end
|
adamc@1080
|
541 | DView (x, n, s, e, t) =>
|
adamc@1080
|
542 let
|
adamc@1080
|
543 val (e, st) = exp ([], e, st)
|
adamc@1080
|
544 in
|
adamc@1080
|
545 ((DView (x, n, s, e, t), #2 d), st)
|
adamc@1080
|
546 end
|
adamc@1080
|
547 | DTask (e1, e2) =>
|
adamc@1080
|
548 let
|
adamc@1080
|
549 val (e1, st) = exp ([], e1, st)
|
adamc@1080
|
550 val (e2, st) = exp ([], e2, st)
|
adamc@1080
|
551 in
|
adamc@1080
|
552 ((DTask (e1, e2), #2 d), st)
|
adamc@1080
|
553 end
|
adamc@1080
|
554 | _ => (d, st)
|
adamc@1080
|
555
|
adamc@1080
|
556 val () = mayNotSpec := SS.empty
|
adamc@521
|
557
|
adamc@482
|
558 (*val () = print "/decl\n"*)
|
adamc@443
|
559
|
adamc@443
|
560 val funcs = #funcs st
|
adamc@443
|
561 val funcs =
|
adamc@443
|
562 case #1 d of
|
adamc@443
|
563 DVal (x, n, c, e as (EAbs _, _), tag) =>
|
adamc@443
|
564 IM.insert (funcs, n, {name = x,
|
adamc@453
|
565 args = KM.empty,
|
adamc@443
|
566 body = e,
|
adamc@443
|
567 typ = c,
|
adamc@443
|
568 tag = tag})
|
adamc@469
|
569 | DVal (_, n, _, (ENamed n', _), _) =>
|
adamc@469
|
570 (case IM.find (funcs, n') of
|
adamc@469
|
571 NONE => funcs
|
adamc@469
|
572 | SOME v => IM.insert (funcs, n, v))
|
adamc@443
|
573 | _ => funcs
|
adamc@443
|
574
|
adamc@453
|
575 val (changed, ds) =
|
adamc@443
|
576 case #decls st of
|
adamc@453
|
577 [] => (changed, [d'])
|
adamc@453
|
578 | vis =>
|
adamc@453
|
579 (true, case d' of
|
adamc@453
|
580 (DValRec vis', _) => [(DValRec (vis @ vis'), ErrorMsg.dummySpan)]
|
adamc@453
|
581 | _ => [(DValRec vis, ErrorMsg.dummySpan), d'])
|
adamc@443
|
582 in
|
adamc@802
|
583 (*Print.prefaces "doDecl" [("d", CorePrint.p_decl E.empty d),
|
adamc@802
|
584 ("d'", CorePrint.p_decl E.empty d')];*)
|
adamc@521
|
585 (ds, ({maxName = #maxName st,
|
adamc@453
|
586 funcs = funcs,
|
adamc@1079
|
587 decls = [],
|
adamc@1079
|
588 specialized = #specialized st}, changed))
|
adamc@443
|
589 end
|
adamc@443
|
590
|
adamc@1120
|
591 (*val () = Print.preface ("RESET", CorePrint.p_file CoreEnv.empty file)*)
|
adamc@1079
|
592 val (ds, (st, changed)) = ListUtil.foldlMapConcat doDecl
|
adamc@521
|
593 ({maxName = U.File.maxName file + 1,
|
adamc@1080
|
594 funcs = funcs,
|
adamc@1079
|
595 decls = [],
|
adamc@1079
|
596 specialized = specialized},
|
adamc@488
|
597 false)
|
adamc@488
|
598 file
|
adamc@443
|
599 in
|
adamc@1120
|
600 (*print ("Changed = " ^ Bool.toString changed ^ "\n");*)
|
adamc@1080
|
601 (changed, ds, #funcs st, #specialized st)
|
adamc@443
|
602 end
|
adamc@443
|
603
|
adamc@1080
|
604 fun specializeL (funcs, specialized) file =
|
adamc@453
|
605 let
|
adamc@721
|
606 val file = ReduceLocal.reduce file
|
adamc@520
|
607 (*val file = ReduceLocal.reduce file*)
|
adamc@1080
|
608 val (changed, file, funcs, specialized) = specialize' (funcs, specialized) file
|
adamc@520
|
609 (*val file = ReduceLocal.reduce file
|
adamc@520
|
610 val file = CoreUntangle.untangle file
|
adamc@488
|
611 val file = Shake.shake file*)
|
adamc@453
|
612 in
|
adamc@488
|
613 (*print "Round over\n";*)
|
adamc@453
|
614 if changed then
|
adamc@520
|
615 let
|
adamc@721
|
616 (*val file = ReduceLocal.reduce file*)
|
adamc@802
|
617 (*val () = Print.prefaces "Pre-untangle" [("file", CorePrint.p_file CoreEnv.empty file)]*)
|
adamc@520
|
618 val file = CoreUntangle.untangle file
|
adamc@802
|
619 (*val () = Print.prefaces "Post-untangle" [("file", CorePrint.p_file CoreEnv.empty file)]*)
|
adamc@520
|
620 val file = Shake.shake file
|
adamc@520
|
621 in
|
adamc@520
|
622 (*print "Again!\n";*)
|
adamc@1080
|
623 (*Print.prefaces "Again" [("file", CorePrint.p_file CoreEnv.empty file)];*)
|
adamc@1080
|
624 specializeL (funcs, specialized) file
|
adamc@520
|
625 end
|
adamc@453
|
626 else
|
adamc@453
|
627 file
|
adamc@453
|
628 end
|
adamc@453
|
629
|
adamc@1080
|
630 val specialize = specializeL (IM.empty, IS.empty)
|
adamc@1079
|
631
|
adamc@443
|
632 end
|