# HG changeset patch # User wenzelm # Date 1729262573 -7200 # Node ID 60fedd5b7c5813621ae4a6d026aa3dcca88ecf49 # Parent 47a0dfee26eaadd565b98349aa1f83a8a53f22cd tuned whitespace; diff -r 47a0dfee26ea -r 60fedd5b7c58 src/HOL/Hoare/SchorrWaite.thy --- a/src/HOL/Hoare/SchorrWaite.thy Fri Oct 18 16:37:39 2024 +0200 +++ b/src/HOL/Hoare/SchorrWaite.thy Fri Oct 18 16:42:53 2024 +0200 @@ -153,7 +153,7 @@ where stkOk_nil: "stkOk c l r iL iR t [] = True" | stkOk_cons: - "stkOk c l r iL iR t (p#stk) = (stkOk c l r iL iR (Ref p) (stk) \ + "stkOk c l r iL iR t (p#stk) = (stkOk c l r iL iR (Ref p) (stk) \ iL p = (if c p then l p else t) \ iR p = (if c p then t else r p))" @@ -198,9 +198,9 @@ subsection \The Schorr-Waite algorithm\ -theorem SchorrWaiteAlgorithm: +theorem SchorrWaiteAlgorithm: "VARS c m l r t p q root - {R = reachable (relS {l, r}) {root} \ (\x. \ m x) \ iR = r \ iL = l} + {R = reachable (relS {l, r}) {root} \ (\x. \ m x) \ iR = r \ iL = l} t := root; p := Null; WHILE p \ Null \ t \ Null \ \ t^.m INV {\stack. @@ -216,7 +216,7 @@ THEN IF p^.c THEN q := t; t := p; p := p^.r; t^.r := q \ \\pop\\ ELSE q := t; t := p^.r; p^.r := p^.l; \ \\swing\\ - p^.l := q; p^.c := True FI + p^.l := q; p^.c := True FI ELSE q := p; p := t; t := t^.l; p^.l := q; \ \\push\\ p^.m := True; p^.c := False FI OD {(\x. (x \ R) = m x) \ (r = iR \ l = iL) }" @@ -226,15 +226,13 @@ (Aseq _ (Aseq _ (Awhile {(c, m, l, r, t, p, q, root). ?inv c m l r t p} _ _))) _") proof (vcg) { - fix c m l r t p q root assume "?Pre c m l r root" thus "?inv c m l r root Null" by (auto simp add: reachable_def addrs_def) next - fix c m l r t p q let "\stack. ?Inv stack" = "?inv c m l r t p" - assume a: "?inv c m l r t p \ \(p \ Null \ t \ Null \ \ t^.m)" + assume a: "?inv c m l r t p \ \(p \ Null \ t \ Null \ \ t^.m)" then obtain stack where inv: "?Inv stack" by blast from a have pNull: "p = Null" and tDisj: "t=Null \ (t\Null \ t^.m )" by auto let "?I1 \ _ \ _ \ ?I4 \ ?I5 \ ?I6 \ _" = "?Inv stack" @@ -242,336 +240,335 @@ from pNull i1 have stackEmpty: "stack = []" by simp from tDisj i4 have RisMarked[rule_format]: "\x. x \ R \ m x" by(auto simp: reachable_def addrs_def stackEmpty) from i5 i6 show "(\x.(x \ R) = m x) \ r = iR \ l = iL" by(auto simp: stackEmpty fun_eq_iff intro:RisMarked) - - next - fix c m l r t p q root - let "\stack. ?Inv stack" = "?inv c m l r t p" - let "\stack. ?popInv stack" = "?inv c m l (r(p \ t)) p (p^.r)" - let "\stack. ?swInv stack" = - "?inv (c(p \ True)) m (l(p \ t)) (r(p \ p^.l)) (p^.r) p" - let "\stack. ?puInv stack" = - "?inv (c(t \ False)) (m(t \ True)) (l(t \ p)) r (t^.l) t" - let "?ifB1" = "(t = Null \ t^.m)" - let "?ifB2" = "p^.c" - - assume "(\stack.?Inv stack) \ ?whileB m t p" - then obtain stack where inv: "?Inv stack" and whileB: "?whileB m t p" by blast - let "?I1 \ ?I2 \ ?I3 \ ?I4 \ ?I5 \ ?I6 \ ?I7" = "?Inv stack" - from inv have i1: "?I1" and i2: "?I2" and i3: "?I3" and i4: "?I4" - and i5: "?I5" and i6: "?I6" and i7: "?I7" by simp+ - have stackDist: "distinct (stack)" using i1 by (rule List_distinct) + next + fix c m l r t p q root + let "\stack. ?Inv stack" = "?inv c m l r t p" + let "\stack. ?popInv stack" = "?inv c m l (r(p \ t)) p (p^.r)" + let "\stack. ?swInv stack" = + "?inv (c(p \ True)) m (l(p \ t)) (r(p \ p^.l)) (p^.r) p" + let "\stack. ?puInv stack" = + "?inv (c(t \ False)) (m(t \ True)) (l(t \ p)) r (t^.l) t" + let "?ifB1" = "(t = Null \ t^.m)" + let "?ifB2" = "p^.c" - show "(?ifB1 \ (?ifB2 \ (\stack.?popInv stack)) \ - (\?ifB2 \ (\stack.?swInv stack)) ) \ - (\?ifB1 \ (\stack.?puInv stack))" - proof - - { - assume ifB1: "t = Null \ t^.m" and ifB2: "p^.c" - from ifB1 whileB have pNotNull: "p \ Null" by auto - then obtain addr_p where addr_p_eq: "p = Ref addr_p" by auto - with i1 obtain stack_tl where stack_eq: "stack = (addr p) # stack_tl" - by auto - with i2 have m_addr_p: "p^.m" by auto - have stackDist: "distinct (stack)" using i1 by (rule List_distinct) - from stack_eq stackDist have p_notin_stack_tl: "addr p \ set stack_tl" by simp - let "?poI1\ ?poI2\ ?poI3\ ?poI4\ ?poI5\ ?poI6\ ?poI7" = "?popInv stack_tl" - have "?popInv stack_tl" - proof - - - \ \List property is maintained:\ - from i1 p_notin_stack_tl ifB2 - have poI1: "List (S c l (r(p \ t))) (p^.r) stack_tl" - by(simp add: addr_p_eq stack_eq, simp add: S_def) + assume "(\stack.?Inv stack) \ ?whileB m t p" + then obtain stack where inv: "?Inv stack" and whileB: "?whileB m t p" by blast + let "?I1 \ ?I2 \ ?I3 \ ?I4 \ ?I5 \ ?I6 \ ?I7" = "?Inv stack" + from inv have i1: "?I1" and i2: "?I2" and i3: "?I3" and i4: "?I4" + and i5: "?I5" and i6: "?I6" and i7: "?I7" by simp+ + have stackDist: "distinct (stack)" using i1 by (rule List_distinct) - moreover - \ \Everything on the stack is marked:\ - from i2 have poI2: "\ x \ set stack_tl. m x" by (simp add:stack_eq) - moreover + show "(?ifB1 \ (?ifB2 \ (\stack.?popInv stack)) \ + (\?ifB2 \ (\stack.?swInv stack)) ) \ + (\?ifB1 \ (\stack.?puInv stack))" + proof - + { + assume ifB1: "t = Null \ t^.m" and ifB2: "p^.c" + from ifB1 whileB have pNotNull: "p \ Null" by auto + then obtain addr_p where addr_p_eq: "p = Ref addr_p" by auto + with i1 obtain stack_tl where stack_eq: "stack = (addr p) # stack_tl" + by auto + with i2 have m_addr_p: "p^.m" by auto + have stackDist: "distinct (stack)" using i1 by (rule List_distinct) + from stack_eq stackDist have p_notin_stack_tl: "addr p \ set stack_tl" by simp + let "?poI1\ ?poI2\ ?poI3\ ?poI4\ ?poI5\ ?poI6\ ?poI7" = "?popInv stack_tl" + have "?popInv stack_tl" + proof - - \ \Everything is still reachable:\ - let "(R = reachable ?Ra ?A)" = "?I3" - let "?Rb" = "(relS {l, r(p \ t)})" - let "?B" = "{p, p^.r}" - \ \Our goal is \R = reachable ?Rb ?B\.\ - have "?Ra\<^sup>* `` addrs ?A = ?Rb\<^sup>* `` addrs ?B" (is "?L = ?R") - proof - show "?L \ ?R" - proof (rule still_reachable) - show "addrs ?A \ ?Rb\<^sup>* `` addrs ?B" by(fastforce simp:addrs_def relS_def rel_def addr_p_eq - intro:oneStep_reachable Image_iff[THEN iffD2]) - show "\(x,y) \ ?Ra-?Rb. y \ (?Rb\<^sup>* `` addrs ?B)" by (clarsimp simp:relS_def) - (fastforce simp add:rel_def Image_iff addrs_def dest:rel_upd1) - qed - show "?R \ ?L" - proof (rule still_reachable) - show "addrs ?B \ ?Ra\<^sup>* `` addrs ?A" - by(fastforce simp:addrs_def rel_defs addr_p_eq - intro:oneStep_reachable Image_iff[THEN iffD2]) - next - show "\(x, y)\?Rb-?Ra. y\(?Ra\<^sup>*``addrs ?A)" - by (clarsimp simp:relS_def) - (fastforce simp add:rel_def Image_iff addrs_def dest:rel_upd2) - qed - qed - with i3 have poI3: "R = reachable ?Rb ?B" by (simp add:reachable_def) - moreover + \ \List property is maintained:\ + from i1 p_notin_stack_tl ifB2 + have poI1: "List (S c l (r(p \ t))) (p^.r) stack_tl" + by(simp add: addr_p_eq stack_eq, simp add: S_def) - \ \If it is reachable and not marked, it is still reachable using...\ - let "\x. x \ R \ \ m x \ x \ reachable ?Ra ?A" = ?I4 - let "?Rb" = "relS {l, r(p \ t)} | m" - let "?B" = "{p} \ set (map (r(p \ t)) stack_tl)" - \ \Our goal is \\x. x \ R \ \ m x \ x \ reachable ?Rb ?B\.\ - let ?T = "{t, p^.r}" + moreover + \ \Everything on the stack is marked:\ + from i2 have poI2: "\ x \ set stack_tl. m x" by (simp add:stack_eq) + moreover - have "?Ra\<^sup>* `` addrs ?A \ ?Rb\<^sup>* `` (addrs ?B \ addrs ?T)" + \ \Everything is still reachable:\ + let "(R = reachable ?Ra ?A)" = "?I3" + let "?Rb" = "(relS {l, r(p \ t)})" + let "?B" = "{p, p^.r}" + \ \Our goal is \R = reachable ?Rb ?B\.\ + have "?Ra\<^sup>* `` addrs ?A = ?Rb\<^sup>* `` addrs ?B" (is "?L = ?R") + proof + show "?L \ ?R" proof (rule still_reachable) - have rewrite: "\s\set stack_tl. (r(p \ t)) s = r s" - by (auto simp add:p_notin_stack_tl intro:fun_upd_other) - show "addrs ?A \ ?Rb\<^sup>* `` (addrs ?B \ addrs ?T)" - by (fastforce cong:map_cong simp:stack_eq addrs_def rewrite intro:self_reachable) - show "\(x, y)\?Ra-?Rb. y\(?Rb\<^sup>*``(addrs ?B \ addrs ?T))" - by (clarsimp simp:restr_def relS_def) - (fastforce simp add:rel_def Image_iff addrs_def dest:rel_upd1) - qed - \ \We now bring a term from the right to the left of the subset relation.\ - hence subset: "?Ra\<^sup>* `` addrs ?A - ?Rb\<^sup>* `` addrs ?T \ ?Rb\<^sup>* `` addrs ?B" - by blast - have poI4: "\x. x \ R \ \ m x \ x \ reachable ?Rb ?B" - proof (rule allI, rule impI) - fix x - assume a: "x \ R \ \ m x" - \ \First, a disjunction on \<^term>\p^.r\ used later in the proof\ - have pDisj:"p^.r = Null \ (p^.r \ Null \ p^.r^.m)" using poI1 poI2 - by auto - \ \\<^term>\x\ belongs to the left hand side of @{thm[source] subset}:\ - have incl: "x \ ?Ra\<^sup>*``addrs ?A" using a i4 by (simp only:reachable_def, clarsimp) - have excl: "x \ ?Rb\<^sup>*`` addrs ?T" using pDisj ifB1 a by (auto simp add:addrs_def) - \ \And therefore also belongs to the right hand side of @{thm[source]subset},\ - \ \which corresponds to our goal.\ - from incl excl subset show "x \ reachable ?Rb ?B" by (auto simp add:reachable_def) + show "addrs ?A \ ?Rb\<^sup>* `` addrs ?B" by(fastforce simp:addrs_def relS_def rel_def addr_p_eq + intro:oneStep_reachable Image_iff[THEN iffD2]) + show "\(x,y) \ ?Ra-?Rb. y \ (?Rb\<^sup>* `` addrs ?B)" by (clarsimp simp:relS_def) + (fastforce simp add:rel_def Image_iff addrs_def dest:rel_upd1) qed - moreover - - \ \If it is marked, then it is reachable\ - from i5 have poI5: "\x. m x \ x \ R" . - moreover - - \ \If it is not on the stack, then its \<^term>\l\ and \<^term>\r\ fields are unchanged\ - from i7 i6 ifB2 - have poI6: "\x. x \ set stack_tl \ (r(p \ t)) x = iR x \ l x = iL x" - by(auto simp: addr_p_eq stack_eq fun_upd_apply) - - moreover - - \ \If it is on the stack, then its \<^term>\l\ and \<^term>\r\ fields can be reconstructed\ - from p_notin_stack_tl i7 have poI7: "stkOk c l (r(p \ t)) iL iR p stack_tl" - by (clarsimp simp:stack_eq addr_p_eq) - - ultimately show "?popInv stack_tl" by simp - qed - hence "\stack. ?popInv stack" .. - } - moreover - - \ \Proofs of the Swing and Push arm follow.\ - \ \Since they are in principle simmilar to the Pop arm proof,\ - \ \we show fewer comments and use frequent pattern matching.\ - { - \ \Swing arm\ - assume ifB1: "?ifB1" and nifB2: "\?ifB2" - from ifB1 whileB have pNotNull: "p \ Null" by clarsimp - then obtain addr_p where addr_p_eq: "p = Ref addr_p" by clarsimp - with i1 obtain stack_tl where stack_eq: "stack = (addr p) # stack_tl" by clarsimp - with i2 have m_addr_p: "p^.m" by clarsimp - from stack_eq stackDist have p_notin_stack_tl: "(addr p) \ set stack_tl" - by simp - let "?swI1\?swI2\?swI3\?swI4\?swI5\?swI6\?swI7" = "?swInv stack" - have "?swInv stack" - proof - - - \ \List property is maintained:\ - from i1 p_notin_stack_tl nifB2 - have swI1: "?swI1" - by (simp add:addr_p_eq stack_eq, simp add:S_def) - moreover - - \ \Everything on the stack is marked:\ - from i2 - have swI2: "?swI2" . - moreover - - \ \Everything is still reachable:\ - let "R = reachable ?Ra ?A" = "?I3" - let "R = reachable ?Rb ?B" = "?swI3" - have "?Ra\<^sup>* `` addrs ?A = ?Rb\<^sup>* `` addrs ?B" - proof (rule still_reachable_eq) - show "addrs ?A \ ?Rb\<^sup>* `` addrs ?B" - by(fastforce simp:addrs_def rel_defs addr_p_eq intro:oneStep_reachable Image_iff[THEN iffD2]) - next + show "?R \ ?L" + proof (rule still_reachable) show "addrs ?B \ ?Ra\<^sup>* `` addrs ?A" - by(fastforce simp:addrs_def rel_defs addr_p_eq intro:oneStep_reachable Image_iff[THEN iffD2]) - next - show "\(x, y)\?Ra-?Rb. y\(?Rb\<^sup>*``addrs ?B)" - by (clarsimp simp:relS_def) (fastforce simp add:rel_def Image_iff addrs_def fun_upd_apply dest:rel_upd1) + by(fastforce simp:addrs_def rel_defs addr_p_eq + intro:oneStep_reachable Image_iff[THEN iffD2]) next show "\(x, y)\?Rb-?Ra. y\(?Ra\<^sup>*``addrs ?A)" - by (clarsimp simp:relS_def) (fastforce simp add:rel_def Image_iff addrs_def fun_upd_apply dest:rel_upd2) - qed - with i3 - have swI3: "?swI3" by (simp add:reachable_def) - moreover - - \ \If it is reachable and not marked, it is still reachable using...\ - let "\x. x \ R \ \ m x \ x \ reachable ?Ra ?A" = ?I4 - let "\x. x \ R \ \ m x \ x \ reachable ?Rb ?B" = ?swI4 - let ?T = "{t}" - have "?Ra\<^sup>*``addrs ?A \ ?Rb\<^sup>*``(addrs ?B \ addrs ?T)" - proof (rule still_reachable) - have rewrite: "(\s\set stack_tl. (r(addr p := l(addr p))) s = r s)" - by (auto simp add:p_notin_stack_tl intro:fun_upd_other) - show "addrs ?A \ ?Rb\<^sup>* `` (addrs ?B \ addrs ?T)" - by (fastforce cong:map_cong simp:stack_eq addrs_def rewrite intro:self_reachable) - next - show "\(x, y)\?Ra-?Rb. y\(?Rb\<^sup>*``(addrs ?B \ addrs ?T))" - by (clarsimp simp:relS_def restr_def) (fastforce simp add:rel_def Image_iff addrs_def fun_upd_apply dest:rel_upd1) + by (clarsimp simp:relS_def) + (fastforce simp add:rel_def Image_iff addrs_def dest:rel_upd2) qed - then have subset: "?Ra\<^sup>*``addrs ?A - ?Rb\<^sup>*``addrs ?T \ ?Rb\<^sup>*``addrs ?B" - by blast - have ?swI4 - proof (rule allI, rule impI) - fix x - assume a: "x \ R \\ m x" - with i4 addr_p_eq stack_eq have inc: "x \ ?Ra\<^sup>*``addrs ?A" - by (simp only:reachable_def, clarsimp) - with ifB1 a - have exc: "x \ ?Rb\<^sup>*`` addrs ?T" - by (auto simp add:addrs_def) - from inc exc subset show "x \ reachable ?Rb ?B" - by (auto simp add:reachable_def) - qed - moreover - - \ \If it is marked, then it is reachable\ - from i5 - have "?swI5" . - moreover + qed + with i3 have poI3: "R = reachable ?Rb ?B" by (simp add:reachable_def) + moreover + + \ \If it is reachable and not marked, it is still reachable using...\ + let "\x. x \ R \ \ m x \ x \ reachable ?Ra ?A" = ?I4 + let "?Rb" = "relS {l, r(p \ t)} | m" + let "?B" = "{p} \ set (map (r(p \ t)) stack_tl)" + \ \Our goal is \\x. x \ R \ \ m x \ x \ reachable ?Rb ?B\.\ + let ?T = "{t, p^.r}" + + have "?Ra\<^sup>* `` addrs ?A \ ?Rb\<^sup>* `` (addrs ?B \ addrs ?T)" + proof (rule still_reachable) + have rewrite: "\s\set stack_tl. (r(p \ t)) s = r s" + by (auto simp add:p_notin_stack_tl intro:fun_upd_other) + show "addrs ?A \ ?Rb\<^sup>* `` (addrs ?B \ addrs ?T)" + by (fastforce cong:map_cong simp:stack_eq addrs_def rewrite intro:self_reachable) + show "\(x, y)\?Ra-?Rb. y\(?Rb\<^sup>*``(addrs ?B \ addrs ?T))" + by (clarsimp simp:restr_def relS_def) + (fastforce simp add:rel_def Image_iff addrs_def dest:rel_upd1) + qed + \ \We now bring a term from the right to the left of the subset relation.\ + hence subset: "?Ra\<^sup>* `` addrs ?A - ?Rb\<^sup>* `` addrs ?T \ ?Rb\<^sup>* `` addrs ?B" + by blast + have poI4: "\x. x \ R \ \ m x \ x \ reachable ?Rb ?B" + proof (rule allI, rule impI) + fix x + assume a: "x \ R \ \ m x" + \ \First, a disjunction on \<^term>\p^.r\ used later in the proof\ + have pDisj:"p^.r = Null \ (p^.r \ Null \ p^.r^.m)" using poI1 poI2 + by auto + \ \\<^term>\x\ belongs to the left hand side of @{thm[source] subset}:\ + have incl: "x \ ?Ra\<^sup>*``addrs ?A" using a i4 by (simp only:reachable_def, clarsimp) + have excl: "x \ ?Rb\<^sup>*`` addrs ?T" using pDisj ifB1 a by (auto simp add:addrs_def) + \ \And therefore also belongs to the right hand side of @{thm[source]subset},\ + \ \which corresponds to our goal.\ + from incl excl subset show "x \ reachable ?Rb ?B" by (auto simp add:reachable_def) + qed + moreover + + \ \If it is marked, then it is reachable\ + from i5 have poI5: "\x. m x \ x \ R" . + moreover + + \ \If it is not on the stack, then its \<^term>\l\ and \<^term>\r\ fields are unchanged\ + from i7 i6 ifB2 + have poI6: "\x. x \ set stack_tl \ (r(p \ t)) x = iR x \ l x = iL x" + by(auto simp: addr_p_eq stack_eq fun_upd_apply) + + moreover - \ \If it is not on the stack, then its \<^term>\l\ and \<^term>\r\ fields are unchanged\ - from i6 stack_eq - have "?swI6" - by clarsimp - moreover + \ \If it is on the stack, then its \<^term>\l\ and \<^term>\r\ fields can be reconstructed\ + from p_notin_stack_tl i7 have poI7: "stkOk c l (r(p \ t)) iL iR p stack_tl" + by (clarsimp simp:stack_eq addr_p_eq) + + ultimately show "?popInv stack_tl" by simp + qed + hence "\stack. ?popInv stack" .. + } + moreover + + \ \Proofs of the Swing and Push arm follow.\ + \ \Since they are in principle simmilar to the Pop arm proof,\ + \ \we show fewer comments and use frequent pattern matching.\ + { + \ \Swing arm\ + assume ifB1: "?ifB1" and nifB2: "\?ifB2" + from ifB1 whileB have pNotNull: "p \ Null" by clarsimp + then obtain addr_p where addr_p_eq: "p = Ref addr_p" by clarsimp + with i1 obtain stack_tl where stack_eq: "stack = (addr p) # stack_tl" by clarsimp + with i2 have m_addr_p: "p^.m" by clarsimp + from stack_eq stackDist have p_notin_stack_tl: "(addr p) \ set stack_tl" + by simp + let "?swI1\?swI2\?swI3\?swI4\?swI5\?swI6\?swI7" = "?swInv stack" + have "?swInv stack" + proof - - \ \If it is on the stack, then its \<^term>\l\ and \<^term>\r\ fields can be reconstructed\ - from stackDist i7 nifB2 - have "?swI7" - by (clarsimp simp:addr_p_eq stack_eq) + \ \List property is maintained:\ + from i1 p_notin_stack_tl nifB2 + have swI1: "?swI1" + by (simp add:addr_p_eq stack_eq, simp add:S_def) + moreover + + \ \Everything on the stack is marked:\ + from i2 + have swI2: "?swI2" . + moreover - ultimately show ?thesis by auto + \ \Everything is still reachable:\ + let "R = reachable ?Ra ?A" = "?I3" + let "R = reachable ?Rb ?B" = "?swI3" + have "?Ra\<^sup>* `` addrs ?A = ?Rb\<^sup>* `` addrs ?B" + proof (rule still_reachable_eq) + show "addrs ?A \ ?Rb\<^sup>* `` addrs ?B" + by(fastforce simp:addrs_def rel_defs addr_p_eq intro:oneStep_reachable Image_iff[THEN iffD2]) + next + show "addrs ?B \ ?Ra\<^sup>* `` addrs ?A" + by(fastforce simp:addrs_def rel_defs addr_p_eq intro:oneStep_reachable Image_iff[THEN iffD2]) + next + show "\(x, y)\?Ra-?Rb. y\(?Rb\<^sup>*``addrs ?B)" + by (clarsimp simp:relS_def) (fastforce simp add:rel_def Image_iff addrs_def fun_upd_apply dest:rel_upd1) + next + show "\(x, y)\?Rb-?Ra. y\(?Ra\<^sup>*``addrs ?A)" + by (clarsimp simp:relS_def) (fastforce simp add:rel_def Image_iff addrs_def fun_upd_apply dest:rel_upd2) qed - then have "\stack. ?swInv stack" by blast - } - moreover + with i3 + have swI3: "?swI3" by (simp add:reachable_def) + moreover - { - \ \Push arm\ - assume nifB1: "\?ifB1" - from nifB1 whileB have tNotNull: "t \ Null" by clarsimp - then obtain addr_t where addr_t_eq: "t = Ref addr_t" by clarsimp - with i1 obtain new_stack where new_stack_eq: "new_stack = (addr t) # stack" by clarsimp - from tNotNull nifB1 have n_m_addr_t: "\ (t^.m)" by clarsimp - with i2 have t_notin_stack: "(addr t) \ set stack" by blast - let "?puI1\?puI2\?puI3\?puI4\?puI5\?puI6\?puI7" = "?puInv new_stack" - have "?puInv new_stack" - proof - - - \ \List property is maintained:\ - from i1 t_notin_stack - have puI1: "?puI1" - by (simp add:addr_t_eq new_stack_eq, simp add:S_def) - moreover - - \ \Everything on the stack is marked:\ - from i2 - have puI2: "?puI2" - by (simp add:new_stack_eq fun_upd_apply) - moreover - - \ \Everything is still reachable:\ - let "R = reachable ?Ra ?A" = "?I3" - let "R = reachable ?Rb ?B" = "?puI3" - have "?Ra\<^sup>* `` addrs ?A = ?Rb\<^sup>* `` addrs ?B" - proof (rule still_reachable_eq) - show "addrs ?A \ ?Rb\<^sup>* `` addrs ?B" - by(fastforce simp:addrs_def rel_defs addr_t_eq intro:oneStep_reachable Image_iff[THEN iffD2]) - next - show "addrs ?B \ ?Ra\<^sup>* `` addrs ?A" - by(fastforce simp:addrs_def rel_defs addr_t_eq intro:oneStep_reachable Image_iff[THEN iffD2]) - next - show "\(x, y)\?Ra-?Rb. y\(?Rb\<^sup>*``addrs ?B)" - by (clarsimp simp:relS_def) (fastforce simp add:rel_def Image_iff addrs_def dest:rel_upd1) - next - show "\(x, y)\?Rb-?Ra. y\(?Ra\<^sup>*``addrs ?A)" - by (clarsimp simp:relS_def) (fastforce simp add:rel_def Image_iff addrs_def fun_upd_apply dest:rel_upd2) - qed - with i3 - have puI3: "?puI3" by (simp add:reachable_def) - moreover - - \ \If it is reachable and not marked, it is still reachable using...\ - let "\x. x \ R \ \ m x \ x \ reachable ?Ra ?A" = ?I4 - let "\x. x \ R \ \ ?new_m x \ x \ reachable ?Rb ?B" = ?puI4 - let ?T = "{t}" - have "?Ra\<^sup>*``addrs ?A \ ?Rb\<^sup>*``(addrs ?B \ addrs ?T)" - proof (rule still_reachable) - show "addrs ?A \ ?Rb\<^sup>* `` (addrs ?B \ addrs ?T)" - by (fastforce simp:new_stack_eq addrs_def intro:self_reachable) - next - show "\(x, y)\?Ra-?Rb. y\(?Rb\<^sup>*``(addrs ?B \ addrs ?T))" - by (clarsimp simp:relS_def new_stack_eq restr_un restr_upd) - (fastforce simp add:rel_def Image_iff restr_def addrs_def fun_upd_apply addr_t_eq dest:rel_upd3) - qed - then have subset: "?Ra\<^sup>*``addrs ?A - ?Rb\<^sup>*``addrs ?T \ ?Rb\<^sup>*``addrs ?B" - by blast - have ?puI4 - proof (rule allI, rule impI) - fix x - assume a: "x \ R \ \ ?new_m x" - have xDisj: "x=(addr t) \ x\(addr t)" by simp - with i4 a have inc: "x \ ?Ra\<^sup>*``addrs ?A" - by (fastforce simp:addr_t_eq addrs_def reachable_def intro:self_reachable) - have exc: "x \ ?Rb\<^sup>*`` addrs ?T" - using xDisj a n_m_addr_t - by (clarsimp simp add:addrs_def addr_t_eq) - from inc exc subset show "x \ reachable ?Rb ?B" - by (auto simp add:reachable_def) - qed - moreover - - \ \If it is marked, then it is reachable\ - from i5 - have "?puI5" - by (auto simp:addrs_def i3 reachable_def addr_t_eq fun_upd_apply intro:self_reachable) - moreover - - \ \If it is not on the stack, then its \<^term>\l\ and \<^term>\r\ fields are unchanged\ - from i6 - have "?puI6" - by (simp add:new_stack_eq) - moreover + \ \If it is reachable and not marked, it is still reachable using...\ + let "\x. x \ R \ \ m x \ x \ reachable ?Ra ?A" = ?I4 + let "\x. x \ R \ \ m x \ x \ reachable ?Rb ?B" = ?swI4 + let ?T = "{t}" + have "?Ra\<^sup>*``addrs ?A \ ?Rb\<^sup>*``(addrs ?B \ addrs ?T)" + proof (rule still_reachable) + have rewrite: "(\s\set stack_tl. (r(addr p := l(addr p))) s = r s)" + by (auto simp add:p_notin_stack_tl intro:fun_upd_other) + show "addrs ?A \ ?Rb\<^sup>* `` (addrs ?B \ addrs ?T)" + by (fastforce cong:map_cong simp:stack_eq addrs_def rewrite intro:self_reachable) + next + show "\(x, y)\?Ra-?Rb. y\(?Rb\<^sup>*``(addrs ?B \ addrs ?T))" + by (clarsimp simp:relS_def restr_def) (fastforce simp add:rel_def Image_iff addrs_def fun_upd_apply dest:rel_upd1) + qed + then have subset: "?Ra\<^sup>*``addrs ?A - ?Rb\<^sup>*``addrs ?T \ ?Rb\<^sup>*``addrs ?B" + by blast + have ?swI4 + proof (rule allI, rule impI) + fix x + assume a: "x \ R \\ m x" + with i4 addr_p_eq stack_eq have inc: "x \ ?Ra\<^sup>*``addrs ?A" + by (simp only:reachable_def, clarsimp) + with ifB1 a + have exc: "x \ ?Rb\<^sup>*`` addrs ?T" + by (auto simp add:addrs_def) + from inc exc subset show "x \ reachable ?Rb ?B" + by (auto simp add:reachable_def) + qed + moreover + + \ \If it is marked, then it is reachable\ + from i5 + have "?swI5" . + moreover + + \ \If it is not on the stack, then its \<^term>\l\ and \<^term>\r\ fields are unchanged\ + from i6 stack_eq + have "?swI6" + by clarsimp + moreover + + \ \If it is on the stack, then its \<^term>\l\ and \<^term>\r\ fields can be reconstructed\ + from stackDist i7 nifB2 + have "?swI7" + by (clarsimp simp:addr_p_eq stack_eq) + + ultimately show ?thesis by auto + qed + then have "\stack. ?swInv stack" by blast + } + moreover + + { + \ \Push arm\ + assume nifB1: "\?ifB1" + from nifB1 whileB have tNotNull: "t \ Null" by clarsimp + then obtain addr_t where addr_t_eq: "t = Ref addr_t" by clarsimp + with i1 obtain new_stack where new_stack_eq: "new_stack = (addr t) # stack" by clarsimp + from tNotNull nifB1 have n_m_addr_t: "\ (t^.m)" by clarsimp + with i2 have t_notin_stack: "(addr t) \ set stack" by blast + let "?puI1\?puI2\?puI3\?puI4\?puI5\?puI6\?puI7" = "?puInv new_stack" + have "?puInv new_stack" + proof - + + \ \List property is maintained:\ + from i1 t_notin_stack + have puI1: "?puI1" + by (simp add:addr_t_eq new_stack_eq, simp add:S_def) + moreover + + \ \Everything on the stack is marked:\ + from i2 + have puI2: "?puI2" + by (simp add:new_stack_eq fun_upd_apply) + moreover - \ \If it is on the stack, then its \<^term>\l\ and \<^term>\r\ fields can be reconstructed\ - from stackDist i6 t_notin_stack i7 - have "?puI7" by (clarsimp simp:addr_t_eq new_stack_eq) + \ \Everything is still reachable:\ + let "R = reachable ?Ra ?A" = "?I3" + let "R = reachable ?Rb ?B" = "?puI3" + have "?Ra\<^sup>* `` addrs ?A = ?Rb\<^sup>* `` addrs ?B" + proof (rule still_reachable_eq) + show "addrs ?A \ ?Rb\<^sup>* `` addrs ?B" + by(fastforce simp:addrs_def rel_defs addr_t_eq intro:oneStep_reachable Image_iff[THEN iffD2]) + next + show "addrs ?B \ ?Ra\<^sup>* `` addrs ?A" + by(fastforce simp:addrs_def rel_defs addr_t_eq intro:oneStep_reachable Image_iff[THEN iffD2]) + next + show "\(x, y)\?Ra-?Rb. y\(?Rb\<^sup>*``addrs ?B)" + by (clarsimp simp:relS_def) (fastforce simp add:rel_def Image_iff addrs_def dest:rel_upd1) + next + show "\(x, y)\?Rb-?Ra. y\(?Ra\<^sup>*``addrs ?A)" + by (clarsimp simp:relS_def) (fastforce simp add:rel_def Image_iff addrs_def fun_upd_apply dest:rel_upd2) + qed + with i3 + have puI3: "?puI3" by (simp add:reachable_def) + moreover - ultimately show ?thesis by auto + \ \If it is reachable and not marked, it is still reachable using...\ + let "\x. x \ R \ \ m x \ x \ reachable ?Ra ?A" = ?I4 + let "\x. x \ R \ \ ?new_m x \ x \ reachable ?Rb ?B" = ?puI4 + let ?T = "{t}" + have "?Ra\<^sup>*``addrs ?A \ ?Rb\<^sup>*``(addrs ?B \ addrs ?T)" + proof (rule still_reachable) + show "addrs ?A \ ?Rb\<^sup>* `` (addrs ?B \ addrs ?T)" + by (fastforce simp:new_stack_eq addrs_def intro:self_reachable) + next + show "\(x, y)\?Ra-?Rb. y\(?Rb\<^sup>*``(addrs ?B \ addrs ?T))" + by (clarsimp simp:relS_def new_stack_eq restr_un restr_upd) + (fastforce simp add:rel_def Image_iff restr_def addrs_def fun_upd_apply addr_t_eq dest:rel_upd3) qed - then have "\stack. ?puInv stack" by blast + then have subset: "?Ra\<^sup>*``addrs ?A - ?Rb\<^sup>*``addrs ?T \ ?Rb\<^sup>*``addrs ?B" + by blast + have ?puI4 + proof (rule allI, rule impI) + fix x + assume a: "x \ R \ \ ?new_m x" + have xDisj: "x=(addr t) \ x\(addr t)" by simp + with i4 a have inc: "x \ ?Ra\<^sup>*``addrs ?A" + by (fastforce simp:addr_t_eq addrs_def reachable_def intro:self_reachable) + have exc: "x \ ?Rb\<^sup>*`` addrs ?T" + using xDisj a n_m_addr_t + by (clarsimp simp add:addrs_def addr_t_eq) + from inc exc subset show "x \ reachable ?Rb ?B" + by (auto simp add:reachable_def) + qed + moreover - } - ultimately show ?thesis by blast - qed - } - qed + \ \If it is marked, then it is reachable\ + from i5 + have "?puI5" + by (auto simp:addrs_def i3 reachable_def addr_t_eq fun_upd_apply intro:self_reachable) + moreover + + \ \If it is not on the stack, then its \<^term>\l\ and \<^term>\r\ fields are unchanged\ + from i6 + have "?puI6" + by (simp add:new_stack_eq) + moreover + + \ \If it is on the stack, then its \<^term>\l\ and \<^term>\r\ fields can be reconstructed\ + from stackDist i6 t_notin_stack i7 + have "?puI7" by (clarsimp simp:addr_t_eq new_stack_eq) + + ultimately show ?thesis by auto + qed + then have "\stack. ?puInv stack" by blast + + } + ultimately show ?thesis by blast + qed + } +qed end