Theory J1JVMBisim

(*  Title:      JinjaThreads/Compiler/J1JVMBisim.thy
    Author:     Andreas Lochbihler
*)

section ‹The delay bisimulation between intermediate language and JVM›

theory J1JVMBisim imports 
  Execs
  "../BV/BVNoTypeError"
  J1
begin

declare Listn.lesub_list_impl_same_size[simp del]

lemma (in JVM_heap_conf_base') τexec_1_τexec_1_d:
  " wf_jvm_prog⇘ΦP; τexec_1 P t σ σ'; Φ |- t:σ [ok]   τexec_1_d P t σ σ'"
by(auto simp add: τexec_1_def τexec_1_d_def welltyped_commute[symmetric] elim: jvmd_NormalE)

context JVM_conf_read begin

lemma τExec_1r_preserves_correct_state:
  assumes wf: "wf_jvm_prog⇘ΦP"
  and exec: "τExec_1r P t σ σ'"
  shows "Φ |- t:σ [ok]  Φ |- t:σ' [ok]"
using exec
by(induct)(blast intro: BV_correct_1[OF wf])+

lemma τExec_1t_preserves_correct_state:
  assumes wf: "wf_jvm_prog⇘ΦP"
  and exec: "τExec_1t P t σ σ'"
  shows "Φ |- t:σ [ok]  Φ |- t:σ' [ok]"
using exec
by(induct)(blast intro: BV_correct_1[OF wf])+

lemma τExec_1r_τExec_1_dr:
  assumes wf: "wf_jvm_prog⇘ΦP"
  shows " τExec_1r P t σ σ'; Φ |- t:σ [ok]   τExec_1_dr P t σ σ'"
apply(induct rule: rtranclp_induct)
apply(blast intro: rtranclp.rtrancl_into_rtrancl τexec_1_τexec_1_d[OF wf] τExec_1r_preserves_correct_state[OF wf])+
done

lemma τExec_1t_τExec_1_dt:
  assumes wf: "wf_jvm_prog⇘ΦP"
  shows " τExec_1t P t σ σ'; Φ |- t:σ [ok]   τExec_1_dt P t σ σ'"
apply(induct rule: tranclp_induct)
apply(blast intro: tranclp.trancl_into_trancl τexec_1_τexec_1_d[OF wf] τExec_1t_preserves_correct_state[OF wf])+
done

lemma τExec_1_dr_preserves_correct_state:
  assumes wf: "wf_jvm_prog⇘ΦP"
  and exec: "τExec_1_dr P t σ σ'"
  shows "Φ |- t: σ [ok]  Φ |- t: σ' [ok]"
using exec
by(induct)(blast intro: BV_correct_1[OF wf])+

lemma τExec_1_dt_preserves_correct_state:
  assumes wf: "wf_jvm_prog⇘ΦP"
  and exec: "τExec_1_dt P t σ σ'"
  shows "Φ |- t:σ [ok]  Φ |- t:σ' [ok]"
using exec
by(induct)(blast intro: BV_correct_1[OF wf])+

end

locale J1_JVM_heap_base =
  J1_heap_base +
  JVM_heap_base +
  constrains addr2thread_id :: "('addr :: addr)  'thread_id"
  and thread_id2addr :: "'thread_id  'addr"
  and spurious_wakeups :: bool
  and empty_heap :: "'heap"
  and allocate :: "'heap  htype  ('heap × 'addr) set"
  and typeof_addr :: "'heap  'addr  htype"
  and heap_read :: "'heap  'addr  addr_loc  'addr val  bool"
  and heap_write :: "'heap  'addr  addr_loc  'addr val  'heap  bool"
begin

inductive bisim1 ::
  "'m prog  'heap  'addr expr1  ('addr expr1 × 'addr locals1)
   ('addr val list × 'addr val list × pc × 'addr option)  bool"

  and bisims1 :: 
  "'m prog  'heap  'addr expr1 list  ('addr expr1 list × 'addr locals1)
   ('addr val list × 'addr val list × pc × 'addr option)  bool"
  
  and bisim1_syntax :: 
  "'m prog  'addr expr1  'heap  ('addr expr1 × 'addr locals1)
   ('addr val list × 'addr val list × pc × 'addr option)  bool"
  (‹_,_,_  _  _› [50, 0, 0, 0, 50] 100)

  and bisims1_syntax :: 
  "'m prog  'addr expr1 list  'heap  ('addr expr1 list × 'addr locals1)
   ('addr val list × 'addr val list × pc × 'addr option)  bool"
  (‹_,_,_  _ [↔] _› [50, 0, 0, 0, 50] 100)
  for P :: "'m prog" and  h :: 'heap
where
  "P, e, h  exs  s  bisim1 P h e exs s"
| "P, es, h  esxs [↔] s  bisims1 P h es esxs s"

| bisim1Val2:
  "pc = length (compE2 e)  P, e, h  (Val v, xs)  (v # [], xs, pc, None)"

| bisim1New:
  "P, new C, h  (new C, xs)  ([], xs, 0, None)"

| bisim1NewThrow:
  "P, new C, h  (THROW OutOfMemory, xs)  ([], xs, 0, addr_of_sys_xcpt OutOfMemory)"


| bisim1NewArray:
  "P, e, h  (e', xs)  (stk, loc, pc, xcp)  P, newA Te, h  (newA Te', xs)  (stk, loc, pc, xcp)"

| bisim1NewArrayThrow:
  "P, e, h  (Throw a, xs)  (stk, loc, pc, a)  P, newA Te, h  (Throw a, xs)  (stk, loc, pc, a)"

| bisim1NewArrayFail:
  "P, newA Te, h  (Throw a, xs)  ([v], xs, length (compE2 e), a)"


| bisim1Cast:
  "P, e, h  (e', xs)  (stk, loc, pc, xcp)  P, Cast T e, h  (Cast T e', xs)  (stk, loc, pc, xcp)"

| bisim1CastThrow:
  "P, e, h  (Throw a, xs)  (stk, loc, pc, a)  P, Cast T e, h  (Throw a, xs)  (stk, loc, pc, a)"

| bisim1CastFail:
  "P, Cast T e, h  (THROW ClassCast, xs)  ([v], xs, length (compE2 e), addr_of_sys_xcpt ClassCast)"


| bisim1InstanceOf:
  "P, e, h  (e', xs)  (stk, loc, pc, xcp)  P, e instanceof T, h  (e' instanceof T, xs)  (stk, loc, pc, xcp)"

| bisim1InstanceOfThrow:
  "P, e, h  (Throw a, xs)  (stk, loc, pc, a)  P, e instanceof T, h  (Throw a, xs)  (stk, loc, pc, a)"


| bisim1Val: "P, Val v, h  (Val v, xs)  ([], xs, 0, None)"

| bisim1Var: "P, Var V, h  (Var V, xs)  ([], xs, 0, None)"


| bisim1BinOp1:
  "P, e1, h  (e', xs)  (stk, loc, pc, xcp)  P, e1«bop»e2, h  (e'«bop»e2, xs)  (stk, loc, pc, xcp)"

| bisim1BinOp2:
  "P, e2, h  (e', xs)  (stk, loc, pc, xcp)
   P, e1«bop»e2, h  (Val v1 «bop» e', xs)  (stk @ [v1], loc, length (compE2 e1) + pc, xcp)"

| bisim1BinOpThrow1:
  "P, e1, h  (Throw a, xs)  (stk, loc, pc, a)
   P, e1«bop»e2, h  (Throw a, xs)  (stk, loc, pc, a)"

| bisim1BinOpThrow2:
  "P, e2, h  (Throw a, xs)  (stk, loc, pc, a)
   P, e1«bop»e2, h  (Throw a, xs)  (stk @ [v1], loc, length (compE2 e1) + pc, a)"

| bisim1BinOpThrow:
  "P, e1«bop»e2, h  (Throw a, xs)  ([v1, v2], xs, length (compE2 e1) + length (compE2 e2), a)"

| bisim1LAss1:
  "P, e, h  (e', xs)  (stk, loc, pc, xcp)  P, V:=e, h  (V:=e', xs)  (stk, loc, pc, xcp)"

| bisim1LAss2:
  "P, V:=e, h  (unit, xs)  ([], xs, Suc (length (compE2 e)), None)"

| bisim1LAssThrow:
  "P, e, h  (Throw a, xs)  (stk, loc, pc, a)  P, V:=e, h  (Throw a, xs)  (stk, loc, pc, a)"

| bisim1AAcc1:
  "P, a, h  (a', xs)  (stk, loc, pc, xcp)
   P, ai, h  (a'i, xs)  (stk, loc, pc, xcp)"

| bisim1AAcc2:
  "P, i, h  (i', xs)  (stk, loc, pc, xcp)
   P, ai, h  (Val vi', xs)  (stk @ [v], loc, length (compE2 a) + pc, xcp)"

| bisim1AAccThrow1:
  "P, a, h  (Throw ad, xs)  (stk, loc, pc, ad)
   P, ai, h  (Throw ad, xs)  (stk, loc, pc, ad)"

| bisim1AAccThrow2:
  "P, i, h  (Throw ad, xs)  (stk, loc, pc, ad)
   P, ai, h  (Throw ad, xs)  (stk @ [v], loc, length (compE2 a) + pc, ad)"

| bisim1AAccFail:
  "P, ai, h  (Throw ad, xs)  ([v, v'], xs, length (compE2 a) + length (compE2 i), ad)"


| bisim1AAss1:
  "P, a, h  (a', xs)  (stk, loc, pc, xcp)
   P, ai := e, h  (a'i := e, xs)  (stk, loc, pc, xcp)"

| bisim1AAss2:
  "P, i, h  (i', xs)  (stk, loc, pc, xcp)
   P, ai := e, h  (Val vi' := e, xs)  (stk @ [v], loc, length (compE2 a) + pc, xcp)"

| bisim1AAss3:
  "P, e, h  (e', xs)  (stk, loc, pc, xcp)
   P, ai := e, h  (Val vVal v' := e', xs)  (stk @ [v', v], loc, length (compE2 a) + length (compE2 i) + pc, xcp)"

| bisim1AAssThrow1:
  "P, a, h  (Throw ad, xs)  (stk, loc, pc, ad)
   P, ai := e, h  (Throw ad, xs)  (stk, loc, pc, ad)"

| bisim1AAssThrow2:
  "P, i, h  (Throw ad, xs)  (stk, loc, pc, ad)
   P, ai := e, h  (Throw ad, xs)  (stk @ [v], loc, length (compE2 a) + pc, ad)"

| bisim1AAssThrow3:
  "P, e, h  (Throw ad, xs)  (stk, loc, pc, ad)
   P, ai := e, h  (Throw ad, xs)  (stk @ [v', v], loc, length (compE2 a) + length (compE2 i) + pc, ad)"

| bisim1AAssFail:
  "P, ai := e, h  (Throw ad, xs)  ([v', v, v''], xs, length (compE2 a) + length (compE2 i) + length (compE2 e), ad)"

| bisim1AAss4:
  "P, ai := e, h  (unit, xs)  ([], xs, Suc (length (compE2 a) + length (compE2 i) + length (compE2 e)), None)"


| bisim1ALength: 
  "P, a, h  (a', xs)  (stk, loc, pc, xcp)
   P, a∙length, h  (a'∙length, xs)  (stk, loc, pc, xcp)"

| bisim1ALengthThrow:
  "P, a, h  (Throw ad, xs)  (stk, loc, pc, ad)
   P, a∙length, h  (Throw ad, xs)  (stk, loc, pc, ad)"


| bisim1ALengthNull:
  "P, a∙length, h  (THROW NullPointer, xs)  ([Null], xs, length (compE2 a), addr_of_sys_xcpt NullPointer)"


| bisim1FAcc: 
  "P, e, h  (e', xs)  (stk, loc, pc, xcp)
   P, eF{D}, h  (e'F{D}, xs)  (stk, loc, pc, xcp)"

| bisim1FAccThrow:
  "P, e, h  (Throw ad, xs)  (stk, loc, pc, ad)
   P, eF{D}, h  (Throw ad, xs)  (stk, loc, pc, ad)"

| bisim1FAccNull:
  "P, eF{D}, h  (THROW NullPointer, xs)  ([Null], xs, length (compE2 e), addr_of_sys_xcpt NullPointer)"


| bisim1FAss1: 
  "P, e, h  (e', xs)  (stk, loc, pc, xcp)
   P, eF{D} := e2, h  (e'F{D} := e2, xs)  (stk, loc, pc, xcp)"

| bisim1FAss2: 
  "P, e2, h  (e', xs)  (stk, loc, pc, xcp)
   P, eF{D} := e2, h  (Val vF{D} := e', xs)  (stk @ [v], loc, length (compE2 e) + pc, xcp)"

| bisim1FAssThrow1:
  "P, e, h  (Throw ad, xs)  (stk, loc, pc, ad)
   P, eF{D} := e2, h  (Throw ad, xs)  (stk, loc, pc, ad)"

| bisim1FAssThrow2:
  "P, e2, h  (Throw ad, xs)  (stk, loc, pc, ad)
   P, eF{D} := e2, h  (Throw ad, xs)  (stk @ [v], loc, length (compE2 e) + pc, ad)"

| bisim1FAssNull:
  "P, eF{D} := e2, h  (THROW NullPointer, xs)  ([v, Null], xs, length (compE2 e) + length (compE2 e2), addr_of_sys_xcpt NullPointer)"

| bisim1FAss3:
  "P, eF{D} := e2, h  (unit, xs)  ([], xs, Suc (length (compE2 e) + length (compE2 e2)), None)"


| bisim1CAS1:
  "P, e1, h  (e1', xs)  (stk, loc, pc, xcp)
   P, e1∙compareAndSwap(DF, e2, e3), h  (e1'∙compareAndSwap(DF, e2, e3), xs)  (stk, loc, pc, xcp)"

| bisim1CAS2:
  "P, e2, h  (e2', xs)  (stk, loc, pc, xcp)
   P, e1∙compareAndSwap(DF, e2, e3), h  (Val v∙compareAndSwap(DF, e2', e3), xs)  (stk @ [v], loc, length (compE2 e1) + pc, xcp)"

| bisim1CAS3:
  "P, e3, h  (e3', xs)  (stk, loc, pc, xcp)
   P, e1∙compareAndSwap(DF, e2, e3), h  (Val v∙compareAndSwap(DF, Val v', e3'), xs)  (stk @ [v', v], loc, length (compE2 e1) + length (compE2 e2) + pc, xcp)"

| bisim1CASThrow1:
  "P, e1, h  (Throw ad, xs)  (stk, loc, pc, ad)
   P, e1∙compareAndSwap(DF, e2, e3), h  (Throw ad, xs)  (stk, loc, pc, ad)"

| bisim1CASThrow2:
  "P, e2, h  (Throw ad, xs)  (stk, loc, pc, ad)
   P, e1∙compareAndSwap(DF, e2, e3), h  (Throw ad, xs)  (stk @ [v], loc, length (compE2 e1) + pc, ad)"

| bisim1CASThrow3:
  "P, e3, h  (Throw ad, xs)  (stk, loc, pc, ad)
   P, e1∙compareAndSwap(DF, e2, e3), h  (Throw ad, xs)  (stk @ [v', v], loc, length (compE2 e1) + length (compE2 e2) + pc, ad)"

| bisim1CASFail:
  "P, e1∙compareAndSwap(DF, e2, e3), h  (Throw ad, xs)  ([v', v, v''], xs, length (compE2 e1) + length (compE2 e2) + length (compE2 e3), ad)"


| bisim1Call1:
  "P, obj, h  (obj', xs)  (stk, loc, pc, xcp)
   P, objM(ps), h  (obj'M(ps), xs)  (stk, loc, pc, xcp)"

| bisim1CallParams:
  "P, ps, h  (ps', xs) [↔] (stk, loc, pc, xcp)
   P, objM(ps), h  (Val vM(ps'), xs)  (stk @ [v], loc, length (compE2 obj) +  pc, xcp)"

| bisim1CallThrowObj:
  "P, obj, h  (Throw a, xs)  (stk, loc, pc, a)
   P, objM(ps), h  (Throw a, xs)  (stk, loc, pc, a)"

| bisim1CallThrowParams:
  "P, ps, h  (map Val vs @ Throw a # ps', xs) [↔] (stk, loc, pc, a)
   P, objM(ps), h  (Throw a, xs)  (stk @ [v], loc, length (compE2 obj) + pc, a)"

| bisim1CallThrow:
  "length ps = length vs
   P, objM(ps), h  (Throw a, xs)  (vs @ [v], xs, length (compE2 obj) + length (compEs2 ps), a)"

| bisim1BlockSome1:
  "P, {V:T=v; e}, h  ({V:T=v; e}, xs)  ([], xs, 0, None)"

| bisim1BlockSome2:
  "P, {V:T=v; e}, h  ({V:T=v; e}, xs)  ([v], xs, Suc 0, None)"

| bisim1BlockSome4:
  "P, e, h  (e', xs)  (stk, loc, pc, xcp)
   P, {V:T=v; e}, h  ({V:T=None; e'}, xs)  (stk, loc, Suc (Suc pc), xcp)"

| bisim1BlockThrowSome:
  "P, e, h  (Throw a, xs)  (stk, loc, pc, a)
   P, {V:T=v; e}, h  (Throw a, xs)  (stk, loc, Suc (Suc pc), a)"

| bisim1BlockNone:
  "P, e, h  (e', xs)  (stk, loc, pc, xcp)
   P, {V:T=None; e}, h  ({V:T=None; e'}, xs)  (stk, loc, pc, xcp)"

| bisim1BlockThrowNone:
  "P, e, h  (Throw a, xs)  (stk, loc, pc, a)
    P, {V:T=None; e}, h  (Throw a, xs)  (stk, loc, pc, a)"


| bisim1Sync1:
  "P, e1, h  (e', xs)  (stk, loc, pc, xcp)
   P, sync⇘V(e1) e2, h  (sync⇘V(e') e2, xs)  (stk, loc, pc, xcp)"

| bisim1Sync2:
  "P, sync⇘V(e1) e2, h  (sync⇘V(Val v) e2, xs)  ([v, v], xs, Suc (length (compE2 e1)), None)"

| bisim1Sync3:
  "P, sync⇘V(e1) e2, h  (sync⇘V(Val v) e2, xs)  ([v], xs[V := v], Suc (Suc (length (compE2 e1))), None)"

| bisim1Sync4:
  "P, e2, h  (e', xs)  (stk, loc, pc, xcp)
   P, sync⇘V(e1) e2, h  (insync⇘V(a) e', xs)  (stk, loc, Suc (Suc (Suc (length (compE2 e1) + pc))), xcp)"

| bisim1Sync5:
  "P, sync⇘V(e1) e2, h  (insync⇘V(a) Val v, xs)  ([xs ! V, v], xs, 4 + length (compE2 e1) + length (compE2 e2), None)"

| bisim1Sync6:
  "P, sync⇘V(e1) e2, h  (Val v, xs)  ([v], xs, 5 + length (compE2 e1) + length (compE2 e2), None)"

| bisim1Sync7:
  "P, sync⇘V(e1) e2, h  (insync⇘V(a) Throw a', xs)  ([Addr a'], xs, 6 + length (compE2 e1) + length (compE2 e2), None)"

| bisim1Sync8:
  "P, sync⇘V(e1) e2, h  (insync⇘V(a) Throw a', xs) 
                         ([xs ! V, Addr a'], xs, 7 + length (compE2 e1) + length (compE2 e2), None)"

| bisim1Sync9:
  "P, sync⇘V(e1) e2, h  (Throw a, xs)  ([Addr a], xs, 8 + length (compE2 e1) + length (compE2 e2), None)"

| bisim1Sync10:
  "P, sync⇘V(e1) e2, h  (Throw a, xs)  ([Addr a], xs, 8 + length (compE2 e1) + length (compE2 e2), a)"

| bisim1Sync11:
  "P, sync⇘V(e1) e2, h  (THROW NullPointer, xs)  ([Null], xs, Suc (Suc (length (compE2 e1))), addr_of_sys_xcpt NullPointer)"

| bisim1Sync12:
  "P, sync⇘V(e1) e2, h  (Throw a, xs)  ([v, v'], xs, 4 + length (compE2 e1) + length (compE2 e2), a)"

| bisim1Sync14:
  "P, sync⇘V(e1) e2, h  (Throw a, xs) 
        ([v, Addr a'], xs, 7 + length (compE2 e1) + length (compE2 e2), a)"

| bisim1SyncThrow:
  "P, e1, h  (Throw a, xs)  (stk, loc, pc, a)
   P, sync⇘V(e1) e2, h  (Throw a, xs)  (stk, loc, pc, a)"


| bisim1InSync: ― ‹This rule only exists such that @{text "P,e,h ⊢ (e, xs) ↔ ([], xs, 0, None)"} holds for all @{text "e"} 
  "P, insync⇘V(a) e, h  (insync⇘V(a) e, xs)  ([], xs, 0, None)"


| bisim1Seq1:
  "P, e1, h  (e', xs)  (stk, loc, pc, xcp)  P, e1;;e2, h  (e';;e2, xs)  (stk, loc, pc, xcp)"

| bisim1SeqThrow1:
  "P, e1, h  (Throw a, xs)  (stk, loc, pc, a)  P, e1;;e2, h  (Throw a, xs)  (stk, loc, pc, a)"

| bisim1Seq2:
  "P, e2, h  exs  (stk, loc, pc, xcp)
   P, e1;;e2, h  exs  (stk, loc, Suc (length (compE2 e1) + pc), xcp)"


| bisim1Cond1:
  "P, e, h  (e', xs)  (stk, loc, pc, xcp)
   P, if (e) e1 else e2, h  (if (e') e1 else e2, xs)  (stk, loc, pc, xcp)"

| bisim1CondThen:
  "P, e1, h  exs  (stk, loc, pc, xcp)
   P, if (e) e1 else e2, h  exs  (stk, loc, Suc (length (compE2 e) + pc), xcp)"

| bisim1CondElse:
  "P, e2, h  exs  (stk, loc, pc, xcp)
   P, if (e) e1 else e2, h  exs  (stk, loc, Suc (Suc (length (compE2 e) + length (compE2 e1) +  pc)), xcp)"

| bisim1CondThrow:
  "P, e, h  (Throw a, xs)  (stk, loc, pc, a)
   P, if (e) e1 else e2, h  (Throw a, xs)  (stk, loc, pc, a)"


| bisim1While1:
  "P, while (c) e, h  (while (c) e, xs)  ([], xs, 0, None)"

| bisim1While3:
  "P, c, h  (e', xs)  (stk, loc, pc, xcp)
   P, while (c) e, h  (if (e') (e;; while (c) e) else unit, xs)  (stk, loc, pc, xcp)"

| bisim1While4:
  "P, e, h  (e', xs)  (stk, loc, pc, xcp)
   P, while (c) e, h   (e';; while (c) e, xs)  (stk, loc, Suc (length (compE2 c) + pc), xcp)"

| bisim1While6:
  "P, while (c) e, h  (while (c) e, xs)  ([], xs, Suc (Suc (length (compE2 c) + length (compE2 e))), None)"

| bisim1While7:
  "P, while (c) e, h  (unit, xs)  ([], xs, Suc (Suc (Suc (length (compE2 c) + length (compE2 e)))), None)"

| bisim1WhileThrow1:
  "P, c, h  (Throw a, xs)  (stk, loc, pc, a)
   P, while (c) e, h  (Throw a, xs)  (stk, loc, pc, a)"

| bisim1WhileThrow2:
  "P, e, h  (Throw a, xs)  (stk, loc, pc, a)
    P, while (c) e, h  (Throw a, xs)  (stk, loc, Suc (length (compE2 c) + pc), a)"


| bisim1Throw1:
  "P, e, h  (e', xs)  (stk, loc, pc, xcp)  P, throw e, h  (throw e', xs)  (stk, loc, pc, xcp)"

| bisim1Throw2:
  "P, throw e, h  (Throw a, xs)  ([Addr a], xs, length (compE2 e), a)"

| bisim1ThrowNull:
  "P, throw e, h  (THROW NullPointer, xs)  ([Null], xs, length (compE2 e), addr_of_sys_xcpt NullPointer)"

| bisim1ThrowThrow:
  "P, e, h  (Throw a, xs)  (stk, loc, pc, a)  P, throw e, h  (Throw a, xs)  (stk, loc, pc, a)"


| bisim1Try:
  "P, e, h  (e', xs)  (stk, loc, pc, xcp)
    P, try e catch(C V) e2, h  (try e' catch(C V) e2, xs)  (stk, loc, pc, xcp)"

| bisim1TryCatch1:
  " P, e, h  (Throw a, xs)  (stk, loc, pc, a); typeof_addr h a = Class_type C'; P  C' * C 
   P, try e catch(C V) e2, h  ({V:Class C=None; e2}, xs[V := Addr a])  ([Addr a], loc, Suc (length (compE2 e)), None)"

| bisim1TryCatch2:
  "P, e2, h  (e', xs)  (stk, loc, pc, xcp)
    P, try e catch(C V) e2, h  ({V:Class C=None; e'}, xs)  (stk, loc, Suc (Suc (length (compE2 e) + pc)), xcp)"

| bisim1TryFail:
  " P, e, h  (Throw a, xs)  (stk, loc, pc, a); typeof_addr h a = Class_type C'; ¬ P  C' * C  
   P, try e catch(C V) e2, h  (Throw a, xs)  (stk, loc, pc, a)"

| bisim1TryCatchThrow:
  "P, e2, h  (Throw a, xs)  (stk, loc, pc, a)
    P, try e catch(C V) e2, h  (Throw a, xs)  (stk, loc, Suc (Suc (length (compE2 e) + pc)), a)"

| bisims1Nil: "P, [], h  ([], xs) [↔] ([], xs, 0, None)"

| bisims1List1:
  "P, e, h  (e', xs)  (stk, loc, pc, xcp)  P, e#es, h  (e'#es, xs) [↔] (stk, loc, pc, xcp)"

| bisims1List2:
  "P, es, h  (es', xs) [↔] (stk, loc, pc, xcp)
   P, e#es, h  (Val v # es', xs) [↔] (stk @ [v], loc, length (compE2 e) + pc, xcp)"


inductive_cases bisim1_cases:
  "P,e,h  (Val v, xs)  (stk, loc, pc, xcp)"


lemma bisim1_refl: "P,e,h  (e, xs)  ([], xs, 0, None)"
  and bisims1_refl: "P,es,h  (es, xs) [↔] ([], xs, 0, None)"
apply(induct e and es rule: call.induct calls.induct)
apply(auto intro: bisim1_bisims1.intros simp add: nat_fun_sum_eq_conv)
apply(rename_tac option a)
apply(case_tac option)
apply(auto intro: bisim1_bisims1.intros split: if_split_asm)
done

lemma bisims1_lengthD: "P, es, h  (es', xs) [↔] s  length es = length es'"
apply(induct es arbitrary: es' s)
apply(auto elim: bisims1.cases)
done

text ‹
  Derive an alternative induction rule for @{term bisim1} such that
  (i) induction hypothesis are generated for all subexpressions and
  (ii) the number of surrounding blocks is passed through.
›

inductive bisim1' :: 
  "'m prog  'heap  'addr expr1  nat  ('addr expr1 × 'addr locals1) 
   ('addr val list × 'addr val list × pc × 'addr option)  bool"

  and bisims1' :: 
  "'m prog  'heap  'addr expr1 list  nat  ('addr expr1 list × 'addr locals1)
   ('addr val list × 'addr val list × pc × 'addr option)  bool"

  and bisim1'_syntax :: 
  "'m prog  'addr expr1  nat  'heap  ('addr expr1 × 'addr locals1) 
   ('addr val list × 'addr val list × pc × 'addr option)  bool"
  (‹_,_,_,_ ⊢'' _  _› [50, 0, 0, 0, 0, 50] 100)

  and bisims1'_syntax :: 
  "'m prog  'addr expr1 list  nat  'heap  ('addr expr1 list × 'addr val list) 
   ('addr val list × 'addr val list × pc × 'addr option)  bool"
  (‹_,_,_,_ ⊢'' _ [↔] _› [50, 0, 0, 0, 0, 50] 100)
  for P :: "'m prog" and  h :: 'heap
where
  "P, e, n, h ⊢' exs  s  bisim1' P h e n exs s"
| "P, es, n, h ⊢' esxs [↔] s  bisims1' P h es n esxs s"

| bisim1Val2':
  "P, e, n, h ⊢' (Val v, xs)  (v # [], xs, length (compE2 e), None)"

| bisim1New':
  "P, new C, n, h ⊢' (new C, xs)  ([], xs, 0, None)"

| bisim1NewThrow':
  "P, new C, n, h ⊢' (THROW OutOfMemory, xs)  ([], xs, 0, addr_of_sys_xcpt OutOfMemory)"


| bisim1NewArray':
  "P, e, n, h ⊢' (e', xs)  (stk, loc, pc, xcp)
   P, newA Te, n, h ⊢' (newA Te', xs)  (stk, loc, pc, xcp)"

| bisim1NewArrayThrow':
  "P, e, n, h ⊢' (Throw a, xs)  (stk, loc, pc, a)
   P, newA Te, n, h ⊢' (Throw a, xs)  (stk, loc, pc, a)"

| bisim1NewArrayFail':
  "(xs. P, e, n, h ⊢' (e, xs)  ([], xs, 0, None))
   P, newA Te, n, h ⊢' (Throw a, xs)  ([v], xs, length (compE2 e), a)"


| bisim1Cast':
  "P, e, n, h ⊢' (e', xs)  (stk, loc, pc, xcp)
   P, Cast T e, n, h ⊢' (Cast T e', xs)  (stk, loc, pc, xcp)"

| bisim1CastThrow':
  "P, e, n, h ⊢' (Throw a, xs)  (stk, loc, pc, a)
   P, Cast T e, n, h ⊢' (Throw a, xs)  (stk, loc, pc, a)"

| bisim1CastFail':
  "(xs. P, e, n, h ⊢' (e, xs)  ([], xs, 0, None))
   P, Cast T e, n, h ⊢' (THROW ClassCast, xs)  ([v], xs, length (compE2 e), addr_of_sys_xcpt ClassCast)"


| bisim1InstanceOf':
  "P, e, n, h ⊢' (e', xs)  (stk, loc, pc, xcp)
   P, e instanceof T, n, h ⊢' (e' instanceof T, xs)  (stk, loc, pc, xcp)"

| bisim1InstanceOfThrow':
  "P, e, n, h ⊢' (Throw a, xs)  (stk, loc, pc, a)
   P, e instanceof T, n, h ⊢' (Throw a, xs)  (stk, loc, pc, a)"


| bisim1Val': "P, Val v, n, h ⊢' (Val v, xs)  ([], xs, 0, None)"

| bisim1Var': "P, Var V, n, h ⊢' (Var V, xs)  ([], xs, 0, None)"


| bisim1BinOp1':
  " P, e1, n, h ⊢' (e', xs)  (stk, loc, pc, xcp);
     xs. P, e2, n, h ⊢' (e2, xs)  ([], xs, 0, None) 
   P, e1«bop»e2, n, h ⊢' (e'«bop»e2, xs)  (stk, loc, pc, xcp)"

| bisim1BinOp2':
  " P, e2, n, h ⊢' (e', xs)  (stk, loc, pc, xcp);
     xs. P, e1, n, h ⊢' (e1, xs)  ([], xs, 0, None) 
   P, e1«bop»e2, n, h ⊢' (Val v1 «bop» e', xs)  (stk @ [v1], loc, length (compE2 e1) + pc, xcp)"

| bisim1BinOpThrow1':
  " P, e1, n, h ⊢' (Throw a, xs)  (stk, loc, pc, a);
     xs. P, e2, n, h ⊢' (e2, xs)  ([], xs, 0, None) 
   P, e1«bop»e2, n, h ⊢' (Throw a, xs)  (stk, loc, pc, a)"

| bisim1BinOpThrow2':
  " P, e2, n, h ⊢' (Throw a, xs)  (stk, loc, pc, a);
     xs. P, e1, n, h ⊢' (e1, xs)  ([], xs, 0, None) 
   P, e1«bop»e2, n, h ⊢' (Throw a, xs)  (stk @ [v1], loc, length (compE2 e1) + pc, a)"

| bisim1BinOpThrow':
  " xs. P, e1, n, h ⊢' (e1, xs)  ([], xs, 0, None); 
     xs. P, e2, n, h ⊢' (e2, xs)  ([], xs, 0, None) 
   P, e1«bop»e2, n, h ⊢' (Throw a, xs)  ([v1, v2], xs, length (compE2 e1) + length (compE2 e2), a)"

| bisim1LAss1':
  "P, e, n, h ⊢' (e', xs)  (stk, loc, pc, xcp)
   P, V:=e, n, h ⊢' (V:=e', xs)  (stk, loc, pc, xcp)"

| bisim1LAss2':
  "(xs. P, e, n, h ⊢' (e, xs)  ([], xs, 0, None))
    P, V:=e, n, h ⊢' (unit, xs)  ([], xs, Suc (length (compE2 e)), None)"

| bisim1LAssThrow':
  "P, e, n, h ⊢' (Throw a, xs)  (stk, loc, pc, a)
   P, V:=e, n, h ⊢' (Throw a, xs)  (stk, loc, pc, a)"


| bisim1AAcc1':
  " P, a, n, h ⊢' (a', xs)  (stk, loc, pc, xcp); xs. P, i, n, h ⊢' (i, xs)  ([], xs, 0, None) 
   P, ai, n, h ⊢' (a'i, xs)  (stk, loc, pc, xcp)"

| bisim1AAcc2':
  " P, i, n, h ⊢' (i', xs)  (stk, loc, pc, xcp); xs. P, a, n, h ⊢' (a, xs)  ([], xs, 0, None) 
   P, ai, n, h ⊢' (Val vi', xs)  (stk @ [v], loc, length (compE2 a) + pc, xcp)"

| bisim1AAccThrow1':
  " P, a, n, h ⊢' (Throw ad, xs)  (stk, loc, pc, ad);
     xs. P, i, n, h ⊢' (i, xs)  ([], xs, 0, None) 
   P, ai, n, h ⊢' (Throw ad, xs)  (stk, loc, pc, ad)"

| bisim1AAccThrow2':
  " P, i, n, h ⊢' (Throw ad, xs)  (stk, loc, pc, ad);
     xs. P, a, n, h ⊢' (a, xs)  ([], xs, 0, None) 
   P, ai, n, h ⊢' (Throw ad, xs)  (stk @ [v], loc, length (compE2 a) + pc, ad)"

| bisim1AAccFail':
  " xs. P, a, n, h ⊢' (a, xs)  ([], xs, 0, None); xs. P, i, n, h ⊢' (i, xs)  ([], xs, 0, None) 
   P, ai, n, h ⊢' (Throw ad, xs)  ([v, v'], xs, length (compE2 a) + length (compE2 i), ad)"


| bisim1AAss1':
  " P, a, n, h ⊢' (a', xs)  (stk, loc, pc, xcp); 
     xs. P, i, n, h ⊢' (i, xs)  ([], xs, 0, None);
     xs. P, e, n, h ⊢' (e, xs)  ([], xs, 0, None) 
   P, ai := e, n, h ⊢' (a'i := e, xs)  (stk, loc, pc, xcp)"

| bisim1AAss2':
  " P, i, n, h ⊢' (i', xs)  (stk, loc, pc, xcp);
     xs. P, a, n, h ⊢' (a, xs)  ([], xs, 0, None);
     xs. P, e, n, h ⊢' (e, xs)  ([], xs, 0, None) 
   P, ai := e, n, h ⊢' (Val vi' := e, xs)  (stk @ [v], loc, length (compE2 a) + pc, xcp)"

| bisim1AAss3':
  " P, e, n, h ⊢' (e', xs)  (stk, loc, pc, xcp); 
     xs. P, a, n, h ⊢' (a, xs)  ([], xs, 0, None);
     xs. P, i, n, h ⊢' (i, xs)  ([], xs, 0, None) 
   P, ai := e, n, h ⊢' (Val vVal v' := e', xs)  (stk @ [v', v], loc, length (compE2 a) + length (compE2 i) + pc, xcp)"

| bisim1AAssThrow1':
  " P, a, n, h ⊢' (Throw ad, xs)  (stk, loc, pc, ad);
     xs. P, i, n, h ⊢' (i, xs)  ([], xs, 0, None); 
     xs. P, e, n, h ⊢' (e, xs)  ([], xs, 0, None) 
   P, ai := e, n, h ⊢' (Throw ad, xs)  (stk, loc, pc, ad)"

| bisim1AAssThrow2':
  " P, i, n, h ⊢' (Throw ad, xs)  (stk, loc, pc, ad); 
     xs. P, a, n, h ⊢' (a, xs)  ([], xs, 0, None);
     xs. P, e, n, h ⊢' (e, xs)  ([], xs, 0, None) 
   P, ai := e, n, h ⊢' (Throw ad, xs)  (stk @ [v], loc, length (compE2 a) + pc, ad)"

| bisim1AAssThrow3':
  " P, e, n, h ⊢' (Throw ad, xs)  (stk, loc, pc, ad);
     xs. P, a, n, h ⊢' (a, xs)  ([], xs, 0, None); 
     xs. P, i, n, h ⊢' (i, xs)  ([], xs, 0, None) 
   P, ai := e, n, h ⊢' (Throw ad, xs)  (stk @ [v', v], loc, length (compE2 a) + length (compE2 i) + pc, ad)"

| bisim1AAssFail':
  " xs. P, a, n, h ⊢' (a, xs)  ([], xs, 0, None);  
     xs. P, i, n, h ⊢' (i, xs)  ([], xs, 0, None);
     xs. P, e, n, h ⊢' (e, xs)  ([], xs, 0, None) 
   P, ai := e, n, h ⊢' (Throw ad, xs)  ([v', v, v''], xs, length (compE2 a) + length (compE2 i) + length (compE2 e), ad)"

| bisim1AAss4':
  " xs. P, a, n, h ⊢' (a, xs)  ([], xs, 0, None);  
     xs. P, i, n, h ⊢' (i, xs)  ([], xs, 0, None);
     xs. P, e, n, h ⊢' (e, xs)  ([], xs, 0, None) 
   P, ai := e, n, h ⊢' (unit, xs)  ([], xs, Suc (length (compE2 a) + length (compE2 i) + length (compE2 e)), None)"


| bisim1ALength': 
  "P, a, n, h ⊢' (a', xs)  (stk, loc, pc, xcp)
   P, a∙length, n, h ⊢' (a'∙length, xs)  (stk, loc, pc, xcp)"

| bisim1ALengthThrow':
  "P, a, n, h ⊢' (Throw ad, xs)  (stk, loc, pc, ad)
   P, a∙length, n, h ⊢' (Throw ad, xs)  (stk, loc, pc, ad)"


| bisim1ALengthNull':
  "(xs. P, a, n, h ⊢' (a, xs)  ([], xs, 0, None))
   P, a∙length, n, h ⊢' (THROW NullPointer, xs)  ([Null], xs, length (compE2 a), addr_of_sys_xcpt NullPointer)"


| bisim1FAcc': 
  "P, e, n, h ⊢' (e', xs)  (stk, loc, pc, xcp)
   P, eF{D}, n, h ⊢' (e'F{D}, xs)  (stk, loc, pc, xcp)"

| bisim1FAccThrow':
  "P, e, n, h ⊢' (Throw ad, xs)  (stk, loc, pc, ad)
   P, eF{D}, n, h ⊢' (Throw ad, xs)  (stk, loc, pc, ad)"

| bisim1FAccNull':
  "(xs. P, e, n, h ⊢' (e, xs)  ([], xs, 0, None))
    P, eF{D}, n, h ⊢' (THROW NullPointer, xs)  ([Null], xs, length (compE2 e), addr_of_sys_xcpt NullPointer)"


| bisim1FAss1': 
  " P, e, n, h ⊢' (e', xs)  (stk, loc, pc, xcp); 
     xs. P, e2, n, h ⊢' (e2, xs)  ([], xs, 0, None) 
   P, eF{D} := e2, n, h ⊢' (e'F{D} := e2, xs)  (stk, loc, pc, xcp)"

| bisim1FAss2': 
  " P, e2, n, h ⊢' (e', xs)  (stk, loc, pc, xcp);
     xs. P, e, n, h ⊢' (e, xs)  ([], xs, 0, None) 
   P, eF{D} := e2, n, h ⊢' (Val vF{D} := e', xs)  (stk @ [v], loc, length (compE2 e) + pc, xcp)"

| bisim1FAssThrow1':
  " P, e, n, h ⊢' (Throw ad, xs)  (stk, loc, pc, ad);
     xs. P, e2, n, h ⊢' (e2, xs)  ([], xs, 0, None) 
   P, eF{D} := e2, n, h ⊢' (Throw ad, xs)  (stk, loc, pc, ad)"

| bisim1FAssThrow2':
  " P, e2, n, h ⊢' (Throw ad, xs)  (stk, loc, pc, ad);
     xs. P, e, n, h ⊢' (e, xs)  ([], xs, 0, None) 
   P, eF{D} := e2, n, h ⊢' (Throw ad, xs)  (stk @ [v], loc, length (compE2 e) + pc, ad)"

| bisim1FAssNull':
  " xs. P, e, n, h ⊢' (e, xs)  ([], xs, 0, None);
     xs. P, e2, n, h ⊢' (e2, xs)  ([], xs, 0, None) 
    P, eF{D} := e2, n, h ⊢' (THROW NullPointer, xs)  ([v, Null], xs, length (compE2 e) + length (compE2 e2), addr_of_sys_xcpt NullPointer)"

| bisim1FAss3':
  " xs. P, e, n, h ⊢' (e, xs)  ([], xs, 0, None); 
     xs. P, e2, n, h ⊢' (e2, xs)  ([], xs, 0, None) 
    P, eF{D} := e2, n, h ⊢' (unit, xs)  ([], xs, Suc (length (compE2 e) + length (compE2 e2)), None)"


| bisim1CAS1':
  " P, e1, n, h ⊢' (e1', xs)  (stk, loc, pc, xcp); 
    xs. P, e2, n, h ⊢' (e2, xs)  ([], xs, 0, None);
    xs. P, e3, n, h ⊢' (e3, xs)  ([], xs, 0, None) 
   P, e1∙compareAndSwap(DF, e2, e3), n, h ⊢' (e1'∙compareAndSwap(DF, e2, e3), xs)  (stk, loc, pc, xcp)"

| bisim1CAS2':
  " P, e2, n, h ⊢' (e2', xs)  (stk, loc, pc, xcp); 
    xs. P, e1, n, h ⊢' (e1, xs)  ([], xs, 0, None);
    xs. P, e3, n, h ⊢' (e3, xs)  ([], xs, 0, None) 
   P, e1∙compareAndSwap(DF, e2, e3), n, h ⊢' (Val v∙compareAndSwap(DF, e2', e3), xs)  (stk @ [v], loc, length (compE2 e1) + pc, xcp)"

| bisim1CAS3':
  " P, e3, n, h ⊢' (e3', xs)  (stk, loc, pc, xcp);
    xs. P, e1, n, h ⊢' (e1, xs)  ([], xs, 0, None);
    xs. P, e2, n, h ⊢' (e2, xs)  ([], xs, 0, None) 
   P, e1∙compareAndSwap(DF, e2, e3), n, h ⊢' (Val v∙compareAndSwap(DF, Val v', e3'), xs)  (stk @ [v', v], loc, length (compE2 e1) + length (compE2 e2) + pc, xcp)"

| bisim1CASThrow1':
  " P, e1, n, h ⊢' (Throw ad, xs)  (stk, loc, pc, ad);
    xs. P, e2, n, h ⊢' (e2, xs)  ([], xs, 0, None);
    xs. P, e3, n, h ⊢' (e3, xs)  ([], xs, 0, None) 
   P, e1∙compareAndSwap(DF, e2, e3), n, h ⊢' (Throw ad, xs)  (stk, loc, pc, ad)"

| bisim1CASThrow2':
  " P, e2, n, h ⊢' (Throw ad, xs)  (stk, loc, pc, ad);
    xs. P, e1, n, h ⊢' (e1, xs)  ([], xs, 0, None);
    xs. P, e3, n, h ⊢' (e3, xs)  ([], xs, 0, None) 
   P, e1∙compareAndSwap(DF, e2, e3), n, h ⊢' (Throw ad, xs)  (stk @ [v], loc, length (compE2 e1) + pc, ad)"

| bisim1CASThrow3':
  " P, e3, n, h ⊢' (Throw ad, xs)  (stk, loc, pc, ad);
    xs. P, e1, n, h ⊢' (e1, xs)  ([], xs, 0, None);
    xs. P, e2, n, h ⊢' (e2, xs)  ([], xs, 0, None) 
   P, e1∙compareAndSwap(DF, e2, e3), n, h ⊢' (Throw ad, xs)  (stk @ [v', v], loc, length (compE2 e1) + length (compE2 e2) + pc, ad)"

| bisim1CASFail':
  " xs. P, e1, n, h ⊢' (e1, xs)  ([], xs, 0, None);
    xs. P, e2, n, h ⊢' (e2, xs)  ([], xs, 0, None); 
    xs. P, e3, n, h ⊢' (e3, xs)  ([], xs, 0, None) 
   P, e1∙compareAndSwap(DF, e2, e3), n, h ⊢' (Throw ad, xs)  ([v', v, v''], xs, length (compE2 e1) + length (compE2 e2) + length (compE2 e3), ad)"


| bisim1Call1':
  " P, obj, n, h ⊢' (obj', xs)  (stk, loc, pc, xcp);
     xs. P, ps, n, h ⊢' (ps, xs) [↔] ([], xs, 0, None) 
   P, objM(ps), n, h ⊢' (obj'M(ps), xs)  (stk, loc, pc, xcp)"

| bisim1CallParams':
  " P, ps, n, h ⊢' (ps', xs) [↔] (stk, loc, pc, xcp); ps  [];
     xs. P, obj, n, h ⊢' (obj, xs)  ([], xs, 0, None) 
   P, objM(ps), n, h ⊢' (Val vM(ps'), xs)  (stk @ [v], loc, length (compE2 obj) +  pc, xcp)"

| bisim1CallThrowObj':
  " P, obj, n, h ⊢' (Throw a, xs)  (stk, loc, pc, a);
     xs. P, ps, n, h ⊢' (ps, xs) [↔] ([], xs, 0, None)
   P, objM(ps), n, h ⊢' (Throw a, xs)  (stk, loc, pc, a)"

| bisim1CallThrowParams':
  " P, ps, n, h ⊢' (map Val vs @ Throw a # ps', xs) [↔] (stk, loc, pc, a);
     xs. P, obj, n, h ⊢' (obj, xs)  ([], xs, 0, None) 
   P, objM(ps), n, h ⊢' (Throw a, xs)  (stk @ [v], loc, length (compE2 obj) + pc, a)"

| bisim1CallThrow':
  " length ps = length vs;
     xs. P, obj, n, h ⊢' (obj, xs)  ([], xs, 0, None); xs. P, ps, n, h ⊢' (ps, xs) [↔] ([], xs, 0, None) 
   P, objM(ps), n, h ⊢' (Throw a, xs)  (vs @ [v], xs, length (compE2 obj) + length (compEs2 ps), a)"

| bisim1BlockSome1':
  "(xs. P, e, Suc n, h ⊢' (e, xs)  ([], xs, 0, None))
   P, {V:T=v; e}, n, h ⊢' ({V:T=v; e}, xs)  ([], xs, 0, None)"

| bisim1BlockSome2':
  "(xs. P, e, Suc n, h ⊢' (e, xs)  ([], xs, 0, None))
   P, {V:T=v; e}, n, h ⊢' ({V:T=v; e}, xs)  ([v], xs, Suc 0, None)"

| bisim1BlockSome4':
  "P, e, Suc n, h ⊢' (e', xs)  (stk, loc, pc, xcp)
   P, {V:T=v; e}, n, h ⊢' ({V:T=None; e'}, xs)  (stk, loc, Suc (Suc pc), xcp)"

| bisim1BlockThrowSome':
  "P, e, Suc n, h ⊢' (Throw a, xs)  (stk, loc, pc, a)
   P, {V:T=v; e}, n, h ⊢' (Throw a, xs)  (stk, loc, Suc (Suc pc), a)"

| bisim1BlockNone':
  "P, e, Suc n, h ⊢' (e', xs)  (stk, loc, pc, xcp)
   P, {V:T=None; e}, n, h ⊢' ({V:T=None; e'}, xs)  (stk, loc, pc, xcp)"

| bisim1BlockThrowNone':
  "P, e, Suc n, h ⊢' (Throw a, xs)  (stk, loc, pc, a)
   P, {V:T=None; e}, n, h ⊢' (Throw a, xs)  (stk, loc, pc, a)"


| bisim1Sync1':
  " P, e1, n, h ⊢' (e', xs)  (stk, loc, pc, xcp); 
     xs. P, e2, Suc n, h ⊢' (e2, xs)  ([], xs, 0, None) 
   P, sync⇘V(e1) e2, n, h ⊢' (sync⇘V(e') e2, xs)  (stk, loc, pc, xcp)"

| bisim1Sync2':
  " xs. P, e1, n, h ⊢' (e1, xs)  ([], xs, 0, None);
    xs. P, e2, Suc n, h ⊢' (e2, xs)  ([], xs, 0, None) 
   P, sync⇘V(e1) e2, n, h ⊢' (sync⇘V(Val v) e2, xs)  ([v, v], xs, Suc (length (compE2 e1)), None)"

| bisim1Sync3':
  " xs. P, e1, n, h ⊢' (e1, xs)  ([], xs, 0, None);
    xs. P, e2, Suc n, h ⊢' (e2, xs)  ([], xs, 0, None) 
   P, sync⇘V(e1) e2, n, h ⊢' (sync⇘V(Val v) e2, xs)  ([v], xs[V := v], Suc (Suc (length (compE2 e1))), None)"

| bisim1Sync4':
  " P, e2, Suc n, h ⊢' (e', xs)  (stk, loc, pc, xcp); 
     xs. P, e1, n, h ⊢' (e1, xs)  ([], xs, 0, None) 
   P, sync⇘V(e1) e2, n, h ⊢' (insync⇘V(a) e', xs)  (stk, loc, Suc (Suc (Suc (length (compE2 e1) + pc))), xcp)"

| bisim1Sync5':
  " xs. P, e1, n, h ⊢' (e1, xs)  ([], xs, 0, None);
    xs. P, e2, Suc n, h ⊢' (e2, xs)  ([], xs, 0, None) 
   P, sync⇘V(e1) e2, n, h ⊢' (insync⇘V(a) Val v, xs)  ([xs ! V, v], xs, 4 + length (compE2 e1) + length (compE2 e2), None)"

| bisim1Sync6':
  " xs. P, e1, n, h ⊢' (e1, xs)  ([], xs, 0, None);
    xs. P, e2, Suc n, h ⊢' (e2, xs)  ([], xs, 0, None) 
   P, sync⇘V(e1) e2, n, h ⊢' (Val v, xs)  ([v], xs, 5 + length (compE2 e1) + length (compE2 e2), None)"

| bisim1Sync7':
  " xs. P, e1, n, h ⊢' (e1, xs)  ([], xs, 0, None);
    xs. P, e2, Suc n, h ⊢' (e2, xs)  ([], xs, 0, None) 
   P, sync⇘V(e1) e2, n, h ⊢' (insync⇘V(a) Throw a', xs)  ([Addr a'], xs, 6 + length (compE2 e1) + length (compE2 e2), None)"

| bisim1Sync8':
  " xs. P, e1, n, h ⊢' (e1, xs)  ([], xs, 0, None);
    xs. P, e2, Suc n, h ⊢' (e2, xs)  ([], xs, 0, None) 
   P, sync⇘V(e1) e2, n, h ⊢' (insync⇘V(a) Throw a', xs) 
        ([xs ! V, Addr a'], xs, 7 + length (compE2 e1) + length (compE2 e2), None)"

| bisim1Sync9':
  " xs. P, e1, n, h ⊢' (e1, xs)  ([], xs, 0, None);
    xs. P, e2, Suc n, h ⊢' (e2, xs)  ([], xs, 0, None) 
   P, sync⇘V(e1) e2, n, h ⊢' (Throw a, xs)  ([Addr a], xs, 8 + length (compE2 e1) + length (compE2 e2), None)"

| bisim1Sync10':
  " xs. P, e1, n, h ⊢' (e1, xs)  ([], xs, 0, None);
    xs. P, e2, Suc n, h ⊢' (e2, xs)  ([], xs, 0, None) 
   P, sync⇘V(e1) e2, n, h ⊢' (Throw a, xs)  ([Addr a], xs, 8 + length (compE2 e1) + length (compE2 e2), a)"

| bisim1Sync11':
  " xs. P, e1, n, h ⊢' (e1, xs)  ([], xs, 0, None);
    xs. P, e2, Suc n, h ⊢' (e2, xs)  ([], xs, 0, None) 
   P, sync⇘V(e1) e2, n, h ⊢' (THROW NullPointer, xs)  ([Null], xs, Suc (Suc (length (compE2 e1))), addr_of_sys_xcpt NullPointer)"

| bisim1Sync12':
  " xs. P, e1, n, h ⊢' (e1, xs)  ([], xs, 0, None);
    xs. P, e2, Suc n, h ⊢' (e2, xs)  ([], xs, 0, None) 
   P, sync⇘V(e1) e2, n, h ⊢' (Throw a, xs)  ([v, v'], xs, 4 + length (compE2 e1) + length (compE2 e2), a)"

| bisim1Sync14':
  " xs. P, e1, n, h ⊢' (e1, xs)  ([], xs, 0, None);
    xs. P, e2, Suc n, h ⊢' (e2, xs)  ([], xs, 0, None) 
   P, sync⇘V(e1) e2, n, h ⊢' (Throw a, xs) 
        ([v, Addr a'], xs, 7 + length (compE2 e1) + length (compE2 e2), a)"

| bisim1SyncThrow':
  " P, e1, n, h ⊢' (Throw a, xs)  (stk, loc, pc, a); 
    xs. P, e2, Suc n, h ⊢' (e2, xs)  ([], xs, 0, None) 
   P, sync⇘V(e1) e2, n, h ⊢' (Throw a, xs)  (stk, loc, pc, a)"


| bisim1InSync':
  "P, insync⇘V(a) e, n, h ⊢' (insync⇘V(a) e, xs)  ([], xs, 0, None)"


| bisim1Seq1':
  " P, e1, n, h ⊢' (e', xs)  (stk, loc, pc, xcp);
     xs. P, e2, n, h ⊢' (e2, xs)  ([], xs, 0, None) 
    P, e1;;e2, n, h ⊢' (e';;e2, xs)  (stk, loc, pc, xcp)"

| bisim1SeqThrow1':
  " P, e1, n, h ⊢' (Throw a, xs)  (stk, loc, pc, a);
     xs. P, e2, n, h ⊢' (e2, xs)  ([], xs, 0, None) 
    P, e1;;e2, n, h ⊢' (Throw a, xs)  (stk, loc, pc, a)"

| bisim1Seq2':
  " P, e2, n, h ⊢' (e', xs)  (stk, loc, pc, xcp);
     xs. P, e1, n, h ⊢' (e1, xs)  ([], xs, 0, None) 
   P, e1;;e2, n, h ⊢' (e', xs)  (stk, loc, Suc (length (compE2 e1) + pc), xcp)"


| bisim1Cond1':
  " P, e, n, h ⊢' (e', xs)  (stk, loc, pc, xcp);
     xs. P, e1, n, h ⊢' (e1, xs)  ([], xs, 0, None);
     xs. P, e2, n, h ⊢' (e2, xs)  ([], xs, 0, None) 
   P, if (e) e1 else e2, n, h ⊢' (if (e') e1 else e2, xs)  (stk, loc, pc, xcp)"

| bisim1CondThen':
  " P, e1, n, h ⊢' (e', xs)  (stk, loc, pc, xcp);
     xs. P, e, n, h ⊢' (e, xs)  ([], xs, 0, None);
     xs. P, e2, n, h ⊢' (e2, xs)  ([], xs, 0, None) 
   P, if (e) e1 else e2, n, h ⊢' (e', xs)  (stk, loc, Suc (length (compE2 e) + pc), xcp)"

| bisim1CondElse':
  " P, e2, n, h ⊢' (e', xs)  (stk, loc, pc, xcp);
     xs. P, e, n, h ⊢' (e, xs)  ([], xs, 0, None);
     xs. P, e1, n, h ⊢' (e1, xs)  ([], xs, 0, None) 
   P, if (e) e1 else e2, n, h ⊢' (e', xs)  (stk, loc, Suc (Suc (length (compE2 e) + length (compE2 e1) +  pc)), xcp)"

| bisim1CondThrow':
  " P, e, n, h ⊢' (Throw a, xs)  (stk, loc, pc, a);
     xs. P, e1, n, h ⊢' (e1, xs)  ([], xs, 0, None);
     xs. P, e2, n, h ⊢' (e2, xs)  ([], xs, 0, None) 
   P, if (e) e1 else e2, n, h ⊢' (Throw a, xs)  (stk, loc, pc, a)"


| bisim1While1':
  " xs. P, c, n, h ⊢' (c, xs)  ([], xs, 0, None);
     xs. P, e, n, h ⊢' (e, xs)  ([], xs, 0, None) 
   P, while (c) e, n, h ⊢' (while (c) e, xs)  ([], xs, 0, None)"

| bisim1While3':
  " P, c, n, h ⊢' (e', xs)  (stk, loc, pc, xcp);
     xs. P, e, n, h ⊢' (e, xs)  ([], xs, 0, None) 
   P, while (c) e, n, h ⊢' (if (e') (e;; while (c) e) else unit, xs)  (stk, loc, pc, xcp)"

| bisim1While4':
  " P, e, n, h ⊢' (e', xs)  (stk, loc, pc, xcp);
     xs. P, c, n, h ⊢' (c, xs)  ([], xs, 0, None) 
   P, while (c) e, n, h  ⊢' (e';; while (c) e, xs)  (stk, loc, Suc (length (compE2 c) + pc), xcp)"

| bisim1While6':
  " xs. P, c, n, h ⊢' (c, xs)  ([], xs, 0, None);
     xs. P, e, n, h ⊢' (e, xs)  ([], xs, 0, None)   
  P, while (c) e, n, h ⊢' (while (c) e, xs)  ([], xs, Suc (Suc (length (compE2 c) + length (compE2 e))), None)"

| bisim1While7':
  " xs. P, c, n, h ⊢' (c, xs)  ([], xs, 0, None);
     xs. P, e, n, h ⊢' (e, xs)  ([], xs, 0, None)   
  P, while (c) e, n, h ⊢' (unit, xs)  ([], xs, Suc (Suc (Suc (length (compE2 c) + length (compE2 e)))), None)"

| bisim1WhileThrow1':
  " P, c, n, h ⊢' (Throw a, xs)  (stk, loc, pc, a);
     xs. P, e, n, h ⊢' (e, xs)  ([], xs, 0, None) 
   P, while (c) e, n, h ⊢' (Throw a, xs)  (stk, loc, pc, a)"

| bisim1WhileThrow2':
  " P, e, n, h ⊢' (Throw a, xs)  (stk, loc, pc, a); 
     xs. P, c, n, h ⊢' (c, xs)  ([], xs, 0, None) 
    P, while (c) e, n, h ⊢' (Throw a, xs)  (stk, loc, Suc (length (compE2 c) + pc), a)"


| bisim1Throw1':
  "P, e, n, h ⊢' (e', xs)  (stk, loc, pc, xcp)
   P, throw e, n, h ⊢' (throw e', xs)  (stk, loc, pc, xcp)"

| bisim1Throw2':
  "(xs. P, e, n, h ⊢' (e, xs)  ([], xs, 0, None))
   P, throw e, n, h ⊢' (Throw a, xs)  ([Addr a], xs, length (compE2 e), a)"

| bisim1ThrowNull':
  "(xs. P, e, n, h ⊢' (e, xs)  ([], xs, 0, None))
   P, throw e, n, h ⊢' (THROW NullPointer, xs)  ([Null], xs, length (compE2 e), addr_of_sys_xcpt NullPointer)"

| bisim1ThrowThrow':
  "P, e, n, h ⊢' (Throw a, xs)  (stk, loc, pc, a)
   P, throw e, n, h ⊢' (Throw a, xs)  (stk, loc, pc, a)"


| bisim1Try':
  " P, e, n, h ⊢' (e', xs)  (stk, loc, pc, xcp);
     xs. P, e2, Suc n, h ⊢' (e2, xs)  ([], xs, 0, None) 
    P, try e catch(C V) e2, n, h ⊢' (try e' catch(C V) e2, xs)  (stk, loc, pc, xcp)"

| bisim1TryCatch1':
  " P, e, n, h ⊢' (Throw a, xs)  (stk, loc, pc, a); typeof_addr h a = Class_type C'; P  C' * C;
     xs. P, e2, Suc n, h ⊢' (e2, xs)  ([], xs, 0, None) 
   P, try e catch(C V) e2, n, h ⊢' ({V:Class C=None; e2}, xs[V := Addr a])  ([Addr a], loc, Suc (length (compE2 e)), None)"

| bisim1TryCatch2':
  " P, e2, Suc n, h ⊢' (e', xs)  (stk, loc, pc, xcp);
     xs. P, e, n, h ⊢' (e, xs)  ([], xs, 0, None) 
    P, try e catch(C V) e2, n, h ⊢' ({V:Class C=None; e'}, xs)  (stk, loc, Suc (Suc (length (compE2 e) + pc)), xcp)"

| bisim1TryFail':
  " P, e, n, h ⊢' (Throw a, xs)  (stk, loc, pc, a); typeof_addr h a = Class_type C'; ¬ P  C' * C;
     xs. P, e2, Suc n, h ⊢' (e2, xs)  ([], xs, 0, None)  
   P, try e catch(C V) e2, n, h ⊢' (Throw a, xs)  (stk, loc, pc, a)"

| bisim1TryCatchThrow':
  " P, e2, Suc n, h ⊢' (Throw a, xs)  (stk, loc, pc, a);
     xs. P, e, n, h ⊢' (e, xs)  ([], xs, 0, None) 
    P, try e catch(C V) e2, n, h ⊢' (Throw a, xs)  (stk, loc, Suc (Suc (length (compE2 e) + pc)), a)"

| bisims1Nil': "P, [], n, h ⊢' ([], xs) [↔] ([], xs, 0, None)"

| bisims1List1':
  " P, e, n, h ⊢' (e', xs)  (stk, loc, pc, xcp);
     xs. P, es, n, h ⊢' (es, xs) [↔] ([], xs, 0, None) 
   P, e#es, n, h ⊢' (e'#es, xs) [↔] (stk, loc, pc, xcp)"

| bisims1List2':
  " P, es, n, h ⊢' (es', xs) [↔] (stk, loc, pc, xcp);
     xs. P, e, n, h ⊢' (e, xs)  ([], xs, 0, None) 
   P, e#es, n, h ⊢' (Val v # es', xs) [↔] (stk @ [v], loc, length (compE2 e) + pc, xcp)"

lemma bisim1'_refl: "P,e,n,h ⊢' (e,xs)  ([],xs,0,None)"
  and bisims1'_refl: "P,es,n,h ⊢' (es,xs) [↔] ([],xs,0,None)"
apply(induct e and es arbitrary: n xs and n xs rule: call.induct calls.induct)
apply(auto intro: bisim1'_bisims1'.intros simp add: nat_fun_sum_eq_conv)
apply(rename_tac option a b c)
apply(case_tac option)
apply(auto intro: bisim1'_bisims1'.intros simp add: fun_eq_iff split: if_split_asm)
done

lemma bisim1_imp_bisim1': "P, e, h  exs  s  P, e, n, h ⊢' exs  s"
  and bisims1_imp_bisims1': "P, es, h  esxs [↔] s  P, es, n, h ⊢' esxs [↔] s"
proof(induct arbitrary: n and n rule: bisim1_bisims1.inducts)
  case (bisim1CallParams ps ps' xs stk loc pc xcp obj M v)
  show ?case
  proof(cases "ps = []")
    case True
    with P,ps,h  (ps', xs) [↔] (stk, loc, pc, xcp) have "ps' = []" "pc = 0" "stk = []" "loc = xs" "xcp = None"
      by(auto elim: bisims1.cases)
    moreover have "P,obj,n,h ⊢' (Val v,xs)  ([v],xs,length (compE2 obj),None)"
      by(blast intro: bisim1Val2' bisim1'_refl)
    hence "P,objM([]),n,h ⊢' (Val vM([]),xs)  ([v],xs,length (compE2 obj),None)"
      by-(rule bisim1Call1', auto intro!: bisims1Nil' simp add: bsoks_def)
    ultimately show ?thesis using True by simp
  next
    case False with bisim1CallParams show ?thesis
      by(auto intro: bisim1CallParams' bisims1'_refl bisim1'_refl)
  qed
qed(auto intro: bisim1'_bisims1'.intros bisim1'_refl bisims1'_refl)

lemma bisim1'_imp_bisim1: "P, e, n, h ⊢' exs  s  P, e, h  exs  s"
  and bisims1'_imp_bisims1: "P, es, n, h ⊢' esxs [↔] s  P, es, h  esxs [↔] s"
apply(induct rule: bisim1'_bisims1'.inducts)
apply(blast intro: bisim1_bisims1.intros)+
done

lemma bisim1'_eq_bisim1: "bisim1' P h e n = bisim1 P h e"
  and bisims1'_eq_bisims1: "bisims1' P h es n = bisims1 P h es"
by(blast intro!: ext bisim1_imp_bisim1' bisims1_imp_bisims1' bisim1'_imp_bisim1 bisims1'_imp_bisims1)+

end

(* FIXME: Take lemmas out of locale to speed up opening the context *)

lemmas bisim1_bisims1_inducts = 
  J1_JVM_heap_base.bisim1'_bisims1'.inducts
  [simplified J1_JVM_heap_base.bisim1'_eq_bisim1 J1_JVM_heap_base.bisims1'_eq_bisims1, 
  consumes 1,
  case_names bisim1Val2 bisim1New bisim1NewThrow
  bisim1NewArray bisim1NewArrayThrow bisim1NewArrayFail bisim1Cast bisim1CastThrow bisim1CastFail
  bisim1InstanceOf bisim1InstanceOfThrow
  bisim1Val bisim1Var bisim1BinOp1 bisim1BinOp2 bisim1BinOpThrow1 bisim1BinOpThrow2 bisim1BinOpThrow
  bisim1LAss1 bisim1LAss2 bisim1LAssThrow
  bisim1AAcc1 bisim1AAcc2 bisim1AAccThrow1 bisim1AAccThrow2 bisim1AAccFail
  bisim1AAss1 bisim1AAss2 bisim1AAss3 bisim1AAssThrow1 bisim1AAssThrow2
  bisim1AAssThrow3 bisim1AAssFail bisim1AAss4
  bisim1ALength bisim1ALengthThrow bisim1ALengthNull
  bisim1FAcc bisim1FAccThrow bisim1FAccNull
  bisim1FAss1 bisim1FAss2 bisim1FAssThrow1 bisim1FAssThrow2 bisim1FAssNull bisim1FAss3
  bisim1CAS1 bisim1CAS2 bisim1CAS3 bisim1CASThrow1 bisim1CASThrow2
  bisim1CASThrow3 bisim1CASFail
  bisim1Call1 bisim1CallParams bisim1CallThrowObj bisim1CallThrowParams
  bisim1CallThrow
  bisim1BlockSome1 bisim1BlockSome2 bisim1BlockSome4 bisim1BlockThrowSome
  bisim1BlockNone bisim1BlockThrowNone
  bisim1Sync1 bisim1Sync2 bisim1Sync3 bisim1Sync4 bisim1Sync5 bisim1Sync6
  bisim1Sync7 bisim1Sync8 bisim1Sync9 bisim1Sync10 bisim1Sync11 bisim1Sync12
  bisim1Sync14 bisim1SyncThrow bisim1InSync
  bisim1Seq1 bisim1SeqThrow1 bisim1Seq2
  bisim1Cond1 bisim1CondThen bisim1CondElse bisim1CondThrow
  bisim1While1 bisim1While3 bisim1While4
  bisim1While6 bisim1While7 bisim1WhileThrow1 bisim1WhileThrow2
  bisim1Throw1 bisim1Throw2 bisim1ThrowNull bisim1ThrowThrow
  bisim1Try bisim1TryCatch1 bisim1TryCatch2 bisim1TryFail bisim1TryCatchThrow
  bisims1Nil bisims1List1 bisims1List2]

lemmas bisim1_bisims1_inducts_split = bisim1_bisims1_inducts[split_format (complete)]

context J1_JVM_heap_base begin

lemma bisim1_pc_length_compE2: "P,E,h  (e, xs)  (stk, loc, pc, xcp)  pc  length (compE2 E)"
  and bisims1_pc_length_compEs2: "P,Es,h  (es, xs) [↔] (stk, loc, pc, xcp)  pc  length (compEs2 Es)"
apply(induct "(stk, loc, pc, xcp)" and "(stk, loc, pc, xcp)" 
  arbitrary: stk loc pc xcp and stk loc pc xcp rule: bisim1_bisims1.inducts)
apply(auto)
done

lemma bisim1_pc_length_compE2D:
  "P,e,h  (e', xs)  (stk,loc,length (compE2 e),xcp)
   xcp = None  call1 e' = None  (v. stk = [v]  (is_val e'  e' = Val v  xs = loc))"

  and bisims1_pc_length_compEs2D:
  "P,es,h  (es', xs) [↔] (stk,loc,length (compEs2 es),xcp)
   xcp = None  calls1 es' = None  (vs. stk = rev vs  length vs = length es  (is_vals es'  es' = map Val vs  xs = loc))"
proof(induct "(e', xs)" "(stk, loc, length (compE2 e), xcp)"
        and "(es', xs)" "(stk, loc, length (compEs2 es), xcp)" 
 arbitrary: e' xs stk loc xcp and es' xs stk loc xcp rule: bisim1_bisims1.inducts)
  case (bisims1List2 es es' xs stk loc pc xcp e v)
  then obtain vs where "xcp = None" "calls1 es' = None" 
    "stk = rev vs" "length vs = length es" "is_vals es'  es' = map Val vs  xs = loc" by auto
  thus ?case
    by(clarsimp)(rule_tac x="v#vs" in exI, auto)
qed(simp_all (no_asm_use), (fastforce dest: bisim1_pc_length_compE2 bisims1_pc_length_compEs2 split: bop.split_asm if_split_asm)+)

corollary bisim1_call_pcD: " P,e,h  (e', xs)  (stk, loc, pc, xcp); call1 e' = aMvs   pc < length (compE2 e)"
  and bisims1_calls_pcD: " P,es,h  (es', xs) [↔] (stk, loc, pc, xcp); calls1 es' = aMvs   pc < length (compEs2 es)"
proof -
  assume bisim: "P,e,h  (e', xs)  (stk, loc, pc, xcp)"
    and call: "call1 e' = aMvs"

  { assume "pc = length (compE2 e)"
    with bisim call have False
      by(auto dest: bisim1_pc_length_compE2D) }
  moreover from bisim have "pc  length (compE2 e)"
    by(rule bisim1_pc_length_compE2)
  ultimately show "pc < length (compE2 e)"
    by(cases "pc < length (compE2 e)")(auto)
next
  assume bisim: "P,es,h  (es', xs) [↔] (stk, loc, pc, xcp)"
    and call: "calls1 es' = aMvs"
  { assume "pc = length (compEs2 es)"
    with bisim call have False
      by(auto dest: bisims1_pc_length_compEs2D) }
  moreover from bisim have "pc  length (compEs2 es)"
    by(rule bisims1_pc_length_compEs2)
  ultimately show "pc < length (compEs2 es)"
    by(cases "pc < length (compEs2 es)")(auto)
qed

lemma bisim1_length_xs: "P,e,h  (e',xs)  (stk, loc, pc, xcp)  length xs = length loc"
  and bisims1_length_xs: "P,es,h  (es',xs) [↔] (stk, loc, pc, xcp)  length xs = length loc"
by(induct "(e',xs)" "(stk, loc, pc, xcp)" and "(es',xs)" "(stk, loc, pc, xcp)"
  arbitrary: e' xs stk loc pc xcp and es' xs stk loc pc xcp rule: bisim1_bisims1.inducts)
  auto

lemma bisim1_Val_length_compE2D:
  "P,e,h  (Val v,xs)  (stk, loc, length (compE2 e), xcp)  stk = [v]  xs = loc  xcp = None"

  and bisims1_Val_length_compEs2D:
  "P,es,h  (map Val vs,xs) [↔] (stk, loc, length (compEs2 es), xcp)  stk = rev vs  xs = loc  xcp = None"
by(auto dest: bisim1_pc_length_compE2D bisims1_pc_length_compEs2D)

lemma bisim_Val_loc_eq_xcp_None:
  "P, e, h  (Val v, xs)  (stk, loc, pc, xcp)  xs = loc  xcp = None"

  and bisims_Val_loc_eq_xcp_None:
  "P, es, h  (map Val vs, xs) [↔] (stk, loc, pc, xcp)  xs = loc  xcp = None"
apply(induct "(Val v :: 'addr expr1, xs)" "(stk, loc, pc, xcp)" 
  and "(map Val vs :: 'addr expr1 list, xs)" "(stk, loc, pc, xcp)"
  arbitrary: v xs stk loc pc xcp and vs xs stk loc pc xcp rule: bisim1_bisims1.inducts)
apply(auto)
done

lemma bisim_Val_pc_not_Invoke: 
  " P,e,h  (Val v,xs)  (stk,loc,pc,xcp); pc < length (compE2 e)   compE2 e ! pc  Invoke M n'"

  and bisims_Val_pc_not_Invoke: 
  " P,es,h  (map Val vs,xs) [↔] (stk,loc,pc,xcp); pc < length (compEs2 es)   compEs2 es ! pc  Invoke M n'"
apply(induct "(Val v :: 'addr expr1, xs)" "(stk, loc, pc, xcp)"
         and "(map Val vs :: 'addr expr1 list, xs)" "(stk, loc, pc, xcp)"
  arbitrary: v xs stk loc pc xcp and vs xs stk loc pc xcp rule: bisim1_bisims1.inducts)
apply(auto simp add: nth_append compEs2_map_Val dest: bisim1_pc_length_compE2)
done

lemma bisim1_VarD: "P, E, h  (Var V,xs)  (stk,loc,pc,xcp)  xs = loc"
  and "P, es, h  (es', xs) [↔] (stk, loc, pc, xcp)  True"
by(induct "(Var V :: 'addr expr1, xs)" "(stk, loc, pc, xcp)" and arbitrary: V xs stk loc pc xcp and rule: bisim1_bisims1.inducts) auto

lemma bisim1_ThrowD:
  "P, e, h  (Throw a, xs)  (stk, loc, pc, xcp)
   pc < length (compE2 e)  (xcp = a  xcp = None)  xs = loc"

  and bisims1_ThrowD:
  "P, es, h  (map Val vs @ Throw a # es', xs) [↔] (stk, loc, pc, xcp)
   pc < length (compEs2 es)  (xcp = a  xcp = None)  xs = loc"
apply(induct "(Throw a :: 'addr expr1, xs)" "(stk, loc, pc, xcp)"
         and "(map Val vs @ Throw a # es', xs)" "(stk, loc, pc, xcp)"
         arbitrary: xs stk loc pc xcp and vs es' xs stk loc pc xcp rule: bisim1_bisims1.inducts)
apply(fastforce dest: bisim1_pc_length_compE2 bisim_Val_loc_eq_xcp_None simp add: Cons_eq_append_conv)+
done

lemma fixes P :: "'addr J1_prog"
  shows bisim1_Invoke_stkD:
  " P,e,h  exs  (stk,loc,pc,None); pc < length (compE2 e); compE2 e ! pc = Invoke M n'  
   vs v stk'. stk = vs @ v # stk'  length vs = n'"

  and bisims1_Invoke_stkD: 
  " P,es,h  esxs [↔] (stk,loc,pc,None); pc < length (compEs2 es); compEs2 es ! pc = Invoke M n' 
   vs v stk'. stk = vs @ v # stk'  length vs = n'"
proof(induct "(stk, loc, pc, None :: 'addr option)" and "(stk, loc, pc, None :: 'addr option)"
    arbitrary: stk loc pc and stk loc pc rule: bisim1_bisims1.inducts)
  case bisim1Call1
  thus ?case
    apply(clarsimp simp add: nth_append append_eq_append_conv2 neq_Nil_conv split: if_split_asm)
    apply(drule bisim1_pc_length_compE2, clarsimp simp add: neq_Nil_conv nth_append)
    apply(frule bisim1_pc_length_compE2, clarsimp)
    apply(drule bisim1_pc_length_compE2D, fastforce)
    done
next
  case bisim1CallParams thus ?case
    apply(clarsimp simp add: nth_append append_eq_Cons_conv split: if_split_asm)
    apply(fastforce simp add: append_eq_append_conv2 Cons_eq_append_conv)
    apply(frule bisims1_pc_length_compEs2, clarsimp)
    apply(drule bisims1_pc_length_compEs2D, fastforce simp add: append_eq_append_conv2)
    done
qed(fastforce simp add: nth_append append_eq_append_conv2 neq_Nil_conv split: if_split_asm bop.split_asm dest: bisim1_pc_length_compE2 bisims1_pc_length_compEs2)+

lemma fixes P :: "'addr J1_prog"
  shows bisim1_call_xcpNone: "P,e,h  (e',xs)  (stk,loc,pc,a)  call1 e' = None"
  and bisims1_calls_xcpNone: "P,es,h  (es',xs) [↔] (stk,loc,pc,a)  calls1 es' = None"
apply(induct "(e', xs)" "(stk, loc, pc, a :: 'addr)" and "(es',xs)" "(stk, loc, pc, a :: 'addr)"
  arbitrary: e' xs stk loc pc and es' xs stk loc pc rule: bisim1_bisims1.inducts)
apply(auto dest: bisim_Val_loc_eq_xcp_None bisims_Val_loc_eq_xcp_None simp add: is_vals_conv)
done

lemma bisims1_map_Val_append:
  assumes bisim: "P, es', h  (es'', xs) [↔] (stk, loc, pc, xcp)"
  shows "length es = length vs
           P, es @ es', h  (map Val vs @ es'', xs) [↔] (stk @ rev vs, loc, length (compEs2 es) + pc, xcp)"
proof(induction vs arbitrary: es)
  case Nil thus ?case using bisim by simp
next
  case (Cons v vs)
  from length es = length (v # vs) obtain e es''' where [simp]: "es = e # es'''" by(cases es, auto)
  with length es = length (v # vs) have len: "length es''' = length vs" by simp
  from Cons.IH[OF len]
  show ?case by(simp add: add.assoc append_assoc[symmetric] del: append_assoc)(rule bisims1List2, auto)
qed

lemma bisim1_hext_mono: " P,e,h  exs  s; hext h h'   P,e,h'  exs  s" (is "PROP ?thesis1")
  and bisims1_hext_mono: " P,es,h  esxs [↔] s; hext h h'   P,es,h'  esxs [↔] s" (is "PROP ?thesis2")
proof -
  assume hext: "hext h h'"
  have "P,e,h  exs  s  P,e,h'  exs  s"
    and "P,es,h  esxs [↔] s  P,es,h'  esxs [↔] s"
    apply(induct rule: bisim1_bisims1.inducts)
    apply(insert hext)
    apply(auto intro: bisim1_bisims1.intros dest: hext_objD)
    done
  thus "PROP ?thesis1" and "PROP ?thesis2" by auto
qed

declare match_ex_table_append_not_pcs [simp]
       match_ex_table_eq_NoneI[simp]
       outside_pcs_compxE2_not_matches_entry[simp]
       outside_pcs_compxEs2_not_matches_entry[simp]

lemma bisim1_xcp_Some_not_caught:
  "P, e, h  (Throw a, xs)  (stk, loc, pc, a)
   match_ex_table (compP f P) (cname_of h a) (pc' + pc) (compxE2 e pc' d) = None"

  and bisims1_xcp_Some_not_caught:
  "P, es, h  (map Val vs @ Throw a # es', xs) [↔] (stk, loc, pc, a)
   match_ex_table (compP f P) (cname_of h a) (pc' + pc) (compxEs2 es pc' d) = None"
proof(induct "(Throw a :: 'addr expr1, xs)" "(stk, loc, pc, a :: 'addr)" 
    and "(map Val vs @ Throw a # es' :: 'addr expr1 list, xs)" "(stk, loc, pc, a :: 'addr)"
    arbitrary: xs stk loc pc pc' d and xs stk loc pc vs es' pc' d rule: bisim1_bisims1.inducts)
  case bisim1Sync10
  thus ?case by(simp add: matches_ex_entry_def)
next
  case bisim1Sync11
  thus ?case by(simp add: matches_ex_entry_def)
next
  case (bisim1SyncThrow e1 xs stk loc pc e2)
  note IH = match_ex_table (compP f P) (cname_of h a) (pc' + pc) (compxE2 e1 pc' d) = None
  from P,e1,h  (Throw a,xs)  (stk,loc,pc,a) have "pc < length (compE2 e1)" by(auto dest: bisim1_ThrowD)
  with IH show ?case
    by(auto simp add: match_ex_table_append matches_ex_entry_def dest: match_ex_table_pc_length_compE2 intro: match_ex_table_not_pcs_None)
next
  case bisims1List1 thus ?case
    by(auto simp add: Cons_eq_append_conv dest: bisim1_ThrowD bisim_Val_loc_eq_xcp_None)
next
  case (bisims1List2 es es'' xs stk loc pc e v)
  hence "pc' d. match_ex_table (compP f P) (cname_of h a) (pc' + pc) (compxEs2 es pc' d) = None"
    by(auto simp add: Cons_eq_append_conv)
  from this[of "pc' + length (compE2 e)" "Suc d"] show ?case by(auto simp add: add.assoc)
next
  case (bisim1BlockThrowSome e xs stk loc pc T v)
  hence "pc'. match_ex_table (compP f P) (cname_of h a) (pc' + pc) (compxE2 e pc' d) = None" by auto
  from this[of "2+pc'"] show ?case by(auto)
next
  case (bisim1Seq2 e2 stk loc pc e1 xs)
  hence "pc'. match_ex_table (compP f P) (cname_of h a) (pc' + pc) (compxE2 e2 pc' d) = None" by auto
  from this[of "Suc (pc' + length (compE2 e1))"] show ?case by(simp add: add.assoc)
next
  case (bisim1CondThen e1 stk loc pc e e2 xs)
  hence "pc'. match_ex_table (compP f P) (cname_of h a) (pc' + pc) (compxE2 e1 pc' d) = None" by auto
  note this[of "Suc (pc' + length (compE2 e))"]
  moreover from P,e1,h  (Throw a,xs)  (stk,loc,pc,a)
  have "pc < length (compE2 e1)" by(auto dest: bisim1_ThrowD)
  ultimately show ?case by(simp add: add.assoc match_ex_table_eq_NoneI outside_pcs_compxE2_not_matches_entry)
next
  case (bisim1CondElse e2 stk loc pc e e1 xs)
  hence "pc'. match_ex_table (compP f P) (cname_of h a) (pc' + pc) (compxE2 e2 pc' d) = None" by auto
  note this[of "Suc (Suc (pc' + (length (compE2 e) + length (compE2 e1))))"]
  thus ?case by(simp add: add.assoc)
next
  case (bisim1WhileThrow2 e xs stk loc pc c)
  hence "pc'. match_ex_table (compP f P) (cname_of h a) (pc' + pc) (compxE2 e pc' d) = None" by auto
  from this[of "Suc (pc' + (length (compE2 c)))"]
  show ?case by(simp add: add.assoc)
next
  case (bisim1Throw1 e xs stk loc pc)
  thus ?case by(auto dest: bisim_Val_loc_eq_xcp_None)
next
  case (bisim1TryFail e xs stk loc pc C' C e2)
  hence "match_ex_table (compP f P) (cname_of h a) (pc' + pc) (compxE2 e pc' d) = None" by auto
  moreover from P,e,h  (Throw a,xs)  (stk,loc,pc,a) have "pc < length (compE2 e)"
    by(auto dest: bisim1_ThrowD)
  ultimately show ?case using typeof_addr h a = Class_type C' ¬ P  C' * C
    by(simp add: matches_ex_entry_def cname_of_def)
next
  case (bisim1TryCatchThrow e2 xs stk loc pc e C)
  hence "pc'. match_ex_table (compP f P) (cname_of h a) (pc' + pc) (compxE2 e2 pc' d) = None" by auto
  from this[of "Suc (Suc (pc' + (length (compE2 e))))"]
  show ?case by(simp add: add.assoc matches_ex_entry_def)
next
  case bisim1Sync12 thus ?case
    by(auto dest: bisim1_ThrowD simp add: match_ex_table_append eval_nat_numeral, simp add: matches_ex_entry_def)
next
  case bisim1Sync14 thus ?case
    by(auto dest: bisim1_ThrowD simp add: match_ex_table_append eval_nat_numeral, simp add: matches_ex_entry_def)
qed(fastforce dest: bisim1_ThrowD simp add: add.assoc[symmetric])+

declare match_ex_table_append_not_pcs [simp del]
       match_ex_table_eq_NoneI[simp del]
       outside_pcs_compxE2_not_matches_entry[simp del]
       outside_pcs_compxEs2_not_matches_entry[simp del]

lemma bisim1_xcp_pcD: "P,e,h  (e', xs)  (stk, loc, pc, a)  pc < length (compE2 e)"
  and bisims1_xcp_pcD: "P,es,h  (es', xs) [↔] (stk, loc, pc, a)  pc < length (compEs2 es)"
by(induct "(e', xs)" "(stk, loc, pc, a :: 'addr)" and "(es', xs)" "(stk, loc, pc, a :: 'addr)"
  arbitrary: e' xs stk loc pc and es' xs stk loc pc rule: bisim1_bisims1.inducts)
  auto

declare nth_append [simp]

lemma bisim1_Val_τExec_move:
  " P, E, h  (Val v, xs)  (stk, loc, pc, xcp); pc < length (compE2 E)  
   xs = loc  xcp = None 
     τExec_mover_a P t E h (stk, xs, pc, None) ([v], xs, length (compE2 E), None)"

 and bisims1_Val_τExec_moves:
  " P, Es, h  (map Val vs, xs) [↔] (stk, loc, pc, xcp); pc < length (compEs2 Es)  
   xs = loc  xcp = None 
    τExec_movesr_a P t Es h (stk, xs, pc, None) (rev vs, xs, length (compEs2 Es), None)"
proof(induct "(Val v :: 'addr expr1, xs)" "(stk, loc, pc, xcp)" 
    and "(map Val vs :: 'addr expr1 list, xs)" "(stk, loc, pc, xcp)"
    arbitrary: v xs stk loc pc xcp and vs xs stk loc pc xcp rule: bisim1_bisims1.inducts)
  case bisim1Val thus ?case by(auto intro!: τExecr1step exec_instr τmove2Val simp add: exec_move_def)
next
  case (bisim1LAss2 V e xs)
  have "τExec_mover_a P t (V:=e) h ([], xs, Suc (length (compE2 e)), None) ([Unit], xs, Suc (Suc (length (compE2 e))), None)"
    by(auto intro!: τExecr1step exec_instr τmove2LAssRed2 simp add: exec_move_def)
  with bisim1LAss2 show ?case by simp
next
  case (bisim1AAss4 a i e xs)
  have "τExec_mover_a P t (ai := e) h ([], xs, Suc (length (compE2 a) + length (compE2 i) + length (compE2 e)), None) ([Unit], xs, Suc (Suc (length (compE2 a) + length (compE2 i) + length (compE2 e))), None)"
    by(auto intro!: τExecr1step exec_instr τmove2AAssRed simp add: exec_move_def)
  with bisim1AAss4 show ?case by(simp add: ac_simps)
next
  case (bisim1FAss3 e F D e2 xs)
  have "τExec_mover_a P t (eF{D} := e2) h ([], xs, Suc (length (compE2 e) + length (compE2 e2)), None) ([Unit], xs, Suc (Suc (length (compE2 e) + length (compE2 e2))), None)"
    by(auto intro!: τExecr1step exec_instr τmove2FAssRed simp add: exec_move_def)
  with bisim1FAss3 show ?case by simp
next
  case (bisim1Sync6 V e1 e2 v xs)
  have "τExec_mover_a P t (sync⇘V(e1) e2) h ([v], xs, 5 + length (compE2 e1) + length (compE2 e2), None)
                                        ([v], xs, 9 + length (compE2 e1) + length (compE2 e2), None)"
    by(rule τExecr1step)(auto intro: exec_instr τmove2Sync6 simp add: exec_move_def)
  with bisim1Sync6 show ?case by(auto simp add: eval_nat_numeral)
next
  case (bisim1Seq2 e2 stk loc pc xcp e1 v xs)
  from Suc (length (compE2 e1) + pc) < length (compE2 (e1;; e2)) have pc: "pc < length (compE2 e2)" by simp
  with pc < length (compE2 e2)  xs = loc  xcp = None  τExec_mover_a P t e2 h (stk, xs, pc, None) ([v], xs, length (compE2 e2), None)
  have "xs = loc" "xcp = None"
    "τExec_mover_a P t e2 h (stk, xs, pc, None) ([v], xs, length (compE2 e2), None)" by auto
  moreover 
  hence "τExec_mover_a P t (e1;;e2) h (stk, xs, Suc (length (compE2 e1) + pc), None) ([v], xs, Suc (length (compE2 e1) + length (compE2 e2)), None)"
    by -(rule Seq_τExecrI2)
  ultimately show ?case by(simp)
next
  case (bisim1CondThen e1 stk loc pc xcp e e2 v xs)
  from P, e1, h  (Val v,xs)  (stk,loc,pc,xcp)
  have "pc  length (compE2 e1)" by(rule bisim1_pc_length_compE2)

  have e: "τExec_mover_a P t (if (e) e1 else e2) h
                     ([v], xs, Suc (length (compE2 e) + (length (compE2 e1))), None)
                     ([v], xs, length (compE2 (if (e) e1 else e2)), None)" 
    by(rule τExecr1step)(auto simp add: exec_move_def intro!: exec_instr τmove2CondThenExit)
  show ?case
  proof(cases "pc < length (compE2 e1)")
    case True
    with pc < length (compE2 e1)
          xs = loc  xcp = None  τExec_mover_a P t e1 h (stk, xs, pc, None) ([v], xs, length (compE2 e1), None)
    have s: "xs = loc" "xcp = None"
      and "τExec_mover_a P t e1 h (stk, xs, pc, None) ([v], xs, length (compE2 e1), None)" by auto
    hence "τExec_mover_a P t (if (e) e1 else e2) h
                     (stk, xs, Suc (length (compE2 e) + pc), None)
                     ([v], xs, Suc (length (compE2 e) + length (compE2 e1)), None)"
      by -(rule Cond_τExecrI2)
    with e True s show ?thesis by(simp)
  next
    case False
    with pc  length (compE2 e1) have pc: "pc = length (compE2 e1)" by auto
    with P, e1, h  (Val v,xs)  (stk,loc,pc,xcp)
    have "stk = [v]" "xs = loc" "xcp = None" by(auto dest: bisim1_Val_length_compE2D)
    with pc e show ?thesis by(simp)
  qed
next
  case (bisim1CondElse e2 stk loc pc xcp e e1 v xs)
  from P, e2, h  (Val v,xs)  (stk,loc,pc,xcp)
  have "pc  length (compE2 e2)" by(rule bisim1_pc_length_compE2)

  show ?case
  proof(cases "pc < length (compE2 e2)")
    case True
    with pc < length (compE2 e2)
          xs = loc  xcp = None  τExec_mover_a P t e2 h (stk, xs, pc, None) ([v], xs, length (compE2 e2), None)
    have s: "xs = loc" "xcp = None"
      and e: "τExec_mover_a P t e2 h (stk, xs, pc, None) ([v], xs, length (compE2 e2), None)" by auto
    from e have "τExec_mover_a P t (if (e) e1 else e2) h (stk, xs, Suc (Suc (length (compE2 e) + length (compE2 e1) + pc)), None) ([v], xs, Suc (Suc (length (compE2 e) + length (compE2 e1) + length (compE2 e2))), None)"
      by(rule Cond_τExecrI3)
    with True s show ?thesis by(simp add: add.assoc)
  next
    case False
    with pc  length (compE2 e2) have pc: "pc = length (compE2 e2)" by auto
    with P, e2, h  (Val v,xs)  (stk,loc,pc,xcp)
    have "stk = [v]" "xs = loc" "xcp = None" by(auto dest: bisim1_Val_length_compE2D)
    with pc show ?thesis by(simp add: add.assoc)
  qed
next
  case (bisim1While7 c e xs)
  have "τExec_mover_a P t (while (c) e) h
                   ([], xs, Suc (Suc (Suc (length (compE2 c) + length (compE2 e)))), None)
                   ([Unit], xs, length (compE2 (while (c) e)), None)"
    by(auto intro!: τExecr1step exec_instr τmove2While4 simp add: exec_move_def)
  thus ?case by(simp)
next
  case (bisims1List1 e e' xs stk loc pc xcp es)
  from e' # es = map Val vs obtain v vs' where [simp]: "vs = v # vs'" "e' = Val v" "es = map Val vs'" by auto
  from P,e,h  (e',xs)  (stk,loc,pc,xcp)
  have length: "pc  length (compE2 e)" by(auto dest: bisim1_pc_length_compE2)
  hence "xs = loc  xcp = None  τExec_mover_a P t e h (stk, xs, pc, None) ([v], xs, length (compE2 e), None)"
  proof(cases "pc < length (compE2 e)")
    case True
    with e' = Val v; pc < length (compE2 e)  xs = loc  xcp = None  τExec_mover_a P t e h (stk, xs, pc, None) ([v], xs, length (compE2 e), None)
    show ?thesis by auto
  next
    case False
    with length have pc: "pc = length (compE2 e)" by auto
    with P,e,h  (e',xs)  (stk,loc,pc,xcp) have "stk = [v]" "xs = loc" "xcp = None"
      by(auto dest: bisim1_Val_length_compE2D)
    with pc show ?thesis by(auto)
  qed
  hence s: "xs = loc" "xcp = None"
    and exec1: "τExec_mover_a P t e h (stk, xs, pc, None) ([v], xs, length (compE2 e), None)" by auto
  from exec1 have "τExec_movesr_a P t (e # es) h (stk, xs, pc, None) ([v], xs, length (compE2 e), None)"
    by(auto intro: τExec_mover_τExec_movesr)
  moreover have "τExec_movesr_a P t (map Val vs') h ([], xs, 0, None) (rev vs', xs, length (compEs2 (map Val vs')), None)"
    by(rule τExec_movesr_map_Val)
  hence "τExec_movesr_a P t ([e] @ map Val vs') h ([] @ [v], xs, length (compEs2 [e]) + 0, None) (rev vs' @ [v], xs, length (compEs2 [e]) + length (compEs2 (map Val vs')), None)"
    by -(rule append_τExec_movesr, auto)
  ultimately show ?case using s by(auto)
next
  case (bisims1List2 es es' xs stk loc pc xcp e v)
  from Val v # es' = map Val vs obtain vs' where [simp]: "vs = v # vs'" "es' = map Val vs'" by auto
  from P,es,h  (es',xs) [↔] (stk,loc,pc,xcp)
  have length: "pc  length (compEs2 es)" by(auto dest: bisims1_pc_length_compEs2)
  hence "xs = loc  xcp = None  τExec_movesr_a P t es h (stk, xs, pc, None) (rev vs', xs, length (compEs2 es), None)"
  proof(cases "pc < length (compEs2 es)")
    case True
    with es' = map Val vs'; pc < length (compEs2 es)  xs = loc  xcp = None  τExec_movesr_a P t es h (stk, xs, pc, None)
      (rev vs', xs, length (compEs2 es), None)
    show ?thesis by auto
  next
    case False
    with length have pc: "pc = length (compEs2 es)" by auto
    with P,es,h  (es',xs) [↔] (stk,loc,pc,xcp) have "stk = rev vs'" "xs = loc" "xcp = None"
      by(auto dest: bisims1_Val_length_compEs2D)
    with pc show ?thesis by(auto)
  qed
  hence s: "xs = loc" "xcp = None"
    and exec1: "τExec_movesr_a P t es h (stk, xs, pc, None) (rev vs', xs, length (compEs2 es), None)" by auto
  from exec1 have "τExec_movesr_a P t ([e] @ es) h (stk @ [v], xs, length (compEs2 [e]) + pc, None) (rev vs' @ [v], xs, length (compEs2 [e]) + length (compEs2 es), None)"
    by -(rule append_τExec_movesr, auto)
  thus ?case using s by(auto)
qed(auto)

lemma bisim1Val2D1:
  assumes bisim: "P, e, h  (Val v,xs)  (stk,loc,pc,xcp)"
  shows "xcp = None  xs = loc  τExec_mover_a P t e h (stk, loc, pc, xcp) ([v], loc, length (compE2 e), None)"
proof -
  from bisim have "xcp = None" "xs = loc" by(auto dest: bisim_Val_loc_eq_xcp_None)
  moreover 
  have "τExec_mover_a P t e h (stk, loc, pc, xcp) ([v], loc, length (compE2 e), None)"
  proof(cases "pc < length (compE2 e)")
    case True
    from bisim1_Val_τExec_move[OF bisim True] show ?thesis by auto
  next
    case False
    from bisim have "pc  length (compE2 e)" by(auto dest: bisim1_pc_length_compE2)
    with False have "pc = length (compE2 e)" by auto
    with bisim have "stk = [v]" "loc = xs" "xcp=None" by(auto dest: bisim1_Val_length_compE2D)
    with pc = length (compE2 e) show ?thesis by(auto)
  qed
  ultimately show ?thesis by simp
qed

lemma bisim1_Throw_τExec_movet:
  " P, e, h  (Throw a,xs)  (stk,loc,pc,None) 
   pc'. τExec_movet_a P t e h (stk, loc, pc, None) ([Addr a], loc, pc', a) 
      P, e, h  (Throw a,xs)  ([Addr a], loc, pc', a)  xs = loc"

  and bisims1_Throw_τExec_movest:
  " P, es, h   (map Val vs @ Throw a # es',xs) [↔] (stk,loc,pc,None) 
   pc'. τExec_movest_a P t es h (stk, loc, pc, None) (Addr a # rev vs, loc, pc', a) 
      P, es, h  (map Val vs @ Throw a # es',xs) [↔] (Addr a # rev vs, loc, pc', a)  xs = loc"
proof(induct e "n :: nat" "Throw a :: 'addr expr1" xs stk loc pc "None :: 'addr option"
    and es "n :: nat" "map Val vs @ Throw a # es' :: 'addr expr1 list" xs stk loc pc "None :: 'addr option"
    arbitrary: and vs rule: bisim1_bisims1_inducts_split)
  case (bisim1Sync9 e1 n e2 V xs)
  let ?pc = "8 + length (compE2 e1) + length (compE2 e2)"
  have "τExec_movet_a P t (sync⇘V(e1) e2) h ([Addr a], xs, ?pc, None) ([Addr a], xs, ?pc, a)"
    by(rule τExect1step)(auto intro: exec_instr τmove2_τmoves2.intros simp add: is_Ref_def exec_move_def)
  moreover
  have "P,sync⇘V(e1) e2,h  (Throw a,xs)  ([Addr a],xs,?pc,a)" by(rule bisim1Sync10)
  ultimately show ?case by auto
next
  case (bisim1Seq2 e2 n xs stk loc pc e1)
  then obtain pc' where "τExec_movet_a P t e2 h (stk, loc, pc, None) ([Addr a], loc, pc', a)"
    "P, e2, h  (Throw a,xs)  ([Addr a],loc,pc',a)" "xs = loc" by auto
  thus ?case by(auto intro: Seq_τExectI2 bisim1_bisims1.bisim1Seq2)
next
  case (bisim1CondThen e1 n xs stk loc pc e e2)
  then obtain pc' where exec: "τExec_movet_a P t e1 h (stk, loc, pc, None) ([Addr a], loc, pc', a)"
    and bisim: "P, e1, h  (Throw a,xs)  ([Addr a],loc,pc',a)" and s: "xs = loc" by auto
  from exec have "τExec_movet_a P t (if (e) e1 else e2) h (stk, loc, Suc (length (compE2 e) + pc), None) ([Addr a], loc, Suc (length (compE2 e) + pc'), a)"
    by(rule Cond_τExectI2)
  moreover from bisim
  have "P, if (e) e1 else e2, h  (Throw a, xs)  ([Addr a], loc, Suc (length (compE2 e) + pc'), a)"
    by(rule bisim1_bisims1.bisim1CondThen)
  ultimately show ?case using s by(auto)
next
  case (bisim1CondElse e2 n xs stk loc pc e e1)
  then obtain pc' where exec: "τExec_movet_a P t e2 h (stk, loc, pc, None) ([Addr a], loc, pc', a)"
    and bisim: "P, e2, h  (Throw a, xs )  ([Addr a], loc, pc', a)" and s: "xs = loc" by auto
  let "?pc pc" = "Suc (Suc (length (compE2 e) + length (compE2 e1) + pc))"
  from exec have "τExec_movet_a P t (if (e) e1 else e2) h (stk, loc, (?pc pc), None) ([Addr a], loc, ?pc pc', a)"
    by(rule Cond_τExectI3)
  moreover from bisim
  have "P, if (e) e1 else e2, h  (Throw a, xs )  ([Addr a], loc, ?pc pc', a)"
    by(rule bisim1_bisims1.bisim1CondElse)
  ultimately show ?case using s by auto
next
  case (bisim1Throw1 e n xs stk loc pc)
  note bisim = P, e, h  (addr a, xs)  (stk, loc, pc, None)
  hence s: "xs = loc" 
    and exec: "τExec_mover_a P t e h (stk, loc, pc, None) ([Addr a], loc, length (compE2 e), None)"
    by(auto dest: bisim1Val2D1)
  from exec have "τExec_mover_a P t (throw e) h (stk, loc, pc, None) ([Addr a], loc, length (compE2 e), None)"
    by(rule Throw_τExecrI)
  also have "τExec_movet_a P t (throw e) h ([Addr a], loc, length (compE2 e), None) ([Addr a], loc, length (compE2 e), a)"
    by(rule τExect1step, auto intro: exec_instr τmove2Throw2 simp add: is_Ref_def exec_move_def)
  also have "P, throw e, h  (Throw a, loc )  ([Addr a], loc, length (compE2 e), a)"
    by(rule bisim1Throw2)
  ultimately show ?case using s by auto
next
  case (bisims1List1 e n e' xs stk loc pc es vs)
  note bisim = P,e,h  (e', xs)  (stk, loc, pc, None)
  show ?case
  proof(cases "is_val e'")
    case True
    with e' # es = map Val vs @ Throw a # es' obtain v vs' where "vs = v # vs'" "e' = Val v"
      and es: "es = map Val vs' @ Throw a # es'" by(auto simp add: Cons_eq_append_conv)
    with bisim have "P,e,h  (Val v, xs)  (stk, loc, pc, None)" by simp
    from bisim1Val2D1[OF this] have [simp]: "xs = loc"
      and exec: "τExec_mover_a P t e h (stk, loc, pc, None) ([v], loc, length (compE2 e), None)"
      by auto
    from exec have "τExec_movesr_a P t (e # es) h (stk, loc, pc, None) ([v], loc, length (compE2 e), None)"
      by(rule τExec_mover_τExec_movesr)
    also from es es = map Val vs' @ Throw a # es'
          pc'. τExec_movest_a P t es h ([], loc, 0, None) (Addr a # rev vs', loc, pc', a) 
           P,es,h  (map Val vs' @ Throw a # es', loc) [↔] (Addr a # rev vs', loc, pc', a)  loc = loc
    obtain pc' where execes: "τExec_movest_a P t es h ([], loc, 0, None) (Addr a # rev vs', loc, pc', a)"
      and bisim': "P,es,h  (map Val vs' @ Throw a # es', loc) [↔] (Addr a # rev vs', loc, pc', a)" by auto
    from append_τExec_movest[OF _ execes, of "[v]" "[e]"]
    have "τExec_movest_a P t (e # es) h ([v], loc, length (compE2 e), None) (Addr a # rev vs' @ [v], loc, length (compE2 e) + pc', a)" by simp
    also from bisims1List2[OF bisim', of e v] es e' = Val v vs = v # vs'
    have "P,e # es,h  (e' # es, xs) [↔] ((Addr a # rev vs), loc, length (compE2 e) + pc', a)" by simp
    ultimately show ?thesis using vs = v # vs' es e' = Val v by auto
  next
    case False
    with e' # es = map Val vs @ Throw a # es' have [simp]: "e' = Throw a" "es = es'" "vs = []"
      by(auto simp add: Cons_eq_append_conv)
    from e' = Throw a  pc'. τExec_movet_a P t e h (stk, loc, pc, None) ([Addr a], loc, pc', a)  P,e,h  (Throw a, xs )  ([Addr a], loc, pc', a)  xs = loc
    obtain pc' where "τExec_movet_a P t e h (stk, loc, pc, None) ([Addr a], loc, pc', a)"
      and bisim: "P,e,h  (Throw a, xs )  ([Addr a], loc, pc', a)" and s: "xs = loc" by auto
    hence "τExec_movest_a P t (e # es) h (stk, loc, pc, None) ([Addr a], loc, pc', a)"
      by-(rule τExec_movet_τExec_movest)
    moreover from bisim
    have "P,e#es,h  (Throw a#es,xs) [↔] ([Addr a],loc,pc',a)" by(rule bisim1_bisims1.bisims1List1)
    ultimately show ?thesis using s by auto
  qed
next
  case (bisims1List2 es n es'' xs stk loc pc e v)
  note IH = vs. es'' = map Val vs @ Throw a # es'
     pc'. τExec_movest_a P t es h (stk, loc, pc, None) (Addr a # rev vs, loc, pc', a) 
           P,es,h  (map Val vs @ Throw a # es',xs) [↔] (Addr a # rev vs,loc,pc',a)  xs = loc
  from Val v # es'' = map Val vs @ Throw a # es'
  obtain vs' where [simp]: "vs = v # vs'" "es'' = map Val vs' @ Throw a # es'" by(auto simp add: Cons_eq_append_conv)
  from IH[OF es'' = map Val vs' @ Throw a # es']
  obtain pc' where exec: "τExec_movest_a P t es h (stk, loc, pc, None) (Addr a # rev vs', loc, pc', a)"
    and bisim: "P,es,h  (map Val vs' @ Throw a # es',xs) [↔] (Addr a # rev vs',loc,pc',a)"
    and [simp]: "xs = loc" by auto
  from append_τExec_movest[OF _ exec, of "[v]" "[e]"]
  have "τExec_movest_a P t (e # es) h (stk @ [v], loc, length (compE2 e) + pc, None) (Addr a # rev vs, loc, length (compE2 e) + pc', a)" by simp
  moreover from bisim 
  have "P,e#es,h  (Val v # map Val vs' @ Throw a # es',xs) [↔] ((Addr a # rev vs')@[v],loc,length (compE2 e) + pc',a)"
    by(rule bisim1_bisims1.bisims1List2)
  ultimately show ?case by(auto)
qed(auto)

lemma bisim1_Throw_τExec_mover:
  " P, e, h  (Throw a,xs)  (stk,loc,pc,None) 
   pc'. τExec_mover_a P t e h (stk, loc, pc, None) ([Addr a], loc, pc', a) 
      P, e, h  (Throw a,xs)  ([Addr a], loc, pc', a)  xs = loc"
by(drule bisim1_Throw_τExec_movet)(blast intro: tranclp_into_rtranclp)

lemma bisims1_Throw_τExec_movesr:
  " P, es, h   (map Val vs @ Throw a # es',xs) [↔] (stk,loc,pc,None) 
   pc'. τExec_movesr_a P t es h (stk, loc, pc, None) (Addr a # rev vs, loc, pc', a) 
      P, es, h  (map Val vs @ Throw a # es',xs) [↔] (Addr a # rev vs, loc, pc', a)  xs = loc"
by(drule bisims1_Throw_τExec_movest)(blast intro: tranclp_into_rtranclp)

declare split_beta [simp]

lemma bisim1_inline_call_Throw:
  " P,e,h  (e', xs)  (stk, loc, pc, None); call1 e' = (a, M, vs);
     compE2 e ! pc = Invoke M n0; pc < length (compE2 e) 
   n0 = length vs  P,e,h  (inline_call (Throw A) e', xs)  (stk, loc, pc, A)"
  (is " _; _; _; _   ?concl e n e' xs pc stk loc")

  and bisims1_inline_calls_Throw:
  " P,es,h  (es', xs) [↔] (stk, loc, pc, None); calls1 es' = (a, M, vs);
     compEs2 es ! pc = Invoke M n0; pc < length (compEs2 es) 
   n0 = length vs  P,es,h  (inline_calls (Throw A) es', xs) [↔] (stk, loc, pc, A)"
  (is " _; _; _; _   ?concls es n es' xs pc stk loc")
proof(induct e "n :: nat" e' xs stk loc pc "None :: 'addr option"
        and es "n :: nat" es' xs stk loc pc "None :: 'addr option"
      rule: bisim1_bisims1_inducts_split)
  case (bisim1BinOp1 e1 n e' xs stk loc pc e2 bop)
  note IH1 = call1 e' = (a, M, vs); compE2 e1 ! pc = Invoke M n0; pc < length (compE2 e1) 
               ?concl e1 n e' xs pc stk loc
  note bisim1 = P,e1,h  (e', xs)  (stk, loc, pc, None)
  note ins = compE2 (e1 «bop» e2) ! pc = Invoke M n0
  note call = call1 (e' «bop» e2) = (a, M, vs)
  show ?case
  proof(cases "is_val e'")
    case False
    with bisim1 call have "pc < length (compE2 e1)"
      by(auto intro: bisim1_call_pcD)
    with call ins IH1 False show ?thesis
      by(auto intro: bisim1_bisims1.bisim1BinOp1)
  next
    case True
    then obtain v where [simp]: "e' = Val v" by auto
    from bisim1 have "pc  length (compE2 e1)" by(auto dest: bisim1_pc_length_compE2)
    moreover {
      assume pc: "pc < length (compE2 e1)"
      with bisim1 ins have False
        by(auto dest: bisim_Val_pc_not_Invoke) }
    ultimately have [simp]: "pc = length (compE2 e1)" by(cases "pc < length (compE2 e1)") auto
    from call ins show ?thesis by simp
  qed
next
  case bisim1BinOp2 thus ?case
    by(auto split: if_split_asm bop.split_asm dest: bisim1_bisims1.bisim1BinOp2)
next
  case (bisim1AAcc1 A n a' xs stk loc pc i)
  note IH1 = call1 a' = (a, M, vs); compE2 A ! pc = Invoke M n0; pc < length (compE2 A) 
               ?concl A n a' xs pc stk loc
  note bisim1 = P,A,h  (a', xs)  (stk, loc, pc, None)
  note ins = compE2 (Ai) ! pc = Invoke M n0
  note call = call1 (a'i) = (a, M, vs)
  show ?case
  proof(cases "is_val a'")
    case False
    with bisim1 call have "pc < length (compE2 A)"
      by(auto intro: bisim1_call_pcD)
    with call ins IH1 False show ?thesis
      by(auto intro: bisim1_bisims1.bisim1AAcc1)
  next
    case True
    then obtain v where [simp]: "a' = Val v" by auto
    from bisim1 have "pc  length (compE2 A)" by(auto dest: bisim1_pc_length_compE2)
    moreover {
      assume pc: "pc < length (compE2 A)"
      with bisim1 ins have False
        by(auto dest: bisim_Val_pc_not_Invoke) }
    ultimately have [simp]: "pc = length (compE2 A)" by(cases "pc < length (compE2 A)") auto
    from call ins show ?thesis by simp
  qed
next
  case bisim1AAcc2 thus ?case
    by(auto split: if_split_asm dest: bisim1_bisims1.bisim1AAcc2)
next
  case (bisim1AAss1 A n a' xs stk loc pc i e)
  note IH1 = call1 a' = (a, M, vs); compE2 A ! pc = Invoke M n0; pc < length (compE2 A) 
               ?concl A n a' xs pc stk loc
  note bisim1 = P,A,h  (a', xs)  (stk, loc, pc, None)
  note ins = compE2 (Ai := e) ! pc = Invoke M n0
  note call = call1 (a'i := e) = (a, M, vs)
  show ?case
  proof(cases "is_val a'")
    case False
    with bisim1 call have "pc < length (compE2 A)"
      by(auto intro: bisim1_call_pcD)
    with call ins IH1 False show ?thesis
      by(auto intro: bisim1_bisims1.bisim1AAss1)
  next
    case True
    then obtain v where [simp]: "a' = Val v" by auto
    from bisim1 have "pc  length (compE2 A)" by(auto dest: bisim1_pc_length_compE2)
    moreover {
      assume pc: "pc < length (compE2 A)"
      with bisim1 ins have False
        by(auto dest: bisim_Val_pc_not_Invoke) }
    ultimately have [simp]: "pc = length (compE2 A)" by(cases "pc < length (compE2 A)") auto
    from call ins show ?thesis by simp
  qed
next
  case (bisim1AAss2 i n i' xs stk loc pc A e v)
  note IH1 = call1 i' = (a, M, vs); compE2 i ! pc = Invoke M n0; pc < length (compE2 i) 
               ?concl i n i' xs pc stk loc
  note bisim1 = P,i,h  (i', xs)  (stk, loc, pc, None)
  note ins = compE2 (Ai := e) ! (length (compE2 A) + pc) = Invoke M n0
  note call = call1 (Val vi' := e) = (a, M, vs)
  show ?case
  proof(cases "is_val i'")
    case False
    with bisim1 call have "pc < length (compE2 i)"
      by(auto intro: bisim1_call_pcD)
    with call ins IH1 False show ?thesis
      by(auto intro: bisim1_bisims1.bisim1AAss2)
  next
    case True
    then obtain v where [simp]: "i' = Val v" by auto
    from bisim1 have "pc  length (compE2 i)" by(auto dest: bisim1_pc_length_compE2)
    moreover {
      assume pc: "pc < length (compE2 i)"
      with bisim1 ins have False
        by(auto dest: bisim_Val_pc_not_Invoke) }
    ultimately have [simp]: "pc = length (compE2 i)" by(cases "pc < length (compE2 i)") auto
    from call ins show ?thesis by simp
  qed
next
  case bisim1AAss3 thus ?case
    by(auto split: if_split_asm nat.split_asm simp add: nth_Cons dest: bisim1_bisims1.bisim1AAss3)
next
  case (bisim1FAss1 e n e' xs stk loc pc e2 F D)
  note IH1 = call1 e' = (a, M, vs); compE2 e ! pc = Invoke M n0; pc < length (compE2 e) 
               ?concl e n e' xs pc stk loc
  note bisim1 = P,e,h  (e', xs)  (stk, loc, pc, None)
  note ins = compE2 (eF{D} := e2) ! pc = Invoke M n0
  note call = call1 (e'F{D} := e2) = (a, M, vs)
  show ?case
  proof(cases "is_val e'")
    case False
    with bisim1 call have "pc < length (compE2 e)"
      by(auto intro: bisim1_call_pcD)
    with call ins IH1 False show ?thesis
      by(auto intro: bisim1_bisims1.bisim1FAss1)
  next
    case True
    then obtain v where [simp]: "e' = Val v" by auto
    from bisim1 have "pc  length (compE2 e)" by(auto dest: bisim1_pc_length_compE2)
    moreover {
      assume pc: "pc < length (compE2 e)"
      with bisim1 ins have False
        by(auto dest: bisim_Val_pc_not_Invoke) }
    ultimately have [simp]: "pc = length (compE2 e)" by(cases "pc < length (compE2 e)") auto
    from call ins show ?thesis by simp
  qed
next
  case bisim1FAss2 thus ?case
    by(auto split: if_split_asm nat.split_asm simp add: nth_Cons dest: bisim1_bisims1.bisim1FAss2)
next
  case (bisim1CAS1 E n e' xs stk loc pc e2 e3 D F)
  note IH1 = call1 e' = (a, M, vs); compE2 E ! pc = Invoke M n0; pc < length (compE2 E) 
               ?concl E n e' xs pc stk loc
  note bisim1 = P,E,h  (e', xs)  (stk, loc, pc, None)
  note ins = compE2 _ ! pc = Invoke M n0
  note call = call1 _ = (a, M, vs)
  show ?case
  proof(cases "is_val e'")
    case False
    with bisim1 call have "pc < length (compE2 E)"
      by(auto intro: bisim1_call_pcD)
    with call ins IH1 False show ?thesis
      by(auto intro: bisim1_bisims1.bisim1CAS1)
  next
    case True
    then obtain v where [simp]: "e' = Val v" by auto
    from bisim1 have "pc  length (compE2 E)" by(auto dest: bisim1_pc_length_compE2)
    moreover {
      assume pc: "pc < length (compE2 E)"
      with bisim1 ins have False
        by(auto dest: bisim_Val_pc_not_Invoke) }
    ultimately have [simp]: "pc = length (compE2 E)" by(cases "pc < length (compE2 E)") auto
    from call ins show ?thesis by simp
  qed
next
  case (bisim1CAS2 e2 n e2' xs stk loc pc e1 e3 D F v)
  note IH1 = call1 e2' = (a, M, vs); compE2 e2 ! pc = Invoke M n0; pc < length (compE2 e2) 
               ?concl e2 n e2' xs pc stk loc
  note bisim1 = P,e2,h  (e2', xs)  (stk, loc, pc, None)
  note ins = compE2 _ ! (length (compE2 e1) + pc) = Invoke M n0
  note call = call1 _ = (a, M, vs)
  show ?case
  proof(cases "is_val e2'")
    case False
    with bisim1 call have "pc < length (compE2 e2)"
      by(auto intro: bisim1_call_pcD)
    with call ins IH1 False show ?thesis
      by(auto intro: bisim1_bisims1.bisim1CAS2)
  next
    case True
    then obtain v where [simp]: "e2' = Val v" by auto
    from bisim1 have "pc  length (compE2 e2)" by(auto dest: bisim1_pc_length_compE2)
    moreover {
      assume pc: "pc < length (compE2 e2)"
      with bisim1 ins have False
        by(auto dest: bisim_Val_pc_not_Invoke) }
    ultimately have [simp]: "pc = length (compE2 e2)" by(cases "pc < length (compE2 e2)") auto
    from call ins show ?thesis by simp
  qed
next
  case (bisim1Call1 obj n obj' xs stk loc pc ps M')
  note IH1 = call1 obj' = (a, M, vs); compE2 obj ! pc = Invoke M n0;
              pc < length (compE2 obj) 
               ?concl obj n obj' xs pc stk loc
  note IH2 = xs. calls1 ps = (a, M, vs); compEs2 ps ! 0 = Invoke M n0; 0 < length (compEs2 ps) 
              ?concls ps n ps xs 0 [] xs
  note ins = compE2 (objM'(ps)) ! pc = Invoke M n0
  note bisim1 = P,obj,h  (obj', xs)  (stk, loc, pc, None)
  note call = call1 (obj'M'(ps)) = (a, M, vs)
  thus ?case
  proof(cases rule: call1_callE)
    case CallObj
    with bisim1 call have "pc < length (compE2 obj)" by(auto intro: bisim1_call_pcD)
    with call ins CallObj IH1 show ?thesis
      by(auto intro: bisim1_bisims1.bisim1Call1)
  next
    case (CallParams v)
    from bisim1 have "pc  length (compE2 obj)" by(auto dest: bisim1_pc_length_compE2)
    moreover {
      assume pc: "pc < length (compE2 obj)"
      with bisim1 ins CallParams have False by(auto dest: bisim_Val_pc_not_Invoke) }
    ultimately have [simp]: "pc = length (compE2 obj)" by(cases "pc < length (compE2 obj)") auto
    with bisim1 CallParams have [simp]: "stk = [v]" "loc = xs" by(auto dest: bisim1_Val_length_compE2D)
    from IH2[of loc] CallParams ins
    show ?thesis
      apply(clarsimp simp add: compEs2_map_Val is_vals_conv split: if_split_asm)
      apply(drule bisim1_bisims1.bisim1CallParams)
      apply(auto simp add: neq_Nil_conv)
      done
  next
    case [simp]: Call
    from bisim1 have "pc  length (compE2 obj)" by(auto dest: bisim1_pc_length_compE2)
    moreover {
      assume pc: "pc < length (compE2 obj)"
      with bisim1 ins have False by(auto dest: bisim_Val_pc_not_Invoke) }
    ultimately have [simp]: "pc = length (compE2 obj)" by(cases "pc < length (compE2 obj)") auto
    with ins have [simp]: "vs = []" by(auto simp add: compEs2_map_Val split: if_split_asm)
    from bisim1 have [simp]: "stk = [Addr a]" "xs = loc" by(auto dest: bisim1_Val_length_compE2D)
    from ins show ?thesis by(auto intro: bisim1CallThrow[of "[]" "[]", simplified])
  qed
next
  case (bisim1CallParams ps n ps' xs stk loc pc obj M' v)
  note IH2 = calls1 ps' = (a, M, vs); compEs2 ps ! pc = Invoke M n0; pc < length (compEs2 ps) 
              ?concls ps n ps' xs pc stk loc
  note ins = compE2 (objM'(ps)) ! (length (compE2 obj) + pc) = Invoke M n0
  note bisim2 = P,ps,h  (ps', xs) [↔] (stk, loc, pc, None)
  note call = call1 (Val vM'(ps')) = (a, M, vs)
  thus ?case
  proof(cases rule: call1_callE)
    case CallObj thus ?thesis by simp
  next
    case (CallParams v')
    hence [simp]: "v' = v" and call': "calls1 ps' = (a, M, vs)" by auto
    from bisim2 call' have "pc < length (compEs2 ps)" by(auto intro: bisims1_calls_pcD)
    with IH2 CallParams ins show ?thesis
      by(auto simp add: is_vals_conv split: if_split_asm intro: bisim1_bisims1.bisim1CallParams)
  next
    case Call
    hence [simp]: "v = Addr a" "M' = M" "ps' = map Val vs" by auto
    from bisim2 have "pc  length (compEs2 ps)" by(auto dest: bisims1_pc_length_compEs2)
    moreover {
      assume pc: "pc < length (compEs2 ps)"
      with bisim2 ins have False by(auto dest: bisims_Val_pc_not_Invoke) }
    ultimately have [simp]: "pc = length (compEs2 ps)" by(cases "pc < length (compEs2 ps)") auto
    from bisim2 have [simp]: "stk = rev vs" "xs = loc" by(auto dest: bisims1_Val_length_compEs2D)
    from bisim2 have "length ps = length vs" by(auto dest: bisims1_lengthD)
    with ins show ?thesis by(auto intro: bisim1CallThrow)
  qed
next
  case (bisims1List1 e n e' xs stk loc pc es)
  note IH1 = call1 e' = (a, M, vs); compE2 e ! pc = Invoke M n0; pc < length (compE2 e) 
               ?concl e n e' xs pc stk loc
  note IH2 = xs. calls1 es = (a, M, vs); compEs2 es ! 0 = Invoke M n0; 0 < length (compEs2 es) 
              ?concls es n es xs 0 [] xs
  note bisim1 = P,e,h  (e', xs)  (stk, loc, pc, None)
  note call = calls1 (e' # es) = (a, M, vs)
  note ins = compEs2 (e # es) ! pc = Invoke M n0
  show ?case
  proof(cases "is_val e'")
    case False
    with bisim1 call have "pc < length (compE2 e)" by(auto intro: bisim1_call_pcD)
    with call ins False IH1 show ?thesis
      by(auto intro: bisim1_bisims1.bisims1List1)
  next
    case True
    then obtain v where [simp]: "e' = Val v" by auto
    from bisim1 have "pc  length (compE2 e)" by(auto dest: bisim1_pc_length_compE2)
    moreover {
      assume pc: "pc < length (compE2 e)"
      with bisim1 ins have False by(auto dest: bisim_Val_pc_not_Invoke) }
    ultimately have [simp]: "pc = length (compE2 e)" by(cases "pc < length (compE2 e)") auto
    with bisim1 have [simp]: "stk = [v]" "loc = xs" by(auto dest: bisim1_Val_length_compE2D)
    from call have "es  []" by(cases es) simp_all
    with IH2[of loc] call ins
    show ?thesis by(auto split: if_split_asm dest: bisims1List2)
  qed
qed(auto split: if_split_asm bop.split_asm intro: bisim1_bisims1.intros dest: bisim1_pc_length_compE2)

lemma bisim1_max_stack: "P,e,h  (e', xs)  (stk, loc, pc, xcp)  length stk  max_stack e"
  and bisims1_max_stacks: "P,es,h  (es', xs) [↔] (stk, loc, pc, xcp)  length stk  max_stacks es"
apply(induct "(e', xs)" "(stk, loc, pc, xcp)" and "(es', xs)" "(stk, loc, pc, xcp)"
  arbitrary: e' xs stk loc pc xcp and es' xs stk loc pc xcp rule: bisim1_bisims1.inducts)
apply(auto simp add: max_stack1[simplified] max_def max_stacks_ge_length)
apply(drule sym, simp add: max_stacks_ge_length, drule sym, simp, rule le_trans[OF max_stacks_ge_length], simp)
done

inductive bisim1_fr :: "'addr J1_prog  'heap  'addr expr1 × 'addr locals1  'addr frame  bool"
for P :: "'addr J1_prog" and h :: 'heap
where
  " P  C sees M:TsT = body in D;
     P,blocks1 0 (Class D#Ts) body, h  (e, xs)  (stk, loc, pc, None);
     call1 e = (a, M', vs);
     max_vars e  length xs 
   bisim1_fr P h (e, xs) (stk, loc, C, M, pc)"

declare bisim1_fr.intros [intro]
declare bisim1_fr.cases [elim]

lemma bisim1_fr_hext_mono:
  " bisim1_fr P h exs fr; hext h h'    bisim1_fr P h' exs fr"
by(auto intro: bisim1_hext_mono)

lemma bisim1_max_vars: "P,E,h  (e, xs)  (stk, loc, pc, xcp)  max_vars E  max_vars e"
  and bisims1_max_varss: "P,Es,h  (es,xs) [↔] (stk,loc,pc,xcp)  max_varss Es  max_varss es"
apply(induct E "(e, xs)" "(stk, loc, pc, xcp)" and Es "(es, xs)" "(stk, loc, pc, xcp)"
  arbitrary: e xs stk loc pc xcp and es xs stk loc pc xcp rule: bisim1_bisims1.inducts)
apply(auto)
done

lemma bisim1_call_τExec_move:
  " P,e,h  (e', xs)  (stk, loc, pc, None); call1 e' = (a, M', vs); n + max_vars e'  length xs; ¬ contains_insync e 
   pc' loc' stk'. τExec_mover_a P t e h (stk, loc, pc, None) (rev vs @ Addr a # stk', loc', pc', None) 
                     pc' < length (compE2 e)  compE2 e ! pc' = Invoke M' (length vs) 
                     P,e,h  (e', xs)  (rev vs @ Addr a # stk', loc', pc', None)"
  (is " _; _; _; _   ?concl e n e' xs pc stk loc")

  and bisims1_calls_τExec_moves:
  " P,es,h  (es',xs) [↔] (stk, loc, pc, None); calls1 es' = (a, M', vs);
     n + max_varss es'  length xs; ¬ contains_insyncs es 
   pc' stk' loc'. τExec_movesr_a P t es h (stk, loc, pc, None) (rev vs @ Addr a # stk', loc', pc', None) 
                     pc' < length (compEs2 es)  compEs2 es ! pc' = Invoke M' (length vs) 
                     P,es,h  (es', xs) [↔] (rev vs @ Addr a # stk', loc', pc', None)"
  (is "_; _; _; _   ?concls es n es' xs pc stk loc")
proof(induct e "n :: nat" e' xs stk loc pc xcp"None :: 'addr option"
    and es "n :: nat" es' xs stk loc pc xcp"None :: 'addr option"
    rule: bisim1_bisims1_inducts_split)
  case bisim1Val2 thus ?case by auto
next
  case bisim1New thus ?case by auto
next
  case bisim1NewArray thus ?case
    by auto (fastforce intro: bisim1_bisims1.bisim1NewArray elim!: NewArray_τExecrI intro!: exI)
next
  case bisim1Cast thus ?case
    by(auto)(fastforce intro: bisim1_bisims1.bisim1Cast elim!: Cast_τExecrI intro!: exI)+
next
  case bisim1InstanceOf thus ?case
    by(auto)(fastforce intro: bisim1_bisims1.bisim1InstanceOf elim!: InstanceOf_τExecrI intro!: exI)+
next
  case bisim1Val thus ?case by auto
next
  case bisim1Var thus ?case by auto
next
  case (bisim1BinOp1 e1 n e' xs stk loc pc e2 bop)
  note IH1 = call1 e' = (a, M', vs); n + max_vars e'  length xs; ¬ contains_insync e1   ?concl e1 n e' xs pc stk loc
  note IH2 = xs. call1 e2 = (a, M', vs); n + max_vars e2  length xs; ¬ contains_insync e2   ?concl e2 n e2 xs 0 [] xs
  note call = call1 (e' «bop» e2) = (a, M', vs)
  note len = n + max_vars (e' «bop» e2)  length xs
  note bisim1 = P,e1,h  (e', xs)  (stk, loc, pc, None)
  note cs = ¬ contains_insync (e1 «bop» e2)
  show ?case
  proof(cases "is_val e'")
    case True
    then obtain v where [simp]: "e' = Val v" by auto
    from bisim1 have "τExec_mover_a P t e1 h (stk, loc, pc, None) ([v], loc, length (compE2 e1), None)"
      and [simp]: "xs = loc" by(auto dest!: bisim1Val2D1)
    hence "τExec_mover_a P t (e1«bop»e2) h (stk, loc, pc, None) ([v], loc, length (compE2 e1), None)"
      by-(rule BinOp_τExecrI1)
    also from call IH2[of loc] len cs  obtain pc' stk' loc'
      where exec: "τExec_mover_a P t e2 h ([], xs, 0, None) (rev vs @ Addr a # stk', loc', pc', None)"
      and ins: "compE2 e2 ! pc' = Invoke M' (length vs)" "pc' < length (compE2 e2)"
      and bisim': "P,e2,h  (e2, xs)  (rev vs @ Addr a # stk', loc', pc', None)" by auto
    from BinOp_τExecrI2[OF exec, of e1 bop v]
    have "τExec_mover_a P t (e1«bop»e2) h ([v], loc, length (compE2 e1), None) (rev vs @ Addr a # (stk' @ [v]), loc', length (compE2 e1) + pc', None)" by simp
    also (rtranclp_trans) from bisim'
    have "P,e1«bop»e2,h  (Val v «bop» e2, xs)  ((rev vs @ Addr a # stk') @ [v], loc', length (compE2 e1) + pc', None)"
      by(rule bisim1BinOp2)
    ultimately show ?thesis using ins by fastforce
  next
    case False with IH1 len False call cs show ?thesis
      by(clarsimp)(fastforce intro: bisim1_bisims1.bisim1BinOp1 elim!: BinOp_τExecrI1 intro!: exI)
  qed
next
  case (bisim1BinOp2 e2 n e' xs stk loc pc e1 bop v1)
  then obtain pc' loc' stk' where pc': "pc' < length (compE2 e2)" "compE2 e2 ! pc' = Invoke M' (length vs)"
    and exec: "τExec_mover_a P t e2 h (stk, loc, pc, None) (rev vs @ Addr a # stk', loc', pc', None)"
    and bisim': "P,e2,h  (e', xs)  (rev vs @ Addr a # stk', loc', pc', None)" by fastforce
  from exec have "τExec_mover_a P t (e1 «bop» e2) h (stk @ [v1], loc, length (compE2 e1) + pc, None)
                                              ((rev vs @ Addr a # stk') @ [v1], loc', length (compE2 e1) + pc', None)"
    by(rule BinOp_τExecrI2)
  moreover from bisim'
  have "P,e1 «bop» e2,h  (Val v1 «bop» e', xs)  ((rev vs @ Addr a # stk') @ [v1], loc', length (compE2 e1) + pc', None)"
    by(rule bisim1_bisims1.bisim1BinOp2)
  ultimately show ?case using pc' by(fastforce)
next
  case bisim1LAss1 thus ?case
    by(auto)(fastforce intro: bisim1_bisims1.bisim1LAss1 elim!: LAss_τExecrI intro!: exI)
next
  case bisim1LAss2 thus ?case by simp
next
  case (bisim1AAcc1 A n a' xs stk loc pc i)
  note IH1 = call1 a' = (a, M', vs); n + max_vars a'  length xs; ¬ contains_insync A  ?concl A n a' xs pc stk loc
  note IH2 = xs. call1 i = (a, M', vs); n + max_vars i  length xs; ¬ contains_insync i  ?concl i n i xs 0 [] xs
  note call = call1 (a'i) = (a, M', vs)
  note len = n + max_vars (a'i)  length xs
  note bisim1 = P,A,h  (a', xs)  (stk, loc, pc, None)
  note cs = ¬ contains_insync (Ai)
  show ?case
  proof(cases "is_val a'")
    case True
    then obtain v where [simp]: "a' = Val v" by auto
    from bisim1 have "τExec_mover_a P t A h (stk, loc, pc, None) ([v], loc, length (compE2 A), None)"
      and [simp]: "xs = loc" by(auto dest!: bisim1Val2D1)
    hence "τExec_mover_a P t (Ai) h (stk, loc, pc, None) ([v], loc, length (compE2 A), None)"
      by-(rule AAcc_τExecrI1)
    also from call IH2[of loc] len cs obtain pc' stk' loc'
      where exec: "τExec_mover_a P t i h ([], xs, 0, None) (rev vs @ Addr a # stk', loc', pc', None)"
      and ins: "compE2 i ! pc' = Invoke M' (length vs)" "pc' < length (compE2 i)"
      and bisim': "P,i,h  (i, xs)  (rev vs @ Addr a # stk', loc', pc', None)" by auto
    from AAcc_τExecrI2[OF exec, of A v]
    have "τExec_mover_a P t (Ai) h ([v], loc, length (compE2 A), None) (rev vs @ Addr a # (stk' @ [v]), loc', length (compE2 A) + pc', None)" by simp
    also (rtranclp_trans) from bisim'
    have "P,Ai,h  (Val vi, xs)  ((rev vs @ Addr a # stk') @ [v], loc', length (compE2 A) + pc', None)"
      by(rule bisim1AAcc2)
    ultimately show ?thesis using ins by fastforce
  next
    case False with IH1 len False call cs show ?thesis
      by(clarsimp)(fastforce intro: bisim1_bisims1.bisim1AAcc1 elim!: AAcc_τExecrI1 intro!: exI)
  qed
next
  case (bisim1AAcc2 i n i' xs stk loc pc A v)
  then obtain pc' loc' stk' where pc': "pc' < length (compE2 i)" "compE2 i ! pc' = Invoke M' (length vs)"
    and exec: "τExec_mover_a P t i h (stk, loc, pc, None) (rev vs @ Addr a # stk', loc', pc', None)"
    and bisim': "P,i,h  (i', xs)  (rev vs @ Addr a # stk', loc', pc', None)" by fastforce
  from exec have "τExec_mover_a P t (Ai) h (stk @ [v], loc, length (compE2 A) + pc, None)
                                       ((rev vs @ Addr a # stk') @ [v], loc', length (compE2 A) + pc', None)"
    by(rule AAcc_τExecrI2)
  moreover from bisim'
  have "P,Ai,h  (Val vi', xs)  ((rev vs @ Addr a # stk') @ [v], loc', length (compE2 A) + pc', None)"
    by(rule bisim1_bisims1.bisim1AAcc2)
  ultimately show ?case using pc' by(fastforce)
next
  case (bisim1AAss1 A n a' xs stk loc pc i e)
  note IH1 = call1 a' = (a, M', vs); n + max_vars a'  length xs; ¬ contains_insync A   ?concl A n a' xs pc stk loc
  note IH2 = xs. call1 i = (a, M', vs); n + max_vars i  length xs; ¬ contains_insync i  ?concl i n i xs 0 [] xs
  note IH3 = xs. call1 e = (a, M', vs); n + max_vars e  length xs; ¬ contains_insync e  ?concl e n e xs 0 [] xs
  note call = call1 (a'i := e) = (a, M', vs)
  note len = n + max_vars (a'i := e)  length xs
  note bisim1 = P,A,h  (a', xs)  (stk, loc, pc, None)
  note bisim2 = P,i,h  (i, loc)  ([], loc, 0, None)
  note cs = ¬ contains_insync (Ai := e)
  show ?case
  proof(cases "is_val a'")
    case True
    then obtain v where [simp]: "a' = Val v" by auto
    from bisim1 have "τExec_mover_a P t A h (stk, loc, pc, None) ([v], loc, length (compE2 A), None)"
      and [simp]: "xs = loc" by(auto dest!: bisim1Val2D1)
    hence exec: "τExec_mover_a P t (Ai := e) h (stk, loc, pc, None) ([v], loc, length (compE2 A), None)"
      by-(rule AAss_τExecrI1)
    show ?thesis
    proof(cases "is_val i")
      case True
      then obtain v' where [simp]: "i = Val v'" by auto
      note exec also from bisim2
      have "τExec_mover_a P t i h ([], loc, 0, None) ([v'], loc, length (compE2 i), None)"
        by(auto dest!: bisim1Val2D1)
      from AAss_τExecrI2[OF this, of A e v]
      have "τExec_mover_a P t (Ai := e) h ([v], loc, length (compE2 A), None) ([v', v], loc, length (compE2 A) + length (compE2 i), None)" by simp
      also (rtranclp_trans) from call IH3[of loc] len cs obtain pc' stk' loc'
        where exec: "τExec_mover_a P t e h ([], loc, 0, None) (rev vs @ Addr a # stk', loc', pc', None)"
        and ins: "compE2 e ! pc' = Invoke M' (length vs)" "pc' < length (compE2 e)"
        and bisim': "P,e,h  (e, loc)  (rev vs @ Addr a # stk', loc', pc', None)" by auto
      from AAss_τExecrI3[OF exec, of A i v' v]
      have "τExec_mover_a P t (Ai := e) h ([v', v], loc, length (compE2 A) + length (compE2 i), None)
                        ((rev vs @ Addr a # stk') @ [v', v], loc', length (compE2 A) + length (compE2 i) + pc', None)" by simp
      also (rtranclp_trans) from bisim'
      have "P,Ai := e,h  (Val vVal v' := e, xs)  ((rev vs @ Addr a # stk') @ [v', v], loc', length (compE2 A) + length (compE2 i) + pc', None)"
        by - (rule bisim1AAss3, simp)
      ultimately show ?thesis using ins by fastforce
    next
      case False
      note exec also from False call IH2[of loc] len cs obtain pc' stk' loc'
        where exec: "τExec_mover_a P t i h ([], xs, 0, None) (rev vs @ Addr a # stk', loc', pc', None)"
        and ins: "compE2 i ! pc' = Invoke M' (length vs)" "pc' < length (compE2 i)"
        and bisim': "P,i,h  (i, xs)  (rev vs @ Addr a # stk', loc', pc', None)" by auto
      from AAss_τExecrI2[OF exec, of A e v]
      have "τExec_mover_a P t (Ai := e) h ([v], loc, length (compE2 A), None) (rev vs @ Addr a # (stk' @ [v]), loc', length (compE2 A) + pc', None)" by simp
      also (rtranclp_trans) from bisim'
      have "P,Ai := e,h  (Val vi := e, xs)  ((rev vs @ Addr a # stk') @ [v], loc', length (compE2 A) + pc', None)"
        by(rule bisim1AAss2)
      ultimately show ?thesis using ins False by(fastforce intro!: exI)
    qed
  next
    case False with IH1 len False call cs show ?thesis
      by(clarsimp)(fastforce intro: bisim1_bisims1.bisim1AAss1 elim!: AAss_τExecrI1 intro!: exI)
  qed
next
  case (bisim1AAss2 i n i' xs stk loc pc A e v)
  note IH2 = call1 i' = (a, M', vs); n + max_vars i'  length xs; ¬ contains_insync i  ?concl i n i' xs pc stk loc
  note IH3 = xs. call1 e = (a, M', vs); n + max_vars e  length xs; ¬ contains_insync e  ?concl e n e xs 0 [] xs
  note call = call1 (Val vi' := e) = (a, M', vs)
  note len = n + max_vars (Val vi' := e)  length xs
  note bisim2 = P,i,h  (i', xs)  (stk, loc, pc, None)
  note cs = ¬ contains_insync (Ai := e)
  show ?case
  proof(cases "is_val i'")
    case True
    then obtain v' where [simp]: "i' = Val v'" by auto
    from bisim2 have exec: "τExec_mover_a P t i h (stk, loc, pc, None) ([v'], loc, length (compE2 i), None)"
      and [simp]: "xs = loc" by(auto dest!: bisim1Val2D1)
    from AAss_τExecrI2[OF exec, of A e v]
    have "τExec_mover_a P t (Ai := e) h (stk @ [v], loc, length (compE2 A) + pc, None) ([v', v], loc, length (compE2 A) + length (compE2 i), None)" by simp
    also from call IH3[of loc] len cs obtain pc' stk' loc'
      where exec: "τExec_mover_a P t e h ([], xs, 0, None) (rev vs @ Addr a # stk', loc', pc', None)"
      and ins: "compE2 e ! pc' = Invoke M' (length vs)" "pc' < length (compE2 e)"
      and bisim': "P,e,h  (e, xs)  (rev vs @ Addr a # stk', loc', pc', None)" by auto
    from AAss_τExecrI3[OF exec, of A i v' v]
    have "τExec_mover_a P t (Ai := e) h ([v', v], loc, length (compE2 A) + length (compE2 i), None)
                       ((rev vs @ Addr a # stk') @ [v', v], loc', length (compE2 A) + length (compE2 i) + pc', None)" by simp
    also (rtranclp_trans) from bisim'
    have "P,Ai := e,h  (Val vVal v' := e, xs)  ((rev vs @ Addr a # stk') @ [v', v], loc', length (compE2 A) + length (compE2 i) + pc', None)"
      by(rule bisim1AAss3)
    ultimately show ?thesis using ins by(fastforce intro!: exI)
  next
    case False
    with IH2 len call cs obtain pc' loc' stk'
      where ins: "pc' < length (compE2 i)" "compE2 i ! pc' = Invoke M' (length vs)"
      and exec: "τExec_mover_a P t i h (stk, loc, pc, None) (rev vs @ Addr a # stk', loc', pc', None)"
      and bisim': "P,i,h  (i', xs)  (rev vs @ Addr a # stk', loc', pc', None)" by fastforce
    from bisim' have "P,Ai := e,h  (Val vi' := e, xs)  ((rev vs @ Addr a # stk') @ [v], loc', length (compE2 A) + pc', None)"
      by(rule bisim1_bisims1.bisim1AAss2)
    with AAss_τExecrI2[OF exec, of A e v] ins False show ?thesis by(auto intro!: exI)
  qed
next
  case (bisim1AAss3 e n e' xs stk loc pc A i v v')
  then obtain pc' loc' stk' where pc': "pc' < length (compE2 e)" "compE2 e ! pc' = Invoke M' (length vs)"
    and exec: "τExec_mover_a P t e h (stk, loc, pc, None) (rev vs @ Addr a # stk', loc', pc', None)"
    and bisim': "P,e,h  (e', xs)  (rev vs @ Addr a # stk', loc', pc', None)" by fastforce
  from exec have "τExec_mover_a P t (Ai:=e) h (stk @ [v', v], loc, length (compE2 A) + length (compE2 i) + pc, None)
                                       ((rev vs @ Addr a # stk') @ [v', v], loc', length (compE2 A) + length (compE2 i) + pc', None)"
    by(rule AAss_τExecrI3)
  moreover from bisim'
  have "P,Ai := e,h  (Val vVal v' := e', xs)  ((rev vs @ Addr a # stk') @ [v', v], loc', length (compE2 A) + length (compE2 i) + pc', None)"
    by(rule bisim1_bisims1.bisim1AAss3)
  ultimately show ?case using pc' by(fastforce intro!: exI)
next
  case bisim1AAss4 thus ?case by simp
next
  case bisim1ALength thus ?case
    by(auto)(fastforce intro: bisim1_bisims1.bisim1ALength elim!: ALength_τExecrI intro!: exI)
next
  case bisim1FAcc thus ?case
    by(auto)(fastforce intro: bisim1_bisims1.bisim1FAcc elim!: FAcc_τExecrI intro!: exI)
next
  case (bisim1FAss1 e n e' xs stk loc pc e2 F D)
  note IH1 = call1 e' = (a, M', vs); n + max_vars e'  length xs; ¬ contains_insync e  ?concl e n e' xs pc stk loc
  note IH2 = xs. call1 e2 = (a, M', vs); n + max_vars e2  length xs; ¬ contains_insync e2  ?concl e2 n e2 xs 0 [] xs
  note call = call1 (e'F{D} := e2) = (a, M', vs)
  note len = n + max_vars (e'F{D} := e2)  length xs
  note bisim1 = P,e,h  (e', xs)  (stk, loc, pc, None)
  note cs = ¬ contains_insync (eF{D} := e2)
  show ?case
  proof(cases "is_val e'")
    case True
    then obtain v where [simp]: "e' = Val v" by auto
    from bisim1 have "τExec_mover_a P t e h (stk, loc, pc, None) ([v], loc, length (compE2 e), None)"
      and [simp]: "xs = loc" by(auto dest!: bisim1Val2D1)
    hence "τExec_mover_a P t (eF{D} := e2) h (stk, loc, pc, None) ([v], loc, length (compE2 e), None)"
      by-(rule FAss_τExecrI1)
    also from call IH2[of loc] len cs obtain pc' stk' loc'
      where exec: "τExec_mover_a P t e2 h ([], xs, 0, None) (rev vs @ Addr a # stk', loc', pc', None)"
      and ins: "compE2 e2 ! pc' = Invoke M' (length vs)" "pc' < length (compE2 e2)"
      and bisim': "P,e2,h  (e2, xs)  (rev vs @ Addr a # stk', loc', pc', None)" by auto
    from FAss_τExecrI2[OF exec, of e F D v]
    have "τExec_mover_a P t (eF{D} := e2) h ([v], loc, length (compE2 e), None) (rev vs @ Addr a # (stk' @ [v]), loc', length (compE2 e) + pc', None)" by simp
    also (rtranclp_trans) from bisim'
    have "P,eF{D} := e2,h  (Val vF{D} := e2, xs)  ((rev vs @ Addr a # stk') @ [v], loc', length (compE2 e) + pc', None)"
      by(rule bisim1FAss2)
    ultimately show ?thesis using ins by fastforce
  next
    case False with IH1 len False call cs show ?thesis
      by(clarsimp)(fastforce intro: bisim1_bisims1.bisim1FAss1 elim!: FAss_τExecrI1 intro!: exI)
  qed
next
  case (bisim1FAss2 e2 n e' xs stk loc pc e F D v)
  then obtain pc' loc' stk' where pc': "pc' < length (compE2 e2)" "compE2 e2 ! pc' = Invoke M' (length vs)"
    and exec: "τExec_mover_a P t e2 h (stk, loc, pc, None) (rev vs @ Addr a # stk', loc', pc', None)"
    and bisim': "P,e2,h  (e', xs)  (rev vs @ Addr a # stk', loc', pc', None)" by fastforce
  from exec have "τExec_mover_a P t (eF{D} := e2) h (stk @ [v], loc, length (compE2 e) + pc, None)
                                       ((rev vs @ Addr a # stk') @ [v], loc', length (compE2 e) + pc', None)"
    by(rule FAss_τExecrI2)
  moreover from bisim'
  have "P,eF{D} := e2,h  (Val vF{D} := e', xs)  ((rev vs @ Addr a # stk') @ [v], loc', length (compE2 e) + pc', None)"
    by(rule bisim1_bisims1.bisim1FAss2)
  ultimately show ?case using pc' by(fastforce)
next
  case bisim1FAss3 thus ?case by simp
next
  case (bisim1CAS1 e1 n e' xs stk loc pc e2 e3 D F)
  note IH1 = call1 e' = (a, M', vs); n + max_vars e'  length xs; ¬ contains_insync e1   ?concl e1 n e' xs pc stk loc
  note IH2 = xs. call1 e2 = (a, M', vs); n + max_vars e2  length xs; ¬ contains_insync e2  ?concl e2 n e2 xs 0 [] xs
  note IH3 = xs. call1 e3 = (a, M', vs); n + max_vars e3  length xs; ¬ contains_insync e3  ?concl e3 n e3 xs 0 [] xs
  note call = call1 _ = (a, M', vs)
  note len = n + max_vars _  length xs
  note bisim1 = P,e1,h  (e', xs)  (stk, loc, pc, None)
  note bisim2 = P,e2,h  (e2, loc)  ([], loc, 0, None)
  note cs = ¬ contains_insync _
  show ?case
  proof(cases "is_val e'")
    case True
    then obtain v where [simp]: "e' = Val v" by auto
    from bisim1 have "τExec_mover_a P t e1 h (stk, loc, pc, None) ([v], loc, length (compE2 e1), None)"
      and [simp]: "xs = loc" by(auto dest!: bisim1Val2D1)
    hence exec: "τExec_mover_a P t (e1∙compareAndSwap(DF, e2, e3)) h (stk, loc, pc, None) ([v], loc, length (compE2 e1), None)"
      by-(rule CAS_τExecrI1)
    show ?thesis
    proof(cases "is_val e2")
      case True
      then obtain v' where [simp]: "e2 = Val v'" by auto
      note exec also from bisim2
      have "τExec_mover_a P t e2 h ([], loc, 0, None) ([v'], loc, length (compE2 e2), None)"
        by(auto dest!: bisim1Val2D1)
      from CAS_τExecrI2[OF this, of e1 D F e3]
      have "τExec_mover_a P t (e1∙compareAndSwap(DF, e2, e3)) h ([v], loc, length (compE2 e1), None) ([v', v], loc, length (compE2 e1) + length (compE2 e2), None)" by simp
      also (rtranclp_trans) from call IH3[of loc] len cs obtain pc' stk' loc'
        where exec: "τExec_mover_a P t e3 h ([], loc, 0, None) (rev vs @ Addr a # stk', loc', pc', None)"
        and ins: "compE2 e3 ! pc' = Invoke M' (length vs)" "pc' < length (compE2 e3)"
        and bisim': "P,e3,h  (e3, loc)  (rev vs @ Addr a # stk', loc', pc', None)" by auto
      from CAS_τExecrI3[OF exec, of e1 D F e2 v' v]
      have "τExec_mover_a P t (e1∙compareAndSwap(DF, e2, e3)) h ([v', v], loc, length (compE2 e1) + length (compE2 e2), None)
                        ((rev vs @ Addr a # stk') @ [v', v], loc', length (compE2 e1) + length (compE2 e2) + pc', None)" by simp
      also (rtranclp_trans) from bisim'
      have "P,e1∙compareAndSwap(DF, e2, e3),h  (Val v∙compareAndSwap(DF, Val v', e3), xs)  ((rev vs @ Addr a # stk') @ [v', v], loc', length (compE2 e1) + length (compE2 e2) + pc', None)"
        by - (rule bisim1CAS3, simp)
      ultimately show ?thesis using ins by fastforce
    next
      case False
      note exec also from False call IH2[of loc] len cs obtain pc' stk' loc'
        where exec: "τExec_mover_a P t e2 h ([], xs, 0, None) (rev vs @ Addr a # stk', loc', pc', None)"
        and ins: "compE2 e2 ! pc' = Invoke M' (length vs)" "pc' < length (compE2 e2)"
        and bisim': "P,e2,h  (e2, xs)  (rev vs @ Addr a # stk', loc', pc', None)" by auto
      from CAS_τExecrI2[OF exec, of e1 D F e3 v]
      have "τExec_mover_a P t (e1∙compareAndSwap(DF, e2, e3)) h ([v], loc, length (compE2 e1), None) (rev vs @ Addr a # (stk' @ [v]), loc', length (compE2 e1) + pc', None)" by simp
      also (rtranclp_trans) from bisim'
      have "P,e1∙compareAndSwap(DF, e2, e3),h  (Val v∙compareAndSwap(DF, e2, e3), xs)  ((rev vs @ Addr a # stk') @ [v], loc', length (compE2 e1) + pc', None)"
        by(rule bisim1CAS2)
      ultimately show ?thesis using ins False by(fastforce intro!: exI)
    qed
  next
    case False with IH1 len False call cs show ?thesis
      by(clarsimp)(fastforce intro: bisim1_bisims1.bisim1CAS1 elim!: CAS_τExecrI1 intro!: exI)
  qed
next
  case (bisim1CAS2 e2 n e2' xs stk loc pc e1 e3 D F v)
  note IH2 = call1 e2' = (a, M', vs); n + max_vars e2'  length xs; ¬ contains_insync e2  ?concl e2 n e2' xs pc stk loc
  note IH3 = xs. call1 e3 = (a, M', vs); n + max_vars e3  length xs; ¬ contains_insync e3  ?concl e3 n e3 xs 0 [] xs
  note call = call1 _ = (a, M', vs)
  note len = n + max_vars _  length xs
  note bisim2 = P,e2,h  (e2', xs)  (stk, loc, pc, None)
  note cs = ¬ contains_insync _
  show ?case
  proof(cases "is_val e2'")
    case True
    then obtain v' where [simp]: "e2' = Val v'" by auto
    from bisim2 have exec: "τExec_mover_a P t e2 h (stk, loc, pc, None) ([v'], loc, length (compE2 e2), None)"
      and [simp]: "xs = loc" by(auto dest!: bisim1Val2D1)
    from CAS_τExecrI2[OF exec, of e1 D F e3 v]
    have "τExec_mover_a P t (e1∙compareAndSwap(DF, e2, e3)) h (stk @ [v], loc, length (compE2 e1) + pc, None) ([v', v], loc, length (compE2 e1) + length (compE2 e2), None)" by simp
    also from call IH3[of loc] len cs obtain pc' stk' loc'
      where exec: "τExec_mover_a P t e3 h ([], xs, 0, None) (rev vs @ Addr a # stk', loc', pc', None)"
      and ins: "compE2 e3 ! pc' = Invoke M' (length vs)" "pc' < length (compE2 e3)"
      and bisim': "P,e3,h  (e3, xs)  (rev vs @ Addr a # stk', loc', pc', None)" by auto
    from CAS_τExecrI3[OF exec, of e1 D F e2 v' v]
    have "τExec_mover_a P t (e1∙compareAndSwap(DF, e2, e3)) h ([v', v], loc, length (compE2 e1) + length (compE2 e2), None)
                       ((rev vs @ Addr a # stk') @ [v', v], loc', length (compE2 e1) + length (compE2 e2) + pc', None)" by simp
    also (rtranclp_trans) from bisim'
    have "P,e1∙compareAndSwap(DF, e2, e3),h  (Val v∙compareAndSwap(DF, Val v', e3), xs)  ((rev vs @ Addr a # stk') @ [v', v], loc', length (compE2 e1) + length (compE2 e2) + pc', None)"
      by(rule bisim1CAS3)
    ultimately show ?thesis using ins by(fastforce intro!: exI)
  next
    case False
    with IH2 len call cs obtain pc' loc' stk'
      where ins: "pc' < length (compE2 e2)" "compE2 e2 ! pc' = Invoke M' (length vs)"
      and exec: "τExec_mover_a P t e2 h (stk, loc, pc, None) (rev vs @ Addr a # stk', loc', pc', None)"
      and bisim': "P,e2,h  (e2', xs)  (rev vs @ Addr a # stk', loc', pc', None)" by fastforce
    from bisim' have "P,e1∙compareAndSwap(DF, e2, e3),h  (Val v∙compareAndSwap(DF, e2', e3), xs)  ((rev vs @ Addr a # stk') @ [v], loc', length (compE2 e1) + pc', None)"
      by(rule bisim1_bisims1.bisim1CAS2)
    with CAS_τExecrI2[OF exec, of e1 D F e3 v] ins False show ?thesis by(auto intro!: exI)
  qed
next
  case (bisim1CAS3 e3 n e3' xs stk loc pc e1 e2 D F v v')
  then obtain pc' loc' stk' where pc': "pc' < length (compE2 e3)" "compE2 e3 ! pc' = Invoke M' (length vs)"
    and exec: "τExec_mover_a P t e3 h (stk, loc, pc, None) (rev vs @ Addr a # stk', loc', pc', None)"
    and bisim': "P,e3,h  (e3', xs)  (rev vs @ Addr a # stk', loc', pc', None)" by fastforce
  from exec have "τExec_mover_a P t (e1∙compareAndSwap(DF, e2, e3)) h (stk @ [v', v], loc, length (compE2 e1) + length (compE2 e2) + pc, None)
                                    ((rev vs @ Addr a # stk') @ [v', v], loc', length (compE2 e1) + length (compE2 e2) + pc', None)"
    by(rule CAS_τExecrI3)
  moreover from bisim'
  have "P,e1∙compareAndSwap(DF, e2, e3),h  (Val v∙compareAndSwap(DF, Val v', e3'), xs)  ((rev vs @ Addr a # stk') @ [v', v], loc', length (compE2 e1) + length (compE2 e2) + pc', None)"
    by(rule bisim1_bisims1.bisim1CAS3)
  ultimately show ?case using pc' by(fastforce intro!: exI)
next
  case (bisim1Call1 obj n obj' xs stk loc pc ps M)
  note IH1 = call1 obj' = (a, M', vs); n + max_vars obj'  length xs; ¬ contains_insync obj  ?concl obj n obj' xs pc stk loc
  note IH2 = xs. calls1 ps = (a, M', vs); n + max_varss ps  length xs; ¬ contains_insyncs ps  ?concls ps n ps xs 0 [] xs
  note len = n + max_vars (obj'M(ps))  length xs
  note bisim1 = P,obj,h  (obj', xs)  (stk, loc, pc, None)
  note call = call1 (obj'M(ps)) = (a, M', vs)
  note cs = ¬ contains_insync (objM(ps))
  from call show ?case
  proof(cases rule: call1_callE)
    case CallObj
    hence "¬ is_val obj'" by auto
    with CallObj IH1 len cs show ?thesis
      by(clarsimp)(fastforce intro: bisim1_bisims1.bisim1Call1 elim!: Call_τExecrI1 intro!: exI)
  next
    case (CallParams v)
    with bisim1 have "τExec_mover_a P t obj h (stk, loc, pc, None) ([v], loc, length (compE2 obj), None)"
      and [simp]: "xs = loc" by(auto dest!: bisim1Val2D1)
    hence "τExec_mover_a P t (objM(ps)) h (stk, loc, pc, None) ([v], loc, length (compE2 obj), None)"
      by-(rule Call_τExecrI1)
    also from IH2[of loc] CallParams len cs obtain pc' stk' loc'
      where exec: "τExec_movesr_a P t ps h ([], loc, 0, None) (rev vs @ Addr a # stk', loc', pc', None)"
      and ins: "compEs2 ps ! pc' = Invoke M' (length vs)" "pc' < length (compEs2 ps)"
      and bisim': "P,ps,h  (ps, xs) [↔] (rev vs @ Addr a # stk',loc',pc',None)" by auto
    from Call_τExecrI2[OF exec, of obj M v]
    have "τExec_mover_a P t (objM(ps)) h ([v], loc, length (compE2 obj), None) (rev vs @ Addr a # (stk' @ [v]), loc', length (compE2 obj) + pc', None)" by simp
    also (rtranclp_trans)
    have "P,objM(ps),h  (Val vM(ps), xs)  ((rev vs @ Addr a # stk') @ [v], loc', length (compE2 obj) + pc', None)"
      using bisim' by(rule bisim1CallParams)
    ultimately show ?thesis using ins CallParams by fastforce
  next
    case [simp]: Call
    from bisim1 have "τExec_mover_a P t obj h (stk, loc, pc, None) ([Addr a], loc, length (compE2 obj), None)"
      and [simp]: "xs = loc" by(auto dest!: bisim1Val2D1)
    hence "τExec_mover_a P t (objM(ps)) h (stk, loc, pc, None) ([Addr a], loc, length (compE2 obj), None)"
      by-(rule Call_τExecrI1)
    also have "τExec_movesr_a P t ps h ([], xs, 0, None) (rev vs, xs, length (compEs2 ps), None)"
    proof(cases vs)
      case Nil with Call show ?thesis by(auto)
    next
      case Cons with Call bisims1_Val_τExec_moves[OF bisims1_refl[of P h "map Val vs" loc]]
      show ?thesis by(auto simp add: bsoks_def)
    qed
    from Call_τExecrI2[OF this, of obj M "Addr a"]
    have "τExec_mover_a P t (objM(ps)) h ([Addr a], loc, length (compE2 obj), None) (rev vs @ [Addr a], xs, length (compE2 obj) + length (compEs2 ps), None)" by simp
    also (rtranclp_trans)
    have "P,ps,h  (map Val vs,xs) [↔] (rev vs,xs,length (compEs2 ps),None)"
      by(rule bisims1_map_Val_append[OF bisims1Nil, simplified])(simp_all add: bsoks_def)
    hence "P,objM(ps),h  (addr aM(map Val vs), xs)  (rev vs @ [Addr a], xs, length (compE2 obj) + length (compEs2 ps), None)"
      by(rule bisim1CallParams)
    ultimately show ?thesis by fastforce
  qed
next
  case (bisim1CallParams ps n ps' xs stk loc pc obj M v)
  note IH2 = calls1 ps' = (a, M', vs); n + max_varss ps'  length xs; ¬ contains_insyncs ps  ?concls ps n ps' xs pc stk loc
  note bisim2 = P,ps,h  (ps', xs) [↔] (stk, loc, pc, None)
  note call = call1 (Val vM(ps')) = (a, M', vs)
  note len = n + max_vars (Val vM(ps'))  length xs
  note cs = ¬ contains_insync (objM(ps))
  from call show ?case
  proof(cases rule: call1_callE)
    case CallObj thus ?thesis by simp
  next
    case (CallParams v')
    with IH2 len cs obtain pc' stk' loc'
      where exec: "τExec_movesr_a P t ps h (stk, loc, pc, None) (rev vs @ Addr a # stk', loc', pc', None)"
      and ins: "pc' < length (compEs2 ps)" "compEs2 ps ! pc' = Invoke M' (length vs)"
      and bisim': "P,ps,h  (ps', xs) [↔] (rev vs @ Addr a # stk',loc',pc',None)" by auto
    from exec have "τExec_mover_a P t (objM(ps)) h (stk @ [v], loc, length (compE2 obj) + pc, None)
                                ((rev vs @ Addr a # stk') @ [v], loc', length (compE2 obj) + pc', None)"
      by(rule Call_τExecrI2)
    moreover have "P,objM(ps),h  (Val vM(ps'), xs) 
                                  ((rev vs @ Addr a # stk') @ [v], loc', length (compE2 obj) + pc', None)"
      using bisim' by(rule bisim1_bisims1.bisim1CallParams)
    ultimately show ?thesis using ins by fastforce
  next
    case Call
    hence [simp]: "v = Addr a" "ps' = map Val vs" "M' = M" by simp_all
    have "xs = loc  τExec_movesr_a P t ps h (stk, loc, pc, None) (rev vs, loc, length (compEs2 ps), None)"
    proof(cases "pc < length (compEs2 ps)")
      case True with bisim2 show ?thesis by(auto dest: bisims1_Val_τExec_moves)
    next
      case False
      from bisim2 have "pc  length (compEs2 ps)" by(rule bisims1_pc_length_compEs2)
      with False have "pc = length (compEs2 ps)" by simp
      with bisim2 show ?thesis by(auto dest: bisims1_Val_length_compEs2D)
    qed
    then obtain [simp]: "xs = loc"
      and exec: "τExec_movesr_a P t ps h (stk, loc, pc, None) (rev vs, loc, length (compEs2 ps), None)" ..
    from exec have "τExec_mover_a P t (objM(ps)) h (stk @ [v], loc, length (compE2 obj) + pc, None)
                              (rev vs @ [v], loc, length (compE2 obj) + length (compEs2 ps), None)"
      by(rule Call_τExecrI2)
    moreover from bisim2 have len: "length ps = length ps'" by(auto dest: bisims1_lengthD)
    moreover have "P,ps,h  (map Val vs,xs) [↔] (rev vs,xs,length (compEs2 ps),None)" using len
      by-(rule bisims1_map_Val_append[OF bisims1Nil, simplified], simp_all)
    hence "P,objM(ps),h  (addr aM(map Val vs), xs)  (rev vs @ [Addr a], xs, length (compE2 obj) + length (compEs2 ps), None)" by(rule bisim1_bisims1.bisim1CallParams)
    ultimately show ?thesis by fastforce
  qed
next
  case bisim1BlockSome1 thus ?case by simp
next
  case bisim1BlockSome2 thus ?case by simp
next
  case (bisim1BlockSome4 e n e' xs stk loc pc V T v)
  then obtain pc' loc' stk' where pc': "pc' < length (compE2 e)" "compE2 e ! pc' = Invoke M' (length vs)"
    and exec: "τExec_mover_a P t e h (stk, loc, pc, None) (rev vs @ Addr a # stk', loc', pc', None)"
    and bisim': "P,e,h  (e', xs)  (rev vs @ Addr a # stk', loc', pc', None)" by auto
  note Block_τExecrI_Some[OF exec, of V T v]
  moreover from bisim' have "P,{V:T=v; e},h  ({V:T=None; e'}, xs)  (rev vs @ Addr a # stk', loc', Suc (Suc pc'), None)"
    by(rule bisim1_bisims1.bisim1BlockSome4)
  ultimately show ?case using pc' by fastforce
next  
 case (bisim1BlockNone e n e' xs stk loc pc V T)
  then obtain pc' loc' stk' where pc': "pc' < length (compE2 e)" "compE2 e ! pc' = Invoke M' (length vs)"
    and exec: "τExec_mover_a P t e h (stk, loc, pc, None) (rev vs @ Addr a # stk', loc', pc', None)"
    and bisim': "P,e,h  (e', xs)  (rev vs @ Addr a # stk', loc', pc', None)" by auto
  note Block_τExecrI_None[OF exec, of V T]
  moreover from bisim' have "P,{V:T=None; e},h  ({V:T=None; e'}, xs)  (rev vs @ Addr a # stk', loc', pc', None)"
    by(rule bisim1_bisims1.bisim1BlockNone)
  ultimately show ?case using pc' by fastforce
next
  case bisim1Sync1 thus ?case
    by (auto)(fastforce intro: bisim1_bisims1.bisim1Sync1 elim!: Sync_τExecrI intro!: exI)
next
  case bisim1Sync2 thus ?case by simp
next
  case bisim1Sync3 thus ?case by simp
next
  case bisim1Sync4 thus ?case
    by (auto)(fastforce intro: bisim1_bisims1.bisim1Sync4 elim!: Insync_τExecrI intro!: exI)
next
  case bisim1Sync5 thus ?case by simp
next
  case bisim1Sync6 thus ?case by simp
next
  case bisim1Sync7 thus ?case by simp
next
  case bisim1Sync8 thus ?case by simp
next
  case bisim1Sync9 thus ?case by simp
next
  case bisim1InSync thus ?case by simp
next
  case bisim1Seq1 thus ?case
    by (auto)(fastforce intro: bisim1_bisims1.bisim1Seq1 elim!: Seq_τExecrI1 intro!: exI)
next
  case (bisim1Seq2 e2 n e' xs stk loc pc e1)
  then obtain pc' loc' stk' where pc': "pc' < length (compE2 e2)" "compE2 e2 ! pc' = Invoke M' (length vs)"
    and exec: "τExec_mover_a P t e2 h (stk, loc, pc, None) (rev vs @ Addr a # stk', loc', pc', None)"
    and bisim': "P,e2,h  (e', xs)  (rev vs @ Addr a # stk', loc', pc', None)" by auto
  from Seq_τExecrI2[OF exec, of e1] pc' bisim'
  show ?case by(fastforce intro: bisim1_bisims1.bisim1Seq2 intro!: exI)
next
  case bisim1Cond1 thus ?case
    by (auto)(fastforce intro: bisim1_bisims1.bisim1Cond1 elim!: Cond_τExecrI1 intro!: exI)+
next
  case (bisim1CondThen e1 n e' xs stk loc pc e e2)
  then obtain pc' loc' stk' where pc': "pc' < length (compE2 e1)" "compE2 e1 ! pc' = Invoke M' (length vs)"
    and exec: "τExec_mover_a P t e1 h (stk, loc, pc, None) (rev vs @ Addr a # stk', loc', pc', None)"
    and bisim': "P,e1,h  (e', xs)  (rev vs @ Addr a # stk', loc', pc', None)" by auto
  from Cond_τExecrI2[OF exec] pc' bisim' show ?case
    by(fastforce intro: bisim1_bisims1.bisim1CondThen intro!: exI)
next
  case (bisim1CondElse e2 n e' xs stk loc pc e e1)
  then obtain pc' loc' stk' where pc': "pc' < length (compE2 e2)" "compE2 e2 ! pc' = Invoke M' (length vs)"
    and exec: "τExec_mover_a P t e2 h (stk, loc, pc, None) (rev vs @ Addr a # stk', loc', pc', None)"
    and bisim': "P,e2,h  (e', xs)  (rev vs @ Addr a # stk', loc', pc', None)" by auto
  from Cond_τExecrI3[OF exec] pc' bisim' show ?case
    by (fastforce intro: bisim1_bisims1.bisim1CondElse intro!: exI)
next
  case bisim1While1 thus ?case by simp
next
  case bisim1While3 thus ?case
    by (auto)(fastforce intro: bisim1_bisims1.bisim1While3 elim!: While_τExecrI1 intro!: exI)+
next
  case bisim1While4 thus ?case
    by (auto)(fastforce intro!: While_τExecrI2 bisim1_bisims1.bisim1While4 exI)+
next
  case bisim1While6 thus ?case by simp
next
  case bisim1While7 thus ?case by simp
next
  case bisim1Throw1 thus ?case
    by (auto)(fastforce intro!: exI bisim1_bisims1.bisim1Throw1 elim!: Throw_τExecrI)+
next
  case bisim1Try thus ?case
    by (auto)(fastforce intro: bisim1_bisims1.bisim1Try elim!: Try_τExecrI1 intro!: exI)+
next
  case (bisim1TryCatch1 e n a' xs stk loc pc C' C e2 V)
  note IH2 = xs. call1 e2 = (a, M', vs); Suc n + max_vars e2  length xs; ¬ contains_insync e2   ?concl e2 (Suc V) e2 xs 0 [] xs
  note bisim1 = P,e,h  (Throw a', xs)  (stk, loc, pc, a')
  note bisim2 = xs. P,e2,h  (e2, xs)  ([], xs, 0, None)
  note len = n + max_vars {V:Class C=None; e2}  length (xs[V := Addr a'])
  note cs = ¬ contains_insync (try e catch(C V) e2)
  from bisim1 have [simp]: "xs = loc" by(auto dest: bisim1_ThrowD)
  from len have "τExec_mover_a P t (try e catch(C V) e2) h ([Addr a'], loc, Suc (length (compE2 e)), None) ([], loc[V := Addr a'], Suc (Suc (length (compE2 e))), None)"
    by -(rule τExecr1step,auto simp add: exec_move_def intro: τmove2_τmoves2.intros exec_instr)
  also from IH2[of "loc[V := Addr a']"] len call1 {V:Class C=None; e2} = (a, M', vs) cs
  obtain pc' loc' stk'
    where exec: "τExec_mover_a P t e2 h ([], loc[V := Addr a'], 0, None) (rev vs @ Addr a # stk', loc', pc', None)"
    and ins: "pc' < length (compE2 e2)" "compE2 e2 ! pc' = Invoke M' (length vs)"
    and bisim': "P,e2,h  (e2, loc[V := Addr a'])  (rev vs @ Addr a # stk', loc', pc', None)" by auto
  from Try_τExecrI2[OF exec, of e C V]
  have "τExec_mover_a P t (try e catch(C V) e2) h ([], loc[V := Addr a'], Suc (Suc (length (compE2 e))), None) (rev vs @ Addr a # stk', loc', Suc (Suc (length (compE2 e) + pc')), None)" by simp
  also from bisim'
  have "P,try e catch(C V) e2,h  ({V:Class C=None; e2}, loc[V := Addr a'])  (rev vs @ Addr a # stk', loc', (Suc (Suc (length (compE2 e) + pc'))), None)"
    by(rule bisim1TryCatch2)
  ultimately show ?case using ins by fastforce
next
  case bisim1TryCatch2 thus ?case
    by (auto)(fastforce intro!: Try_τExecrI2 bisim1_bisims1.bisim1TryCatch2 exI)+
next
  case bisims1Nil thus ?case by simp
next
  case (bisims1List1 e n e' xs stk loc pc es)
  note IH1 = call1 e' = (a, M', vs); n + max_vars e'  length xs; ¬ contains_insync e  ?concl e n e' xs pc stk loc
  note IH2 = xs. calls1 es = (a, M', vs); n + max_varss es  length xs; ¬ contains_insyncs es  ?concls es n es xs 0 [] xs
  note bisim1 = P,e,h  (e', xs)  (stk, loc, pc, None)
  note call = calls1 (e' # es) = (a, M', vs)
  note len = n + max_varss (e' # es)  length xs
  note cs = ¬ contains_insyncs (e # es)
  show ?case
  proof(cases "is_val e'")
    case True
    then obtain v where [simp]: "e' = Val v" by auto
    with bisim1 have "τExec_mover_a P t e h (stk, loc, pc, None) ([v], loc, length (compE2 e), None)"
      and [simp]: "xs = loc" by(auto dest!: bisim1Val2D1)
    hence "τExec_movesr_a P t (e # es) h (stk, loc, pc, None) ([v], loc, length (compE2 e), None)"
      by-(rule τExec_mover_τExec_movesr)
    also from call IH2[of loc] len cs obtain pc' stk' loc'
      where exec: "τExec_movesr_a P t es h ([], xs, 0, None) (rev vs @ Addr a # stk', loc', pc', None)"
      and ins: "compEs2 es ! pc' = Invoke M' (length vs)" "pc' < length (compEs2 es)"
      and bisim': "P,es,h  (es, xs) [↔] (rev vs @ Addr a # stk',loc',pc',None)" by auto
    from append_τExec_movesr[OF _ exec, of "[v]" "[e]"]
    have "τExec_movesr_a P t (e # es) h ([v], loc, length (compE2 e), None) (rev vs @ Addr a # (stk' @ [v]), loc', length (compE2 e) + pc', None)"
      by simp
    also (rtranclp_trans) from bisim'
    have "P,e # es,h  (Val v # es, xs) [↔]
                         ((rev vs @ Addr a # stk') @ [v],loc',length (compE2 e) + pc',None)"
      by(rule bisim1_bisims1.bisims1List2)
    ultimately show ?thesis using ins by fastforce
  next
    case False
    with call IH1 len cs show ?thesis
      by (auto)(fastforce intro!: τExec_mover_τExec_movesr bisim1_bisims1.bisims1List1 exI)+
  qed
next
  case (bisims1List2 es n es' xs stk loc pc e v)
  then obtain pc' stk' loc' where pc': "pc' < length (compEs2 es)" "compEs2 es ! pc' = Invoke M' (length vs)"
    and exec: "τExec_movesr_a P t es h (stk, loc, pc, None) (rev vs @ Addr a # stk', loc', pc', None)"
    and bisim': "P,es,h  (es', xs) [↔] (rev vs @ Addr a # stk', loc', pc', None)" by auto
  note append_τExec_movesr[OF _ exec, of "[v]" "[e]"]
  moreover from bisim'
  have "P,e#es,h  (Val v# es', xs) [↔] ((rev vs @ Addr a # stk') @ [v],loc',length (compE2 e) + pc',None)"
    by(rule bisim1_bisims1.bisims1List2)
  ultimately show ?case using pc' by fastforce
qed 

lemma fixes P :: "'addr J1_prog"
  shows bisim1_inline_call_Val:
  " P,e,h  (e', xs)  (stk, loc, pc, None); call1 e' = (a, M, vs);
     compE2 e ! pc = Invoke M n0 
     length stk  Suc (length vs)  n0 = length vs 
       P,e,h  (inline_call (Val v) e', xs)  (v # drop (Suc (length vs)) stk, loc, Suc pc, None)"
  (is " _; _; _   ?concl e n e' xs pc stk loc")

  and bisims1_inline_calls_Val:
  " P,es,h  (es',xs) [↔] (stk,loc,pc,None); calls1 es' = (a, M, vs);
     compEs2 es ! pc = Invoke M n0 
     length stk  Suc (length vs)  n0 = length vs 
       P,es,h  (inline_calls (Val v) es', xs) [↔] (v # drop (Suc (length vs)) stk,loc,Suc pc,None)"
  (is " _; _; _   ?concls es n es' xs pc stk loc")
proof(induct "(e', xs)" "(stk, loc, pc, None :: 'addr option)"
    and "(es', xs)" "(stk, loc, pc, None :: 'addr option)"
    arbitrary: e' xs stk loc pc and es' xs stk loc pc rule: bisim1_bisims1.inducts)
  case bisim1Val2 thus ?case by simp
next
  case bisim1New thus ?case by simp
next
  case bisim1NewArray thus ?case
    by(auto split: if_split_asm dest: bisim1_pc_length_compE2 intro: bisim1_bisims1.bisim1NewArray)
next
  case bisim1Cast thus ?case
    by(auto split: if_split_asm dest: bisim1_pc_length_compE2 intro: bisim1_bisims1.bisim1Cast)
next
  case bisim1InstanceOf thus ?case
    by(auto split: if_split_asm dest: bisim1_pc_length_compE2 intro: bisim1_bisims1.bisim1InstanceOf)
next
  case bisim1Val thus ?case by simp
next
  case bisim1Var thus ?case by simp
next
  case (bisim1BinOp1 e1 e' xs stk loc pc bop e2)
  note IH1 = call1 e' = (a, M, vs); compE2 e1 ! pc = Invoke M n0   ?concl e1 n e' xs pc stk loc
  note bisim1 = P,e1,h  (e', xs)  (stk, loc, pc, None)
  note call = call1 (e' «bop» e2) = (a, M, vs)
  note ins = compE2 (e1 «bop» e2) ! pc = Invoke M n0
  show ?case
  proof(cases "is_val e'")
    case False
    with bisim1 call have "pc < length (compE2 e1)" by(auto intro: bisim1_call_pcD)
    with call ins False IH1 show ?thesis
      by(auto intro: bisim1_bisims1.bisim1BinOp1)
  next
    case True
    then obtain v where [simp]: "e' = Val v" by auto
    from bisim1 have "pc  length (compE2 e1)" by(auto dest: bisim1_pc_length_compE2)
    moreover {
      assume pc: "pc < length (compE2 e1)"
      with bisim1 ins have False by(auto dest: bisim_Val_pc_not_Invoke) }
    ultimately have [simp]: "pc = length (compE2 e1)" by(cases "pc < length (compE2 e1)") auto
    with ins have False by(simp)
    thus ?thesis ..
  qed
next
  case (bisim1BinOp2 e2 e' xs stk loc pc e1 bop v1)
  note IH2 = call1 e' = (a, M, vs); compE2 e2 ! pc = Invoke M n0  ?concl e2 n e' xs pc stk loc
  note bisim2 = P,e2,h  (e', xs)  (stk, loc, pc, None)
  note call = call1 (Val v1 «bop» e') = (a, M, vs)
  note ins = compE2 (e1 «bop» e2) ! (length (compE2 e1) + pc) = Invoke M n0
  from call bisim2 have pc: "pc < length (compE2 e2)" by(auto intro: bisim1_call_pcD)
  with ins have ins': "compE2 e2 ! pc = Invoke M n0" by(simp)
  from IH2 ins' pc call show ?case by(auto dest: bisim1_bisims1.bisim1BinOp2)
next
  case bisim1LAss1 thus ?case
    by(auto split: if_split_asm dest: bisim1_pc_length_compE2 intro: bisim1_bisims1.bisim1LAss1)
next
  case bisim1LAss2 thus ?case by simp
next
  case (bisim1AAcc1 A a' xs stk loc pc i)
  note IH1 = call1 a' = (a, M, vs); compE2 A ! pc = Invoke M n0  ?concl A n a' xs pc stk loc
  note bisim1 = P,A,h  (a', xs)  (stk, loc, pc, None)
  note call = call1 (a'i) = (a, M, vs)
  note ins = compE2 (Ai) ! pc = Invoke M n0
  show ?case
  proof(cases "is_val a'")
    case False
    with bisim1 call have "pc < length (compE2 A)" by(auto intro: bisim1_call_pcD)
    with call ins False IH1 show ?thesis
      by(auto intro: bisim1_bisims1.bisim1AAcc1)
  next
    case True
    then obtain v where [simp]: "a' = Val v" by auto
    from bisim1 have "pc  length (compE2 A)" by(auto dest: bisim1_pc_length_compE2)
    moreover {
      assume pc: "pc < length (compE2 A)"
      with bisim1 ins have False by(auto dest: bisim_Val_pc_not_Invoke) }
    ultimately have [simp]: "pc = length (compE2 A)" by(cases "pc < length (compE2 A)") auto
    with ins have False by(simp)
    thus ?thesis ..
  qed
next
  case (bisim1AAcc2 i i' xs stk loc pc A v)
  note IH2 = call1 i' = (a, M, vs); compE2 i ! pc = Invoke M n0  ?concl i n i' xs pc stk loc
  note bisim2 = P,i,h  (i', xs)  (stk, loc, pc, None)
  note call = call1 (Val vi') = (a, M, vs)
  note ins = compE2 (Ai) ! (length (compE2 A) + pc) = Invoke M n0
  from call bisim2 have pc: "pc < length (compE2 i)" by(auto intro: bisim1_call_pcD)
  with ins have ins': "compE2 i ! pc = Invoke M n0" by(simp)
  from IH2 ins' pc call show ?case
    by(auto dest: bisim1_bisims1.bisim1AAcc2)
next
  case (bisim1AAss1 A a' xs stk loc pc i e)
  note IH1 = call1 a' = (a, M, vs); compE2 A ! pc = Invoke M n0  ?concl A n a' xs pc stk loc
  note bisim1 = P,A,h  (a', xs)  (stk, loc, pc, None)
  note call = call1 (a'i := e) = (a, M, vs)
  note ins = compE2 (Ai := e) ! pc = Invoke M n0
  show ?case
  proof(cases "is_val a'")
    case False
    with bisim1 call have "pc < length (compE2 A)" by(auto intro: bisim1_call_pcD)
    with call ins False IH1 show ?thesis by(auto intro: bisim1_bisims1.bisim1AAss1)
  next
    case True
    then obtain v where [simp]: "a' = Val v" by auto
    from bisim1 have "pc  length (compE2 A)" by(auto dest: bisim1_pc_length_compE2)
    moreover {
      assume pc: "pc < length (compE2 A)"
      with bisim1 ins have False by(auto dest: bisim_Val_pc_not_Invoke) }
    ultimately have [simp]: "pc = length (compE2 A)" by(cases "pc < length (compE2 A)") auto
    with ins have False by(simp)
    thus ?thesis ..
  qed
next
  case (bisim1AAss2 i i' xs stk loc pc A e v)
  note IH2 = call1 i' = (a, M, vs); compE2 i ! pc = Invoke M n0  ?concl i n i' xs pc stk loc
  note bisim2 = P,i,h  (i', xs)  (stk, loc, pc, None)
  note call = call1 (Val vi' := e) = (a, M, vs)
  note ins = compE2 (Ai := e) ! (length (compE2 A) + pc) = Invoke M n0
  show ?case
  proof(cases "is_val i'")
    case False
    with bisim2 call have pc: "pc < length (compE2 i)" by(auto intro: bisim1_call_pcD)
    with ins have ins': "compE2 i ! pc = Invoke M n0" by(simp)
    from IH2 ins' pc False call show ?thesis by(auto dest: bisim1_bisims1.bisim1AAss2)
  next
    case True
    then obtain v where [simp]: "i' = Val v" by auto
    from bisim2 have "pc  length (compE2 i)" by(auto dest: bisim1_pc_length_compE2)
    moreover {
      assume pc: "pc < length (compE2 i)"
      with bisim2 ins have False by(auto dest: bisim_Val_pc_not_Invoke) }
    ultimately have [simp]: "pc = length (compE2 i)" by(cases "pc < length (compE2 i)") auto
    with ins have False by(simp)
    thus ?thesis ..
  qed
next
  case (bisim1AAss3 e e' xs stk loc pc i A v v')
  note IH2 = call1 e' = (a, M, vs); compE2 e ! pc = Invoke M n0  ?concl e n e' xs pc stk loc
  note bisim3 = P,e,h  (e', xs)  (stk, loc, pc, None)
  note call = call1 (Val vVal v' := e') = (a, M, vs)
  note ins = compE2 (iA := e) ! (length (compE2 i) + length (compE2 A) + pc) = Invoke M n0
  from call bisim3 have pc: "pc < length (compE2 e)" by(auto intro: bisim1_call_pcD)
  with ins have ins': "compE2 e ! pc = Invoke M n0" by(simp)
  from IH2 ins' pc call show ?case by(auto dest: bisim1_bisims1.bisim1AAss3)
next
  case bisim1AAss4 thus ?case by simp
next
  case bisim1ALength thus ?case
    by(auto split: if_split_asm dest: bisim1_pc_length_compE2 intro: bisim1_bisims1.bisim1ALength)
next
  case bisim1FAcc thus ?case
    by(auto split: if_split_asm dest: bisim1_pc_length_compE2 intro: bisim1_bisims1.bisim1FAcc)
next
  case (bisim1FAss1 e1 e' xs stk loc pc F D e2)
  note IH1 = call1 e' = (a, M, vs); compE2 e1 ! pc = Invoke M n0  ?concl e1 n e' xs pc stk loc
  note bisim1 = P,e1,h  (e', xs)  (stk, loc, pc, None)
  note call = call1 (e'F{D} := e2) = (a, M, vs)
  note ins = compE2 (e1F{D} := e2) ! pc = Invoke M n0
  show ?case
  proof(cases "is_val e'")
    case False
    with bisim1 call have "pc < length (compE2 e1)" by(auto intro: bisim1_call_pcD)
    with call ins False IH1 show ?thesis
      by(auto intro: bisim1_bisims1.bisim1FAss1)
  next
    case True
    then obtain v where [simp]: "e' = Val v" by auto
    from bisim1 have "pc  length (compE2 e1)" by(auto dest: bisim1_pc_length_compE2)
    moreover {
      assume pc: "pc < length (compE2 e1)"
      with bisim1 ins have False by(auto dest: bisim_Val_pc_not_Invoke) }
    ultimately have [simp]: "pc = length (compE2 e1)" by(cases "pc < length (compE2 e1)") auto
    with ins have False by(simp)
    thus ?thesis ..
  qed
next
  case (bisim1FAss2 e2 e' xs stk loc pc e1 F D v1)
  note IH2 = call1 e' = (a, M, vs); compE2 e2 ! pc = Invoke M n0  ?concl e2 n e' xs pc stk loc
  note bisim2 = P,e2,h  (e', xs)  (stk, loc, pc, None)
  note call = call1 (Val v1F{D} := e') = (a, M, vs)
  note ins = compE2 (e1F{D} := e2) ! (length (compE2 e1) + pc) = Invoke M n0
  from call bisim2 have pc: "pc < length (compE2 e2)" by(auto intro: bisim1_call_pcD)
  with ins have ins': "compE2 e2 ! pc = Invoke M n0" by(simp)
  from IH2 ins' pc call show ?case by(auto dest: bisim1_bisims1.bisim1FAss2)
next
  case bisim1FAss3 thus ?case by simp
next
  case (bisim1CAS1 e1 e' xs stk loc pc D F e2 E3)
  note IH1 = call1 e' = (a, M, vs); compE2 e1 ! pc = Invoke M n0  ?concl e1 n e' xs pc stk loc
  note bisim1 = P,e1,h  (e', xs)  (stk, loc, pc, None)
  note call = call1 _ = (a, M, vs)
  note ins = compE2 _ ! pc = Invoke M n0
  show ?case
  proof(cases "is_val e'")
    case False
    with bisim1 call have "pc < length (compE2 e1)" by(auto intro: bisim1_call_pcD)
    with call ins False IH1 show ?thesis by(auto intro: bisim1_bisims1.bisim1CAS1)
  next
    case True
    then obtain v where [simp]: "e' = Val v" by auto
    from bisim1 have "pc  length (compE2 e1)" by(auto dest: bisim1_pc_length_compE2)
    moreover {
      assume pc: "pc < length (compE2 e1)"
      with bisim1 ins have False by(auto dest: bisim_Val_pc_not_Invoke) }
    ultimately have [simp]: "pc = length (compE2 e1)" by(cases "pc < length (compE2 e1)") auto
    with ins have False by(simp)
    thus ?thesis ..
  qed
next
  case (bisim1CAS2 e2 e2' xs stk loc pc e1 D F e3 v)
  note IH2 = call1 e2' = (a, M, vs); compE2 e2 ! pc = Invoke M n0  ?concl e2 n e2' xs pc stk loc
  note bisim2 = P,e2,h  (e2', xs)  (stk, loc, pc, None)
  note call = call1 _ = (a, M, vs)
  note ins = compE2 _ ! (length (compE2 e1) + pc) = Invoke M n0
  show ?case
  proof(cases "is_val e2'")
    case False
    with bisim2 call have pc: "pc < length (compE2 e2)" by(auto intro: bisim1_call_pcD)
    with ins have ins': "compE2 e2 ! pc = Invoke M n0" by(simp)
    from IH2 ins' pc False call show ?thesis by(auto dest: bisim1_bisims1.bisim1CAS2)
  next
    case True
    then obtain v where [simp]: "e2' = Val v" by auto
    from bisim2 have "pc  length (compE2 e2)" by(auto dest: bisim1_pc_length_compE2)
    moreover {
      assume pc: "pc < length (compE2 e2)"
      with bisim2 ins have False by(auto dest: bisim_Val_pc_not_Invoke) }
    ultimately have [simp]: "pc = length (compE2 e2)" by(cases "pc < length (compE2 e2)") auto
    with ins have False by(simp)
    thus ?thesis ..
  qed
next
  case (bisim1CAS3 e3 e3' xs stk loc pc e1 D F e2 v v')
  note IH2 = call1 e3' = (a, M, vs); compE2 e3 ! pc = Invoke M n0  ?concl e3 n e3' xs pc stk loc
  note bisim3 = P,e3,h  (e3', xs)  (stk, loc, pc, None)
  note call = call1 _ = (a, M, vs)
  note ins = compE2 _ ! (length (compE2 e1) + length (compE2 e2) + pc) = Invoke M n0
  from call bisim3 have pc: "pc < length (compE2 e3)" by(auto intro: bisim1_call_pcD)
  with ins have ins': "compE2 e3 ! pc = Invoke M n0" by(simp)
  from IH2 ins' pc call show ?case by(auto dest: bisim1_bisims1.bisim1CAS3)
next
  case (bisim1Call1 obj obj' xs stk loc pc M' ps)
  note IH1 = call1 obj' = (a, M, vs); compE2 obj ! pc = Invoke M n0  ?concl obj n obj' xs pc stk loc
  note bisim1 = P,obj,h  (obj', xs)  (stk, loc, pc, None)
  note call = call1 (obj'M'(ps)) = (a, M, vs)
  note ins = compE2 (objM'(ps)) ! pc = Invoke M n0
  show ?case
  proof(cases "is_val obj'")
    case False
    with call bisim1 have "pc < length (compE2 obj)" by(auto intro: bisim1_call_pcD)
    with call False ins IH1 False show ?thesis
      by(auto intro: bisim1_bisims1.bisim1Call1)
  next
    case True
    then obtain v' where [simp]: "obj' = Val v'" by auto
    from bisim1 have "pc  length (compE2 obj)" by(auto dest: bisim1_pc_length_compE2)
    moreover {
      assume pc: "pc < length (compE2 obj)"
      with bisim1 ins have False by(auto dest: bisim_Val_pc_not_Invoke) }
    ultimately have [simp]: "pc = length (compE2 obj)" by(cases "pc < length (compE2 obj)") auto
    with ins have [simp]: "ps = []" "M' = M"
      by(auto split: if_split_asm)(auto simp add: neq_Nil_conv)
    from ins call have [simp]: "vs = []" by(auto split: if_split_asm)
    with bisim1 have [simp]: "stk = [v']" "xs = loc" by(auto dest: bisim1_pc_length_compE2D)
    from bisim1Val2[of "length (compE2 (objM([])))" "objM([])" P h v loc] call ins
    show ?thesis by(auto simp add: is_val_iff)
  qed
next
  case (bisim1CallParams ps ps' xs stk loc pc obj M' v')
  note IH2 = calls1 ps' = (a, M, vs); compEs2 ps ! pc = Invoke M n0  ?concls ps n ps' xs pc stk loc
  note bisim = P,ps,h  (ps', xs) [↔] (stk, loc, pc, None)
  note call = call1 (Val v'M'(ps')) = (a, M, vs)
  note ins = compE2 (objM'(ps)) ! (length (compE2 obj) + pc) = Invoke M n0
  from call show ?case
  proof(cases rule: call1_callE)
    case CallObj thus ?thesis by simp
  next
    case (CallParams v'')
    hence [simp]: "v'' = v'" and call': "calls1 ps' = (a, M, vs)" by simp_all
    from bisim call' have pc: "pc < length (compEs2 ps)" by(rule bisims1_calls_pcD)
    with ins have ins': "compEs2 ps ! pc = Invoke M n0" by(simp)
    with IH2 call' ins pc
    have "P,ps,h  (inline_calls (Val v) ps', xs)
                [↔] (v # drop (Suc (length vs)) stk, loc, Suc pc, None)"
      and len: "Suc (length vs)  length stk" and n0: "n0 = length vs" by auto
    hence "P,objM'(ps),h  (Val v'M'(inline_calls (Val v) ps'), xs)
                            ((v # drop (Suc (length vs)) stk) @ [v'], loc, length (compE2 obj) + Suc pc, None)"
      by-(rule bisim1_bisims1.bisim1CallParams)
    thus ?thesis using call' len n0 by(auto simp add: is_vals_conv)
  next
    case Call
    hence [simp]: "v' = Addr a" "M' = M" "ps' = map Val vs" by auto
    from bisim have "pc  length (compEs2 ps)" by(auto dest: bisims1_pc_length_compEs2)
    moreover {
      assume pc: "pc < length (compEs2 ps)"
      with bisim ins have False by(auto dest: bisims_Val_pc_not_Invoke) }
    ultimately have [simp]: "pc = length (compEs2 ps)" by(cases "pc < length (compEs2 ps)") auto
    from bisim have [simp]: "stk = rev vs" "xs = loc" by(auto dest: bisims1_Val_length_compEs2D)
    hence "P,objM(ps),h  (Val v, loc)  ([v], loc, length (compE2 (objM(ps))), None)" by-(rule bisim1Val2, simp)
    moreover from bisim have "length ps = length ps'" by(rule bisims1_lengthD)
    ultimately show ?thesis using ins by(auto)
  qed
next
  case bisim1BlockSome1 thus ?case by simp
next
  case bisim1BlockSome2 thus ?case by simp
next
  case bisim1BlockSome4 thus ?case
    by(auto intro: bisim1_bisims1.bisim1BlockSome4)
next
  case bisim1BlockNone thus ?case
    by(auto intro: bisim1_bisims1.bisim1BlockNone)
next
  case bisim1Sync1 thus ?case
    by(auto split: if_split_asm dest: bisim1_pc_length_compE2 intro: bisim1_bisims1.bisim1Sync1)
next
  case bisim1Sync2 thus ?case by simp
next
  case bisim1Sync3 thus ?case by simp
next
  case bisim1Sync4 thus ?case
    by(auto split: if_split_asm dest: bisim1_pc_length_compE2 bisim1_bisims1.bisim1Sync4)
next
  case bisim1Sync5 thus ?case by simp
next
  case bisim1Sync6 thus ?case by simp
next
  case bisim1Sync7 thus ?case by simp
next
  case bisim1Sync8 thus ?case by simp
next
  case bisim1Sync9 thus ?case by simp
next
  case bisim1InSync thus ?case by(simp)
next
  case bisim1Seq1 thus ?case
    by(auto split: if_split_asm dest: bisim1_pc_length_compE2 intro: bisim1_bisims1.bisim1Seq1)
next
  case bisim1Seq2 thus ?case
    by(auto split: if_split_asm dest: bisim1_pc_length_compE2)(fastforce dest: bisim1_bisims1.bisim1Seq2)
next
  case bisim1Cond1 thus ?case
    by(auto split: if_split_asm dest: bisim1_pc_length_compE2 intro: bisim1_bisims1.bisim1Cond1)
next
  case (bisim1CondThen e1 stk loc pc e e2 e' xs) thus ?case
    by(auto split: if_split_asm dest: bisim1_pc_length_compE2)
      (fastforce dest: bisim1_bisims1.bisim1CondThen[where e=e and ?e2.0=e2])
next
  case (bisim1CondElse e2 stk loc pc e e1 e' xs) thus ?case
    by(auto split: if_split_asm dest: bisim1_pc_length_compE2)
      (fastforce dest: bisim1_bisims1.bisim1CondElse[where e=e and ?e1.0=e1])
next
  case bisim1While1 thus ?case by simp
next
  case bisim1While3 thus ?case
    by(auto split: if_split_asm dest: bisim1_pc_length_compE2 intro: bisim1_bisims1.bisim1While3)
next
  case bisim1While4 thus ?case
    by(auto split: if_split_asm dest: bisim1_pc_length_compE2)(fastforce dest: bisim1_bisims1.bisim1While4)
next
  case bisim1While6 thus ?case by simp
next
  case bisim1While7 thus ?case by simp
next
  case bisim1Throw1 thus ?case
    by(auto split: if_split_asm dest: bisim1_pc_length_compE2 intro: bisim1_bisims1.bisim1Throw1)
next
  case bisim1Try thus ?case
    by(auto split: if_split_asm dest: bisim1_pc_length_compE2 intro: bisim1_bisims1.bisim1Try)
next
  case bisim1TryCatch1 thus ?case by simp
next
  case bisim1TryCatch2 thus ?case
    by(fastforce dest: bisim1_bisims1.bisim1TryCatch2)
next
  case bisims1Nil thus ?case by simp
next
  case (bisims1List1 e e' xs stk loc pc es)
  note IH1 = call1 e' = (a, M, vs); compE2 e ! pc = Invoke M n0  ?concl e n e' xs pc stk loc
  note bisim1 = P,e,h  (e', xs)  (stk, loc, pc, None)
  note call = calls1 (e' # es) = (a, M, vs)
  note ins = compEs2 (e # es) ! pc = Invoke M n0
  show ?case
  proof(cases "is_val e'")
    case False
    with bisim1 call have "pc < length (compE2 e)" by(auto intro: bisim1_call_pcD)
    with call ins False IH1 show ?thesis
      by(auto intro: bisim1_bisims1.bisims1List1)
  next
    case True
    then obtain v where [simp]: "e' = Val v" by auto
    from bisim1 have "pc  length (compE2 e)" by(auto dest: bisim1_pc_length_compE2)
    moreover {
      assume pc: "pc < length (compE2 e)"
      with bisim1 ins have False by(auto dest: bisim_Val_pc_not_Invoke) }
    ultimately have [simp]: "pc = length (compE2 e)" by(cases "pc < length (compE2 e)") auto
    with ins call have False by(cases es)(auto)
    thus ?thesis ..
  qed
next
  case (bisims1List2 es es' xs stk loc pc e v')
  note IH = calls1 es' = (a, M, vs); compEs2 es ! pc = Invoke M n0  ?concls es n es' xs pc stk loc
  note call = calls1 (Val v' # es') = (a, M, vs)
  note bisim = P,es,h  (es', xs) [↔] (stk, loc, pc, None)
  note ins = compEs2 (e # es) ! (length (compE2 e) + pc) = Invoke M n0
  from call have call': "calls1 es' = (a, M, vs)" by simp
  with bisim have pc: "pc < length (compEs2 es)" by(rule bisims1_calls_pcD)
  with ins have ins': "compEs2 es ! pc = Invoke M n0" by(simp)
  from IH call ins pc show ?case
    by(auto split: if_split_asm dest: bisim1_bisims1.bisims1List2)
qed

lemma bisim1_fv: "P,e,h  (e', xs)  s  fv e'  fv e"
  and bisims1_fvs: "P,es,h  (es', xs) [↔] s  fvs es'  fvs es"
apply(induct "(e', xs)" s and "(es', xs)" s arbitrary: e' xs and es' xs rule: bisim1_bisims1.inducts)
apply(auto)
done


lemma bisim1_syncvars: " P,e,h  (e', xs)  s; syncvars e   syncvars e'"
  and bisims1_syncvarss: " P,es,h  (es', xs) [↔] s; syncvarss es   syncvarss es'"
apply(induct "(e', xs)" s and "(es', xs)" s arbitrary: e' xs and es' xs rule: bisim1_bisims1.inducts)
apply(auto dest: bisim1_fv)
done

declare pcs_stack_xlift [simp]

lemma bisim1_Val_τred1r:
  " P, E, h  (e, xs)  ([v], loc, length (compE2 E), None); n + max_vars e  length xs;  E n  
   τred1r P t h (e, xs) (Val v, loc)"

 and bisims1_Val_τReds1r:
  " P, Es, h  (es, xs) [↔] (rev vs, loc, length (compEs2 Es), None); n + max_varss es  length xs; ℬs Es n 
    τreds1r P t h (es, xs) (map Val vs, loc)"
proof(induct E n e xs stk"[v]" loc pc"length (compE2 E)" xcp"None::'addr option"
         and Es n es xs stk"rev vs" loc pc"length (compEs2 Es)" xcp"None::'addr option"
      arbitrary: v and vs rule: bisim1_bisims1_inducts_split)
  case bisim1BlockSome2 thus ?case by(simp (no_asm_use))
next
  case (bisim1BlockSome4 e n e' xs loc pc V T val)
  from  {V:T=val; e} n have [simp]: "n = V" and " e (Suc n)" by auto
  note len = n + max_vars {V:T=None; e'}  length xs
  hence V: "V < length xs" by simp
  from P,e,h  (e', xs)  ([v], loc, pc, None)
  have lenxs: "length xs = length loc" by(auto dest: bisim1_length_xs)
  note IH = pc = length (compE2 e); Suc n + max_vars e'  length xs;  e (Suc n)
              τred1r P t h (e', xs) (Val v, loc)
  with len Suc (Suc pc) = length (compE2 {V:T=val; e})  e (Suc n)
  have "τred1r P t h (e', xs) (Val v, loc)" by(simp)
  hence "τred1r P t h ({V:T=None; e'}, xs) ({V:T=None; Val v}, loc)"
    by(rule Block_None_τred1r_xt)
  thus ?case using V lenxs by(auto elim!: rtranclp.rtrancl_into_rtrancl intro: Red1Block τmove1BlockRed)
next
  case (bisim1BlockNone e n e' xs loc V T)
  from  {V:T=None; e} n have [simp]: "n = V" and " e (Suc n)" by auto
  note len = n + max_vars {V:T=None; e'}  length xs
  hence V: "V < length xs" by simp
  from P,e,h  (e', xs)  ([v], loc, length (compE2 {V:T=None; e}), None)
  have lenxs: "length xs = length loc" by(auto dest: bisim1_length_xs)
  note IH = length (compE2 {V:T=None; e}) = length (compE2 e); Suc n + max_vars e'  length xs;  e (Suc n) 
               τred1r P t h (e', xs) (Val v, loc)
  with len  e (Suc n) have "τred1r P t h (e', xs) (Val v, loc)" by(simp)
  hence "τred1r P t h ({V:T=None; e'}, xs) ({V:T=None; Val v}, loc)"
    by(rule Block_None_τred1r_xt)
  thus ?case using V lenxs by(auto elim!: rtranclp.rtrancl_into_rtrancl intro: Red1Block τmove1BlockRed)
next
  case (bisim1TryCatch2 e2 n e' xs loc pc e C V)
  from  (try e catch(C V) e2) n have [simp]: "n = V" and " e2 (Suc n)" by auto
  note len = n + max_vars {V:Class C=None; e'}  length xs
  hence V: "V < length xs" by simp
  from P,e2,h  (e', xs)  ([v], loc, pc, None)
  have lenxs: "length xs = length loc" by(auto dest: bisim1_length_xs)
  note IH = pc = length (compE2 e2); Suc n + max_vars e'  length xs;  e2 (Suc n)
              τred1r P t h (e', xs) (Val v, loc)
  with len Suc (Suc (length (compE2 e) + pc)) = length (compE2 (try e catch(C V) e2))  e2 (Suc n)
  have "τred1r P t h (e', xs) (Val v, loc)" by(simp)
  hence "τred1r P t h ({V:Class C=None; e'}, xs) ({V:Class C=None; Val v}, loc)"
    by(rule Block_None_τred1r_xt)
  thus ?case using V lenxs by(auto elim!: rtranclp.rtrancl_into_rtrancl intro: Red1Block τmove1BlockRed)
next
  case (bisims1List1 e n e' xs loc es)
  note bisim = P,e,h  (e', xs)  (rev vs, loc, length (compEs2 (e # es)), None)
  then have es: "es = []" and pc: "length (compEs2 (e # es)) = length (compE2 e)"
    by(auto dest: bisim1_pc_length_compE2)
  with bisim obtain val where stk: "rev vs = [val]" and e': "is_val e'  e' = Val val"
    by(auto dest: bisim1_pc_length_compE2D)
  with es pc bisims1List1 have "τred1r P t h (e', xs) (Val val, loc)" by simp
  with stk es show ?case by(auto intro: τred1r_inj_τreds1r)
next
  case (bisims1List2 es n es' xs stk loc pc e v)
  from stk @ [v] = rev vs obtain vs' where vs: "vs = v # vs'" by(cases vs) auto
  with bisims1List2 show ?case by(auto intro: τreds1r_cons_τreds1r)
qed(fastforce dest: bisim1_pc_length_compE2 bisims1_pc_length_compEs2)+

lemma exec_meth_stk_split:
  " P,E,h  (e, xs)  (stk, loc, pc, xcp);
     exec_meth_d (compP2 P) (compE2 E) (stack_xlift (length STK) (compxE2 E 0 0)) t
                h (stk @ STK, loc, pc, xcp) ta h' (stk', loc', pc', xcp') 
   stk''. stk' = stk'' @ STK  exec_meth_d (compP2 P) (compE2 E) (compxE2 E 0 0) t
                                             h (stk, loc, pc, xcp) ta h' (stk'', loc', pc', xcp')"
  (is " _; ?exec E stk STK loc pc xcp stk' loc' pc' xcp'   ?concl E stk STK loc pc xcp stk' loc' pc' xcp'")

  and exec_meth_stk_splits:
  " P,Es,h  (es,xs) [↔] (stk,loc,pc,xcp);
     exec_meth_d (compP2 P) (compEs2 Es) (stack_xlift (length STK) (compxEs2 Es 0 0)) t
                h (stk @ STK, loc, pc, xcp) ta h' (stk', loc', pc', xcp') 
   stk''. stk' = stk'' @ STK  exec_meth_d (compP2 P) (compEs2 Es) (compxEs2 Es 0 0) t
                                             h (stk, loc, pc, xcp) ta h' (stk'', loc', pc', xcp')"
  (is " _; ?execs Es stk STK loc pc xcp stk' loc' pc' xcp'   ?concls Es stk STK loc pc xcp stk' loc' pc' xcp'")
proof(induct E "n :: nat" e xs stk loc pc xcp and Es "n :: nat" es xs stk loc pc xcp
    arbitrary: stk' loc' pc' xcp' STK and stk' loc' pc' xcp' STK rule: bisim1_bisims1_inducts_split)
  case bisim1InSync thus ?case by(auto elim!: exec_meth.cases intro!: exec_meth.intros)
next
  case bisim1Val2 thus ?case by(auto dest: exec_meth_length_compE2_stack_xliftD)
next
  case bisim1New thus ?case
    by (fastforce elim: exec_meth.cases intro: exec_meth.intros split: if_split_asm cong del: image_cong_simp)
next
  case bisim1NewThrow thus ?case by(fastforce elim: exec_meth.cases intro: exec_meth.intros)
next
  case (bisim1NewArray e n e' xs stk loc pc xcp T)
  note bisim = P,e,h  (e', xs)  (stk, loc, pc, xcp)
  note IH = stk' loc' pc' xcp' STK. ?exec e stk STK loc pc xcp stk' loc' pc' xcp'
              ?concl e stk STK loc pc xcp stk' loc' pc' xcp'
  note exec = ?exec (newA Te) stk STK loc pc xcp stk' loc' pc' xcp'
  from bisim have pc: "pc  length (compE2 e)" by(rule bisim1_pc_length_compE2)
  show ?case
  proof(cases "pc < length (compE2 e)")
    case True
    with exec have "?exec e stk STK loc pc xcp stk' loc' pc' xcp'"
      by(simp add: compxE2_size_convs)(erule exec_meth_take)
    from IH[OF this] show ?thesis by auto
  next
    case False
    with pc have [simp]: "pc = length (compE2 e)" by simp
    with bisim obtain v where [simp]: "stk = [v]" "xcp = None"
      by(auto dest: dest: bisim1_pc_length_compE2D)
    with exec show ?thesis
      apply simp
      apply (erule exec_meth.cases)
       apply (auto 4 4 intro: exec_meth.intros split: if_split_asm cong del: image_cong_simp)
      done
  qed
next
  case (bisim1NewArrayThrow e n a xs stk loc pc T)
  note bisim = P,e,h  (Throw a, xs)  (stk, loc, pc, a)
  note IH = stk' loc' pc' xcp' STK. ?exec e stk STK loc pc a stk' loc' pc' xcp'
              ?concl e stk STK loc pc a stk' loc' pc' xcp'
  note exec = ?exec (newA Te) stk STK loc pc a stk' loc' pc' xcp'
  from bisim have pc: "pc < length (compE2 e)" and [simp]: "xs = loc"
    by(auto dest: bisim1_ThrowD)
  from exec have "?exec e stk STK loc pc a stk' loc' pc' xcp'"
    by(simp)(erule exec_meth_take[OF _ pc])
  from IH[OF this] show ?case by(auto)
next
  case bisim1NewArrayFail thus ?case
    by(auto elim!: exec_meth.cases dest: match_ex_table_pcsD simp add: stack_xlift_compxEs2 stack_xlift_compxE2)
next
  case (bisim1Cast e n e' xs stk loc pc xcp T)
  note bisim = P,e,h  (e', xs)  (stk, loc, pc, xcp)
  note IH = stk' loc' pc' xcp' STK. ?exec e stk STK loc pc xcp stk' loc' pc' xcp'
              ?concl e stk STK loc pc xcp stk' loc' pc' xcp'
  note exec = ?exec (Cast T e) stk STK loc pc xcp stk' loc' pc' xcp'
  from bisim have pc: "pc  length (compE2 e)" by(rule bisim1_pc_length_compE2)
  show ?case
  proof(cases "pc < length (compE2 e)")
    case True
    with exec have "?exec e stk STK loc pc xcp stk' loc' pc' xcp'"
      by(simp add: compxE2_size_convs)(erule exec_meth_take)
    from IH[OF this] show ?thesis by auto
  next
    case False
    with pc have [simp]: "pc = length (compE2 e)" by simp
    with bisim obtain v where [simp]: "stk = [v]" "xcp = None"
      by(auto dest: dest: bisim1_pc_length_compE2D)
    with exec show ?thesis apply(simp)
      by(erule exec_meth.cases)(auto intro!: exec_meth.intros split: if_split_asm)
  qed
next
  case (bisim1CastThrow e n a xs stk loc pc T)
  note bisim = P,e,h  (Throw a, xs)  (stk, loc, pc, a)
  note IH = stk' loc' pc' xcp' STK. ?exec e stk STK loc pc a stk' loc' pc' xcp'
              ?concl e stk STK loc pc a stk' loc' pc' xcp'
  note exec = ?exec (Cast T e) stk STK loc pc a stk' loc' pc' xcp'
  from bisim have pc: "pc < length (compE2 e)" and [simp]: "xs = loc"
    by(auto dest: bisim1_ThrowD)
  from exec have "?exec e stk STK loc pc a stk' loc' pc' xcp'"
    by(simp)(erule exec_meth_take[OF _ pc])
  from IH[OF this] show ?case by(auto)
next
  case bisim1CastFail thus ?case
    by(auto elim!: exec_meth.cases dest: match_ex_table_pcsD simp add: stack_xlift_compxEs2 stack_xlift_compxE2)
next
  case (bisim1InstanceOf e n e' xs stk loc pc xcp T)
  note bisim = P,e,h  (e', xs)  (stk, loc, pc, xcp)
  note IH = stk' loc' pc' xcp' STK. ?exec e stk STK loc pc xcp stk' loc' pc' xcp'
              ?concl e stk STK loc pc xcp stk' loc' pc' xcp'
  note exec = ?exec (e instanceof T) stk STK loc pc xcp stk' loc' pc' xcp'
  from bisim have pc: "pc  length (compE2 e)" by(rule bisim1_pc_length_compE2)
  show ?case
  proof(cases "pc < length (compE2 e)")
    case True
    with exec have "?exec e stk STK loc pc xcp stk' loc' pc' xcp'"
      by(simp add: compxE2_size_convs)(erule exec_meth_take)
    from IH[OF this] show ?thesis by auto
  next
    case False
    with pc have [simp]: "pc = length (compE2 e)" by simp
    with bisim obtain v where [simp]: "stk = [v]" "xcp = None"
      by(auto dest: dest: bisim1_pc_length_compE2D)
    with exec show ?thesis apply(simp)
      by(erule exec_meth.cases)(auto intro!: exec_meth.intros split: if_split_asm)
  qed
next
  case (bisim1InstanceOfThrow e n a xs stk loc pc T)
  note bisim = P,e,h  (Throw a, xs)  (stk, loc, pc, a)
  note IH = stk' loc' pc' xcp' STK. ?exec e stk STK loc pc a stk' loc' pc' xcp'
              ?concl e stk STK loc pc a stk' loc' pc' xcp'
  note exec = ?exec (e instanceof T) stk STK loc pc a stk' loc' pc' xcp'
  from bisim have pc: "pc < length (compE2 e)" and [simp]: "xs = loc"
    by(auto dest: bisim1_ThrowD)
  from exec have "?exec e stk STK loc pc a stk' loc' pc' xcp'"
    by(simp)(erule exec_meth_take[OF _ pc])
  from IH[OF this] show ?case by(auto)
next
  case bisim1Val thus ?case by(fastforce elim: exec_meth.cases intro: exec_meth.intros)
next
  case bisim1Var thus ?case by(fastforce elim: exec_meth.cases intro: exec_meth.intros)
next
  case (bisim1BinOp1 e1 n e1' xs stk loc pc xcp e2 bop)
  note IH1 = stk' loc' pc' xcp' STK. ?exec e1 stk STK loc pc xcp stk' loc' pc' xcp'
              ?concl e1 stk STK loc pc xcp stk' loc' pc' xcp'
  note IH2 = xs stk' loc' pc' xcp' STK. ?exec e2 [] STK xs 0 None stk' loc' pc' xcp'
              ?concl e2 [] STK xs 0 None stk' loc' pc' xcp'
  note bisim1 = P,e1,h  (e1', xs)  (stk, loc, pc, xcp)
  note bisim2 = P,e2,h  (e2, loc)  ([], loc, 0, None)
  note exec = ?exec (e1 «bop» e2) stk STK loc pc xcp stk' loc' pc' xcp'
  from bisim1 have pc: "pc  length (compE2 e1)" by(rule bisim1_pc_length_compE2)
  show ?case
  proof(cases "pc < length (compE2 e1)")
    case True
    with exec have "?exec e1 stk STK loc pc xcp stk' loc' pc' xcp'"
      by(simp add: compxE2_size_convs)(erule exec_meth_take_xt)
    from IH1[OF this] show ?thesis by auto
  next
    case False
    with pc have pc: "pc = length (compE2 e1)" by simp
    with exec have "pc'  length (compE2 e1)"
      by(simp add: compxE2_size_convs stack_xlift_compxE2)(auto split: bop.splits elim!: exec_meth_drop_xt_pc)
    then obtain PC where PC: "pc' = PC + length (compE2 e1)"
      by -(rule_tac PC34="pc' - length (compE2 e1)" in that, simp)
    from pc bisim1 obtain v where "stk = [v]" "xcp = None" by(auto dest: bisim1_pc_length_compE2D)
    with exec pc have "exec_meth_d (compP2 P) (compE2 e1 @ compE2 e2)
   (stack_xlift (length STK) (compxE2 e1 0 0 @ compxE2 e2 (length (compE2 e1)) (Suc 0))) t h (stk @ STK, loc, length (compE2 e1) + 0, xcp) ta h' (stk', loc', pc', xcp')"
      by-(rule exec_meth_take, auto)
    hence "?exec e2 [] (v # STK) loc 0 None stk' loc' (pc' - length (compE2 e1)) xcp'"
      using stk = [v] xcp = None
      by -(rule exec_meth_drop_xt, auto simp add: stack_xlift_compxE2 shift_compxE2)
    from IH2[OF this] PC obtain stk'' where stk': "stk' = stk'' @ v # STK"
      and "exec_meth_d (compP2 P) (compE2 e2) (compxE2 e2 0 0) t h ([], loc, 0, None) ta h' (stk'', loc', PC, xcp')" by auto
    hence "exec_meth_d (compP2 P) ((compE2 e1 @ compE2 e2) @ [BinOpInstr bop])
        (compxE2 e1 0 0 @ shift (length (compE2 e1)) (stack_xlift (length [v]) (compxE2 e2 0 0))) t h
        ([] @ [v], loc, length (compE2 e1) + 0, None) ta h' (stk'' @ [v], loc', length (compE2 e1) + PC, xcp')"
      apply -
      apply(rule exec_meth_append)
      apply(rule append_exec_meth_xt)
      apply(erule exec_meth_stk_offer)
      by(auto)
    thus ?thesis using stk = [v] xcp = None stk' pc PC
      by(clarsimp simp add: shift_compxE2 stack_xlift_compxE2 ac_simps)
  qed
next
  case (bisim1BinOp2 e2 n e2' xs stk loc pc xcp e1 bop v1)
  note IH2 = stk' loc' pc' xcp' STK. ?exec e2 stk STK loc pc xcp stk' loc' pc' xcp'
              ?concl e2 stk STK loc pc xcp stk' loc' pc' xcp'
  note bisim1 = P,e1,h  (e1, xs)  ([], xs, 0, None)
  note bisim2 = P,e2,h  (e2', xs)  (stk, loc, pc, xcp)
  note exec = ?exec (e1 «bop» e2) (stk @ [v1]) STK loc (length (compE2 e1) + pc) xcp stk' loc' pc' xcp'
  from bisim2 have pc: "pc  length (compE2 e2)" by(rule bisim1_pc_length_compE2)
  show ?case
  proof(cases "pc < length (compE2 e2)")
    case True
    from exec have "exec_meth_d (compP2 P) ((compE2 e1 @ compE2 e2) @ [BinOpInstr bop])
      (stack_xlift (length STK) (compxE2 e1 0 0) @ shift (length (compE2 e1)) (stack_xlift (length STK) (compxE2 e2 0 (Suc 0)))) t
      h (stk @ v1 # STK, loc, length (compE2 e1) + pc, xcp) ta h' (stk', loc', pc', xcp')" by(simp add: compxE2_size_convs)
    hence exec': "exec_meth_d (compP2 P) (compE2 e1 @ compE2 e2) (stack_xlift (length STK) (compxE2 e1 0 0) @
      shift (length (compE2 e1)) (stack_xlift (length STK) (compxE2 e2 0 (Suc 0)))) t
      h (stk @ v1 # STK, loc, length (compE2 e1) + pc, xcp) ta h' (stk', loc', pc', xcp')"
      by(rule exec_meth_take)(simp add: True)
    hence "exec_meth_d (compP2 P) (compE2 e2) (stack_xlift (length STK) (compxE2 e2 0 (Suc 0))) t
      h (stk @ v1 # STK, loc, pc, xcp) ta h' (stk', loc', pc' - length (compE2 e1), xcp')"
      by(rule exec_meth_drop_xt)(auto simp add: stack_xlift_compxE2)
    hence "?exec e2 stk (v1 # STK) loc pc xcp stk' loc' (pc' - length (compE2 e1)) xcp'"
      by(simp add: compxE2_stack_xlift_convs)
    from IH2[OF this] obtain stk'' where stk': "stk' = stk'' @ v1 # STK"
      and exec'': "exec_meth_d (compP2 P) (compE2 e2) (compxE2 e2 0 0) t h (stk, loc, pc, xcp) ta h' (stk'', loc', pc' - length (compE2 e1), xcp')" by blast
    from exec'' have "exec_meth_d (compP2 P) (compE2 e2) (stack_xlift (length [v1]) (compxE2 e2 0 0)) t h (stk @ [v1], loc, pc, xcp)
      ta h' (stk'' @ [v1], loc', pc' - length (compE2 e1), xcp')"
      by(rule exec_meth_stk_offer)
    hence "exec_meth_d (compP2 P) (compE2 e1 @ compE2 e2) (compxE2 e1 0 0 @ shift (length (compE2 e1)) (stack_xlift (length [v1]) (compxE2 e2 0 0))) t h (stk @ [v1], loc, length (compE2 e1) + pc, xcp)
      ta h' (stk'' @ [v1], loc', length (compE2 e1) + (pc' - length (compE2 e1)), xcp')"
      by(rule append_exec_meth_xt) auto
    hence "exec_meth_d (compP2 P) ((compE2 e1 @ compE2 e2) @ [BinOpInstr bop]) (compxE2 e1 0 0 @ shift (length (compE2 e1)) (stack_xlift (length [v1]) (compxE2 e2 0 0))) t h (stk @ [v1], loc, length (compE2 e1) + pc, xcp)
      ta h' (stk'' @ [v1], loc', length (compE2 e1) + (pc' - length (compE2 e1)), xcp')"
      by(rule exec_meth_append)
    moreover from exec' have "pc'  length (compE2 e1)"
      by(rule exec_meth_drop_xt_pc)(auto simp add: stack_xlift_compxE2)
    ultimately show ?thesis using stk' by(simp add: stack_xlift_compxE2 shift_compxE2)
  next
    case False
    with pc have pc: "pc = length (compE2 e2)" by simp
    with bisim2 obtain v2 where [simp]: "stk = [v2]" "xcp = None"
      by(auto dest: dest: bisim1_pc_length_compE2D)
    with exec pc show ?thesis 
      by(fastforce elim: exec_meth.cases split: sum.split_asm intro!: exec_meth.intros)
  qed
next
  case (bisim1BinOpThrow1 e1 n a xs stk loc pc e2 bop)
  note bisim1 = P,e1,h  (Throw a, xs)  (stk, loc, pc, a)
  note IH1 = stk' loc' pc' xcp' STK. ?exec e1 stk STK loc pc a stk' loc' pc' xcp'
              ?concl e1 stk STK loc pc a stk' loc' pc' xcp'
  note exec = ?exec (e1 «bop» e2) stk STK loc pc a stk' loc' pc' xcp'
  from bisim1 have pc: "pc < length (compE2 e1)" and [simp]: "xs = loc"
    by(auto dest: bisim1_ThrowD)
  from exec have "exec_meth_d (compP2 P) (compE2 e1 @ (compE2 e2 @ [BinOpInstr bop]))
     (stack_xlift (length STK) (compxE2 e1 0 0) @ shift (length (compE2 e1)) (stack_xlift (length STK) (compxE2 e2 0 (Suc 0)))) t
     h (stk @ STK, loc, pc, a) ta h' (stk', loc', pc', xcp')" by(simp add: compxE2_size_convs)
  hence "?exec e1 stk STK loc pc a stk' loc' pc' xcp'"
    by(rule exec_meth_take_xt)(rule pc)
  from IH1[OF this] show ?case by(auto)
next
  case (bisim1BinOpThrow2 e2 n a xs stk loc pc e1 bop v1)
  note bisim2 = P,e2,h  (Throw a, xs)  (stk, loc, pc, a)
  note IH2 = stk' loc' pc' xcp' STK. ?exec e2 stk STK loc pc a stk' loc' pc' xcp'
              ?concl e2 stk STK loc pc a stk' loc' pc' xcp'
  note exec = ?exec (e1 «bop» e2) (stk @ [v1]) STK loc (length (compE2 e1) + pc) a stk' loc' pc' xcp'
  from bisim2 have pc: "pc < length (compE2 e2)" and [simp]: "xs = loc"
    by(auto dest: bisim1_ThrowD)
  from exec have "exec_meth_d (compP2 P) ((compE2 e1 @ compE2 e2) @ [BinOpInstr bop])
     (stack_xlift (length STK) (compxE2 e1 0 0) @ shift (length (compE2 e1)) (stack_xlift (length STK) (compxE2 e2 0 (Suc 0))))
     t h (stk @ v1 # STK, loc, length (compE2 e1) + pc, a) ta h' (stk', loc', pc', xcp')"
    by(simp add: compxE2_size_convs)
  hence exec': "exec_meth_d (compP2 P) (compE2 e1 @ compE2 e2)
     (stack_xlift (length STK) (compxE2 e1 0 0) @ shift (length (compE2 e1)) (stack_xlift (length STK) (compxE2 e2 0 (Suc 0)))) t
     h (stk @ v1 # STK, loc, length (compE2 e1) + pc, a) ta h' (stk', loc', pc', xcp')"
    by(rule exec_meth_take)(simp add: pc)
  hence "exec_meth_d (compP2 P) (compE2 e2) (stack_xlift (length STK) (compxE2 e2 0 (Suc 0))) t
     h (stk @ v1 # STK, loc, pc, a) ta h' (stk', loc', pc' - length (compE2 e1), xcp')"
    by(rule exec_meth_drop_xt)(auto simp add: stack_xlift_compxE2)
  hence "?exec e2 stk (v1 # STK) loc pc a stk' loc' (pc' - length (compE2 e1)) xcp'"
    by(simp add: compxE2_stack_xlift_convs)
  from IH2[OF this] obtain stk'' where stk': "stk' = stk'' @ v1 # STK" and
    exec'': "exec_meth_d (compP2 P) (compE2 e2) (compxE2 e2 0 0) t h (stk, loc, pc, a) ta h' (stk'', loc', pc' - length (compE2 e1), xcp')" by blast
  from exec'' have "exec_meth_d (compP2 P) (compE2 e2) (stack_xlift (length [v1]) (compxE2 e2 0 0)) t h (stk @ [v1], loc, pc, a)
      ta h' (stk'' @ [v1], loc', pc' - length (compE2 e1), xcp')"
    by(rule exec_meth_stk_offer)
  hence "exec_meth_d (compP2 P) (compE2 e1 @ compE2 e2) (compxE2 e1 0 0 @ shift (length (compE2 e1)) (stack_xlift (length [v1]) (compxE2 e2 0 0))) t h (stk @ [v1], loc, length (compE2 e1) + pc, a)
      ta h' (stk'' @ [v1], loc', length (compE2 e1) + (pc' - length (compE2 e1)), xcp')"
    by(rule append_exec_meth_xt)(auto)
  hence "exec_meth_d (compP2 P) ((compE2 e1 @ compE2 e2) @ [BinOpInstr bop]) (compxE2 e1 0 0 @ shift (length (compE2 e1)) (stack_xlift (length [v1]) (compxE2 e2 0 0))) t h (stk @ [v1], loc, length (compE2 e1) + pc, a)
      ta h' (stk'' @ [v1], loc', length (compE2 e1) + (pc' - length (compE2 e1)), xcp')"
    by(rule exec_meth_append)
  moreover from exec' have pc': "pc'  length (compE2 e1)"
    by(rule exec_meth_drop_xt_pc)(auto simp add: stack_xlift_compxE2)
  ultimately show ?case using stk' by(auto simp add: stack_xlift_compxE2 shift_compxE2)
next
  case bisim1BinOpThrow thus ?case
    by(auto elim!: exec_meth.cases dest: match_ex_table_pcsD simp add: stack_xlift_compxEs2 stack_xlift_compxE2)
next
  case (bisim1LAss1 e n e' xs stk loc pc xcp V)
  note bisim = P,e,h  (e', xs)  (stk, loc, pc, xcp)
  note IH = stk' loc' pc' xcp' STK. ?exec e stk STK loc pc xcp stk' loc' pc' xcp'
              ?concl e stk STK loc pc xcp stk' loc' pc' xcp'
  note exec = ?exec (V := e) stk STK loc pc xcp stk' loc' pc' xcp'
  from bisim have pc: "pc  length (compE2 e)" by(rule bisim1_pc_length_compE2)
  show ?case
  proof(cases "pc < length (compE2 e)")
    case True
    with exec have "?exec e stk STK loc pc xcp stk' loc' pc' xcp'"
      by(simp add: compxE2_size_convs)(erule exec_meth_take)
    from IH[OF this] show ?thesis by auto
  next
    case False
    with pc have [simp]: "pc = length (compE2 e)" by simp
    with bisim obtain v where [simp]: "stk = [v]" "xcp = None"
      by(auto dest: dest: bisim1_pc_length_compE2D)
    with exec show ?thesis apply(simp)
      by(erule exec_meth.cases)(auto intro!: exec_meth.intros)
  qed
next
  case (bisim1LAss2 e n xs V)
  thus ?case by(fastforce elim: exec_meth.cases intro: exec_meth.intros)
next
  case (bisim1LAssThrow e n a xs stk loc pc V)
  note bisim = P,e,h  (Throw a, xs)  (stk, loc, pc, a)
  note IH = stk' loc' pc' xcp' STK. ?exec e stk STK loc pc a stk' loc' pc' xcp'
              ?concl e stk STK loc pc a stk' loc' pc' xcp'
  note exec = ?exec (V := e) stk STK loc pc a stk' loc' pc' xcp'
  from bisim have pc: "pc < length (compE2 e)" and [simp]: "xs = loc"
    by(auto dest: bisim1_ThrowD)
  from exec have "?exec e stk STK loc pc a stk' loc' pc' xcp'"
    by(simp)(erule exec_meth_take[OF _ pc])
  from IH[OF this] show ?case by(auto)
next
  case (bisim1AAcc1 a n a' xs stk loc pc xcp i)
  note IH1 = stk' loc' pc' xcp' STK. ?exec a stk STK loc pc xcp stk' loc' pc' xcp'
              ?concl a stk STK loc pc xcp stk' loc' pc' xcp'
  note IH2 = xs stk' loc' pc' xcp' STK. ?exec i [] STK xs 0 None stk' loc' pc' xcp'
              ?concl i [] STK xs 0 None stk' loc' pc' xcp'
  note bisim1 = P,a,h  (a', xs)  (stk, loc, pc, xcp)
  note bisim2 = P,i,h  (i, loc)  ([], loc, 0, None)
  note exec = ?exec (ai) stk STK loc pc xcp stk' loc' pc' xcp'
  from bisim1 have pc: "pc  length (compE2 a)" by(rule bisim1_pc_length_compE2)
  show ?case
  proof(cases "pc < length (compE2 a)")
    case True
    with exec have "?exec a stk STK loc pc xcp stk' loc' pc' xcp'"
      by(simp add: compxE2_size_convs)(erule exec_meth_take_xt)
    from IH1[OF this] show ?thesis by auto
  next
    case False
    with pc have pc: "pc = length (compE2 a)" by simp
    with exec have "pc'  length (compE2 a)"
      by(simp add: compxE2_size_convs stack_xlift_compxE2)(auto elim!: exec_meth_drop_xt_pc)
    then obtain PC where PC: "pc' = PC + length (compE2 a)"
      by -(rule_tac PC34="pc' - length (compE2 a)" in that, simp)
    from pc bisim1 obtain v where "stk = [v]" "xcp = None" by(auto dest: bisim1_pc_length_compE2D)
    with exec pc have "exec_meth_d (compP2 P) (compE2 a @ compE2 i)
   (stack_xlift (length STK) (compxE2 a 0 0 @ compxE2 i (length (compE2 a)) (Suc 0))) t h (stk @ STK, loc, length (compE2 a) + 0, xcp) ta h' (stk', loc', pc', xcp')"
      by-(rule exec_meth_take, auto)
    hence "?exec i [] (v # STK) loc 0 None stk' loc' (pc' - length (compE2 a)) xcp'"
      using stk = [v] xcp = None
      by -(rule exec_meth_drop_xt, auto simp add: stack_xlift_compxE2 shift_compxE2)
    from IH2[OF this] PC obtain stk'' where stk': "stk' = stk'' @ v # STK"
      and "exec_meth_d (compP2 P) (compE2 i) (compxE2 i 0 0) t h ([], loc, 0, None) ta h' (stk'', loc', PC, xcp')" by auto
    hence "exec_meth_d (compP2 P) ((compE2 a @ compE2 i) @ [ALoad])
        (compxE2 a 0 0 @ shift (length (compE2 a)) (stack_xlift (length [v]) (compxE2 i 0 0))) t h
        ([] @ [v], loc, length (compE2 a) + 0, None) ta h' (stk'' @ [v], loc', length (compE2 a) + PC, xcp')"
      apply -
      apply(rule exec_meth_append)
      apply(rule append_exec_meth_xt)
      apply(erule exec_meth_stk_offer)
      by(auto)
    thus ?thesis using stk = [v] xcp = None stk' pc PC
      by(clarsimp simp add: shift_compxE2 stack_xlift_compxE2 ac_simps)
  qed
next
  case (bisim1AAcc2 i n i' xs stk loc pc xcp a v1)
  note IH2 = stk' loc' pc' xcp' STK. ?exec i stk STK loc pc xcp stk' loc' pc' xcp'
              ?concl i stk STK loc pc xcp stk' loc' pc' xcp'
  note bisim2 = P,i,h  (i', xs)  (stk, loc, pc, xcp)
  note exec = ?exec (ai) (stk @ [v1]) STK loc (length (compE2 a) + pc) xcp stk' loc' pc' xcp'
  from bisim2 have pc: "pc  length (compE2 i)" by(rule bisim1_pc_length_compE2)
  show ?case
  proof(cases "pc < length (compE2 i)")
    case True
    from exec have "exec_meth_d (compP2 P) ((compE2 a @ compE2 i) @ [ALoad])
      (stack_xlift (length STK) (compxE2 a 0 0) @ shift (length (compE2 a)) (stack_xlift (length STK) (compxE2 i 0 (Suc 0)))) t
      h (stk @ v1 # STK, loc, length (compE2 a) + pc, xcp) ta h' (stk', loc', pc', xcp')" by(simp add: compxE2_size_convs)
    hence exec': "exec_meth_d (compP2 P) (compE2 a @ compE2 i) (stack_xlift (length STK) (compxE2 a 0 0) @
      shift (length (compE2 a)) (stack_xlift (length STK) (compxE2 i 0 (Suc 0)))) t
      h (stk @ v1 # STK, loc, length (compE2 a) + pc, xcp) ta h' (stk', loc', pc', xcp')"
      by(rule exec_meth_take)(simp add: True)
    hence "exec_meth_d (compP2 P) (compE2 i) (stack_xlift (length STK) (compxE2 i 0 (Suc 0))) t
      h (stk @ v1 # STK, loc, pc, xcp) ta h' (stk', loc', pc' - length (compE2 a), xcp')"
      by(rule exec_meth_drop_xt)(auto simp add: stack_xlift_compxE2)
    hence "?exec i stk (v1 # STK) loc pc xcp stk' loc' (pc' - length (compE2 a)) xcp'"
      by(simp add: compxE2_stack_xlift_convs)
    from IH2[OF this] obtain stk'' where stk': "stk' = stk'' @ v1 # STK"
      and exec'': "exec_meth_d (compP2 P) (compE2 i) (compxE2 i 0 0) t h (stk, loc, pc, xcp) ta h' (stk'', loc', pc' - length (compE2 a), xcp')" by blast
    from exec'' have "exec_meth_d (compP2 P) (compE2 i) (stack_xlift (length [v1]) (compxE2 i 0 0)) t h (stk @ [v1], loc, pc, xcp)
      ta h' (stk'' @ [v1], loc', pc' - length (compE2 a), xcp')"
      by(rule exec_meth_stk_offer)
    hence "exec_meth_d (compP2 P) (compE2 a @ compE2 i) (compxE2 a 0 0 @ shift (length (compE2 a)) (stack_xlift (length [v1]) (compxE2 i 0 0))) t h (stk @ [v1], loc, length (compE2 a) + pc, xcp)
      ta h' (stk'' @ [v1], loc', length (compE2 a) + (pc' - length (compE2 a)), xcp')"
      by(rule append_exec_meth_xt) auto
    hence "exec_meth_d (compP2 P) ((compE2 a @ compE2 i) @ [ALoad]) (compxE2 a 0 0 @ shift (length (compE2 a)) (stack_xlift (length [v1]) (compxE2 i 0 0))) t h (stk @ [v1], loc, length (compE2 a) + pc, xcp)
      ta h' (stk'' @ [v1], loc', length (compE2 a) + (pc' - length (compE2 a)), xcp')"
      by(rule exec_meth_append)
    moreover from exec' have "pc'  length (compE2 a)"
      by(rule exec_meth_drop_xt_pc)(auto simp add: stack_xlift_compxE2)
    ultimately show ?thesis using stk' by(simp add: stack_xlift_compxE2 shift_compxE2)
  next
    case False
    with pc have pc: "pc = length (compE2 i)" by simp
    with bisim2 obtain v2 where [simp]: "stk = [v2]" "xcp = None"
      by(auto dest: dest: bisim1_pc_length_compE2D)
    with exec pc show ?thesis
      by(clarsimp)(erule exec_meth.cases, auto intro!: exec_meth.intros split: if_split_asm)
  qed
next
  case (bisim1AAccThrow1 A n a xs stk loc pc i)
  note bisim1 = P,A,h  (Throw a, xs)  (stk, loc, pc, a)
  note IH1 = stk' loc' pc' xcp' STK. ?exec A stk STK loc pc a stk' loc' pc' xcp'
              ?concl A stk STK loc pc a stk' loc' pc' xcp'
  note exec = ?exec (Ai) stk STK loc pc a stk' loc' pc' xcp'
  from bisim1 have pc: "pc < length (compE2 A)" and [simp]: "xs = loc"
    by(auto dest: bisim1_ThrowD)
  from exec have "exec_meth_d (compP2 P) (compE2 A @ (compE2 i @ [ALoad]))
     (stack_xlift (length STK) (compxE2 A 0 0) @ shift (length (compE2 A)) (stack_xlift (length STK) (compxE2 i 0 (Suc 0)))) t
     h (stk @ STK, loc, pc, a) ta h' (stk', loc', pc', xcp')" by(simp add: compxE2_size_convs)
  hence "?exec A stk STK loc pc a stk' loc' pc' xcp'" by(rule exec_meth_take_xt)(rule pc)
  from IH1[OF this] show ?case by(auto)
next
  case (bisim1AAccThrow2 i n a xs stk loc pc A v1)
  note bisim2 = P,i,h  (Throw a, xs)  (stk, loc, pc, a)
  note IH2 = stk' loc' pc' xcp' STK. ?exec i stk STK loc pc a stk' loc' pc' xcp'
              ?concl i stk STK loc pc a stk' loc' pc' xcp'
  note exec = ?exec (Ai) (stk @ [v1]) STK loc (length (compE2 A) + pc) a stk' loc' pc' xcp'
  from bisim2 have pc: "pc < length (compE2 i)" and [simp]: "xs = loc"
    by(auto dest: bisim1_ThrowD)
  from exec have "exec_meth_d (compP2 P) ((compE2 A @ compE2 i) @ [ALoad])
     (stack_xlift (length STK) (compxE2 A 0 0) @ shift (length (compE2 A)) (stack_xlift (length STK) (compxE2 i 0 (Suc 0)))) t
     h (stk @ v1 # STK, loc, length (compE2 A) + pc, a) ta h' (stk', loc', pc', xcp')"
    by(simp add: compxE2_size_convs)
  hence exec': "exec_meth_d (compP2 P) (compE2 A @ compE2 i)
     (stack_xlift (length STK) (compxE2 A 0 0) @ shift (length (compE2 A)) (stack_xlift (length STK) (compxE2 i 0 (Suc 0)))) t
     h (stk @ v1 # STK, loc, length (compE2 A) + pc, a) ta h' (stk', loc', pc', xcp')"
    by(rule exec_meth_take)(simp add: pc)
  hence "exec_meth_d (compP2 P) (compE2 i) (stack_xlift (length STK) (compxE2 i 0 (Suc 0))) t
     h (stk @ v1 # STK, loc, pc, a) ta h' (stk', loc', pc' - length (compE2 A), xcp')"
    by(rule exec_meth_drop_xt)(auto simp add: stack_xlift_compxE2)
  hence "?exec i stk (v1 # STK) loc pc a stk' loc' (pc' - length (compE2 A)) xcp'"
    by(simp add: compxE2_stack_xlift_convs)
  from IH2[OF this] obtain stk'' where stk': "stk' = stk'' @ v1 # STK" and
    exec'': "exec_meth_d (compP2 P) (compE2 i) (compxE2 i 0 0) t h (stk, loc, pc, a) ta h' (stk'', loc', pc' - length (compE2 A), xcp')" by blast
  from exec'' have "exec_meth_d (compP2 P) (compE2 i) (stack_xlift (length [v1]) (compxE2 i 0 0)) t h (stk @ [v1], loc, pc, a)
      ta h' (stk'' @ [v1], loc', pc' - length (compE2 A), xcp')"
    by(rule exec_meth_stk_offer)
  hence "exec_meth_d (compP2 P) (compE2 A @ compE2 i) (compxE2 A 0 0 @ shift (length (compE2 A)) (stack_xlift (length [v1]) (compxE2 i 0 0))) t h (stk @ [v1], loc, length (compE2 A) + pc, a)
      ta h' (stk'' @ [v1], loc', length (compE2 A) + (pc' - length (compE2 A)), xcp')"
    by(rule append_exec_meth_xt)(auto)
  hence "exec_meth_d (compP2 P) ((compE2 A @ compE2 i) @ [ALoad]) (compxE2 A 0 0 @ shift (length (compE2 A)) (stack_xlift (length [v1]) (compxE2 i 0 0))) t h (stk @ [v1], loc, length (compE2 A) + pc, a)
      ta h' (stk'' @ [v1], loc', length (compE2 A) + (pc' - length (compE2 A)), xcp')"
    by(rule exec_meth_append)
  moreover from exec' have pc': "pc'  length (compE2 A)"
    by(rule exec_meth_drop_xt_pc)(auto simp add: stack_xlift_compxE2)
  ultimately show ?case using stk' by(auto simp add: stack_xlift_compxE2 shift_compxE2)
next
  case bisim1AAccFail thus ?case
    by(auto elim!: exec_meth.cases dest: match_ex_table_pcsD simp add: stack_xlift_compxEs2 stack_xlift_compxE2)
next
  case (bisim1AAss1 a n a' xs stk loc pc xcp i e)
  note IH1 = stk' loc' pc' xcp' STK. ?exec a stk STK loc pc xcp stk' loc' pc' xcp'
              ?concl a stk STK loc pc xcp stk' loc' pc' xcp'
  note IH2 = xs stk' loc' pc' xcp' STK. ?exec i [] STK xs 0 None stk' loc' pc' xcp'
              ?concl i [] STK xs 0 None stk' loc' pc' xcp'
  note bisim1 = P,a,h  (a', xs)  (stk, loc, pc, xcp)
  note bisim2 = P,i,h  (i, loc)  ([], loc, 0, None)
  note exec = ?exec (ai := e) stk STK loc pc xcp stk' loc' pc' xcp'
  from bisim1 have pc: "pc  length (compE2 a)" by(rule bisim1_pc_length_compE2)
  from exec have exec': "exec_meth_d (compP2 P) (compE2 a @ compE2 i @ compE2 e @ [AStore, Push Unit]) (stack_xlift (length STK) (compxE2 a 0 0) @ shift (length (compE2 a)) (stack_xlift (length STK) (compxE2 i 0 (Suc 0) @ compxE2 e (length (compE2 i)) (Suc (Suc 0))))) t
    h (stk @ STK, loc, pc, xcp) ta h' (stk', loc', pc', xcp')"
    by(simp add: compxE2_size_convs)
  show ?case
  proof(cases "pc < length (compE2 a)")
    case True
    with exec' have "?exec a stk STK loc pc xcp stk' loc' pc' xcp'" by(rule exec_meth_take_xt)
    from IH1[OF this] show ?thesis by auto
  next
    case False
    with pc have pc: "pc = length (compE2 a)" by simp
    with exec' have "pc'  length (compE2 a)" by -(erule exec_meth_drop_xt_pc, auto)
    then obtain PC where PC: "pc' = PC + length (compE2 a)"
      by -(rule_tac PC34="pc' - length (compE2 a)" in that, simp)
    from pc bisim1 obtain v where "stk = [v]" "xcp = None" by(auto dest: bisim1_pc_length_compE2D)
    with exec PC pc
    have "exec_meth_d (compP2 P) ((compE2 a @ compE2 i) @ compE2 e @ [AStore, Push Unit]) (stack_xlift (length STK) (compxE2 a 0 0 @ shift (length (compE2 a)) (compxE2 i 0 (Suc 0))) @ shift (length (compE2 a @ compE2 i)) (compxE2 e 0 (length STK + Suc (Suc 0)))) t
    h (v # STK, loc, length (compE2 a) + 0, None) ta h' (stk', loc', length (compE2 a) + PC, xcp')" 
      by(simp add: shift_compxE2 stack_xlift_compxE2 ac_simps)
    hence "exec_meth_d (compP2 P) (compE2 a @ compE2 i)
   (stack_xlift (length STK) (compxE2 a 0 0 @ shift (length (compE2 a)) (compxE2 i 0 (Suc 0)))) t h (v # STK, loc, length (compE2 a) + 0, None) ta h' (stk', loc', length (compE2 a) + PC, xcp')"
      by(rule exec_meth_take_xt) simp
    hence "?exec i [] (v # STK) loc 0 None stk' loc' ((length (compE2 a) + PC) - length (compE2 a)) xcp'"
      by -(rule exec_meth_drop_xt, auto simp add: stack_xlift_compxE2 shift_compxE2)
    from IH2[OF this] PC obtain stk'' where stk': "stk' = stk'' @ v # STK"
      and "exec_meth_d (compP2 P) (compE2 i) (compxE2 i 0 0) t h ([], loc, 0, None) ta h' (stk'', loc', PC, xcp')" by auto
    hence "exec_meth_d (compP2 P) ((compE2 a @ compE2 i) @ (compE2 e @ [AStore, Push Unit]))
        ((compxE2 a 0 0 @ shift (length (compE2 a)) (stack_xlift (length [v]) (compxE2 i 0 0))) @
         shift (length (compE2 a @ compE2 i)) (compxE2 e 0 (Suc (Suc 0)))) t h
        ([] @ [v], loc, length (compE2 a) + 0, None) ta h' (stk'' @ [v], loc', length (compE2 a) + PC, xcp')"
      apply -
      apply(rule exec_meth_append_xt)
      apply(rule append_exec_meth_xt)
      apply(erule exec_meth_stk_offer)
      by(auto)
    thus ?thesis using stk = [v] xcp = None stk' pc PC
      by(clarsimp simp add: shift_compxE2 stack_xlift_compxE2 ac_simps)
  qed
next
  case (bisim1AAss2 i n i' xs stk loc pc xcp a e v)
  note IH2 = stk' loc' pc' xcp' STK. ?exec i stk STK loc pc xcp stk' loc' pc' xcp'
              ?concl i stk STK loc pc xcp stk' loc' pc' xcp'
  note IH3 = xs stk' loc' pc' xcp' STK. ?exec e [] STK xs 0 None stk' loc' pc' xcp'
              ?concl e [] STK xs 0 None stk' loc' pc' xcp'
  note bisim2 = P,i,h  (i', xs)  (stk, loc, pc, xcp)
  note bisim3 = P,e,h  (e, loc)  ([], loc, 0, None)
  note exec = ?exec (ai := e) (stk @ [v]) STK loc (length (compE2 a) + pc) xcp stk' loc' pc' xcp'
  from bisim2 have pc: "pc  length (compE2 i)" by(rule bisim1_pc_length_compE2)
  from exec have exec': "v'. exec_meth_d (compP2 P) ((compE2 a @ compE2 i) @ compE2 e @ [AStore, Push Unit]) ((compxE2 a 0 (length STK) @ shift (length (compE2 a)) (stack_xlift (length (v # STK)) (compxE2 i 0 0))) @ shift (length (compE2 a @ compE2 i)) (stack_xlift (length (v' # v # STK)) (compxE2 e 0 0))) t
    h (stk @ v # STK, loc, length (compE2 a) + pc, xcp) ta h' (stk', loc', pc', xcp')"
    by(simp add: shift_compxE2 stack_xlift_compxE2)
  show ?case
  proof(cases "pc < length (compE2 i)")
    case True with exec'[of arbitrary]
    have exec'': "exec_meth_d (compP2 P) (compE2 a @ compE2 i) (compxE2 a 0 (length STK) @ shift (length (compE2 a)) (stack_xlift (length (v # STK)) (compxE2 i 0 0))) t h (stk @ v # STK, loc, length (compE2 a) + pc, xcp) ta h' (stk', loc', pc', xcp')"
      by-(erule exec_meth_take_xt, simp)
    hence "?exec i stk (v # STK) loc pc xcp stk' loc' (pc' - length (compE2 a)) xcp'"
      by(rule exec_meth_drop_xt) auto
    from IH2[OF this] obtain stk'' where stk': "stk' = stk'' @ v # STK"
      and exec''': "exec_meth_d (compP2 P) (compE2 i) (compxE2 i 0 0) t h (stk, loc, pc, xcp) ta h' (stk'', loc', pc' - length (compE2 a), xcp')" by blast
    from exec''' have "exec_meth_d (compP2 P) ((compE2 a @ compE2 i) @ compE2 e @ [AStore, Push Unit]) ((compxE2 a 0 0 @ shift (length (compE2 a)) (stack_xlift (length [v]) (compxE2 i 0 0))) @ shift (length (compE2 a @ compE2 i)) (compxE2 e 0 (Suc (Suc 0)))) t h (stk @ [v], loc, length (compE2 a) + pc, xcp) ta h' (stk'' @ [v], loc', length (compE2 a) + (pc' - length (compE2 a)), xcp')"
      apply -
      apply(rule exec_meth_append_xt)
      apply(rule append_exec_meth_xt)
      apply(erule exec_meth_stk_offer)
      by auto
    moreover from exec'' have "pc'  length (compE2 a)"
      by(rule exec_meth_drop_xt_pc) auto
    ultimately show ?thesis using stk' by(auto simp add: shift_compxE2 stack_xlift_compxE2)
  next
    case False
    with pc have pc: "pc = length (compE2 i)" by simp
    with exec'[of arbitrary] have "pc'  length (compE2 a @ compE2 i)"
      by-(erule exec_meth_drop_xt_pc, auto simp add: shift_compxE2 stack_xlift_compxE2)
    then obtain PC where PC: "pc' = PC + length (compE2 a) + length (compE2 i)"
      by -(rule_tac PC34="pc' - length (compE2 a @ compE2 i)" in that, simp)
    from pc bisim2 obtain v' where stk: "stk = [v']" and xcp: "xcp = None" by(auto dest: bisim1_pc_length_compE2D)
    from exec'[of v'] 
    have "exec_meth_d (compP2 P) (compE2 e @ [AStore, Push Unit]) (stack_xlift (length (v' # v # STK)) (compxE2 e 0 0)) t
                    h (v' # v # STK, loc, 0, xcp) ta h' (stk', loc', pc' - length (compE2 a @ compE2 i), xcp')"
      unfolding stk pc append_Cons append_Nil
      by -(rule exec_meth_drop_xt, simp only: add_0_right length_append, auto simp add: shift_compxE2 stack_xlift_compxE2)
    with PC xcp have "?exec e [] (v' # v # STK) loc 0 None stk' loc' PC xcp'"
      by -(rule exec_meth_take,auto)
    from IH3[OF this] obtain stk'' where stk': "stk' = stk'' @ v' # v # STK"
      and "exec_meth_d (compP2 P) (compE2 e) (compxE2 e 0 0) t h ([], loc, 0, None) ta h' (stk'', loc', PC, xcp')"  by auto
    hence "exec_meth_d (compP2 P) (((compE2 a @ compE2 i) @ compE2 e) @ [AStore, Push Unit]) ((compxE2 a 0 0 @ compxE2 i (length (compE2 a)) (Suc 0)) @ shift (length (compE2 a @ compE2 i)) (stack_xlift (length [v', v]) (compxE2 e 0 0))) t h ([] @ [v', v], loc, length (compE2 a @ compE2 i) + 0, None) ta h' (stk'' @ [v', v], loc', length (compE2 a @ compE2 i) + PC, xcp')"
      apply -
      apply(rule exec_meth_append)
      apply(rule append_exec_meth_xt)
      apply(erule exec_meth_stk_offer)
      by auto
    thus ?thesis using stk xcp stk' pc PC
      by(clarsimp simp add: shift_compxE2 stack_xlift_compxE2 ac_simps)
  qed
next
  case (bisim1AAss3 e n e' xs stk loc pc xcp a i v1 v2)
  note IH3 = stk' loc' pc' xcp' STK. ?exec e stk STK loc pc xcp stk' loc' pc' xcp'
              ?concl e stk STK loc pc xcp stk' loc' pc' xcp'
  note bisim3 = P,e,h  (e', xs)  (stk, loc, pc, xcp)
  note exec = ?exec (ai := e) (stk @ [v2, v1]) STK loc (length (compE2 a) + length (compE2 i) + pc) xcp stk' loc' pc' xcp'
  from bisim3 have pc: "pc  length (compE2 e)" by(rule bisim1_pc_length_compE2)
  show ?case
  proof(cases "pc < length (compE2 e)")
    case True
    from exec have "exec_meth_d (compP2 P) (((compE2 a @ compE2 i) @ compE2 e) @ [AStore, Push Unit])
      ((compxE2 a 0 (length STK) @ compxE2 i (length (compE2 a)) (Suc (length STK))) @ shift (length (compE2 a @ compE2 i)) (stack_xlift (length (v2 # v1 # STK)) (compxE2 e 0 0))) t
      h (stk @ v2 # v1 # STK, loc, length (compE2 a @ compE2 i) + pc, xcp) ta h' (stk', loc', pc', xcp')"
      by(simp add: shift_compxE2 stack_xlift_compxE2)
    hence exec': "exec_meth_d (compP2 P) ((compE2 a @ compE2 i) @ compE2 e)
      ((compxE2 a 0 (length STK) @ compxE2 i (length (compE2 a)) (Suc (length STK))) @ shift (length (compE2 a @ compE2 i)) (stack_xlift (length (v2 # v1 # STK)) (compxE2 e 0 0))) t
      h (stk @ v2 # v1 # STK, loc, length (compE2 a @ compE2 i) + pc, xcp) ta h' (stk', loc', pc', xcp')"
      by(rule exec_meth_take)(simp add: True)
    hence "?exec e stk (v2 # v1 # STK) loc pc xcp stk' loc' (pc' - length (compE2 a @ compE2 i)) xcp'"
      by(rule exec_meth_drop_xt) auto
    from IH3[OF this] obtain stk'' where stk': "stk' = stk'' @ v2 # v1 # STK"
      and exec'': "exec_meth_d (compP2 P) (compE2 e) (compxE2 e 0 0) t h (stk, loc, pc, xcp) ta h' (stk'', loc', pc' - length (compE2 a @ compE2 i), xcp')" by blast
    from exec'' have "exec_meth_d (compP2 P) (compE2 e) (stack_xlift (length [v2, v1]) (compxE2 e 0 0)) t h (stk @ [v2, v1], loc, pc, xcp)
      ta h' (stk'' @ [v2, v1], loc', pc' - length (compE2 a @ compE2 i), xcp')"
      by(rule exec_meth_stk_offer)
    hence "exec_meth_d (compP2 P) ((compE2 a @ compE2 i) @ compE2 e) ((compxE2 a 0 0 @ compxE2 i (length (compE2 a)) (Suc 0)) @ shift (length (compE2 a @ compE2 i)) (stack_xlift (length [v2, v1]) (compxE2 e 0 0))) t
      h (stk @ [v2, v1], loc, length (compE2 a @ compE2 i) + pc, xcp)
      ta h' (stk'' @ [v2, v1], loc', length (compE2 a @ compE2 i) + (pc' - length (compE2 a @ compE2 i)), xcp')"
      by(rule append_exec_meth_xt) auto
    hence "exec_meth_d (compP2 P) (((compE2 a @ compE2 i) @ compE2 e) @ [AStore, Push Unit]) ((compxE2 a 0 0 @ compxE2 i (length (compE2 a)) (Suc 0)) @ shift (length (compE2 a @ compE2 i)) (stack_xlift (length [v2, v1]) (compxE2 e 0 0))) t
      h (stk @ [v2, v1], loc, length (compE2 a @ compE2 i) + pc, xcp)
      ta h' (stk'' @ [v2, v1], loc', length (compE2 a @ compE2 i) + (pc' - length (compE2 a @ compE2 i)), xcp')"
      by(rule exec_meth_append)
    moreover from exec' have "pc'  length (compE2 a @ compE2 i)"
      by(rule exec_meth_drop_xt_pc)(auto simp add: stack_xlift_compxE2)
    ultimately show ?thesis using stk' by(simp add: stack_xlift_compxE2 shift_compxE2)
  next
    case False
    with pc have pc: "pc = length (compE2 e)" by simp
    with bisim3 obtain v3 where [simp]: "stk = [v3]" "xcp = None"
      by(auto dest: dest: bisim1_pc_length_compE2D)
    with exec pc show ?thesis apply(simp)
      by(erule exec_meth.cases)(auto intro!: exec_meth.intros split: if_split_asm)
  qed
next
  case (bisim1AAssThrow1 A n a xs stk loc pc i e)
  note bisim1 = P,A,h  (Throw a, xs)  (stk, loc, pc, a)
  note IH1 = stk' loc' pc' xcp' STK. ?exec A stk STK loc pc a stk' loc' pc' xcp'
              ?concl A stk STK loc pc a stk' loc' pc' xcp'
  note exec = ?exec (Ai := e) stk STK loc pc a stk' loc' pc' xcp'
  from bisim1 have pc: "pc < length (compE2 A)" and [simp]: "xs = loc"
    by(auto dest: bisim1_ThrowD)
  from exec have "exec_meth_d (compP2 P) (compE2 A @ (compE2 i @ compE2 e @ [AStore, Push Unit]))
     (stack_xlift (length STK) (compxE2 A 0 0) @ shift (length (compE2 A)) (stack_xlift (length STK) (compxE2 i 0 (Suc 0) @ compxE2 e (length (compE2 i)) (Suc (Suc 0))))) t
     h (stk @ STK, loc, pc, a) ta h' (stk', loc', pc', xcp')" by(simp add: compxE2_size_convs)
  hence "?exec A stk STK loc pc a stk' loc' pc' xcp'" by(rule exec_meth_take_xt)(rule pc)
  from IH1[OF this] show ?case by(auto)
next
  case (bisim1AAssThrow2 i n a xs stk loc pc A e v1)
  note bisim2 = P,i,h  (Throw a, xs)  (stk, loc, pc, a)
  note IH2 = stk' loc' pc' xcp' STK. ?exec i stk STK loc pc a stk' loc' pc' xcp'
              ?concl i stk STK loc pc a stk' loc' pc' xcp'
  note exec = ?exec (Ai := e) (stk @ [v1]) STK loc (length (compE2 A) + pc) a stk' loc' pc' xcp'
  from bisim2 have pc: "pc < length (compE2 i)" and [simp]: "xs = loc"
    by(auto dest: bisim1_ThrowD)
  from exec have "exec_meth_d (compP2 P) ((compE2 A @ compE2 i) @ compE2 e @ [AStore, Push Unit])
     ((stack_xlift (length STK) (compxE2 A 0 0) @ shift (length (compE2 A)) (stack_xlift (length STK) (compxE2 i 0 (Suc 0)))) @ (shift (length (compE2 A @ compE2 i)) (compxE2 e 0 (Suc (Suc (length STK)))))) t
     h (stk @ v1 # STK, loc, length (compE2 A) + pc, a) ta h' (stk', loc', pc', xcp')"
    by(simp add: shift_compxE2 stack_xlift_compxE2 ac_simps)
  hence exec': "exec_meth_d (compP2 P) (compE2 A @ compE2 i)
     (stack_xlift (length STK) (compxE2 A 0 0) @ shift (length (compE2 A)) (stack_xlift (length STK) (compxE2 i 0 (Suc 0)))) t
     h (stk @ v1 # STK, loc, length (compE2 A) + pc, a) ta h' (stk', loc', pc', xcp')"
    by(rule exec_meth_take_xt)(simp add: pc)
  hence "exec_meth_d (compP2 P) (compE2 i) (stack_xlift (length STK) (compxE2 i 0 (Suc 0))) t
     h (stk @ v1 # STK, loc, pc, a) ta h' (stk', loc', pc' - length (compE2 A), xcp')"
    by(rule exec_meth_drop_xt)(auto simp add: stack_xlift_compxE2)
  hence "?exec i stk (v1 # STK) loc pc a stk' loc' (pc' - length (compE2 A)) xcp'"
    by(simp add: compxE2_stack_xlift_convs)
  from IH2[OF this] obtain stk'' where stk': "stk' = stk'' @ v1 # STK" and
    exec'': "exec_meth_d (compP2 P) (compE2 i) (compxE2 i 0 0) t h (stk, loc, pc, a) ta h' (stk'', loc', pc' - length (compE2 A), xcp')" by blast
  from exec'' have "exec_meth_d (compP2 P) (compE2 i) (stack_xlift (length [v1]) (compxE2 i 0 0)) t 
      h (stk @ [v1], loc, pc, a)
      ta h' (stk'' @ [v1], loc', pc' - length (compE2 A), xcp')"
    by(rule exec_meth_stk_offer)
  hence "exec_meth_d (compP2 P) (compE2 A @ compE2 i) (compxE2 A 0 0 @ shift (length (compE2 A)) (stack_xlift (length [v1]) (compxE2 i 0 0))) t 
      h (stk @ [v1], loc, length (compE2 A) + pc, a)
      ta h' (stk'' @ [v1], loc', length (compE2 A) + (pc' - length (compE2 A)), xcp')"
    by(rule append_exec_meth_xt)(auto)
  hence "exec_meth_d (compP2 P) ((compE2 A @ compE2 i) @ compE2 e @ [AStore, Push Unit]) ((compxE2 A 0 0 @ shift (length (compE2 A)) (stack_xlift (length [v1]) (compxE2 i 0 0))) @ (shift (length (compE2 A @ compE2 i)) (compxE2 e 0 (Suc (Suc 0))))) t
      h (stk @ [v1], loc, length (compE2 A) + pc, a)
      ta h' (stk'' @ [v1], loc', length (compE2 A) + (pc' - length (compE2 A)), xcp')"
    by(rule exec_meth_append_xt)
  moreover from exec' have pc': "pc'  length (compE2 A)"
    by(rule exec_meth_drop_xt_pc)(auto simp add: stack_xlift_compxE2)
  ultimately show ?case using stk' by(auto simp add: stack_xlift_compxE2 shift_compxE2)
next
  case (bisim1AAssThrow3 e n a xs stk loc pc A i v2 v1)
  note bisim3 = P,e,h  (Throw a, xs)  (stk, loc, pc, a)
  note IH3 = stk' loc' pc' xcp' STK. ?exec e stk STK loc pc a stk' loc' pc' xcp'
              ?concl e stk STK loc pc a stk' loc' pc' xcp'
  note exec = ?exec (Ai := e) (stk @ [v2, v1]) STK loc (length (compE2 A) + length (compE2 i) + pc) a stk' loc' pc' xcp'
  from bisim3 have pc: "pc < length (compE2 e)" and [simp]: "xs = loc"
    by(auto dest: bisim1_ThrowD)
  from exec have "exec_meth_d (compP2 P) (((compE2 A @ compE2 i) @ compE2 e) @ [AStore, Push Unit])
     ((stack_xlift (length STK) (compxE2 A 0 0 @ compxE2 i (length (compE2 A)) (Suc 0))) @ shift (length (compE2 A @ compE2 i)) (stack_xlift (length (v2 # v1 # STK)) (compxE2 e 0 0))) t
     h (stk @ v2 # v1 # STK, loc, length (compE2 A @ compE2 i) + pc, a) ta h' (stk', loc', pc', xcp')"
    by(simp add: shift_compxE2 stack_xlift_compxE2 ac_simps)
  hence exec': "exec_meth_d (compP2 P) ((compE2 A @ compE2 i) @ compE2 e)
     ((stack_xlift (length STK) (compxE2 A 0 0 @ compxE2 i (length (compE2 A)) (Suc 0))) @ shift (length (compE2 A @ compE2 i)) (stack_xlift (length (v2 # v1 # STK)) (compxE2 e 0 0))) t
     h (stk @ v2 # v1 # STK, loc, length (compE2 A @ compE2 i) + pc, a) ta h' (stk', loc', pc', xcp')"
    by(rule exec_meth_take)(simp add: pc)
  hence "?exec e stk (v2 # v1 # STK) loc pc a stk' loc' (pc' - length (compE2 A @ compE2 i)) xcp'"
    by(rule exec_meth_drop_xt) auto
  from IH3[OF this] obtain stk'' where stk': "stk' = stk'' @ v2 # v1 # STK" and
    exec'': "exec_meth_d (compP2 P) (compE2 e) (compxE2 e 0 0) t h (stk, loc, pc, a) ta h' (stk'', loc', pc' - length (compE2 A @ compE2 i), xcp')" by blast
  from exec'' have "exec_meth_d (compP2 P) (compE2 e) (stack_xlift (length [v2, v1]) (compxE2 e 0 0)) t h (stk @ [v2, v1], loc, pc, a)
      ta h' (stk'' @ [v2, v1], loc', pc' - length (compE2 A @ compE2 i), xcp')"
    by(rule exec_meth_stk_offer)
  hence "exec_meth_d (compP2 P) ((compE2 A @ compE2 i) @ compE2 e) ((compxE2 A 0 0 @ compxE2 i (length (compE2 A)) (Suc 0)) @ shift (length (compE2 A @ compE2 i)) (stack_xlift (length [v2, v1]) (compxE2 e 0 0))) t h (stk @ [v2, v1], loc, length (compE2 A @ compE2 i) + pc, a)
      ta h' (stk'' @ [v2, v1], loc', length (compE2 A @ compE2 i) + (pc' - length (compE2 A @ compE2 i)), xcp')"
    by(rule append_exec_meth_xt)(auto)
  hence "exec_meth_d (compP2 P) (((compE2 A @ compE2 i) @ compE2 e) @ [AStore, Push Unit]) ((compxE2 A 0 0 @ compxE2 i (length (compE2 A)) (Suc 0)) @ shift (length (compE2 A @ compE2 i)) (stack_xlift (length [v2, v1]) (compxE2 e 0 0))) t h (stk @ [v2, v1], loc, length (compE2 A @ compE2 i) + pc, a)
      ta h' (stk'' @ [v2, v1], loc', length (compE2 A @ compE2 i) + (pc' - length (compE2 A @ compE2 i)), xcp')"
    by(rule exec_meth_append)
  moreover from exec' have pc': "pc'  length (compE2 A @ compE2 i)"
    by(rule exec_meth_drop_xt_pc)(auto simp add: stack_xlift_compxE2)
  ultimately show ?case using stk' by(auto simp add: stack_xlift_compxE2 shift_compxE2)
next
  case bisim1AAssFail thus ?case
    by(auto elim!: exec_meth.cases dest: match_ex_table_pcsD simp add: stack_xlift_compxEs2 stack_xlift_compxE2)
next
  case bisim1AAss4 thus ?case
    by -(erule exec_meth.cases, auto intro!: exec_meth.exec_instr)
next
  case (bisim1ALength a n a' xs stk loc pc xcp)
  note bisim = P,a,h  (a', xs)  (stk, loc, pc, xcp)
  note IH = stk' loc' pc' xcp' STK. ?exec a stk STK loc pc xcp stk' loc' pc' xcp'
              ?concl a stk STK loc pc xcp stk' loc' pc' xcp'
  note exec = ?exec (a∙length) stk STK loc pc xcp stk' loc' pc' xcp'
  from bisim have pc: "pc  length (compE2 a)" by(rule bisim1_pc_length_compE2)
  show ?case
  proof(cases "pc < length (compE2 a)")
    case True
    with exec have "?exec a stk STK loc pc xcp stk' loc' pc' xcp'"
      by(simp add: compxE2_size_convs)(erule exec_meth_take)
    from IH[OF this] show ?thesis by auto
  next
    case False
    with pc have [simp]: "pc = length (compE2 a)" by simp
    with bisim obtain v where [simp]: "stk = [v]" "xcp = None"
      by(auto dest: dest: bisim1_pc_length_compE2D)
    with exec show ?thesis apply(simp)
      by(erule exec_meth.cases)(auto intro!: exec_meth.intros split: if_split_asm)
  qed
next
  case (bisim1ALengthThrow e n a xs stk loc pc)
  note bisim = P,e,h  (Throw a, xs)  (stk, loc, pc, a)
  note IH = stk' loc' pc' xcp' STK. ?exec e stk STK loc pc a stk' loc' pc' xcp'
              ?concl e stk STK loc pc a stk' loc' pc' xcp'
  note exec = ?exec (e∙length) stk STK loc pc a stk' loc' pc' xcp'
  from bisim have pc: "pc < length (compE2 e)" and [simp]: "xs = loc"
    by(auto dest: bisim1_ThrowD)
  from exec have "?exec e stk STK loc pc a stk' loc' pc' xcp'"
    by(simp)(erule exec_meth_take[OF _ pc])
  from IH[OF this] show ?case by(auto)
next
  case bisim1ALengthNull thus ?case
    by(auto elim!: exec_meth.cases dest: match_ex_table_pcsD simp add: stack_xlift_compxEs2 stack_xlift_compxE2)
next
  case (bisim1FAcc e n e' xs stk loc pc xcp F D)
  note bisim = P,e,h  (e', xs)  (stk, loc, pc, xcp)
  note IH = stk' loc' pc' xcp' STK. ?exec e stk STK loc pc xcp stk' loc' pc' xcp'
              ?concl e stk STK loc pc xcp stk' loc' pc' xcp'
  note exec = ?exec (eF{D}) stk STK loc pc xcp stk' loc' pc' xcp'
  from bisim have pc: "pc  length (compE2 e)" by(rule bisim1_pc_length_compE2)
  show ?case
  proof(cases "pc < length (compE2 e)")
    case True
    with exec have "?exec e stk STK loc pc xcp stk' loc' pc' xcp'"
      by(simp add: compxE2_size_convs)(erule exec_meth_take)
    from IH[OF this] show ?thesis by auto
  next
    case False
    with pc have [simp]: "pc = length (compE2 e)" by simp
    with bisim obtain v where [simp]: "stk = [v]" "xcp = None"
      by(auto dest: dest: bisim1_pc_length_compE2D)
    with exec show ?thesis apply(simp)
      by(erule exec_meth.cases)(fastforce intro!: exec_meth.intros simp add: is_Ref_def split: if_split_asm)+
  qed
next
  case (bisim1FAccThrow e n a xs stk loc pc F D)
  note bisim = P,e,h  (Throw a, xs)  (stk, loc, pc, a)
  note IH = stk' loc' pc' xcp' STK. ?exec e stk STK loc pc a stk' loc' pc' xcp'
              ?concl e stk STK loc pc a stk' loc' pc' xcp'
  note exec = ?exec (eF{D}) stk STK loc pc a stk' loc' pc' xcp'
  from bisim have pc: "pc < length (compE2 e)" and [simp]: "xs = loc"
    by(auto dest: bisim1_ThrowD)
  from exec have "?exec e stk STK loc pc a stk' loc' pc' xcp'"
    by(simp)(erule exec_meth_take[OF _ pc])
  from IH[OF this] show ?case by(auto)
next
  case bisim1FAccNull thus ?case
    by(auto elim!: exec_meth.cases dest: match_ex_table_pcsD simp add: stack_xlift_compxEs2 stack_xlift_compxE2)
next
  case (bisim1FAss1 e n e' xs stk loc pc xcp e2 F D)
  note IH1 = stk' loc' pc' xcp' STK. ?exec e stk STK loc pc xcp stk' loc' pc' xcp'
              ?concl e stk STK loc pc xcp stk' loc' pc' xcp'
  note IH2 = xs stk' loc' pc' xcp' STK. ?exec e2 [] STK xs 0 None stk' loc' pc' xcp'
              ?concl e2 [] STK xs 0 None stk' loc' pc' xcp'
  note bisim1 = P,e,h  (e', xs)  (stk, loc, pc, xcp)
  note bisim2 = P,e2,h  (e2, loc)  ([], loc, 0, None)
  note exec = ?exec (eF{D} := e2) stk STK loc pc xcp stk' loc' pc' xcp'
  from bisim1 have pc: "pc  length (compE2 e)" by(rule bisim1_pc_length_compE2)
  show ?case
  proof(cases "pc < length (compE2 e)")
    case True
    with exec have "?exec e stk STK loc pc xcp stk' loc' pc' xcp'"
      by(simp add: compxE2_size_convs)(erule exec_meth_take_xt)
    from IH1[OF this] show ?thesis by auto
  next
    case False
    with pc have pc: "pc = length (compE2 e)" by simp
    with exec have "pc'  length (compE2 e)"
      by(simp add: compxE2_size_convs stack_xlift_compxE2)(auto elim!: exec_meth_drop_xt_pc)
    then obtain PC where PC: "pc' = PC + length (compE2 e)"
      by -(rule_tac PC34="pc' - length (compE2 e)" in that, simp)
    from pc bisim1 obtain v where "stk = [v]" "xcp = None" by(auto dest: bisim1_pc_length_compE2D)
    with exec pc have "exec_meth_d (compP2 P) (compE2 e @ compE2 e2)
      (stack_xlift (length STK) (compxE2 e 0 0 @ compxE2 e2 (length (compE2 e)) (Suc 0))) t 
      h (stk @ STK, loc, length (compE2 e) + 0, xcp) ta h' (stk', loc', pc', xcp')"
      by-(rule exec_meth_take, auto)
    hence "?exec e2 [] (v # STK) loc 0 None stk' loc' (pc' - length (compE2 e)) xcp'"
      using stk = [v] xcp = None
      by -(rule exec_meth_drop_xt, auto simp add: stack_xlift_compxE2 shift_compxE2)
    from IH2[OF this] PC obtain stk'' where stk': "stk' = stk'' @ v # STK"
      and "exec_meth_d (compP2 P) (compE2 e2) (compxE2 e2 0 0) t h ([], loc, 0, None) ta h' (stk'', loc', PC, xcp')" by auto
    hence "exec_meth_d (compP2 P) ((compE2 e @ compE2 e2) @ [Putfield F D, Push Unit])
        (compxE2 e 0 0 @ shift (length (compE2 e)) (stack_xlift (length [v]) (compxE2 e2 0 0))) t h
        ([] @ [v], loc, length (compE2 e) + 0, None) ta h' (stk'' @ [v], loc', length (compE2 e) + PC, xcp')"
      apply -
      apply(rule exec_meth_append)
      apply(rule append_exec_meth_xt)
      apply(erule exec_meth_stk_offer)
      by(auto)
    thus ?thesis using stk = [v] xcp = None stk' pc PC
      by(clarsimp simp add: shift_compxE2 stack_xlift_compxE2 ac_simps)
  qed
next
  case (bisim1FAss2 e2 n e' xs stk loc pc xcp e F D v1)
  note IH2 = stk' loc' pc' xcp' STK. ?exec e2 stk STK loc pc xcp stk' loc' pc' xcp'
              ?concl e2 stk STK loc pc xcp stk' loc' pc' xcp'
  note bisim2 = P,e2,h  (e', xs)  (stk, loc, pc, xcp)
  note exec = ?exec (eF{D} := e2) (stk @ [v1]) STK loc (length (compE2 e) + pc) xcp stk' loc' pc' xcp'
  from bisim2 have pc: "pc  length (compE2 e2)" by(rule bisim1_pc_length_compE2)
  show ?case
  proof(cases "pc < length (compE2 e2)")
    case True
    from exec have "exec_meth_d (compP2 P) ((compE2 e @ compE2 e2) @ [Putfield F D, Push Unit])
      (stack_xlift (length STK) (compxE2 e 0 0) @ shift (length (compE2 e)) (stack_xlift (length STK) (compxE2 e2 0 (Suc 0)))) t
      h (stk @ v1 # STK, loc, length (compE2 e) + pc, xcp) ta h' (stk', loc', pc', xcp')" by(simp add: compxE2_size_convs)
    hence exec': "exec_meth_d (compP2 P) (compE2 e @ compE2 e2) (stack_xlift (length STK) (compxE2 e 0 0) @
      shift (length (compE2 e)) (stack_xlift (length STK) (compxE2 e2 0 (Suc 0)))) t
      h (stk @ v1 # STK, loc, length (compE2 e) + pc, xcp) ta h' (stk', loc', pc', xcp')"
      by(rule exec_meth_take)(simp add: True)
    hence "exec_meth_d (compP2 P) (compE2 e2) (stack_xlift (length STK) (compxE2 e2 0 (Suc 0))) t
      h (stk @ v1 # STK, loc, pc, xcp) ta h' (stk', loc', pc' - length (compE2 e), xcp')"
      by(rule exec_meth_drop_xt)(auto simp add: stack_xlift_compxE2)
    hence "?exec e2 stk (v1 # STK) loc pc xcp stk' loc' (pc' - length (compE2 e)) xcp'"
      by(simp add: compxE2_stack_xlift_convs)
    from IH2[OF this] obtain stk'' where stk': "stk' = stk'' @ v1 # STK"
      and exec'': "exec_meth_d (compP2 P) (compE2 e2) (compxE2 e2 0 0) t h (stk, loc, pc, xcp) ta h' (stk'', loc', pc' - length (compE2 e), xcp')" by blast
    from exec'' have "exec_meth_d (compP2 P) (compE2 e2) (stack_xlift (length [v1]) (compxE2 e2 0 0)) t h (stk @ [v1], loc, pc, xcp)
      ta h' (stk'' @ [v1], loc', pc' - length (compE2 e), xcp')"
      by(rule exec_meth_stk_offer)
    hence "exec_meth_d (compP2 P) (compE2 e @ compE2 e2) (compxE2 e 0 0 @ shift (length (compE2 e)) (stack_xlift (length [v1]) (compxE2 e2 0 0))) t h (stk @ [v1], loc, length (compE2 e) + pc, xcp)
      ta h' (stk'' @ [v1], loc', length (compE2 e) + (pc' - length (compE2 e)), xcp')"
      by(rule append_exec_meth_xt) auto
    hence "exec_meth_d (compP2 P) ((compE2 e @ compE2 e2) @ [Putfield F D, Push Unit]) (compxE2 e 0 0 @ shift (length (compE2 e)) (stack_xlift (length [v1]) (compxE2 e2 0 0))) t h (stk @ [v1], loc, length (compE2 e) + pc, xcp)
      ta h' (stk'' @ [v1], loc', length (compE2 e) + (pc' - length (compE2 e)), xcp')"
      by(rule exec_meth_append)
    moreover from exec' have "pc'  length (compE2 e)"
      by(rule exec_meth_drop_xt_pc)(auto simp add: stack_xlift_compxE2)
    ultimately show ?thesis using stk' by(simp add: stack_xlift_compxE2 shift_compxE2)
  next
    case False
    with pc have pc: "pc = length (compE2 e2)" by simp
    with bisim2 obtain v2 where [simp]: "stk = [v2]" "xcp = None"
      by(auto dest: dest: bisim1_pc_length_compE2D)
    with exec pc show ?thesis apply(simp)
      by(erule exec_meth.cases)(fastforce intro!: exec_meth.intros split: if_split_asm)+
  qed
next
  case (bisim1FAssThrow1 e n a xs stk loc pc e2 F D)
  note bisim1 = P,e,h  (Throw a, xs)  (stk, loc, pc, a)
  note IH1 = stk' loc' pc' xcp' STK. ?exec e stk STK loc pc a stk' loc' pc' xcp'
              ?concl e stk STK loc pc a stk' loc' pc' xcp'
  note exec = ?exec (eF{D} := e2) stk STK loc pc a stk' loc' pc' xcp'
  from bisim1 have pc: "pc < length (compE2 e)" and [simp]: "xs = loc"
    by(auto dest: bisim1_ThrowD)
  from exec have "exec_meth_d (compP2 P) (compE2 e @ (compE2 e2 @ [Putfield F D, Push Unit]))
     (stack_xlift (length STK) (compxE2 e 0 0) @ shift (length (compE2 e)) (stack_xlift (length STK) (compxE2 e2 0 (Suc 0)))) t
     h (stk @ STK, loc, pc, a) ta h' (stk', loc', pc', xcp')" by(simp add: compxE2_size_convs)
  hence "?exec e stk STK loc pc a stk' loc' pc' xcp'" by(rule exec_meth_take_xt)(rule pc)
  from IH1[OF this] show ?case by(auto)
next
  case (bisim1FAssThrow2 e2 n a xs stk loc pc e F D v1)
  note bisim2 = P,e2,h  (Throw a, xs)  (stk, loc, pc, a)
  note IH2 = stk' loc' pc' xcp' STK. ?exec e2 stk STK loc pc a stk' loc' pc' xcp'
              ?concl e2 stk STK loc pc a stk' loc' pc' xcp'
  note exec = ?exec (eF{D} := e2) (stk @ [v1]) STK loc (length (compE2 e) + pc) a stk' loc' pc' xcp'
  from bisim2 have pc: "pc < length (compE2 e2)" and [simp]: "xs = loc"
    by(auto dest: bisim1_ThrowD)
  from exec have "exec_meth_d (compP2 P) ((compE2 e @ compE2 e2) @ [Putfield F D, Push Unit])
     (stack_xlift (length STK) (compxE2 e 0 0) @ shift (length (compE2 e)) (stack_xlift (length STK) (compxE2 e2 0 (Suc 0)))) t
     h (stk @ v1 # STK, loc, length (compE2 e) + pc, a) ta h' (stk', loc', pc', xcp')"
    by(simp add: compxE2_size_convs)
  hence exec': "exec_meth_d (compP2 P) (compE2 e @ compE2 e2)
     (stack_xlift (length STK) (compxE2 e 0 0) @ shift (length (compE2 e)) (stack_xlift (length STK) (compxE2 e2 0 (Suc 0)))) t
     h (stk @ v1 # STK, loc, length (compE2 e) + pc, a) ta h' (stk', loc', pc', xcp')"
    by(rule exec_meth_take)(simp add: pc)
  hence "exec_meth_d (compP2 P) (compE2 e2) (stack_xlift (length STK) (compxE2 e2 0 (Suc 0))) t
     h (stk @ v1 # STK, loc, pc, a) ta h' (stk', loc', pc' - length (compE2 e), xcp')"
    by(rule exec_meth_drop_xt)(auto simp add: stack_xlift_compxE2)
  hence "?exec e2 stk (v1 # STK) loc pc a stk' loc' (pc' - length (compE2 e)) xcp'"
    by(simp add: compxE2_stack_xlift_convs)
  from IH2[OF this] obtain stk'' where stk': "stk' = stk'' @ v1 # STK" and
    exec'': "exec_meth_d (compP2 P) (compE2 e2) (compxE2 e2 0 0) t h (stk, loc, pc, a) ta h' (stk'', loc', pc' - length (compE2 e), xcp')" by blast
  from exec'' have "exec_meth_d (compP2 P) (compE2 e2) (stack_xlift (length [v1]) (compxE2 e2 0 0)) t h (stk @ [v1], loc, pc, a)
      ta h' (stk'' @ [v1], loc', pc' - length (compE2 e), xcp')"
    by(rule exec_meth_stk_offer)
  hence "exec_meth_d (compP2 P) (compE2 e @ compE2 e2) (compxE2 e 0 0 @ shift (length (compE2 e)) (stack_xlift (length [v1]) (compxE2 e2 0 0))) t h (stk @ [v1], loc, length (compE2 e) + pc, a)
      ta h' (stk'' @ [v1], loc', length (compE2 e) + (pc' - length (compE2 e)), xcp')"
    by(rule append_exec_meth_xt)(auto)
  hence "exec_meth_d (compP2 P) ((compE2 e @ compE2 e2) @ [Putfield F D, Push Unit]) (compxE2 e 0 0 @ shift (length (compE2 e)) (stack_xlift (length [v1]) (compxE2 e2 0 0))) t h (stk @ [v1], loc, length (compE2 e) + pc, a)
      ta h' (stk'' @ [v1], loc', length (compE2 e) + (pc' - length (compE2 e)), xcp')"
    by(rule exec_meth_append)
  moreover from exec' have pc': "pc'  length (compE2 e)"
    by(rule exec_meth_drop_xt_pc)(auto simp add: stack_xlift_compxE2)
  ultimately show ?case using stk' by(auto simp add: stack_xlift_compxE2 shift_compxE2)
next
  case bisim1FAssNull thus ?case
    by(auto elim!: exec_meth.cases dest: match_ex_table_pcsD simp add: stack_xlift_compxEs2 stack_xlift_compxE2)
next
  case bisim1FAss3 thus ?case
    by -(erule exec_meth.cases, auto intro!: exec_meth.exec_instr)
next
  case (bisim1CAS1 e1 n e1' xs stk loc pc xcp e2 e3 D F)
  note IH1 = stk' loc' pc' xcp' STK. ?exec e1 stk STK loc pc xcp stk' loc' pc' xcp'
              ?concl e1 stk STK loc pc xcp stk' loc' pc' xcp'
  note IH2 = xs stk' loc' pc' xcp' STK. ?exec e2 [] STK xs 0 None stk' loc' pc' xcp'
              ?concl e2 [] STK xs 0 None stk' loc' pc' xcp'
  note bisim1 = P,e1,h  (e1', xs)  (stk, loc, pc, xcp)
  note bisim2 = P,e2,h  (e2, loc)  ([], loc, 0, None)
  note exec = ?exec _ stk STK loc pc xcp stk' loc' pc' xcp'
  from bisim1 have pc: "pc  length (compE2 e1)" by(rule bisim1_pc_length_compE2)
  from exec have exec': "exec_meth_d (compP2 P) (compE2 e1 @ compE2 e2 @ compE2 e3 @ [CAS F D]) (stack_xlift (length STK) (compxE2 e1 0 0) @ shift (length (compE2 e1)) (stack_xlift (length STK) (compxE2 e2 0 (Suc 0) @ compxE2 e3 (length (compE2 e2)) (Suc (Suc 0))))) t
    h (stk @ STK, loc, pc, xcp) ta h' (stk', loc', pc', xcp')"
    by(simp add: compxE2_size_convs)
  show ?case
  proof(cases "pc < length (compE2 e1)")
    case True
    with exec' have "?exec e1 stk STK loc pc xcp stk' loc' pc' xcp'" by(rule exec_meth_take_xt)
    from IH1[OF this] show ?thesis by auto
  next
    case False
    with pc have pc: "pc = length (compE2 e1)" by simp
    with exec' have "pc'  length (compE2 e1)" by -(erule exec_meth_drop_xt_pc, auto)
    then obtain PC where PC: "pc' = PC + length (compE2 e1)"
      by -(rule_tac PC34="pc' - length (compE2 e1)" in that, simp)
    from pc bisim1 obtain v where "stk = [v]" "xcp = None" by(auto dest: bisim1_pc_length_compE2D)
    with exec PC pc
    have "exec_meth_d (compP2 P) ((compE2 e1 @ compE2 e2) @ compE2 e3 @ [CAS F D]) (stack_xlift (length STK) (compxE2 e1 0 0 @ shift (length (compE2 e1)) (compxE2 e2 0 (Suc 0))) @ shift (length (compE2 e1 @ compE2 e2)) (compxE2 e3 0 (length STK + Suc (Suc 0)))) t
    h (v # STK, loc, length (compE2 e1) + 0, None) ta h' (stk', loc', length (compE2 e1) + PC, xcp')" 
      by(simp add: shift_compxE2 stack_xlift_compxE2 ac_simps)
    hence "exec_meth_d (compP2 P) (compE2 e1 @ compE2 e2)
   (stack_xlift (length STK) (compxE2 e1 0 0 @ shift (length (compE2 e1)) (compxE2 e2 0 (Suc 0)))) t h (v # STK, loc, length (compE2 e1) + 0, None) ta h' (stk', loc', length (compE2 e1) + PC, xcp')"
      by(rule exec_meth_take_xt) simp
    hence "?exec e2 [] (v # STK) loc 0 None stk' loc' ((length (compE2 e1) + PC) - length (compE2 e1)) xcp'"
      by -(rule exec_meth_drop_xt, auto simp add: stack_xlift_compxE2 shift_compxE2)
    from IH2[OF this] PC obtain stk'' where stk': "stk' = stk'' @ v # STK"
      and "exec_meth_d (compP2 P) (compE2 e2) (compxE2 e2 0 0) t h ([], loc, 0, None) ta h' (stk'', loc', PC, xcp')" by auto
    hence "exec_meth_d (compP2 P) ((compE2 e1 @ compE2 e2) @ (compE2 e3 @ [CAS F D]))
        ((compxE2 e1 0 0 @ shift (length (compE2 e1)) (stack_xlift (length [v]) (compxE2 e2 0 0))) @
         shift (length (compE2 e1 @ compE2 e2)) (compxE2 e3 0 (Suc (Suc 0)))) t h
        ([] @ [v], loc, length (compE2 e1) + 0, None) ta h' (stk'' @ [v], loc', length (compE2 e1) + PC, xcp')"
      apply -
      apply(rule exec_meth_append_xt)
      apply(rule append_exec_meth_xt)
      apply(erule exec_meth_stk_offer)
      by(auto)
    thus ?thesis using stk = [v] xcp = None stk' pc PC
      by(clarsimp simp add: shift_compxE2 stack_xlift_compxE2 ac_simps)
  qed
next
  case (bisim1CAS2 e2 n e2' xs stk loc pc xcp e1 e3 D F v)
  note IH2 = stk' loc' pc' xcp' STK. ?exec e2 stk STK loc pc xcp stk' loc' pc' xcp'
              ?concl e2 stk STK loc pc xcp stk' loc' pc' xcp'
  note IH3 = xs stk' loc' pc' xcp' STK. ?exec e3 [] STK xs 0 None stk' loc' pc' xcp'
              ?concl e3 [] STK xs 0 None stk' loc' pc' xcp'
  note bisim2 = P,e2,h  (e2', xs)  (stk, loc, pc, xcp)
  note bisim3 = P,e3,h  (e3, loc)  ([], loc, 0, None)
  note exec = ?exec _ (stk @ [v]) STK loc (length (compE2 e1) + pc) xcp stk' loc' pc' xcp'
  from bisim2 have pc: "pc  length (compE2 e2)" by(rule bisim1_pc_length_compE2)
  from exec have exec': "v'. exec_meth_d (compP2 P) ((compE2 e1 @ compE2 e2) @ compE2 e3 @ [CAS F D]) ((compxE2 e1 0 (length STK) @ shift (length (compE2 e1)) (stack_xlift (length (v # STK)) (compxE2 e2 0 0))) @ shift (length (compE2 e1 @ compE2 e2)) (stack_xlift (length (v' # v # STK)) (compxE2 e3 0 0))) t
    h (stk @ v # STK, loc, length (compE2 e1) + pc, xcp) ta h' (stk', loc', pc', xcp')"
    by(simp add: shift_compxE2 stack_xlift_compxE2)
  show ?case
  proof(cases "pc < length (compE2 e2)")
    case True with exec'[of undefined]
    have exec'': "exec_meth_d (compP2 P) (compE2 e1 @ compE2 e2) (compxE2 e1 0 (length STK) @ shift (length (compE2 e1)) (stack_xlift (length (v # STK)) (compxE2 e2 0 0))) t h (stk @ v # STK, loc, length (compE2 e1) + pc, xcp) ta h' (stk', loc', pc', xcp')"
      by-(erule exec_meth_take_xt, simp)
    hence "?exec e2 stk (v # STK) loc pc xcp stk' loc' (pc' - length (compE2 e1)) xcp'"
      by(rule exec_meth_drop_xt) auto
    from IH2[OF this] obtain stk'' where stk': "stk' = stk'' @ v # STK"
      and exec''': "exec_meth_d (compP2 P) (compE2 e2) (compxE2 e2 0 0) t h (stk, loc, pc, xcp) ta h' (stk'', loc', pc' - length (compE2 e1), xcp')" by blast
    from exec''' have "exec_meth_d (compP2 P) ((compE2 e1 @ compE2 e2) @ compE2 e3 @ [CAS F D]) ((compxE2 e1 0 0 @ shift (length (compE2 e1)) (stack_xlift (length [v]) (compxE2 e2 0 0))) @ shift (length (compE2 e1 @ compE2 e2)) (compxE2 e3 0 (Suc (Suc 0)))) t h (stk @ [v], loc, length (compE2 e1) + pc, xcp) ta h' (stk'' @ [v], loc', length (compE2 e1) + (pc' - length (compE2 e1)), xcp')"
      apply -
      apply(rule exec_meth_append_xt)
      apply(rule append_exec_meth_xt)
      apply(erule exec_meth_stk_offer)
      by auto
    moreover from exec'' have "pc'  length (compE2 e1)"
      by(rule exec_meth_drop_xt_pc) auto
    ultimately show ?thesis using stk' by(auto simp add: shift_compxE2 stack_xlift_compxE2)
  next
    case False
    with pc have pc: "pc = length (compE2 e2)" by simp
    with exec'[of undefined] have "pc'  length (compE2 e1 @ compE2 e2)"
      by-(erule exec_meth_drop_xt_pc, auto simp add: shift_compxE2 stack_xlift_compxE2)
    then obtain PC where PC: "pc' = PC + length (compE2 e1) + length (compE2 e2)"
      by -(rule_tac PC34="pc' - length (compE2 e1 @ compE2 e2)" in that, simp)
    from pc bisim2 obtain v' where stk: "stk = [v']" and xcp: "xcp = None" by(auto dest: bisim1_pc_length_compE2D)
    from exec'[of v'] 
    have "exec_meth_d (compP2 P) (compE2 e3 @ [CAS F D]) (stack_xlift (length (v' # v # STK)) (compxE2 e3 0 0)) t
                    h (v' # v # STK, loc, 0, xcp) ta h' (stk', loc', pc' - length (compE2 e1 @ compE2 e2), xcp')"
      unfolding stk pc append_Cons append_Nil
      by -(rule exec_meth_drop_xt, simp only: add_0_right length_append, auto simp add: shift_compxE2 stack_xlift_compxE2)
    with PC xcp have "?exec e3 [] (v' # v # STK) loc 0 None stk' loc' PC xcp'"
      by -(rule exec_meth_take,auto)
    from IH3[OF this] obtain stk'' where stk': "stk' = stk'' @ v' # v # STK"
      and "exec_meth_d (compP2 P) (compE2 e3) (compxE2 e3 0 0) t h ([], loc, 0, None) ta h' (stk'', loc', PC, xcp')"  by auto
    hence "exec_meth_d (compP2 P) (((compE2 e1 @ compE2 e2) @ compE2 e3) @ [CAS F D]) ((compxE2 e1 0 0 @ compxE2 e2 (length (compE2 e1)) (Suc 0)) @ shift (length (compE2 e1 @ compE2 e2)) (stack_xlift (length [v', v]) (compxE2 e3 0 0))) t h ([] @ [v', v], loc, length (compE2 e1 @ compE2 e2) + 0, None) ta h' (stk'' @ [v', v], loc', length (compE2 e1 @ compE2 e2) + PC, xcp')"
      apply -
      apply(rule exec_meth_append)
      apply(rule append_exec_meth_xt)
      apply(erule exec_meth_stk_offer)
      by auto
    thus ?thesis using stk xcp stk' pc PC
      by(clarsimp simp add: shift_compxE2 stack_xlift_compxE2 ac_simps)
  qed
next
  case (bisim1CAS3 e3 n e3' xs stk loc pc xcp e1 e2 D F v1 v2)
  note IH3 = stk' loc' pc' xcp' STK. ?exec e3 stk STK loc pc xcp stk' loc' pc' xcp'
              ?concl e3 stk STK loc pc xcp stk' loc' pc' xcp'
  note bisim3 = P,e3,h  (e3', xs)  (stk, loc, pc, xcp)
  note exec = ?exec _ (stk @ [v2, v1]) STK loc (length (compE2 e1) + length (compE2 e2) + pc) xcp stk' loc' pc' xcp'
  from bisim3 have pc: "pc  length (compE2 e3)" by(rule bisim1_pc_length_compE2)
  show ?case
  proof(cases "pc < length (compE2 e3)")
    case True
    from exec have "exec_meth_d (compP2 P) (((compE2 e1 @ compE2 e2) @ compE2 e3) @ [CAS F D])
      ((compxE2 e1 0 (length STK) @ compxE2 e2 (length (compE2 e1)) (Suc (length STK))) @ shift (length (compE2 e1 @ compE2 e2)) (stack_xlift (length (v2 # v1 # STK)) (compxE2 e3 0 0))) t
      h (stk @ v2 # v1 # STK, loc, length (compE2 e1 @ compE2 e2) + pc, xcp) ta h' (stk', loc', pc', xcp')"
      by(simp add: shift_compxE2 stack_xlift_compxE2)
    hence exec': "exec_meth_d (compP2 P) ((compE2 e1 @ compE2 e2) @ compE2 e3)
      ((compxE2 e1 0 (length STK) @ compxE2 e2 (length (compE2 e1)) (Suc (length STK))) @ shift (length (compE2 e1 @ compE2 e2)) (stack_xlift (length (v2 # v1 # STK)) (compxE2 e3 0 0))) t
      h (stk @ v2 # v1 # STK, loc, length (compE2 e1 @ compE2 e2) + pc, xcp) ta h' (stk', loc', pc', xcp')"
      by(rule exec_meth_take)(simp add: True)
    hence "?exec e3 stk (v2 # v1 # STK) loc pc xcp stk' loc' (pc' - length (compE2 e1 @ compE2 e2)) xcp'"
      by(rule exec_meth_drop_xt) auto
    from IH3[OF this] obtain stk'' where stk': "stk' = stk'' @ v2 # v1 # STK"
      and exec'': "exec_meth_d (compP2 P) (compE2 e3) (compxE2 e3 0 0) t h (stk, loc, pc, xcp) ta h' (stk'', loc', pc' - length (compE2 e1 @ compE2 e2), xcp')" by blast
    from exec'' have "exec_meth_d (compP2 P) (compE2 e3) (stack_xlift (length [v2, v1]) (compxE2 e3 0 0)) t h (stk @ [v2, v1], loc, pc, xcp)
      ta h' (stk'' @ [v2, v1], loc', pc' - length (compE2 e1 @ compE2 e2), xcp')"
      by(rule exec_meth_stk_offer)
    hence "exec_meth_d (compP2 P) ((compE2 e1 @ compE2 e2) @ compE2 e3) ((compxE2 e1 0 0 @ compxE2 e2 (length (compE2 e1)) (Suc 0)) @ shift (length (compE2 e1 @ compE2 e2)) (stack_xlift (length [v2, v1]) (compxE2 e3 0 0))) t
      h (stk @ [v2, v1], loc, length (compE2 e1 @ compE2 e2) + pc, xcp)
      ta h' (stk'' @ [v2, v1], loc', length (compE2 e1 @ compE2 e2) + (pc' - length (compE2 e1 @ compE2 e2)), xcp')"
      by(rule append_exec_meth_xt) auto
    hence "exec_meth_d (compP2 P) (((compE2 e1 @ compE2 e2) @ compE2 e3) @ [CAS F D]) ((compxE2 e1 0 0 @ compxE2 e2 (length (compE2 e1)) (Suc 0)) @ shift (length (compE2 e1 @ compE2 e2)) (stack_xlift (length [v2, v1]) (compxE2 e3 0 0))) t
      h (stk @ [v2, v1], loc, length (compE2 e1 @ compE2 e2) + pc, xcp)
      ta h' (stk'' @ [v2, v1], loc', length (compE2 e1 @ compE2 e2) + (pc' - length (compE2 e1 @ compE2 e2)), xcp')"
      by(rule exec_meth_append)
    moreover from exec' have "pc'  length (compE2 e1 @ compE2 e2)"
      by(rule exec_meth_drop_xt_pc)(auto simp add: stack_xlift_compxE2)
    ultimately show ?thesis using stk' by(simp add: stack_xlift_compxE2 shift_compxE2)
  next
    case False
    with pc have pc: "pc = length (compE2 e3)" by simp
    with bisim3 obtain v3 where [simp]: "stk = [v3]" "xcp = None"
      by(auto dest: dest: bisim1_pc_length_compE2D)
    with exec pc show ?thesis apply(simp)
      by(erule exec_meth.cases)(fastforce intro!: exec_meth.intros split: if_split_asm)+
  qed
next
  case (bisim1CASThrow1 e1 n a xs stk loc pc e2 e3 D F)
  note bisim1 = P,e1,h  (Throw a, xs)  (stk, loc, pc, a)
  note IH1 = stk' loc' pc' xcp' STK. ?exec e1 stk STK loc pc a stk' loc' pc' xcp'
              ?concl e1 stk STK loc pc a stk' loc' pc' xcp'
  note exec = ?exec _ stk STK loc pc a stk' loc' pc' xcp'
  from bisim1 have pc: "pc < length (compE2 e1)" and [simp]: "xs = loc"
    by(auto dest: bisim1_ThrowD)
  from exec have "exec_meth_d (compP2 P) (compE2 e1 @ (compE2 e2 @ compE2 e3 @ [CAS F D]))
     (stack_xlift (length STK) (compxE2 e1 0 0) @ shift (length (compE2 e1)) (stack_xlift (length STK) (compxE2 e2 0 (Suc 0) @ compxE2 e3 (length (compE2 e2)) (Suc (Suc 0))))) t
     h (stk @ STK, loc, pc, a) ta h' (stk', loc', pc', xcp')" by(simp add: compxE2_size_convs)
  hence "?exec e1 stk STK loc pc a stk' loc' pc' xcp'" by(rule exec_meth_take_xt)(rule pc)
  from IH1[OF this] show ?case by(auto)
next
  case (bisim1CASThrow2 e2 n a xs stk loc pc e1 e3 D F v1)
  note bisim2 = P,e2,h  (Throw a, xs)  (stk, loc, pc, a)
  note IH2 = stk' loc' pc' xcp' STK. ?exec e2 stk STK loc pc a stk' loc' pc' xcp'
              ?concl e2 stk STK loc pc a stk' loc' pc' xcp'
  note exec = ?exec _ (stk @ [v1]) STK loc (length (compE2 e1) + pc) a stk' loc' pc' xcp'
  from bisim2 have pc: "pc < length (compE2 e2)" and [simp]: "xs = loc"
    by(auto dest: bisim1_ThrowD)
  from exec have "exec_meth_d (compP2 P) ((compE2 e1 @ compE2 e2) @ compE2 e3 @ [CAS F D])
     ((stack_xlift (length STK) (compxE2 e1 0 0) @ shift (length (compE2 e1)) (stack_xlift (length STK) (compxE2 e2 0 (Suc 0)))) @ (shift (length (compE2 e1 @ compE2 e2)) (compxE2 e3 0 (Suc (Suc (length STK)))))) t
     h (stk @ v1 # STK, loc, length (compE2 e1) + pc, a) ta h' (stk', loc', pc', xcp')"
    by(simp add: shift_compxE2 stack_xlift_compxE2 ac_simps)
  hence exec': "exec_meth_d (compP2 P) (compE2 e1 @ compE2 e2)
     (stack_xlift (length STK) (compxE2 e1 0 0) @ shift (length (compE2 e1)) (stack_xlift (length STK) (compxE2 e2 0 (Suc 0)))) t
     h (stk @ v1 # STK, loc, length (compE2 e1) + pc, a) ta h' (stk', loc', pc', xcp')"
    by(rule exec_meth_take_xt)(simp add: pc)
  hence "exec_meth_d (compP2 P) (compE2 e2) (stack_xlift (length STK) (compxE2 e2 0 (Suc 0))) t
     h (stk @ v1 # STK, loc, pc, a) ta h' (stk', loc', pc' - length (compE2 e1), xcp')"
    by(rule exec_meth_drop_xt)(auto simp add: stack_xlift_compxE2)
  hence "?exec e2 stk (v1 # STK) loc pc a stk' loc' (pc' - length (compE2 e1)) xcp'"
    by(simp add: compxE2_stack_xlift_convs)
  from IH2[OF this] obtain stk'' where stk': "stk' = stk'' @ v1 # STK" and
    exec'': "exec_meth_d (compP2 P) (compE2 e2) (compxE2 e2 0 0) t h (stk, loc, pc, a) ta h' (stk'', loc', pc' - length (compE2 e1), xcp')" by blast
  from exec'' have "exec_meth_d (compP2 P) (compE2 e2) (stack_xlift (length [v1]) (compxE2 e2 0 0)) t 
      h (stk @ [v1], loc, pc, a)
      ta h' (stk'' @ [v1], loc', pc' - length (compE2 e1), xcp')"
    by(rule exec_meth_stk_offer)
  hence "exec_meth_d (compP2 P) (compE2 e1 @ compE2 e2) (compxE2 e1 0 0 @ shift (length (compE2 e1)) (stack_xlift (length [v1]) (compxE2 e2 0 0))) t 
      h (stk @ [v1], loc, length (compE2 e1) + pc, a)
      ta h' (stk'' @ [v1], loc', length (compE2 e1) + (pc' - length (compE2 e1)), xcp')"
    by(rule append_exec_meth_xt)(auto)
  hence "exec_meth_d (compP2 P) ((compE2 e1 @ compE2 e2) @ compE2 e3 @ [CAS F D]) ((compxE2 e1 0 0 @ shift (length (compE2 e1)) (stack_xlift (length [v1]) (compxE2 e2 0 0))) @ (shift (length (compE2 e1 @ compE2 e2)) (compxE2 e3 0 (Suc (Suc 0))))) t
      h (stk @ [v1], loc, length (compE2 e1) + pc, a)
      ta h' (stk'' @ [v1], loc', length (compE2 e1) + (pc' - length (compE2 e1)), xcp')"
    by(rule exec_meth_append_xt)
  moreover from exec' have pc': "pc'  length (compE2 e1)"
    by(rule exec_meth_drop_xt_pc)(auto simp add: stack_xlift_compxE2)
  ultimately show ?case using stk' by(auto simp add: stack_xlift_compxE2 shift_compxE2)
next
  case (bisim1CASThrow3 e3 n a xs stk loc pc e1 e2 D F v2 v1)
  note bisim3 = P,e3,h  (Throw a, xs)  (stk, loc, pc, a)
  note IH3 = stk' loc' pc' xcp' STK. ?exec e3 stk STK loc pc a stk' loc' pc' xcp'
              ?concl e3 stk STK loc pc a stk' loc' pc' xcp'
  note exec = ?exec _ (stk @ [v2, v1]) STK loc (length (compE2 e1) + length (compE2 e2) + pc) a stk' loc' pc' xcp'
  from bisim3 have pc: "pc < length (compE2 e3)" and [simp]: "xs = loc"
    by(auto dest: bisim1_ThrowD)
  from exec have "exec_meth_d (compP2 P) (((compE2 e1 @ compE2 e2) @ compE2 e3) @ [CAS F D])
     ((stack_xlift (length STK) (compxE2 e1 0 0 @ compxE2 e2 (length (compE2 e1)) (Suc 0))) @ shift (length (compE2 e1 @ compE2 e2)) (stack_xlift (length (v2 # v1 # STK)) (compxE2 e3 0 0))) t
     h (stk @ v2 # v1 # STK, loc, length (compE2 e1 @ compE2 e2) + pc, a) ta h' (stk', loc', pc', xcp')"
    by(simp add: shift_compxE2 stack_xlift_compxE2 ac_simps)
  hence exec': "exec_meth_d (compP2 P) ((compE2 e1 @ compE2 e2) @ compE2 e3)
     ((stack_xlift (length STK) (compxE2 e1 0 0 @ compxE2 e2 (length (compE2 e1)) (Suc 0))) @ shift (length (compE2 e1 @ compE2 e2)) (stack_xlift (length (v2 # v1 # STK)) (compxE2 e3 0 0))) t
     h (stk @ v2 # v1 # STK, loc, length (compE2 e1 @ compE2 e2) + pc, a) ta h' (stk', loc', pc', xcp')"
    by(rule exec_meth_take)(simp add: pc)
  hence "?exec e3 stk (v2 # v1 # STK) loc pc a stk' loc' (pc' - length (compE2 e1 @ compE2 e2)) xcp'"
    by(rule exec_meth_drop_xt) auto
  from IH3[OF this] obtain stk'' where stk': "stk' = stk'' @ v2 # v1 # STK" and
    exec'': "exec_meth_d (compP2 P) (compE2 e3) (compxE2 e3 0 0) t h (stk, loc, pc, a) ta h' (stk'', loc', pc' - length (compE2 e1 @ compE2 e2), xcp')" by blast
  from exec'' have "exec_meth_d (compP2 P) (compE2 e3) (stack_xlift (length [v2, v1]) (compxE2 e3 0 0)) t h (stk @ [v2, v1], loc, pc, a)
      ta h' (stk'' @ [v2, v1], loc', pc' - length (compE2 e1 @ compE2 e2), xcp')"
    by(rule exec_meth_stk_offer)
  hence "exec_meth_d (compP2 P) ((compE2 e1 @ compE2 e2) @ compE2 e3) ((compxE2 e1 0 0 @ compxE2 e2 (length (compE2 e1)) (Suc 0)) @ shift (length (compE2 e1 @ compE2 e2)) (stack_xlift (length [v2, v1]) (compxE2 e3 0 0))) t h (stk @ [v2, v1], loc, length (compE2 e1 @ compE2 e2) + pc, a)
      ta h' (stk'' @ [v2, v1], loc', length (compE2 e1 @ compE2 e2) + (pc' - length (compE2 e1 @ compE2 e2)), xcp')"
    by(rule append_exec_meth_xt)(auto)
  hence "exec_meth_d (compP2 P) (((compE2 e1 @ compE2 e2) @ compE2 e3) @ [CAS F D]) ((compxE2 e1 0 0 @ compxE2 e2 (length (compE2 e1)) (Suc 0)) @ shift (length (compE2 e1 @ compE2 e2)) (stack_xlift (length [v2, v1]) (compxE2 e3 0 0))) t h (stk @ [v2, v1], loc, length (compE2 e1 @ compE2 e2) + pc, a)
      ta h' (stk'' @ [v2, v1], loc', length (compE2 e1 @ compE2 e2) + (pc' - length (compE2 e1 @ compE2 e2)), xcp')"
    by(rule exec_meth_append)
  moreover from exec' have pc': "pc'  length (compE2 e1 @ compE2 e2)"
    by(rule exec_meth_drop_xt_pc)(auto simp add: stack_xlift_compxE2)
  ultimately show ?case using stk' by(auto simp add: stack_xlift_compxE2 shift_compxE2)
next
  case bisim1CASFail thus ?case
    by(auto elim!: exec_meth.cases dest: match_ex_table_pcsD simp add: stack_xlift_compxEs2 stack_xlift_compxE2)
next
  case (bisim1Call1 obj n obj' xs stk loc pc xcp ps M')
  note bisimObj = P,obj,h  (obj', xs)  (stk, loc, pc, xcp)
  note IHobj = stk' loc' pc' xcp' STK. ?exec obj stk STK loc pc xcp stk' loc' pc' xcp'
              ?concl obj stk STK loc pc xcp stk' loc' pc' xcp'
  note IHparams = xs stk' loc' pc' xcp' STK. ?execs ps [] STK xs 0 None stk' loc' pc' xcp'
              ?concls ps [] STK xs 0 None stk' loc' pc' xcp'
  note exec = ?exec (objM'(ps)) stk STK loc pc xcp stk' loc' pc' xcp'
  from bisimObj have pc: "pc  length (compE2 obj)" by(rule bisim1_pc_length_compE2)
  show ?case
  proof(cases "pc < length (compE2 obj)")
    case True
    from exec have "?exec obj stk STK loc pc xcp stk' loc' pc' xcp'"
      by(simp add: compxEs2_size_convs)(erule exec_meth_take_xt[OF _ True])
    from IHobj[OF this] show ?thesis by auto
  next
    case False
    with pc have [simp]: "pc = length (compE2 obj)" by simp
    with exec have "pc'  length (compE2 obj)"
      by(simp add: compxEs2_size_convs stack_xlift_compxE2)(auto elim!: exec_meth_drop_xt_pc)
    then obtain PC where PC: "pc' = PC + length (compE2 obj)"
      by -(rule_tac PC34="pc' - length (compE2 obj)" in that, simp)
    from pc bisimObj obtain v where [simp]: "stk = [v]" "xcp = None" by(auto dest: bisim1_pc_length_compE2D)
    show ?thesis
    proof(cases ps)
      case Cons
      with exec pc have "exec_meth_d (compP2 P) (compE2 obj @ compEs2 ps)
        (stack_xlift (length STK) (compxE2 obj 0 0 @ compxEs2 ps (length (compE2 obj)) (Suc 0))) t
        h (stk @ STK, loc, length (compE2 obj) + 0, xcp) ta h' (stk', loc', pc', xcp')"
        by -(rule exec_meth_take, auto)
      hence "?execs ps [] (v # STK) loc 0 None stk' loc' (pc' - length (compE2 obj)) xcp'"
        apply -
        apply(rule exec_meth_drop_xt)
        apply(simp add: compxEs2_size_convs compxEs2_stack_xlift_convs)
        apply(auto simp add: stack_xlift_compxE2)
        done
      from IHparams[OF this] PC obtain stk'' where stk': "stk' = stk'' @ v # STK"
        and exec': "exec_meth_d (compP2 P) (compEs2 ps) (compxEs2 ps 0 0) t h ([], loc, 0, None) ta h' (stk'', loc', PC, xcp')"
        by auto
      from exec' have "exec_meth_d (compP2 P) ((compE2 obj @ compEs2 ps) @ [Invoke M' (length ps)]) (compxE2 obj 0 0 @ shift (length (compE2 obj)) (stack_xlift (length [v]) (compxEs2 ps 0 0))) t h ([] @ [v], loc, length (compE2 obj) + 0, None) ta h' (stk'' @ [v], loc', length (compE2 obj) + PC, xcp')"
        apply -
        apply(rule exec_meth_append)
        apply(rule append_exec_meth_xt)
        apply(erule exec_meth_stk_offer)
        by(auto)
      thus ?thesis using stk' PC by(clarsimp simp add: shift_compxEs2 stack_xlift_compxEs2 ac_simps)
    next
      case Nil
      with exec pc show ?thesis 
        apply(auto elim!: exec_meth.cases intro!: exec_meth.intros simp add: split_beta split: if_split_asm)
        apply(auto split: extCallRet.split_asm intro!: exec_meth.intros)
        apply(force intro!: exI)
        apply(force intro!: exI)
        apply(force intro!: exI)
        done
    qed
  qed
next
  case (bisim1CallParams ps n ps' xs stk loc pc xcp obj M' v)
  note bisimParam = P,ps,h  (ps',xs) [↔] (stk,loc,pc,xcp)
  note IHparam = stk' loc' pc' xcp' STK. ?execs ps stk STK loc pc xcp stk' loc' pc' xcp'
              ?concls ps stk STK loc pc xcp stk' loc' pc' xcp'
  note exec = ?exec (objM'(ps)) (stk @ [v]) STK loc (length (compE2 obj) + pc) xcp stk' loc' pc' xcp'
  show ?case
  proof(cases ps)
    case Nil
    with bisimParam have "pc = 0" "xcp = None" by(auto elim: bisims1.cases)
    with exec Nil show ?thesis 
      apply(auto elim!: exec_meth.cases intro!: exec_meth.intros simp add: split_beta extRet2JVM_def split: if_split_asm)
      apply(auto split: extCallRet.split_asm simp add: neq_Nil_conv)
      apply(force intro!: exec_meth.intros)+
      done
  next
    case Cons
    from bisimParam have pc: "pc  length (compEs2 ps)" by(rule bisims1_pc_length_compEs2)
    show ?thesis
    proof(cases "pc < length (compEs2 ps)")
      case True
      from exec have "exec_meth_d (compP2 P) ((compE2 obj @ compEs2 ps) @ [Invoke M' (length ps)])
        (stack_xlift (length STK) (compxE2 obj 0 0) @ shift (length (compE2 obj)) (stack_xlift (length (v # STK)) (compxEs2 ps 0 0))) t
        h (stk @ v # STK, loc, length (compE2 obj) + pc, xcp) ta h' (stk', loc', pc', xcp')"
        by(simp add: compxEs2_size_convs compxEs2_stack_xlift_convs)
      hence exec': "exec_meth_d (compP2 P) (compE2 obj @ compEs2 ps) (stack_xlift (length STK) (compxE2 obj 0 0) @
        shift (length (compE2 obj)) (stack_xlift (length (v # STK)) (compxEs2 ps 0 0))) t
        h (stk @ v # STK, loc, length (compE2 obj) + pc, xcp) ta h' (stk', loc', pc', xcp')"
        by(rule exec_meth_take)(simp add: True)
      hence "?execs ps stk (v # STK) loc pc xcp stk' loc' (pc' - length (compE2 obj)) xcp'"
        by(rule exec_meth_drop_xt)(auto simp add: stack_xlift_compxE2)
      from IHparam[OF this] obtain stk'' where stk': "stk' = stk'' @ v # STK"
        and exec'': "exec_meth_d (compP2 P) (compEs2 ps) (compxEs2 ps 0 0) t h (stk, loc, pc, xcp) ta h' (stk'', loc', pc' - length (compE2 obj), xcp')" by blast
      from exec'' have "exec_meth_d (compP2 P) (compEs2 ps) (stack_xlift (length [v]) (compxEs2 ps 0 0)) t h (stk @ [v], loc, pc, xcp) ta h' (stk'' @ [v], loc', pc' - length (compE2 obj), xcp')"
        by(rule exec_meth_stk_offer)
      hence "exec_meth_d (compP2 P) (compE2 obj @ compEs2 ps) (compxE2 obj 0 0 @ shift (length (compE2 obj)) (stack_xlift (length [v]) (compxEs2 ps 0 0))) t
 h (stk @ [v], loc, length (compE2 obj) + pc, xcp) ta h' (stk'' @ [v], loc', length (compE2 obj) + (pc' - length (compE2 obj)), xcp')"
        by(rule append_exec_meth_xt) auto
      hence "exec_meth_d (compP2 P) ((compE2 obj @ compEs2 ps) @ [Invoke M' (length ps)])
     (compxE2 obj 0 0 @ shift (length (compE2 obj)) (stack_xlift (length [v]) (compxEs2 ps 0 0))) t
 h (stk @ [v], loc, length (compE2 obj) + pc, xcp) ta h' (stk'' @ [v], loc', length (compE2 obj) + (pc' - length (compE2 obj)), xcp')"
        by(rule exec_meth_append)
      moreover from exec' have "pc'  length (compE2 obj)"
        by(rule exec_meth_drop_xt_pc)(auto simp add: stack_xlift_compxE2)
      ultimately show ?thesis using stk'
        by(auto simp add: shift_compxEs2 stack_xlift_compxEs2)
    next
      case False
      with pc have pc: "pc = length (compEs2 ps)" by simp
      with bisimParam obtain vs where "stk = vs" "length vs = length ps" "xcp = None"
        by(auto dest: bisims1_pc_length_compEs2D)
      with exec pc Cons show ?thesis
        apply(auto elim!: exec_meth.cases intro!: exec_meth.intros simp add: split_beta extRet2JVM_def split: if_split_asm)
        apply(auto simp add: neq_Nil_conv split: extCallRet.split_asm)
        apply(force intro!: exec_meth.intros)+
        done
    qed
  qed
next
  case (bisim1CallThrowObj obj n a xs stk loc pc ps M')
  note bisim = P,obj,h  (Throw a, xs)  (stk, loc, pc, a)
  note IH = stk' loc' pc' xcp' STK. ?exec obj stk STK loc pc a stk' loc' pc' xcp'
              ?concl obj stk STK loc pc a stk' loc' pc' xcp'
  note exec = ?exec (objM'(ps)) stk STK loc pc a stk' loc' pc' xcp'
  from bisim have "pc < length (compE2 obj)" and [simp]: "xs = loc" by(auto dest: bisim1_ThrowD)
  with exec have "?exec obj stk STK loc pc a stk' loc' pc' xcp'"
    by(simp add: compxEs2_size_convs compxEs2_stack_xlift_convs)(erule exec_meth_take_xt)
  from IH[OF this] show ?case by auto
next
  case (bisim1CallThrowParams ps n vs a ps' xs stk loc pc obj M' v)
  note bisim = P,ps,h  (map Val vs @ Throw a # ps',xs) [↔] (stk,loc,pc,a)
  note IH = stk' loc' pc' xcp' STK. ?execs ps stk STK loc pc a stk' loc' pc' xcp'
              ?concls ps stk STK loc pc a stk' loc' pc' xcp'
  note exec = ?exec (objM'(ps)) (stk @ [v]) STK loc (length (compE2 obj) + pc) a stk' loc' pc' xcp'
  from bisim have pc: "pc < length (compEs2 ps)" "loc = xs" by(auto dest: bisims1_ThrowD)
  from exec have "exec_meth_d (compP2 P) ((compE2 obj @ compEs2 ps) @ [Invoke M' (length ps)])
     (stack_xlift (length STK) (compxE2 obj 0 0) @ shift (length (compE2 obj)) (stack_xlift (length (v # STK)) (compxEs2 ps 0 0))) t
     h (stk @ v # STK, loc, length (compE2 obj) + pc, a) ta h' (stk', loc', pc', xcp')"
    by(simp add: compxEs2_size_convs compxEs2_stack_xlift_convs)
  hence exec': "exec_meth_d (compP2 P) (compE2 obj @ compEs2 ps) (stack_xlift (length STK) (compxE2 obj 0 0) @
      shift (length (compE2 obj)) (stack_xlift (length (v # STK)) (compxEs2 ps 0 0))) t
     h (stk @ v # STK, loc, length (compE2 obj) + pc, a) ta h' (stk', loc', pc', xcp')"
    by(rule exec_meth_take)(simp add: pc)
  hence "?execs ps stk (v # STK) loc pc a stk' loc' (pc' - length (compE2 obj)) xcp'"
    by(rule exec_meth_drop_xt)(auto simp add: stack_xlift_compxE2)
  from IH[OF this] obtain stk'' where stk': "stk' = stk'' @ v # STK"
    and exec'': "exec_meth_d (compP2 P) (compEs2 ps) (compxEs2 ps 0 0) t h (stk, loc, pc, a) ta h' (stk'', loc', pc' - length (compE2 obj), xcp')" by auto
  from exec'' have "exec_meth_d (compP2 P) ((compE2 obj @ compEs2 ps) @ [Invoke M' (length ps)])
     (compxE2 obj 0 0 @ shift (length (compE2 obj)) (stack_xlift (length [v]) (compxEs2 ps 0 0))) t
     h (stk @ [v], loc, length (compE2 obj) + pc, a) ta h' (stk'' @ [v], loc', length (compE2 obj) + (pc' - length (compE2 obj)), xcp')"
    apply - 
    apply(rule exec_meth_append)
    apply(rule append_exec_meth_xt)
    apply(erule exec_meth_stk_offer)
    apply auto
    done
  moreover from exec' have "pc'  length (compE2 obj)"
    by(rule exec_meth_drop_xt_pc)(auto simp add: stack_xlift_compxE2)
  ultimately show ?case using stk' by(auto simp add: compxEs2_size_convs compxEs2_stack_xlift_convs)
next
  case bisim1CallThrow thus ?case
    by(auto elim!: exec_meth.cases dest: match_ex_table_pcsD simp add: stack_xlift_compxEs2 stack_xlift_compxE2)
next
  case bisim1BlockSome1 thus ?case
    by(fastforce elim: exec_meth.cases intro: exec_meth.intros)
next
  case bisim1BlockSome2 thus ?case
    by(fastforce elim: exec_meth.cases intro: exec_meth.intros)
next
  case (bisim1BlockSome4 e n e' xs stk loc pc xcp V T v)
  note IH = stk' loc' pc' xcp' STK. ?exec e stk STK loc pc xcp stk' loc' pc' xcp'
              ?concl e stk STK loc pc xcp stk' loc' pc' xcp'
  note bisim = P,e,h  (e', xs)  (stk, loc, pc, xcp)
  note exec = ?exec {V:T=v; e} stk STK loc (Suc (Suc pc)) xcp stk' loc' pc' xcp'
  hence exec': "exec_meth_d (compP2 P) ([Push v, Store V] @ compE2 e)
     (shift (length [Push v, Store V]) (stack_xlift (length STK) (compxE2 e 0 0))) t h (stk @ STK, loc, length [Push v, Store V] + pc, xcp) ta h' (stk', loc', pc', xcp')"
    by(simp add: compxE2_size_convs)
  hence "?exec e stk STK loc pc xcp stk' loc' (pc' - length [Push v, Store V]) xcp'"
    by(rule exec_meth_drop) auto
  from IH[OF this] obtain stk'' where stk': "stk' = stk'' @ STK"
    and exec'': "exec_meth_d (compP2 P) (compE2 e) (compxE2 e 0 0) t h (stk, loc, pc, xcp) ta
      h' (stk'', loc', pc' - length [Push v, Store V], xcp')" by auto
  from exec'' have "exec_meth_d (compP2 P) ([Push v, Store V] @ compE2 e)
     (shift (length [Push v, Store V]) (compxE2 e 0 0)) t h (stk, loc, length [Push v, Store V] + pc, xcp) ta h' (stk'', loc', length [Push v, Store V] + (pc' - length [Push v, Store V]), xcp')"
    by(rule append_exec_meth) auto
  moreover from exec' have "pc'  length [Push v, Store V]"
    by(rule exec_meth_drop_pc)(auto simp add: stack_xlift_compxE2)
  hence "Suc (Suc (pc' - Suc (Suc 0))) = pc'" by(simp)
  ultimately show ?case using stk' by(auto simp add: compxE2_size_convs)
next
  case (bisim1BlockThrowSome e n a xs stk loc pc V T v)
  note IH = stk' loc' pc' xcp' STK. ?exec e stk STK loc pc a stk' loc' pc' xcp'
              ?concl e stk STK loc pc a stk' loc' pc' xcp'
  note exec = ?exec {V:T=v; e} stk STK loc (Suc (Suc pc)) a stk' loc' pc' xcp'
  hence exec': "exec_meth_d (compP2 P) ([Push v, Store V] @ compE2 e)
     (shift (length [Push v, Store V]) (stack_xlift (length STK) (compxE2 e 0 0))) t h (stk @ STK, loc, length [Push v, Store V] + pc, a) ta h' (stk', loc', pc', xcp')"
    by(simp add: compxE2_size_convs)
  hence "?exec e stk STK loc pc a stk' loc' (pc' - length [Push v, Store V]) xcp'"
    by(rule exec_meth_drop) auto
  from IH[OF this] obtain stk'' where stk': "stk' = stk'' @ STK"
    and exec'': "exec_meth_d (compP2 P) (compE2 e) (compxE2 e 0 0) t h (stk, loc, pc, a) ta
      h' (stk'', loc', pc' - length [Push v, Store V], xcp')" by auto
  from exec'' have "exec_meth_d (compP2 P) ([Push v, Store V] @ compE2 e)
     (shift (length [Push v, Store V]) (compxE2 e 0 0)) t h (stk, loc, length [Push v, Store V] + pc, a) ta h' (stk'', loc', length [Push v, Store V] + (pc' - length [Push v, Store V]), xcp')"
    by(rule append_exec_meth) auto
  moreover from exec' have "pc'  length [Push v, Store V]"
    by(rule exec_meth_drop_pc)(auto simp add: stack_xlift_compxE2)
  hence "Suc (Suc (pc' - Suc (Suc 0))) = pc'" by(simp)
  ultimately show ?case using stk' by(auto simp add: compxE2_size_convs)
next
  case bisim1BlockNone thus ?case
    by(fastforce elim: exec_meth.cases intro: exec_meth.intros)
next
  case bisim1BlockThrowNone thus ?case
    by(fastforce elim: exec_meth.cases intro: exec_meth.intros)
next
  case (bisim1Sync1 e1 n e1' xs stk loc pc xcp e2 V)
  note bisim = P,e1,h  (e1', xs)  (stk, loc, pc, xcp)
  note IH = stk' loc' pc' xcp' STK. ?exec e1 stk STK loc pc xcp stk' loc' pc' xcp'
              ?concl e1 stk STK loc pc xcp stk' loc' pc' xcp'
  note exec = ?exec (sync⇘V(e1) e2) stk STK loc pc xcp stk' loc' pc' xcp'
  from bisim have pc: "pc  length (compE2 e1)" by(rule bisim1_pc_length_compE2)
  show ?case
  proof(cases "pc < length (compE2 e1)")
    case True
    from exec have "exec_meth_d (compP2 P)
      (compE2 e1 @ (Dup # Store V # MEnter # compE2 e2 @ [Load V, MExit, Goto 4, Load V, MExit, ThrowExc]))
      (stack_xlift (length STK) (compxE2 e1 0 0) @ shift (length (compE2 e1)) (stack_xlift (length STK) (compxE2 e2 3 0) @
       stack_xlift (length STK) [(3, 3 + length (compE2 e2), None, 6 + length (compE2 e2), 0)])) t
      h (stk @ STK, loc, pc, xcp) ta h' (stk', loc', pc', xcp')"
      by(simp add: shift_compxE2 stack_xlift_compxE2 ac_simps)
    hence "?exec e1 stk STK loc pc xcp stk' loc' pc' xcp'"
      by(rule exec_meth_take_xt)(rule True)
    from IH[OF this] obtain stk'' where stk': "stk' = stk'' @ STK"
      and exec': "exec_meth_d (compP2 P) (compE2 e1) (compxE2 e1 0 0) t h (stk, loc, pc, xcp) ta h' (stk'', loc', pc', xcp')"
      by blast
    from exec' have "exec_meth_d (compP2 P) (compE2 e1 @ (Dup # Store V # MEnter # compE2 e2 @ [Load V, MExit, Goto 4, Load V, MExit, ThrowExc]))
      (compxE2 e1 0 0 @ shift (length (compE2 e1)) (compxE2 e2 3 0 @ [(3, 3 + length (compE2 e2), None, 6 + length (compE2 e2), 0)])) t
      h (stk, loc, pc, xcp) ta h' (stk'', loc', pc', xcp')"
      by(rule exec_meth_append_xt)
    thus ?thesis using stk' by(simp add: shift_compxE2 stack_xlift_compxE2 ac_simps)
  next
    case False
    with pc have [simp]: "pc = length (compE2 e1)" by simp
    with bisim obtain v where "stk = [v]" "xcp = None" by(auto dest: bisim1_pc_length_compE2D)
    thus ?thesis using exec by(auto elim!: exec_meth.cases intro!: exec_meth.intros)
  qed
next
  case bisim1Sync2 thus ?case
    by(fastforce elim!: exec_meth.cases intro!: exec_meth.intros)
next
  case bisim1Sync3 thus ?case
    by(fastforce elim!: exec_meth.cases intro!: exec_meth.intros split: if_split_asm)
next
  case (bisim1Sync4 e2 n e2' xs stk loc pc xcp e1 V a)
  note IH = stk' loc' pc' xcp' STK. ?exec e2 stk STK loc pc xcp stk' loc' pc' xcp'
              ?concl e2 stk STK loc pc xcp stk' loc' pc' xcp'
  note bisim = P,e2,h  (e2', xs)  (stk, loc, pc, xcp)
  note exec = ?exec (sync⇘V(e1) e2) stk STK loc (Suc (Suc (Suc (length (compE2 e1) + pc)))) xcp stk' loc' pc' xcp'
  from bisim have pc: "pc  length (compE2 e2)" by(rule bisim1_pc_length_compE2)
  show ?case
  proof(cases "pc < length (compE2 e2)")
    case True
    let ?pre = "compE2 e1 @ [Dup, Store V, MEnter]"
    from exec have exec': "exec_meth_d (compP2 P) (?pre @ compE2 e2 @ [Load V, MExit, Goto 4, Load V, MExit, ThrowExc])
     (stack_xlift (length STK) (compxE2 e1 0 0) @ shift (length ?pre) (stack_xlift (length STK) (compxE2 e2 0 0) @
      [(0, length (compE2 e2), None, 3 + length (compE2 e2), length STK)])) t
     h (stk @ STK, loc, length ?pre + pc, xcp) ta h' (stk', loc', pc', xcp')"
      by(simp add: stack_xlift_compxE2 shift_compxE2 eval_nat_numeral ac_simps)
    hence exec'': "exec_meth_d (compP2 P) (compE2 e2 @ [Load V, MExit, Goto 4, Load V, MExit, ThrowExc])
      (stack_xlift (length STK) (compxE2 e2 0 0) @ [(0, length (compE2 e2), None, 3 + length (compE2 e2), length STK)]) t
     h (stk @ STK, loc, pc, xcp) ta h' (stk', loc', pc' - length ?pre, xcp')"
      by(rule exec_meth_drop_xt[where n=1])(auto simp add: stack_xlift_compxE2)
    from exec' have pc': "pc'  length ?pre"
      by(rule exec_meth_drop_xt_pc[where n'=1])(auto simp add: stack_xlift_compxE2)
    hence pc'': "(Suc (Suc (Suc (pc' - Suc (Suc (Suc 0)))))) = pc'" by simp
    show ?thesis
    proof(cases xcp)
      case None
      from exec'' None True
      have "?exec e2 stk STK loc pc xcp stk' loc' (pc' - length ?pre) xcp'"
        apply -
        apply (erule exec_meth.cases)
        apply (cases "compE2 e2 ! pc")
                            apply (fastforce simp add: is_Ref_def intro: exec_meth.intros split: if_split_asm cong del: image_cong_simp)+
        done
      from IH[OF this] obtain stk'' where stk: "stk' = stk'' @ STK"
        and exec''': "exec_meth_d (compP2 P) (compE2 e2) (compxE2 e2 0 0) t h (stk, loc, pc, xcp)
      ta h' (stk'', loc', pc' - length ?pre, xcp')" by blast
      from exec''' have "exec_meth_d (compP2 P) (compE2 e2 @ [Load V, MExit, Goto 4, Load V, MExit, ThrowExc])
      (compxE2 e2 0 0 @ [(0, length (compE2 e2), None, 3 + length (compE2 e2), 0)]) t
     h (stk, loc, pc, xcp) ta h' (stk'', loc', pc' - length ?pre, xcp')"
        by(rule exec_meth_append_xt)
      hence "exec_meth_d (compP2 P) (?pre @ compE2 e2 @ [Load V, MExit, Goto 4, Load V, MExit, ThrowExc])
      (compxE2 e1 0 0 @ shift (length ?pre) (compxE2 e2 0 0 @ [(0, length (compE2 e2), None, 3 + length (compE2 e2), 0)])) t
     h (stk, loc, length ?pre + pc, xcp) ta h' (stk'', loc', length ?pre + (pc' - length ?pre), xcp')"
        by(rule append_exec_meth_xt[where n=1]) auto
      thus ?thesis using stk pc' pc'' by(simp add: eval_nat_numeral shift_compxE2 ac_simps)
    next
      case (Some a)
      with exec'' have [simp]: "h' = h" "xcp' = None" "loc' = loc" "ta = ε"
        by(auto elim!: exec_meth.cases simp add: match_ex_table_append
           split: if_split_asm dest!: match_ex_table_stack_xliftD)
      show ?thesis
      proof(cases "match_ex_table (compP2 P) (cname_of h a) pc (compxE2 e2 0 0)")
        case None
        with Some exec'' True have [simp]: "stk' = Addr a # STK"
          and pc': "pc' = length (compE2 e1) + length (compE2 e2) + 6"
          by(auto elim!: exec_meth.cases simp add: match_ex_table_append
                  split: if_split_asm dest!: match_ex_table_stack_xliftD)
        with exec'' Some None
        have "exec_meth_d (compP2 P) (compE2 e2 @ [Load V, MExit, Goto 4, Load V, MExit, ThrowExc])
        (compxE2 e2 0 0 @ [(0, length (compE2 e2), None, 3 + length (compE2 e2), 0)]) t
        h (stk, loc, pc, a) ε h (Addr a # drop (length stk - 0) stk, loc, pc' - length ?pre, None)"
          by -(rule exec_catch, auto elim!: exec_meth.cases simp add: match_ex_table_append matches_ex_entry_def
                                     split: if_split_asm dest!: match_ex_table_stack_xliftD)
        hence "exec_meth_d (compP2 P) (?pre @ compE2 e2 @ [Load V, MExit, Goto 4, Load V, MExit, ThrowExc])
        (compxE2 e1 0 0 @ shift (length ?pre) (compxE2 e2 0 0 @ [(0, length (compE2 e2), None, 3 + length (compE2 e2), 0)])) t
        h (stk, loc, length ?pre + pc, a) ε h (Addr a # drop (length stk - 0) stk, loc,
        length ?pre + (pc' - length ?pre), None)"
          by(rule append_exec_meth_xt[where n=1]) auto
        with pc' Some show ?thesis by(simp add: eval_nat_numeral shift_compxE2 ac_simps)
      next
        case (Some pcd)
        with xcp = a exec'' True
        have "exec_meth_d (compP2 P) (compE2 e2) (compxE2 e2 0 0) t
          h (stk, loc, pc, a) ε h (Addr a # drop (length stk - snd pcd) stk, loc, pc' - length ?pre, None)"
          apply -
          apply(rule exec_catch)
          apply(auto elim!: exec_meth.cases simp add: match_ex_table_append split: if_split_asm
                     dest!: match_ex_table_stack_xliftD)
          done
        hence "exec_meth_d (compP2 P) (compE2 e2 @ [Load V, MExit, Goto 4, Load V, MExit, ThrowExc]) (compxE2 e2 0 0 @ [(0, length (compE2 e2), None, 3 + length (compE2 e2), 0)]) t
   h (stk, loc, pc, a) ε h (Addr a # drop (length stk - snd pcd) stk, loc, pc' - length ?pre, None)"
          by(rule exec_meth_append_xt)
        hence "exec_meth_d (compP2 P) (?pre @ compE2 e2 @ [Load V, MExit, Goto 4, Load V, MExit, ThrowExc]) 
              (compxE2 e1 0 0 @ shift (length ?pre) (compxE2 e2 0 0 @ [(0, length (compE2 e2), None, 3 + length (compE2 e2), 0)])) t
   h (stk, loc, length ?pre + pc, a) ε h (Addr a # drop (length stk - snd pcd) stk, loc, length ?pre + (pc' - length ?pre), None)"
          by(rule append_exec_meth_xt[where n=1])(auto)
        moreover from Some xcp = a exec'' True pc'
        have "pc' = length (compE2 e1) + 3 + fst pcd" "stk' = Addr a # drop (length stk - snd pcd) stk @ STK"
          by(auto elim!: exec_meth.cases dest!: match_ex_table_stack_xliftD simp: match_ex_table_append split: if_split_asm)
        ultimately show ?thesis using xcp = a by(auto simp add: eval_nat_numeral shift_compxE2 ac_simps)
      qed
    qed
  next
    case False
    with pc have [simp]: "pc = length (compE2 e2)" by simp
    with exec show ?thesis
      by(auto elim!: exec_meth.cases intro!: exec_meth.intros split: if_split_asm simp add: match_ex_table_append_not_pcs eval_nat_numeral)(simp_all add: matches_ex_entry_def)
  qed
next
  case bisim1Sync5 thus ?case
    by(fastforce elim: exec_meth.cases intro: exec_meth.intros split: if_split_asm)
next
  case bisim1Sync6 thus ?case  
    by(fastforce elim: exec_meth.cases intro: exec_meth.intros split: if_split_asm)     
next
  case bisim1Sync7 thus ?case
    by(fastforce elim: exec_meth.cases intro: exec_meth.intros split: if_split_asm)
next
  case bisim1Sync8 thus ?case
    by(fastforce elim: exec_meth.cases intro: exec_meth.intros split: if_split_asm)
next
  case (bisim1Sync9 e1 n e2 V a xs)
  note exec = ?exec (sync⇘V(e1) e2) [Addr a] STK xs (8 + length (compE2 e1) + length (compE2 e2)) None stk' loc' pc' xcp'
  let ?pre = "compE2 e1 @ Dup # Store V # MEnter # compE2 e2 @ [Load V, MExit, Goto 4, Load V, MExit]"
  from exec have exec': "exec_meth_d (compP2 P) (?pre @ [ThrowExc]) (stack_xlift (length STK) (compxE2 (sync⇘V(e1) e2) 0 0) @ shift (length ?pre) []) t h (Addr a # STK, xs, length ?pre + 0, None) ta h' (stk', loc', pc', xcp')"
    by(simp add: eval_nat_numeral)
  hence "exec_meth_d (compP2 P) [ThrowExc] [] t h (Addr a # STK, xs, 0, None) ta h' (stk', loc', pc' - length ?pre, xcp')"
    by(rule exec_meth_drop_xt)(auto simp add: stack_xlift_compxE2)
  moreover from exec' have "pc' = 8 + length (compE2 e1) + length (compE2 e2)" "stk' = Addr a # STK"
    by(auto elim!: exec_meth.cases)
  ultimately show ?case by(fastforce elim!: exec_meth.cases intro: exec_meth.intros)
next
  case (bisim1Sync10 e1 n e2 V a xs)
  note exec = ?exec (sync⇘V(e1) e2) [Addr a] STK xs (8 + length (compE2 e1) + length (compE2 e2)) a stk' loc' pc' xcp'
  hence "match_ex_table (compP2 P) (cname_of h a) (8 + length (compE2 e1) + length (compE2 e2)) (stack_xlift (length STK) (compxE2 (sync⇘V(e1) e2) 0 0))  None"
    by(rule exec_meth.cases) auto
  hence False by(auto split: if_split_asm simp add: match_ex_table_append_not_pcs)(simp add: matches_ex_entry_def)
  thus ?case ..
next
  case (bisim1Sync11 e1 n e2 V xs)
  note exec = ?exec (sync⇘V(e1) e2) [Null] STK xs (Suc (Suc (length (compE2 e1)))) addr_of_sys_xcpt NullPointer stk' loc' pc' xcp'
  hence "match_ex_table (compP2 P) (cname_of h (addr_of_sys_xcpt NullPointer)) (2 + length (compE2 e1)) (stack_xlift (length STK) (compxE2 (sync⇘V(e1) e2) 0 0))  None"
    by(rule exec_meth.cases)(auto split: if_split_asm)
  hence False by(auto split: if_split_asm simp add: match_ex_table_append_not_pcs)(simp add: matches_ex_entry_def)
  thus ?case ..
next
  case (bisim1SyncThrow e1 n a xs stk loc pc e2 V)
  note exec = ?exec (sync⇘V(e1) e2) stk STK loc pc a stk' loc' pc' xcp'
  note IH = stk' loc' pc' xcp' STK. ?exec e1 stk STK loc pc a stk' loc' pc' xcp'
              ?concl e1 stk STK loc pc a stk' loc' pc' xcp'
  note bisim = P,e1,h  (Throw a, xs)  (stk, loc, pc, a)
  from bisim have pc: "pc < length (compE2 e1)"
    and [simp]: "loc = xs" by(auto dest: bisim1_ThrowD)
  from exec have "exec_meth_d (compP2 P) (compE2 e1 @ Dup # Store V # MEnter # compE2 e2 @ [Load V, MExit, Goto 4, Load V, MExit, ThrowExc])
     (stack_xlift (length STK) (compxE2 e1 0 0) @ shift (length (compE2 e1)) (stack_xlift (length STK) (compxE2 e2 3 0) @
      [(3, 3 + length (compE2 e2), None, 6 + length (compE2 e2), length STK)])) t
     h (stk @ STK, loc, pc, a) ta h' (stk', loc', pc', xcp')"
    by(simp add: shift_compxE2 stack_xlift_compxE2 ac_simps)
  hence "?exec e1 stk STK loc pc a stk' loc' pc' xcp'"
    by(rule exec_meth_take_xt)(rule pc)
  from IH[OF this] show ?case by auto
next
  case (bisim1Seq1 e1 n e1' xs stk loc pc xcp e2)
  note bisim1 = P,e1,h  (e1', xs)  (stk, loc, pc, xcp)
  note IH = stk' loc' pc' xcp' STK. ?exec e1 stk STK loc pc xcp stk' loc' pc' xcp'
              ?concl e1 stk STK loc pc xcp stk' loc' pc' xcp'
  note exec = ?exec (e1;;e2) stk STK loc pc xcp stk' loc' pc' xcp'
  from bisim1 have pc: "pc  length (compE2 e1)" by(rule bisim1_pc_length_compE2)
  show ?case
  proof(cases "pc < length (compE2 e1)")
    case True
    from exec have "exec_meth_d (compP2 P) (compE2 e1 @ Pop # compE2 e2) (stack_xlift (length STK) (compxE2 e1 0 0) @
      shift (length (compE2 e1)) (stack_xlift (length STK) (compxE2 e2 (Suc 0) 0))) t
     h (stk @ STK, loc, pc, xcp) ta h' (stk', loc', pc', xcp')"
      by(simp add: shift_compxE2 stack_xlift_compxE2)
    hence "?exec e1 stk STK loc pc xcp stk' loc' pc' xcp'"
      by(rule exec_meth_take_xt)(rule True)
    from IH[OF this] show ?thesis by auto
  next
    case False
    with pc have [simp]: "pc = length (compE2 e1)" by simp
    with bisim1 obtain v where "xcp = None" "stk = [v]" by(auto dest: bisim1_pc_length_compE2D)
    with exec show ?thesis by(fastforce elim: exec_meth.cases intro: exec_meth.intros)
  qed
next
  case (bisim1SeqThrow1 e1 n a xs stk loc pc e2)
  note bisim1 = P,e1,h  (Throw a, xs)  (stk, loc, pc, a)
  note IH = stk' loc' pc' xcp' STK. ?exec e1 stk STK loc pc a stk' loc' pc' xcp'
              ?concl e1 stk STK loc pc a stk' loc' pc' xcp'
  note exec = ?exec (e1;;e2) stk STK loc pc a stk' loc' pc' xcp'
  from bisim1 have pc: "pc < length (compE2 e1)" by(auto dest: bisim1_ThrowD)
  from exec have "exec_meth_d (compP2 P) (compE2 e1 @ Pop # compE2 e2) (stack_xlift (length STK) (compxE2 e1 0 0) @
      shift (length (compE2 e1)) (stack_xlift (length STK) (compxE2 e2 (Suc 0) 0))) t
     h (stk @ STK, loc, pc, a) ta h' (stk', loc', pc', xcp')"
    by(simp add: shift_compxE2 stack_xlift_compxE2)
  hence "?exec e1 stk STK loc pc a stk' loc' pc' xcp'"
    by(rule exec_meth_take_xt)(rule pc)
  from IH[OF this] show ?case by(fastforce elim: exec_meth.cases intro: exec_meth.intros)
next
  case (bisim1Seq2 e2 n e2' xs stk loc pc xcp e1)
  note bisim2 = P,e2,h  (e2', xs)  (stk, loc, pc, xcp)
  note IH = stk' loc' pc' xcp' STK. ?exec e2 stk STK loc pc xcp stk' loc' pc' xcp'
              ?concl e2 stk STK loc pc xcp stk' loc' pc' xcp'
  note exec = ?exec (e1;;e2) stk STK loc (Suc (length (compE2 e1) + pc)) xcp stk' loc' pc' xcp'
  from bisim2 have pc: "pc  length (compE2 e2)" by(rule bisim1_pc_length_compE2)
  show ?case
  proof(cases "pc < length (compE2 e2)")
    case False
    with pc have [simp]: "pc = length (compE2 e2)" by simp
    from bisim2 have "xcp = None" by(auto dest: bisim1_pc_length_compE2D)
    with exec have False by(auto elim: exec_meth.cases)
    thus ?thesis ..
  next
    case True
    from exec have exec':
      "exec_meth_d (compP2 P) ((compE2 e1 @ [Pop]) @ compE2 e2) (stack_xlift (length STK) (compxE2 e1 0 0) @
      shift (length (compE2 e1 @ [Pop])) (stack_xlift (length STK) (compxE2 e2 0 0))) t
     h (stk @ STK, loc, length ((compE2 e1) @ [Pop]) + pc, xcp) ta h' (stk', loc', pc', xcp')"
      by(simp add: compxE2_size_convs)
    hence "?exec e2 stk STK loc pc xcp stk' loc' (pc' - length ((compE2 e1) @ [Pop])) xcp'"
      by(rule exec_meth_drop_xt)(auto simp add: stack_xlift_compxE2)
    from IH[OF this] obtain stk'' where stk': "stk' = stk'' @ STK"
      and exec'': "exec_meth_d (compP2 P) (compE2 e2) (compxE2 e2 0 0) t h (stk, loc, pc, xcp)
      ta h' (stk'', loc', pc' - length (compE2 e1 @ [Pop]), xcp')" by auto
    from exec'' have "exec_meth_d (compP2 P) ((compE2 e1 @ [Pop]) @ compE2 e2) (compxE2 e1 0 0 @ shift (length (compE2 e1 @ [Pop])) (compxE2 e2 0 0)) t
     h (stk, loc, length ((compE2 e1) @ [Pop]) + pc, xcp) ta h' (stk'', loc', length ((compE2 e1) @ [Pop]) + (pc' - length ((compE2 e1) @ [Pop])), xcp')"
      by(rule append_exec_meth_xt) auto
    moreover from exec' have "pc'  length ((compE2 e1) @ [Pop])"
      by(rule exec_meth_drop_xt_pc)(auto simp add: stack_xlift_compxE2)
    ultimately show ?thesis using stk' by(auto simp add: shift_compxE2 stack_xlift_compxE2)
  qed
next
  case (bisim1Cond1 e n e' xs stk loc pc xcp e1 e2)
  note bisim = P,e,h  (e', xs)  (stk, loc, pc, xcp)
  note IH = stk' loc' pc' xcp' STK. ?exec e stk STK loc pc xcp stk' loc' pc' xcp'
              ?concl e stk STK loc pc xcp stk' loc' pc' xcp'
  note exec = ?exec (if (e) e1 else e2) stk STK loc pc xcp stk' loc' pc' xcp'
  from bisim have pc: "pc  length (compE2 e)" by(rule bisim1_pc_length_compE2)
  show ?case
  proof(cases "pc < length (compE2 e)")
    case True
    from exec have "exec_meth_d (compP2 P) (compE2 e @ IfFalse (2 + int (length (compE2 e1))) # compE2 e1 @ Goto (1 + int (length (compE2 e2))) # compE2 e2)
     (stack_xlift (length STK) (compxE2 e 0 0) @ shift (length (compE2 e)) (stack_xlift (length STK) (compxE2 e1 (Suc 0) 0) @
      stack_xlift (length STK) (compxE2 e2 (Suc (Suc (length (compE2 e1)))) 0))) t
     h (stk @ STK, loc, pc, xcp) ta h' (stk', loc', pc', xcp')"
      by(simp add: stack_xlift_compxE2 shift_compxE2 ac_simps)
    hence "?exec e stk STK loc pc xcp stk' loc' pc' xcp'"
      by(rule exec_meth_take_xt)(rule True)
    from IH[OF this] show ?thesis by auto
  next
    case False
    with pc have [simp]: "pc = length (compE2 e)" by simp
    from bisim obtain v where "stk = [v]" "xcp = None"
      by(auto dest: bisim1_pc_length_compE2D)
    with exec show ?thesis by(auto elim!: exec_meth.cases intro!: exec_meth.intros)
  qed
next
  case (bisim1CondThen e1 n e1' xs stk loc pc xcp e e2)
  note bisim = P,e1,h  (e1', xs)  (stk, loc, pc, xcp)
  note IH = stk' loc' pc' xcp' STK. ?exec e1 stk STK loc pc xcp stk' loc' pc' xcp'
              ?concl e1 stk STK loc pc xcp stk' loc' pc' xcp'
  note exec = ?exec (if (e) e1 else e2) stk STK loc (Suc (length (compE2 e) + pc)) xcp stk' loc' pc' xcp'
  from bisim have pc: "pc  length (compE2 e1)" by(rule bisim1_pc_length_compE2)
  show ?case
  proof(cases "pc < length (compE2 e1)")
    case True
    let ?pre = "compE2 e @ [IfFalse (2 + int (length (compE2 e1)))]"
    from exec have exec': "exec_meth_d (compP2 P) (?pre @ compE2 e1 @ Goto (1 + int (length (compE2 e2))) # compE2 e2)
     (stack_xlift (length STK) (compxE2 e 0 0) @ shift (length ?pre) (stack_xlift (length STK) (compxE2 e1 0 0) @
      shift (length (compE2 e1)) (stack_xlift (length STK) (compxE2 e2 (Suc 0) 0)))) t
     h (stk @ STK, loc, length ?pre + pc, xcp) ta h' (stk', loc', pc', xcp')"
      by(simp add: stack_xlift_compxE2 shift_compxE2 ac_simps)
    hence "exec_meth_d (compP2 P) (compE2 e1 @ Goto (1 + int (length (compE2 e2))) # compE2 e2)
      (stack_xlift (length STK) (compxE2 e1 0 0) @ shift (length (compE2 e1)) (stack_xlift (length STK) (compxE2 e2 (Suc 0) 0))) t
     h (stk @ STK, loc, pc, xcp) ta h' (stk', loc', pc' - length ?pre, xcp')"
      by(rule exec_meth_drop_xt)(auto simp add: stack_xlift_compxE2)
    hence "?exec e1 stk STK loc pc xcp stk' loc' (pc' - length ?pre) xcp'"
      by(rule exec_meth_take_xt)(rule True)
    from IH[OF this] obtain stk'' where stk': "stk' = stk'' @ STK"
      and exec'': "exec_meth_d (compP2 P) (compE2 e1) (compxE2 e1 0 0) t h (stk, loc, pc, xcp)
      ta h' (stk'', loc', pc' - length ?pre, xcp')" by blast
    from exec'' have "exec_meth_d (compP2 P) (compE2 e1 @ Goto (1 + int (length (compE2 e2))) # compE2 e2)
      (compxE2 e1 0 0 @ shift (length (compE2 e1)) (compxE2 e2 (Suc 0) 0)) t
     h (stk, loc, pc, xcp) ta h' (stk'', loc', pc' - length ?pre, xcp')"
      by(rule exec_meth_append_xt)
    hence "exec_meth_d (compP2 P) (?pre @ compE2 e1 @ Goto (1 + int (length (compE2 e2))) # compE2 e2)
      (compxE2 e 0 0 @ shift (length ?pre) (compxE2 e1 0 0 @ shift (length (compE2 e1)) (compxE2 e2 (Suc 0) 0))) t
     h (stk, loc, length ?pre + pc, xcp) ta h' (stk'', loc', length ?pre + (pc' - length ?pre), xcp')"
      by(rule append_exec_meth_xt)(auto)
    moreover from exec' have "pc'  length ?pre"
      by(rule exec_meth_drop_xt_pc)(auto simp add: stack_xlift_compxE2)
    ultimately show ?thesis using stk'
      by(auto simp add: shift_compxE2 stack_xlift_compxE2 ac_simps)
  next
    case False
    with pc have [simp]: "pc = length (compE2 e1)" by simp
    from bisim obtain v where "stk = [v]" "xcp = None"
      by(auto dest: bisim1_pc_length_compE2D)
    with exec show ?thesis by(auto elim!: exec_meth.cases intro!: exec_meth.intros)
  qed
next
  case (bisim1CondElse e2 n e2' xs stk loc pc xcp e e1)
  note IH = stk' loc' pc' xcp' STK. ?exec e2 stk STK loc pc xcp stk' loc' pc' xcp'
              ?concl e2 stk STK loc pc xcp stk' loc' pc' xcp'
  note exec = ?exec (if (e) e1 else e2) stk STK loc (Suc (Suc (length (compE2 e) + length (compE2 e1) + pc))) xcp stk' loc' pc' xcp'
  note bisim = P,e2,h  (e2', xs)  (stk, loc, pc, xcp)
  from bisim have pc: "pc  length (compE2 e2)" by(rule bisim1_pc_length_compE2)

  let ?pre = "compE2 e @ IfFalse (2 + int (length (compE2 e1))) # compE2 e1 @ [Goto (1 + int (length (compE2 e2)))]"
  from exec have exec': "exec_meth_d (compP2 P) (?pre @ compE2 e2)
    (stack_xlift (length STK) (compxE2 e 0 0 @ compxE2 e1 (Suc (length (compE2 e))) 0) @
     shift (length ?pre) (stack_xlift (length STK) (compxE2 e2 0 0))) t
    h (stk @ STK, loc, length ?pre + pc, xcp) ta h' (stk', loc', pc', xcp')"
    by(simp add: stack_xlift_compxE2 shift_compxE2 ac_simps)
  hence "?exec e2 stk STK loc pc xcp stk' loc' (pc' - length ?pre) xcp'"
    by(rule exec_meth_drop_xt)(auto simp add: stack_xlift_compxE2 shift_compxEs2 ac_simps)
  from IH[OF this] obtain stk'' where stk': "stk' = stk'' @ STK"
    and exec'': "exec_meth_d (compP2 P) (compE2 e2) (compxE2 e2 0 0) t h (stk, loc, pc, xcp)
    ta h' (stk'', loc', pc' - length ?pre, xcp')" by blast
  from exec'' have "exec_meth_d (compP2 P) (?pre @ compE2 e2)
    ((compxE2 e 0 0 @ compxE2 e1 (Suc (length (compE2 e))) 0) @ shift (length ?pre) (compxE2 e2 0 0)) t
    h (stk, loc, length ?pre + pc, xcp) ta h' (stk'', loc', length ?pre + (pc' - length ?pre), xcp')"
    by(rule append_exec_meth_xt)(auto)
  moreover from exec' have "pc'  length ?pre"
    by(rule exec_meth_drop_xt_pc)(auto simp add: stack_xlift_compxE2)
  moreover hence "(Suc (Suc (pc' - Suc (Suc 0)))) = pc'" by simp
  ultimately show ?case using stk'
    by(auto simp add: shift_compxE2 stack_xlift_compxE2 ac_simps eval_nat_numeral)
next
  case (bisim1CondThrow e n a xs stk loc pc e1 e2)
  note bisim = P,e,h  (Throw a, xs)  (stk, loc, pc, a)
  note IH = stk' loc' pc' xcp' STK. ?exec e stk STK loc pc a stk' loc' pc' xcp'
              ?concl e stk STK loc pc a stk' loc' pc' xcp'
  note exec = ?exec (if (e) e1 else e2) stk STK loc pc a stk' loc' pc' xcp'
  from bisim have pc: "pc < length (compE2 e)" by(auto dest: bisim1_ThrowD)
  from exec have "exec_meth_d (compP2 P) (compE2 e @ IfFalse (2 + int (length (compE2 e1))) # compE2 e1 @ Goto (1 + int (length (compE2 e2))) # compE2 e2)
     (stack_xlift (length STK) (compxE2 e 0 0) @ shift (length (compE2 e)) (stack_xlift (length STK) (compxE2 e1 (Suc 0) 0) @
      stack_xlift (length STK) (compxE2 e2 (Suc (Suc (length (compE2 e1)))) 0))) t
     h (stk @ STK, loc, pc, a) ta h' (stk', loc', pc', xcp')"
    by(simp add: stack_xlift_compxE2 shift_compxE2 ac_simps)
  hence "?exec e stk STK loc pc a stk' loc' pc' xcp'"
    by(rule exec_meth_take_xt)(rule pc)
  from IH[OF this] show ?case by auto
next
  case (bisim1While1 c n e xs)
  note IH = stk' loc' pc' xcp' STK. ?exec c [] STK xs 0 None stk' loc' pc' xcp'
              ?concl c [] STK xs 0 None stk' loc' pc' xcp'
  note exec = ?exec (while (c) e) [] STK xs 0 None stk' loc' pc' xcp'
  hence "exec_meth_d (compP2 P) (compE2 c @ IfFalse (int (length (compE2 e)) + 3) # compE2 e @ [Pop, Goto (-2 + (- int (length (compE2 e)) - int (length (compE2 c)))), Push Unit])
     (stack_xlift (length STK) (compxE2 c 0 0) @ shift (length (compE2 c)) (stack_xlift (length STK) (compxE2 e (Suc 0) 0))) t
     h ([] @ STK, xs, 0, None) ta h' (stk', loc', pc', xcp')"
    by(simp add: compxE2_size_convs)
  hence "?exec c [] STK xs 0 None stk' loc' pc' xcp'"
    by(rule exec_meth_take_xt) simp
  from IH[OF this] show ?case by auto
next
  case (bisim1While3 c n c' xs stk loc pc xcp e)
  note bisim = P,c,h  (c', xs)  (stk, loc, pc, xcp)
  note IH = stk' loc' pc' xcp' STK. ?exec c stk STK loc pc xcp stk' loc' pc' xcp'
              ?concl c stk STK loc pc xcp stk' loc' pc' xcp'
  note exec = ?exec (while (c) e) stk STK loc pc xcp stk' loc' pc' xcp'
  from bisim have pc: "pc  length (compE2 c)" by(rule bisim1_pc_length_compE2)
  show ?case
  proof(cases "pc < length (compE2 c)")
    case True
    from exec have "exec_meth_d (compP2 P) (compE2 c @ IfFalse (int (length (compE2 e)) + 3) # compE2 e @ [Pop, Goto (-2 + (- int (length (compE2 e)) - int (length (compE2 c)))), Push Unit])
     (stack_xlift (length STK) (compxE2 c 0 0) @ shift (length (compE2 c)) (stack_xlift (length STK) (compxE2 e (Suc 0) 0))) t
      h (stk @ STK, loc, pc, xcp) ta h' (stk', loc', pc', xcp')"
      by(simp add: compxE2_size_convs)
    hence "?exec c stk STK loc pc xcp stk' loc' pc' xcp'"
      by(rule exec_meth_take_xt)(rule True)
    from IH[OF this] show ?thesis by auto
  next
    case False
    with pc have [simp]: "pc = length (compE2 c)" by simp
    from bisim obtain v where "stk = [v]" "xcp = None" by(auto dest: bisim1_pc_length_compE2D)
    with exec show ?thesis by(auto elim!: exec_meth.cases intro!: exec_meth.intros)
  qed
next
  case (bisim1While4 e n e' xs stk loc pc xcp c)
  note bisim = P,e,h  (e', xs)  (stk, loc, pc, xcp)
  note IH = stk' loc' pc' xcp' STK. ?exec e stk STK loc pc xcp stk' loc' pc' xcp'
              ?concl e stk STK loc pc xcp stk' loc' pc' xcp'
  note exec = ?exec (while (c) e) stk STK loc (Suc (length (compE2 c) + pc)) xcp stk' loc' pc' xcp'
  from bisim have pc: "pc  length (compE2 e)" by(rule bisim1_pc_length_compE2)
  show ?case
  proof(cases "pc < length (compE2 e)")
    case True
    let ?pre = "compE2 c @ [IfFalse (int (length (compE2 e)) + 3)]"
    from exec have "exec_meth_d (compP2 P) ((?pre @ compE2 e) @ [Pop, Goto (-2 + (- int (length (compE2 e)) - int (length (compE2 c)))), Push Unit])
                   (stack_xlift (length STK) (compxE2 c 0 0) @ shift (length ?pre) (stack_xlift (length STK) (compxE2 e 0 0))) t
                    h (stk @ STK, loc, length ?pre + pc, xcp) ta h' (stk', loc', pc', xcp')"
      by(simp add: compxE2_size_convs)
    hence exec': "exec_meth_d (compP2 P) (?pre @ compE2 e) (stack_xlift (length STK) (compxE2 c 0 0) @ shift (length ?pre) (stack_xlift (length STK) (compxE2 e 0 0))) t
                 h (stk @ STK, loc, length ?pre + pc, xcp) ta h' (stk', loc', pc', xcp')"
      by(rule exec_meth_take)(auto intro: True)
    hence "?exec e stk STK loc pc xcp stk' loc' (pc' - length ?pre) xcp'"
      by(rule exec_meth_drop_xt)(auto simp add: stack_xlift_compxE2)      
    from IH[OF this] obtain stk'' where stk': "stk' = stk'' @ STK"
      and exec'': "exec_meth_d (compP2 P) (compE2 e) (compxE2 e 0 0) t h (stk, loc, pc, xcp) ta h' (stk'', loc', pc' - length ?pre, xcp')" by auto
    from exec'' have "exec_meth_d (compP2 P) (?pre @ compE2 e) (compxE2 c 0 0 @ shift (length ?pre) (compxE2 e 0 0)) t
                     h (stk, loc, length ?pre + pc, xcp) ta h' (stk'', loc', length ?pre + (pc' - length ?pre), xcp')"
      by(rule append_exec_meth_xt) auto
    hence "exec_meth_d (compP2 P) ((?pre @ compE2 e) @ [Pop, Goto (-2 + (- int (length (compE2 e)) - int (length (compE2 c)))), Push Unit])
           (compxE2 c 0 0 @ shift (length ?pre) (compxE2 e 0 0)) t
           h (stk, loc, length ?pre + pc, xcp) ta h' (stk'', loc', length ?pre + (pc' - length ?pre), xcp')"
      by(rule exec_meth_append)
    moreover from exec' have "pc'  length ?pre"
     by(rule exec_meth_drop_xt_pc)(auto simp add: stack_xlift_compxE2)
   moreover have "-2 + (- int (length (compE2 e)) - int (length (compE2 c))) = - int (length (compE2 c)) + (-2 - int (length (compE2 e)))" by simp
   ultimately show ?thesis using stk'
     by(auto simp add: shift_compxE2 stack_xlift_compxE2 algebra_simps uminus_minus_left_commute)
 next
    case False
    with pc have [simp]: "pc = length (compE2 e)" by simp
    from bisim obtain v where "stk = [v]" "xcp = None" by(auto dest: bisim1_pc_length_compE2D)
    with exec show ?thesis by(auto elim!: exec_meth.cases intro!: exec_meth.intros)
  qed
next
  case (bisim1While6 c n e xs)
  note exec = ?exec (while (c) e) [] STK xs (Suc (Suc (length (compE2 c) + length (compE2 e)))) None stk' loc' pc' xcp'
  thus ?case by(rule exec_meth.cases)(simp_all, auto intro!: exec_meth.intros)
next
  case (bisim1While7 c n e xs)
  note exec = ?exec (while (c) e) [] STK xs (Suc (Suc (Suc (length (compE2 c) + length (compE2 e))))) None stk' loc' pc' xcp'
  thus ?case by(rule exec_meth.cases)(simp_all, auto intro!: exec_meth.intros)
next
  case (bisim1WhileThrow1 c n a xs stk loc pc e)
  note bisim = P,c,h  (Throw a, xs)  (stk, loc, pc, a)
  note IH = stk' loc' pc' xcp' STK. ?exec c stk STK loc pc a stk' loc' pc' xcp'
              ?concl c stk STK loc pc a stk' loc' pc' xcp'
  note exec = ?exec (while (c) e) stk STK loc pc a stk' loc' pc' xcp'
  from bisim have pc: "pc < length (compE2 c)" by(auto dest: bisim1_ThrowD)
  from exec have "exec_meth_d (compP2 P) (compE2 c @ IfFalse (int (length (compE2 e)) + 3) # compE2 e @ [Pop, Goto (-2 + (- int (length (compE2 e)) - int (length (compE2 c)))), Push Unit])
     (stack_xlift (length STK) (compxE2 c 0 0) @ shift (length (compE2 c)) (stack_xlift (length STK) (compxE2 e (Suc 0) 0))) t
     h (stk @ STK, loc, pc, a) ta h' (stk', loc', pc', xcp')"
    by(simp add: compxE2_size_convs)
  hence "?exec c stk STK loc pc a stk' loc' pc' xcp'"
    by(rule exec_meth_take_xt)(rule pc)
  from IH[OF this] show ?case by auto
next
  case (bisim1WhileThrow2 e n a xs stk loc pc c)
  note bisim = P,e,h  (Throw a, xs)  (stk, loc, pc, a)
  note IH = stk' loc' pc' xcp' STK. ?exec e stk STK loc pc a stk' loc' pc' xcp'
              ?concl e stk STK loc pc a stk' loc' pc' xcp'
  note exec = ?exec (while (c) e) stk STK loc (Suc (length (compE2 c) + pc)) a stk' loc' pc' xcp'
  from bisim have pc: "pc < length (compE2 e)" by(auto dest: bisim1_ThrowD)
  let ?pre = "compE2 c @ [IfFalse (int (length (compE2 e)) + 3)]"
  from exec have "exec_meth_d (compP2 P) ((?pre @ compE2 e) @ [Pop, Goto (-2 + (- int (length (compE2 e)) - int (length (compE2 c)))), Push Unit])
     (stack_xlift (length STK) (compxE2 c 0 0) @ shift (length ?pre) (stack_xlift (length STK) (compxE2 e 0 0))) t
    h (stk @ STK, loc, length ?pre + pc, a) ta h' (stk', loc', pc', xcp')"
    by(simp add: compxE2_size_convs)
  hence exec': "exec_meth_d (compP2 P) (?pre @ compE2 e)
    (stack_xlift (length STK) (compxE2 c 0 0) @ shift (length ?pre) (stack_xlift (length STK) (compxE2 e 0 0))) t
    h (stk @ STK, loc, (length ?pre + pc), a) ta h' (stk', loc', pc', xcp')"
    by(rule exec_meth_take)(auto intro: pc)
  hence "?exec e stk STK loc pc a stk' loc' (pc' - length ?pre) xcp'"
    by(rule exec_meth_drop_xt)(auto simp add: stack_xlift_compxE2)      
  from IH[OF this] obtain stk'' where stk': "stk' = stk'' @ STK"
    and exec'': "exec_meth_d (compP2 P) (compE2 e) (compxE2 e 0 0) t h (stk, loc, pc, a) ta h' (stk'', loc', pc' - length ?pre, xcp')" by auto
  from exec'' have "exec_meth_d (compP2 P) (?pre @ compE2 e) (compxE2 c 0 0 @ shift (length ?pre) (compxE2 e 0 0)) t
    h (stk, loc, length ?pre + pc, a) ta h' (stk'', loc', length ?pre + (pc' - length ?pre), xcp')"
    by(rule append_exec_meth_xt) auto
  hence "exec_meth_d (compP2 P) ((?pre @ compE2 e) @ [Pop, Goto (-2 + (- int (length (compE2 e)) - int (length (compE2 c)))), Push Unit])
    (compxE2 c 0 0 @ shift (length ?pre) (compxE2 e 0 0)) t
    h (stk, loc, length ?pre + pc, a) ta h' (stk'', loc', length ?pre + (pc' - length ?pre), xcp')"
    by(rule exec_meth_append)
  moreover from exec' have "pc'  length ?pre"
    by(rule exec_meth_drop_xt_pc)(auto simp add: stack_xlift_compxE2)
  moreover have "-2 + (- int (length (compE2 e)) - int (length (compE2 c))) = - int (length (compE2 c)) + (-2 - int (length (compE2 e)))" by simp
  ultimately show ?case using stk'
    by(auto simp add: shift_compxE2 stack_xlift_compxE2 algebra_simps uminus_minus_left_commute)
next
  case (bisim1Throw1 e n e' xs stk loc pc xcp)
  note bisim = P,e,h  (e', xs)  (stk, loc, pc, xcp)
  note IH = stk' loc' pc' xcp' STK. ?exec e stk STK loc pc xcp stk' loc' pc' xcp'
              ?concl e stk STK loc pc xcp stk' loc' pc' xcp'
  note exec = ?exec (throw e) stk STK loc pc xcp stk' loc' pc' xcp'
  from bisim have pc: "pc  length (compE2 e)" by(rule bisim1_pc_length_compE2)
  show ?case
  proof(cases "pc < length (compE2 e)")
    case True
    with exec have "?exec e stk STK loc pc xcp stk' loc' pc' xcp'" by(auto elim: exec_meth_take)
    from IH[OF this] show ?thesis by auto
  next
    case False
    with pc have [simp]: "pc = length (compE2 e)" by simp
    from bisim obtain v where "stk = [v]" "xcp = None" by(auto dest: bisim1_pc_length_compE2D)
    with exec show ?thesis by(auto elim!: exec_meth.cases intro!: exec_meth.intros split: if_split_asm)
  qed
next
  case bisim1Throw2 thus ?case
    apply(auto elim!:exec_meth.cases intro: exec_meth.intros dest!: match_ex_table_stack_xliftD)
    apply(auto intro: exec_meth.intros dest!: match_ex_table_stack_xliftD intro!: exI)
    apply(auto simp add: le_Suc_eq)
    done
next
  case bisim1ThrowNull thus ?case
    apply(auto elim!:exec_meth.cases intro: exec_meth.intros dest!: match_ex_table_stack_xliftD)
    apply(auto intro: exec_meth.intros dest!: match_ex_table_stack_xliftD intro!: exI)
    apply(auto simp add: le_Suc_eq)
    done
next
  case (bisim1ThrowThrow e n a xs stk loc pc)
  note bisim = P,e,h  (Throw a, xs)  (stk, loc, pc, a)
  note IH = stk' loc' pc' xcp' STK. ?exec e stk STK loc pc a stk' loc' pc' xcp'
              ?concl e stk STK loc pc a stk' loc' pc' xcp'
  note exec = ?exec (throw e) stk STK loc pc a stk' loc' pc' xcp'
  from bisim have pc: "pc < length (compE2 e)" by(auto dest: bisim1_ThrowD)
  with exec have "?exec e stk STK loc pc a stk' loc' pc' xcp'"
    by(auto elim: exec_meth_take simp add: compxE2_size_convs)
  from IH[OF this] show ?case by auto
next
  case (bisim1Try e n e' xs stk loc pc xcp e2 C' V)
  note bisim = P,e,h  (e', xs)  (stk, loc, pc, xcp)
  note IH = stk' loc' pc' xcp' STK. ?exec e stk STK loc pc xcp stk' loc' pc' xcp'
              ?concl e stk STK loc pc xcp stk' loc' pc' xcp'
  note exec = ?exec (try e catch(C' V) e2) stk STK loc pc xcp stk' loc' pc' xcp'
  from bisim have pc: "pc  length (compE2 e)" by(rule bisim1_pc_length_compE2)
  show ?case
  proof(cases "pc < length (compE2 e)")
    case True
    from exec have exec': "exec_meth_d (compP2 P) (compE2 e @ Goto (int (length (compE2 e2)) + 2) # Store V # compE2 e2)
      (stack_xlift (length STK) (compxE2 e 0 0) @  shift (length (compE2 e)) (stack_xlift (length STK) (compxE2 e2 (Suc (Suc 0)) 0)) @ [(0, length (compE2 e), C', Suc (length (compE2 e)), length STK)]) t
      h (stk @ STK, loc, pc, xcp) ta h' (stk', loc', pc', xcp')"
      by(simp add: compxE2_size_convs)
    show ?thesis
    proof(cases xcp)
      case None
      with exec' True have "?exec e stk STK loc pc xcp stk' loc' pc' xcp'"
        apply -
        apply (erule exec_meth.cases)
        apply (cases "compE2 e ! pc")
        apply (fastforce simp add: is_Ref_def intro: exec_meth.intros split: if_split_asm cong del: image_cong_simp)+
        done
      from IH[OF this] show ?thesis by auto
    next
      case (Some a)
      with exec' have [simp]: "h' = h" "loc' = loc" "xcp' = None" "ta = ε"
        by(auto elim: exec_meth.cases)
      show ?thesis
      proof(cases "match_ex_table (compP2 P) (cname_of h a) pc (compxE2 e 0 0)")
        case (Some pcd)
        from exec xcp = a Some pc
        have stk': "stk' = Addr a # (drop (length stk - snd pcd) stk) @ STK"
          by(auto elim!: exec_meth.cases simp add: match_ex_table_append split: if_split_asm dest!: match_ex_table_stack_xliftD)
        from exec' xcp = a Some pc have "exec_meth_d (compP2 P)
          (compE2 e) (stack_xlift (length STK) (compxE2 e 0 0)) t h (stk @ STK, loc, pc, a) ε h (Addr a # (drop (length (stk @ STK) - (snd pcd + length STK)) (stk @ STK)), loc, pc', None)"
          apply -
          apply(rule exec_meth.intros)
          apply(auto elim!: exec_meth.cases simp add: match_ex_table_append split: if_split_asm dest!: match_ex_table_shift_pcD match_ex_table_stack_xliftD)
          done
        from IH[unfolded ta = ε xcp = a h' = h, OF this]
        have stk: "Addr a # drop (length stk - snd pcd) (stk @ STK) = Addr a # drop (length stk - snd pcd) stk @ STK"
          and exec'': "exec_meth_d (compP2 P) (compE2 e) (compxE2 e 0 0) t h (stk, loc, pc, a) ε h (Addr a # drop (length stk - snd pcd) stk, loc, pc', None)" by auto
        thus ?thesis using Some stk' xcp = a by(auto)
      next
        case None
        with Some exec pc have stk': "stk' = Addr a # STK"
          and pc': "pc' = Suc (length (compE2 e))"
          and subcls: "compP2 P  cname_of h a * C'"
          by(auto elim!: exec_meth.cases split: if_split_asm simp add: match_ex_table_append_not_pcs)(simp add: matches_ex_entry_def)
        moreover from Some True None pc' subcls
        have "exec_meth_d (compP2 P) (compE2 (try e catch(C' V) e2)) (compxE2 (try e catch(C' V) e2) 0 0) t h
          (stk, loc, pc, a) ε h (Addr a # drop (length stk - 0) stk, loc, pc', None)"
          by -(rule exec_catch,auto simp add: match_ex_table_append_not_pcs matches_ex_entry_def)
        ultimately show ?thesis using Some by auto
      qed
    qed
  next
    case False
    with pc have [simp]: "pc = length (compE2 e)" by simp
    from bisim obtain v where "stk = [v]" "xcp = None" by(auto dest: bisim1_pc_length_compE2D)
    with exec show ?thesis by(auto elim!: exec_meth.cases intro!: exec_meth.intros split: if_split_asm)
  qed
next
  case bisim1TryCatch1 thus ?case
    by(auto elim!: exec_meth.cases intro!: exec_meth.intros split: if_split_asm)
next
  case (bisim1TryCatch2 e2 n e' xs stk loc pc xcp e C' V)
  note bisim = P,e2,h  (e', xs)  (stk, loc, pc, xcp)
  note IH = stk' loc' pc' xcp' STK. ?exec e2 stk STK loc pc xcp stk' loc' pc' xcp'
              ?concl e2 stk STK loc pc xcp stk' loc' pc' xcp'
  note exec = ?exec (try e catch(C' V) e2) stk STK loc (Suc (Suc (length (compE2 e) + pc))) xcp stk' loc' pc' xcp'
  let ?pre = "compE2 e @ [Goto (int (length (compE2 e2)) + 2), Store V]"
  from exec have exec': "exec_meth_d (compP2 P) (?pre @ compE2 e2)
    (stack_xlift (length STK) (compxE2 e 0 0) @ shift (length ?pre) (stack_xlift (length STK) (compxE2 e2 0 0))) t
    h (stk @ STK, loc, length ?pre + pc, xcp) ta h' (stk', loc', pc', xcp')"
  proof(cases)
    case (exec_catch xcp'' d)
    let ?stk = "stk @ STK" and ?PC = "Suc (Suc (length (compE2 e) + pc))"
    note s = stk' = Addr xcp'' # drop (length ?stk - d) ?stk
      ta = ε h' = h xcp' = None xcp = xcp'' loc' = loc
    from match_ex_table (compP2 P) (cname_of h xcp'') ?PC (stack_xlift (length STK) (compxE2 (try e catch(C' V) e2) 0 0)) = (pc', d) d  length ?stk
    show ?thesis unfolding s
      by -(rule exec_meth.exec_catch, simp_all add: shift_compxE2 stack_xlift_compxE2, simp add: match_ex_table_append add: matches_ex_entry_def)
  qed(auto intro: exec_meth.intros simp add: shift_compxE2 stack_xlift_compxE2)
  hence "?exec e2 stk STK loc pc xcp stk' loc' (pc' - length ?pre) xcp'"
    by(rule exec_meth_drop_xt)(auto simp add: stack_xlift_compxE2)
  from IH[OF this] obtain stk'' where stk': "stk' = stk'' @ STK"
    and exec'': "exec_meth_d (compP2 P) (compE2 e2) (compxE2 e2 0 0) t h (stk, loc, pc, xcp) ta h' (stk'', loc', pc' - length ?pre, xcp')" by auto
  from exec'' have "exec_meth_d (compP2 P) (?pre @ compE2 e2) (compxE2 e 0 0 @ shift (length ?pre) (compxE2 e2 0 0)) t h (stk, loc, length ?pre + pc, xcp) ta h' (stk'', loc', length ?pre + (pc' - length ?pre), xcp')"
    by(rule append_exec_meth_xt) auto
  hence "exec_meth_d (compP2 P) (?pre @ compE2 e2) (compxE2 e 0 0 @ shift (length ?pre) (compxE2 e2 0 0) @ [(0, length (compE2 e), C', Suc (length (compE2 e)), 0)]) t h (stk, loc, length ?pre + pc, xcp) ta h' (stk'', loc', length ?pre + (pc' - length ?pre), xcp')"
    by(rule exec_meth.cases)(auto intro: exec_meth.intros simp add: match_ex_table_append_not_pcs)
  moreover from exec' have "pc'  length ?pre"
    by(rule exec_meth_drop_xt_pc)(auto simp add: stack_xlift_compxE2)
  moreover hence "(Suc (Suc (pc' - Suc (Suc 0)))) = pc'" by simp
  ultimately show ?case using stk' by(auto simp add: shift_compxE2 eval_nat_numeral)
next
  case (bisim1TryFail e n a xs stk loc pc C' C'' e2 V)
  note bisim = P,e,h  (Throw a, xs)  (stk, loc, pc, a)
  note exec = ?exec (try e catch(C'' V) e2) stk STK loc pc a stk' loc' pc' xcp'
  note a = typeof_addr h a = Class_type C' ¬ P  C' * C''
  from bisim have "match_ex_table (compP2 P) (cname_of h a) (0 + pc) (compxE2 e 0 0) = None"
    unfolding compP2_def by(rule bisim1_xcp_Some_not_caught)
  moreover from bisim have "pc < length (compE2 e)" by(auto dest: bisim1_ThrowD)
  ultimately have False using exec a
    apply(auto elim!: exec_meth.cases simp add: outside_pcs_compxE2_not_matches_entry outside_pcs_not_matches_entry split: if_split_asm)
    apply(auto simp add: compP2_def match_ex_entry match_ex_table_append_not_pcs cname_of_def split: if_split_asm)
    done
  thus ?case ..
next
  case (bisim1TryCatchThrow e2 n a xs stk loc pc e C' V)
  note bisim = P,e2,h  (Throw a, xs)  (stk, loc, pc, a)
  note IH = stk' loc' pc' xcp' STK. ?exec e2 stk STK loc pc a stk' loc' pc' xcp'
              ?concl e2 stk STK loc pc a stk' loc' pc' xcp'
  note exec = ?exec (try e catch(C' V) e2) stk STK loc (Suc (Suc (length (compE2 e) + pc))) a stk' loc' pc' xcp'
  from bisim have pc: "pc < length (compE2 e2)" by(auto dest: bisim1_ThrowD)
  let ?pre = "compE2 e @ [Goto (int (length (compE2 e2)) + 2), Store V]"
  from exec have exec': "exec_meth_d (compP2 P) (?pre @ compE2 e2) (stack_xlift (length STK) (compxE2 e 0 0) @
    shift (length ?pre) (stack_xlift (length STK)  (compxE2 e2 0 0))) t
    h (stk @ STK, loc, length ?pre + pc, a) ta h' (stk', loc', pc', xcp')"
  proof(cases)
    case (exec_catch d)
    let ?stk = "stk @ STK" and ?PC = "Suc (Suc (length (compE2 e) + pc))"
    note s = stk' = Addr a # drop (length ?stk - d) ?stk loc' = loc
      ta = ε h' = h xcp' = None
    from match_ex_table (compP2 P) (cname_of h a) ?PC (stack_xlift (length STK) (compxE2 (try e catch(C' V) e2) 0 0)) = (pc', d) d  length ?stk
    show ?thesis unfolding s
      by -(rule exec_meth.exec_catch, simp_all add: shift_compxE2 stack_xlift_compxE2, simp add: match_ex_table_append add: matches_ex_entry_def)
  qed
  hence "?exec e2 stk STK loc pc a stk' loc' (pc' - length ?pre) xcp'"
    by(rule exec_meth_drop_xt)(auto simp add: stack_xlift_compxE2)
  from IH[OF this] obtain stk'' where stk': "stk' = stk'' @ STK"
    and exec'': "exec_meth_d (compP2 P) (compE2 e2) (compxE2 e2 0 0) t h (stk, loc, pc, a) ta h' (stk'', loc', pc' - length ?pre, xcp')" by auto
  from exec'' have "exec_meth_d (compP2 P) (?pre @ compE2 e2) (compxE2 e 0 0 @ shift (length ?pre) (compxE2 e2 0 0)) t h (stk, loc, length ?pre + pc, a) ta h' (stk'', loc', length ?pre + (pc' - length ?pre), xcp')"
    by(rule append_exec_meth_xt) auto
  hence "exec_meth_d (compP2 P) (?pre @ compE2 e2) (compxE2 e 0 0 @ shift (length ?pre) (compxE2 e2 0 0) @ [(0, length (compE2 e), C', Suc (length (compE2 e)), 0)]) t h (stk, loc, length ?pre + pc, a) ta h' (stk'', loc', length ?pre + (pc' - length ?pre), xcp')"
    by(rule exec_meth.cases)(auto intro!: exec_meth.intros simp add: match_ex_table_append_not_pcs)
  moreover from exec' have "pc'  length ?pre"
    by(rule exec_meth_drop_xt_pc)(auto simp add: stack_xlift_compxE2)
  moreover hence "(Suc (Suc (pc' - Suc (Suc 0)))) = pc'" by simp
  ultimately show ?case using stk' by(auto simp add: shift_compxE2 eval_nat_numeral)
next
  case bisims1Nil thus ?case by(auto elim: exec_meth.cases)
next
  case (bisims1List1 e n e' xs stk loc pc xcp es)
  note bisim1 = P,e,h  (e', xs )  (stk, loc, pc, xcp)
  note IH1 = stk' loc' pc' xcp' STK. ?exec e stk STK loc pc xcp stk' loc' pc' xcp'
               ?concl e stk STK loc pc xcp stk' loc' pc' xcp'
  note IH2 = xs stk' loc' pc' xcp' STK. ?execs es [] STK xs 0 None stk' loc' pc' xcp'
              ?concls es [] STK xs 0 None stk' loc' pc' xcp'
  note exec = ?execs (e # es) stk STK loc pc xcp stk' loc' pc' xcp'
  from bisim1 have pc: "pc  length (compE2 e)" by(rule bisim1_pc_length_compE2)
  show ?case
  proof(cases "pc < length (compE2 e)")
    case True
    with exec have "?exec e stk STK loc pc xcp stk' loc' pc' xcp'"
      by(simp add: compxEs2_size_convs)(erule exec_meth_take_xt)
    from IH1[OF this] show ?thesis by auto
  next
    case False
    with pc have pc: "pc = length (compE2 e)" by simp
    with bisim1 obtain v where s: "stk = [v]" "xcp = None" by(auto dest: bisim1_pc_length_compE2D)
    with exec pc have exec': "exec_meth_d (compP2 P) (compE2 e @ compEs2 es)
      (stack_xlift (length STK) (compxE2 e 0 0) @ shift (length (compE2 e)) (stack_xlift (length (v # STK)) (compxEs2 es 0 0))) t
      h ([] @ v # STK, loc, length (compE2 e) + 0, None) ta h' (stk', loc', pc', xcp')"
      by(simp add: compxEs2_size_convs compxEs2_stack_xlift_convs)
    hence "?execs es [] (v # STK) loc 0 None stk' loc' (pc' - length (compE2 e)) xcp'"
      by(rule exec_meth_drop_xt)(auto simp add: stack_xlift_compxE2)
    from IH2[OF this] obtain stk'' where stk': "stk' = stk'' @ v # STK"
      and exec'': "exec_meth_d (compP2 P) (compEs2 es) (compxEs2 es 0 0) t h ([], loc, 0, None) ta h' (stk'', loc', pc' - length (compE2 e), xcp')" by auto
    from exec'' have "exec_meth_d (compP2 P) (compEs2 es) (stack_xlift (length [v]) (compxEs2 es 0 0)) t h ([] @ [v], loc, 0, None) ta h' (stk'' @ [v], loc', pc' - length (compE2 e), xcp')"
      by(rule exec_meth_stk_offer)
    hence "exec_meth_d (compP2 P) (compE2 e @ compEs2 es) (compxE2 e 0 0 @ shift (length (compE2 e)) (stack_xlift (length [v]) (compxEs2 es 0 0))) t h ([] @ [v], loc, length (compE2 e) + 0, None) ta h' (stk'' @ [v], loc', length (compE2 e) + (pc' - length (compE2 e)), xcp')"
      by(rule append_exec_meth_xt) auto
    moreover from exec' have "pc'  length (compE2 e)"
      by(rule exec_meth_drop_xt_pc)(auto simp add: stack_xlift_compxE2)
    ultimately show ?thesis using s pc stk' by(auto simp add: shift_compxEs2 stack_xlift_compxEs2)
  qed
next
  case (bisims1List2 es n es' xs stk loc pc xcp e v)
  note bisim = P,es,h  (es',xs) [↔] (stk,loc,pc,xcp)
  note IH = stk' loc' pc' xcp' STK. ?execs es stk STK loc pc xcp stk' loc' pc' xcp'
              ?concls es stk STK loc pc xcp stk' loc' pc' xcp'
  note exec = ?execs (e # es) (stk @ [v]) STK loc (length (compE2 e) + pc) xcp stk' loc' pc' xcp'
  from exec have exec': "exec_meth_d (compP2 P) (compE2 e @ compEs2 es)
     (stack_xlift (length STK) (compxE2 e 0 0) @ shift (length (compE2 e)) (stack_xlift (length (v # STK)) (compxEs2 es 0 0))) t
     h (stk @ v # STK, loc, length (compE2 e) + pc, xcp) ta h' (stk', loc', pc', xcp')"
    by(simp add: compxEs2_size_convs compxEs2_stack_xlift_convs)
  hence "?execs es stk (v # STK) loc pc xcp stk' loc' (pc' - length (compE2 e)) xcp'"
    by(rule exec_meth_drop_xt)(auto simp add: stack_xlift_compxE2)
  from IH[OF this] obtain stk'' where stk': "stk' = stk'' @ v # STK"
    and exec'': "exec_meth_d (compP2 P) (compEs2 es) (compxEs2 es 0 0) t h (stk, loc, pc, xcp) ta h' (stk'', loc', pc' - length (compE2 e), xcp')" by auto
  from exec'' have "exec_meth_d (compP2 P) (compEs2 es) (stack_xlift (length [v]) (compxEs2 es 0 0)) t h (stk @ [v], loc, pc, xcp) ta h' (stk'' @ [v], loc', pc' - length (compE2 e), xcp')"
    by(rule exec_meth_stk_offer)
  hence "exec_meth_d (compP2 P) (compE2 e @ compEs2 es) (compxE2 e 0 0 @ shift (length (compE2 e)) (stack_xlift (length [v]) (compxEs2 es 0 0))) t h (stk @ [v], loc, length (compE2 e) + pc, xcp) ta h' (stk'' @ [v], loc', length (compE2 e) + (pc' - length (compE2 e)), xcp')"
    by(rule append_exec_meth_xt) auto
  moreover from exec' have "pc'  length (compE2 e)"
    by(rule exec_meth_drop_xt_pc)(auto simp add: stack_xlift_compxE2)
  ultimately show ?case using stk' by(auto simp add: shift_compxEs2 stack_xlift_compxEs2)
next
  case (bisim1Sync12 e1 n e2 V a xs v v')
  note exec = ?exec (sync⇘V(e1) e2) [v, v'] STK xs (4 + length (compE2 e1) + length (compE2 e2)) a stk' loc' pc' xcp'
  thus ?case by(auto elim!: exec_meth.cases split: if_split_asm simp add: match_ex_table_append_not_pcs)(simp add: matches_ex_entry_def)
next
  case (bisim1Sync14 e1 n e2 V a xs v a')
  note exec = ?exec (sync⇘V(e1) e2) [v, Addr a'] STK xs (7 + length (compE2 e1) + length (compE2 e2)) a stk' loc' pc' xcp'
  thus ?case by(auto elim!: exec_meth.cases split: if_split_asm simp add: match_ex_table_append_not_pcs)(simp add: matches_ex_entry_def)
qed

lemma shows bisim1_callD:
  " P,e,h  (e', xs)  (stk, loc, pc, xcp); call1 e' = (a, M, vs);
     compE2 e ! pc = Invoke M' n0 
     M = M'"

  and bisims1_callD:
  " P,es,h  (es',xs) [↔] (stk,loc,pc, xcp); calls1 es' = (a, M, vs);
     compEs2 es ! pc = Invoke M' n0 
     M = M'"
proof(induct e "n :: nat" e' xs stk loc pc xcp and es "n :: nat" es' xs stk loc pc xcp
    rule: bisim1_bisims1_inducts_split)
  case bisim1AAss1 thus ?case
    apply(simp (no_asm_use) split: if_split_asm add: is_val_iff)
    apply(fastforce dest: bisim_Val_pc_not_Invoke)
    apply(fastforce dest: bisim_Val_pc_not_Invoke)
    apply(fastforce dest: bisim_Val_pc_not_Invoke bisim1_pc_length_compE2)+
    done
next
  case bisim1Call1 thus ?case
    apply(clarsimp split: if_split_asm simp add: is_vals_conv)
    apply(drule bisim_Val_pc_not_Invoke, simp, fastforce)
    apply(drule bisim_Val_pc_not_Invoke, simp, fastforce)
    apply(drule bisim1_pc_length_compE2, clarsimp simp add: neq_Nil_conv)
    apply(drule bisim1_pc_length_compE2, simp)
    apply(drule bisim1_pc_length_compE2, simp)
    apply(drule bisim1_pc_length_compE2, simp)
    apply(drule bisim1_call_pcD, simp, simp)
    apply(drule bisim1_call_pcD, simp, simp)
    done
next
  case bisim1CallParams thus ?case
    apply(clarsimp split: if_split_asm simp add: is_vals_conv)
    apply(drule bisims_Val_pc_not_Invoke, simp, fastforce)
    apply(drule bisims1_pc_length_compEs2, simp)
    apply(drule bisims1_calls_pcD, simp, simp)
    done
qed(fastforce split: if_split_asm dest: bisim1_pc_length_compE2 bisims1_pc_length_compEs2 bisim1_call_pcD bisims1_calls_pcD bisim1_call_xcpNone bisims1_calls_xcpNone bisim_Val_pc_not_Invoke bisims_Val_pc_not_Invoke)+

lemma bisim1_xcpD: "P,e,h  (e', xs)  (stk, loc, pc, a)  pc < length (compE2 e)"
  and bisims1_xcpD: "P,es,h  (es', xs) [↔] (stk, loc, pc, a)  pc < length (compEs2 es)"
by(induct "(e', xs)" "(stk, loc, pc, a :: 'addr)" and "(es', xs)" "(stk, loc, pc, a :: 'addr)"
  arbitrary: e' xs stk loc pc and es' xs stk loc pc rule: bisim1_bisims1.inducts)
  simp_all

lemma bisim1_match_Some_stk_length:
  " P,E,h  (e, xs)  (stk, loc, pc, a);
     match_ex_table (compP2 P) (cname_of h a) pc (compxE2 E 0 0) = (pc', d) 
   d  length stk"

  and bisims1_match_Some_stk_length:
  " P,Es,h  (es, xs) [↔] (stk, loc, pc, a);
     match_ex_table (compP2 P) (cname_of h a) pc (compxEs2 Es 0 0) = (pc', d) 
   d  length stk"
proof(induct "(e, xs)" "(stk, loc, pc, a :: 'addr)" and "(es, xs)" "(stk, loc, pc, a :: 'addr)"
  arbitrary: pc' d e xs stk loc pc and pc' d es xs stk loc pc rule: bisim1_bisims1.inducts)
  case bisim1Call1 thus ?case
    by(fastforce dest: bisim1_xcpD simp add: match_ex_table_append match_ex_table_not_pcs_None)
next
  case bisim1CallThrowObj thus ?case
    by(fastforce dest: bisim1_xcpD simp add: match_ex_table_append match_ex_table_not_pcs_None)
next
  case bisim1Sync4 thus ?case
    apply(clarsimp simp add: match_ex_table_not_pcs_None match_ex_table_append matches_ex_entry_def split: if_split_asm)
    apply(fastforce simp add: match_ex_table_compxE2_shift_conv dest: bisim1_xcpD)
    done
next
  case bisim1Try thus ?case
    by(fastforce simp add: match_ex_table_append matches_ex_entry_def match_ex_table_not_pcs_None dest: bisim1_xcpD split: if_split_asm)
next
  case bisim1TryCatch2 thus ?case
    apply(clarsimp simp add: match_ex_table_not_pcs_None match_ex_table_append matches_ex_entry_def split: if_split_asm)
    apply(fastforce simp add: match_ex_table_compxE2_shift_conv dest: bisim1_xcpD)
    done
next
  case bisim1TryFail thus ?case
    by(fastforce simp add: match_ex_table_append matches_ex_entry_def match_ex_table_not_pcs_None dest: bisim1_xcpD split: if_split_asm)
next
  case bisim1TryCatchThrow thus ?case
    apply(clarsimp simp add: match_ex_table_not_pcs_None match_ex_table_append matches_ex_entry_def split: if_split_asm)
    apply(fastforce simp add: match_ex_table_compxE2_shift_conv dest: bisim1_xcpD)
    done
next
  case bisims1List1 thus ?case
    by(fastforce simp add: match_ex_table_append split: if_split_asm dest: bisim1_xcpD match_ex_table_pcsD)
qed(fastforce simp add: match_ex_table_not_pcs_None match_ex_table_append match_ex_table_compxE2_shift_conv match_ex_table_compxEs2_shift_conv match_ex_table_compxE2_stack_conv match_ex_table_compxEs2_stack_conv matches_ex_entry_def dest: bisim1_xcpD)+

end

locale J1_JVM_heap_conf_base =
  J1_JVM_heap_base
    addr2thread_id thread_id2addr
    spurious_wakeups
    empty_heap allocate typeof_addr heap_read heap_write 
  +
  J1_heap_conf_base
    addr2thread_id thread_id2addr
    spurious_wakeups
    empty_heap allocate typeof_addr heap_read heap_write 
    hconf P 
  +
  JVM_heap_conf_base
    addr2thread_id thread_id2addr
    spurious_wakeups
    empty_heap allocate typeof_addr heap_read heap_write 
    hconf "compP2 P"
  for addr2thread_id :: "('addr :: addr)  'thread_id"
  and thread_id2addr :: "'thread_id  'addr"
  and spurious_wakeups :: bool
  and empty_heap :: "'heap"
  and allocate :: "'heap  htype  ('heap × 'addr) set"
  and typeof_addr :: "'heap  'addr  htype"
  and heap_read :: "'heap  'addr  addr_loc  'addr val  bool"
  and heap_write :: "'heap  'addr  addr_loc  'addr val  'heap  bool"
  and hconf :: "'heap  bool"
  and P :: "'addr J1_prog"
begin

inductive bisim1_list1 :: 
  "'thread_id  'heap  'addr expr1 × 'addr locals1  ('addr expr1 × 'addr locals1) list
   'addr option  'addr frame list  bool"
for t :: 'thread_id and h :: 'heap
where
  bl1_Normal:
  " compTP P  t:(xcp, h, (stk, loc, C, M, pc) # frs) ;
     P  C sees M : TsT = body in D;
     P,blocks1 0 (Class D#Ts) body, h  (e, xs)  (stk, loc, pc, xcp); max_vars e  length xs;
     list_all2 (bisim1_fr P h) exs frs 
   bisim1_list1 t h (e, xs) exs xcp ((stk, loc, C, M, pc) # frs)"

| bl1_finalVal:
  " hconf h; preallocated h   bisim1_list1 t h (Val v, xs) [] None []"

| bl1_finalThrow:
  " hconf h; preallocated h   bisim1_list1 t h (Throw a, xs) [] a []"

fun wbisim1 :: 
  "'thread_id
   ((('addr expr1 × 'addr locals1) × ('addr expr1 × 'addr locals1) list) × 'heap, 
      ('addr option × 'addr frame list) × 'heap) bisim"
where "wbisim1 t ((ex, exs), h) ((xcp, frs), h')  h = h'  bisim1_list1 t h ex exs xcp frs"

lemma new_thread_conf_compTP:
  assumes hconf: "hconf h" "preallocated h"
  and ha: "typeof_addr h a = Class_type C"
  and sub: "typeof_addr h (thread_id2addr t) = Class_type C'" "P  C' * Thread"
  and sees: "P  C sees M: []T = meth in D"
  shows "compTP P  t:(None, h, [([], Addr a # replicate (max_vars meth) undefined_value, D, M, 0)]) "
proof -
  from ha sees_method_decl_above[OF sees]
  have "P,h  Addr a :≤ Class D" by(simp add: conf_def)
  moreover
  hence "compP2 P,h  Addr a :≤ Class D" by(simp add: compP2_def)
  hence "compP2 P,h  Addr a # replicate (max_vars meth) undefined_value [:≤] map (λi. if i = 0 then OK ([Class D] ! i) else Err) [0..<max_vars meth] @ [Err]"
    by -(rule list_all2_all_nthI, simp_all)
  hence "conf_f (compP2 P) h ([], map (λi. if i = 0 then OK ([Class D] ! i) else Err) [0..<max_vars meth] @ [Err])
                (compE2 meth @ [Return]) ([], Addr a # replicate (max_vars meth) undefined_value, D, M, 0)"
    unfolding conf_f_def2 by(simp add: compP2_def)
  ultimately have "conf_f (compP2 P) h ([], TC0.tyl (Suc (max_vars meth)) [Class D] {0}) (compE2 meth @ [Return])
                       ([], Addr a # replicate (max_vars meth) undefined_value, D, M, 0)"
    by(simp add: TC0.tyl_def conf_f_def2 compP2_def)
  with hconf ha sub sees_method_compP[OF sees, where f="λC M Ts T. compMb2"] sees_method_idemp[OF sees]
  show ?thesis
    by(auto simp add: TC0.tyi'_def correct_state_def compTP_def tconf_def)(fastforce simp add: compP2_def compMb2_def tconf_def intro: sees_method_idemp)+
qed

lemma ta_bisim12_extTA2J1_extTA2JVM:
  assumes nt: "n T C M a h.  n < length tat; tat ! n = NewThread T (C, M, a) h  
            typeof_addr h a = Class_type C  (C'. typeof_addr h (thread_id2addr T) = Class_type C'  P  C' * Thread) 
              (T meth D. P  C sees M:[]T =meth in D)  hconf h  preallocated h"
  shows "ta_bisim wbisim1 (extTA2J1 P ta) (extTA2JVM (compP2 P) ta)"
proof -
  { fix n t C M a m
    assume "n < length tat" and "tat ! n = NewThread t (C, M, a) m"
    from nt[OF this] obtain T meth D C'
      where ma: "typeof_addr m a = Class_type C"
      and sees: "P  C sees M: []T = meth in D"
      and sub: "typeof_addr m (thread_id2addr t) = Class_type C'" "P  C' * Thread"
      and mconf: "hconf m" "preallocated m" by fastforce
    from sees_method_compP[OF sees, where f="λC M Ts T. compMb2"]
    have sees': "compP2 P  C sees M: []T = (max_stack meth, max_vars meth, compE2 meth @ [Return], compxE2 meth 0 0) in D"
      by(simp add: compMb2_def compP2_def)
    have "bisim1_list1 t m ({0:Class D=None; meth}, Addr a # replicate (max_vars meth) undefined_value) ([]) None [([], Addr a # replicate (max_vars meth) undefined_value, D, M, 0)]"
    proof
      from mconf ma sub sees
      show "compTP P  t:(None, m, [([], Addr a # replicate (max_vars meth) undefined_value, D, M, 0)]) "
        by(rule new_thread_conf_compTP)

      from sees show "P  D sees M: []T = meth in D" by(rule sees_method_idemp)
      show "list_all2 (bisim1_fr P m) [] []" by simp
      show "P,blocks1 0 [Class D] meth,m  ({0:Class D=None; meth}, Addr a # replicate (max_vars meth) undefined_value) 
                                                ([], Addr a # replicate (max_vars meth) undefined_value, 0, None)"
        by simp(rule bisim1_refl)
    qed simp
    with sees sees' have "bisim1_list1 t m ({0:Class (fst (method P C M))=None; the (snd (snd (snd (method P C M))))}, Addr a # replicate (max_vars (the (snd (snd (snd (method P C M)))))) undefined_value) [] None [([], Addr a # replicate (fst (snd (the (snd (snd (snd (method (compP2 P) C M))))))) undefined_value, fst (method (compP2 P) C M), M, 0)]" by simp }
  thus ?thesis
    apply(auto simp add: ta_bisim_def intro!: list_all2_all_nthI)
    apply(case_tac "tat ! n", auto simp add: extNTA2JVM_def)
    done
qed

end

definition no_call2 :: "'addr expr1  pc  bool"
where "no_call2 e pc  (pc  length (compE2 e))  (pc < length (compE2 e)  (M n. compE2 e ! pc  Invoke M n))"

definition no_calls2 :: "'addr expr1 list  pc  bool"
where "no_calls2 es pc  (pc  length (compEs2 es))  (pc < length (compEs2 es)  (M n. compEs2 es ! pc  Invoke M n))"

locale J1_JVM_conf_read =
  J1_JVM_heap_conf_base
    addr2thread_id thread_id2addr
    spurious_wakeups
    empty_heap allocate typeof_addr heap_read heap_write
    hconf P 
  +
  JVM_conf_read
    addr2thread_id thread_id2addr
    spurious_wakeups
    empty_heap allocate typeof_addr heap_read heap_write 
    hconf "compP2 P"
  for addr2thread_id :: "('addr :: addr)  'thread_id"
  and thread_id2addr :: "'thread_id  'addr"
  and spurious_wakeups :: bool
  and empty_heap :: "'heap"
  and allocate :: "'heap  htype  ('heap × 'addr) set"
  and typeof_addr :: "'heap  'addr  htype"
  and heap_read :: "'heap  'addr  addr_loc  'addr val  bool"
  and heap_write :: "'heap  'addr  addr_loc  'addr val  'heap  bool"
  and hconf :: "'heap  bool"
  and P :: "'addr J1_prog"

locale J1_JVM_heap_conf =
  J1_JVM_heap_conf_base
    addr2thread_id thread_id2addr
    spurious_wakeups
    empty_heap allocate typeof_addr heap_read heap_write 
    hconf P 
  +
  JVM_heap_conf
    addr2thread_id thread_id2addr
    spurious_wakeups
    empty_heap allocate typeof_addr heap_read heap_write 
    hconf "compP2 P"
  for addr2thread_id :: "('addr :: addr)  'thread_id"
  and thread_id2addr :: "'thread_id  'addr"
  and spurious_wakeups :: bool
  and empty_heap :: "'heap"
  and allocate :: "'heap  htype  ('heap × 'addr) set"
  and typeof_addr :: "'heap  'addr  htype"
  and heap_read :: "'heap  'addr  addr_loc  'addr val  bool"
  and heap_write :: "'heap  'addr  addr_loc  'addr val  'heap  bool"
  and hconf :: "'heap  bool"
  and P :: "'addr J1_prog"
begin

lemma red_external_ta_bisim21: 
  " wf_prog wf_md P; P,t  aM(vs), h -ta→ext va, h'; hconf h'; preallocated h' 
   ta_bisim wbisim1 (extTA2J1 P ta) (extTA2JVM (compP2 P) ta)"
apply(rule ta_bisim12_extTA2J1_extTA2JVM)
apply(frule (1) red_external_new_thread_sees)
 apply(fastforce simp add: in_set_conv_nth)
apply(frule red_ext_new_thread_heap)
 apply(fastforce simp add: in_set_conv_nth)
apply(frule red_external_new_thread_exists_thread_object[unfolded compP2_def, simplified])
 apply(fastforce simp add: in_set_conv_nth)
apply simp
done

lemma ta_bisim_red_extTA2J1_extTA2JVM:
  assumes wf: "wf_prog wf_md P"
  and red: "uf,P,t' ⊢1 e, s -ta e', s'"
  and hconf: "hconf (hp s')" "preallocated (hp s')"
  shows "ta_bisim wbisim1 (extTA2J1 P ta) (extTA2JVM (compP2 P) ta)"
proof -
  { fix n t C M a H
    assume len: "n < length tat" and tan: "tat ! n = NewThread t (C, M, a) H"
    hence nt: "NewThread t (C, M, a) H  set tat" unfolding set_conv_nth by(auto intro!: exI)
    from red1_new_threadD[OF red nt] obtain ad M' vs va T C' Ts' Tr' D'
      where rede: "P,t'  adM'(vs),hp s -ta→ext va,hp s'"
      and ad: "typeof_addr (hp s) ad = T" by blast
    from red_ext_new_thread_heap[OF rede nt] have [simp]: "hp s' = H" by simp
    from red_external_new_thread_sees[OF wf rede nt] 
    obtain T body D where Ha: "typeof_addr H a = Class_type C"
      and sees: "P  C sees M:[]T=body in D" by auto
    have sees': "compP2 P  C sees M:[]T=(max_stack body, max_vars body, compE2 body @ [Return], compxE2 body 0 0) in D"
      using sees unfolding compP2_def compMb2_def Let_def by(auto dest: sees_method_compP)
    from red_external_new_thread_exists_thread_object[unfolded compP2_def, simplified, OF rede nt] hconf Ha sees
    have "compTP P  t:(None, H, [([], Addr a # replicate (max_vars body) undefined_value, D, M, 0)]) "
      by(auto intro: new_thread_conf_compTP)
    hence "bisim1_list1 t H ({0:Class D=None; body}, Addr a # replicate (max_vars body) undefined_value) [] None [([], Addr a # replicate (max_vars body) undefined_value, D, M, 0)]"
    proof
      from sees show "P  D sees M:[]T=body in D" by(rule sees_method_idemp)

      show "P,blocks1 0 [Class D] body,H  ({0:Class D=None; body}, Addr a # replicate (max_vars body) undefined_value) 
                                                ([], Addr a # replicate (max_vars body) undefined_value, 0, None)"
        by(auto intro: bisim1_refl)
    qed simp_all
    hence "bisim1_list1 t H ({0:Class (fst (method P C M))=None; the (snd (snd (snd (method P C M))))},
                               Addr a # replicate (max_vars (the (snd (snd (snd (method P C M)))))) undefined_value)
                              []
                              None [([], Addr a # replicate (fst (snd (the (snd (snd (snd (method (compP2 P) C M))))))) undefined_value,
                                    fst (method (compP2 P) C M), M, 0)]"
      using sees sees' by simp }
  thus ?thesis
    apply(auto simp add: ta_bisim_def intro!: list_all2_all_nthI)
    apply(case_tac "tat ! n")
    apply(auto simp add: extNTA2JVM_def extNTA2J1_def)
    done
qed

end

sublocale J1_JVM_conf_read < heap_conf?: J1_JVM_heap_conf
by(unfold_locales)

sublocale J1_JVM_conf_read < heap?: J1_heap
apply(rule J1_heap.intro)
apply(subst compP_heap[symmetric, where f="λ_ _ _ _. compMb2", folded compP2_def])
apply(unfold_locales)
done

end