Mercurial > urweb
comparison src/iflow.sml @ 1251:70092a661f70
Basic handling of recursive functions in Iflow
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Sat, 01 May 2010 09:51:46 -0400 |
parents | e80582b927f2 |
children | 2e4159a7d2d3 |
comparison
equal
deleted
inserted
replaced
1250:e80582b927f2 | 1251:70092a661f70 |
---|---|
1231 val update : ErrorMsg.span -> unit | 1231 val update : ErrorMsg.span -> unit |
1232 | 1232 |
1233 val havocReln : reln -> unit | 1233 val havocReln : reln -> unit |
1234 val havocCookie : string -> unit | 1234 val havocCookie : string -> unit |
1235 | 1235 |
1236 val check : atom -> bool | |
1237 | |
1236 val debug : unit -> unit | 1238 val debug : unit -> unit |
1237 end = struct | 1239 end = struct |
1238 | 1240 |
1239 val hnames = ref 1 | 1241 val hnames = ref 1 |
1240 | 1242 |
1517 in | 1519 in |
1518 hnames := n + 1; | 1520 hnames := n + 1; |
1519 hyps := (n, List.filter (fn AReln (Eq, [_, Func (Other f, [])]) => f <> cname | _ => true) hs, ref false) | 1521 hyps := (n, List.filter (fn AReln (Eq, [_, Func (Other f, [])]) => f <> cname | _ => true) hs, ref false) |
1520 end | 1522 end |
1521 | 1523 |
1524 fun check a = Cc.check (db, a) | |
1525 | |
1522 fun debug () = | 1526 fun debug () = |
1523 let | 1527 let |
1524 val (_, hs, _) = !hyps | 1528 val (_, hs, _) = !hyps |
1525 in | 1529 in |
1526 Print.preface ("Hyps", Print.p_list p_atom hs) | 1530 Print.preface ("Hyps", Print.p_list p_atom hs) |
1547 ERel n => SOME (List.nth (env, n)) | 1551 ERel n => SOME (List.nth (env, n)) |
1548 | EField (e, f) => | 1552 | EField (e, f) => |
1549 (case deinj env e of | 1553 (case deinj env e of |
1550 NONE => NONE | 1554 NONE => NONE |
1551 | SOME e => SOME (Proj (e, f))) | 1555 | SOME e => SOME (Proj (e, f))) |
1556 | EApp ((EFfi mf, _), e) => | |
1557 if Settings.isEffectful mf orelse Settings.isBenignEffectful mf then | |
1558 NONE | |
1559 else (case deinj env e of | |
1560 NONE => NONE | |
1561 | SOME e => SOME (Func (Other (#1 mf ^ "." ^ #2 mf), [e]))) | |
1552 | _ => NONE | 1562 | _ => NONE |
1553 | 1563 |
1554 fun expIn rv env rvOf = | 1564 fun expIn rv env rvOf = |
1555 let | 1565 let |
1556 fun expIn e = | 1566 fun expIn e = |
1819 in | 1829 in |
1820 St.assert [AReln (PCon1 "Some", [e])]; | 1830 St.assert [AReln (PCon1 "Some", [e])]; |
1821 env | 1831 env |
1822 end | 1832 end |
1823 | 1833 |
1834 datatype arg_mode = Fixed | Decreasing | Arbitrary | |
1835 type rfun = {args : arg_mode list, tables : SS.set, cookies : SS.set, body : Mono.exp} | |
1836 val rfuns = ref (IM.empty : rfun IM.map) | |
1837 | |
1824 fun evalExp env (e as (_, loc)) k = | 1838 fun evalExp env (e as (_, loc)) k = |
1825 let | 1839 let |
1826 (*val () = St.debug ()*) | 1840 (*val () = St.debug ()*) |
1827 (*val () = Print.preface ("evalExp", MonoPrint.p_exp MonoEnv.empty e)*) | 1841 (*val () = Print.preface ("evalExp", MonoPrint.p_exp MonoEnv.empty e)*) |
1828 | 1842 |
1881 k e | 1895 k e |
1882 end | 1896 end |
1883 | EFfiApp x => doFfi x | 1897 | EFfiApp x => doFfi x |
1884 | EApp ((EFfi (m, s), _), e) => doFfi (m, s, [e]) | 1898 | EApp ((EFfi (m, s), _), e) => doFfi (m, s, [e]) |
1885 | 1899 |
1886 | EApp (e1, e2) => evalExp env e1 (fn _ => evalExp env e2 (fn _ => default ())) | 1900 | EApp (e1 as (EError _, _), _) => evalExp env e1 k |
1901 | |
1902 | EApp (e1, e2) => | |
1903 let | |
1904 fun adefault () = (ErrorMsg.errorAt loc "Excessively fancy function call"; | |
1905 Print.preface ("Call", MonoPrint.p_exp MonoEnv.empty e); | |
1906 default ()) | |
1907 | |
1908 fun doArgs (e, args) = | |
1909 case #1 e of | |
1910 EApp (e1, e2) => doArgs (e1, e2 :: args) | |
1911 | ENamed n => | |
1912 (case IM.find (!rfuns, n) of | |
1913 NONE => adefault () | |
1914 | SOME rf => | |
1915 if length (#args rf) <> length args then | |
1916 adefault () | |
1917 else | |
1918 let | |
1919 val () = (SS.app (St.havocReln o Sql) (#tables rf); | |
1920 SS.app St.havocCookie (#cookies rf)) | |
1921 val saved = St.stash () | |
1922 | |
1923 fun doArgs (args, modes, env') = | |
1924 case (args, modes) of | |
1925 ([], []) => (evalExp env' (#body rf) (fn _ => ()); | |
1926 St.reinstate saved; | |
1927 default ()) | |
1928 | |
1929 | (arg :: args, mode :: modes) => | |
1930 evalExp env arg (fn arg => | |
1931 let | |
1932 val v = case mode of | |
1933 Arbitrary => Var (St.nextVar ()) | |
1934 | Fixed => arg | |
1935 | Decreasing => | |
1936 let | |
1937 val v = Var (St.nextVar ()) | |
1938 in | |
1939 if St.check (AReln (Known, [arg])) then | |
1940 St.assert [(AReln (Known, [v]))] | |
1941 else | |
1942 (); | |
1943 v | |
1944 end | |
1945 in | |
1946 doArgs (args, modes, v :: env') | |
1947 end) | |
1948 | _ => raise Fail "Iflow.doArgs: Impossible" | |
1949 in | |
1950 doArgs (args, #args rf, []) | |
1951 end) | |
1952 | _ => adefault () | |
1953 in | |
1954 doArgs (e, []) | |
1955 end | |
1887 | 1956 |
1888 | EAbs _ => default () | 1957 | EAbs _ => default () |
1889 | EUnop (s, e1) => evalExp env e1 (fn e1 => k (Func (Other s, [e1]))) | 1958 | EUnop (s, e1) => evalExp env e1 (fn e1 => k (Func (Other s, [e1]))) |
1890 | EBinop (s, e1, e2) => evalExp env e1 (fn e1 => evalExp env e2 (fn e2 => k (Func (Other s, [e1, e2])))) | 1959 | EBinop (s, e1, e2) => evalExp env e1 (fn e1 => evalExp env e2 (fn e2 => k (Func (Other s, [e1, e2])))) |
1891 | ERecord xets => | 1960 | ERecord xets => |
2026 val saved = St.stash () | 2095 val saved = St.stash () |
2027 in | 2096 in |
2028 St.assert [AReln (Sql (tab ^ "$New"), [Recd es])]; | 2097 St.assert [AReln (Sql (tab ^ "$New"), [Recd es])]; |
2029 St.insert loc; | 2098 St.insert loc; |
2030 St.reinstate saved; | 2099 St.reinstate saved; |
2100 St.assert [AReln (Sql tab, [Recd es])]; | |
2031 k (Recd []) | 2101 k (Recd []) |
2032 end | 2102 end |
2033 | Delete (tab, e) => | 2103 | Delete (tab, e) => |
2034 let | 2104 let |
2035 val old = St.nextVar () | 2105 val old = St.nextVar () |
2129 | ERecv _ => default () | 2199 | ERecv _ => default () |
2130 | ESleep _ => default () | 2200 | ESleep _ => default () |
2131 | ESpawn _ => default () | 2201 | ESpawn _ => default () |
2132 end | 2202 end |
2133 | 2203 |
2204 datatype var_source = Input of int | SubInput of int | Unknown | |
2205 | |
2134 fun check file = | 2206 fun check file = |
2135 let | 2207 let |
2136 val () = St.reset () | 2208 val () = (St.reset (); |
2209 rfuns := IM.empty) | |
2137 | 2210 |
2138 val file = MonoReduce.reduce file | 2211 val file = MonoReduce.reduce file |
2139 val file = MonoOpt.optimize file | 2212 val file = MonoOpt.optimize file |
2140 val file = Fuse.fuse file | 2213 val file = Fuse.fuse file |
2141 val file = MonoOpt.optimize file | 2214 val file = MonoOpt.optimize file |
2194 St.assert ps; | 2267 St.assert ps; |
2195 (evalExp env e (fn _ => ()) handle Cc.Contradiction => ()); | 2268 (evalExp env e (fn _ => ()) handle Cc.Contradiction => ()); |
2196 St.reinstate saved | 2269 St.reinstate saved |
2197 end | 2270 end |
2198 | 2271 |
2199 | DValRec _ => ErrorMsg.errorAt loc "Iflow can't check recursive functions." | 2272 | DValRec [(x, n, _, e, _)] => |
2273 let | |
2274 val tables = ref SS.empty | |
2275 val cookies = ref SS.empty | |
2276 | |
2277 fun deAbs (e, env, modes) = | |
2278 case #1 e of | |
2279 EAbs (_, _, _, e) => deAbs (e, Input (length env) :: env, ref Fixed :: modes) | |
2280 | _ => (e, env, rev modes) | |
2281 | |
2282 val (e, env, modes) = deAbs (e, [], []) | |
2283 | |
2284 fun doExp env (e as (_, loc)) = | |
2285 case #1 e of | |
2286 EPrim _ => e | |
2287 | ERel _ => e | |
2288 | ENamed _ => e | |
2289 | ECon (_, _, NONE) => e | |
2290 | ECon (dk, pc, SOME e) => (ECon (dk, pc, SOME (doExp env e)), loc) | |
2291 | ENone _ => e | |
2292 | ESome (t, e) => (ESome (t, doExp env e), loc) | |
2293 | EFfi _ => e | |
2294 | EFfiApp (m, f, es) => | |
2295 (case (m, f, es) of | |
2296 ("Basis", "set_cookie", [_, (EPrim (Prim.String cname), _), _, _, _]) => | |
2297 cookies := SS.add (!cookies, cname) | |
2298 | _ => (); | |
2299 (EFfiApp (m, f, map (doExp env) es), loc)) | |
2300 | |
2301 | EApp (e1, e2) => | |
2302 let | |
2303 fun default () = (EApp (doExp env e1, doExp env e2), loc) | |
2304 | |
2305 fun explore (e, args) = | |
2306 case #1 e of | |
2307 EApp (e1, e2) => explore (e1, e2 :: args) | |
2308 | ENamed n' => | |
2309 if n' = n then | |
2310 let | |
2311 fun doArgs (pos, args, modes) = | |
2312 case (args, modes) of | |
2313 ((e1, _) :: args, m1 :: modes) => | |
2314 (case e1 of | |
2315 ERel n => | |
2316 (case List.nth (env, n) of | |
2317 Input pos' => | |
2318 if pos' = pos then | |
2319 () | |
2320 else | |
2321 m1 := Arbitrary | |
2322 | SubInput pos' => | |
2323 if pos' = pos then | |
2324 if !m1 = Arbitrary then | |
2325 () | |
2326 else | |
2327 m1 := Decreasing | |
2328 else | |
2329 m1 := Arbitrary | |
2330 | Unknown => m1 := Arbitrary) | |
2331 | _ => m1 := Arbitrary; | |
2332 doArgs (pos + 1, args, modes)) | |
2333 | (_ :: _, []) => () | |
2334 | ([], ms) => app (fn m => m := Arbitrary) ms | |
2335 in | |
2336 doArgs (0, args, modes); | |
2337 (EFfi ("Basis", "?"), loc) | |
2338 end | |
2339 else | |
2340 default () | |
2341 | _ => default () | |
2342 in | |
2343 explore (e, []) | |
2344 end | |
2345 | EAbs (x, t1, t2, e) => (EAbs (x, t1, t2, doExp (Unknown :: env) e), loc) | |
2346 | EUnop (uo, e1) => (EUnop (uo, doExp env e1), loc) | |
2347 | EBinop (bo, e1, e2) => (EBinop (bo, doExp env e1, doExp env e2), loc) | |
2348 | ERecord xets => (ERecord (map (fn (x, e, t) => (x, doExp env e, t)) xets), loc) | |
2349 | EField (e1, f) => (EField (doExp env e1, f), loc) | |
2350 | ECase (e, pes, ts) => | |
2351 let | |
2352 val source = | |
2353 case #1 e of | |
2354 ERel n => | |
2355 (case List.nth (env, n) of | |
2356 Input n => SOME n | |
2357 | SubInput n => SOME n | |
2358 | Unknown => NONE) | |
2359 | _ => NONE | |
2360 | |
2361 fun doV v = | |
2362 let | |
2363 fun doPat (p, env) = | |
2364 case #1 p of | |
2365 PWild => env | |
2366 | PVar _ => v :: env | |
2367 | PPrim _ => env | |
2368 | PCon (_, _, NONE) => env | |
2369 | PCon (_, _, SOME p) => doPat (p, env) | |
2370 | PRecord xpts => foldl (fn ((_, p, _), env) => doPat (p, env)) env xpts | |
2371 | PNone _ => env | |
2372 | PSome (_, p) => doPat (p, env) | |
2373 in | |
2374 (ECase (e, map (fn (p, e) => (p, doExp (doPat (p, env)) e)) pes, ts), loc) | |
2375 end | |
2376 in | |
2377 case source of | |
2378 NONE => doV Unknown | |
2379 | SOME inp => doV (SubInput inp) | |
2380 end | |
2381 | EStrcat (e1, e2) => (EStrcat (doExp env e1, doExp env e2), loc) | |
2382 | EError (e1, t) => (EError (doExp env e1, t), loc) | |
2383 | EReturnBlob {blob = b, mimeType = m, t} => | |
2384 (EReturnBlob {blob = doExp env b, mimeType = doExp env m, t = t}, loc) | |
2385 | ERedirect (e1, t) => (ERedirect (doExp env e1, t), loc) | |
2386 | EWrite e1 => (EWrite (doExp env e1), loc) | |
2387 | ESeq (e1, e2) => (ESeq (doExp env e1, doExp env e2), loc) | |
2388 | ELet (x, t, e1, e2) => (ELet (x, t, doExp env e1, doExp (Unknown :: env) e2), loc) | |
2389 | EClosure (n, es) => (EClosure (n, map (doExp env) es), loc) | |
2390 | EQuery {exps, tables, state, query, body, initial} => | |
2391 (EQuery {exps = exps, tables = tables, state = state, | |
2392 query = doExp env query, | |
2393 body = doExp (Unknown :: Unknown :: env) body, | |
2394 initial = doExp env initial}, loc) | |
2395 | EDml e1 => | |
2396 (case parse dml e1 of | |
2397 NONE => () | |
2398 | SOME c => | |
2399 case c of | |
2400 Insert _ => () | |
2401 | Delete (tab, _) => | |
2402 tables := SS.add (!tables, tab) | |
2403 | Update (tab, _, _) => | |
2404 tables := SS.add (!tables, tab); | |
2405 (EDml (doExp env e1), loc)) | |
2406 | ENextval e1 => (ENextval (doExp env e1), loc) | |
2407 | ESetval (e1, e2) => (ESetval (doExp env e1, doExp env e2), loc) | |
2408 | EUnurlify (e1, t, b) => (EUnurlify (doExp env e1, t, b), loc) | |
2409 | EJavaScript (m, e) => (EJavaScript (m, doExp env e), loc) | |
2410 | ESignalReturn _ => e | |
2411 | ESignalBind _ => e | |
2412 | ESignalSource _ => e | |
2413 | EServerCall _ => e | |
2414 | ERecv _ => e | |
2415 | ESleep _ => e | |
2416 | ESpawn _ => e | |
2417 | |
2418 val e = doExp env e | |
2419 in | |
2420 rfuns := IM.insert (!rfuns, n, {tables = !tables, cookies = !cookies, | |
2421 args = map (fn r => !r) modes, body = e}) | |
2422 end | |
2423 | |
2424 | DValRec _ => ErrorMsg.errorAt loc "Iflow can't check mutually-recursive functions yet." | |
2200 | 2425 |
2201 | DPolicy pol => | 2426 | DPolicy pol => |
2202 let | 2427 let |
2203 val rvN = ref 0 | 2428 val rvN = ref 0 |
2204 fun rv () = | 2429 fun rv () = |