Mercurial > urweb
comparison src/especialize.sml @ 488:5521bb0b4014
Get preliminary ThreadedBlog working
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Tue, 11 Nov 2008 15:12:24 -0500 |
parents | 33d5bd69da00 |
children | 3f20c22098af |
comparison
equal
deleted
inserted
replaced
487:33d5bd69da00 | 488:5521bb0b4014 |
---|---|
41 | 41 |
42 structure KM = BinaryMapFn(K) | 42 structure KM = BinaryMapFn(K) |
43 structure IM = IntBinaryMap | 43 structure IM = IntBinaryMap |
44 structure IS = IntBinarySet | 44 structure IS = IntBinarySet |
45 | 45 |
46 val sizeOf = U.Exp.fold {kind = fn (_, n) => n, | 46 val freeVars = U.Exp.foldB {kind = fn (_, xs) => xs, |
47 con = fn (_, n) => n, | 47 con = fn (_, _, xs) => xs, |
48 exp = fn (_, n) => n + 1} | 48 exp = fn (bound, e, xs) => |
49 0 | |
50 | |
51 val isOpen = U.Exp.existsB {kind = fn _ => false, | |
52 con = fn ((nc, _), c) => | |
53 case c of | |
54 CRel n => n >= nc | |
55 | _ => false, | |
56 exp = fn ((_, ne), e) => | |
57 case e of | 49 case e of |
58 ERel n => n >= ne | 50 ERel x => |
59 | _ => false, | 51 if x >= bound then |
60 bind = fn ((nc, ne), b) => | 52 IS.add (xs, x - bound) |
53 else | |
54 xs | |
55 | _ => xs, | |
56 bind = fn (bound, b) => | |
61 case b of | 57 case b of |
62 U.Exp.RelC _ => (nc + 1, ne) | 58 U.Exp.RelE _ => bound + 1 |
63 | U.Exp.RelE _ => (nc, ne + 1) | 59 | _ => bound} |
64 | _ => (nc, ne)} | 60 0 IS.empty |
65 (0, 0) | 61 |
66 | 62 fun positionOf (v : int, ls) = |
67 fun baseBad (e, _) = | 63 let |
68 case e of | 64 fun pof (pos, ls) = |
69 EAbs (_, _, _, e) => sizeOf e > 20 | 65 case ls of |
70 | ENamed _ => false | 66 [] => raise Fail "Defunc.positionOf" |
71 | _ => true | 67 | v' :: ls' => |
72 | 68 if v = v' then |
73 fun isBad e = | 69 pos |
74 case e of | 70 else |
75 (ERecord xes, _) => | 71 pof (pos + 1, ls') |
76 length xes > 10 | 72 in |
77 orelse List.exists (fn (_, e, _) => baseBad e) xes | 73 pof (0, ls) |
78 | _ => baseBad e | 74 end |
79 | 75 |
80 fun skeyIn e = | 76 fun squish fvs = |
81 if isBad e orelse isOpen e then | 77 U.Exp.mapB {kind = fn k => k, |
82 NONE | 78 con = fn _ => fn c => c, |
83 else | 79 exp = fn bound => fn e => |
84 SOME e | 80 case e of |
85 | 81 ERel x => |
86 fun skeyOut e = e | 82 if x >= bound then |
83 ERel (positionOf (x - bound, fvs) + bound) | |
84 else | |
85 e | |
86 | _ => e, | |
87 bind = fn (bound, b) => | |
88 case b of | |
89 U.Exp.RelE _ => bound + 1 | |
90 | _ => bound} | |
91 0 | |
87 | 92 |
88 type func = { | 93 type func = { |
89 name : string, | 94 name : string, |
90 args : int KM.map, | 95 args : int KM.map, |
91 body : exp, | 96 body : exp, |
97 maxName : int, | 102 maxName : int, |
98 funcs : func IM.map, | 103 funcs : func IM.map, |
99 decls : (string * int * con * exp * string) list | 104 decls : (string * int * con * exp * string) list |
100 } | 105 } |
101 | 106 |
102 fun kind (k, st) = (k, st) | 107 fun kind x = x |
103 fun con (c, st) = (c, st) | 108 fun default (_, x, st) = (x, st) |
104 | 109 |
105 fun specialize' file = | 110 fun specialize' file = |
106 let | 111 let |
107 fun default (_, fs) = fs | 112 fun default' (_, fs) = fs |
108 | 113 |
109 fun actionableExp (e, fs) = | 114 fun actionableExp (e, fs) = |
110 case e of | 115 case e of |
111 ERecord xes => | 116 ERecord xes => |
112 foldl (fn (((CName s, _), e, _), fs) => | 117 foldl (fn (((CName s, _), e, _), fs) => |
125 | (_, fs) => fs) | 130 | (_, fs) => fs) |
126 fs xes | 131 fs xes |
127 | _ => fs | 132 | _ => fs |
128 | 133 |
129 val actionable = | 134 val actionable = |
130 U.File.fold {kind = default, | 135 U.File.fold {kind = default', |
131 con = default, | 136 con = default', |
132 exp = actionableExp, | 137 exp = actionableExp, |
133 decl = default} | 138 decl = default'} |
134 IS.empty file | 139 IS.empty file |
135 | 140 |
136 fun exp (e, st : state) = | 141 fun bind (env, b) = |
142 case b of | |
143 U.Decl.RelC (x, k) => E.pushCRel env x k | |
144 | U.Decl.NamedC (x, n, k, co) => E.pushCNamed env x n k co | |
145 | U.Decl.RelE (x, t) => E.pushERel env x t | |
146 | U.Decl.NamedE (x, n, t, eo, s) => E.pushENamed env x n t eo s | |
147 | |
148 fun exp (env, e, st : state) = | |
137 let | 149 let |
138 fun getApp' e = | 150 fun getApp e = |
139 case e of | 151 case e of |
140 ENamed f => SOME (f, [], []) | 152 ENamed f => SOME (f, []) |
141 | EApp (e1, e2) => | 153 | EApp (e1, e2) => |
142 (case getApp' (#1 e1) of | 154 (case getApp (#1 e1) of |
143 NONE => NONE | 155 NONE => NONE |
144 | SOME (f, xs, xs') => | 156 | SOME (f, xs) => SOME (f, xs @ [e2])) |
145 let | |
146 val k = | |
147 if List.null xs' then | |
148 skeyIn e2 | |
149 else | |
150 NONE | |
151 in | |
152 case k of | |
153 NONE => SOME (f, xs, xs' @ [e2]) | |
154 | SOME k => SOME (f, xs @ [k], xs') | |
155 end) | |
156 | _ => NONE | 157 | _ => NONE |
157 | |
158 fun getApp e = | |
159 case getApp' e of | |
160 NONE => NONE | |
161 | SOME (f, xs, xs') => | |
162 if List.all (fn (ERecord [], _) => true | _ => false) xs then | |
163 SOME (f, [], xs @ xs') | |
164 else | |
165 SOME (f, xs, xs') | |
166 in | 158 in |
167 case getApp e of | 159 case getApp e of |
168 NONE => (e, st) | 160 NONE => (e, st) |
169 | SOME (f, [], []) => (e, st) | 161 | SOME (f, xs) => |
170 | SOME (f, [], xs') => | |
171 (case IM.find (#funcs st, f) of | |
172 NONE => (e, st) | |
173 | SOME {typ, body, ...} => | |
174 let | |
175 val functionInside = U.Con.exists {kind = fn _ => false, | |
176 con = fn TFun _ => true | |
177 | CFfi ("Basis", "transaction") => true | |
178 | _ => false} | |
179 | |
180 fun hasFunarg (t, xs) = | |
181 case (t, xs) of | |
182 ((TFun (dom, ran), _), _ :: xs) => | |
183 functionInside dom | |
184 orelse hasFunarg (ran, xs) | |
185 | _ => false | |
186 in | |
187 if List.all (fn (ERel _, _) => false | _ => true) xs' | |
188 andalso List.exists (fn (ERecord [], _) => false | _ => true) xs' | |
189 andalso not (IS.member (actionable, f)) | |
190 andalso hasFunarg (typ, xs') then | |
191 let | |
192 val e = foldl (fn (arg, e) => (EApp (e, arg), ErrorMsg.dummySpan)) | |
193 body xs' | |
194 in | |
195 (*Print.prefaces "Unfolded" | |
196 [("e", CorePrint.p_exp CoreEnv.empty e)];*) | |
197 (#1 e, st) | |
198 end | |
199 else | |
200 (e, st) | |
201 end) | |
202 | SOME (f, xs, xs') => | |
203 case IM.find (#funcs st, f) of | 162 case IM.find (#funcs st, f) of |
204 NONE => (e, st) | 163 NONE => (e, st) |
205 | SOME {name, args, body, typ, tag} => | 164 | SOME {name, args, body, typ, tag} => |
206 case KM.find (args, xs) of | 165 let |
207 SOME f' => (#1 (foldl (fn (arg, e) => (EApp (e, arg), ErrorMsg.dummySpan)) | 166 val functionInside = U.Con.exists {kind = fn _ => false, |
208 (ENamed f', ErrorMsg.dummySpan) xs'), | 167 con = fn TFun _ => true |
209 st) | 168 | CFfi ("Basis", "transaction") => true |
210 | NONE => | 169 | _ => false} |
211 let | 170 val loc = ErrorMsg.dummySpan |
212 fun subBody (body, typ, xs) = | 171 |
213 case (#1 body, #1 typ, xs) of | 172 fun findSplit (xs, typ, fxs, fvs) = |
214 (_, _, []) => SOME (body, typ) | 173 case (#1 typ, xs) of |
215 | (EAbs (_, _, _, body'), TFun (_, typ'), x :: xs) => | 174 (TFun (dom, ran), e :: xs') => |
216 let | 175 if functionInside dom then |
217 val body'' = E.subExpInExp (0, skeyOut x) body' | 176 findSplit (xs', |
218 in | 177 ran, |
219 subBody (body'', | 178 e :: fxs, |
220 typ', | 179 IS.union (fvs, freeVars e)) |
221 xs) | 180 else |
222 end | 181 (rev fxs, xs, fvs) |
223 | _ => NONE | 182 | _ => (rev fxs, xs, fvs) |
224 in | 183 |
225 case subBody (body, typ, xs) of | 184 val (fxs, xs, fvs) = findSplit (xs, typ, [], IS.empty) |
226 NONE => (e, st) | 185 |
227 | SOME (body', typ') => | 186 val fxs' = map (squish (IS.listItems fvs)) fxs |
187 | |
188 fun firstRel () = | |
189 case fxs' of | |
190 (ERel _, _) :: _ => true | |
191 | _ => false | |
192 in | |
193 if firstRel () | |
194 orelse List.all (fn (ERel _, _) => true | |
195 | _ => false) fxs' then | |
196 (e, st) | |
197 else | |
198 case KM.find (args, fxs') of | |
199 SOME f' => | |
228 let | 200 let |
229 (*val () = Print.prefaces "sub'd" | 201 val e = (ENamed f', loc) |
230 [("body'", CorePrint.p_exp CoreEnv.empty body')]*) | 202 val e = IS.foldr (fn (arg, e) => (EApp (e, (ERel arg, loc)), loc)) |
231 | 203 e fvs |
232 val f' = #maxName st | 204 val e = foldl (fn (arg, e) => (EApp (e, arg), loc)) |
233 val funcs = IM.insert (#funcs st, f, {name = name, | 205 e xs |
234 args = KM.insert (args, | |
235 xs, f'), | |
236 body = body, | |
237 typ = typ, | |
238 tag = tag}) | |
239 val st = { | |
240 maxName = f' + 1, | |
241 funcs = funcs, | |
242 decls = #decls st | |
243 } | |
244 | |
245 (*val () = print ("Created " ^ Int.toString f' ^ " from " | |
246 ^ Int.toString f ^ "\n") | |
247 val () = Print.prefaces "body'" | |
248 [("body'", CorePrint.p_exp CoreEnv.empty body')]*) | |
249 val (body', st) = specExp st body' | |
250 (*val () = Print.prefaces "body''" | |
251 [("body'", CorePrint.p_exp CoreEnv.empty body')]*) | |
252 val e' = foldl (fn (arg, e) => (EApp (e, arg), ErrorMsg.dummySpan)) | |
253 (ENamed f', ErrorMsg.dummySpan) xs' | |
254 in | 206 in |
255 (#1 e', | 207 (*Print.prefaces "Brand new (reuse)" |
256 {maxName = #maxName st, | 208 [("e'", CorePrint.p_exp env e)];*) |
257 funcs = #funcs st, | 209 (#1 e, st) |
258 decls = (name, f', typ', body', tag) :: #decls st}) | |
259 end | 210 end |
260 end | 211 | NONE => |
212 let | |
213 fun subBody (body, typ, fxs') = | |
214 case (#1 body, #1 typ, fxs') of | |
215 (_, _, []) => SOME (body, typ) | |
216 | (EAbs (_, _, _, body'), TFun (_, typ'), x :: fxs'') => | |
217 let | |
218 val body'' = E.subExpInExp (0, x) body' | |
219 in | |
220 subBody (body'', | |
221 typ', | |
222 fxs'') | |
223 end | |
224 | _ => NONE | |
225 in | |
226 case subBody (body, typ, fxs') of | |
227 NONE => (e, st) | |
228 | SOME (body', typ') => | |
229 let | |
230 val f' = #maxName st | |
231 val args = KM.insert (args, fxs', f') | |
232 val funcs = IM.insert (#funcs st, f, {name = name, | |
233 args = args, | |
234 body = body, | |
235 typ = typ, | |
236 tag = tag}) | |
237 val st = { | |
238 maxName = f' + 1, | |
239 funcs = funcs, | |
240 decls = #decls st | |
241 } | |
242 | |
243 (*val () = Print.prefaces "specExp" | |
244 [("f", CorePrint.p_exp env (ENamed f, loc)), | |
245 ("f'", CorePrint.p_exp env (ENamed f', loc)), | |
246 ("xs", Print.p_list (CorePrint.p_exp env) xs), | |
247 ("fxs'", Print.p_list | |
248 (CorePrint.p_exp E.empty) fxs'), | |
249 ("e", CorePrint.p_exp env (e, loc))]*) | |
250 val (body', typ') = IS.foldl (fn (n, (body', typ')) => | |
251 let | |
252 val (x, xt) = E.lookupERel env n | |
253 in | |
254 ((EAbs (x, xt, typ', body'), | |
255 loc), | |
256 (TFun (xt, typ'), loc)) | |
257 end) | |
258 (body', typ') fvs | |
259 val (body', st) = specExp env st body' | |
260 | |
261 val e' = (ENamed f', loc) | |
262 val e' = IS.foldr (fn (arg, e) => (EApp (e, (ERel arg, loc)), loc)) | |
263 e' fvs | |
264 val e' = foldl (fn (arg, e) => (EApp (e, arg), loc)) | |
265 e' xs | |
266 (*val () = Print.prefaces "Brand new" | |
267 [("e'", CorePrint.p_exp env e'), | |
268 ("e", CorePrint.p_exp env (e, loc)), | |
269 ("body'", CorePrint.p_exp env body')]*) | |
270 in | |
271 (#1 e', | |
272 {maxName = #maxName st, | |
273 funcs = #funcs st, | |
274 decls = (name, f', typ', body', tag) :: #decls st}) | |
275 end | |
276 end | |
277 end | |
261 end | 278 end |
262 | 279 |
263 and specExp st = U.Exp.foldMap {kind = kind, con = con, exp = exp} st | 280 and specExp env = U.Exp.foldMapB {kind = kind, con = default, exp = exp, bind = bind} env |
264 | 281 |
265 fun decl (d, st) = (d, st) | 282 val specDecl = U.Decl.foldMapB {kind = kind, con = default, exp = exp, decl = default, bind = bind} |
266 | 283 |
267 val specDecl = U.Decl.foldMap {kind = kind, con = con, exp = exp, decl = decl} | 284 fun doDecl (d, (env, st : state, changed)) = |
268 | |
269 | |
270 | |
271 fun doDecl (d, (st : state, changed)) = | |
272 let | 285 let |
286 val env = E.declBinds env d | |
287 | |
273 val funcs = #funcs st | 288 val funcs = #funcs st |
274 val funcs = | 289 val funcs = |
275 case #1 d of | 290 case #1 d of |
276 DValRec vis => | 291 DValRec vis => |
277 foldl (fn ((x, n, c, e, tag), funcs) => | 292 foldl (fn ((x, n, c, e, tag), funcs) => |
286 val st = {maxName = #maxName st, | 301 val st = {maxName = #maxName st, |
287 funcs = funcs, | 302 funcs = funcs, |
288 decls = []} | 303 decls = []} |
289 | 304 |
290 (*val () = Print.prefaces "decl" [("d", CorePrint.p_decl CoreEnv.empty d)]*) | 305 (*val () = Print.prefaces "decl" [("d", CorePrint.p_decl CoreEnv.empty d)]*) |
291 val (d', st) = specDecl st d | 306 val (d', st) = specDecl env st d |
292 (*val () = print "/decl\n"*) | 307 (*val () = print "/decl\n"*) |
293 | 308 |
294 val funcs = #funcs st | 309 val funcs = #funcs st |
295 val funcs = | 310 val funcs = |
296 case #1 d of | 311 case #1 d of |
312 | vis => | 327 | vis => |
313 (true, case d' of | 328 (true, case d' of |
314 (DValRec vis', _) => [(DValRec (vis @ vis'), ErrorMsg.dummySpan)] | 329 (DValRec vis', _) => [(DValRec (vis @ vis'), ErrorMsg.dummySpan)] |
315 | _ => [(DValRec vis, ErrorMsg.dummySpan), d']) | 330 | _ => [(DValRec vis, ErrorMsg.dummySpan), d']) |
316 in | 331 in |
317 (ds, ({maxName = #maxName st, | 332 (ds, (env, |
333 {maxName = #maxName st, | |
318 funcs = funcs, | 334 funcs = funcs, |
319 decls = []}, changed)) | 335 decls = []}, changed)) |
320 end | 336 end |
321 | 337 |
322 val (ds, (_, changed)) = ListUtil.foldlMapConcat doDecl | 338 val (ds, (_, _, changed)) = ListUtil.foldlMapConcat doDecl |
323 ({maxName = U.File.maxName file + 1, | 339 (E.empty, |
324 funcs = IM.empty, | 340 {maxName = U.File.maxName file + 1, |
325 decls = []}, false) | 341 funcs = IM.empty, |
326 file | 342 decls = []}, |
343 false) | |
344 file | |
327 in | 345 in |
328 (changed, ds) | 346 (changed, ds) |
329 end | 347 end |
330 | 348 |
331 fun specialize file = | 349 fun specialize file = |
332 let | 350 let |
333 (*val () = Print.prefaces "Intermediate" [("file", CorePrint.p_file CoreEnv.empty file)];*) | 351 (*val () = Print.prefaces "Intermediate" [("file", CorePrint.p_file CoreEnv.empty file)];*) |
352 val file = ReduceLocal.reduce file | |
334 val (changed, file) = specialize' file | 353 val (changed, file) = specialize' file |
354 val file = ReduceLocal.reduce file | |
355 (*val file = CoreUntangle.untangle file | |
356 val file = Shake.shake file*) | |
335 in | 357 in |
358 (*print "Round over\n";*) | |
336 if changed then | 359 if changed then |
337 specialize (ReduceLocal.reduce file) | 360 specialize file |
338 else | 361 else |
339 file | 362 file |
340 end | 363 end |
341 | 364 |
342 end | 365 end |