Mercurial > urweb
comparison src/reduce.sml @ 509:140c68046598
Most exp rules for new Reduce
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Wed, 26 Nov 2008 12:59:32 -0500 |
parents | 04053089878a |
children | c644ec94866d |
comparison
equal
deleted
inserted
replaced
508:04053089878a | 509:140c68046598 |
---|---|
57 fun find (n', env, lift) = | 57 fun find (n', env, lift) = |
58 if n' = 0 then | 58 if n' = 0 then |
59 case env of | 59 case env of |
60 UnknownC :: _ => (CRel (n + lift), loc) | 60 UnknownC :: _ => (CRel (n + lift), loc) |
61 | KnownC c :: _ => con (Lift (lift, 0) :: env) c | 61 | KnownC c :: _ => con (Lift (lift, 0) :: env) c |
62 | Lift (lift', _) :: rest => find (0, rest, lift + lift') | |
62 | _ => raise Fail "Reduce.con: CRel [1]" | 63 | _ => raise Fail "Reduce.con: CRel [1]" |
63 else | 64 else |
64 case env of | 65 case env of |
65 UnknownC :: rest => find (n' - 1, rest, lift + 1) | 66 UnknownC :: rest => find (n' - 1, rest, lift + 1) |
66 | KnownC _ :: rest => find (n' - 1, rest, lift) | 67 | KnownC _ :: rest => find (n' - 1, rest, lift) |
67 | UnknownE :: rest => find (n' - 1, rest, lift) | 68 | UnknownE :: rest => find (n' - 1, rest, lift) |
68 | KnownE _ :: rest => find (n' - 1, rest, lift) | 69 | KnownE _ :: rest => find (n' - 1, rest, lift) |
69 | Lift (lift', _) :: rest => find (n' - 1, rest, lift + lift') | 70 | Lift (lift', _) :: rest => find (n', rest, lift + lift') |
70 | [] => raise Fail "Reduce.con: CRel [2]" | 71 | [] => raise Fail "Reduce.con: CRel [2]" |
71 in | 72 in |
72 find (n, env, 0) | 73 find (n, env, 0) |
73 end | 74 end |
74 | CNamed n => | 75 | CNamed n => |
123 case #1 c of | 124 case #1 c of |
124 CTuple cs => List.nth (cs, n - 1) | 125 CTuple cs => List.nth (cs, n - 1) |
125 | _ => (CProj (c, n), loc) | 126 | _ => (CProj (c, n), loc) |
126 end | 127 end |
127 | 128 |
128 fun exp env e = e | 129 fun patCon pc = |
130 case pc of | |
131 PConVar _ => pc | |
132 | PConFfi {mod = m, datatyp, params, con = c, arg, kind} => | |
133 PConFfi {mod = m, datatyp = datatyp, params = params, con = c, | |
134 arg = Option.map (con (map (fn _ => UnknownC) params)) arg, | |
135 kind = kind} | |
136 | |
137 | |
138 val k = (KType, ErrorMsg.dummySpan) | |
139 fun doPart e (this as (x, t), rest) = | |
140 ((x, (EField (e, x, {field = t, rest = (CRecord (k, rest), #2 t)}), #2 t), t), | |
141 this :: rest) | |
142 | |
143 fun exp env (all as (e, loc)) = | |
144 case e of | |
145 EPrim _ => all | |
146 | ERel n => | |
147 let | |
148 fun find (n', env, liftC, liftE) = | |
149 if n' = 0 then | |
150 case env of | |
151 UnknownE :: _ => (ERel (n + liftE), loc) | |
152 | KnownE e :: _ => exp (Lift (liftC, liftE) :: env) e | |
153 | Lift (liftC', liftE') :: rest => find (0, rest, liftC + liftC', liftE + liftE') | |
154 | _ => raise Fail "Reduce.exp: ERel [1]" | |
155 else | |
156 case env of | |
157 UnknownC :: rest => find (n' - 1, rest, liftC + 1, liftE) | |
158 | KnownC _ :: rest => find (n' - 1, rest, liftC, liftE) | |
159 | UnknownE :: rest => find (n' - 1, rest, liftC, liftE + 1) | |
160 | KnownE _ :: rest => find (n' - 1, rest, liftC, liftE) | |
161 | Lift (liftC', liftE') :: rest => find (n', rest, liftC + liftC', liftE + liftE') | |
162 | [] => raise Fail "Reduce.exp: ERel [2]" | |
163 in | |
164 find (n, env, 0, 0) | |
165 end | |
166 | ENamed n => | |
167 (case IM.find (namedE, n) of | |
168 NONE => all | |
169 | SOME e => e) | |
170 | ECon (dk, pc, cs, eo) => (ECon (dk, patCon pc, | |
171 map (con env) cs, Option.map (exp env) eo), loc) | |
172 | EFfi _ => all | |
173 | EFfiApp (m, f, es) => (EFfiApp (m, f, map (exp env) es), loc) | |
174 | |
175 | EApp (e1, e2) => | |
176 let | |
177 val e1 = exp env e1 | |
178 val e2 = exp env e2 | |
179 in | |
180 case #1 e1 of | |
181 EAbs (_, _, _, b) => exp (KnownE e2 :: env) b | |
182 | _ => (EApp (e1, e2), loc) | |
183 end | |
184 | |
185 | EAbs (x, dom, ran, e) => (EAbs (x, con env dom, con env ran, exp (UnknownE :: env) e), loc) | |
186 | |
187 | ECApp (e, c) => | |
188 let | |
189 val e = exp env e | |
190 val c = con env c | |
191 in | |
192 case #1 e of | |
193 ECAbs (_, _, b) => exp (KnownC c :: env) b | |
194 | _ => (ECApp (e, c), loc) | |
195 end | |
196 | |
197 | ECAbs (x, k, e) => (ECAbs (x, k, exp (UnknownC :: env) e), loc) | |
198 | |
199 | ERecord xcs => (ERecord (map (fn (x, e, t) => (con env x, exp env e, con env t)) xcs), loc) | |
200 | EField (e, c, {field, rest}) => | |
201 let | |
202 val e = exp env e | |
203 val c = con env c | |
204 | |
205 fun default () = (EField (e, c, {field = con env field, rest = con env rest}), loc) | |
206 in | |
207 case (#1 e, #1 c) of | |
208 (ERecord xcs, CName x) => | |
209 (case List.find (fn ((CName x', _), _, _) => x' = x | _ => false) xcs of | |
210 NONE => default () | |
211 | SOME (_, e, _) => e) | |
212 | _ => default () | |
213 end | |
214 | |
215 | EConcat (e1, c1, e2, c2) => | |
216 let | |
217 val e1 = exp env e1 | |
218 val e2 = exp env e2 | |
219 in | |
220 case (#1 e1, #1 e2) of | |
221 (ERecord xes1, ERecord xes2) => (ERecord (xes1 @ xes2), loc) | |
222 | _ => | |
223 let | |
224 val c1 = con env c1 | |
225 val c2 = con env c2 | |
226 in | |
227 case (#1 c1, #1 c2) of | |
228 (CRecord (k, xcs1), CRecord (_, xcs2)) => | |
229 let | |
230 val (xes1, rest) = ListUtil.foldlMap (doPart e1) [] xcs1 | |
231 val (xes2, _) = ListUtil.foldlMap (doPart e2) rest xcs2 | |
232 in | |
233 exp env (ERecord (xes1 @ xes2), loc) | |
234 end | |
235 | _ => (EConcat (e1, c1, e2, c2), loc) | |
236 end | |
237 end | |
238 | |
239 | ECut (e, c, {field, rest}) => | |
240 let | |
241 val e = exp env e | |
242 val c = con env c | |
243 | |
244 fun default () = | |
245 let | |
246 val rest = con env rest | |
247 in | |
248 case #1 rest of | |
249 CRecord (k, xcs) => | |
250 let | |
251 val (xes, _) = ListUtil.foldlMap (doPart e) [] xcs | |
252 in | |
253 exp env (ERecord xes, loc) | |
254 end | |
255 | _ => (ECut (e, c, {field = con env field, rest = rest}), loc) | |
256 end | |
257 in | |
258 case (#1 e, #1 c) of | |
259 (ERecord xes, CName x) => | |
260 if List.all (fn ((CName _, _), _, _) => true | _ => false) xes then | |
261 (ERecord (List.filter (fn ((CName x', _), _, _) => x' <> x | |
262 | _ => raise Fail "Reduce: ECut") xes), loc) | |
263 else | |
264 default () | |
265 | _ => default () | |
266 end | |
267 | |
268 | ECutMulti (e, c, {rest}) => | |
269 let | |
270 val e = exp env e | |
271 val c = con env c | |
272 | |
273 fun default () = | |
274 let | |
275 val rest = con env rest | |
276 in | |
277 case #1 rest of | |
278 CRecord (k, xcs) => | |
279 let | |
280 val (xes, _) = ListUtil.foldlMap (doPart e) [] xcs | |
281 in | |
282 exp env (ERecord xes, loc) | |
283 end | |
284 | _ => (ECutMulti (e, c, {rest = rest}), loc) | |
285 end | |
286 in | |
287 case (#1 e, #1 c) of | |
288 (ERecord xes, CRecord (_, xcs)) => | |
289 if List.all (fn ((CName _, _), _, _) => true | _ => false) xes | |
290 andalso List.all (fn ((CName _, _), _) => true | _ => false) xcs then | |
291 (ERecord (List.filter (fn ((CName x', _), _, _) => | |
292 List.all (fn ((CName x, _), _) => x' <> x | |
293 | _ => raise Fail "Reduce: ECutMulti [1]") xcs | |
294 | _ => raise Fail "Reduce: ECutMulti [2]") xes), loc) | |
295 else | |
296 default () | |
297 | _ => default () | |
298 end | |
299 | |
300 | EFold _ => all | |
301 | |
302 | ECase (e, pes, {disc, result}) => | |
303 let | |
304 fun patBinds (p, _) = | |
305 case p of | |
306 PWild => 0 | |
307 | PVar _ => 1 | |
308 | PPrim _ => 0 | |
309 | PCon (_, _, _, NONE) => 0 | |
310 | PCon (_, _, _, SOME p) => patBinds p | |
311 | PRecord xpts => foldl (fn ((_, p, _), n) => n + patBinds p) 0 xpts | |
312 | |
313 fun pat (all as (p, loc)) = | |
314 case p of | |
315 PWild => all | |
316 | PVar (x, t) => (PVar (x, con env t), loc) | |
317 | PPrim _ => all | |
318 | PCon (dk, pc, cs, po) => | |
319 (PCon (dk, patCon pc, map (con env) cs, Option.map pat po), loc) | |
320 | PRecord xpts => (PRecord (map (fn (x, p, t) => (x, pat p, con env t)) xpts), loc) | |
321 in | |
322 (ECase (exp env e, | |
323 map (fn (p, e) => (pat p, | |
324 exp (List.tabulate (patBinds p, fn _ => UnknownE) @ env) e)) | |
325 pes, {disc = con env disc, result = con env result}), loc) | |
326 end | |
327 | |
328 | EWrite e => (EWrite (exp env e), loc) | |
329 | EClosure (n, es) => (EClosure (n, map (exp env) es), loc) | |
330 | |
331 | ELet (x, t, e1, e2) => (ELet (x, con env t, exp env e1, exp (UnknownE :: env) e2), loc) | |
129 in | 332 in |
130 {con = con, exp = exp} | 333 {con = con, exp = exp} |
131 end | 334 end |
132 | 335 |
133 fun con namedC c = #con (conAndExp (namedC, IM.empty)) [] c | 336 fun con namedC env c = #con (conAndExp (namedC, IM.empty)) env c |
134 fun exp (namedC, namedE) e = #exp (conAndExp (namedC, namedE)) [] e | 337 fun exp (namedC, namedE) env e = #exp (conAndExp (namedC, namedE)) env e |
135 | 338 |
136 fun reduce file = | 339 fun reduce file = |
137 let | 340 let |
138 fun doDecl (d as (_, loc), st as (namedC, namedE)) = | 341 fun doDecl (d as (_, loc), st as (namedC, namedE)) = |
139 case #1 d of | 342 case #1 d of |
140 DCon (x, n, k, c) => | 343 DCon (x, n, k, c) => |
141 let | 344 let |
142 val c = con namedC c | 345 val c = con namedC [] c |
143 in | 346 in |
144 ((DCon (x, n, k, c), loc), | 347 ((DCon (x, n, k, c), loc), |
145 (IM.insert (namedC, n, c), namedE)) | 348 (IM.insert (namedC, n, c), namedE)) |
146 end | 349 end |
147 | DDatatype (x, n, ps, cs) => | 350 | DDatatype (x, n, ps, cs) => |
148 ((DDatatype (x, n, ps, map (fn (x, n, co) => (x, n, Option.map (con namedC) co)) cs), loc), | 351 let |
149 st) | 352 val env = map (fn _ => UnknownC) ps |
353 in | |
354 ((DDatatype (x, n, ps, map (fn (x, n, co) => (x, n, Option.map (con namedC env) co)) cs), loc), | |
355 st) | |
356 end | |
150 | DVal (x, n, t, e, s) => | 357 | DVal (x, n, t, e, s) => |
151 let | 358 let |
152 val t = con namedC t | 359 val t = con namedC [] t |
153 val e = exp (namedC, namedE) e | 360 val e = exp (namedC, namedE) [] e |
154 in | 361 in |
155 ((DVal (x, n, t, e, s), loc), | 362 ((DVal (x, n, t, e, s), loc), |
156 (namedC, IM.insert (namedE, n, e))) | 363 (namedC, IM.insert (namedE, n, e))) |
157 end | 364 end |
158 | DValRec vis => | 365 | DValRec vis => |
159 ((DValRec (map (fn (x, n, t, e, s) => (x, n, con namedC t, exp (namedC, namedE) e, s)) vis), loc), | 366 ((DValRec (map (fn (x, n, t, e, s) => (x, n, con namedC [] t, exp (namedC, namedE) [] e, s)) vis), loc), |
160 st) | 367 st) |
161 | DExport _ => (d, st) | 368 | DExport _ => (d, st) |
162 | DTable (s, n, c, s') => ((DTable (s, n, con namedC c, s'), loc), st) | 369 | DTable (s, n, c, s') => ((DTable (s, n, con namedC [] c, s'), loc), st) |
163 | DSequence _ => (d, st) | 370 | DSequence _ => (d, st) |
164 | DDatabase _ => (d, st) | 371 | DDatabase _ => (d, st) |
165 | DCookie (s, n, c, s') => ((DCookie (s, n, con namedC c, s'), loc), st) | 372 | DCookie (s, n, c, s') => ((DCookie (s, n, con namedC [] c, s'), loc), st) |
166 | 373 |
167 val (file, _) = ListUtil.foldlMap doDecl (IM.empty, IM.empty) file | 374 val (file, _) = ListUtil.foldlMap doDecl (IM.empty, IM.empty) file |
168 in | 375 in |
169 file | 376 file |
170 end | 377 end |