annotate src/especialize.sml @ 1183:9d3ccb8b39ac

safeGet
author Adam Chlipala <adamc@hcoop.net>
date Tue, 09 Mar 2010 18:28:44 -0500
parents 618f9f458da9
children 338be96f8533
rev   line source
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