comparison src/monoize.sml @ 1287:5137b0537c92

Polymorphic variants
author Adam Chlipala <adam@chlipala.net>
date Thu, 19 Aug 2010 17:28:52 -0400
parents a9a500d22ebc
children fc7ecf8883b1
comparison
equal deleted inserted replaced
1286:829da30fb808 1287:5137b0537c92
34 structure L' = Mono 34 structure L' = Mono
35 35
36 structure IM = IntBinaryMap 36 structure IM = IntBinaryMap
37 structure IS = IntBinarySet 37 structure IS = IntBinarySet
38 38
39 structure SS = BinarySetFn(struct 39 structure SK = struct
40 type ord_key = string 40 type ord_key = string
41 val compare = String.compare 41 val compare = String.compare
42 end
43
44 structure SS = BinarySetFn(SK)
45 structure SM = BinaryMapFn(SK)
46
47 structure RM = BinaryMapFn(struct
48 type ord_key = (string * L'.typ) list
49 fun compare (r1, r2) = MonoUtil.Typ.compare ((L'.TRecord r1, E.dummySpan),
50 (L'.TRecord r2, E.dummySpan))
42 end) 51 end)
52
53 val nextPvar = ref 0
54 val pvars = ref (RM.empty : (int * (string * int * L'.typ) list) RM.map)
55 val pvarDefs = ref ([] : L'.decl list)
56
57 fun choosePvar () =
58 let
59 val n = !nextPvar
60 in
61 nextPvar := n + 1;
62 n
63 end
64
65 fun pvar (r, loc) =
66 case RM.find (!pvars, r) of
67 NONE =>
68 let
69 val n = choosePvar ()
70 val fs = map (fn (x, t) => (x, choosePvar (), t)) r
71 val fs' = foldl (fn ((x, n, _), fs') => SM.insert (fs', x, n)) SM.empty fs
72 in
73 pvars := RM.insert (!pvars, r, (n, fs));
74 pvarDefs := (L'.DDatatype [("$poly" ^ Int.toString n, n, map (fn (x, n, t) => (x, n, SOME t)) fs)], loc)
75 :: !pvarDefs;
76 (n, fs)
77 end
78 | SOME v => v
43 79
44 val singletons = SS.addList (SS.empty, 80 val singletons = SS.addList (SS.empty,
45 ["link", 81 ["link",
46 "br", 82 "br",
47 "p", 83 "p",
117 153
118 | L.CApp ((L.CFfi ("Basis", "option"), _), t) => 154 | L.CApp ((L.CFfi ("Basis", "option"), _), t) =>
119 (L'.TOption (mt env dtmap t), loc) 155 (L'.TOption (mt env dtmap t), loc)
120 | L.CApp ((L.CFfi ("Basis", "list"), _), t) => 156 | L.CApp ((L.CFfi ("Basis", "list"), _), t) =>
121 (L'.TList (mt env dtmap t), loc) 157 (L'.TList (mt env dtmap t), loc)
158
159 | L.CApp ((L.CFfi ("Basis", "variant"), _), (L.CRecord ((L.KType, _), xts), _)) =>
160 let
161 val xts = map (fn (x, t) => (monoName env x, mt env dtmap t)) xts
162 val xts = ListMergeSort.sort (fn ((x, _), (y, _)) => String.compare (x, y) = GREATER) xts
163 val (n, cs) = pvar (xts, loc)
164 val cs = map (fn (x, n, t) => (x, n, SOME t)) cs
165 in
166 (L'.TDatatype (n, ref (ElabUtil.classifyDatatype cs, cs)), loc)
167 end
122 168
123 | L.CApp ((L.CFfi ("Basis", "monad"), _), _) => 169 | L.CApp ((L.CFfi ("Basis", "monad"), _), _) =>
124 (L'.TRecord [], loc) 170 (L'.TRecord [], loc)
125 171
126 | L.CApp ((L.CFfi ("Basis", "eq"), _), t) => 172 | L.CApp ((L.CFfi ("Basis", "eq"), _), t) =>
346 map = M.empty, 392 map = M.empty,
347 listMap = M.empty, 393 listMap = M.empty,
348 decls = [] 394 decls = []
349 } 395 }
350 396
397 fun chooseNext count =
398 let
399 val n = !nextPvar
400 in
401 if count < n then
402 (count, count+1)
403 else
404 (nextPvar := n + 1;
405 (n, n+1))
406 end
407
351 fun enter ({count, map, listMap, ...} : t) = {count = count, map = map, listMap = listMap, decls = []} 408 fun enter ({count, map, listMap, ...} : t) = {count = count, map = map, listMap = listMap, decls = []}
352 fun freshName {count, map, listMap, decls} = (count, {count = count + 1, map = map, listMap = listMap, decls = decls}) 409 fun freshName {count, map, listMap, decls} =
410 let
411 val (next, count) = chooseNext count
412 in
413 (next, {count = count , map = map, listMap = listMap, decls = decls})
414 end
353 fun decls ({decls, ...} : t) = decls 415 fun decls ({decls, ...} : t) = decls
354 416
355 fun lookup (t as {count, map, listMap, decls}) k n thunk = 417 fun lookup (t as {count, map, listMap, decls}) k n thunk =
356 let 418 let
357 val im = Option.getOpt (M.find (map, k), IM.empty) 419 val im = Option.getOpt (M.find (map, k), IM.empty)
749 val (e, fm) = monoExp (env, st, fm) e 811 val (e, fm) = monoExp (env, st, fm) e
750 in 812 in
751 ((L'.ESome (monoType env t, e), loc), fm) 813 ((L'.ESome (monoType env t, e), loc), fm)
752 end 814 end
753 | L.ECon _ => poly () 815 | L.ECon _ => poly ()
816
817 | L.ECApp (
818 (L.ECApp (
819 (L.ECApp ((L.EFfi ("Basis", "make"), _), (L.CName nm, _)), _),
820 t), _),
821 (L.CRecord (_, xts), _)) =>
822 let
823 val t = monoType env t
824 val xts = map (fn (x, t) => (monoName env x, monoType env t)) xts
825 val xts = (nm, t) :: xts
826 val xts = ListMergeSort.sort (fn ((x, _), (y, _)) => String.compare (x, y) = GREATER) xts
827 val (n, cs) = pvar (xts, loc)
828 val cs' = map (fn (x, n, t) => (x, n, SOME t)) cs
829 val cl = ElabUtil.classifyDatatype cs'
830 in
831 case List.find (fn (nm', _, _) => nm' = nm) cs of
832 NONE => raise Fail "Monoize: Polymorphic variant tag mismatch for 'make'"
833 | SOME (_, n', _) => ((L'.EAbs ("x", t, (L'.TDatatype (n, ref (cl, cs')), loc),
834 (L'.ECon (cl, L'.PConVar n', SOME (L'.ERel 0, loc)), loc)), loc),
835 fm)
836 end
837
838 | L.ECApp (
839 (L.ECApp ((L.EFfi ("Basis", "match"), _), (L.CRecord (_, xts), _)), _),
840 t) =>
841 let
842 val t = monoType env t
843 val xts = map (fn (x, t) => (monoName env x, monoType env t)) xts
844 val xts = ListMergeSort.sort (fn ((x, _), (y, _)) => String.compare (x, y) = GREATER) xts
845 val (n, cs) = pvar (xts, loc)
846 val cs' = map (fn (x, n, t) => (x, n, SOME t)) cs
847 val cl = ElabUtil.classifyDatatype cs'
848 val fs = (L'.TRecord (map (fn (x, t') => (x, (L'.TFun (t', t), loc))) xts), loc)
849 val dt = (L'.TDatatype (n, ref (cl, cs')), loc)
850 in
851 ((L'.EAbs ("v",
852 dt,
853 (L'.TFun (fs, t), loc),
854 (L'.EAbs ("fs", fs, t,
855 (L'.ECase ((L'.ERel 1, loc),
856 map (fn (x, n', t') =>
857 ((L'.PCon (cl, L'.PConVar n', SOME (L'.PVar ("x", t'), loc)), loc),
858 (L'.EApp ((L'.EField ((L'.ERel 1, loc), x), loc),
859 (L'.ERel 0, loc)), loc))) cs,
860 {disc = dt, result = t}), loc)), loc)), loc),
861 fm)
862 end
754 863
755 | L.ECApp ((L.EFfi ("Basis", "eq"), _), t) => 864 | L.ECApp ((L.EFfi ("Basis", "eq"), _), t) =>
756 let 865 let
757 val t = monoType env t 866 val t = monoType env t
758 val b = (L'.TFfi ("Basis", "bool"), loc) 867 val b = (L'.TFfi ("Basis", "bool"), loc)
3819 3928
3820 datatype expungable = Client | Channel 3929 datatype expungable = Client | Channel
3821 3930
3822 fun monoize env file = 3931 fun monoize env file =
3823 let 3932 let
3933 val () = pvars := RM.empty
3934
3824 (* Calculate which exported functions need cookie signature protection *) 3935 (* Calculate which exported functions need cookie signature protection *)
3825 val rcook = foldl (fn ((d, _), rcook) => 3936 val rcook = foldl (fn ((d, _), rcook) =>
3826 case d of 3937 case d of
3827 L.DExport (L.Action L.ReadCookieWrite, n, _) => IS.add (rcook, n) 3938 L.DExport (L.Action L.ReadCookieWrite, n, _) => IS.add (rcook, n)
3828 | L.DExport (L.Rpc L.ReadCookieWrite, n, _) => IS.add (rcook, n) 3939 | L.DExport (L.Rpc L.ReadCookieWrite, n, _) => IS.add (rcook, n)
3955 foldl (fn ((d, _), e) => 4066 foldl (fn ((d, _), e) =>
3956 case d of 4067 case d of
3957 L.DTable (_, _, xts, tab, _, _, _, _) => doTable (tab, #1 xts, e) 4068 L.DTable (_, _, xts, tab, _, _, _, _) => doTable (tab, #1 xts, e)
3958 | _ => e) e file 4069 | _ => e) e file
3959 end 4070 end
4071
4072 val mname = CoreUtil.File.maxName file + 1
4073 val () = nextPvar := mname
3960 4074
3961 val (_, _, ds) = List.foldl (fn (d, (env, fm, ds)) => 4075 val (_, _, ds) = List.foldl (fn (d, (env, fm, ds)) =>
3962 case #1 d of 4076 case #1 d of
3963 L.DDatabase s => 4077 L.DDatabase s =>
3964 let 4078 let
3982 :: (dExp, loc) 4096 :: (dExp, loc)
3983 :: (dIni, loc) 4097 :: (dIni, loc)
3984 :: ds) 4098 :: ds)
3985 end 4099 end
3986 | _ => 4100 | _ =>
3987 case monoDecl (env, fm) d of 4101 (pvarDefs := [];
3988 NONE => (env, fm, ds) 4102 case monoDecl (env, fm) d of
3989 | SOME (env, fm, ds') => 4103 NONE => (env, fm, ds)
3990 (env, 4104 | SOME (env, fm, ds') =>
3991 Fm.enter fm, 4105 (env,
3992 ds' @ Fm.decls fm @ ds)) 4106 Fm.enter fm,
3993 (env, Fm.empty (CoreUtil.File.maxName file + 1), []) file 4107 ds' @ Fm.decls fm @ !pvarDefs @ ds)))
4108 (env, Fm.empty mname, []) file
3994 in 4109 in
4110 pvars := RM.empty;
4111 pvarDefs := [];
3995 rev ds 4112 rev ds
3996 end 4113 end
3997 4114
3998 end 4115 end