Mercurial > urweb
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 |