Up to index of Isabelle/HOL/CoreC++
theory Equivalence(* Title: CoreC++ ID: $Id: Equivalence.thy,v 1.20 2009-03-20 17:56:16 makarius Exp $ Author: Daniel Wasserrab Maintainer: Daniel Wasserrab <wasserra at fmi.uni-passau.de> Based on the Jinja theory J/Equivalence.thy by Tobias Nipkow *) header {* \isaheader{Equivalence of Big Step and Small Step Semantics} *} theory Equivalence imports BigStep SmallStep WWellForm begin section{* Some casts-lemmas *} lemma assumes wf:"wf_prog wf_md P" shows casts_casts: "P \<turnstile> T casts v to v' ==> P \<turnstile> T casts v' to v'" proof(induct rule:casts_to.induct) case casts_prim thus ?case by(rule casts_to.casts_prim) next case (casts_null C) thus ?case by(rule casts_to.casts_null) next case (casts_ref Cs C Cs' Ds a) have path_via:"P \<turnstile> Path last Cs to C via Cs'" and Ds:"Ds = Cs @p Cs'" by fact+ with wf have "last Cs' = C" and "Cs' ≠ []" and "class": "is_class P C" by(auto intro!:Subobjs_nonempty Subobj_last_isClass simp:path_via_def) with Ds have last:"last Ds = C" by -(drule_tac Cs' = "Cs" in appendPath_last,simp) hence Ds':"Ds = Ds @p [C]" by(simp add:appendPath_def) from last "class" have "P \<turnstile> Path last Ds to C via [C]" by(fastsimp intro:Subobjs_Base simp:path_via_def) with Ds' show ?case by(fastsimp intro:casts_to.casts_ref) qed lemma casts_casts_eq: "[| P \<turnstile> T casts v to v; P \<turnstile> T casts v to v'; wf_prog wf_md P |] ==> v = v'" apply - apply(erule casts_to.cases) apply clarsimp apply(erule casts_to.cases) apply simp apply simp apply (simp (asm_lr)) apply(erule casts_to.cases) apply simp apply simp apply simp apply simp apply(erule casts_to.cases) apply simp apply simp apply clarsimp apply(erule appendPath_path_via) by auto lemma assumes wf:"wf_prog wf_md P" shows None_lcl_casts_values: "P,E \<turnstile> 〈e,(h,l)〉 -> 〈e',(h',l')〉 ==> (!!V. [|l V = None; E V = Some T; l' V = Some v'|] ==> P \<turnstile> T casts v' to v')" and "P,E \<turnstile> 〈es,(h,l)〉 [->] 〈es',(h',l')〉 ==> (!!V. [|l V = None; E V = Some T; l' V = Some v'|] ==> P \<turnstile> T casts v' to v')" proof(induct rule:red_reds_inducts) case (RedLAss E V T' w w' h l V') have env:"E V = Some T'" and env':"E V' = Some T" and l:"l V' = None" and lupd:"(l(V \<mapsto> w')) V' = Some v'" and casts:"P \<turnstile> T' casts w to w'" by fact+ show ?case proof(cases "V = V'") case True with lupd have v':"v' = w'" by simp from True env env' have "T = T'" by simp with v' casts wf show ?thesis by(fastsimp intro:casts_casts) next case False with lupd have "l V' = Some v'" by(fastsimp split:split_if_asm) with l show ?thesis by simp qed next case (BlockRedNone E V T' e h l e' h' l' V') have l:"l V' = None" and l'upd:"(l'(V := l V)) V' = Some v'" and env:"E V' = Some T" and IH:"!!V'. [|(l(V := None)) V' = None; (E(V \<mapsto> T')) V' = Some T; l' V' = Some v'|] ==> P \<turnstile> T casts v' to v'" by fact+ show ?case proof(cases "V = V'") case True with l'upd l show ?thesis by fastsimp next case False with l l'upd have lnew:"(l(V := None)) V' = None" and l'new:"l' V' = Some v'" by (auto split:split_if_asm) from env False have env':"(E(V \<mapsto> T')) V' = Some T" by fastsimp from IH[OF lnew env' l'new] show ?thesis . qed next case (BlockRedSome E V T' e h l e' h' l' v V') have l:"l V' = None" and l'upd:"(l'(V := l V)) V' = Some v'" and env:"E V' = Some T" and IH:"!!V'. [|(l(V := None)) V' = None; (E(V \<mapsto> T')) V' = Some T; l' V' = Some v'|] ==> P \<turnstile> T casts v' to v'" by fact+ show ?case proof(cases "V = V'") case True with l l'upd show ?thesis by fastsimp next case False with l l'upd have lnew:"(l(V := None)) V' = None" and l'new:"l' V' = Some v'" by (auto split:split_if_asm) from env False have env':"(E(V \<mapsto> T')) V' = Some T" by fastsimp from IH[OF lnew env' l'new] show ?thesis . qed next case (InitBlockRed E V T' e h l w' e' h' l' w'' w V') have l:"l V' = None" and l'upd:"(l'(V := l V)) V' = Some v'" and env:"E V' = Some T" and IH:"!!V'. [|(l(V \<mapsto> w')) V' = None; (E(V \<mapsto> T')) V' = Some T; l' V' = Some v'|] ==> P \<turnstile> T casts v' to v'" by fact+ show ?case proof(cases "V = V'") case True with l l'upd show ?thesis by fastsimp next case False with l l'upd have lnew:"(l(V \<mapsto> w')) V' = None" and l'new:"l' V' = Some v'" by (auto split:split_if_asm) from env False have env':"(E(V \<mapsto> T')) V' = Some T" by fastsimp from IH[OF lnew env' l'new] show ?thesis . qed qed (auto intro:casts_casts wf) lemma assumes wf:"wf_prog wf_md P" shows Some_lcl_casts_values: "P,E \<turnstile> 〈e,(h,l)〉 -> 〈e',(h',l')〉 ==> (!!V. [|l V = Some v; E V = Some T; P \<turnstile> T casts v'' to v; l' V = Some v'|] ==> P \<turnstile> T casts v' to v')" and "P,E \<turnstile> 〈es,(h,l)〉 [->] 〈es',(h',l')〉 ==> (!!V. [|l V = Some v; E V = Some T; P \<turnstile> T casts v'' to v; l' V = Some v'|] ==> P \<turnstile> T casts v' to v')" proof(induct rule:red_reds_inducts) case (RedNew h a h' C' E l V) have l1:"l V = Some v" and l2:"l V = Some v'" and casts:"P \<turnstile> T casts v'' to v " by fact+ from l1 l2 have eq:"v = v'" by simp with casts wf show ?case by(fastsimp intro:casts_casts) next case (RedLAss E V T' w w' h l V') have l:"l V' = Some v" and lupd:"(l(V \<mapsto> w')) V' = Some v'" and T'casts:"P \<turnstile> T' casts w to w'" and env:"E V = Some T'" and env':"E V' = Some T" and casts:"P \<turnstile> T casts v'' to v" by fact+ show ?case proof (cases "V = V'") case True with lupd have v':"v' = w'" by simp from True env env' have "T = T'" by simp with T'casts v' wf show ?thesis by(fastsimp intro:casts_casts) next case False with l lupd have "v = v'" by (auto split:split_if_asm) with casts wf show ?thesis by(fastsimp intro:casts_casts) qed next case (RedFAss h a D S Cs' F T' Cs w w' Ds fs E l V) have l1:"l V = Some v" and l2:"l V = Some v'" and hp:"h a = Some(D, S)" and T'casts:"P \<turnstile> T' casts w to w'" and casts:"P \<turnstile> T casts v'' to v" by fact+ from l1 l2 have eq:"v = v'" by simp with casts wf show ?case by(fastsimp intro:casts_casts) next case (BlockRedNone E V T' e h l e' h' l' V') have l':"l' V = None" and l:"l V' = Some v" and l'upd:"(l'(V := l V)) V' = Some v'" and env:"E V' = Some T" and casts:"P \<turnstile> T casts v'' to v" and IH:"!!V'. [|(l(V := None)) V' = Some v; (E(V \<mapsto> T')) V' = Some T; P \<turnstile> T casts v'' to v ; l' V' = Some v'|] ==> P \<turnstile> T casts v' to v'" by fact+ show ?case proof(cases "V = V'") case True with l' l'upd have "l V = Some v'" by auto with True l have eq:"v = v'" by simp with casts wf show ?thesis by(fastsimp intro:casts_casts) next case False with l l'upd have lnew:"(l(V := None)) V' = Some v" and l'new:"l' V' = Some v'" by (auto split:split_if_asm) from env False have env':"(E(V \<mapsto> T')) V' = Some T" by fastsimp from IH[OF lnew env' casts l'new] show ?thesis . qed next case (BlockRedSome E V T' e h l e' h' l' w V') have l':"l' V = Some w" and l:"l V' = Some v" and l'upd:"(l'(V := l V)) V' = Some v'" and env:"E V' = Some T" and casts:"P \<turnstile> T casts v'' to v" and IH:"!!V'. [|(l(V := None)) V' = Some v; (E(V \<mapsto> T')) V' = Some T; P \<turnstile> T casts v'' to v ; l' V' = Some v'|] ==> P \<turnstile> T casts v' to v'" by fact+ show ?case proof(cases "V = V'") case True with l' l'upd have "l V = Some v'" by auto with True l have eq:"v = v'" by simp with casts wf show ?thesis by(fastsimp intro:casts_casts) next case False with l l'upd have lnew:"(l(V := None)) V' = Some v" and l'new:"l' V' = Some v'" by (auto split:split_if_asm) from env False have env':"(E(V \<mapsto> T')) V' = Some T" by fastsimp from IH[OF lnew env' casts l'new] show ?thesis . qed next case (InitBlockRed E V T' e h l w' e' h' l' w'' w V') have l:"l V' = Some v" and l':"l' V = Some w''" and l'upd:"(l'(V := l V)) V' = Some v'" and env:"E V' = Some T" and casts:"P \<turnstile> T casts v'' to v" and IH:"!!V'. [|(l(V \<mapsto> w')) V' = Some v; (E(V \<mapsto> T')) V' = Some T; P \<turnstile> T casts v'' to v ; l' V' = Some v'|] ==> P \<turnstile> T casts v' to v'" by fact+ show ?case proof(cases "V = V'") case True with l' l'upd have "l V = Some v'" by auto with True l have eq:"v = v'" by simp with casts wf show ?thesis by(fastsimp intro:casts_casts) next case False with l l'upd have lnew:"(l(V \<mapsto> w')) V' = Some v" and l'new:"l' V' = Some v'" by (auto split:split_if_asm) from env False have env':"(E(V \<mapsto> T')) V' = Some T" by fastsimp from IH[OF lnew env' casts l'new] show ?thesis . qed qed (auto intro:casts_casts wf) section{*Small steps simulate big step*} subsection {*Cast*} lemma StaticCastReds: "P,E \<turnstile> 〈e,s〉 ->* 〈e',s'〉 ==> P,E \<turnstile> 〈(|C|)),e,s〉 ->* 〈(|C|)),e',s'〉" apply(erule rtrancl_induct2) apply blast apply(erule rtrancl_into_rtrancl) apply (simp add:StaticCastRed) done lemma StaticCastRedsNull: "P,E \<turnstile> 〈e,s〉 ->* 〈null,s'〉 ==> P,E \<turnstile> 〈(|C|)),e,s〉 ->* 〈null,s'〉" apply(rule rtrancl_into_rtrancl) apply(erule StaticCastReds) apply(simp add:RedStaticCastNull) done lemma StaticUpCastReds: "[| P,E \<turnstile> 〈e,s〉 ->* 〈ref(a,Cs),s'〉; P \<turnstile> Path last Cs to C via Cs'; Ds = Cs@pCs' |] ==> P,E \<turnstile> 〈(|C|)),e,s〉 ->* 〈ref(a,Ds),s'〉" apply(rule rtrancl_into_rtrancl) apply(erule StaticCastReds) apply(fastsimp intro:RedStaticUpCast) done lemma StaticDownCastReds: "P,E \<turnstile> 〈e,s〉 ->* 〈ref(a,Cs@[C]@Cs'),s'〉 ==> P,E \<turnstile> 〈(|C|)),e,s〉 ->* 〈ref(a,Cs@[C]),s'〉" apply(rule rtrancl_into_rtrancl) apply(erule StaticCastReds) apply simp apply(subgoal_tac "P,E \<turnstile> 〈(|C|)),ref(a,Cs@[C]@Cs'),s'〉 -> 〈ref(a,Cs@[C]),s'〉") apply simp apply(rule RedStaticDownCast) done lemma StaticCastRedsFail: "[| P,E \<turnstile> 〈e,s〉 ->* 〈ref(a,Cs),s'〉; C ∉ set Cs; ¬ P \<turnstile> (last Cs) \<preceq>* C |] ==> P,E \<turnstile> 〈(|C|)),e,s〉 ->* 〈THROW ClassCast,s'〉" apply(rule rtrancl_into_rtrancl) apply(erule StaticCastReds) apply(fastsimp intro:RedStaticCastFail) done lemma StaticCastRedsThrow: "[| P,E \<turnstile> 〈e,s〉 ->* 〈Throw r,s'〉 |] ==> P,E \<turnstile> 〈(|C|)),e,s〉 ->* 〈Throw r,s'〉" apply(rule rtrancl_into_rtrancl) apply(erule StaticCastReds) apply(simp add:red_reds.StaticCastThrow) done lemma DynCastReds: "P,E \<turnstile> 〈e,s〉 ->* 〈e',s'〉 ==> P,E \<turnstile> 〈Cast C e,s〉 ->* 〈Cast C e',s'〉" apply(erule rtrancl_induct2) apply blast apply(erule rtrancl_into_rtrancl) apply (simp add:DynCastRed) done lemma DynCastRedsNull: "P,E \<turnstile> 〈e,s〉 ->* 〈null,s'〉 ==> P,E \<turnstile> 〈Cast C e,s〉 ->* 〈null,s'〉" apply(rule rtrancl_into_rtrancl) apply(erule DynCastReds) apply(simp add:RedDynCastNull) done lemma DynCastRedsRef: "[| P,E \<turnstile> 〈e,s〉 ->* 〈ref(a,Cs),s'〉; hp s' a = Some (D,S); P \<turnstile> Path D to C via Cs'; P \<turnstile> Path D to C unique |] ==> P,E \<turnstile> 〈Cast C e,s〉 ->* 〈ref(a,Cs'),s'〉" apply(rule rtrancl_into_rtrancl) apply(erule DynCastReds) apply(fastsimp intro:RedDynCast) done lemma StaticUpDynCastReds: "[| P,E \<turnstile> 〈e,s〉 ->* 〈ref(a,Cs),s'〉; P \<turnstile> Path last Cs to C unique; P \<turnstile> Path last Cs to C via Cs'; Ds = Cs@pCs' |] ==> P,E \<turnstile> 〈Cast C e,s〉 ->* 〈ref(a,Ds),s'〉" apply(rule rtrancl_into_rtrancl) apply(erule DynCastReds) apply(fastsimp intro:RedStaticUpDynCast) done lemma StaticDownDynCastReds: "P,E \<turnstile> 〈e,s〉 ->* 〈ref(a,Cs@[C]@Cs'),s'〉 ==> P,E \<turnstile> 〈Cast C e,s〉 ->* 〈ref(a,Cs@[C]),s'〉" apply(rule rtrancl_into_rtrancl) apply(erule DynCastReds) apply simp apply(subgoal_tac "P,E \<turnstile> 〈Cast C (ref(a,Cs@[C]@Cs')),s'〉 -> 〈ref(a,Cs@[C]),s'〉") apply simp apply(rule RedStaticDownDynCast) done lemma DynCastRedsFail: "[| P,E \<turnstile> 〈e,s〉 ->* 〈ref(a,Cs),s'〉; hp s' a = Some (D,S); ¬ P \<turnstile> Path D to C unique; ¬ P \<turnstile> Path last Cs to C unique; C ∉ set Cs |] ==> P,E \<turnstile> 〈Cast C e,s〉 ->* 〈null,s'〉" apply(rule rtrancl_into_rtrancl) apply(erule DynCastReds) apply(fastsimp intro:RedDynCastFail) done lemma DynCastRedsThrow: "[| P,E \<turnstile> 〈e,s〉 ->* 〈Throw r,s'〉 |] ==> P,E \<turnstile> 〈Cast C e,s〉 ->* 〈Throw r,s'〉" apply(rule rtrancl_into_rtrancl) apply(erule DynCastReds) apply(simp add:red_reds.DynCastThrow) done subsection {*LAss*} lemma LAssReds: "P,E \<turnstile> 〈e,s〉 ->* 〈e',s'〉 ==> P,E \<turnstile> 〈V:=e,s〉 ->* 〈V:=e',s'〉" apply(erule rtrancl_induct2) apply blast apply(erule rtrancl_into_rtrancl) apply(simp add:LAssRed) done lemma LAssRedsVal: "[| P,E \<turnstile> 〈e,s〉 ->* 〈Val v,(h',l')〉; E V = Some T; P \<turnstile> T casts v to v'|] ==> P,E \<turnstile> 〈 V:=e,s〉 ->* 〈Val v',(h',l'(V\<mapsto>v'))〉" apply(rule rtrancl_into_rtrancl) apply(erule LAssReds) apply(simp add:RedLAss) done lemma LAssRedsThrow: "[| P,E \<turnstile> 〈e,s〉 ->* 〈Throw r,s'〉 |] ==> P,E \<turnstile> 〈 V:=e,s〉 ->* 〈Throw r,s'〉" apply(rule rtrancl_into_rtrancl) apply(erule LAssReds) apply(simp add:red_reds.LAssThrow) done subsection {*BinOp*} lemma BinOp1Reds: "P,E \<turnstile> 〈e,s〉 ->* 〈e',s'〉 ==> P,E \<turnstile> 〈 e «bop» e2, s〉 ->* 〈e' «bop» e2, s'〉" apply(erule rtrancl_induct2) apply blast apply(erule rtrancl_into_rtrancl) apply(simp add:BinOpRed1) done lemma BinOp2Reds: "P,E \<turnstile> 〈e,s〉 ->* 〈e',s'〉 ==> P,E \<turnstile> 〈(Val v) «bop» e, s〉 ->* 〈(Val v) «bop» e', s'〉" apply(erule rtrancl_induct2) apply blast apply(erule rtrancl_into_rtrancl) apply(simp add:BinOpRed2) done lemma BinOpRedsVal: "[| P,E \<turnstile> 〈e1,s0〉 ->* 〈Val v1,s1〉; P,E \<turnstile> 〈e2,s1〉 ->* 〈Val v2,s2〉; binop(bop,v1,v2) = Some v |] ==> P,E \<turnstile> 〈e1 «bop» e2, s0〉 ->* 〈Val v,s2〉" apply(rule rtrancl_trans) apply(erule BinOp1Reds) apply(rule rtrancl_into_rtrancl) apply(erule BinOp2Reds) apply(simp add:RedBinOp) done lemma BinOpRedsThrow1: "P,E \<turnstile> 〈e,s〉 ->* 〈Throw r,s'〉 ==> P,E \<turnstile> 〈e «bop» e2, s〉 ->* 〈Throw r, s'〉" apply(rule rtrancl_into_rtrancl) apply(erule BinOp1Reds) apply(simp add:red_reds.BinOpThrow1) done lemma BinOpRedsThrow2: "[| P,E \<turnstile> 〈e1,s0〉 ->* 〈Val v1,s1〉; P,E \<turnstile> 〈e2,s1〉 ->* 〈Throw r,s2〉|] ==> P,E \<turnstile> 〈e1 «bop» e2, s0〉 ->* 〈Throw r,s2〉" apply(rule rtrancl_trans) apply(erule BinOp1Reds) apply(rule rtrancl_into_rtrancl) apply(erule BinOp2Reds) apply(simp add:red_reds.BinOpThrow2) done subsection {*FAcc*} lemma FAccReds: "P,E \<turnstile> 〈e,s〉 ->* 〈e',s'〉 ==> P,E \<turnstile> 〈e•F{Cs}, s〉 ->* 〈e'•F{Cs}, s'〉" apply(erule rtrancl_induct2) apply blast apply(erule rtrancl_into_rtrancl) apply(simp add:FAccRed) done lemma FAccRedsVal: "[|P,E \<turnstile> 〈e,s〉 ->* 〈ref(a,Cs'),s'〉; hp s' a = Some(D,S); Ds = Cs'@pCs; (Ds,fs) ∈ S; fs F = Some v |] ==> P,E \<turnstile> 〈e•F{Cs},s〉 ->* 〈Val v,s'〉" apply(rule rtrancl_into_rtrancl) apply(erule FAccReds) apply (fastsimp intro:RedFAcc) done lemma FAccRedsNull: "P,E \<turnstile> 〈e,s〉 ->* 〈null,s'〉 ==> P,E \<turnstile> 〈e•F{Cs},s〉 ->* 〈THROW NullPointer,s'〉" apply(rule rtrancl_into_rtrancl) apply(erule FAccReds) apply(simp add:RedFAccNull) done lemma FAccRedsThrow: "P,E \<turnstile> 〈e,s〉 ->* 〈Throw r,s'〉 ==> P,E \<turnstile> 〈e•F{Cs},s〉 ->* 〈Throw r,s'〉" apply(rule rtrancl_into_rtrancl) apply(erule FAccReds) apply(simp add:red_reds.FAccThrow) done subsection {*FAss*} lemma FAssReds1: "P,E \<turnstile> 〈e,s〉 ->* 〈e',s'〉 ==> P,E \<turnstile> 〈e•F{Cs}:=e2, s〉 ->* 〈e'•F{Cs}:=e2, s'〉" apply(erule rtrancl_induct2) apply blast apply(erule rtrancl_into_rtrancl) apply(simp add:FAssRed1) done lemma FAssReds2: "P,E \<turnstile> 〈e,s〉 ->* 〈e',s'〉 ==> P,E \<turnstile> 〈Val v•F{Cs}:=e, s〉 ->* 〈Val v•F{Cs}:=e', s'〉" apply(erule rtrancl_induct2) apply blast apply(erule rtrancl_into_rtrancl) apply(simp add:FAssRed2) done lemma FAssRedsVal: "[| P,E \<turnstile> 〈e1,s0〉 ->* 〈ref(a,Cs'),s1〉; P,E \<turnstile> 〈e2,s1〉 ->* 〈Val v,(h2,l2)〉; h2 a = Some(D,S); P \<turnstile> (last Cs') has least F:T via Cs; P \<turnstile> T casts v to v'; Ds = Cs'@pCs; (Ds,fs) ∈ S |] ==> P,E \<turnstile> 〈e1•F{Cs}:=e2, s0〉 ->* 〈Val v',(h2(a\<mapsto>(D,insert (Ds,fs(F\<mapsto>v')) (S - {(Ds,fs)}))),l2)〉" apply(rule rtrancl_trans) apply(erule FAssReds1) apply(rule rtrancl_into_rtrancl) apply(erule FAssReds2) apply(fastsimp intro:RedFAss) done lemma FAssRedsNull: "[| P,E \<turnstile> 〈e1,s0〉 ->* 〈null,s1〉; P,E \<turnstile> 〈e2,s1〉 ->* 〈Val v,s2〉 |] ==> P,E \<turnstile> 〈e1•F{Cs}:=e2, s0〉 ->* 〈THROW NullPointer, s2〉" apply(rule rtrancl_trans) apply(erule FAssReds1) apply(rule rtrancl_into_rtrancl) apply(erule FAssReds2) apply(simp add:RedFAssNull) done lemma FAssRedsThrow1: "P,E \<turnstile> 〈e,s〉 ->* 〈Throw r,s'〉 ==> P,E \<turnstile> 〈e•F{Cs}:=e2, s〉 ->* 〈Throw r, s'〉" apply(rule rtrancl_into_rtrancl) apply(erule FAssReds1) apply(simp add:red_reds.FAssThrow1) done lemma FAssRedsThrow2: "[| P,E \<turnstile> 〈e1,s0〉 ->* 〈Val v,s1〉; P,E \<turnstile> 〈e2,s1〉 ->* 〈Throw r,s2〉 |] ==> P,E \<turnstile> 〈e1•F{Cs}:=e2,s0〉 ->* 〈Throw r,s2〉" apply(rule rtrancl_trans) apply(erule FAssReds1) apply(rule rtrancl_into_rtrancl) apply(erule FAssReds2) apply(simp add:red_reds.FAssThrow2) done subsection {*;;*} lemma SeqReds: "P,E \<turnstile> 〈e,s〉 ->* 〈e',s'〉 ==> P,E \<turnstile> 〈e;;e2, s〉 ->* 〈e';;e2, s'〉" apply(erule rtrancl_induct2) apply blast apply(erule rtrancl_into_rtrancl) apply(simp add:SeqRed) done lemma SeqRedsThrow: "P,E \<turnstile> 〈e,s〉 ->* 〈Throw r,s'〉 ==> P,E \<turnstile> 〈e;;e2, s〉 ->* 〈Throw r, s'〉" apply(rule rtrancl_into_rtrancl) apply(erule SeqReds) apply(simp add:red_reds.SeqThrow) done lemma SeqReds2: "[| P,E \<turnstile> 〈e1,s0〉 ->* 〈Val v1,s1〉; P,E \<turnstile> 〈e2,s1〉 ->* 〈e2',s2〉 |] ==> P,E \<turnstile> 〈e1;;e2, s0〉 ->* 〈e2',s2〉" apply(rule rtrancl_trans) apply(erule SeqReds) apply(rule_tac b="(e2,s1)" in converse_rtrancl_into_rtrancl) apply(simp add:RedSeq) apply assumption done subsection {*If*} lemma CondReds: "P,E \<turnstile> 〈e,s〉 ->* 〈e',s'〉 ==> P,E \<turnstile> 〈if (e) e1 else e2,s〉 ->* 〈if (e') e1 else e2,s'〉" apply(erule rtrancl_induct2) apply blast apply(erule rtrancl_into_rtrancl) apply(simp add:CondRed) done lemma CondRedsThrow: "P,E \<turnstile> 〈e,s〉 ->* 〈Throw r,s'〉 ==> P,E \<turnstile> 〈if (e) e1 else e2, s〉 ->* 〈Throw r,s'〉" apply(rule rtrancl_into_rtrancl) apply(erule CondReds) apply(simp add:red_reds.CondThrow) done lemma CondReds2T: "[|P,E \<turnstile> 〈e,s0〉 ->* 〈true,s1〉; P,E \<turnstile> 〈e1, s1〉 ->* 〈e',s2〉 |] ==> P,E \<turnstile> 〈if (e) e1 else e2, s0〉 ->* 〈e',s2〉" apply(rule rtrancl_trans) apply(erule CondReds) apply(rule_tac b="(e1, s1)" in converse_rtrancl_into_rtrancl) apply(simp add:RedCondT) apply assumption done lemma CondReds2F: "[|P,E \<turnstile> 〈e,s0〉 ->* 〈false,s1〉; P,E \<turnstile> 〈e2, s1〉 ->* 〈e',s2〉 |] ==> P,E \<turnstile> 〈if (e) e1 else e2, s0〉 ->* 〈e',s2〉" apply(rule rtrancl_trans) apply(erule CondReds) apply(rule_tac b="(e2, s1)" in converse_rtrancl_into_rtrancl) apply(simp add:RedCondF) apply assumption done subsection {*While*} lemma WhileFReds: "P,E \<turnstile> 〈b,s〉 ->* 〈false,s'〉 ==> P,E \<turnstile> 〈while (b) c,s〉 ->* 〈unit,s'〉" apply(rule_tac b="(if(b) (c;;while(b) c) else unit, s)" in converse_rtrancl_into_rtrancl) apply(simp add:RedWhile) apply(rule rtrancl_into_rtrancl) apply(erule CondReds) apply(simp add:RedCondF) done lemma WhileRedsThrow: "P,E \<turnstile> 〈b,s〉 ->* 〈Throw r,s'〉 ==> P,E \<turnstile> 〈while (b) c,s〉 ->* 〈Throw r,s'〉" apply(rule_tac b="(if(b) (c;;while(b) c) else unit, s)" in converse_rtrancl_into_rtrancl) apply(simp add:RedWhile) apply(rule rtrancl_into_rtrancl) apply(erule CondReds) apply(simp add:red_reds.CondThrow) done lemma WhileTReds: "[| P,E \<turnstile> 〈b,s0〉 ->* 〈true,s1〉; P,E \<turnstile> 〈c,s1〉 ->* 〈Val v1,s2〉; P,E \<turnstile> 〈while (b) c,s2〉 ->* 〈e,s3〉 |] ==> P,E \<turnstile> 〈while (b) c,s0〉 ->* 〈e,s3〉" apply(rule_tac b="(if(b) (c;;while(b) c) else unit, s0)" in converse_rtrancl_into_rtrancl) apply(simp add:RedWhile) apply(rule rtrancl_trans) apply(erule CondReds) apply(rule_tac b="(c;;while(b) c,s1)" in converse_rtrancl_into_rtrancl) apply(simp add:RedCondT) apply(rule rtrancl_trans) apply(erule SeqReds) apply(rule_tac b="(while(b) c,s2)" in converse_rtrancl_into_rtrancl) apply(simp add:RedSeq) apply assumption done lemma WhileTRedsThrow: "[| P,E \<turnstile> 〈b,s0〉 ->* 〈true,s1〉; P,E \<turnstile> 〈c,s1〉 ->* 〈Throw r,s2〉 |] ==> P,E \<turnstile> 〈while (b) c,s0〉 ->* 〈Throw r,s2〉" apply(rule_tac b="(if(b) (c;;while(b) c) else unit, s0)" in converse_rtrancl_into_rtrancl) apply(simp add:RedWhile) apply(rule rtrancl_trans) apply(erule CondReds) apply(rule_tac b="(c;;while(b) c,s1)" in converse_rtrancl_into_rtrancl) apply(simp add:RedCondT) apply(rule rtrancl_trans) apply(erule SeqReds) apply(rule_tac b="(Throw r,s2)" in converse_rtrancl_into_rtrancl) apply(simp add:red_reds.SeqThrow) apply simp done subsection {*Throw*} lemma ThrowReds: "P,E \<turnstile> 〈e,s〉 ->* 〈e',s'〉 ==> P,E \<turnstile> 〈throw e,s〉 ->* 〈throw e',s'〉" apply(erule rtrancl_induct2) apply blast apply(erule rtrancl_into_rtrancl) apply(simp add:ThrowRed) done lemma ThrowRedsNull: "P,E \<turnstile> 〈e,s〉 ->* 〈null,s'〉 ==> P,E \<turnstile> 〈throw e,s〉 ->* 〈THROW NullPointer,s'〉" apply(rule rtrancl_into_rtrancl) apply(erule ThrowReds) apply(simp add:RedThrowNull) done lemma ThrowRedsThrow: "P,E \<turnstile> 〈e,s〉 ->* 〈Throw r,s'〉 ==> P,E \<turnstile> 〈throw e,s〉 ->* 〈Throw r,s'〉" apply(rule rtrancl_into_rtrancl) apply(erule ThrowReds) apply(simp add:red_reds.ThrowThrow) done subsection {*InitBlock*} lemma assumes wf:"wf_prog wf_md P" shows InitBlockReds_aux: "P,E(V \<mapsto> T) \<turnstile> 〈e,s〉 ->* 〈e',s'〉 ==> ∀h l h' l' v v'. s = (h,l(V\<mapsto>v')) --> P \<turnstile> T casts v to v' --> s' = (h',l') --> (∃v'' w. P,E \<turnstile> 〈{V:T := Val v; e},(h,l)〉 ->* 〈{V:T := Val v''; e'},(h',l'(V:=(l V)))〉 ∧ P \<turnstile> T casts v'' to w)" proof (erule converse_rtrancl_induct2) { fix h l h' l' v v' assume "s' = (h, l(V \<mapsto> v'))" and "s' = (h', l')" hence h:"h = h'" and l':"l' = l(V \<mapsto> v')" by simp_all hence "P,E \<turnstile> 〈{V:T; V:=Val v;; e'},(h, l)〉 ->* 〈{V:T; V:=Val v;; e'},(h', l'(V := l V))〉" by(fastsimp simp: fun_upd_same simp del:fun_upd_apply) } hence "∀h l h' l' v v'. s' = (h, l(V \<mapsto> v')) --> P \<turnstile> T casts v to v' --> s' = (h', l') --> P,E \<turnstile> 〈{V:T; V:=Val v;; e'},(h, l)〉 ->* 〈{V:T; V:=Val v;; e'},(h', l'(V := l V))〉 ∧ P \<turnstile> T casts v to v'" by auto thus "∀h l h' l' v v'. s' = (h, l(V \<mapsto> v')) --> P \<turnstile> T casts v to v' --> s' = (h', l') --> (∃v'' w. P,E \<turnstile> 〈{V:T; V:=Val v;; e'},(h, l)〉 ->* 〈{V:T; V:=Val v'';; e'},(h', l'(V := l V))〉 ∧ P \<turnstile> T casts v'' to w)" by auto next fix e s e'' s'' assume Red:"((e,s),e'',s'') ∈ Red P (E(V \<mapsto> T))" and reds:"P,E(V \<mapsto> T) \<turnstile> 〈e'',s''〉 ->* 〈e',s'〉" and IH:"∀h l h' l' v v'. s'' = (h, l(V \<mapsto> v')) --> P \<turnstile> T casts v to v' --> s' = (h', l') --> (∃v'' w. P,E \<turnstile> 〈{V:T; V:=Val v;; e''},(h, l)〉 ->* 〈{V:T; V:=Val v'';; e'},(h', l'(V := l V))〉 ∧ P \<turnstile> T casts v'' to w)" { fix h l h' l' v v' assume s:"s = (h, l(V \<mapsto> v'))" and s':"s' = (h', l')" and casts:"P \<turnstile> T casts v to v'" obtain h'' l'' where s'':"s'' = (h'',l'')" by (cases s'') auto with Red s have "V ∈ dom l''" by (fastsimp dest:red_lcl_incr) then obtain v'' where l'':"l'' V = Some v''" by auto with Red s s'' casts have step:"P,E \<turnstile> 〈{V:T := Val v; e},(h, l)〉 -> 〈{V:T := Val v''; e''}, (h'',l''(V := l V))〉" by(fastsimp intro:InitBlockRed) from Red s s'' l'' casts wf have casts':"P \<turnstile> T casts v'' to v''" by(fastsimp intro:Some_lcl_casts_values) with IH s'' s' l'' obtain v''' w where "P,E \<turnstile> 〈{V:T := Val v''; e''}, (h'',l''(V := l V))〉 ->* 〈{V:T := Val v'''; e'},(h', l'(V := l V))〉 ∧ P \<turnstile> T casts v''' to w" apply simp apply (erule_tac x = "l''(V := l V)" in allE) apply (erule_tac x = "v''" in allE) apply (erule_tac x = "v''" in allE) by(auto intro:ext) with step have "∃v'' w. P,E \<turnstile> 〈{V:T; V:=Val v;; e},(h, l)〉 ->* 〈{V:T; V:=Val v'';; e'},(h', l'(V := l V))〉 ∧ P \<turnstile> T casts v'' to w" apply(rule_tac x="v'''" in exI) apply auto apply (rule converse_rtrancl_into_rtrancl) by simp_all } thus "∀h l h' l' v v'. s = (h, l(V \<mapsto> v')) --> P \<turnstile> T casts v to v' --> s' = (h', l') --> (∃v'' w. P,E \<turnstile> 〈{V:T; V:=Val v;; e},(h, l)〉 ->* 〈{V:T; V:=Val v'';; e'},(h', l'(V := l V))〉 ∧ P \<turnstile> T casts v'' to w)" by auto qed lemma InitBlockReds: "[|P,E(V \<mapsto> T) \<turnstile> 〈e, (h,l(V\<mapsto>v'))〉 ->* 〈e', (h',l')〉; P \<turnstile> T casts v to v'; wf_prog wf_md P |] ==> ∃v'' w. P,E \<turnstile> 〈{V:T := Val v; e}, (h,l)〉 ->* 〈{V:T := Val v''; e'}, (h',l'(V:=(l V)))〉 ∧ P \<turnstile> T casts v'' to w" by(blast dest:InitBlockReds_aux) lemma InitBlockRedsFinal: assumes reds:"P,E(V \<mapsto> T) \<turnstile> 〈e,(h,l(V\<mapsto>v'))〉 ->* 〈e',(h',l')〉" and final:"final e'" and casts:"P \<turnstile> T casts v to v'" and wf:"wf_prog wf_md P" shows "P,E \<turnstile> 〈{V:T := Val v; e},(h,l)〉 ->* 〈e',(h', l'(V := l V))〉" proof - from reds casts wf obtain v'' and w where steps:"P,E \<turnstile> 〈{V:T := Val v; e},(h,l)〉 ->* 〈{V:T := Val v''; e'}, (h',l'(V:=(l V)))〉" and casts':"P \<turnstile> T casts v'' to w" by (auto dest:InitBlockReds) from final casts casts' have step:"P,E \<turnstile> 〈{V:T := Val v''; e'}, (h',l'(V:=(l V)))〉 -> 〈e',(h',l'(V := l V))〉" by(auto elim!:finalE intro:RedInitBlock InitBlockThrow) from step steps show ?thesis by(fastsimp intro:rtrancl_into_rtrancl) qed subsection {*Block*} lemma BlockRedsFinal: assumes reds: "P,E(V \<mapsto> T) \<turnstile> 〈e0,s0〉 ->* 〈e2,(h2,l2)〉" and fin: "final e2" and wf:"wf_prog wf_md P" shows "!!h0 l0. s0 = (h0,l0(V:=None)) ==> P,E \<turnstile> 〈{V:T; e0},(h0,l0)〉 ->* 〈e2,(h2,l2(V:=l0 V))〉" using reds proof (induct rule:converse_rtrancl_induct2) case refl thus ?case by(fastsimp intro:finalE[OF fin] RedBlock BlockThrow simp del:fun_upd_apply) next case (step e0 s0 e1 s1) have Red: "((e0,s0),e1,s1) ∈ Red P (E(V \<mapsto> T))" and reds: "P,E(V \<mapsto> T) \<turnstile> 〈e1,s1〉 ->* 〈e2,(h2,l2)〉" and IH: "!!h l. s1 = (h,l(V := None)) ==> P,E \<turnstile> 〈{V:T; e1},(h,l)〉 ->* 〈e2,(h2, l2(V := l V))〉" and s0: "s0 = (h0, l0(V := None))" by fact+ obtain h1 l1 where s1: "s1 = (h1,l1)" by fastsimp show ?case proof cases assume "assigned V e0" then obtain v e where e0: "e0 = V:= Val v;; e" by (unfold assigned_def)blast from Red e0 s0 obtain v' where e1: "e1 = Val v';;e" and s1: "s1 = (h0, l0(V \<mapsto> v'))" and casts:"P \<turnstile> T casts v to v'" by auto from e1 fin have "e1 ≠ e2" by (auto simp:final_def) then obtain e' s' where red1: "P,E(V \<mapsto> T) \<turnstile> 〈e1,s1〉 -> 〈e',s'〉" and reds': "P,E(V \<mapsto> T) \<turnstile> 〈e',s'〉 ->* 〈e2,(h2,l2)〉" using converse_rtranclE2[OF reds] by simp blast from red1 e1 have es': "e' = e" "s' = s1" by auto show ?thesis using e0 s1 es' reds' by(fastsimp intro!: InitBlockRedsFinal[OF _ fin casts wf] simp del:fun_upd_apply) next assume unass: "¬ assigned V e0" show ?thesis proof (cases "l1 V") assume None: "l1 V = None" hence "P,E \<turnstile> 〈{V:T; e0},(h0,l0)〉 -> 〈{V:T; e1},(h1, l1(V := l0 V))〉" using s0 s1 Red by(simp add: BlockRedNone[OF _ _ unass]) moreover have "P,E \<turnstile> 〈{V:T; e1},(h1, l1(V := l0 V))〉 ->* 〈e2,(h2, l2(V := l0 V))〉" using IH[of _ "l1(V := l0 V)"] s1 None by(simp add:fun_upd_idem) ultimately show ?case by(rule_tac b="({V:T; e1},(h1, l1(V := l0 V)))" in converse_rtrancl_into_rtrancl,simp) next fix v assume Some: "l1 V = Some v" with Red Some s0 s1 wf have casts:"P \<turnstile> T casts v to v" by(fastsimp intro:None_lcl_casts_values) from Some have "P,E \<turnstile> 〈{V:T;e0},(h0,l0)〉 -> 〈{V:T := Val v; e1},(h1,l1(V := l0 V))〉" using s0 s1 Red by(simp add: BlockRedSome[OF _ _ unass]) moreover have "P,E \<turnstile> 〈{V:T := Val v; e1},(h1,l1(V:= l0 V))〉 ->* 〈e2,(h2,l2(V:=l0 V))〉" using InitBlockRedsFinal[OF _ fin casts wf,of _ _ "l1(V:=l0 V)" V] Some reds s1 by (simp add:fun_upd_idem) ultimately show ?case by(rule_tac b="({V:T; V:=Val v;; e1},(h1, l1(V := l0 V)))" in converse_rtrancl_into_rtrancl,simp) qed qed qed subsection {*List*} lemma ListReds1: "P,E \<turnstile> 〈e,s〉 ->* 〈e',s'〉 ==> P,E \<turnstile> 〈e#es,s〉 [->]* 〈e' # es,s'〉" apply(erule rtrancl_induct2) apply blast apply(erule rtrancl_into_rtrancl) apply(simp add:ListRed1) done lemma ListReds2: "P,E \<turnstile> 〈es,s〉 [->]* 〈es',s'〉 ==> P,E \<turnstile> 〈Val v # es,s〉 [->]* 〈Val v # es',s'〉" apply(erule rtrancl_induct2) apply blast apply(erule rtrancl_into_rtrancl) apply(simp add:ListRed2) done lemma ListRedsVal: "[| P,E \<turnstile> 〈e,s0〉 ->* 〈Val v,s1〉; P,E \<turnstile> 〈es,s1〉 [->]* 〈es',s2〉 |] ==> P,E \<turnstile> 〈e#es,s0〉 [->]* 〈Val v # es',s2〉" apply(rule rtrancl_trans) apply(erule ListReds1) apply(erule ListReds2) done subsection {*Call*} text{* First a few lemmas on what happens to free variables during redction. *} lemma assumes wf: "wwf_prog P" shows Red_fv: "P,E \<turnstile> 〈e,(h,l)〉 -> 〈e',(h',l')〉 ==> fv e' ⊆ fv e" and "P,E \<turnstile> 〈es,(h,l)〉 [->] 〈es',(h',l')〉 ==> fvs es' ⊆ fvs es" proof (induct rule:red_reds_inducts) case (RedCall h l a C S Cs M Ts' T' pns' body' Ds Ts T pns body Cs' vs bs new_body E) hence "fv body ⊆ {this} ∪ set pns" using prems by(fastsimp dest!:select_method_wf_mdecl simp:wf_mdecl_def) with prems show ?case by(cases T') auto next case (RedStaticCall Cs C Cs'' M Ts T pns body Cs' Ds vs E a a' b) hence "fv body ⊆ {this} ∪ set pns" using prems by(fastsimp dest!:has_least_wf_mdecl simp:wf_mdecl_def) with prems show ?case by auto qed auto lemma Red_dom_lcl: "P,E \<turnstile> 〈e,(h,l)〉 -> 〈e',(h',l')〉 ==> dom l' ⊆ dom l ∪ fv e" and "P,E \<turnstile> 〈es,(h,l)〉 [->] 〈es',(h',l')〉 ==> dom l' ⊆ dom l ∪ fvs es" proof (induct rule:red_reds_inducts) case RedLAss thus ?case by(force split:if_splits) next case CallParams thus ?case by(force split:if_splits) next case BlockRedNone thus ?case by clarsimp (fastsimp split:if_splits) next case BlockRedSome thus ?case by clarsimp (fastsimp split:if_splits) next case InitBlockRed thus ?case by clarsimp (fastsimp split:if_splits) qed auto lemma Reds_dom_lcl: "[| wwf_prog P; P,E \<turnstile> 〈e,(h,l)〉 ->* 〈e',(h',l')〉 |] ==> dom l' ⊆ dom l ∪ fv e" apply(erule converse_rtrancl_induct_red) apply blast apply(blast dest: Red_fv Red_dom_lcl) done text{* Now a few lemmas on the behaviour of blocks during reduction. *} lemma override_on_upd_lemma: "(override_on f (g(a\<mapsto>b)) A)(a := g a) = override_on f g (insert a A)" apply(rule ext) apply(simp add:override_on_def) done declare fun_upd_apply[simp del] map_upds_twist[simp del] lemma assumes wf:"wf_prog wf_md P" shows blocksReds: "!!l0 E vs'. [| length Vs = length Ts; length vs = length Ts; distinct Vs; (*∀T∈set Ts. is_type P T;*) P \<turnstile> Ts Casts vs to vs'; P,E(Vs [\<mapsto>] Ts) \<turnstile> 〈e, (h0,l0(Vs [\<mapsto>] vs'))〉 ->* 〈e', (h1,l1)〉 |] ==> ∃vs''. P,E \<turnstile> 〈blocks(Vs,Ts,vs,e), (h0,l0)〉 ->* 〈blocks(Vs,Ts,vs'',e'), (h1,override_on l1 l0 (set Vs))〉 ∧ (∃ws. P \<turnstile> Ts Casts vs'' to ws) ∧ length vs = length vs''" proof(induct Vs Ts vs e rule:blocks.induct) case (5 V Vs T Ts v vs e) have length1:"length (V#Vs) = length (T#Ts)" and length2:"length (v#vs) = length (T#Ts)" and dist:"distinct (V#Vs)" and casts:"P \<turnstile> (T#Ts) Casts (v#vs) to vs'" and reds:"P,E(V#Vs [\<mapsto>] T#Ts) \<turnstile> 〈e,(h0,l0(V#Vs [\<mapsto>] vs'))〉 ->* 〈e',(h1,l1)〉" and IH:"!!l0 E vs''. [|length Vs = length Ts; length vs = length Ts; distinct Vs; P \<turnstile> Ts Casts vs to vs''; P,E(Vs [\<mapsto>] Ts) \<turnstile> 〈e,(h0,l0(Vs [\<mapsto>] vs''))〉 ->* 〈e',(h1,l1)〉|] ==> ∃vs''. P,E \<turnstile> 〈blocks (Vs,Ts,vs,e),(h0,l0)〉 ->* 〈blocks (Vs,Ts,vs'',e'),(h1, override_on l1 l0 (set Vs))〉 ∧ (∃ws. P \<turnstile> Ts Casts vs'' to ws) ∧ length vs = length vs''" by fact+ from length1 have length1':"length Vs = length Ts" by simp from length2 have length2':"length vs = length Ts" by simp from dist have dist':"distinct Vs" by simp from casts obtain x xs where vs':"vs' = x#xs" by(cases vs',auto dest:length_Casts_vs') with reds have reds':"P,E(V \<mapsto> T)(Vs [\<mapsto>] Ts) \<turnstile> 〈e,(h0,l0(V \<mapsto> x)(Vs [\<mapsto>] xs))〉 ->* 〈e',(h1,l1)〉" by simp from casts vs' have casts':"P \<turnstile> Ts Casts vs to xs" and cast':"P \<turnstile> T casts v to x" by(auto elim:Casts_to.cases) from IH[OF length1' length2' dist' casts' reds'] obtain vs'' ws where blocks:"P,E(V \<mapsto> T) \<turnstile> 〈blocks (Vs, Ts, vs, e),(h0, l0(V \<mapsto> x))〉 ->* 〈blocks (Vs, Ts, vs'', e'),(h1, override_on l1 (l0(V \<mapsto> x)) (set Vs))〉" and castsws:"P \<turnstile> Ts Casts vs'' to ws" and lengthvs'':"length vs = length vs''" by auto from InitBlockReds[OF blocks cast' wf] obtain v'' w where blocks':"P,E \<turnstile> 〈{V:T; V:=Val v;; blocks (Vs, Ts, vs, e)},(h0, l0)〉 ->* 〈{V:T; V:=Val v'';; blocks (Vs, Ts, vs'', e')}, (h1, (override_on l1 (l0(V \<mapsto> x)) (set Vs))(V := l0 V))〉" and "P \<turnstile> T casts v'' to w" by auto with castsws have "P \<turnstile> T#Ts Casts v''#vs'' to w#ws" by -(rule Casts_Cons) with blocks' lengthvs'' show ?case by(rule_tac x="v''#vs''" in exI,auto simp:override_on_upd_lemma) next case (6 e) have casts:"P \<turnstile> [] Casts [] to vs'" and step:"P,E([] [\<mapsto>] []) \<turnstile> 〈e,(h0, l0([] [\<mapsto>] vs'))〉 ->* 〈e',(h1, l1)〉" by fact+ from casts have "vs' = []" by(fastsimp dest:length_Casts_vs') with step have "P,E \<turnstile> 〈e,(h0, l0)〉 ->* 〈e',(h1, l1)〉" by simp with casts show ?case by auto qed simp_all lemma assumes wf:"wf_prog wf_md P" shows blocksFinal: "!!E l vs'. [| length Vs = length Ts; length vs = length Ts; (*∀T∈set Ts. is_type P T;*) final e; P \<turnstile> Ts Casts vs to vs' |] ==> P,E \<turnstile> 〈blocks(Vs,Ts,vs,e), (h,l)〉 ->* 〈e, (h,l)〉" proof(induct Vs Ts vs e rule:blocks.induct) case (5 V Vs T Ts v vs e) have length1:"length (V # Vs) = length (T # Ts)" and length2:"length (v # vs) = length (T # Ts)" and final:"final e" and casts:"P \<turnstile> T # Ts Casts v # vs to vs'" and IH:"!!E l vs'. [|length Vs = length Ts; length vs = length Ts; final e; P \<turnstile> Ts Casts vs to vs' |] ==> P,E \<turnstile> 〈blocks (Vs, Ts, vs, e),(h, l)〉 ->* 〈e,(h, l)〉" by fact+ from length1 length2 have length1':"length Vs = length Ts" and length2':"length vs = length Ts" by simp_all from casts obtain x xs where vs':"vs' = x#xs" by(cases vs',auto dest:length_Casts_vs') with casts have casts':"P \<turnstile> Ts Casts vs to xs" and cast':"P \<turnstile> T casts v to x" by(auto elim:Casts_to.cases) from InitBlockReds[OF IH[OF length1' length2' final casts'] cast' wf, of V l] obtain v'' w where blocks:"P,E \<turnstile> 〈{V:T; V:=Val v;; blocks (Vs, Ts, vs, e)},(h, l)〉 ->* 〈{V:T; V:=Val v'';; e},(h,l)〉" and "P \<turnstile> T casts v'' to w" by auto blast with final have "P,E \<turnstile> 〈{V:T; V:=Val v'';; e},(h,l)〉 -> 〈e,(h,l)〉" by(auto elim!:finalE intro:RedInitBlock InitBlockThrow) with blocks show ?case by -(rule_tac b="({V:T; V:=Val v'';; e},(h, l))" in rtrancl_into_rtrancl,simp_all) qed auto lemma assumes wfmd:"wf_prog wf_md P" and wf: "length Vs = length Ts" "length vs = length Ts" "distinct Vs" and casts:"P \<turnstile> Ts Casts vs to vs'" and reds: "P,E(Vs [\<mapsto>] Ts) \<turnstile> 〈e, (h0, l0(Vs [\<mapsto>] vs'))〉 ->* 〈e', (h1, l1)〉" and fin: "final e'" and l2: "l2 = override_on l1 l0 (set Vs)" shows blocksRedsFinal: "P,E \<turnstile> 〈blocks(Vs,Ts,vs,e), (h0, l0)〉 ->* 〈e', (h1,l2)〉" proof - obtain vs'' ws where blocks:"P,E \<turnstile> 〈blocks(Vs,Ts,vs,e), (h0, l0)〉 ->* 〈blocks(Vs,Ts,vs'',e'), (h1,l2)〉" and length:"length vs = length vs''" and casts':"P \<turnstile> Ts Casts vs'' to ws" using l2 blocksReds[OF wfmd wf casts reds] by auto have "P,E \<turnstile> 〈blocks(Vs,Ts,vs'',e'), (h1,l2)〉 ->* 〈e', (h1,l2)〉" using blocksFinal[OF wfmd _ _ fin casts'] wf length by simp with blocks show ?thesis by simp qed text{* An now the actual method call reduction lemmas. *} lemma CallRedsObj: "P,E \<turnstile> 〈e,s〉 ->* 〈e',s'〉 ==> P,E \<turnstile> 〈Call e Copt M es,s〉 ->* 〈Call e' Copt M es,s'〉" apply(erule rtrancl_induct2) apply blast apply(erule rtrancl_into_rtrancl) apply(simp add:CallObj) done lemma CallRedsParams: "P,E \<turnstile> 〈es,s〉 [->]* 〈es',s'〉 ==> P,E \<turnstile> 〈Call (Val v) Copt M es,s〉 ->* 〈Call (Val v) Copt M es',s'〉" apply(erule rtrancl_induct2) apply blast apply(erule rtrancl_into_rtrancl) apply(simp add:CallParams) done lemma cast_lcl: "P,E \<turnstile> 〈(|C|)),(Val v),(h,l)〉 -> 〈Val v',(h,l)〉 ==> P,E \<turnstile> 〈(|C|)),(Val v),(h,l')〉 -> 〈Val v',(h,l')〉" apply(erule red.cases) apply(auto intro:red_reds.intros) apply(subgoal_tac "P,E \<turnstile> 〈(|C|)),ref (a,Cs@[C]@Cs'),(h,l')〉 -> 〈ref (a,Cs@[C]),(h,l')〉") apply simp apply(rule RedStaticDownCast) done lemma cast_env: "P,E \<turnstile> 〈(|C|)),(Val v),(h,l)〉 -> 〈Val v',(h,l)〉 ==> P,E' \<turnstile> 〈(|C|)),(Val v),(h,l)〉 -> 〈Val v',(h,l)〉" apply(erule red.cases) apply(auto intro:red_reds.intros) apply(subgoal_tac "P,E' \<turnstile> 〈(|C|)),ref (a,Cs@[C]@Cs'),(h,l)〉 -> 〈ref (a,Cs@[C]),(h,l)〉") apply simp apply(rule RedStaticDownCast) done lemma Cast_step_Cast_or_fin: "P,E \<turnstile> 〈(|C|)),e,s〉 ->* 〈e',s'〉 ==> final e' ∨ (∃e''. e' = (|C|)),e'')" by(induct rule:rtrancl_induct2,auto elim:red.cases simp:final_def) lemma Cast_red:"P,E \<turnstile> 〈e,s〉 ->* 〈e',s'〉 ==> (!!e1. [|e = (|C|)),e0; e' = (|C|)),e1|] ==> P,E \<turnstile> 〈e0,s〉 ->* 〈e1,s'〉)" proof(induct rule:rtrancl_induct2) case refl thus ?case by simp next case (step e'' s'' e' s') have step:"P,E \<turnstile> 〈e,s〉 ->* 〈e'',s''〉" and Red:"((e'', s''), e', s') ∈ Red P E" and cast:"e = (|C|)),e0" and cast':"e' = (|C|)),e1" and IH:"!!e1. [|e = (|C|)),e0; e'' = (|C|)),e1|] ==> P,E \<turnstile> 〈e0,s〉 ->* 〈e1,s''〉" by fact+ from Red have red:"P,E \<turnstile> 〈e'',s''〉 -> 〈e',s'〉" by simp from step cast have "final e'' ∨ (∃ex. e'' = (|C|)),ex)" by simp(rule Cast_step_Cast_or_fin) thus ?case proof(rule disjE) assume "final e''" with red show ?thesis by(auto simp:final_def) next assume "∃ex. e'' = (|C|)),ex" then obtain ex where e'':"e'' = (|C|)),ex" by blast with cast' red have "P,E \<turnstile> 〈ex,s''〉 -> 〈e1,s'〉" by(auto elim:red.cases) with IH[OF cast e''] show ?thesis by(rule_tac b="(ex,s'')" in rtrancl_into_rtrancl,simp_all) qed qed lemma Cast_final:"[|P,E \<turnstile> 〈(|C|)),e,s〉 ->* 〈e',s'〉; final e'|] ==> ∃e'' s''. P,E \<turnstile> 〈e,s〉 ->* 〈e'',s''〉 ∧ P,E \<turnstile> 〈(|C|)),e'',s''〉 -> 〈e',s'〉 ∧ final e''" proof(induct rule:rtrancl_induct2) case refl thus ?case by (simp add:final_def) next case (step e'' s'' e' s') have step:"P,E \<turnstile> 〈(|C|)),e,s〉 ->* 〈e'',s''〉" and Red:"((e'', s''), e', s') ∈ Red P E" and final:"final e'" and IH:"final e'' ==> ∃ex sx. P,E \<turnstile> 〈e,s〉 ->* 〈ex,sx〉 ∧ P,E \<turnstile> 〈(|C|)),ex,sx〉 -> 〈e'',s''〉 ∧ final ex" by fact+ from Red have red:"P,E \<turnstile> 〈e'',s''〉 -> 〈e',s'〉" by simp from step have "final e'' ∨ (∃ex. e'' = (|C|)),ex)" by(rule Cast_step_Cast_or_fin) thus ?case proof(rule disjE) assume "final e''" with red show ?thesis by(auto simp:final_def) next assume "∃ex. e'' = (|C|)),ex" then obtain ex where e'':"e'' = (|C|)),ex" by blast with red final have final':"final ex" by(auto elim:red.cases simp:final_def) from step e'' have "P,E \<turnstile> 〈e,s〉 ->* 〈ex,s''〉" by(fastsimp intro:Cast_red) with e'' red final' show ?thesis by blast qed qed lemma Cast_final_eq: assumes red:"P,E \<turnstile> 〈(|C|)),e,(h,l)〉 -> 〈e',(h,l)〉" and final:"final e" and final':"final e'" shows "P,E' \<turnstile> 〈(|C|)),e,(h,l')〉 -> 〈e',(h,l')〉" proof - from red final show ?thesis proof(auto simp:final_def) fix v assume "P,E \<turnstile> 〈(|C|)),(Val v),(h,l)〉 -> 〈e',(h,l)〉" with final' show "P,E' \<turnstile> 〈(|C|)),(Val v),(h,l')〉 -> 〈e',(h,l')〉" proof(auto simp:final_def) fix v' assume "P,E \<turnstile> 〈(|C|)),(Val v),(h,l)〉 -> 〈Val v',(h,l)〉" thus "P,E' \<turnstile> 〈(|C|)),(Val v),(h,l')〉 -> 〈Val v',(h,l')〉" by(auto intro:cast_lcl cast_env) next fix a Cs assume "P,E \<turnstile> 〈(|C|)),(Val v),(h,l)〉 -> 〈Throw (a,Cs),(h,l)〉" thus "P,E' \<turnstile> 〈(|C|)),(Val v),(h,l')〉 -> 〈Throw (a,Cs),(h,l')〉" by(auto elim:red.cases intro!:RedStaticCastFail) qed next fix a Cs assume "P,E \<turnstile> 〈(|C|)),(Throw (a,Cs)),(h,l)〉 -> 〈e',(h,l)〉" with final' show "P,E' \<turnstile> 〈(|C|)),(Throw (a,Cs)),(h,l')〉 -> 〈e',(h,l')〉" proof(auto simp:final_def) fix v assume "P,E \<turnstile> 〈(|C|)),(Throw (a,Cs)),(h,l)〉 -> 〈Val v,(h,l)〉" thus "P,E' \<turnstile> 〈(|C|)),(Throw (a,Cs)),(h,l')〉 -> 〈Val v,(h,l')〉" by(auto elim:red.cases) next fix a' Cs' assume "P,E \<turnstile> 〈(|C|)),(Throw (a,Cs)),(h,l)〉 -> 〈Throw (a',Cs'),(h,l)〉" thus "P,E' \<turnstile> 〈(|C|)),(Throw (a,Cs)),(h,l')〉 -> 〈Throw (a',Cs'),(h,l')〉" by(auto elim:red.cases intro:red_reds.StaticCastThrow) qed qed qed lemma CallRedsFinal: assumes wwf: "wwf_prog P" and "P,E \<turnstile> 〈e,s0〉 ->* 〈ref(a,Cs),s1〉" "P,E \<turnstile> 〈es,s1〉 [->]* 〈map Val vs,(h2,l2)〉" and hp: "h2 a = Some(C,S)" and method: "P \<turnstile> last Cs has least M = (Ts',T',pns',body') via Ds" and select: "P \<turnstile> (C,Cs@pDs) selects M = (Ts,T,pns,body) via Cs'" and size: "size vs = size pns" and casts: "P \<turnstile> Ts Casts vs to vs'" and l2': "l2' = [this \<mapsto> Ref(a,Cs'), pns[\<mapsto>]vs']" and body_case:"new_body = (case T' of Class D => (|D|)),body | _ => body)" and body: "P,E(this \<mapsto> Class (last Cs'), pns [\<mapsto>] Ts) \<turnstile> 〈new_body,(h2,l2')〉 ->* 〈ef,(h3,l3)〉" and final:"final ef" shows "P,E \<turnstile> 〈e•M(es), s0〉 ->* 〈ef,(h3,l2)〉" proof - have wf: "size Ts = size pns ∧ distinct pns ∧ this ∉ set pns" and wt: "fv body ⊆ {this} ∪ set pns" using prems by(fastsimp dest!:select_method_wf_mdecl simp:wf_mdecl_def)+ have "dom l3 ⊆ {this} ∪ set pns" using Reds_dom_lcl[OF wwf body] wt l2' set_take_subset body_case by (cases T') force+ hence eql2: "override_on (l2++l3) l2 ({this} ∪ set pns) = l2" by(fastsimp simp add:map_add_def override_on_def expand_fun_eq) from wwf select have "is_class P (last Cs')" by (auto elim!:SelectMethodDef.cases intro:Subobj_last_isClass simp:LeastMethodDef_def FinalOverriderMethodDef_def OverriderMethodDefs_def MinimalMethodDefs_def MethodDefs_def) hence "P \<turnstile> Class (last Cs') casts Ref(a,Cs') to Ref(a,Cs')" by(auto intro!:casts_ref Subobjs_Base simp:path_via_def appendPath_def) with casts have casts':"P \<turnstile> Class (last Cs')#Ts Casts Ref(a,Cs')#vs to Ref(a,Cs')#vs'" by -(rule Casts_Cons) have 1:"P,E \<turnstile> 〈e•M(es),s0〉 ->* 〈(ref(a,Cs))•M(es),s1〉" by(rule CallRedsObj)(rule assms(2)) have 2:"P,E \<turnstile> 〈(ref(a,Cs))•M(es),s1〉 ->* 〈(ref(a,Cs))•M(map Val vs),(h2,l2)〉" by(rule CallRedsParams)(rule assms(3)) from body[THEN Red_lcl_add, of l2] have body': "P,E(this \<mapsto> Class (last Cs'), pns [\<mapsto>] Ts) \<turnstile> 〈new_body,(h2,l2(this\<mapsto> Ref(a,Cs'), pns[\<mapsto>]vs'))〉 ->* 〈ef,(h3,l2++l3)〉" by (simp add:l2') show ?thesis proof(cases "∀C. T'≠ Class C") case True hence "P,E \<turnstile> 〈(ref(a,Cs))•M(map Val vs), (h2,l2)〉 -> 〈blocks(this#pns,Class(last Cs')#Ts,Ref(a,Cs')#vs,body), (h2,l2)〉" using hp method select size wf by -(rule RedCall,auto,cases T',auto) hence 3:"P,E \<turnstile> 〈(ref(a,Cs))•M(map Val vs), (h2,l2)〉 ->* 〈blocks(this#pns,Class(last Cs')#Ts,Ref(a,Cs')#vs,body), (h2,l2)〉" by(simp add:r_into_rtrancl) have "P,E \<turnstile> 〈blocks(this#pns,Class(last Cs')#Ts,Ref(a,Cs')#vs,body),(h2,l2)〉 ->* 〈ef,(h3,override_on (l2++l3) l2 ({this} ∪ set pns))〉" using True wf body' wwf size final casts' body_case by -(rule_tac vs'="Ref(a,Cs')#vs'" in blocksRedsFinal,simp_all,cases T',auto) with 1 2 3 show ?thesis using eql2 by simp next case False then obtain D where T':"T' = Class D" by auto with final body' body_case obtain s' e' where body'':"P,E(this \<mapsto> Class (last Cs'),pns [\<mapsto>] Ts) \<turnstile> 〈body,(h2,l2(this\<mapsto> Ref(a,Cs'), pns[\<mapsto>]vs'))〉 ->* 〈e',s'〉" and final':"final e'" and cast:"P,E(this \<mapsto> Class (last Cs'), pns [\<mapsto>] Ts) \<turnstile> 〈(|D|)),e',s'〉 -> 〈ef,(h3,l2++l3)〉" by(cases T')(auto dest:Cast_final) from T' have "P,E \<turnstile> 〈(ref(a,Cs))•M(map Val vs), (h2,l2)〉 -> 〈(|D|)),blocks(this#pns,Class(last Cs')#Ts,Ref(a,Cs')#vs,body), (h2,l2)〉" using hp method select size wf by -(rule RedCall,auto) hence 3:"P,E \<turnstile> 〈(ref(a,Cs))•M(map Val vs), (h2,l2)〉 ->* 〈(|D|)),blocks(this#pns,Class(last Cs')#Ts,Ref(a,Cs')#vs,body),(h2,l2)〉" by(simp add:r_into_rtrancl) from cast final have eq:"s' = (h3,l2++l3)" by(auto elim:red.cases simp:final_def) hence "P,E \<turnstile> 〈blocks(this#pns, Class (last Cs')#Ts, Ref(a,Cs')#vs,body), (h2,l2)〉 ->* 〈e',(h3,override_on (l2++l3) l2 ({this} ∪ set pns))〉" using wf body'' wwf size final' casts' by -(rule_tac vs'="Ref(a,Cs')#vs'" in blocksRedsFinal,simp_all) hence "P,E \<turnstile> 〈(|D|)),(blocks(this#pns,Class(last Cs')#Ts,Ref(a,Cs')#vs,body)),(h2,l2)〉 ->* 〈(|D|)),e',(h3,override_on (l2++l3) l2 ({this} ∪ set pns))〉" by(rule StaticCastReds) moreover have "P,E \<turnstile> 〈(|D|)),e',(h3,override_on (l2++l3) l2 ({this} ∪ set pns))〉 -> 〈ef,(h3,override_on (l2++l3) l2 ({this} ∪ set pns))〉" using eq cast final final' by(fastsimp intro:Cast_final_eq) ultimately have "P,E \<turnstile> 〈(|D|)),(blocks(this#pns, Class (last Cs')#Ts, Ref(a,Cs')#vs,body)), (h2,l2)〉 ->* 〈ef,(h3,override_on (l2++l3) l2 ({this} ∪ set pns))〉" by(rule_tac b="((|D|)),e',(h3,override_on (l2++l3) l2 ({this} ∪ set pns)))" in rtrancl_into_rtrancl,simp_all) with 1 2 3 show ?thesis using eql2 by simp qed qed lemma StaticCallRedsFinal: assumes wwf: "wwf_prog P" and "P,E \<turnstile> 〈e,s0〉 ->* 〈ref(a,Cs),s1〉" "P,E \<turnstile> 〈es,s1〉 [->]* 〈map Val vs,(h2,l2)〉" and path_unique: "P \<turnstile> Path (last Cs) to C unique" and path_via: "P \<turnstile> Path (last Cs) to C via Cs''" and Ds: "Ds = (Cs@pCs'')@pCs'" and least: "P \<turnstile> C has least M = (Ts,T,pns,body) via Cs'" and size: "size vs = size pns" and casts: "P \<turnstile> Ts Casts vs to vs'" and l2': "l2' = [this \<mapsto> Ref(a,Ds), pns[\<mapsto>]vs']" and body: "P,E(this\<mapsto>Class(last Ds), pns[\<mapsto>]Ts) \<turnstile> 〈body,(h2,l2')〉 ->* 〈ef,(h3,l3)〉" and final:"final ef" shows "P,E \<turnstile> 〈e•(C::)M(es), s0〉 ->* 〈ef,(h3,l2)〉" proof - have wf: "size Ts = size pns ∧ distinct pns ∧ this ∉ set pns ∧ (∀T∈set Ts. is_type P T)" and wt: "fv body ⊆ {this} ∪ set pns" using prems by(fastsimp dest!:has_least_wf_mdecl simp:wf_mdecl_def)+ have "dom l3 ⊆ {this} ∪ set pns" using Reds_dom_lcl[OF wwf body] wt l2' set_take_subset by force hence eql2: "override_on (l2++l3) l2 ({this} ∪ set pns) = l2" by(fastsimp simp add:map_add_def override_on_def expand_fun_eq) from wwf least have "Cs' ≠ []" by (auto elim!:Subobjs_nonempty simp:LeastMethodDef_def MethodDefs_def) with Ds have "last Cs' = last Ds" by(fastsimp intro:appendPath_last) with wwf least have "is_class P (last Ds)" by(auto dest:Subobj_last_isClass simp:LeastMethodDef_def MethodDefs_def) hence "P \<turnstile> Class (last Ds) casts Ref(a,Ds) to Ref(a,Ds)" by(auto intro!:casts_ref Subobjs_Base simp:path_via_def appendPath_def) with casts have casts':"P \<turnstile> Class (last Ds)#Ts Casts Ref(a,Ds)#vs to Ref(a,Ds)#vs'" by -(rule Casts_Cons) have 1:"P,E \<turnstile> 〈e•(C::)M(es),s0〉 ->* 〈(ref(a,Cs))•(C::)M(es),s1〉" by(rule CallRedsObj)(rule assms(2)) have 2:"P,E \<turnstile> 〈(ref(a,Cs))•(C::)M(es),s1〉 ->* 〈(ref(a,Cs))•(C::)M(map Val vs),(h2,l2)〉" by(rule CallRedsParams)(rule assms(3)) from body[THEN Red_lcl_add, of l2] have body': "P,E(this\<mapsto>Class(last Ds), pns[\<mapsto>]Ts) \<turnstile> 〈body,(h2,l2(this\<mapsto> Ref(a,Ds), pns[\<mapsto>]vs'))〉 ->* 〈ef,(h3,l2++l3)〉" by (simp add:l2') have "P,E \<turnstile> 〈(ref(a,Cs))•(C::)M(map Val vs), (h2,l2)〉 -> 〈blocks(this#pns, Class (last Ds)#Ts, Ref(a,Ds)#vs, body), (h2,l2)〉" using path_unique path_via least size wf Ds by -(rule RedStaticCall,auto) hence 3:"P,E \<turnstile> 〈(ref(a,Cs))•(C::)M(map Val vs), (h2,l2)〉 ->* 〈blocks(this#pns,Class(last Ds)#Ts,Ref(a,Ds)#vs,body), (h2,l2)〉" by(simp add:r_into_rtrancl) have "P,E \<turnstile> 〈blocks(this#pns,Class(last Ds)#Ts,Ref(a,Ds)#vs,body),(h2,l2)〉 ->* 〈ef,(h3,override_on (l2++l3) l2 ({this} ∪ set pns))〉" using wf body' wwf size final casts' by -(rule_tac vs'="Ref(a,Ds)#vs'" in blocksRedsFinal,simp_all) with 1 2 3 show ?thesis using eql2 by simp qed lemma CallRedsThrowParams: "[| P,E \<turnstile> 〈e,s0〉 ->* 〈Val v,s1〉; P,E \<turnstile> 〈es,s1〉 [->]* 〈map Val vs1 @ Throw ex # es2,s2〉 |] ==> P,E \<turnstile> 〈Call e Copt M es,s0〉 ->* 〈Throw ex,s2〉" apply(rule rtrancl_trans) apply(erule CallRedsObj) apply(rule rtrancl_into_rtrancl) apply(erule CallRedsParams) apply(simp add:CallThrowParams) done lemma CallRedsThrowObj: "P,E \<turnstile> 〈e,s0〉 ->* 〈Throw ex,s1〉 ==> P,E \<turnstile> 〈Call e Copt M es,s0〉 ->* 〈Throw ex,s1〉" apply(rule rtrancl_into_rtrancl) apply(erule CallRedsObj) apply(simp add:CallThrowObj) done lemma CallRedsNull: "[| P,E \<turnstile> 〈e,s0〉 ->* 〈null,s1〉; P,E \<turnstile> 〈es,s1〉 [->]* 〈map Val vs,s2〉 |] ==> P,E \<turnstile> 〈Call e Copt M es,s0〉 ->* 〈THROW NullPointer,s2〉" apply(rule rtrancl_trans) apply(erule CallRedsObj) apply(rule rtrancl_into_rtrancl) apply(erule CallRedsParams) apply(simp add:RedCallNull) done subsection {*The main Theorem*} lemma assumes wwf: "wwf_prog P" shows big_by_small: "P,E \<turnstile> 〈e,s〉 => 〈e',s'〉 ==> P,E \<turnstile> 〈e,s〉 ->* 〈e',s'〉" and bigs_by_smalls: "P,E \<turnstile> 〈es,s〉 [=>] 〈es',s'〉 ==> P,E \<turnstile> 〈es,s〉 [->]* 〈es',s'〉" proof (induct rule: eval_evals.inducts) case New thus ?case by (auto simp:RedNew) next case NewFail thus ?case by (auto simp:RedNewFail) next case StaticUpCast thus ?case by(simp add:StaticUpCastReds) next case StaticDownCast thus ?case by(simp add:StaticDownCastReds) next case StaticCastNull thus ?case by(simp add:StaticCastRedsNull) next case StaticCastFail thus ?case by(simp add:StaticCastRedsFail) next case StaticCastThrow thus ?case by(auto dest!:eval_final simp:StaticCastRedsThrow) next case StaticUpDynCast thus ?case by(simp add:StaticUpDynCastReds) next case StaticDownDynCast thus ?case by(simp add:StaticDownDynCastReds) next case DynCast thus ?case by(fastsimp intro:DynCastRedsRef) next case DynCastNull thus ?case by(simp add:DynCastRedsNull) next case DynCastFail thus ?case by(fastsimp intro!:DynCastRedsFail) next case DynCastThrow thus ?case by(auto dest!:eval_final simp:DynCastRedsThrow) next case Val thus ?case by simp next case BinOp thus ?case by(fastsimp simp:BinOpRedsVal) next case BinOpThrow1 thus ?case by(fastsimp dest!:eval_final simp: BinOpRedsThrow1) next case BinOpThrow2 thus ?case by(fastsimp dest!:eval_final simp: BinOpRedsThrow2) next case Var thus ?case by (fastsimp simp:RedVar) next case LAss thus ?case by(fastsimp simp: LAssRedsVal) next case LAssThrow thus ?case by(fastsimp dest!:eval_final simp: LAssRedsThrow) next case FAcc thus ?case by(fastsimp intro:FAccRedsVal) next case FAccNull thus ?case by(simp add:FAccRedsNull) next case FAccThrow thus ?case by(fastsimp dest!:eval_final simp:FAccRedsThrow) next case FAss thus ?case by(fastsimp simp:FAssRedsVal) next case FAssNull thus ?case by(fastsimp simp:FAssRedsNull) next case FAssThrow1 thus ?case by(fastsimp dest!:eval_final simp:FAssRedsThrow1) next case FAssThrow2 thus ?case by(fastsimp dest!:eval_final simp:FAssRedsThrow2) next case CallObjThrow thus ?case by(fastsimp dest!:eval_final simp:CallRedsThrowObj) next case CallNull thus ?case thm CallRedsNull by(simp add:CallRedsNull) next case CallParamsThrow thus ?case by(fastsimp dest!:evals_final simp:CallRedsThrowParams) next case (Call E e s0 a Cs s1 ps vs h2 l2 C S M Ts' T' pns' body' Ds Ts T pns body Cs' vs' l2' new_body e' h3 l3) have IHe: "P,E \<turnstile> 〈e,s0〉 ->* 〈ref(a,Cs),s1〉" and IHes: "P,E \<turnstile> 〈ps,s1〉 [->]* 〈map Val vs,(h2,l2)〉" and h2a: "h2 a = Some(C,S)" and method: "P \<turnstile> last Cs has least M = (Ts',T',pns',body') via Ds" and select: "P \<turnstile> (C,Cs@pDs) selects M = (Ts,T,pns,body) via Cs'" and same_length: "length vs = length pns" and casts: "P \<turnstile> Ts Casts vs to vs'" and l2': "l2' = [this \<mapsto> Ref (a,Cs'), pns[\<mapsto>]vs']" and body_case: "new_body = (case T' of Class D => (|D|)),body | _ => body)" and eval_body: "P,E(this \<mapsto> Class (last Cs'), pns [\<mapsto>] Ts) \<turnstile> 〈new_body,(h2, l2')〉 => 〈e',(h3, l3)〉" and IHbody: "P,E(this \<mapsto> Class (last Cs'), pns [\<mapsto>] Ts) \<turnstile> 〈new_body,(h2, l2')〉 ->* 〈e',(h3, l3)〉" by fact+ from wwf select same_length have lengthTs:"length Ts = length vs" by (fastsimp dest!:select_method_wf_mdecl simp:wf_mdecl_def) show "P,E \<turnstile> 〈e•M(ps),s0〉 ->* 〈e',(h3, l2)〉" using method select same_length l2' h2a casts body_case IHbody eval_final[OF eval_body] by(fastsimp intro!:CallRedsFinal[OF wwf IHe IHes]) next case (StaticCall E e s0 a Cs s1 ps vs h2 l2 C Cs'' M Ts T pns body Cs' Ds vs' l2' e' h3 l3) have IHe: "P,E \<turnstile> 〈e,s0〉 ->* 〈ref(a,Cs),s1〉" and IHes: "P,E \<turnstile> 〈ps,s1〉 [->]* 〈map Val vs,(h2,l2)〉" and path_unique: "P \<turnstile> Path last Cs to C unique" and path_via: "P \<turnstile> Path last Cs to C via Cs''" and least: "P \<turnstile> C has least M = (Ts, T, pns, body) via Cs'" and Ds: "Ds = (Cs @p Cs'') @p Cs'" and same_length: "length vs = length pns" and casts: "P \<turnstile> Ts Casts vs to vs'" and l2': "l2' = [this \<mapsto> Ref (a,Ds), pns[\<mapsto>]vs']" and eval_body: "P,E(this \<mapsto> Class (last Ds), pns [\<mapsto>] Ts) \<turnstile> 〈body,(h2, l2')〉 => 〈e',(h3, l3)〉" and IHbody: "P,E(this \<mapsto> Class (last Ds), pns [\<mapsto>] Ts) \<turnstile> 〈body,(h2, l2')〉 ->* 〈e',(h3, l3)〉" by fact+ from wwf least same_length have lengthTs:"length Ts = length vs" by (fastsimp dest!:has_least_wf_mdecl simp:wf_mdecl_def) show "P,E \<turnstile> 〈e•(C::)M(ps),s0〉 ->* 〈e',(h3, l2)〉" using path_unique path_via least Ds same_length l2' casts IHbody eval_final[OF eval_body] by(fastsimp intro!:StaticCallRedsFinal[OF wwf IHe IHes]) next case Block with wwf show ?case by(fastsimp simp: BlockRedsFinal dest:eval_final) next case Seq thus ?case by(fastsimp simp:SeqReds2) next case SeqThrow thus ?case by(fastsimp dest!:eval_final simp: SeqRedsThrow) next case CondT thus ?case by(fastsimp simp:CondReds2T) next case CondF thus ?case by(fastsimp simp:CondReds2F) next case CondThrow thus ?case by(fastsimp dest!:eval_final simp:CondRedsThrow) next case WhileF thus ?case by(fastsimp simp:WhileFReds) next case WhileT thus ?case by(fastsimp simp: WhileTReds) next case WhileCondThrow thus ?case by(fastsimp dest!:eval_final simp: WhileRedsThrow) next case WhileBodyThrow thus ?case by(fastsimp dest!:eval_final simp: WhileTRedsThrow) next case Throw thus ?case by(fastsimp simp:ThrowReds) next case ThrowNull thus ?case by(fastsimp simp:ThrowRedsNull) next case ThrowThrow thus ?case by(fastsimp dest!:eval_final simp:ThrowRedsThrow) next case Nil thus ?case by simp next case Cons thus ?case by(fastsimp intro!:Cons_eq_appendI[OF refl refl] ListRedsVal) next case ConsThrow thus ?case by(fastsimp elim: ListReds1) qed section{*Big steps simulates small step*} text {* The big step equivalent of @{text RedWhile}: *} lemma unfold_while: "P,E \<turnstile> 〈while(b) c,s〉 => 〈e',s'〉 = P,E \<turnstile> 〈if(b) (c;;while(b) c) else (unit),s〉 => 〈e',s'〉" proof assume "P,E \<turnstile> 〈while (b) c,s〉 => 〈e',s'〉" thus "P,E \<turnstile> 〈if (b) (c;; while (b) c) else unit,s〉 => 〈e',s'〉" by cases (fastsimp intro: eval_evals.intros)+ next assume "P,E \<turnstile> 〈if (b) (c;; while (b) c) else unit,s〉 => 〈e',s'〉" thus "P,E \<turnstile> 〈while (b) c,s〉 => 〈e',s'〉" proof (cases) fix ex assume e': "e' = throw ex" assume "P,E \<turnstile> 〈b,s〉 => 〈throw ex,s'〉" hence "P,E \<turnstile> 〈while(b) c,s〉 => 〈throw ex,s'〉" by (rule WhileCondThrow) with e' show ?thesis by simp next fix s1 assume eval_false: "P,E \<turnstile> 〈b,s〉 => 〈false,s1〉" and eval_unit: "P,E \<turnstile> 〈unit,s1〉 => 〈e',s'〉" with eval_unit have "s' = s1" "e' = unit" by (auto elim: eval_cases) moreover from eval_false have "P,E \<turnstile> 〈while (b) c,s〉 => 〈unit,s1〉" by - (rule WhileF, simp) ultimately show ?thesis by simp next fix s1 assume eval_true: "P,E \<turnstile> 〈b,s〉 => 〈true,s1〉" and eval_rest: "P,E \<turnstile> 〈c;; while (b) c,s1〉=>〈e',s'〉" from eval_rest show ?thesis proof (cases) fix s2 v1 assume "P,E \<turnstile> 〈c,s1〉 => 〈Val v1,s2〉" "P,E \<turnstile> 〈while (b) c,s2〉 => 〈e',s'〉" with eval_true show "P,E \<turnstile> 〈while(b) c,s〉 => 〈e',s'〉" by (rule WhileT) next fix ex assume "P,E \<turnstile> 〈c,s1〉 => 〈throw ex,s'〉" "e' = throw ex" with eval_true show "P,E \<turnstile> 〈while(b) c,s〉 => 〈e',s'〉" by (iprover intro: WhileBodyThrow) qed qed qed lemma blocksEval: "!!Ts vs l l' E. [|size ps = size Ts; size ps = size vs; P,E \<turnstile> 〈blocks(ps,Ts,vs,e),(h,l)〉 => 〈e',(h',l')〉 |] ==> ∃ l'' vs'. P,E(ps [\<mapsto>] Ts) \<turnstile> 〈e,(h,l(ps[\<mapsto>]vs'))〉 => 〈e',(h',l'')〉 ∧ P \<turnstile> Ts Casts vs to vs' ∧ length vs' = length vs" proof (induct ps) case Nil then show ?case by(fastsimp intro:Casts_Nil) next case (Cons p ps') have length_eqs: "length (p # ps') = length Ts" "length (p # ps') = length vs" and IH:"!!Ts vs l l' E. [|length ps' = length Ts; length ps' = length vs; P,E \<turnstile> 〈blocks (ps',Ts,vs,e),(h,l)〉 => 〈e',(h',l')〉|] ==> ∃l'' vs'. P,E(ps' [\<mapsto>] Ts) \<turnstile> 〈e,(h,l(ps' [\<mapsto>] vs'))〉 => 〈e',(h', l'')〉 ∧ P \<turnstile> Ts Casts vs to vs' ∧ length vs' = length vs" by fact+ then obtain T Ts' where Ts: "Ts = T#Ts'" by (cases "Ts") simp obtain v vs' where vs: "vs = v#vs'" using length_eqs by (cases "vs") simp with length_eqs Ts have length1:"length ps' = length Ts'" and length2:"length ps' = length vs'" by simp_all have "P,E \<turnstile> 〈blocks (p # ps', Ts, vs, e),(h,l)〉 => 〈e',(h', l')〉" by fact with Ts vs have blocks:"P,E \<turnstile> 〈{p:T := Val v; blocks (ps',Ts',vs',e)},(h,l)〉 => 〈e',(h',l')〉" by simp then obtain l''' v' where eval_ps': "P,E(p \<mapsto> T) \<turnstile> 〈blocks (ps',Ts',vs',e),(h,l(p\<mapsto>v'))〉 => 〈e',(h',l''')〉" and l''': "l'=l'''(p:=l p)" and casts:"P \<turnstile> T casts v to v'" by(auto elim!: eval_cases simp:fun_upd_same) from IH[OF length1 length2 eval_ps'] obtain l'' vs'' where "P,E(p \<mapsto> T)(ps' [\<mapsto>] Ts') \<turnstile> 〈e,(h, l(p\<mapsto>v')(ps'[\<mapsto>]vs''))〉 => 〈e',(h',l'')〉" and "P \<turnstile> Ts' Casts vs' to vs''" and "length vs'' = length vs'" by auto with Ts vs casts show ?case by -(rule_tac x="l''" in exI,rule_tac x="v'#vs''" in exI,simp, rule Casts_Cons) qed lemma CastblocksEval: "!!Ts vs l l' E. [|size ps = size Ts; size ps = size vs; P,E \<turnstile> 〈(|C'|)),(blocks(ps,Ts,vs,e)),(h,l)〉 => 〈e',(h',l')〉 |] ==> ∃ l'' vs'. P,E(ps [\<mapsto>] Ts) \<turnstile> 〈(|C'|)),e,(h,l(ps[\<mapsto>]vs'))〉 => 〈e',(h',l'')〉 ∧ P \<turnstile> Ts Casts vs to vs' ∧ length vs' = length vs" proof (induct ps) case Nil then show ?case by(fastsimp intro:Casts_Nil) next case (Cons p ps') have length_eqs: "length (p # ps') = length Ts" "length (p # ps') = length vs" by fact+ then obtain T Ts' where Ts: "Ts = T#Ts'" by (cases "Ts") simp obtain v vs' where vs: "vs = v#vs'" using length_eqs by (cases "vs") simp with length_eqs Ts have length1:"length ps' = length Ts'" and length2:"length ps' = length vs'" by simp_all have "P,E \<turnstile> 〈(|C'|)),(blocks (p # ps', Ts, vs, e)),(h,l)〉 => 〈e',(h', l')〉" by fact moreover { fix a Cs Cs' assume blocks:"P,E \<turnstile> 〈blocks(p#ps',Ts,vs,e),(h,l)〉 => 〈ref (a,Cs),(h',l')〉" and path_via:"P \<turnstile> Path last Cs to C' via Cs'" and e':"e' = ref(a,Cs@pCs')" from blocks length_eqs obtain l'' vs'' where eval:"P,E(p#ps' [\<mapsto>] Ts) \<turnstile> 〈e,(h,l(p#ps'[\<mapsto>]vs''))〉 => 〈ref (a,Cs),(h',l'')〉" and casts:"P \<turnstile> Ts Casts vs to vs''" and length:"length vs'' = length vs" by -(drule blocksEval,auto) from eval path_via have "P,E(p#ps'[\<mapsto>]Ts) \<turnstile> 〈(|C'|)),e,(h,l(p#ps'[\<mapsto>]vs''))〉 => 〈ref(a,Cs@pCs'),(h',l'')〉" by(auto intro:StaticUpCast) with e' casts length have ?case by simp blast } moreover { fix a Cs Cs' assume blocks:"P,E \<turnstile> 〈blocks(p#ps',Ts,vs,e),(h,l)〉 => 〈ref (a,Cs@C'# Cs'),(h',l')〉" and e':"e' = ref (a,Cs@[C'])" from blocks length_eqs obtain l'' vs'' where eval:"P,E(p#ps' [\<mapsto>] Ts) \<turnstile> 〈e,(h,l(p#ps'[\<mapsto>]vs''))〉 => 〈ref (a,Cs@C'# Cs'),(h',l'')〉" and casts:"P \<turnstile> Ts Casts vs to vs''" and length:"length vs'' = length vs" by -(drule blocksEval,auto) from eval have "P,E(p#ps'[\<mapsto>]Ts) \<turnstile> 〈(|C'|)),e,(h,l(p#ps'[\<mapsto>]vs''))〉 => 〈ref(a,Cs@[C']),(h',l'')〉" by(auto intro:StaticDownCast) with e' casts length have ?case by simp blast } moreover { assume "P,E \<turnstile> 〈blocks(p#ps',Ts,vs,e),(h,l)〉 => 〈null,(h',l')〉" and e':"e' = null" with length_eqs obtain l'' vs'' where eval:"P,E(p#ps' [\<mapsto>] Ts) \<turnstile> 〈e,(h,l(p#ps'[\<mapsto>]vs''))〉 => 〈null,(h',l'')〉" and casts:"P \<turnstile> Ts Casts vs to vs''" and length:"length vs'' = length vs" by -(drule blocksEval,auto) from eval have "P,E(p#ps' [\<mapsto>] Ts) \<turnstile> 〈(|C'|)),e,(h,l(p#ps'[\<mapsto>]vs''))〉 => 〈null,(h',l'')〉" by(auto intro:StaticCastNull) with e' casts length have ?case by simp blast } moreover { fix a Cs assume blocks:"P,E \<turnstile> 〈blocks(p#ps',Ts,vs,e),(h,l)〉 => 〈ref (a,Cs),(h',l')〉" and notin:"C' ∉ set Cs" and leq:"¬ P \<turnstile> (last Cs) \<preceq>* C'" and e':"e' = THROW ClassCast" from blocks length_eqs obtain l'' vs'' where eval:"P,E(p#ps' [\<mapsto>] Ts) \<turnstile> 〈e,(h,l(p#ps'[\<mapsto>]vs''))〉 => 〈ref (a,Cs),(h',l'')〉" and casts:"P \<turnstile> Ts Casts vs to vs''" and length:"length vs'' = length vs" by -(drule blocksEval,auto) from eval notin leq have "P,E(p#ps'[\<mapsto>]Ts) \<turnstile> 〈(|C'|)),e,(h,l(p#ps'[\<mapsto>]vs''))〉 => 〈THROW ClassCast,(h',l'')〉" by(auto intro:StaticCastFail) with e' casts length have ?case by simp blast } moreover { fix r assume "P,E \<turnstile> 〈blocks(p#ps',Ts,vs,e),(h,l)〉 => 〈throw r,(h',l')〉" and e':"e' = throw r" with length_eqs obtain l'' vs'' where eval:"P,E(p#ps' [\<mapsto>] Ts) \<turnstile> 〈e,(h,l(p#ps'[\<mapsto>]vs''))〉 => 〈throw r,(h',l'')〉" and casts:"P \<turnstile> Ts Casts vs to vs''" and length:"length vs'' = length vs" by -(drule blocksEval,auto) from eval have "P,E(p#ps'[\<mapsto>]Ts) \<turnstile> 〈(|C'|)),e,(h,l(p#ps'[\<mapsto>]vs''))〉 => 〈throw r,(h',l'')〉" by(auto intro:eval_evals.StaticCastThrow) with e' casts length have ?case by simp blast } ultimately show ?case by -(erule eval_cases,fastsimp+) qed lemma assumes wf: "wwf_prog P" shows eval_restrict_lcl: "P,E \<turnstile> 〈e,(h,l)〉 => 〈e',(h',l')〉 ==> (!!W. fv e ⊆ W ==> P,E \<turnstile> 〈e,(h,l|`W)〉 => 〈e',(h',l'|`W)〉)" and "P,E \<turnstile> 〈es,(h,l)〉 [=>] 〈es',(h',l')〉 ==> (!!W. fvs es ⊆ W ==> P,E \<turnstile> 〈es,(h,l|`W)〉 [=>] 〈es',(h',l'|`W)〉)" proof(induct rule:eval_evals_inducts) case (Block E V T e0 h0 l0 e1 h1 l1) have IH: "!!W. fv e0 ⊆ W ==> P,E(V \<mapsto> T) \<turnstile> 〈e0,(h0,l0(V:=None)|`W)〉 => 〈e1,(h1,l1|`W)〉" by fact (*have type:"is_type P T" .*) have "fv({V:T; e0}) ⊆ W" by fact hence "fv e0 - {V} ⊆ W" by simp_all hence "fv e0 ⊆ insert V W" by fast with IH[OF this] have "P,E(V \<mapsto> T) \<turnstile> 〈e0,(h0, (l0|`W)(V := None))〉 => 〈e1,(h1, l1|`insert V W)〉" by fastsimp from eval_evals.Block[OF this] show ?case by fastsimp next case Seq thus ?case by simp (blast intro:eval_evals.Seq) next case New thus ?case by(simp add:eval_evals.intros) next case NewFail thus ?case by(simp add:eval_evals.intros) next case StaticUpCast thus ?case by simp (blast intro:eval_evals.StaticUpCast) next case (StaticDownCast E e h l a Cs C Cs' h' l') have IH:"!!W. fv e ⊆ W ==> P,E \<turnstile> 〈e,(h,l |` W)〉 => 〈ref(a,Cs@[C]@Cs'),(h',l' |` W)〉" by fact have "fv ((|C|)),e) ⊆ W" by fact hence "fv e ⊆ W" by simp from IH[OF this] show ?case by(rule eval_evals.StaticDownCast) next case StaticCastNull thus ?case by simp (blast intro:eval_evals.StaticCastNull) next case StaticCastFail thus ?case by simp (blast intro:eval_evals.StaticCastFail) next case StaticCastThrow thus ?case by(simp add:eval_evals.intros) next case DynCast thus ?case by simp (blast intro:eval_evals.DynCast) next case StaticUpDynCast thus ?case by simp (blast intro:eval_evals.StaticUpDynCast) next case (StaticDownDynCast E e h l a Cs C Cs' h' l') have IH:"!!W. fv e ⊆ W ==> P,E \<turnstile> 〈e,(h,l |` W)〉 => 〈ref(a,Cs@[C]@Cs'),(h',l' |` W)〉" by fact have "fv (Cast C e) ⊆ W" by fact hence "fv e ⊆ W" by simp from IH[OF this] show ?case by(rule eval_evals.StaticDownDynCast) next case DynCastNull thus ?case by simp (blast intro:eval_evals.DynCastNull) next case DynCastFail thus ?case by simp (blast intro:eval_evals.DynCastFail) next case DynCastThrow thus ?case by(simp add:eval_evals.intros) next case Val thus ?case by(simp add:eval_evals.intros) next case BinOp thus ?case by simp (blast intro:eval_evals.BinOp) next case BinOpThrow1 thus ?case by simp (blast intro:eval_evals.BinOpThrow1) next case BinOpThrow2 thus ?case by simp (blast intro:eval_evals.BinOpThrow2) next case Var thus ?case by(simp add:eval_evals.intros) next case (LAss E e h0 l0 v h l V T v' l') have IH: "!!W. fv e ⊆ W ==> P,E \<turnstile> 〈e,(h0,l0|`W)〉 => 〈Val v,(h,l|`W)〉" and env:"E V = ⌊T⌋" and casts:"P \<turnstile> T casts v to v'" and [simp]: "l' = l(V \<mapsto> v')" by fact+ have "fv (V:=e) ⊆ W" by fact hence fv: "fv e ⊆ W" and VinW: "V ∈ W" by auto from eval_evals.LAss[OF IH[OF fv] _ casts] env VinW show ?case by fastsimp next case LAssThrow thus ?case by(fastsimp intro: eval_evals.LAssThrow) next case FAcc thus ?case by simp (blast intro: eval_evals.FAcc) next case FAccNull thus ?case by(fastsimp intro: eval_evals.FAccNull) next case FAccThrow thus ?case by(fastsimp intro: eval_evals.FAccThrow) next case (FAss E e1 h l a Cs' h' l' e2 v h2 l2 D S F T Cs v' Ds fs fs' S' h2' W) have IH1: "!!W. fv e1 ⊆ W ==> P,E \<turnstile> 〈e1,(h, l|`W)〉 => 〈ref (a, Cs'),(h', l'|`W)〉" and IH2: "!!W. fv e2 ⊆ W ==> P,E \<turnstile> 〈e2,(h', l'|`W)〉 => 〈Val v,(h2, l2|`W)〉" and fv:"fv (e1•F{Cs} := e2) ⊆ W" and h:"h2 a = Some(D,S)" and Ds:"Ds = Cs' @p Cs" and S:"(Ds,fs) ∈ S" and fs':"fs' = fs(F \<mapsto> v')" and S':"S' = S - {(Ds, fs)} ∪ {(Ds, fs')}" and h':"h2' = h2(a \<mapsto> (D, S'))" and field:"P \<turnstile> last Cs' has least F:T via Cs" and casts:"P \<turnstile> T casts v to v'" by fact+ from fv have fv1:"fv e1 ⊆ W" and fv2:"fv e2 ⊆ W" by auto from eval_evals.FAss[OF IH1[OF fv1] IH2[OF fv2] _ field casts] h Ds S fs' S' h' show ?case by simp next case FAssNull thus ?case by simp (blast intro: eval_evals.FAssNull) next case FAssThrow1 thus ?case by simp (blast intro: eval_evals.FAssThrow1) next case FAssThrow2 thus ?case by simp (blast intro: eval_evals.FAssThrow2) next case CallObjThrow thus ?case by simp (blast intro: eval_evals.intros) next case CallNull thus ?case by simp (blast intro: eval_evals.CallNull) next case CallParamsThrow thus ?case by simp (blast intro: eval_evals.CallParamsThrow) next case (Call E e h0 l0 a Cs h1 l1 ps vs h2 l2 C S M Ts' T' pns' body' Ds Ts T pns body Cs' vs' l2' new_body e' h3 l3 W) have IHe: "!!W. fv e ⊆ W ==> P,E \<turnstile> 〈e,(h0,l0|`W)〉 => 〈ref(a,Cs),(h1,l1|`W)〉" and IHps: "!!W. fvs ps ⊆ W ==> P,E \<turnstile> 〈ps,(h1,l1|`W)〉 [=>] 〈map Val vs,(h2,l2|`W)〉" and IHbd: "!!W. fv new_body ⊆ W ==> P,E(this \<mapsto> Class (last Cs'), pns [\<mapsto>] Ts) \<turnstile> 〈new_body,(h2,l2'|`W)〉 => 〈e',(h3,l3|`W)〉" and h2a: "h2 a = Some (C,S)" and method: "P \<turnstile> last Cs has least M = (Ts',T',pns',body') via Ds" and select:"P \<turnstile> (C,Cs@pDs) selects M = (Ts,T,pns,body) via Cs'" and same_len: "size vs = size pns" and casts:"P \<turnstile> Ts Casts vs to vs'" and l2': "l2' = [this \<mapsto> Ref(a,Cs'), pns [\<mapsto>] vs']" and body_case: "new_body = (case T' of Class D => (|D|)),body | _ => body)" by fact+ have "fv (e•M(ps)) ⊆ W" by fact hence fve: "fv e ⊆ W" and fvps: "fvs(ps) ⊆ W" by auto have wfmethod: "size Ts = size pns ∧ this ∉ set pns" and fvbd: "fv body ⊆ {this} ∪ set pns" using select wf by(fastsimp dest!:select_method_wf_mdecl simp:wf_mdecl_def)+ from fvbd body_case have fvbd':"fv new_body ⊆ {this} ∪ set pns" by(cases T') auto from l2' have "l2' |` ({this} ∪ set pns) = [this \<mapsto> Ref (a, Cs'), pns [\<mapsto>] vs']" by (auto intro!:ext simp:restrict_map_def fun_upd_def) with eval_evals.Call[OF IHe[OF fve] IHps[OF fvps] _ method select same_len casts _ body_case IHbd[OF fvbd']] h2a show ?case by simp next case (StaticCall E e h0 l0 a Cs h1 l1 ps vs h2 l2 C Cs'' M Ts T pns body Cs' Ds vs' l2' e' h3 l3 W) have IHe: "!!W. fv e ⊆ W ==> P,E \<turnstile> 〈e,(h0,l0|`W)〉 => 〈ref(a,Cs),(h1,l1|`W)〉" and IHps: "!!W. fvs ps ⊆ W ==> P,E \<turnstile> 〈ps,(h1,l1|`W)〉 [=>] 〈map Val vs,(h2,l2|`W)〉" and IHbd: "!!W. fv body ⊆ W ==> P,E(this \<mapsto> Class (last Ds), pns [\<mapsto>] Ts) \<turnstile> 〈body,(h2,l2'|`W)〉 => 〈e',(h3,l3|`W)〉" and path_unique: "P \<turnstile> Path last Cs to C unique" and path_via: "P \<turnstile> Path last Cs to C via Cs''" and least: "P \<turnstile> C has least M = (Ts, T, pns, body) via Cs'" and Ds: "Ds = (Cs @p Cs'') @p Cs'" and same_len: "size vs = size pns" and casts:"P \<turnstile> Ts Casts vs to vs'" and l2': "l2' = [this \<mapsto> Ref(a,Ds), pns [\<mapsto>] vs']" by fact+ have "fv (e•(C::)M(ps)) ⊆ W" by fact hence fve: "fv e ⊆ W" and fvps: "fvs(ps) ⊆ W" by auto have wfmethod: "size Ts = size pns ∧ this ∉ set pns" and fvbd: "fv body ⊆ {this} ∪ set pns" using least wf by(fastsimp dest!:has_least_wf_mdecl simp:wf_mdecl_def)+ from fvbd have fvbd':"fv body ⊆ {this} ∪ set pns" by auto from l2' have "l2' |` ({this} ∪ set pns) = [this \<mapsto> Ref(a,Ds), pns [\<mapsto>] vs']" by (auto intro!:ext simp:restrict_map_def fun_upd_def) with eval_evals.StaticCall[OF IHe[OF fve] IHps[OF fvps] path_unique path_via least Ds same_len casts _ IHbd[OF fvbd']] show ?case by simp next case SeqThrow thus ?case by simp (blast intro: eval_evals.SeqThrow) next case CondT thus ?case by simp (blast intro: eval_evals.CondT) next case CondF thus ?case by simp (blast intro: eval_evals.CondF) next case CondThrow thus ?case by simp (blast intro: eval_evals.CondThrow) next case WhileF thus ?case by simp (blast intro: eval_evals.WhileF) next case WhileT thus ?case by simp (blast intro: eval_evals.WhileT) next case WhileCondThrow thus ?case by simp (blast intro: eval_evals.WhileCondThrow) next case WhileBodyThrow thus ?case by simp (blast intro: eval_evals.WhileBodyThrow) next case Throw thus ?case by simp (blast intro: eval_evals.Throw) next case ThrowNull thus ?case by simp (blast intro: eval_evals.ThrowNull) next case ThrowThrow thus ?case by simp (blast intro: eval_evals.ThrowThrow) next case Nil thus ?case by (simp add: eval_evals.Nil) next case Cons thus ?case by simp (blast intro: eval_evals.Cons) next case ConsThrow thus ?case by simp (blast intro: eval_evals.ConsThrow) qed lemma eval_notfree_unchanged: assumes wf:"wwf_prog P" shows "P,E \<turnstile> 〈e,(h,l)〉 => 〈e',(h',l')〉 ==> (!!V. V ∉ fv e ==> l' V = l V)" and "P,E \<turnstile> 〈es,(h,l)〉 [=>] 〈es',(h',l')〉 ==> (!!V. V ∉ fvs es ==> l' V = l V)" proof(induct rule:eval_evals_inducts) case LAss thus ?case by(simp add:fun_upd_apply) next case Block thus ?case by (simp only:fun_upd_apply split:if_splits) fastsimp qed simp_all lemma eval_closed_lcl_unchanged: assumes wf:"wwf_prog P" and eval:"P,E \<turnstile> 〈e,(h,l)〉 => 〈e',(h',l')〉" and fv:"fv e = {}" shows "l' = l" proof - from wf eval have "!!V. V ∉ fv e ==> l' V = l V" by (rule eval_notfree_unchanged) with fv have "!!V. l' V = l V" by simp thus ?thesis by(simp add:expand_fun_eq) qed (* Hiermit kann man die ganze pair-Splitterei in den automatischen Taktiken abschalten. Wieder anschalten siehe nach dem Beweis. *) declare split_paired_All [simp del] split_paired_Ex [simp del] declaration {* K (Simplifier.map_ss (fn ss => ss delloop "split_all_tac")) *} declaration {* K (Classical.map_cs (fn cs => cs delSWrapper "split_all_tac")) *} lemma list_eval_Throw: assumes eval_e: "P,E \<turnstile> 〈throw x,s〉 => 〈e',s'〉" shows "P,E \<turnstile> 〈map Val vs @ throw x # es',s〉 [=>] 〈map Val vs @ e' # es',s'〉" proof - from eval_e obtain a where e': "e' = Throw a" by (cases) (auto dest!: eval_final) { fix es have "!!vs. es = map Val vs @ throw x # es' ==> P,E \<turnstile> 〈es,s〉[=>]〈map Val vs @ e' # es',s'〉" proof (induct es type: list) case Nil thus ?case by simp next case (Cons e es vs) have e_es: "e # es = map Val vs @ throw x # es'" by fact show "P,E \<turnstile> 〈e # es,s〉 [=>] 〈map Val vs @ e' # es',s'〉" proof (cases vs) case Nil with e_es obtain "e=throw x" "es=es'" by simp moreover from eval_e e' have "P,E \<turnstile> 〈throw x # es,s〉 [=>] 〈Throw a # es,s'〉" by (iprover intro: ConsThrow) ultimately show ?thesis using Nil e' by simp next case (Cons v vs') have vs: "vs = v # vs'" by fact with e_es obtain e: "e=Val v" and es:"es= map Val vs' @ throw x # es'" by simp from e have "P,E \<turnstile> 〈e,s〉 => 〈Val v,s〉" by (iprover intro: eval_evals.Val) moreover from es have "P,E \<turnstile> 〈es,s〉 [=>] 〈map Val vs' @ e' # es',s'〉" by (rule Cons.hyps) ultimately show "P,E \<turnstile> 〈e#es,s〉 [=>] 〈map Val vs @ e' # es',s'〉" using vs by (auto intro: eval_evals.Cons) qed qed } thus ?thesis by simp qed text {* The key lemma: *} lemma assumes wf: "wwf_prog P" shows extend_1_eval: "P,E \<turnstile> 〈e,s〉 -> 〈e'',s''〉 ==> (!!s' e'. P,E \<turnstile> 〈e'',s''〉 => 〈e',s'〉 ==> P,E \<turnstile> 〈e,s〉 => 〈e',s'〉)" and extend_1_evals: "P,E \<turnstile> 〈es,t〉 [->] 〈es'',t''〉 ==> (!!t' es'. P,E \<turnstile> 〈es'',t''〉 [=>] 〈es',t'〉 ==> P,E \<turnstile> 〈es,t〉 [=>] 〈es',t'〉)" proof (induct rule: red_reds.inducts) case RedNew thus ?case by (iprover elim: eval_cases intro: eval_evals.intros) next case RedNewFail thus ?case by (fastsimp elim: eval_cases intro: eval_evals.intros) next case (StaticCastRed E e s e'' s'' C s' e') thus ?case by -(erule eval_cases,auto intro:eval_evals.intros, subgoal_tac "P,E \<turnstile> 〈e'',s''〉 => 〈ref(a,Cs@[C]@Cs'),s'〉", rule_tac Cs'="Cs'" in StaticDownCast,auto) next case RedStaticCastNull thus ?case by (fastsimp elim: eval_cases intro: eval_evals.intros) next case RedStaticUpCast thus ?case by (fastsimp elim: eval_cases intro: eval_evals.intros) next case RedStaticDownCast thus ?case by (fastsimp elim: eval_cases intro: eval_evals.intros) next case RedStaticCastFail thus ?case by (fastsimp elim: eval_cases intro: eval_evals.intros) next case RedStaticUpDynCast thus ?case by (fastsimp elim: eval_cases intro: eval_evals.intros) next case RedStaticDownDynCast thus ?case by (fastsimp elim: eval_cases intro: eval_evals.intros) next case (DynCastRed E e s e'' s'' C s' e') have eval:"P,E \<turnstile> 〈Cast C e'',s''〉 => 〈e',s'〉" and IH:"!!ex sx. P,E \<turnstile> 〈e'',s''〉 => 〈ex,sx〉 ==> P,E \<turnstile> 〈e,s〉 => 〈ex,sx〉" by fact+ moreover { fix Cs Cs' a assume "P,E \<turnstile> 〈e'',s''〉 => 〈ref (a, Cs @ C # Cs'),s'〉" from IH[OF this] have "P,E \<turnstile> 〈e,s〉 => 〈ref (a, Cs@[C]@Cs'),s'〉" by simp hence "P,E \<turnstile> 〈Cast C e,s〉 => 〈ref (a, Cs@[C]),s'〉" by(rule StaticDownDynCast) } ultimately show ?case by -(erule eval_cases,auto intro: eval_evals.intros) next case RedDynCastNull thus ?case by (iprover elim:eval_cases intro:eval_evals.intros) next case (RedDynCast s a D S C Cs' E Cs s' e') thus ?case by (cases s)(auto elim!:eval_cases intro:eval_evals.intros) next case (RedDynCastFail s a D S C Cs E s'' e'') thus ?case by (cases s)(auto elim!: eval_cases intro: eval_evals.intros) next case BinOpRed1 thus ?case by -(erule eval_cases,auto intro: eval_evals.intros) next case BinOpRed2 thus ?case by (fastsimp elim!:eval_cases intro:eval_evals.intros eval_finalId) next case RedBinOp thus ?case by (iprover elim:eval_cases intro:eval_evals.intros) next case (RedVar s V v E s' e') thus ?case by (cases s)(fastsimp elim:eval_cases intro:eval_evals.intros) next case LAssRed thus ?case by -(erule eval_cases,auto intro:eval_evals.intros) next case RedLAss thus ?case by (fastsimp elim:eval_cases intro:eval_evals.intros) next case FAccRed thus ?case by -(erule eval_cases,auto intro:eval_evals.intros) next case (RedFAcc s a D S Ds Cs' Cs fs F v E s' e') thus ?case by (cases s)(fastsimp elim:eval_cases intro:eval_evals.intros) next case RedFAccNull thus ?case by (fastsimp elim!:eval_cases intro:eval_evals.intros) next case (FAssRed1 E e1 s e1' s'' F Cs e2 s' e') have eval:"P,E \<turnstile> 〈e1'•F{Cs} := e2,s''〉 => 〈e',s'〉" and IH:"!!ex sx. P,E \<turnstile> 〈e1',s''〉 => 〈ex,sx〉 ==> P,E \<turnstile> 〈e1,s〉 => 〈ex,sx〉" by fact+ { fix Cs' D S T a fs h2 l2 s1 v v' assume ref:"P,E \<turnstile> 〈e1',s''〉 => 〈ref (a, Cs'),s1〉" and rest:"P,E \<turnstile> 〈e2,s1〉 => 〈Val v,(h2, l2)〉" "h2 a = ⌊(D, S)⌋" "P \<turnstile> last Cs' has least F:T via Cs" "P \<turnstile> T casts v to v'" "(Cs' @p Cs, fs) ∈ S" from IH[OF ref] have "P,E \<turnstile> 〈e1,s〉 => 〈ref (a, Cs'),s1〉" . with rest have "P,E \<turnstile> 〈e1•F{Cs} := e2,s〉 => 〈Val v',(h2(a \<mapsto> (D,insert (Cs'@pCs,fs(F \<mapsto> v'))(S - {(Cs'@pCs,fs)}))),l2)〉" by-(rule FAss,simp_all) } moreover { fix s1 v assume null:"P,E \<turnstile> 〈e1',s''〉 => 〈null,s1〉" and rest:"P,E \<turnstile> 〈e2,s1〉 => 〈Val v,s'〉" from IH[OF null] have "P,E \<turnstile> 〈e1,s〉 => 〈null,s1〉" . with rest have "P,E \<turnstile> 〈e1•F{Cs} := e2,s〉 => 〈THROW NullPointer,s'〉" by-(rule FAssNull,simp_all) } moreover { fix e' assume throw:"P,E \<turnstile> 〈e1',s''〉 => 〈throw e',s'〉" from IH[OF throw] have "P,E \<turnstile> 〈e1,s〉 => 〈throw e',s'〉" . hence "P,E \<turnstile> 〈e1•F{Cs} := e2,s〉 => 〈throw e',s'〉" by-(rule eval_evals.FAssThrow1,simp_all) } moreover { fix e' s1 v assume val:"P,E \<turnstile> 〈e1',s''〉 => 〈Val v,s1〉" and rest:"P,E \<turnstile> 〈e2,s1〉 => 〈throw e',s'〉" from IH[OF val] have "P,E \<turnstile> 〈e1,s〉 => 〈Val v,s1〉" . with rest have "P,E \<turnstile> 〈e1•F{Cs} := e2,s〉 => 〈throw e',s'〉" by-(rule eval_evals.FAssThrow2,simp_all) } ultimately show ?case using eval by -(erule eval_cases,auto) next case (FAssRed2 E e2 s e2' s'' v F Cs s' e') have eval:"P,E \<turnstile> 〈Val v•F{Cs} := e2',s''〉 => 〈e',s'〉" and IH:"!!ex sx. P,E \<turnstile> 〈e2',s''〉 => 〈ex,sx〉 ==> P,E \<turnstile> 〈e2,s〉 => 〈ex,sx〉" by fact+ { fix Cs' D S T a fs h2 l2 s1 v' v'' assume val1:"P,E \<turnstile> 〈Val v,s''〉 => 〈ref (a,Cs'),s1〉" and val2:"P,E \<turnstile> 〈e2',s1〉 => 〈Val v',(h2, l2)〉" and rest:"h2 a = ⌊(D, S)⌋" "P \<turnstile> last Cs' has least F:T via Cs" "P \<turnstile> T casts v' to v''" "(Cs'@pCs,fs) ∈ S" from val1 have s'':"s1 = s''" by -(erule eval_cases) with val1 have "P,E \<turnstile> 〈Val v,s〉 => 〈ref (a,Cs'),s〉" by(fastsimp elim:eval_cases intro:eval_finalId) also from IH[OF val2[simplified s'']] have "P,E \<turnstile> 〈e2,s〉 => 〈Val v',(h2, l2)〉" . ultimately have "P,E \<turnstile> 〈Val v•F{Cs} := e2,s〉 => 〈Val v'',(h2(a\<mapsto>(D,insert(Cs'@pCs,fs(F \<mapsto> v''))(S - {(Cs'@pCs,fs)}))),l2)〉" using rest by -(rule FAss,simp_all) } moreover { fix s1 v' assume val1:"P,E \<turnstile> 〈Val v,s''〉 => 〈null,s1〉" and val2:"P,E \<turnstile> 〈e2',s1〉 => 〈Val v',s'〉" from val1 have s'':"s1 = s''" by -(erule eval_cases) with val1 have "P,E \<turnstile> 〈Val v,s〉 => 〈null,s〉" by(fastsimp elim:eval_cases intro:eval_finalId) also from IH[OF val2[simplified s'']] have "P,E \<turnstile> 〈e2,s〉 => 〈Val v',s'〉" . ultimately have "P,E \<turnstile> 〈Val v•F{Cs} := e2,s〉 => 〈THROW NullPointer,s'〉" by -(rule FAssNull,simp_all) } moreover { fix r assume val:"P,E \<turnstile> 〈Val v,s''〉 => 〈throw r,s'〉" hence s'':"s'' = s'" by -(erule eval_cases,simp) with val have "P,E \<turnstile> 〈Val v•F{Cs} := e2,s〉 => 〈throw r,s'〉" by -(rule eval_evals.FAssThrow1,erule eval_cases,simp) } moreover { fix r s1 v' assume val1:"P,E \<turnstile> 〈Val v,s''〉 => 〈Val v',s1〉" and val2:"P,E \<turnstile> 〈e2',s1〉 => 〈throw r,s'〉" from val1 have s'':"s1 = s''" by -(erule eval_cases) with val1 have "P,E \<turnstile> 〈Val v,s〉 => 〈Val v',s〉" by(fastsimp elim:eval_cases intro:eval_finalId) also from IH[OF val2[simplified s'']] have "P,E \<turnstile> 〈e2,s〉 => 〈throw r,s'〉" . ultimately have "P,E \<turnstile> 〈Val v•F{Cs} := e2,s〉 => 〈throw r,s'〉" by -(rule eval_evals.FAssThrow2,simp_all) } ultimately show ?case using eval by -(erule eval_cases,auto) next case (RedFAss h a D S Cs' F T Cs v v' Ds fs E l s' e') have val:"P,E \<turnstile> 〈Val v',(h(a \<mapsto> (D,insert (Ds,fs(F \<mapsto> v'))(S - {(Ds,fs)}))),l)〉 => 〈e',s'〉" and rest:"h a = ⌊(D, S)⌋" "P \<turnstile> last Cs' has least F:T via Cs" "P \<turnstile> T casts v to v'" "Ds = Cs' @p Cs" "(Ds, fs) ∈ S" by fact+ from val have "s' = (h(a \<mapsto> (D,insert (Ds,fs(F \<mapsto> v')) (S - {(Ds,fs)}))),l)" and "e' = Val v'" by -(erule eval_cases,simp_all)+ with rest show ?case apply simp by(rule FAss,simp_all)(rule eval_finalId,simp)+ next case RedFAssNull thus ?case by (fastsimp elim!: eval_cases intro: eval_evals.intros) next case (CallObj E e s e' s' Copt M es s'' e'') thus ?case apply - apply(cases Copt,simp) by(erule eval_cases,auto intro:eval_evals.intros)+ next case (CallParams E es s es' s'' v Copt M s' e') have call:"P,E \<turnstile> 〈Call (Val v) Copt M es',s''〉 => 〈e',s'〉" and IH:"!!esx sx. P,E \<turnstile> 〈es',s''〉 [=>] 〈esx,sx〉 ==> P,E \<turnstile> 〈es,s〉 [=>] 〈esx,sx〉" by fact+ show ?case proof(cases Copt) case None with call have eval:"P,E \<turnstile> 〈Val v•M(es'),s''〉 => 〈e',s'〉" by simp from eval show ?thesis proof(rule eval_cases) fix r assume "P,E \<turnstile> 〈Val v,s''〉 => 〈throw r,s'〉" "e' = throw r" with None show "P,E \<turnstile> 〈Call (Val v) Copt M es,s〉 => 〈e',s'〉" by(fastsimp elim:eval_cases) next fix es'' r sx v' vs assume val:"P,E \<turnstile> 〈Val v,s''〉 => 〈Val v',sx〉" and evals:"P,E \<turnstile> 〈es',sx〉 [=>] 〈map Val vs @ throw r # es'',s'〉" and e':"e' = throw r" have val':"P,E \<turnstile> 〈Val v,s〉 => 〈Val v,s〉" by(rule Val) from val have eq:"v' = v ∧ s'' = sx" by -(erule eval_cases,simp) with IH evals have "P,E \<turnstile> 〈es,s〉 [=>] 〈map Val vs @ throw r # es'',s'〉" by simp with eq CallParamsThrow[OF val'] e' None show "P,E \<turnstile> 〈Call (Val v) Copt M es,s〉 => 〈e',s'〉" by fastsimp next fix C Cs Cs' Ds S T T' Ts Ts' a body body' h2 h3 l2 l3 pns pns' s1 vs vs' assume val:"P,E \<turnstile> 〈Val v,s''〉 => 〈ref(a,Cs),s1〉" and evals:"P,E \<turnstile> 〈es',s1〉 [=>] 〈map Val vs,(h2,l2)〉" and hp:"h2 a = Some(C, S)" and method:"P \<turnstile> last Cs has least M = (Ts',T',pns',body') via Ds" and select:"P \<turnstile> (C,Cs@pDs) selects M = (Ts,T,pns,body) via Cs'" and length:"length vs = length pns" and casts:"P \<turnstile> Ts Casts vs to vs'" and body:"P,E(this \<mapsto> Class (last Cs'), pns [\<mapsto>] Ts) \<turnstile> 〈case T' of Class D => (|D|)),body | _ => body,(h2,[this \<mapsto> Ref(a,Cs'),pns [\<mapsto>] vs'])〉 => 〈e',(h3, l3)〉" and s':"s' = (h3, l2)" from val have val':"P,E \<turnstile> 〈Val v,s〉 => 〈ref(a,Cs),s〉" and eq:"s'' = s1 ∧ v = Ref(a,Cs)" by(auto elim:eval_cases intro:Val) from body obtain new_body where body_case:"new_body = (case T' of Class D => (|D|)),body | _ => body)" and body':"P,E(this \<mapsto> Class (last Cs'), pns [\<mapsto>] Ts) \<turnstile> 〈new_body,(h2,[this \<mapsto> Ref(a,Cs'),pns [\<mapsto>] vs'])〉 => 〈e',(h3, l3)〉" by simp from eq IH evals have "P,E \<turnstile> 〈es,s〉 [=>] 〈map Val vs,(h2,l2)〉" by simp with eq Call[OF val' _ _ method select length casts _ body_case] hp body' s' None show "P,E \<turnstile> 〈Call (Val v) Copt M es,s〉 => 〈e',s'〉" by fastsimp next fix s1 vs assume val:"P,E \<turnstile> 〈Val v,s''〉 => 〈null,s1〉" and evals:"P,E \<turnstile> 〈es',s1〉 [=>] 〈map Val vs,s'〉" and e':"e' = THROW NullPointer" from val have val':"P,E \<turnstile> 〈Val v,s〉 => 〈null,s〉" and eq:"s'' = s1 ∧ v = Null" by(auto elim:eval_cases intro:Val) from eq IH evals have "P,E \<turnstile> 〈es,s〉 [=>] 〈map Val vs,s'〉" by simp with eq CallNull[OF val'] e' None show "P,E \<turnstile> 〈Call (Val v) Copt M es,s〉 => 〈e',s'〉" by fastsimp qed next case (Some C) with call have eval:"P,E \<turnstile> 〈Val v•(C::)M(es'),s''〉 => 〈e',s'〉" by simp from eval show ?thesis proof(rule eval_cases) fix r assume "P,E \<turnstile> 〈Val v,s''〉 => 〈throw r,s'〉" "e' = throw r" with Some show "P,E \<turnstile> 〈Call (Val v) Copt M es,s〉 => 〈e',s'〉" by(fastsimp elim:eval_cases) next fix es'' r sx v' vs assume val:"P,E \<turnstile> 〈Val v,s''〉 => 〈Val v',sx〉" and evals:"P,E \<turnstile> 〈es',sx〉 [=>] 〈map Val vs @ throw r # es'',s'〉" and e':"e' = throw r" have val':"P,E \<turnstile> 〈Val v,s〉 => 〈Val v,s〉" by(rule Val) from val have eq:"v' = v ∧ s'' = sx" by -(erule eval_cases,simp) with IH evals have "P,E \<turnstile> 〈es,s〉 [=>] 〈map Val vs @ throw r # es'',s'〉" by simp with eq CallParamsThrow[OF val'] e' Some show "P,E \<turnstile> 〈Call (Val v) Copt M es,s〉 => 〈e',s'〉" by fastsimp next fix Cs Cs' Cs'' T Ts a body h2 h3 l2 l3 pns s1 vs vs' assume val:"P,E \<turnstile> 〈Val v,s''〉 => 〈ref (a,Cs),s1〉" and evals:"P,E \<turnstile> 〈es',s1〉 [=>] 〈map Val vs,(h2,l2)〉" and path_unique:"P \<turnstile> Path last Cs to C unique" and path_via:"P \<turnstile> Path last Cs to C via Cs''" and least:"P \<turnstile> C has least M = (Ts, T, pns, body) via Cs'" and length:"length vs = length pns" and casts:"P \<turnstile> Ts Casts vs to vs'" and body:"P,E(this \<mapsto> Class (last ((Cs @p Cs'') @p Cs')), pns [\<mapsto>] Ts) \<turnstile> 〈body,(h2,[this \<mapsto> Ref(a,(Cs@pCs'')@pCs'),pns [\<mapsto>] vs'])〉 => 〈e',(h3,l3)〉" and s':"s' = (h3,l2)" from val have val':"P,E \<turnstile> 〈Val v,s〉 => 〈ref(a,Cs),s〉" and eq:"s'' = s1 ∧ v = Ref(a,Cs)" by(auto elim:eval_cases intro:Val) from eq IH evals have "P,E \<turnstile> 〈es,s〉 [=>] 〈map Val vs,(h2,l2)〉" by simp with eq StaticCall[OF val' _ path_unique path_via least _ _ casts _ body] length s' Some show "P,E \<turnstile> 〈Call (Val v) Copt M es,s〉 => 〈e',s'〉" by fastsimp next fix s1 vs assume val:"P,E \<turnstile> 〈Val v,s''〉 => 〈null,s1〉" and evals:"P,E \<turnstile> 〈es',s1〉 [=>] 〈map Val vs,s'〉" and e':"e' = THROW NullPointer" from val have val':"P,E \<turnstile> 〈Val v,s〉 => 〈null,s〉" and eq:"s'' = s1 ∧ v = Null" by(auto elim:eval_cases intro:Val) from eq IH evals have "P,E \<turnstile> 〈es,s〉 [=>] 〈map Val vs,s'〉" by simp with eq CallNull[OF val'] e' Some show "P,E \<turnstile> 〈Call (Val v) Copt M es,s〉 => 〈e',s'〉" by fastsimp qed qed next case (RedCall s a C S Cs M Ts' T' pns' body' Ds Ts T pns body Cs' vs bs new_body E s' e') obtain h l where "s' = (h,l)" by(cases s') auto have "P,E \<turnstile> 〈ref(a,Cs),s〉 => 〈ref(a,Cs),s〉" by (rule eval_evals.intros) moreover have finals: "finals(map Val vs)" by simp obtain h2 l2 where s: "s = (h2,l2)" by (cases s) with finals have "P,E \<turnstile> 〈map Val vs,s〉 [=>] 〈map Val vs,(h2,l2)〉" by (iprover intro: eval_finalsId) moreover from s have h2a:"h2 a = Some (C,S)" using RedCall by simp moreover have method: "P \<turnstile> last Cs has least M = (Ts',T',pns',body') via Ds" by fact moreover have select:"P \<turnstile> (C,Cs@pDs) selects M = (Ts,T,pns,body) via Cs'" by fact moreover have blocks:"bs = blocks(this#pns,Class(last Cs')#Ts,Ref(a,Cs')#vs,body)" by fact moreover have body_case:"new_body = (case T' of Class D => (|D|)),bs | _ => bs)" by fact moreover have same_len1: "length Ts = length pns" and this_distinct: "this ∉ set pns" and fv: "fv body ⊆ {this} ∪ set pns" using select wf by (fastsimp dest!:select_method_wf_mdecl simp:wf_mdecl_def)+ have same_len: "length vs = length pns" by fact moreover obtain h3 l3 where s': "s' = (h3,l3)" by (cases s') have eval_blocks:"P,E \<turnstile> 〈new_body,s〉 => 〈e',s'〉" by fact hence id: "l3 = l2" using fv s s' same_len1 same_len wf blocks body_case by(cases T')(auto elim!: eval_closed_lcl_unchanged) from same_len1 have same_len':"length(this#pns) = length(Class (last Cs')#Ts)" by simp from same_len1 same_len have same_len2:"length(this#pns) = length(Ref(a,Cs')#vs)" by simp from eval_blocks have eval_blocks':"P,E \<turnstile> 〈new_body,(h2,l2)〉 => 〈e',(h3,l3)〉" using s s' by simp have casts_unique:"!!vs'. P \<turnstile> Class (last Cs')#Ts Casts Ref(a,Cs')#vs to vs' ==> vs' = Ref(a,Cs')#tl vs'" using wf by -(erule Casts_to.cases,auto elim!:casts_to.cases dest!:mdc_eq_last simp:path_via_def appendPath_def) have "∃l'' vs' new_body'. P,E(this\<mapsto>Class(last Cs'), pns[\<mapsto>]Ts) \<turnstile> 〈new_body',(h2,l2(this # pns[\<mapsto>]Ref(a,Cs')#vs'))〉 => 〈e',(h3, l'')〉 ∧ P \<turnstile> Class(last Cs')#Ts Casts Ref(a,Cs')#vs to Ref(a,Cs')#vs' ∧ length vs' = length vs ∧ fv new_body' ⊆ {this} ∪ set pns ∧ new_body' = (case T' of Class D => (|D|)),body | _ => body)" proof(cases "∀C. T' ≠ Class C") case True with same_len' same_len2 eval_blocks' casts_unique body_case blocks obtain l'' vs' where body:"P,E(this\<mapsto>Class(last Cs'), pns[\<mapsto>]Ts) \<turnstile> 〈body,(h2,l2(this # pns[\<mapsto>]Ref(a,Cs')#vs'))〉 => 〈e',(h3, l'')〉" and casts:"P \<turnstile> Class(last Cs')#Ts Casts Ref(a,Cs')#vs to Ref(a,Cs')#vs'" and lengthvs':"length vs' = length vs" by -(drule_tac vs="Ref(a,Cs')#vs" in blocksEval,assumption,cases T', auto simp:length_Suc_conv,blast) with fv True show ?thesis by(cases T') auto next case False then obtain D where T':"T' = Class D" by auto with same_len' same_len2 eval_blocks' casts_unique body_case blocks obtain l'' vs' where body:"P,E(this\<mapsto>Class(last Cs'), pns[\<mapsto>]Ts) \<turnstile> 〈(|D|)),body,(h2,l2(this # pns[\<mapsto>]Ref(a,Cs')#vs'))〉 => 〈e',(h3, l'')〉" and casts:"P \<turnstile> Class(last Cs')#Ts Casts Ref(a,Cs')#vs to Ref(a,Cs')#vs'" and lengthvs':"length vs' = length vs" by - (drule_tac vs="Ref(a,Cs')#vs" in CastblocksEval, assumption,simp,clarsimp simp:length_Suc_conv,auto) from fv have "fv ((|D|)),body) ⊆ {this} ∪ set pns" by simp with body casts lengthvs' T' show ?thesis by auto qed then obtain l'' vs' new_body' where body:"P,E(this\<mapsto>Class(last Cs'), pns[\<mapsto>]Ts) \<turnstile> 〈new_body',(h2,l2(this # pns[\<mapsto>]Ref(a,Cs')#vs'))〉 => 〈e',(h3, l'')〉" and casts:"P \<turnstile> Class(last Cs')#Ts Casts Ref(a,Cs')#vs to Ref(a,Cs')#vs'" and lengthvs':"length vs' = length vs" and body_case':"new_body' = (case T' of Class D => (|D|)),body | _ => body)" and fv':"fv new_body' ⊆ {this} ∪ set pns" by auto from same_len2 lengthvs' have same_len3:"length (this # pns) = length (Ref (a, Cs') # vs')" by simp from restrict_map_upds[OF same_len3,of "set(this#pns)" "l2"] have "l2(this # pns[\<mapsto>]Ref(a,Cs')#vs')|`(set(this#pns)) = [this # pns[\<mapsto>]Ref(a,Cs')#vs']" by simp with eval_restrict_lcl[OF wf body fv'] this_distinct same_len1 same_len have "P,E(this\<mapsto>Class(last Cs'), pns[\<mapsto>]Ts) \<turnstile> 〈new_body',(h2,[this # pns[\<mapsto>]Ref(a,Cs')#vs'])〉 => 〈e',(h3, l''|`(set(this#pns)))〉" by simp with casts obtain l2' l3' vs' where "P \<turnstile> Ts Casts vs to vs'" and "P,E(this\<mapsto>Class(last Cs'), pns[\<mapsto>]Ts) \<turnstile> 〈new_body',(h2,l2')〉 => 〈e',(h3,l3')〉" and "l2' = [this\<mapsto>Ref(a,Cs'),pns[\<mapsto>]vs']" by(auto elim:Casts_to.cases) ultimately have "P,E \<turnstile> 〈(ref(a,Cs))•M(map Val vs),s〉 => 〈e',(h3,l2)〉" using body_case' by -(rule Call,simp_all) with s' id show ?case by simp next case (RedStaticCall Cs C Cs'' M Ts T pns body Cs' Ds vs E a s s' e') have "P,E \<turnstile> 〈ref(a,Cs),s〉 => 〈ref(a,Cs),s〉" by (rule eval_evals.intros) moreover have finals: "finals(map Val vs)" by simp obtain h2 l2 where s: "s = (h2,l2)" by (cases s) with finals have "P,E \<turnstile> 〈map Val vs,s〉 [=>] 〈map Val vs,(h2,l2)〉" by (iprover intro: eval_finalsId) moreover have path_unique:"P \<turnstile> Path last Cs to C unique" by fact moreover have path_via:"P \<turnstile> Path last Cs to C via Cs''" by fact moreover have least:"P \<turnstile> C has least M = (Ts, T, pns, body) via Cs'" by fact moreover have same_len1: "length Ts = length pns" and this_distinct: "this ∉ set pns" and fv: "fv body ⊆ {this} ∪ set pns" using least wf by (fastsimp dest!:has_least_wf_mdecl simp:wf_mdecl_def)+ moreover have same_len:"length vs = length pns" by fact moreover have Ds:"Ds = (Cs @p Cs'') @p Cs'" by fact moreover obtain h3 l3 where s': "s' = (h3,l3)" by (cases s') have eval_blocks:"P,E \<turnstile> 〈blocks(this#pns,Class(last Ds)#Ts,Ref(a,Ds)#vs,body),s〉 => 〈e',s'〉" by fact hence id: "l3 = l2" using fv s s' same_len1 same_len wf by(auto elim!: eval_closed_lcl_unchanged) from same_len1 have same_len':"length(this#pns) = length(Class (last Ds)#Ts)" by simp from same_len1 same_len have same_len2:"length(this#pns) = length(Ref(a,Ds)#vs)" by simp from eval_blocks have eval_blocks':"P,E \<turnstile> 〈blocks(this#pns,Class(last Ds)#Ts,Ref(a,Ds)#vs,body), (h2,l2)〉 => 〈e',(h3,l3)〉" using s s' by simp have casts_unique:"!!vs'. P \<turnstile> Class (last Ds)#Ts Casts Ref(a,Ds)#vs to vs' ==> vs' = Ref(a,Ds)#tl vs'" using wf by -(erule Casts_to.cases,auto elim!:casts_to.cases dest!:mdc_eq_last simp:path_via_def appendPath_def) from same_len' same_len2 eval_blocks' casts_unique obtain l'' vs' where body:"P,E(this\<mapsto>Class(last Ds), pns[\<mapsto>]Ts) \<turnstile> 〈body,(h2,l2(this # pns[\<mapsto>]Ref(a,Ds)#vs'))〉 => 〈e',(h3, l'')〉" and casts:"P \<turnstile> Class(last Ds)#Ts Casts Ref(a,Ds)#vs to Ref(a,Ds)#vs'" and lengthvs':"length vs' = length vs" by -(drule_tac vs="Ref(a,Ds)#vs" in blocksEval,auto simp:length_Suc_conv,blast) from same_len2 lengthvs' have same_len3:"length (this # pns) = length (Ref(a,Ds) # vs')" by simp from restrict_map_upds[OF same_len3,of "set(this#pns)" "l2"] have "l2(this # pns[\<mapsto>]Ref(a,Ds)#vs')|`(set(this#pns)) = [this # pns[\<mapsto>]Ref(a,Ds)#vs']" by simp with eval_restrict_lcl[OF wf body fv] this_distinct same_len1 same_len have "P,E(this\<mapsto>Class(last Ds), pns[\<mapsto>]Ts) \<turnstile> 〈body,(h2,[this#pns [\<mapsto>] Ref(a,Ds)#vs'])〉 => 〈e',(h3, l''|`(set(this#pns)))〉" by simp with casts obtain l2' l3' vs' where "P \<turnstile> Ts Casts vs to vs'" and "P,E(this \<mapsto> Class(last Ds),pns [\<mapsto>] Ts) \<turnstile> 〈body,(h2,l2')〉 => 〈e',(h3,l3')〉" and "l2' = [this \<mapsto> Ref(a,Ds),pns [\<mapsto>] vs']" by(auto elim:Casts_to.cases) ultimately have "P,E \<turnstile> 〈(ref(a,Cs))•(C::)M(map Val vs),s〉 => 〈e',(h3,l2)〉" by -(rule StaticCall,simp_all) with s' id show ?case by simp next case RedCallNull thus ?case by (fastsimp elim: eval_cases intro: eval_evals.intros eval_finalsId) next case BlockRedNone thus ?case by (fastsimp elim!: eval_cases intro: eval_evals.intros simp add: fun_upd_same fun_upd_idem) next case (BlockRedSome E V T e h l e'' h' l' v s' e') have eval:"P,E \<turnstile> 〈{V:T:=Val v; e''},(h', l'(V := l V))〉 => 〈e',s'〉" and red:"P,E(V \<mapsto> T) \<turnstile> 〈e,(h, l(V := None))〉 -> 〈e'',(h', l')〉" and notassigned:"¬ assigned V e" and l':"l' V = Some v" and IH:"!!ex sx. P,E(V \<mapsto> T) \<turnstile> 〈e'',(h', l')〉 => 〈ex,sx〉 ==> P,E(V \<mapsto> T) \<turnstile> 〈e,(h, l(V := None))〉 => 〈ex,sx〉" by fact+ from l' have l'upd:"l'(V \<mapsto> v) = l'" by (rule map_upd_triv) from wf red l' have casts:"P \<turnstile> T casts v to v" apply - apply(erule_tac V="V" in None_lcl_casts_values) by(simp add:fun_upd_same)+ from eval obtain h'' l'' where "P,E(V \<mapsto> T) \<turnstile> 〈V:=Val v;; e'',(h',l'(V:=None))〉 => 〈e',(h'',l'')〉 ∧ s' = (h'',l''(V:=l V))" by (fastsimp elim:eval_cases simp:fun_upd_same fun_upd_idem) moreover { fix T' h0 l0 v' v'' assume eval':"P,E(V \<mapsto> T) \<turnstile> 〈e'',(h0,l0(V \<mapsto> v''))〉 => 〈e',(h'', l'')〉" and val:"P,E(V \<mapsto> T) \<turnstile> 〈Val v,(h', l'(V := None))〉 => 〈Val v',(h0,l0)〉" and env:"(E(V \<mapsto> T)) V = Some T'" and casts':"P \<turnstile> T' casts v' to v''" from env have TeqT':"T = T'" by (simp add:fun_upd_same) from val have eq:"v = v' ∧ h' = h0 ∧ l'(V := None) = l0" by -(erule eval_cases,simp) with casts casts' wf TeqT' have "v = v''" by clarsimp(rule casts_casts_eq) with eq eval' have "P,E(V \<mapsto> T) \<turnstile> 〈e'',(h', l'(V \<mapsto> v))〉 => 〈e',(h'', l'')〉" by clarsimp } ultimately have "P,E(V \<mapsto> T) \<turnstile> 〈e'',(h',l'(V \<mapsto> v))〉 => 〈e',(h'',l'')〉" and s':"s' = (h'',l''(V:=l V))" apply auto apply(erule eval_cases) apply(erule eval_cases) apply auto apply(erule eval_cases) apply auto apply(erule eval_cases) apply auto done with l'upd have eval'':"P,E(V \<mapsto> T) \<turnstile> 〈e'',(h',l')〉 => 〈e',(h'',l'')〉" by simp from IH[OF eval''] have "P,E(V \<mapsto> T) \<turnstile> 〈e,(h, l(V := None))〉 => 〈e',(h'', l'')〉" . with s' show ?case by(fastsimp intro:Block) next case (InitBlockRed E V T e h l v' e'' h' l' v'' v s' e') have eval:" P,E \<turnstile> 〈{V:T:=Val v''; e''},(h', l'(V := l V))〉 => 〈e',s'〉" and red:"P,E(V \<mapsto> T) \<turnstile> 〈e,(h, l(V \<mapsto> v'))〉 -> 〈e'',(h', l')〉" and casts:"P \<turnstile> T casts v to v'" and l':"l' V = Some v''" and IH:"!!ex sx. P,E(V \<mapsto> T) \<turnstile> 〈e'',(h', l')〉 => 〈ex,sx〉 ==> P,E(V \<mapsto> T) \<turnstile> 〈e,(h, l(V \<mapsto> v'))〉 => 〈ex,sx〉" by fact+ from l' have l'upd:"l'(V \<mapsto> v'') = l'" by (rule map_upd_triv) from wf casts have "P \<turnstile> T casts v' to v'" by(rule casts_casts) with wf red l' have casts':"P \<turnstile> T casts v'' to v''" apply - apply(erule_tac V="V" in Some_lcl_casts_values) by(simp add:fun_upd_same)+ from eval obtain h'' l'' where "P,E(V \<mapsto> T) \<turnstile> 〈V:=Val v'';; e'',(h',l'(V:=None))〉 => 〈e',(h'',l'')〉 ∧ s' = (h'',l''(V:=l V))" by (fastsimp elim:eval_cases simp:fun_upd_same fun_upd_idem) moreover { fix T' v''' assume eval':"P,E(V \<mapsto> T) \<turnstile> 〈e'',(h',l'(V \<mapsto> v'''))〉 => 〈e',(h'', l'')〉" and env:"(E(V \<mapsto> T)) V = Some T'" and casts'':"P \<turnstile> T' casts v'' to v'''" from env have "T = T'" by (simp add:fun_upd_same) with casts' casts'' wf have "v'' = v'''" by simp(rule casts_casts_eq) with eval' have "P,E(V \<mapsto> T) \<turnstile> 〈e'',(h', l'(V \<mapsto> v''))〉 => 〈e',(h'', l'')〉" by simp } ultimately have "P,E(V \<mapsto> T) \<turnstile> 〈e'',(h',l'(V \<mapsto> v''))〉 => 〈e',(h'',l'')〉" and s':"s' = (h'',l''(V:=l V))" by(auto elim!:eval_cases) with l'upd have eval'':"P,E(V \<mapsto> T) \<turnstile> 〈e'',(h',l')〉 => 〈e',(h'',l'')〉" by simp from IH[OF eval''] have evale:"P,E(V \<mapsto> T) \<turnstile> 〈e,(h, l(V \<mapsto> v'))〉 => 〈e',(h'', l'')〉" . from casts have "P,E(V \<mapsto> T) \<turnstile> 〈V:=Val v,(h,l(V:=None))〉 => 〈Val v',(h,l(V \<mapsto> v'))〉" by -(rule_tac l="l(V:=None)" in LAss, auto intro:eval_evals.intros simp:fun_upd_same) with evale s' show ?case by(fastsimp intro:Block Seq) next case (RedBlock E V T v s s' e') have "P,E \<turnstile> 〈Val v,s〉 => 〈e',s'〉" by fact then obtain s': "s'=s" and e': "e'=Val v" by cases simp obtain h l where s: "s=(h,l)" by (cases s) have "P,E(V \<mapsto> T) \<turnstile> 〈Val v,(h,l(V:=None))〉 => 〈Val v,(h,l(V:=None))〉" by (rule eval_evals.intros) hence "P,E \<turnstile> 〈{V:T;Val v},(h,l)〉 => 〈Val v,(h,(l(V:=None))(V:=l V))〉" by (rule eval_evals.Block) thus "P,E \<turnstile> 〈{V:T; Val v},s〉 => 〈e',s'〉" using s s' e' by simp next case (RedInitBlock T v v' E V u s s' e') have "P,E \<turnstile> 〈Val u,s〉 => 〈e',s'〉" and casts:"P \<turnstile> T casts v to v'" by fact+ then obtain s': "s' = s" and e': "e'=Val u" by cases simp obtain h l where s: "s=(h,l)" by (cases s) have val:"P,E(V \<mapsto> T) \<turnstile> 〈Val v,(h,l(V:=None))〉 => 〈Val v,(h,l(V:=None))〉" by (rule eval_evals.intros) with casts have "P,E(V \<mapsto> T) \<turnstile> 〈V:=Val v,(h,l(V:=None))〉 => 〈Val v',(h,l(V \<mapsto> v'))〉" by -(rule_tac l="l(V:=None)" in LAss,auto simp:fun_upd_same) hence "P,E \<turnstile> 〈{V:T :=Val v; Val u},(h,l)〉 => 〈Val u,(h, (l(V\<mapsto>v'))(V:=l V))〉" by (fastsimp intro!: eval_evals.intros) thus ?case using s s' e' by simp next case SeqRed thus ?case by (fastsimp elim: eval_cases intro: eval_evals.intros) next case RedSeq thus ?case by (fastsimp elim: eval_cases intro: eval_evals.intros) next case CondRed thus ?case by (fastsimp elim: eval_cases intro: eval_evals.intros) next case RedCondT thus ?case by (fastsimp elim: eval_cases intro: eval_evals.intros) next case RedCondF thus ?case by (fastsimp elim: eval_cases intro: eval_evals.intros) next case RedWhile thus ?case by (auto simp add: unfold_while intro:eval_evals.intros elim:eval_cases) next case ThrowRed thus ?case by (fastsimp elim: eval_cases intro: eval_evals.intros) next case RedThrowNull thus ?case by -(auto elim!:eval_cases intro!:eval_evals.ThrowNull eval_finalId) next case ListRed1 thus ?case by (fastsimp elim: evals_cases intro: eval_evals.intros) next case ListRed2 thus ?case by (fastsimp elim!: evals_cases eval_cases intro: eval_evals.intros eval_finalId) next case StaticCastThrow thus ?case by (fastsimp elim: eval_cases intro: eval_evals.intros) next case DynCastThrow thus ?case by (fastsimp elim: eval_cases intro: eval_evals.intros) next case BinOpThrow1 thus ?case by (fastsimp elim: eval_cases intro: eval_evals.intros) next case BinOpThrow2 thus ?case by (fastsimp elim: eval_cases intro: eval_evals.intros) next case LAssThrow thus ?case by (fastsimp elim: eval_cases intro: eval_evals.intros) next case FAccThrow thus ?case by (fastsimp elim: eval_cases intro: eval_evals.intros) next case FAssThrow1 thus ?case by (fastsimp elim: eval_cases intro: eval_evals.intros) next case FAssThrow2 thus ?case by (fastsimp elim: eval_cases intro: eval_evals.intros) next case CallThrowObj thus ?case by (fastsimp elim: eval_cases intro: eval_evals.intros) next case (CallThrowParams es vs r es' E v Copt M s s' e') have "P,E \<turnstile> 〈Val v,s〉 => 〈Val v,s〉" by (rule eval_evals.intros) moreover have es: "es = map Val vs @ Throw r # es'" by fact have eval_e: "P,E \<turnstile> 〈Throw r,s〉 => 〈e',s'〉" by fact then obtain s': "s' = s" and e': "e' = Throw r" by cases (auto elim!:eval_cases) with list_eval_Throw [OF eval_e] es have "P,E \<turnstile> 〈es,s〉 [=>] 〈map Val vs @ Throw r # es',s'〉" by simp ultimately have "P,E \<turnstile> 〈Call (Val v) Copt M es,s〉 => 〈Throw r,s'〉" by (rule eval_evals.CallParamsThrow) thus ?case using e' by simp next case (BlockThrow E V T r s s' e') have "P,E \<turnstile> 〈Throw r, s〉 => 〈e',s'〉" by fact then obtain s': "s' = s" and e': "e' = Throw r" by cases (auto elim!:eval_cases) obtain h l where s: "s=(h,l)" by (cases s) have "P,E(V \<mapsto> T) \<turnstile> 〈Throw r, (h,l(V:=None))〉 => 〈Throw r, (h,l(V:=None))〉" by (simp add:eval_evals.intros eval_finalId) hence "P,E \<turnstile> 〈{V:T;Throw r},(h,l)〉 => 〈Throw r, (h,(l(V:=None))(V:=l V))〉" by (rule eval_evals.Block) thus "P,E \<turnstile> 〈{V:T; Throw r},s〉 => 〈e',s'〉" using s s' e' by simp next case (InitBlockThrow T v v' E V r s s' e') have "P,E \<turnstile> 〈Throw r,s〉 => 〈e',s'〉" and casts:"P \<turnstile> T casts v to v'" by fact+ then obtain s': "s' = s" and e': "e' = Throw r" by cases (auto elim!:eval_cases) obtain h l where s: "s = (h,l)" by (cases s) have "P,E(V \<mapsto> T) \<turnstile> 〈Val v,(h,l(V:=None))〉 => 〈Val v,(h,l(V:=None))〉" by (rule eval_evals.intros) with casts have "P,E(V \<mapsto> T) \<turnstile> 〈V:=Val v,(h,l(V := None))〉 => 〈Val v',(h,l(V \<mapsto> v'))〉" by -(rule_tac l="l(V:=None)" in LAss,auto simp:fun_upd_same) hence "P,E \<turnstile> 〈{V:T := Val v; Throw r},(h,l)〉 => 〈Throw r, (h, (l(V\<mapsto>v'))(V:=l V))〉" by(fastsimp intro:eval_evals.intros) thus "P,E \<turnstile> 〈{V:T := Val v; Throw r},s〉 => 〈e',s'〉" using s s' e' by simp next case SeqThrow thus ?case by (fastsimp elim: eval_cases intro: eval_evals.intros) next case CondThrow thus ?case by (fastsimp elim: eval_cases intro: eval_evals.intros) next case ThrowThrow thus ?case by (fastsimp elim: eval_cases intro: eval_evals.intros) qed (* ... und wieder anschalten: *) declare split_paired_All [simp] split_paired_Ex [simp] declaration {* K (Classical.map_cs (fn cs => cs addSbefore ("split_all_tac", split_all_tac))) *} declaration {* K (Simplifier.map_ss (fn ss => ss addloop ("split_all_tac", split_all_tac))) *} text {* Its extension to @{text"->*"}: *} lemma extend_eval: assumes wf: "wwf_prog P" and reds: "P,E \<turnstile> 〈e,s〉 ->* 〈e'',s''〉" and eval_rest: "P,E \<turnstile> 〈e'',s''〉 => 〈e',s'〉" shows "P,E \<turnstile> 〈e,s〉 => 〈e',s'〉" using reds eval_rest apply (induct rule: converse_rtrancl_induct2) apply simp apply simp apply (rule extend_1_eval) apply (rule wf) apply assumption+ done lemma extend_evals: assumes wf: "wwf_prog P" and reds: "P,E \<turnstile> 〈es,s〉 [->]* 〈es'',s''〉" and eval_rest: "P,E \<turnstile> 〈es'',s''〉 [=>] 〈es',s'〉" shows "P,E \<turnstile> 〈es,s〉 [=>] 〈es',s'〉" using reds eval_rest apply (induct rule: converse_rtrancl_induct2) apply simp apply simp apply (rule extend_1_evals) apply (rule wf) apply assumption+ done text {* Finally, small step semantics can be simulated by big step semantics: *} theorem assumes wf: "wwf_prog P" shows small_by_big: "[|P,E \<turnstile> 〈e,s〉 ->* 〈e',s'〉; final e'|] ==> P,E \<turnstile> 〈e,s〉 => 〈e',s'〉" and "[|P,E \<turnstile> 〈es,s〉 [->]* 〈es',s'〉; finals es'|] ==> P,E \<turnstile> 〈es,s〉 [=>] 〈es',s'〉" proof - note wf moreover assume "P,E \<turnstile> 〈e,s〉 ->* 〈e',s'〉" moreover assume "final e'" then have "P,E \<turnstile> 〈e',s'〉 => 〈e',s'〉" by (rule eval_finalId) ultimately show "P,E \<turnstile> 〈e,s〉=>〈e',s'〉" by (rule extend_eval) next note wf moreover assume "P,E \<turnstile> 〈es,s〉 [->]* 〈es',s'〉" moreover assume "finals es'" then have "P,E \<turnstile> 〈es',s'〉 [=>] 〈es',s'〉" by (rule eval_finalsId) ultimately show "P,E \<turnstile> 〈es,s〉 [=>] 〈es',s'〉" by (rule extend_evals) qed section {*Equivalence*} text{* And now, the crowning achievement: *} corollary big_iff_small: "wwf_prog P ==> P,E \<turnstile> 〈e,s〉 => 〈e',s'〉 = (P,E \<turnstile> 〈e,s〉 ->* 〈e',s'〉 ∧ final e')" by(blast dest: big_by_small eval_final small_by_big) end