ziv@2254
|
1 structure MonoFooify :> MONO_FOOIFY = struct
|
ziv@2254
|
2
|
ziv@2254
|
3 open Mono
|
ziv@2254
|
4
|
ziv@2254
|
5 datatype foo_kind =
|
ziv@2254
|
6 Attr
|
ziv@2254
|
7 | Url
|
ziv@2254
|
8
|
ziv@2254
|
9 val nextPvar = ref 0
|
ziv@2254
|
10 val pvarDefs = ref ([] : (string * int * (string * int * typ option) list) list)
|
ziv@2254
|
11
|
ziv@2254
|
12 structure Fm = struct
|
ziv@2254
|
13
|
ziv@2254
|
14 type vr = string * int * typ * exp * string
|
ziv@2254
|
15
|
ziv@2254
|
16 structure IM = IntBinaryMap
|
ziv@2254
|
17
|
ziv@2254
|
18 structure M = BinaryMapFn(struct
|
ziv@2254
|
19 type ord_key = foo_kind
|
ziv@2254
|
20 fun compare x =
|
ziv@2254
|
21 case x of
|
ziv@2254
|
22 (Attr, Attr) => EQUAL
|
ziv@2254
|
23 | (Attr, _) => LESS
|
ziv@2254
|
24 | (_, Attr) => GREATER
|
ziv@2254
|
25
|
ziv@2254
|
26 | (Url, Url) => EQUAL
|
ziv@2254
|
27 end)
|
ziv@2254
|
28
|
ziv@2254
|
29 structure TM = BinaryMapFn(struct
|
ziv@2254
|
30 type ord_key = typ
|
ziv@2254
|
31 val compare = MonoUtil.Typ.compare
|
ziv@2254
|
32 end)
|
ziv@2254
|
33
|
ziv@2254
|
34 type t = {
|
ziv@2254
|
35 count : int,
|
ziv@2254
|
36 map : int IM.map M.map,
|
ziv@2254
|
37 listMap : int TM.map M.map,
|
ziv@2254
|
38 decls : vr list
|
ziv@2254
|
39 }
|
ziv@2254
|
40
|
ziv@2254
|
41 fun empty count = {
|
ziv@2254
|
42 count = count,
|
ziv@2254
|
43 map = M.empty,
|
ziv@2254
|
44 listMap = M.empty,
|
ziv@2254
|
45 decls = []
|
ziv@2254
|
46 }
|
ziv@2254
|
47
|
ziv@2254
|
48 fun chooseNext count =
|
ziv@2254
|
49 let
|
ziv@2254
|
50 val n = !nextPvar
|
ziv@2254
|
51 in
|
ziv@2254
|
52 if count < n then
|
ziv@2254
|
53 (count, count+1)
|
ziv@2254
|
54 else
|
ziv@2254
|
55 (nextPvar := n + 1;
|
ziv@2254
|
56 (n, n+1))
|
ziv@2254
|
57 end
|
ziv@2254
|
58
|
ziv@2254
|
59 fun enter ({count, map, listMap, ...} : t) = {count = count, map = map, listMap = listMap, decls = []}
|
ziv@2254
|
60 fun freshName {count, map, listMap, decls} =
|
ziv@2254
|
61 let
|
ziv@2254
|
62 val (next, count) = chooseNext count
|
ziv@2254
|
63 in
|
ziv@2254
|
64 (next, {count = count , map = map, listMap = listMap, decls = decls})
|
ziv@2254
|
65 end
|
ziv@2254
|
66 fun decls ({decls, ...} : t) =
|
ziv@2254
|
67 case decls of
|
ziv@2254
|
68 [] => []
|
ziv@2254
|
69 | _ => [(DValRec decls, ErrorMsg.dummySpan)]
|
ziv@2254
|
70
|
ziv@2254
|
71 fun lookup (t as {count, map, listMap, decls}) k n thunk =
|
ziv@2254
|
72 let
|
ziv@2254
|
73 val im = Option.getOpt (M.find (map, k), IM.empty)
|
ziv@2254
|
74 in
|
ziv@2254
|
75 case IM.find (im, n) of
|
ziv@2254
|
76 NONE =>
|
ziv@2254
|
77 let
|
ziv@2254
|
78 val n' = count
|
ziv@2254
|
79 val (d, {count, map, listMap, decls}) =
|
ziv@2254
|
80 thunk count {count = count + 1,
|
ziv@2254
|
81 map = M.insert (map, k, IM.insert (im, n, n')),
|
ziv@2254
|
82 listMap = listMap,
|
ziv@2254
|
83 decls = decls}
|
ziv@2254
|
84 in
|
ziv@2254
|
85 ({count = count,
|
ziv@2254
|
86 map = map,
|
ziv@2254
|
87 listMap = listMap,
|
ziv@2254
|
88 decls = d :: decls}, n')
|
ziv@2254
|
89 end
|
ziv@2254
|
90 | SOME n' => (t, n')
|
ziv@2254
|
91 end
|
ziv@2254
|
92
|
ziv@2254
|
93 fun lookupList (t as {count, map, listMap, decls}) k tp thunk =
|
ziv@2254
|
94 let
|
ziv@2254
|
95 val tm = Option.getOpt (M.find (listMap, k), TM.empty)
|
ziv@2254
|
96 in
|
ziv@2254
|
97 case TM.find (tm, tp) of
|
ziv@2254
|
98 NONE =>
|
ziv@2254
|
99 let
|
ziv@2254
|
100 val n' = count
|
ziv@2254
|
101 val (d, {count, map, listMap, decls}) =
|
ziv@2254
|
102 thunk count {count = count + 1,
|
ziv@2254
|
103 map = map,
|
ziv@2254
|
104 listMap = M.insert (listMap, k, TM.insert (tm, tp, n')),
|
ziv@2254
|
105 decls = decls}
|
ziv@2254
|
106 in
|
ziv@2254
|
107 ({count = count,
|
ziv@2254
|
108 map = map,
|
ziv@2254
|
109 listMap = listMap,
|
ziv@2254
|
110 decls = d :: decls}, n')
|
ziv@2254
|
111 end
|
ziv@2254
|
112 | SOME n' => (t, n')
|
ziv@2254
|
113 end
|
ziv@2254
|
114
|
ziv@2254
|
115 (* Has to be set at the end of [Monoize]. *)
|
ziv@2254
|
116 val canonical = ref (empty 0 : t)
|
ziv@2254
|
117
|
ziv@2254
|
118 end
|
ziv@2254
|
119
|
ziv@2254
|
120 fun fk2s fk =
|
ziv@2254
|
121 case fk of
|
ziv@2254
|
122 Attr => "attr"
|
ziv@2254
|
123 | Url => "url"
|
ziv@2254
|
124
|
ziv@2254
|
125 fun capitalize s =
|
ziv@2254
|
126 if s = "" then
|
ziv@2254
|
127 s
|
ziv@2254
|
128 else
|
ziv@2254
|
129 str (Char.toUpper (String.sub (s, 0))) ^ String.extract (s, 1, NONE)
|
ziv@2254
|
130
|
ziv@2254
|
131 structure E = ErrorMsg
|
ziv@2254
|
132
|
ziv@2254
|
133 val dummyExp = (EPrim (Prim.Int 0), E.dummySpan)
|
ziv@2254
|
134
|
ziv@2254
|
135 fun fooifyExp fk lookupENamed lookupDatatype =
|
ziv@2254
|
136 let
|
ziv@2254
|
137 fun fooify fm (e, tAll as (t, loc)) =
|
ziv@2254
|
138 case #1 e of
|
ziv@2254
|
139 EClosure (fnam, [(ERecord [], _)]) =>
|
ziv@2254
|
140 let
|
ziv@2254
|
141 val (_, s) = lookupENamed fnam
|
ziv@2254
|
142 in
|
ziv@2254
|
143 ((EPrim (Prim.String (Prim.Normal, Settings.getUrlPrefix () ^ s)), loc), fm)
|
ziv@2254
|
144 end
|
ziv@2254
|
145 | EClosure (fnam, args) =>
|
ziv@2254
|
146 let
|
ziv@2254
|
147 val (ft, s) = lookupENamed fnam
|
ziv@2254
|
148 fun attrify (args, ft, e, fm) =
|
ziv@2254
|
149 case (args, ft) of
|
ziv@2254
|
150 ([], _) => (e, fm)
|
ziv@2254
|
151 | (arg :: args, (TFun (t, ft), _)) =>
|
ziv@2254
|
152 let
|
ziv@2254
|
153 val (arg', fm) = fooify fm (arg, t)
|
ziv@2254
|
154 in
|
ziv@2254
|
155 attrify (args, ft,
|
ziv@2254
|
156 (EStrcat (e,
|
ziv@2254
|
157 (EStrcat ((EPrim (Prim.String (Prim.Normal, "/")), loc),
|
ziv@2254
|
158 arg'), loc)), loc),
|
ziv@2254
|
159 fm)
|
ziv@2254
|
160 end
|
ziv@2254
|
161 | _ => (E.errorAt loc "Type mismatch encoding attribute";
|
ziv@2254
|
162 (e, fm))
|
ziv@2254
|
163 in
|
ziv@2254
|
164 attrify (args, ft, (EPrim (Prim.String (Prim.Normal, Settings.getUrlPrefix () ^ s)), loc), fm)
|
ziv@2254
|
165 end
|
ziv@2254
|
166 | _ =>
|
ziv@2254
|
167 case t of
|
ziv@2254
|
168 TFfi ("Basis", "unit") => ((EPrim (Prim.String (Prim.Normal, "")), loc), fm)
|
ziv@2254
|
169 | TFfi (m, x) => ((EFfiApp (m, fk2s fk ^ "ify" ^ capitalize x, [(e, tAll)]), loc), fm)
|
ziv@2254
|
170
|
ziv@2254
|
171 | TRecord [] => ((EPrim (Prim.String (Prim.Normal, "")), loc), fm)
|
ziv@2254
|
172 | TRecord ((x, t) :: xts) =>
|
ziv@2254
|
173 let
|
ziv@2254
|
174 val (se, fm) = fooify fm ((EField (e, x), loc), t)
|
ziv@2254
|
175 in
|
ziv@2254
|
176 foldl (fn ((x, t), (se, fm)) =>
|
ziv@2254
|
177 let
|
ziv@2254
|
178 val (se', fm) = fooify fm ((EField (e, x), loc), t)
|
ziv@2254
|
179 in
|
ziv@2254
|
180 ((EStrcat (se,
|
ziv@2254
|
181 (EStrcat ((EPrim (Prim.String (Prim.Normal, "/")), loc),
|
ziv@2254
|
182 se'), loc)), loc),
|
ziv@2254
|
183 fm)
|
ziv@2254
|
184 end) (se, fm) xts
|
ziv@2254
|
185 end
|
ziv@2254
|
186
|
ziv@2254
|
187 | TDatatype (i, ref (dk, _)) =>
|
ziv@2254
|
188 let
|
ziv@2254
|
189 fun makeDecl n fm =
|
ziv@2254
|
190 let
|
ziv@2254
|
191 val (x, xncs) =
|
ziv@2254
|
192 case ListUtil.search (fn (x, i', xncs) =>
|
ziv@2254
|
193 if i' = i then
|
ziv@2254
|
194 SOME (x, xncs)
|
ziv@2254
|
195 else
|
ziv@2254
|
196 NONE) (!pvarDefs) of
|
ziv@2254
|
197 NONE => lookupDatatype i
|
ziv@2254
|
198 | SOME v => v
|
ziv@2254
|
199
|
ziv@2254
|
200 val (branches, fm) =
|
ziv@2254
|
201 ListUtil.foldlMap
|
ziv@2254
|
202 (fn ((x, n, to), fm) =>
|
ziv@2254
|
203 case to of
|
ziv@2254
|
204 NONE =>
|
ziv@2254
|
205 (((PCon (dk, PConVar n, NONE), loc),
|
ziv@2254
|
206 (EPrim (Prim.String (Prim.Normal, x)), loc)),
|
ziv@2254
|
207 fm)
|
ziv@2254
|
208 | SOME t =>
|
ziv@2254
|
209 let
|
ziv@2254
|
210 val (arg, fm) = fooify fm ((ERel 0, loc), t)
|
ziv@2254
|
211 in
|
ziv@2254
|
212 (((PCon (dk, PConVar n, SOME (PVar ("a", t), loc)), loc),
|
ziv@2254
|
213 (EStrcat ((EPrim (Prim.String (Prim.Normal, x ^ "/")), loc),
|
ziv@2254
|
214 arg), loc)),
|
ziv@2254
|
215 fm)
|
ziv@2254
|
216 end)
|
ziv@2254
|
217 fm xncs
|
ziv@2254
|
218
|
ziv@2254
|
219 val dom = tAll
|
ziv@2254
|
220 val ran = (TFfi ("Basis", "string"), loc)
|
ziv@2254
|
221 in
|
ziv@2254
|
222 ((fk2s fk ^ "ify_" ^ x,
|
ziv@2254
|
223 n,
|
ziv@2254
|
224 (TFun (dom, ran), loc),
|
ziv@2254
|
225 (EAbs ("x",
|
ziv@2254
|
226 dom,
|
ziv@2254
|
227 ran,
|
ziv@2254
|
228 (ECase ((ERel 0, loc),
|
ziv@2254
|
229 branches,
|
ziv@2254
|
230 {disc = dom,
|
ziv@2254
|
231 result = ran}), loc)), loc),
|
ziv@2254
|
232 ""),
|
ziv@2254
|
233 fm)
|
ziv@2254
|
234 end
|
ziv@2254
|
235
|
ziv@2254
|
236 val (fm, n) = Fm.lookup fm fk i makeDecl
|
ziv@2254
|
237 in
|
ziv@2254
|
238 ((EApp ((ENamed n, loc), e), loc), fm)
|
ziv@2254
|
239 end
|
ziv@2254
|
240
|
ziv@2254
|
241 | TOption t =>
|
ziv@2254
|
242 let
|
ziv@2254
|
243 val (body, fm) = fooify fm ((ERel 0, loc), t)
|
ziv@2254
|
244 in
|
ziv@2254
|
245 ((ECase (e,
|
ziv@2254
|
246 [((PNone t, loc),
|
ziv@2254
|
247 (EPrim (Prim.String (Prim.Normal, "None")), loc)),
|
ziv@2254
|
248
|
ziv@2254
|
249 ((PSome (t, (PVar ("x", t), loc)), loc),
|
ziv@2254
|
250 (EStrcat ((EPrim (Prim.String (Prim.Normal, "Some/")), loc),
|
ziv@2254
|
251 body), loc))],
|
ziv@2254
|
252 {disc = tAll,
|
ziv@2254
|
253 result = (TFfi ("Basis", "string"), loc)}), loc),
|
ziv@2254
|
254 fm)
|
ziv@2254
|
255 end
|
ziv@2254
|
256
|
ziv@2254
|
257 | TList t =>
|
ziv@2254
|
258 let
|
ziv@2254
|
259 fun makeDecl n fm =
|
ziv@2254
|
260 let
|
ziv@2254
|
261 val rt = (TRecord [("1", t), ("2", (TList t, loc))], loc)
|
ziv@2254
|
262 val (arg, fm) = fooify fm ((ERel 0, loc), rt)
|
ziv@2254
|
263
|
ziv@2254
|
264 val branches = [((PNone rt, loc),
|
ziv@2254
|
265 (EPrim (Prim.String (Prim.Normal, "Nil")), loc)),
|
ziv@2254
|
266 ((PSome (rt, (PVar ("a", rt), loc)), loc),
|
ziv@2254
|
267 (EStrcat ((EPrim (Prim.String (Prim.Normal, "Cons/")), loc),
|
ziv@2254
|
268 arg), loc))]
|
ziv@2254
|
269
|
ziv@2254
|
270 val dom = tAll
|
ziv@2254
|
271 val ran = (TFfi ("Basis", "string"), loc)
|
ziv@2254
|
272 in
|
ziv@2254
|
273 ((fk2s fk ^ "ify_list",
|
ziv@2254
|
274 n,
|
ziv@2254
|
275 (TFun (dom, ran), loc),
|
ziv@2254
|
276 (EAbs ("x",
|
ziv@2254
|
277 dom,
|
ziv@2254
|
278 ran,
|
ziv@2254
|
279 (ECase ((ERel 0, loc),
|
ziv@2254
|
280 branches,
|
ziv@2254
|
281 {disc = dom,
|
ziv@2254
|
282 result = ran}), loc)), loc),
|
ziv@2254
|
283 ""),
|
ziv@2254
|
284 fm)
|
ziv@2254
|
285 end
|
ziv@2254
|
286
|
ziv@2254
|
287 val (fm, n) = Fm.lookupList fm fk t makeDecl
|
ziv@2254
|
288 in
|
ziv@2254
|
289 ((EApp ((ENamed n, loc), e), loc), fm)
|
ziv@2254
|
290 end
|
ziv@2254
|
291
|
ziv@2254
|
292 | _ => (E.errorAt loc "Don't know how to encode attribute/URL type";
|
ziv@2254
|
293 Print.eprefaces' [("Type", MonoPrint.p_typ MonoEnv.empty tAll)];
|
ziv@2254
|
294 (dummyExp, fm))
|
ziv@2254
|
295 in
|
ziv@2254
|
296 fooify
|
ziv@2254
|
297 end
|
ziv@2254
|
298
|
ziv@2254
|
299 fun urlify env expTyp =
|
ziv@2254
|
300 let
|
ziv@2254
|
301 val (exp, fm) =
|
ziv@2254
|
302 fooifyExp
|
ziv@2254
|
303 Url
|
ziv@2254
|
304 (fn n =>
|
ziv@2254
|
305 let
|
ziv@2254
|
306 val (_, t, _, s) = MonoEnv.lookupENamed env n
|
ziv@2254
|
307 in
|
ziv@2254
|
308 (t, s)
|
ziv@2254
|
309 end)
|
ziv@2254
|
310 (fn n => MonoEnv.lookupDatatype env n)
|
ziv@2254
|
311 (!Fm.canonical)
|
ziv@2254
|
312 expTyp
|
ziv@2254
|
313 in
|
ziv@2254
|
314 Fm.canonical := fm;
|
ziv@2254
|
315 exp
|
ziv@2254
|
316 end
|
ziv@2254
|
317 end
|