comparison src/iflow.sml @ 1208:b5a4c5407ae0

Checking known() correctly, according to a pair of examples
author Adam Chlipala <adamc@hcoop.net>
date Tue, 06 Apr 2010 10:39:15 -0400
parents ae3036773768
children 775357041e48
comparison
equal deleted inserted replaced
1207:ae3036773768 1208:b5a4c5407ae0
210 fun isFinish e = 210 fun isFinish e =
211 case e of 211 case e of
212 Finish => true 212 Finish => true
213 | _ => false 213 | _ => false
214 214
215 val unif = ref (IM.empty : exp IM.map)
216
217 fun reset () = unif := IM.empty
218 fun save () = !unif
219 fun restore x = unif := x
220
215 fun simplify e = 221 fun simplify e =
216 case e of 222 case e of
217 Const _ => e 223 Const _ => e
218 | Var _ => e 224 | Var _ => e
219 | Lvar _ => e 225 | Lvar n =>
226 (case IM.find (!unif, n) of
227 NONE => e
228 | SOME e => simplify e)
220 | Func (f, es) => 229 | Func (f, es) =>
221 let 230 let
222 val es = map simplify es 231 val es = map simplify es
223 in 232 in
224 if List.exists isFinish es then 233 if List.exists isFinish es then
263 | Select _ => k [] 272 | Select _ => k []
264 in 273 in
265 decomp 274 decomp
266 end 275 end
267 276
268 val unif = ref (IM.empty : exp IM.map)
269
270 fun reset () = unif := IM.empty
271 fun save () = !unif
272 fun restore x = unif := x
273
274 fun lvarIn lv = 277 fun lvarIn lv =
275 let 278 let
276 fun lvi e = 279 fun lvi e =
277 case e of 280 case e of
278 Const _ => false 281 Const _ => false
298 case e2 of 301 case e2 of
299 Lvar n2 => 302 Lvar n2 =>
300 (case IM.find (!unif, n2) of 303 (case IM.find (!unif, n2) of
301 SOME e2 => eq' (e1, e2) 304 SOME e2 => eq' (e1, e2)
302 | NONE => n1 = n2 305 | NONE => n1 = n2
303 orelse (unif := IM.insert (!unif, n1, e2); 306 orelse (unif := IM.insert (!unif, n2, e1);
304 true)) 307 true))
305 | _ => 308 | _ =>
306 if lvarIn n1 e2 then 309 if lvarIn n1 e2 then
307 false 310 false
308 else 311 else
336 false) 339 false)
337 end 340 end
338 341
339 exception Imply of prop * prop 342 exception Imply of prop * prop
340 343
341 fun rimp ((r1, es1), (r2, es2)) = 344 val debug = ref false
345
346 (* Congruence closure *)
347 structure Cc :> sig
348 type t
349 val empty : t
350 val assert : t * exp * exp -> t
351 val query : t * exp * exp -> bool
352 val allPeers : t * exp -> exp list
353 end = struct
354
355 fun eq' (e1, e2) =
356 case (e1, e2) of
357 (Const p1, Const p2) => Prim.equal (p1, p2)
358 | (Var n1, Var n2) => n1 = n2
359 | (Lvar n1, Lvar n2) => n1 = n2
360 | (Func (f1, es1), Func (f2, es2)) => f1 = f2 andalso ListPair.allEq eq' (es1, es2)
361 | (Recd xes1, Recd xes2) => length xes1 = length xes2 andalso
362 List.all (fn (x2, e2) =>
363 List.exists (fn (x1, e1) => x1 = x2 andalso eq' (e1, e2)) xes2) xes1
364 | (Proj (e1, x1), Proj (e2, x2)) => eq' (e1, e2) andalso x1 = x2
365 | (Finish, Finish) => true
366 | _ => false
367
368 fun eq (e1, e2) = eq' (simplify e1, simplify e2)
369
370 type t = (exp * exp) list
371
372 val empty = []
373
374 fun lookup (t, e) =
375 case List.find (fn (e', _) => eq (e', e)) t of
376 NONE => e
377 | SOME (_, e2) => lookup (t, e2)
378
379 fun assert (t, e1, e2) =
380 let
381 val r1 = lookup (t, e1)
382 val r2 = lookup (t, e2)
383 in
384 if eq (r1, r2) then
385 t
386 else
387 (r1, r2) :: t
388 end
389
390 open Print
391
392 fun query (t, e1, e2) =
393 (if !debug then
394 prefaces "CC query" [("e1", p_exp (simplify e1)),
395 ("e2", p_exp (simplify e2)),
396 ("t", p_list (fn (e1, e2) => box [p_exp (simplify e1),
397 space,
398 PD.string "->",
399 space,
400 p_exp (simplify e2)]) t)]
401 else
402 ();
403 eq (lookup (t, e1), lookup (t, e2)))
404
405 fun allPeers (t, e) =
406 let
407 val r = lookup (t, e)
408 in
409 r :: List.mapPartial (fn (e1, e2) =>
410 let
411 val r' = lookup (t, e2)
412 in
413 if eq (r, r') then
414 SOME e1
415 else
416 NONE
417 end) t
418 end
419
420 end
421
422 fun rimp cc ((r1, es1), (r2, es2)) =
342 case (r1, r2) of 423 case (r1, r2) of
343 (Sql r1', Sql r2') => 424 (Sql r1', Sql r2') =>
344 r1' = r2' andalso 425 r1' = r2' andalso
345 (case (es1, es2) of 426 (case (es1, es2) of
346 ([Recd xes1], [Recd xes2]) => 427 ([Recd xes1], [Recd xes2]) =>
365 in 446 in
366 if eq (x1, x2) andalso eq (y1, y2) then 447 if eq (x1, x2) andalso eq (y1, y2) then
367 true 448 true
368 else 449 else
369 (restore saved; 450 (restore saved;
370 (*raise Imply (Reln (Eq, es1), Reln (Eq, es2));*) 451 if eq (x1, y2) andalso eq (y1, x2) then
371 eq (x1, y2) andalso eq (y1, x2)) 452 true
453 else
454 (restore saved;
455 false))
372 end 456 end
373 | _ => false) 457 | _ => false)
374 | (Known, Known) => 458 | (Known, Known) =>
375 (case (es1, es2) of 459 (case (es1, es2) of
376 ([e1], [e2]) => 460 ([Var v], [e2]) =>
377 let 461 let
378 fun walk e2 = 462 fun matches e =
379 eq (e1, e2) orelse 463 case e of
380 case e2 of 464 Var v' => v' = v
381 Proj (e2, _) => walk e2 465 | Proj (e, _) => matches e
382 | _ => false 466 | _ => false
383 in 467 in
384 walk e2 468 List.exists matches (Cc.allPeers (cc, e2))
385 end 469 end
386 | _ => false) 470 | _ => false)
387 | _ => false 471 | _ => false
388 472
389 fun imply (p1, p2) = 473 fun imply (p1, p2) =
390 (reset (); 474 let
391 (*raise (Imply (p1, p2));*) 475 fun doOne doKnown =
392 decomp true (fn (e1, e2) => e1 andalso e2 ()) p1 476 decomp true (fn (e1, e2) => e1 andalso e2 ()) p1
393 (fn hyps => 477 (fn hyps =>
394 decomp false (fn (e1, e2) => e1 orelse e2 ()) p2 478 decomp false (fn (e1, e2) => e1 orelse e2 ()) p2
395 (fn goals => 479 (fn goals =>
396 let 480 let
397 fun gls goals onFail = 481 val cc = foldl (fn (p, cc) =>
398 case goals of 482 case p of
399 [] => true 483 (Eq, [e1, e2]) => Cc.assert (cc, e1, e2)
400 | g :: goals => 484 | _ => cc) Cc.empty hyps
401 let 485
402 fun hps hyps = 486 fun gls goals onFail =
403 case hyps of 487 case goals of
404 [] => onFail () 488 [] => true
405 | h :: hyps => 489 | g :: goals =>
406 let 490 case (doKnown, g) of
407 val saved = save () 491 (false, (Known, _)) => gls goals onFail
408 in 492 | _ =>
409 if rimp (h, g) then 493 let
410 let 494 fun hps hyps =
411 val changed = IM.numItems (!unif) <> IM.numItems saved 495 case hyps of
412 in 496 [] => onFail ()
413 gls goals (fn () => (restore saved; 497 | h :: hyps =>
414 changed andalso hps hyps)) 498 let
415 end 499 val saved = save ()
416 else 500 in
417 hps hyps 501 if rimp cc (h, g) then
418 end 502 let
419 in 503 val changed = IM.numItems (!unif)
420 hps hyps 504 <> IM.numItems saved
421 end 505 in
422 in 506 gls goals (fn () => (restore saved;
423 gls goals (fn () => false) 507 changed andalso hps hyps))
424 end))) 508 end
425 509 else
510 hps hyps
511 end
512 in
513 (case g of
514 (Eq, [e1, e2]) => Cc.query (cc, e1, e2)
515 | _ => false)
516 orelse hps hyps
517 end
518 in
519 gls goals (fn () => false)
520 end))
521 in
522 reset ();
523 doOne false;
524 doOne true
525 end
426 526
427 fun patCon pc = 527 fun patCon pc =
428 case pc of 528 case pc of
429 PConVar n => "C" ^ Int.toString n 529 PConVar n => "C" ^ Int.toString n
430 | PConFfi {mod = m, datatyp = d, con = c, ...} => m ^ "." ^ d ^ "." ^ c 530 | PConFfi {mod = m, datatyp = d, con = c, ...} => m ^ "." ^ d ^ "." ^ c
528 end 628 end
529 | _ => NONE 629 | _ => NONE
530 630
531 fun ws p = wrap (follow (skip (fn ch => ch = #" ")) 631 fun ws p = wrap (follow (skip (fn ch => ch = #" "))
532 (follow p (skip (fn ch => ch = #" ")))) (#1 o #2) 632 (follow p (skip (fn ch => ch = #" ")))) (#1 o #2)
533
534 val debug = ref false
535 633
536 fun log name p chs = 634 fun log name p chs =
537 (if !debug then 635 (if !debug then
538 case chs of 636 case chs of
539 String s :: _ => print (name ^ ": " ^ s ^ "\n") 637 String s :: _ => print (name ^ ": " ^ s ^ "\n")
922 in 1020 in
923 app (fn (loc, e, p) => 1021 app (fn (loc, e, p) =>
924 let 1022 let
925 val p = And (p, Reln (Eq, [Var 0, e])) 1023 val p = And (p, Reln (Eq, [Var 0, e]))
926 in 1024 in
927 if List.exists (fn pol => imply (p, pol)) pols then 1025 if List.exists (fn pol => if imply (p, pol) then
1026 (if !debug then
1027 Print.prefaces "Match"
1028 [("Hyp", p_prop p),
1029 ("Goal", p_prop pol)]
1030 else
1031 ();
1032 true)
1033 else
1034 false) pols then
928 () 1035 ()
929 else 1036 else
930 (ErrorMsg.errorAt loc "The information flow policy may be violated here."; 1037 (ErrorMsg.errorAt loc "The information flow policy may be violated here.";
931 Print.preface ("The state satisifes this predicate:", p_prop p)) 1038 Print.preface ("The state satisifes this predicate:", p_prop p))
932 end) vals 1039 end) vals