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 () =