# HG changeset patch # User nipkow # Date 1634065063 -7200 # Node ID 403ce50e6a2a31175ae8e21f6b02478e71983c28 # Parent 40f03761f77fe265bd8c898022c73ec3dd9b9cb9 separated commands from annotations to be able to abstract about the latter only diff -r 40f03761f77f -r 403ce50e6a2a src/HOL/Hoare/ExamplesTC.thy --- a/src/HOL/Hoare/ExamplesTC.thy Mon Oct 11 21:55:21 2021 +0200 +++ b/src/HOL/Hoare/ExamplesTC.thy Tue Oct 12 20:57:43 2021 +0200 @@ -27,7 +27,7 @@ Here is the total-correctness proof for the same program. It needs the additional invariant \m \ a\. \ - +ML \\<^const_syntax>\HOL.eq\\ lemma multiply_by_add_tc: "VARS m s a b [a=A \ b=B] m := 0; s := 0; @@ -84,7 +84,7 @@ r := 0; WHILE (r+1)*(r+1) <= x INV {r*r \ x} - VAR {nat (x-r)} + VAR { nat (x-r)} DO r := r+1 OD [r*r \ x \ x < (r+1)*(r+1)]" apply vcg_tc_simp @@ -113,4 +113,21 @@ using assms(2) sqrt_def by auto qed +text \Nested loops!\ + +lemma "VARS (i::nat) j + [ True ] + WHILE 0 < i + INV { True } + VAR { z = i } + DO i := i - 1; j := i; + WHILE 0 < j + INV { z = i+1 } + VAR { j } + DO j := j - 1 OD + OD + [ i \ 0 ]" + apply vcg_tc + by auto + end diff -r 40f03761f77f -r 403ce50e6a2a src/HOL/Hoare/Hoare_Logic.thy --- a/src/HOL/Hoare/Hoare_Logic.thy Mon Oct 11 21:55:21 2021 +0200 +++ b/src/HOL/Hoare/Hoare_Logic.thy Tue Oct 12 20:57:43 2021 +0200 @@ -20,13 +20,12 @@ type_synonym 'a bexp = "'a set" type_synonym 'a assn = "'a set" -type_synonym 'a var = "'a \ nat" datatype 'a com = Basic "'a \ 'a" | Seq "'a com" "'a com" | Cond "'a bexp" "'a com" "'a com" -| While "'a bexp" "'a assn" "'a var" "'a com" +| While "'a bexp" "'a com" abbreviation annskip ("SKIP") where "SKIP == Basic id" @@ -38,15 +37,15 @@ | "Sem c1 s s'' \ Sem c2 s'' s' \ Sem (Seq c1 c2) s s'" | "s \ b \ Sem c1 s s' \ Sem (Cond b c1 c2) s s'" | "s \ b \ Sem c2 s s' \ Sem (Cond b c1 c2) s s'" -| "s \ b \ Sem (While b x y c) s s" -| "s \ b \ Sem c s s'' \ Sem (While b x y c) s'' s' \ - Sem (While b x y c) s s'" +| "s \ b \ Sem (While b c) s s" +| "s \ b \ Sem c s s'' \ Sem (While b c) s'' s' \ + Sem (While b c) s s'" -definition Valid :: "'a bexp \ 'a com \ 'a bexp \ bool" - where "Valid p c q \ \s s'. Sem c s s' \ s \ p \ s' \ q" +definition Valid :: "'a bexp \ 'a com \ 'a anno \ 'a bexp \ bool" + where "Valid p c a q \ \s s'. Sem c s s' \ s \ p \ s' \ q" -definition ValidTC :: "'a bexp \ 'a com \ 'a bexp \ bool" - where "ValidTC p c q \ \s. s \ p \ (\t. Sem c s t \ t \ q)" +definition ValidTC :: "'a bexp \ 'a com \ 'a anno \ 'a bexp \ bool" + where "ValidTC p c a q \ \s. s \ p \ (\t. Sem c s t \ t \ q)" inductive_cases [elim!]: "Sem (Basic f) s s'" "Sem (Seq c1 c2) s s'" @@ -64,37 +63,37 @@ qed lemma tc_implies_pc: - "ValidTC p c q \ Valid p c q" + "ValidTC p c a q \ Valid p c a q" by (metis Sem_deterministic Valid_def ValidTC_def) lemma tc_extract_function: - "ValidTC p c q \ \f . \s . s \ p \ f s \ q" + "ValidTC p c a q \ \f . \s . s \ p \ f s \ q" by (metis ValidTC_def) -lemma SkipRule: "p \ q \ Valid p (Basic id) q" +lemma SkipRule: "p \ q \ Valid p (Basic id) a q" by (auto simp:Valid_def) -lemma BasicRule: "p \ {s. f s \ q} \ Valid p (Basic f) q" +lemma BasicRule: "p \ {s. f s \ q} \ Valid p (Basic f) a q" by (auto simp:Valid_def) -lemma SeqRule: "Valid P c1 Q \ Valid Q c2 R \ Valid P (Seq c1 c2) R" +lemma SeqRule: "Valid P c1 a1 Q \ Valid Q c2 a2 R \ Valid P (Seq c1 c2) (Aseq a1 a2) R" by (auto simp:Valid_def) lemma CondRule: "p \ {s. (s \ b \ s \ w) \ (s \ b \ s \ w')} - \ Valid w c1 q \ Valid w' c2 q \ Valid p (Cond b c1 c2) q" + \ Valid w c1 a1 q \ Valid w' c2 a2 q \ Valid p (Cond b c1 c2) (Acond a1 a2) q" by (auto simp:Valid_def) lemma While_aux: - assumes "Sem (While b i v c) s s'" + assumes "Sem (While b c) s s'" shows "\s s'. Sem c s s' \ s \ I \ s \ b \ s' \ I \ s \ I \ s' \ I \ s' \ b" using assms - by (induct "While b i v c" s s') auto + by (induct "While b c" s s') auto lemma WhileRule: - "p \ i \ Valid (i \ b) c i \ i \ (-b) \ q \ Valid p (While b i v c) q" + "p \ i \ Valid (i \ b) c (A 0) i \ i \ (-b) \ q \ Valid p (While b c) (Awhile i v A) q" apply (clarsimp simp:Valid_def) apply(drule While_aux) apply assumption @@ -104,25 +103,25 @@ lemma SkipRuleTC: assumes "p \ q" - shows "ValidTC p (Basic id) q" + shows "ValidTC p (Basic id) a q" by (metis assms Sem.intros(1) ValidTC_def id_apply subsetD) lemma BasicRuleTC: assumes "p \ {s. f s \ q}" - shows "ValidTC p (Basic f) q" + shows "ValidTC p (Basic f) a q" by (metis assms Ball_Collect Sem.intros(1) ValidTC_def) lemma SeqRuleTC: - assumes "ValidTC p c1 q" - and "ValidTC q c2 r" - shows "ValidTC p (Seq c1 c2) r" + assumes "ValidTC p c1 a1 q" + and "ValidTC q c2 a2 r" + shows "ValidTC p (Seq c1 c2) (Aseq a1 a2) r" by (meson assms Sem.intros(2) ValidTC_def) lemma CondRuleTC: assumes "p \ {s. (s \ b \ s \ w) \ (s \ b \ s \ w')}" - and "ValidTC w c1 q" - and "ValidTC w' c2 q" - shows "ValidTC p (Cond b c1 c2) q" + and "ValidTC w c1 a1 q" + and "ValidTC w' c2 a2 q" + shows "ValidTC p (Cond b c1 c2) (Acond a1 a2) q" proof (unfold ValidTC_def, rule allI) fix s show "s \ p \ (\t . Sem (Cond b c1 c2) s t \ t \ q)" @@ -133,18 +132,18 @@ lemma WhileRuleTC: assumes "p \ i" - and "\n::nat . ValidTC (i \ b \ {s . v s = n}) c (i \ {s . v s < n})" + and "\n::nat . ValidTC (i \ b \ {s . v s = n}) c (A n) (i \ {s . v s < n})" and "i \ uminus b \ q" - shows "ValidTC p (While b i v c) q" + shows "ValidTC p (While b c) (Awhile i v A) q" proof - { fix s n - have "s \ i \ v s = n \ (\t . Sem (While b i v c) s t \ t \ q)" + have "s \ i \ v s = n \ (\t . Sem (While b c) s t \ t \ q)" proof (induction "n" arbitrary: s rule: less_induct) fix n :: nat fix s :: 'a - assume 1: "\(m::nat) s::'a . m < n \ s \ i \ v s = m \ (\t . Sem (While b i v c) s t \ t \ q)" - show "s \ i \ v s = n \ (\t . Sem (While b i v c) s t \ t \ q)" + assume 1: "\(m::nat) s::'a . m < n \ s \ i \ v s = m \ (\t . Sem (While b c) s t \ t \ q)" + show "s \ i \ v s = n \ (\t . Sem (While b c) s t \ t \ q)" proof (rule impI, cases "s \ b") assume 2: "s \ b" and "s \ i \ v s = n" hence "s \ i \ b \ {s . v s = n}" @@ -153,13 +152,13 @@ by (metis assms(2) ValidTC_def) from this obtain t where 3: "Sem c s t \ t \ i \ {s . v s < n}" by auto - hence "\u . Sem (While b i v c) t u \ u \ q" + hence "\u . Sem (While b c) t u \ u \ q" using 1 by auto - thus "\t . Sem (While b i v c) s t \ t \ q" + thus "\t . Sem (While b c) s t \ t \ q" using 2 3 Sem.intros(6) by force next assume "s \ b" and "s \ i \ v s = n" - thus "\t . Sem (While b i v c) s t \ t \ q" + thus "\t . Sem (While b c) s t \ t \ q" using Sem.intros(5) assms(3) by fastforce qed qed diff -r 40f03761f77f -r 403ce50e6a2a src/HOL/Hoare/Hoare_Logic_Abort.thy --- a/src/HOL/Hoare/Hoare_Logic_Abort.thy Mon Oct 11 21:55:21 2021 +0200 +++ b/src/HOL/Hoare/Hoare_Logic_Abort.thy Tue Oct 12 20:57:43 2021 +0200 @@ -19,7 +19,7 @@ | Abort | Seq "'a com" "'a com" | Cond "'a bexp" "'a com" "'a com" -| While "'a bexp" "'a assn" "'a var" "'a com" +| While "'a bexp" "'a com" abbreviation annskip ("SKIP") where "SKIP == Basic id" @@ -34,10 +34,10 @@ | "Sem (Cond b c1 c2) None None" | "s \ b \ Sem c1 (Some s) s' \ Sem (Cond b c1 c2) (Some s) s'" | "s \ b \ Sem c2 (Some s) s' \ Sem (Cond b c1 c2) (Some s) s'" -| "Sem (While b x y c) None None" -| "s \ b \ Sem (While b x y c) (Some s) (Some s)" -| "s \ b \ Sem c (Some s) s'' \ Sem (While b x y c) s'' s' \ - Sem (While b x y c) (Some s) s'" +| "Sem (While b c) None None" +| "s \ b \ Sem (While b c) (Some s) (Some s)" +| "s \ b \ Sem c (Some s) s'' \ Sem (While b c) s'' s' \ + Sem (While b c) (Some s) s'" inductive_cases [elim!]: "Sem (Basic f) s s'" "Sem (Seq c1 c2) s s'" @@ -54,45 +54,45 @@ using assms by simp qed -definition Valid :: "'a bexp \ 'a com \ 'a bexp \ bool" - where "Valid p c q \ \s s'. Sem c s s' \ s \ Some ` p \ s' \ Some ` q" +definition Valid :: "'a bexp \ 'a com \ 'a anno \ 'a bexp \ bool" + where "Valid p c a q \ \s s'. Sem c s s' \ s \ Some ` p \ s' \ Some ` q" -definition ValidTC :: "'a bexp \ 'a com \ 'a bexp \ bool" - where "ValidTC p c q \ \s . s \ p \ (\t . Sem c (Some s) (Some t) \ t \ q)" +definition ValidTC :: "'a bexp \ 'a com \ 'a anno \ 'a bexp \ bool" + where "ValidTC p c a q \ \s . s \ p \ (\t . Sem c (Some s) (Some t) \ t \ q)" lemma tc_implies_pc: - "ValidTC p c q \ Valid p c q" + "ValidTC p c a q \ Valid p c a q" by (smt (verit) Sem_deterministic ValidTC_def Valid_def image_iff) lemma tc_extract_function: - "ValidTC p c q \ \f . \s . s \ p \ f s \ q" + "ValidTC p c a q \ \f . \s . s \ p \ f s \ q" by (meson ValidTC_def) text \The proof rules for partial correctness\ -lemma SkipRule: "p \ q \ Valid p (Basic id) q" +lemma SkipRule: "p \ q \ Valid p (Basic id) a q" by (auto simp:Valid_def) -lemma BasicRule: "p \ {s. f s \ q} \ Valid p (Basic f) q" +lemma BasicRule: "p \ {s. f s \ q} \ Valid p (Basic f) a q" by (auto simp:Valid_def) -lemma SeqRule: "Valid P c1 Q \ Valid Q c2 R \ Valid P (Seq c1 c2) R" +lemma SeqRule: "Valid P c1 a1 Q \ Valid Q c2 a2 R \ Valid P (Seq c1 c2) (Aseq a1 a2) R" by (auto simp:Valid_def) lemma CondRule: "p \ {s. (s \ b \ s \ w) \ (s \ b \ s \ w')} - \ Valid w c1 q \ Valid w' c2 q \ Valid p (Cond b c1 c2) q" + \ Valid w c1 a1 q \ Valid w' c2 a2 q \ Valid p (Cond b c1 c2) (Acond a1 a2) q" by (fastforce simp:Valid_def image_def) lemma While_aux: - assumes "Sem (While b i v c) s s'" + assumes "Sem (While b c) s s'" shows "\s s'. Sem c s s' \ s \ Some ` (I \ b) \ s' \ Some ` I \ s \ Some ` I \ s' \ Some ` (I \ -b)" using assms - by (induct "While b i v c" s s') auto + by (induct "While b c" s s') auto lemma WhileRule: - "p \ i \ Valid (i \ b) c i \ i \ (-b) \ q \ Valid p (While b i v c) q" + "p \ i \ Valid (i \ b) c (A 0) i \ i \ (-b) \ q \ Valid p (While b c) (Awhile i v A) q" apply (clarsimp simp:Valid_def) apply(drule While_aux) apply assumption @@ -100,32 +100,32 @@ apply blast done -lemma AbortRule: "p \ {s. False} \ Valid p Abort q" +lemma AbortRule: "p \ {s. False} \ Valid p Abort a q" by(auto simp:Valid_def) text \The proof rules for total correctness\ lemma SkipRuleTC: assumes "p \ q" - shows "ValidTC p (Basic id) q" + shows "ValidTC p (Basic id) a q" by (metis Sem.intros(2) ValidTC_def assms id_def subsetD) lemma BasicRuleTC: assumes "p \ {s. f s \ q}" - shows "ValidTC p (Basic f) q" + shows "ValidTC p (Basic f) a q" by (metis Ball_Collect Sem.intros(2) ValidTC_def assms) lemma SeqRuleTC: - assumes "ValidTC p c1 q" - and "ValidTC q c2 r" - shows "ValidTC p (Seq c1 c2) r" + assumes "ValidTC p c1 a1 q" + and "ValidTC q c2 a2 r" + shows "ValidTC p (Seq c1 c2) (Aseq a1 a2) r" by (meson assms Sem.intros(4) ValidTC_def) lemma CondRuleTC: assumes "p \ {s. (s \ b \ s \ w) \ (s \ b \ s \ w')}" - and "ValidTC w c1 q" - and "ValidTC w' c2 q" - shows "ValidTC p (Cond b c1 c2) q" + and "ValidTC w c1 a1 q" + and "ValidTC w' c2 a2 q" + shows "ValidTC p (Cond b c1 c2) (Acons a1 a2) q" proof (unfold ValidTC_def, rule allI) fix s show "s \ p \ (\t . Sem (Cond b c1 c2) (Some s) (Some t) \ t \ q)" @@ -136,18 +136,18 @@ lemma WhileRuleTC: assumes "p \ i" - and "\n::nat . ValidTC (i \ b \ {s . v s = n}) c (i \ {s . v s < n})" + and "\n::nat . ValidTC (i \ b \ {s . v s = n}) c (A n) (i \ {s . v s < n})" and "i \ uminus b \ q" - shows "ValidTC p (While b i v c) q" + shows "ValidTC p (While b c) (Awhile i v A) q" proof - { fix s n - have "s \ i \ v s = n \ (\t . Sem (While b i v c) (Some s) (Some t) \ t \ q)" + have "s \ i \ v s = n \ (\t . Sem (While b c) (Some s) (Some t) \ t \ q)" proof (induction "n" arbitrary: s rule: less_induct) fix n :: nat fix s :: 'a - assume 1: "\(m::nat) s::'a . m < n \ s \ i \ v s = m \ (\t . Sem (While b i v c) (Some s) (Some t) \ t \ q)" - show "s \ i \ v s = n \ (\t . Sem (While b i v c) (Some s) (Some t) \ t \ q)" + assume 1: "\(m::nat) s::'a . m < n \ s \ i \ v s = m \ (\t . Sem (While b c) (Some s) (Some t) \ t \ q)" + show "s \ i \ v s = n \ (\t . Sem (While b c) (Some s) (Some t) \ t \ q)" proof (rule impI, cases "s \ b") assume 2: "s \ b" and "s \ i \ v s = n" hence "s \ i \ b \ {s . v s = n}" @@ -156,13 +156,13 @@ by (metis assms(2) ValidTC_def) from this obtain t where 3: "Sem c (Some s) (Some t) \ t \ i \ {s . v s < n}" by auto - hence "\u . Sem (While b i v c) (Some t) (Some u) \ u \ q" + hence "\u . Sem (While b c) (Some t) (Some u) \ u \ q" using 1 by auto - thus "\t . Sem (While b i v c) (Some s) (Some t) \ t \ q" + thus "\t . Sem (While b c) (Some s) (Some t) \ t \ q" using 2 3 Sem.intros(10) by force next assume "s \ b" and "s \ i \ v s = n" - thus "\t . Sem (While b i v c) (Some s) (Some t) \ t \ q" + thus "\t . Sem (While b c) (Some s) (Some t) \ t \ q" using Sem.intros(9) assms(3) by fastforce qed qed diff -r 40f03761f77f -r 403ce50e6a2a src/HOL/Hoare/Hoare_Syntax.thy --- a/src/HOL/Hoare/Hoare_Syntax.thy Mon Oct 11 21:55:21 2021 +0200 +++ b/src/HOL/Hoare/Hoare_Syntax.thy Tue Oct 12 20:57:43 2021 +0200 @@ -15,10 +15,18 @@ "_Cond" :: "'bexp \ 'com \ 'com \ 'com" ("(1IF _/ THEN _ / ELSE _/ FI)" [0,0,0] 61) "_While" :: "'bexp \ 'assn \ 'var \ 'com \ 'com" ("(1WHILE _/ INV {_} / VAR {_} //DO _ /OD)" [0,0,0,0] 61) +text \The \VAR {_}\ syntax supports two variants: +\<^item> \VAR {x = t}\ where \t::nat\ is the decreasing expression, + the variant, and \x\ a variable that can be referred to from inner annotations. + The \x\ can be necessary for nested loops, e.g. to prove that the inner loops do not mess with \t\. +\<^item> \VAR {t}\ where the variable is omitted because it is not needed. +\ + syntax "_While0" :: "'bexp \ 'assn \ 'com \ 'com" ("(1WHILE _/ INV {_} //DO _ /OD)" [0,0,0] 61) -translations - "WHILE b INV {x} DO c OD" \ "WHILE b INV {x} VAR {0} DO c OD" + +text \The \_While0\ syntax is translated into the \_While\ syntax with the trivial variant 0. +This is ok because partial correctness proofs do not make use of the variant.\ syntax "_hoare_vars" :: "[idts, 'assn,'com, 'assn] \ bool" ("VARS _// {_} // _ // {_}" [0,0,55,0] 50) @@ -27,6 +35,18 @@ "_hoare" :: "['assn, 'com, 'assn] \ bool" ("{_} // _ // {_}" [0,55,0] 50) "_hoare_tc" :: "['assn, 'com, 'assn] \ bool" ("[_] // _ // [_]" [0,55,0] 50) +text \Completeness requires(?) the ability to refer to an outer variant in an inner invariant. +Thus we need to abstract over a variable equated with the variant, the \x\ in \VAR {x = t}\. +But the \x\ should only occur in invariants. To enforce this, syntax translations in \hoare_syntax.ML\ +separate the program from its annotations and only the latter are abstracted over over \x\. +(Thus \x\ can also occur in inner variants, but that neither helps nor hurts.)\ + +datatype 'a anno = + Abasic | + Aseq "'a anno" "'a anno" | + Acond "'a anno" "'a anno" | + Awhile "'a set" "'a \ nat" "nat \ 'a anno" + ML_file \hoare_syntax.ML\ end diff -r 40f03761f77f -r 403ce50e6a2a src/HOL/Hoare/SchorrWaite.thy --- a/src/HOL/Hoare/SchorrWaite.thy Mon Oct 11 21:55:21 2021 +0200 +++ b/src/HOL/Hoare/SchorrWaite.thy Tue Oct 12 20:57:43 2021 +0200 @@ -219,10 +219,11 @@ 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) }" - (is "VARS c m l r t p q root {?Pre c m l r root} (?c1; ?c2; ?c3) {?Post c m l r}") + (is "Valid + {(c, m, l, r, t, p, q, root). ?Pre c m l r root} + (Seq _ (Seq _ (While {(c, m, l, r, t, p, q, root). ?whileB m t p} _))) + (Aseq _ (Aseq _ (Awhile {(c, m, l, r, t, p, q, root). ?inv c m l r t p} _ _))) _") proof (vcg) - let "While {(c, m, l, r, t, p, q, root). ?whileB m t p} - {(c, m, l, r, t, p, q, root). ?inv c m l r t p} _ ?body" = ?c3 { fix c m l r t p q root @@ -252,8 +253,8 @@ let "?ifB1" = "(t = Null \ t^.m)" let "?ifB2" = "p^.c" - assume "(\stack.?Inv stack) \ (p \ Null \ t \ Null \ \ t^.m)" (is "_ \ ?whileB") - then obtain stack where inv: "?Inv stack" and whileB: "?whileB" by blast + 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+ diff -r 40f03761f77f -r 403ce50e6a2a src/HOL/Hoare/hoare_syntax.ML --- a/src/HOL/Hoare/hoare_syntax.ML Mon Oct 11 21:55:21 2021 +0200 +++ b/src/HOL/Hoare/hoare_syntax.ML Tue Oct 12 20:57:43 2021 +0200 @@ -1,6 +1,7 @@ (* Title: HOL/Hoare/hoare_syntax.ML Author: Leonor Prensa Nieto & Tobias Nipkow - Author: Walter Guttmann (extension to total-correctness proofs) + Author: Walter Guttmann (initial extension to total-correctness proofs) + Author: Tobias Nipkow (complete version of total correctness with separate anno type) Syntax translations for Hoare logic. *) @@ -84,14 +85,34 @@ fun com_tr ctxt = let fun tr (Const (\<^syntax_const>\_assign\, _) $ x $ e) xs = - syntax_const ctxt #Basic $ mk_fexp x e xs + (syntax_const ctxt #Basic $ mk_fexp x e xs, Syntax.const \<^const_syntax>\Abasic\) | tr (Const (\<^syntax_const>\_Seq\,_) $ c1 $ c2) xs = - syntax_const ctxt #Seq $ tr c1 xs $ tr c2 xs + let val (c1',a1) = tr c1 xs; + val (c2',a2) = tr c2 xs + in (syntax_const ctxt #Seq $ c1' $ c2', Syntax.const \<^const_syntax>\Aseq\ $ a1 $ a2) end | tr (Const (\<^syntax_const>\_Cond\,_) $ b $ c1 $ c2) xs = - syntax_const ctxt #Cond $ bexp_tr b xs $ tr c1 xs $ tr c2 xs - | tr (Const (\<^syntax_const>\_While\,_) $ b $ I $ V $ c) xs = - syntax_const ctxt #While $ bexp_tr b xs $ assn_tr I xs $ var_tr V xs $ tr c xs - | tr t _ = t; + let val (c1',a1) = tr c1 xs; + val (c2',a2) = tr c2 xs + in (syntax_const ctxt #Cond $ bexp_tr b xs $ c1' $ c2', + Syntax.const \<^const_syntax>\Acond\ $ a1 $ a2) + end + | tr (Const (\<^syntax_const>\_While\,_) $ b $ i $ v $ c) xs = + let val (c',a) = tr c xs + val (v',A) = case v of + Const (\<^const_syntax>\HOL.eq\, _) $ z $ t => (t, Syntax_Trans.abs_tr [z, a]) | + t => (t, absdummy dummyT a) + in (syntax_const ctxt #While $ bexp_tr b xs $ c', + Syntax.const \<^const_syntax>\Awhile\ + $ assn_tr i xs $ var_tr v' xs $ A) + end + | tr (Const (\<^syntax_const>\_While0\,_) $ b $ I $ c) xs = + let val (c',a) = tr c xs + in (syntax_const ctxt #While $ bexp_tr b xs $ c', + Syntax.const \<^const_syntax>\Awhile\ + $ assn_tr I xs $ var_tr (Syntax.const \<^const_syntax>\zero_class.zero\) xs + $ absdummy dummyT a) + end + | tr t _ = (t, Syntax.const \<^const_syntax>\Abasic\) in tr end; fun vars_tr (Const (\<^syntax_const>\_idts\, _) $ idt $ vars) = idt :: vars_tr vars @@ -101,12 +122,14 @@ fun hoare_vars_tr ctxt [vars, pre, prg, post] = let val xs = vars_tr vars - in syntax_const ctxt #Valid $ assn_tr pre xs $ com_tr ctxt prg xs $ assn_tr post xs end + val (c',a) = com_tr ctxt prg xs + in syntax_const ctxt #Valid $ assn_tr pre xs $ c' $ a $ assn_tr post xs end | hoare_vars_tr _ ts = raise TERM ("hoare_vars_tr", ts); fun hoare_tc_vars_tr ctxt [vars, pre, prg, post] = let val xs = vars_tr vars - in syntax_const ctxt #ValidTC $ assn_tr pre xs $ com_tr ctxt prg xs $ assn_tr post xs end + val (c',a) = com_tr ctxt prg xs + in syntax_const ctxt #ValidTC $ assn_tr pre xs $ c' $ a $ assn_tr post xs end | hoare_tc_vars_tr _ ts = raise TERM ("hoare_tc_vars_tr", ts); end; @@ -158,8 +181,9 @@ fun bexp_tr' (Const (\<^const_syntax>\Collect\, _) $ T) = dest_abstuple T | bexp_tr' t = t; -fun var_tr' (Const (\<^const_syntax>\Collect\, _) $ T) = dest_abstuple T - | var_tr' t = t; +fun var_tr' xo T = + let val n = dest_abstuple T + in case xo of NONE => n | SOME x => Syntax.const \<^const_syntax>\HOL.eq\ $ Syntax.free x $ n end (* com_tr' *) @@ -174,32 +198,40 @@ else syntax_const ctxt #Skip end; -fun com_tr' ctxt t = +fun com_tr' ctxt (t,a) = let val (head, args) = apfst (try (#1 o Term.dest_Const)) (Term.strip_comb t); fun arg k = nth args (k - 1); val n = length args; + val (_, args_a) = apfst (try (#1 o Term.dest_Const)) (Term.strip_comb a); + fun arg_a k = nth args_a (k - 1) in - (case head of + case head of NONE => t | SOME c => if c = const_syntax ctxt #Basic andalso n = 1 andalso is_f (arg 1) then mk_assign ctxt (arg 1) else if c = const_syntax ctxt #Seq andalso n = 2 then - Syntax.const \<^syntax_const>\_Seq\ $ com_tr' ctxt (arg 1) $ com_tr' ctxt (arg 2) + Syntax.const \<^syntax_const>\_Seq\ + $ com_tr' ctxt (arg 1, arg_a 1) $ com_tr' ctxt (arg 2, arg_a 2) else if c = const_syntax ctxt #Cond andalso n = 3 then Syntax.const \<^syntax_const>\_Cond\ $ - bexp_tr' (arg 1) $ com_tr' ctxt (arg 2) $ com_tr' ctxt (arg 3) - else if c = const_syntax ctxt #While andalso n = 4 then - Syntax.const \<^syntax_const>\_While\ $ - bexp_tr' (arg 1) $ assn_tr' (arg 2) $ var_tr' (arg 3) $ com_tr' ctxt (arg 4) - else t) + bexp_tr' (arg 1) $ com_tr' ctxt (arg 2, arg_a 1) $ com_tr' ctxt (arg 3, arg_a 2) + else if c = const_syntax ctxt #While andalso n = 2 then + let val (xo,a') = case arg_a 3 of + Abs(x,_,a) => (if loose_bvar1(a,0) then SOME x else NONE, + subst_bound (Syntax.free x, a)) | + t => (NONE,t) + in Syntax.const \<^syntax_const>\_While\ + $ bexp_tr' (arg 1) $ assn_tr' (arg_a 1) $ var_tr' xo (arg_a 2) $ com_tr' ctxt (arg 2, a') + end + else t end; in -fun spec_tr' syn ctxt [p, c, q] = - Syntax.const syn $ assn_tr' p $ com_tr' ctxt c $ assn_tr' q; +fun spec_tr' syn ctxt [p, c, a, q] = + Syntax.const syn $ assn_tr' p $ com_tr' ctxt (c,a) $ assn_tr' q; end; diff -r 40f03761f77f -r 403ce50e6a2a src/HOL/Hoare/hoare_tac.ML --- a/src/HOL/Hoare/hoare_tac.ML Mon Oct 11 21:55:21 2021 +0200 +++ b/src/HOL/Hoare/hoare_tac.ML Tue Oct 12 20:57:43 2021 +0200 @@ -71,7 +71,7 @@ fun get_vars c = let val d = Logic.strip_assums_concl c; - val Const _ $ pre $ _ $ _ = HOLogic.dest_Trueprop d; + val Const _ $ pre $ _ $ _ $ _ = HOLogic.dest_Trueprop d; in mk_vars pre end; fun mk_CollectC tm =