Mercurial > urweb
comparison src/iflow.sml @ 1218:48d2ca496d2c
Path conditions, used to track implicit flows
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Sat, 10 Apr 2010 13:02:15 -0400 |
parents | 4d206e603300 |
children | 3224faec752d |
comparison
equal
deleted
inserted
replaced
1217:4d206e603300 | 1218:48d2ca496d2c |
---|---|
378 | _ => false | 378 | _ => false |
379 | 379 |
380 (* Congruence closure *) | 380 (* Congruence closure *) |
381 structure Cc :> sig | 381 structure Cc :> sig |
382 type database | 382 type database |
383 type representative | |
384 | 383 |
385 exception Contradiction | 384 exception Contradiction |
386 exception Undetermined | 385 exception Undetermined |
387 | 386 |
388 val database : unit -> database | 387 val database : unit -> database |
389 val representative : database * exp -> representative | |
390 | 388 |
391 val assert : database * atom -> unit | 389 val assert : database * atom -> unit |
392 val check : database * atom -> bool | 390 val check : database * atom -> bool |
393 | 391 |
394 val p_database : database Print.printer | 392 val p_database : database Print.printer |
393 | |
394 val builtFrom : database * {Base : exp list, Derived : exp} -> bool | |
395 end = struct | 395 end = struct |
396 | 396 |
397 exception Contradiction | 397 exception Contradiction |
398 exception Undetermined | 398 exception Undetermined |
399 | 399 |
418 type representative = node ref | 418 type representative = node ref |
419 | 419 |
420 val finish = ref (Node {Rep = ref NONE, | 420 val finish = ref (Node {Rep = ref NONE, |
421 Cons = ref SM.empty, | 421 Cons = ref SM.empty, |
422 Variety = VFinish, | 422 Variety = VFinish, |
423 Known = ref false}) | 423 Known = ref true}) |
424 | 424 |
425 type database = {Vars : representative IM.map ref, | 425 type database = {Vars : representative IM.map ref, |
426 Consts : representative CM.map ref, | 426 Consts : representative CM.map ref, |
427 Con0s : representative SM.map ref, | 427 Con0s : representative SM.map ref, |
428 Records : (representative SM.map * representative) list ref, | 428 Records : (representative SM.map * representative) list ref, |
468 newline, | 468 newline, |
469 p_list_sep newline (fn (i, n) => box [string ("x" ^ Int.toString i), | 469 p_list_sep newline (fn (i, n) => box [string ("x" ^ Int.toString i), |
470 space, | 470 space, |
471 string "=", | 471 string "=", |
472 space, | 472 space, |
473 p_rep n]) (IM.listItemsi (!(#Vars db)))] | 473 p_rep n, |
474 if !(#Known (unNode n)) then | |
475 box [space, | |
476 string "(known)"] | |
477 else | |
478 box []]) (IM.listItemsi (!(#Vars db)))] | |
474 | 479 |
475 fun repOf (n : representative) : representative = | 480 fun repOf (n : representative) : representative = |
476 case !(#Rep (unNode n)) of | 481 case !(#Rep (unNode n)) of |
477 NONE => n | 482 NONE => n |
478 | SOME r => | 483 | SOME r => |
482 #Rep (unNode n) := SOME r; | 487 #Rep (unNode n) := SOME r; |
483 r | 488 r |
484 end | 489 end |
485 | 490 |
486 fun markKnown r = | 491 fun markKnown r = |
487 (#Known (unNode r) := true; | 492 if !(#Known (unNode r)) then |
488 case #Variety (unNode r) of | 493 () |
489 Dt1 (_, r) => markKnown r | 494 else |
490 | Recrd xes => SM.app markKnown (!xes) | 495 (#Known (unNode r) := true; |
491 | _ => ()) | 496 SM.app markKnown (!(#Cons (unNode r))); |
497 case #Variety (unNode r) of | |
498 Dt1 (_, r) => markKnown r | |
499 | Recrd xes => SM.app markKnown (!xes) | |
500 | _ => ()) | |
492 | 501 |
493 fun representative (db : database, e) = | 502 fun representative (db : database, e) = |
494 let | 503 let |
495 fun rep e = | 504 fun rep e = |
496 case e of | 505 case e of |
527 | NONE => | 536 | NONE => |
528 let | 537 let |
529 val r = ref (Node {Rep = ref NONE, | 538 val r = ref (Node {Rep = ref NONE, |
530 Cons = ref SM.empty, | 539 Cons = ref SM.empty, |
531 Variety = Dt0 f, | 540 Variety = Dt0 f, |
532 Known = ref false}) | 541 Known = ref true}) |
533 in | 542 in |
534 #Con0s db := SM.insert (!(#Con0s db), f, r); | 543 #Con0s db := SM.insert (!(#Con0s db), f, r); |
535 r | 544 r |
536 end) | 545 end) |
537 | Func (DtCon0 _, _) => raise Fail "Iflow.rep: DtCon0" | 546 | Func (DtCon0 _, _) => raise Fail "Iflow.rep: DtCon0" |
745 in | 754 in |
746 unif (!xes1, !xes2); | 755 unif (!xes1, !xes2); |
747 unif (!xes2, !xes1) | 756 unif (!xes2, !xes1) |
748 end | 757 end |
749 | (VFinish, VFinish) => () | 758 | (VFinish, VFinish) => () |
750 | (Nothing, _) => | 759 | (Nothing, _) => mergeNodes (r1, r2) |
751 (#Rep (unNode r1) := SOME r2; | 760 | (_, Nothing) => mergeNodes (r2, r1) |
752 if !(#Known (unNode r1)) andalso not (!(#Known (unNode r2))) then | |
753 markKnown r2 | |
754 else | |
755 (); | |
756 #Cons (unNode r2) := SM.unionWith #1 (!(#Cons (unNode r2)), !(#Cons (unNode r1))); | |
757 compactFuncs ()) | |
758 | (_, Nothing) => | |
759 (#Rep (unNode r2) := SOME r1; | |
760 if !(#Known (unNode r2)) andalso not (!(#Known (unNode r1))) then | |
761 markKnown r1 | |
762 else | |
763 (); | |
764 #Cons (unNode r1) := SM.unionWith #1 (!(#Cons (unNode r1)), !(#Cons (unNode r2))); | |
765 compactFuncs ()) | |
766 | _ => raise Contradiction | 761 | _ => raise Contradiction |
762 | |
763 and mergeNodes (r1, r2) = | |
764 (#Rep (unNode r1) := SOME r2; | |
765 if !(#Known (unNode r1)) then | |
766 markKnown r2 | |
767 else | |
768 (); | |
769 if !(#Known (unNode r2)) then | |
770 markKnown r1 | |
771 else | |
772 (); | |
773 #Cons (unNode r2) := SM.unionWith #1 (!(#Cons (unNode r2)), !(#Cons (unNode r1))); | |
774 compactFuncs ()) | |
767 | 775 |
768 and compactFuncs () = | 776 and compactFuncs () = |
769 let | 777 let |
770 fun loop funcs = | 778 fun loop funcs = |
771 case funcs of | 779 case funcs of |
813 in | 821 in |
814 repOf r1 = repOf r2 | 822 repOf r1 = repOf r2 |
815 end | 823 end |
816 | _ => false | 824 | _ => false |
817 | 825 |
826 fun builtFrom (db, {Base = bs, Derived = d}) = | |
827 let | |
828 val bs = map (fn b => representative (db, b)) bs | |
829 | |
830 fun loop d = | |
831 let | |
832 val d = repOf d | |
833 in | |
834 List.exists (fn b => repOf b = d) bs | |
835 orelse case #Variety (unNode d) of | |
836 Dt0 _ => true | |
837 | Dt1 (_, d) => loop d | |
838 | Prim _ => true | |
839 | Recrd xes => List.all loop (SM.listItems (!xes)) | |
840 | VFinish => true | |
841 | Nothing => false | |
842 end | |
843 in | |
844 loop (representative (db, d)) | |
845 end | |
846 | |
818 end | 847 end |
819 | 848 |
820 fun decomp fals or = | 849 fun decomp fals or = |
821 let | 850 let |
822 fun decomp p k = | 851 fun decomp p k = |
834 | Cond x => k [ACond x] | 863 | Cond x => k [ACond x] |
835 in | 864 in |
836 decomp | 865 decomp |
837 end | 866 end |
838 | 867 |
839 fun imply (p1, p2) = | 868 fun imply (hyps, goals, outs) = |
840 decomp true (fn (e1, e2) => e1 andalso e2 ()) p1 | 869 let |
841 (fn hyps => | 870 fun gls goals onFail acc = |
842 decomp false (fn (e1, e2) => e1 orelse e2 ()) p2 | 871 case goals of |
843 (fn goals => | 872 [] => |
844 let | 873 (let |
845 fun gls goals onFail acc = | 874 val cc = Cc.database () |
846 case goals of | 875 val () = app (fn a => Cc.assert (cc, a)) hyps |
847 [] => | 876 in |
848 (let | 877 (List.all (fn a => |
849 val cc = Cc.database () | 878 if Cc.check (cc, a) then |
850 val () = app (fn a => Cc.assert (cc, a)) hyps | 879 true |
851 in | 880 else |
852 (List.all (fn a => | 881 ((*Print.prefaces "Can't prove" |
853 if Cc.check (cc, a) then | 882 [("a", p_atom a), |
854 true | 883 ("hyps", Print.p_list p_atom hyps), |
855 else | 884 ("db", Cc.p_database cc)];*) |
856 ((*Print.prefaces "Can't prove" | 885 false)) acc |
857 [("a", p_atom a), | 886 (*andalso (Print.preface ("Finding", Cc.p_database cc); true)*) |
858 ("hyps", Print.p_list p_atom hyps), | 887 andalso Cc.builtFrom (cc, {Derived = Var 0, |
859 ("db", Cc.p_database cc)];*) | 888 Base = outs})) |
860 false)) acc) | 889 handle Cc.Contradiction => false |
861 handle Cc.Contradiction => false | 890 end handle Cc.Undetermined => false) |
862 end handle Cc.Undetermined => false) | 891 orelse onFail () |
863 orelse onFail () | 892 | (g as AReln (Sql gf, [ge])) :: goals => |
864 | (g as AReln (Sql gf, [ge])) :: goals => | 893 let |
865 let | 894 fun hps hyps = |
866 fun hps hyps = | 895 case hyps of |
867 case hyps of | 896 [] => gls goals onFail (g :: acc) |
868 [] => gls goals onFail (g :: acc) | 897 | (h as AReln (Sql hf, [he])) :: hyps => |
869 | (h as AReln (Sql hf, [he])) :: hyps => | 898 if gf = hf then |
870 if gf = hf then | 899 let |
871 let | 900 val saved = save () |
872 val saved = save () | 901 in |
873 in | 902 if eq (ge, he) then |
874 if eq (ge, he) then | 903 let |
875 let | 904 val changed = IM.numItems (!unif) |
876 val changed = IM.numItems (!unif) | 905 <> IM.numItems saved |
877 <> IM.numItems saved | 906 in |
878 in | 907 gls goals (fn () => (restore saved; |
879 gls goals (fn () => (restore saved; | 908 changed |
880 changed | 909 andalso hps hyps)) |
881 andalso hps hyps)) | 910 acc |
882 acc | 911 end |
883 end | 912 else |
884 else | 913 hps hyps |
885 hps hyps | 914 end |
886 end | 915 else |
887 else | 916 hps hyps |
888 hps hyps | 917 | _ :: hyps => hps hyps |
889 | _ :: hyps => hps hyps | 918 in |
890 in | 919 hps hyps |
891 hps hyps | 920 end |
892 end | 921 | g :: goals => gls goals onFail (g :: acc) |
893 | g :: goals => gls goals onFail (g :: acc) | 922 in |
894 in | 923 reset (); |
895 reset (); | 924 (*Print.prefaces "Big go" [("hyps", Print.p_list p_atom hyps), |
896 (*Print.prefaces "Big go" [("hyps", Print.p_list p_atom hyps), | 925 ("goals", Print.p_list p_atom goals)];*) |
897 ("goals", Print.p_list p_atom goals)];*) | 926 gls goals (fn () => false) [] |
898 gls goals (fn () => false) [] | 927 end handle Cc.Contradiction => true |
899 end handle Cc.Contradiction => true)) | |
900 | 928 |
901 fun patCon pc = | 929 fun patCon pc = |
902 case pc of | 930 case pc of |
903 PConVar n => "C" ^ Int.toString n | 931 PConVar n => "C" ^ Int.toString n |
904 | PConFfi {mod = m, datatyp = d, con = c, ...} => m ^ "." ^ d ^ "." ^ c | 932 | PConFfi {mod = m, datatyp = d, con = c, ...} => m ^ "." ^ d ^ "." ^ c |
1202 else | 1230 else |
1203 x :: ls | 1231 x :: ls |
1204 end | 1232 end |
1205 | 1233 |
1206 datatype queryMode = | 1234 datatype queryMode = |
1207 SomeCol of exp | 1235 SomeCol |
1208 | AllCols of exp | 1236 | AllCols of exp |
1209 | 1237 |
1210 exception Default | 1238 exception Default |
1211 | 1239 |
1212 fun queryProp env rvN rv oe e = | 1240 fun queryProp env rvN rv oe e = |
1213 let | 1241 let |
1214 fun default () = (print ("Warning: Information flow checker can't parse SQL query at " | 1242 fun default () = (print ("Warning: Information flow checker can't parse SQL query at " |
1215 ^ ErrorMsg.spanToString (#2 e) ^ "\n"); | 1243 ^ ErrorMsg.spanToString (#2 e) ^ "\n"); |
1216 (rvN, Unknown, Unknown, [])) | 1244 (rvN, Unknown, Unknown, [], [])) |
1217 in | 1245 in |
1218 case parse query e of | 1246 case parse query e of |
1219 NONE => default () | 1247 NONE => default () |
1220 | SOME r => | 1248 | SOME r => |
1221 let | 1249 let |
1279 case expIn e of | 1307 case expIn e of |
1280 inr p' => And (p, p') | 1308 inr p' => And (p, p') |
1281 | _ => p | 1309 | _ => p |
1282 | 1310 |
1283 fun normal () = | 1311 fun normal () = |
1284 (And (p, case oe of | 1312 case oe of |
1285 SomeCol oe => | 1313 SomeCol => |
1286 foldl (fn (si, p) => | 1314 (rvN, p, True, |
1287 let | 1315 List.mapPartial (fn si => |
1288 val p' = case si of | 1316 case si of |
1289 SqField (v, f) => Reln (Eq, [oe, Proj (rvOf v, f)]) | 1317 SqField (v, f) => SOME (Proj (rvOf v, f)) |
1290 | SqExp (e, f) => | 1318 | SqExp (e, f) => |
1291 case expIn e of | 1319 case expIn e of |
1292 inr _ => Unknown | 1320 inr _ => NONE |
1293 | inl e => Reln (Eq, [oe, e]) | 1321 | inl e => SOME e) (#Select r)) |
1294 in | 1322 | AllCols oe => |
1295 Or (p, p') | 1323 (rvN, And (p, foldl (fn (si, p) => |
1296 end) | 1324 let |
1297 False (#Select r) | 1325 val p' = case si of |
1298 | AllCols oe => | 1326 SqField (v, f) => Reln (Eq, [Proj (Proj (oe, v), f), |
1299 foldl (fn (si, p) => | 1327 Proj (rvOf v, f)]) |
1300 let | 1328 | SqExp (e, f) => |
1301 val p' = case si of | 1329 case expIn e of |
1302 SqField (v, f) => Reln (Eq, [Proj (Proj (oe, v), f), | 1330 inr p => Cond (Proj (oe, f), p) |
1303 Proj (rvOf v, f)]) | 1331 | inl e => Reln (Eq, [Proj (oe, f), e]) |
1304 | SqExp (e, f) => | 1332 in |
1305 case expIn e of | |
1306 inr p => Cond (Proj (oe, f), p) | |
1307 | inl e => Reln (Eq, [Proj (oe, f), e]) | |
1308 in | |
1309 And (p, p') | 1333 And (p, p') |
1310 end) | 1334 end) |
1311 True (#Select r)), | 1335 True (#Select r)), |
1312 True) | 1336 True, []) |
1313 | 1337 |
1314 val (p, wp) = | 1338 val (rvN, p, wp, outs) = |
1315 case #Select r of | 1339 case #Select r of |
1316 [SqExp (Binop (Exps bo, Count, SqConst (Prim.Int 0)), f)] => | 1340 [SqExp (Binop (Exps bo, Count, SqConst (Prim.Int 0)), f)] => |
1317 (case bo (Const (Prim.Int 1), Const (Prim.Int 2)) of | 1341 (case bo (Const (Prim.Int 1), Const (Prim.Int 2)) of |
1318 Reln (Gt, [Const (Prim.Int 1), Const (Prim.Int 2)]) => | 1342 Reln (Gt, [Const (Prim.Int 1), Const (Prim.Int 2)]) => |
1319 let | 1343 (case oe of |
1320 val oe = case oe of | 1344 SomeCol => |
1321 SomeCol oe => oe | 1345 let |
1322 | AllCols oe => Proj (oe, f) | 1346 val (rvN, oe) = rv rvN |
1323 in | 1347 in |
1324 (Or (Reln (Eq, [oe, Func (DtCon0 "Basis.bool.False", [])]), | 1348 (rvN, |
1325 And (Reln (Eq, [oe, Func (DtCon0 "Basis.bool.True", [])]), | 1349 Or (Reln (Eq, [oe, Func (DtCon0 "Basis.bool.False", [])]), |
1326 p)), | 1350 And (Reln (Eq, [oe, Func (DtCon0 "Basis.bool.True", [])]), |
1327 Reln (Eq, [oe, Func (DtCon0 "Basis.bool.True", [])])) | 1351 p)), |
1328 end | 1352 Reln (Eq, [oe, Func (DtCon0 "Basis.bool.True", [])]), |
1353 [oe]) | |
1354 end | |
1355 | AllCols oe => | |
1356 let | |
1357 val oe = Proj (oe, f) | |
1358 in | |
1359 (rvN, | |
1360 Or (Reln (Eq, [oe, Func (DtCon0 "Basis.bool.False", [])]), | |
1361 And (Reln (Eq, [oe, Func (DtCon0 "Basis.bool.True", [])]), | |
1362 p)), | |
1363 Reln (Eq, [oe, Func (DtCon0 "Basis.bool.True", [])]), | |
1364 []) | |
1365 end) | |
1329 | _ => normal ()) | 1366 | _ => normal ()) |
1330 | _ => normal () | 1367 | _ => normal () |
1331 in | 1368 in |
1332 (rvN, p, wp, case #Where r of | 1369 (rvN, p, wp, case #Where r of |
1333 NONE => [] | 1370 NONE => [] |
1334 | SOME e => map (fn (v, f) => Proj (rvOf v, f)) (usedFields e)) | 1371 | SOME e => map (fn (v, f) => Proj (rvOf v, f)) (usedFields e), outs) |
1335 end | 1372 end |
1336 handle Default => default () | 1373 handle Default => default () |
1337 end | 1374 end |
1338 | 1375 |
1339 fun evalPat env e (pt, _) = | 1376 fun evalPat env e (pt, _) = |
1386 | _ => p2 | 1423 | _ => p2 |
1387 in | 1424 in |
1388 rr | 1425 rr |
1389 end | 1426 end |
1390 | 1427 |
1428 datatype cflow = Case | Where | |
1429 datatype flow = Data | Control of cflow | |
1430 type check = ErrorMsg.span * exp * prop | |
1431 | |
1391 structure St :> sig | 1432 structure St :> sig |
1392 type t | 1433 type t |
1393 val create : {Var : int, | 1434 val create : {Var : int, |
1394 Ambient : prop} -> t | 1435 Ambient : prop} -> t |
1395 | 1436 |
1397 val nextVar : t -> t * int | 1438 val nextVar : t -> t * int |
1398 | 1439 |
1399 val ambient : t -> prop | 1440 val ambient : t -> prop |
1400 val setAmbient : t * prop -> t | 1441 val setAmbient : t * prop -> t |
1401 | 1442 |
1402 type check = ErrorMsg.span * exp * prop | 1443 val paths : t -> (check * cflow) list |
1403 | 1444 val addPath : t * (check * cflow) -> t |
1404 val path : t -> check list | 1445 val addPaths : t * (check * cflow) list -> t |
1405 val addPath : t * check -> t | 1446 val clearPaths : t -> t |
1406 | 1447 val setPaths : t * (check * cflow) list -> t |
1407 val sent : t -> check list | 1448 |
1408 val addSent : t * check -> t | 1449 val sent : t -> (check * flow) list |
1409 val setSent : t * check list -> t | 1450 val addSent : t * (check * flow) -> t |
1451 val setSent : t * (check * flow) list -> t | |
1410 end = struct | 1452 end = struct |
1411 | |
1412 type check = ErrorMsg.span * exp * prop | |
1413 | 1453 |
1414 type t = {Var : int, | 1454 type t = {Var : int, |
1415 Ambient : prop, | 1455 Ambient : prop, |
1416 Path : check list, | 1456 Path : (check * cflow) list, |
1417 Sent : check list} | 1457 Sent : (check * flow) list} |
1418 | 1458 |
1419 fun create {Var = v, Ambient = p} = {Var = v, | 1459 fun create {Var = v, Ambient = p} = {Var = v, |
1420 Ambient = p, | 1460 Ambient = p, |
1421 Path = [], | 1461 Path = [], |
1422 Sent = []} | 1462 Sent = []} |
1431 fun setAmbient (t : t, p) = {Var = #Var t, | 1471 fun setAmbient (t : t, p) = {Var = #Var t, |
1432 Ambient = p, | 1472 Ambient = p, |
1433 Path = #Path t, | 1473 Path = #Path t, |
1434 Sent = #Sent t} | 1474 Sent = #Sent t} |
1435 | 1475 |
1436 fun path (t : t) = #Path t | 1476 fun paths (t : t) = #Path t |
1437 fun addPath (t : t, c) = {Var = #Var t, | 1477 fun addPath (t : t, c) = {Var = #Var t, |
1438 Ambient = #Ambient t, | 1478 Ambient = #Ambient t, |
1439 Path = c :: #Path t, | 1479 Path = c :: #Path t, |
1440 Sent = #Sent t} | 1480 Sent = #Sent t} |
1481 fun addPaths (t : t, cs) = {Var = #Var t, | |
1482 Ambient = #Ambient t, | |
1483 Path = cs @ #Path t, | |
1484 Sent = #Sent t} | |
1485 fun clearPaths (t : t) = {Var = #Var t, | |
1486 Ambient = #Ambient t, | |
1487 Path = [], | |
1488 Sent = #Sent t} | |
1489 fun setPaths (t : t, cs) = {Var = #Var t, | |
1490 Ambient = #Ambient t, | |
1491 Path = cs, | |
1492 Sent = #Sent t} | |
1441 | 1493 |
1442 fun sent (t : t) = #Sent t | 1494 fun sent (t : t) = #Sent t |
1443 fun addSent (t : t, c) = {Var = #Var t, | 1495 fun addSent (t : t, c) = {Var = #Var t, |
1444 Ambient = #Ambient t, | 1496 Ambient = #Ambient t, |
1445 Path = #Path t, | 1497 Path = #Path t, |
1459 in | 1511 in |
1460 (Var nv, st) | 1512 (Var nv, st) |
1461 end | 1513 end |
1462 | 1514 |
1463 fun addSent (p, e, st) = | 1515 fun addSent (p, e, st) = |
1464 if isKnown e then | 1516 let |
1465 st | 1517 val st = if isKnown e then |
1466 else | 1518 st |
1467 St.addSent (st, (loc, e, p)) | 1519 else |
1520 St.addSent (st, ((loc, e, p), Data)) | |
1521 | |
1522 val st = foldl (fn ((c, fl), st) => St.addSent (st, (c, Control fl))) st (St.paths st) | |
1523 in | |
1524 St.clearPaths st | |
1525 end | |
1468 in | 1526 in |
1469 case #1 e of | 1527 case #1 e of |
1470 EPrim p => (Const p, st) | 1528 EPrim p => (Const p, st) |
1471 | ERel n => (List.nth (env, n), st) | 1529 | ERel n => (List.nth (env, n), st) |
1472 | ENamed _ => default () | 1530 | ENamed _ => default () |
1540 let | 1598 let |
1541 val (e, st) = evalExp env (e, st) | 1599 val (e, st) = evalExp env (e, st) |
1542 in | 1600 in |
1543 (Proj (e, s), st) | 1601 (Proj (e, s), st) |
1544 end | 1602 end |
1545 | ECase (e, pes, _) => | 1603 | ECase (e, pes, {result = res, ...}) => |
1546 let | 1604 let |
1547 val (e, st) = evalExp env (e, st) | 1605 val (e, st) = evalExp env (e, st) |
1548 val (st, r) = St.nextVar st | 1606 val (st, r) = St.nextVar st |
1549 val orig = St.ambient st | 1607 val orig = St.ambient st |
1550 | 1608 val origPaths = St.paths st |
1551 val st = foldl (fn ((pt, pe), st) => | 1609 |
1552 let | 1610 val st = St.addPath (st, ((loc, e, orig), Case)) |
1553 val (env, pp) = evalPat env e pt | 1611 |
1554 val (pe, st') = evalExp env (pe, St.setAmbient (st, And (orig, pp))) | 1612 val (st, paths) = |
1555 (*val () = Print.prefaces "Case" [("loc", Print.PD.string | 1613 foldl (fn ((pt, pe), (st, paths)) => |
1556 (ErrorMsg.spanToString (#2 pt))), | 1614 let |
1557 ("env", Print.p_list p_exp env), | 1615 val (env, pp) = evalPat env e pt |
1558 ("sent", Print.p_list_sep Print.PD.newline | 1616 val (pe, st') = evalExp env (pe, St.setAmbient (st, And (orig, pp))) |
1559 (fn (loc, e, p) => | 1617 |
1560 Print.box [Print.PD.string | 1618 val this = And (removeRedundant orig (St.ambient st'), |
1561 (ErrorMsg.spanToString loc), | 1619 Reln (Eq, [Var r, pe])) |
1562 Print.PD.string ":", | 1620 in |
1563 Print.space, | 1621 (St.setPaths (St.setAmbient (st', Or (St.ambient st, this)), origPaths), |
1564 p_exp e, | 1622 St.paths st' @ paths) |
1565 Print.space, | 1623 end) (St.setAmbient (st, False), []) pes |
1566 Print.PD.string "in", | 1624 |
1567 Print.space, | 1625 val st = case #1 res of |
1568 p_prop p]) | 1626 TRecord [] => St.setPaths (st, origPaths) |
1569 (List.take (#3 st', length (#3 st') | 1627 | _ => St.setPaths (st, paths) |
1570 - length (#3 st))))]*) | |
1571 | |
1572 val this = And (removeRedundant orig (St.ambient st'), | |
1573 Reln (Eq, [Var r, pe])) | |
1574 in | |
1575 St.setAmbient (st', Or (St.ambient st, this)) | |
1576 end) (St.setAmbient (st, False)) pes | |
1577 in | 1628 in |
1578 (Var r, St.setAmbient (st, And (orig, St.ambient st))) | 1629 (Var r, St.setAmbient (st, And (orig, St.ambient st))) |
1579 end | 1630 end |
1580 | EStrcat (e1, e2) => | 1631 | EStrcat (e1, e2) => |
1581 let | 1632 let |
1631 val (st', r) = St.nextVar st | 1682 val (st', r) = St.nextVar st |
1632 val (st', acc) = St.nextVar st' | 1683 val (st', acc) = St.nextVar st' |
1633 | 1684 |
1634 val (b, st') = evalExp (Var acc :: Var r :: env) (b, st') | 1685 val (b, st') = evalExp (Var acc :: Var r :: env) (b, st') |
1635 | 1686 |
1636 val (st', qp, qwp, used) = | 1687 val (st', qp, qwp, used, _) = |
1637 queryProp env | 1688 queryProp env |
1638 st' (fn st' => | 1689 st' (fn st' => |
1639 let | 1690 let |
1640 val (st', rv) = St.nextVar st' | 1691 val (st', rv) = St.nextVar st' |
1641 in | 1692 in |
1660 p')) | 1711 p')) |
1661 in | 1712 in |
1662 (St.setAmbient (st, p), Var out) | 1713 (St.setAmbient (st, p), Var out) |
1663 end | 1714 end |
1664 | 1715 |
1665 val sent = map (fn (loc, e, p) => (loc, e, And (qp, p))) (St.sent st') | 1716 val sent = map (fn ((loc, e, p), fl) => ((loc, e, And (qp, p)), fl)) (St.sent st') |
1666 | 1717 |
1667 val p' = And (p', qwp) | 1718 val p' = And (p', qwp) |
1668 val sent = map (fn e => (loc, e, p')) used @ sent | 1719 val paths = map (fn e => ((loc, e, p'), Where)) used |
1669 in | 1720 in |
1670 (res, St.setSent (st, sent)) | 1721 (res, St.addPaths (St.setSent (st, sent), paths)) |
1671 end | 1722 end |
1672 | EDml _ => default () | 1723 | EDml _ => default () |
1673 | ENextval _ => default () | 1724 | ENextval _ => default () |
1674 | ESetval _ => default () | 1725 | ESetval _ => default () |
1675 | 1726 |
1726 Ambient = p}) | 1777 Ambient = p}) |
1727 in | 1778 in |
1728 (St.sent st @ vals, pols) | 1779 (St.sent st @ vals, pols) |
1729 end | 1780 end |
1730 | 1781 |
1731 | DPolicy (PolClient e) => (vals, #2 (queryProp [] 0 (fn rvN => (rvN + 1, Lvar rvN)) | 1782 | DPolicy (PolClient e) => |
1732 (SomeCol (Var 0)) e) :: pols) | 1783 let |
1784 val (_, p, _, _, outs) = queryProp [] 0 (fn rvN => (rvN + 1, Lvar rvN)) SomeCol e | |
1785 in | |
1786 (vals, (p, outs) :: pols) | |
1787 end | |
1733 | 1788 |
1734 | _ => (vals, pols) | 1789 | _ => (vals, pols) |
1735 | 1790 |
1736 val () = reset () | 1791 val () = reset () |
1737 | 1792 |
1738 val (vals, pols) = foldl decl ([], []) file | 1793 val (vals, pols) = foldl decl ([], []) file |
1739 in | 1794 in |
1740 app (fn (loc, e, p) => | 1795 app (fn ((loc, e, p), fl) => |
1741 let | 1796 let |
1742 fun doOne e = | 1797 fun doOne e = |
1743 let | 1798 let |
1744 val p = And (p, Reln (Eq, [Var 0, e])) | 1799 val p = And (p, Reln (Eq, [Var 0, e])) |
1745 in | 1800 in |
1746 if List.exists (fn pol => if imply (p, pol) then | 1801 if decomp true (fn (e1, e2) => e1 andalso e2 ()) p |
1747 (if !debug then | 1802 (fn hyps => |
1748 Print.prefaces "Match" | 1803 (fl <> Control Where |
1749 [("Hyp", p_prop p), | 1804 andalso imply (hyps, [AReln (Known, [Var 0])], [Var 0])) |
1750 ("Goal", p_prop pol)] | 1805 orelse List.exists (fn (p', outs) => |
1751 else | 1806 decomp false (fn (e1, e2) => e1 orelse e2 ()) p' |
1752 (); | 1807 (fn goals => imply (hyps, goals, outs))) |
1753 true) | 1808 pols) then |
1754 else | |
1755 false) pols then | |
1756 () | 1809 () |
1757 else | 1810 else |
1758 (ErrorMsg.errorAt loc "The information flow policy may be violated here."; | 1811 (ErrorMsg.errorAt loc "The information flow policy may be violated here."; |
1759 Print.preface ("The state satisifies this predicate:", p_prop p)) | 1812 Print.preface ("The state satisifies this predicate:", p_prop p)) |
1760 end | 1813 end |