Mercurial > urweb
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 |