header {* \isaheader{Correctness of Stage 2} *}
theory Correctness2
imports "~~/src/HOL/Library/Sublist" Compiler2
begin
hide_const (open) Throw
subsection{* Instruction sequences *}
text{* How to select individual instructions and subsequences of
instructions from a program given the class, method and program
counter. *}
definition before :: "jvm_prog => cname => mname => nat => instr list => bool"
   ("(_,_,_,_/ \<rhd> _)" [51,0,0,0,51] 50) where
 "P,C,M,pc \<rhd> is <-> prefixeq is (drop pc (instrs_of P C M))"
definition at :: "jvm_prog => cname => mname => nat => instr => bool"
   ("(_,_,_,_/ \<triangleright> _)" [51,0,0,0,51] 50) where
 "P,C,M,pc \<triangleright> i <-> (∃is. drop pc (instrs_of P C M) = i#is)"
lemma [simp]: "P,C,M,pc \<rhd> []"
by(simp add:before_def)
lemma [simp]: "P,C,M,pc \<rhd> (i#is) = (P,C,M,pc \<triangleright> i ∧ P,C,M,pc + 1 \<rhd> is)"
by(fastforce simp add:before_def at_def prefixeq_def drop_Suc drop_tl)
declare drop_drop[simp del]
lemma [simp]: "P,C,M,pc \<rhd> (is⇣1 @ is⇣2) = (P,C,M,pc \<rhd> is⇣1 ∧ P,C,M,pc + size is⇣1 \<rhd> is⇣2)"
apply(simp add:before_def prefixeq_def)
apply(subst add_commute)
apply(simp add: drop_drop[symmetric])
apply fastforce
done
declare drop_drop[simp]
lemma [simp]: "P,C,M,pc \<triangleright> i ==> instrs_of P C M ! pc = i"
by(clarsimp simp add:at_def prefix_def nth_via_drop)
lemma beforeM:
  "P \<turnstile> C sees M: Ts->T = body in D ==>
  compP⇣2 P,D,M,0 \<rhd> compE⇣2 body @ [Return]"
apply(drule sees_method_idemp)
apply(simp add:before_def compP⇣2_def compMb⇣2_def)
done
text{* This lemma executes a single instruction by rewriting: *}
lemma [simp]:
  "P,C,M,pc \<triangleright> instr ==>
  (P \<turnstile> (None, h, (vs,ls,C,M,pc) # frs) -jvm-> σ') =
  ((None, h, (vs,ls,C,M,pc) # frs) = σ' ∨
   (∃σ. exec(P,(None, h, (vs,ls,C,M,pc) # frs)) = Some σ ∧ P \<turnstile> σ -jvm-> σ'))"
apply(simp only: exec_all_def)
apply(blast intro: converse_rtranclE converse_rtrancl_into_rtrancl)
done
section{* Exception tables *}
definition pcs :: "ex_table => nat set"
where
  "pcs xt  ≡  \<Union>(f,t,C,h,d) ∈ set xt. {f ..< t}"
lemma pcs_subset:
shows "!!pc d. pcs(compxE⇣2 e pc d) ⊆ {pc..<pc+size(compE⇣2 e)}"
and "!!pc d. pcs(compxEs⇣2 es pc d) ⊆ {pc..<pc+size(compEs⇣2 es)}"
apply(induct e and es)
apply (simp_all add:pcs_def)
apply (fastforce split:bop.splits)+
done
lemma [simp]: "pcs [] = {}"
by(simp add:pcs_def)
lemma [simp]: "pcs (x#xt) = {fst x ..< fst(snd x)} ∪ pcs xt"
by(auto simp add: pcs_def)
lemma [simp]: "pcs(xt⇣1 @ xt⇣2) = pcs xt⇣1 ∪ pcs xt⇣2"
by(simp add:pcs_def)
lemma [simp]: "pc < pc⇣0 ∨ pc⇣0+size(compE⇣2 e) ≤ pc ==> pc ∉ pcs(compxE⇣2 e pc⇣0 d)"
using pcs_subset by fastforce
lemma [simp]: "pc < pc⇣0 ∨ pc⇣0+size(compEs⇣2 es) ≤ pc ==> pc ∉ pcs(compxEs⇣2 es pc⇣0 d)"
using pcs_subset by fastforce
lemma [simp]: "pc⇣1 + size(compE⇣2 e⇣1) ≤ pc⇣2 ==> pcs(compxE⇣2 e⇣1 pc⇣1 d⇣1) ∩ pcs(compxE⇣2 e⇣2 pc⇣2 d⇣2) = {}"
using pcs_subset by fastforce
lemma [simp]: "pc⇣1 + size(compE⇣2 e) ≤ pc⇣2 ==> pcs(compxE⇣2 e pc⇣1 d⇣1) ∩ pcs(compxEs⇣2 es pc⇣2 d⇣2) = {}"
using pcs_subset by fastforce
lemma [simp]:
 "pc ∉ pcs xt⇣0 ==> match_ex_table P C pc (xt⇣0 @ xt⇣1) = match_ex_table P C pc xt⇣1"
by (induct xt⇣0) (auto simp: matches_ex_entry_def)
lemma [simp]: "[| x ∈ set xt; pc ∉ pcs xt |] ==> ¬ matches_ex_entry P D pc x"
by(auto simp:matches_ex_entry_def pcs_def)
lemma [simp]:
assumes xe: "xe ∈ set(compxE⇣2 e pc d)" and outside: "pc' < pc ∨ pc+size(compE⇣2 e) ≤ pc'"
shows "¬ matches_ex_entry P C pc' xe"
proof
  assume "matches_ex_entry P C pc' xe"
  with xe have "pc' ∈ pcs(compxE⇣2 e pc d)"
    by(force simp add:matches_ex_entry_def pcs_def)
  with outside show False by simp
qed
lemma [simp]:
assumes xe: "xe ∈ set(compxEs⇣2 es pc d)" and outside: "pc' < pc ∨ pc+size(compEs⇣2 es) ≤ pc'"
shows "¬ matches_ex_entry P C pc' xe"
proof
  assume "matches_ex_entry P C pc' xe"
  with xe have "pc' ∈ pcs(compxEs⇣2 es pc d)"
    by(force simp add:matches_ex_entry_def pcs_def)
  with outside show False by simp
qed
lemma match_ex_table_app[simp]:
  "∀xte ∈ set xt⇣1. ¬ matches_ex_entry P D pc xte ==>
  match_ex_table P D pc (xt⇣1 @ xt) = match_ex_table P D pc xt"
by(induct xt⇣1) simp_all
lemma [simp]:
  "∀x ∈ set xtab. ¬ matches_ex_entry P C pc x ==>
  match_ex_table P C pc xtab = None"
using match_ex_table_app[where ?xt = "[]"] by fastforce
lemma match_ex_entry:
  "matches_ex_entry P C pc (start, end, catch_type, handler) =
  (start ≤ pc ∧ pc < end ∧  P \<turnstile> C \<preceq>⇧* catch_type)"
by(simp add:matches_ex_entry_def)
definition caught :: "jvm_prog => pc => heap => addr => ex_table => bool" where
  "caught P pc h a xt <->
  (∃entry ∈ set xt. matches_ex_entry P (cname_of h a) pc entry)"
definition beforex :: "jvm_prog => cname => mname => ex_table => nat set => nat => bool"
              ("(2_,/_,/_ \<rhd>/ _ /'/ _,/_)" [51,0,0,0,0,51] 50) where
  "P,C,M \<rhd> xt / I,d <->
  (∃xt⇣0 xt⇣1. ex_table_of P C M = xt⇣0 @ xt @ xt⇣1 ∧ pcs xt⇣0 ∩ I = {} ∧ pcs xt ⊆ I ∧
    (∀pc ∈ I. ∀C pc' d'. match_ex_table P C pc xt⇣1 = ⌊(pc',d')⌋ --> d' ≤ d))"
definition dummyx :: "jvm_prog => cname => mname => ex_table => nat set => nat => bool"  ("(2_,_,_ \<triangleright>/ _ '/_,_)" [51,0,0,0,0,51] 50) where
  "P,C,M \<triangleright> xt/I,d <-> P,C,M \<rhd> xt/I,d"
lemma beforexD1: "P,C,M \<rhd> xt / I,d ==> pcs xt ⊆ I"
by(auto simp add:beforex_def)
lemma beforex_mono: "[| P,C,M \<rhd> xt/I,d'; d' ≤ d |] ==> P,C,M \<rhd> xt/I,d"
by(fastforce simp:beforex_def)
lemma [simp]: "P,C,M \<rhd> xt/I,d ==> P,C,M \<rhd> xt/I,Suc d"
by(fastforce intro:beforex_mono)
lemma beforex_append[simp]:
  "pcs xt⇣1 ∩ pcs xt⇣2 = {} ==>
  P,C,M \<rhd> xt⇣1 @ xt⇣2/I,d =
  (P,C,M \<rhd> xt⇣1/I-pcs xt⇣2,d  ∧  P,C,M \<rhd> xt⇣2/I-pcs xt⇣1,d ∧ P,C,M \<triangleright> xt⇣1@xt⇣2/I,d)"
apply(rule iffI)
 prefer 2
 apply(simp add:dummyx_def)
apply(auto simp add: beforex_def dummyx_def)
 apply(rule_tac x = xt⇣0 in exI)
 apply auto
apply(rule_tac x = "xt⇣0@xt⇣1" in exI)
apply auto
done
lemma beforex_appendD1:
  "[| P,C,M \<rhd> xt⇣1 @ xt⇣2 @ [(f,t,D,h,d)] / I,d;
    pcs xt⇣1 ⊆ J; J ⊆ I; J ∩ pcs xt⇣2 = {} |]
  ==> P,C,M \<rhd> xt⇣1 / J,d"
apply(auto simp:beforex_def)
apply(rule exI,rule exI,rule conjI, rule refl)
apply(rule conjI, blast)
apply(auto)
apply(subgoal_tac "pc ∉ pcs xt⇣2")
 prefer 2 apply blast
apply (auto split:split_if_asm)
done
lemma beforex_appendD2:
  "[| P,C,M \<rhd> xt⇣1 @ xt⇣2 @ [(f,t,D,h,d)] / I,d;
    pcs xt⇣2 ⊆ J; J ⊆ I; J ∩ pcs xt⇣1 = {} |]
  ==> P,C,M \<rhd> xt⇣2 / J,d"
apply(auto simp:beforex_def)
apply(rule_tac x = "xt⇣0 @ xt⇣1" in exI)
apply fastforce
done
lemma beforexM:
  "P \<turnstile> C sees M: Ts->T = body in D ==>
  compP⇣2 P,D,M \<rhd> compxE⇣2 body 0 0/{..<size(compE⇣2 body)},0"
apply(drule sees_method_idemp)
apply(drule sees_method_compP[where f = compMb⇣2])
apply(simp add:beforex_def compP⇣2_def compMb⇣2_def)
apply(rule_tac x = "[]" in exI)
using pcs_subset apply fastforce
done
lemma match_ex_table_SomeD2:
 "[| match_ex_table P D pc (ex_table_of P C M) = ⌊(pc',d')⌋;
    P,C,M \<rhd> xt/I,d; ∀x ∈ set xt. ¬ matches_ex_entry P D pc x; pc ∈ I |]
 ==> d' ≤ d"
apply(auto simp:beforex_def)
apply(subgoal_tac "pc ∉ pcs xt⇣0")
apply auto
done
lemma match_ex_table_SomeD1:
  "[| match_ex_table P D pc (ex_table_of P C M) = ⌊(pc',d')⌋;
     P,C,M \<rhd> xt / I,d; pc ∈ I; pc ∉ pcs xt |] ==> d' ≤ d"
by(auto elim: match_ex_table_SomeD2)
subsection{* The correctness proof *}
declare nat_add_distrib[simp] caught_def[simp]
declare fun_upd_apply[simp del]
definition
  handle :: "jvm_prog => cname => mname => addr => heap => val list => val list => nat => frame list
                => jvm_state" where
  "handle P C M a h vs ls pc frs = find_handler P a h ((vs,ls,C,M,pc) # frs)"
lemma handle_Cons:
 "[| P,C,M \<rhd> xt/I,d; d ≤ size vs; pc ∈ I;
    ∀x ∈ set xt. ¬ matches_ex_entry P (cname_of h xa) pc x |] ==>
  handle P C M xa h (v # vs) ls pc frs = handle P C M xa h vs ls pc frs"
by(auto simp:handle_def Suc_diff_le dest: match_ex_table_SomeD2)
lemma handle_append:
 "[| P,C,M \<rhd> xt/I,d; d ≤ size vs; pc ∈ I; pc ∉ pcs xt |] ==>
  handle P C M xa h (ws @ vs) ls pc frs = handle P C M xa h vs ls pc frs"
apply(auto simp:handle_def)
apply(rename_tac pc' d')
apply(subgoal_tac "size ws ≤ length ws + length vs - d'")
apply(simp add:drop_all)
apply(fastforce dest:match_ex_table_SomeD2 split:nat_diff_split)
done
lemma aux_isin[simp]: "[| B ⊆ A; a ∈ B |] ==> a ∈ A"
by blast
lemma fixes P⇣1 defines [simp]: "P ≡ compP⇣2 P⇣1"
shows Jcc:
  "P⇣1 \<turnstile>⇩1 〈e,(h⇣0,ls⇣0)〉 => 〈ef,(h⇣1,ls⇣1)〉 ==>
  (!!C M pc v xa vs frs I.
     [| P,C,M,pc \<rhd> compE⇣2 e; P,C,M \<rhd> compxE⇣2 e pc (size vs)/I,size vs;
       {pc..<pc+size(compE⇣2 e)} ⊆ I |] ==>
     (ef = Val v -->
      P \<turnstile> (None,h⇣0,(vs,ls⇣0,C,M,pc)#frs) -jvm->
            (None,h⇣1,(v#vs,ls⇣1,C,M,pc+size(compE⇣2 e))#frs))
     ∧
     (ef = Throw xa -->
      (∃pc⇣1. pc ≤ pc⇣1 ∧ pc⇣1 < pc + size(compE⇣2 e) ∧
               ¬ caught P pc⇣1 h⇣1 xa (compxE⇣2 e pc (size vs)) ∧
               P \<turnstile> (None,h⇣0,(vs,ls⇣0,C,M,pc)#frs) -jvm-> handle P C M xa h⇣1 vs ls⇣1 pc⇣1 frs)))"
  (is "_ ==> (!!C M pc v xa vs frs I.
                  PROP ?P e h⇣0 ls⇣0 ef h⇣1 ls⇣1 C M pc v xa vs frs I)")
and "P⇣1 \<turnstile>⇩1 〈es,(h⇣0,ls⇣0)〉 [=>] 〈fs,(h⇣1,ls⇣1)〉 ==>
    (!!C M pc ws xa es' vs frs I.
      [| P,C,M,pc \<rhd> compEs⇣2 es; P,C,M \<rhd> compxEs⇣2 es pc (size vs)/I,size vs;
       {pc..<pc+size(compEs⇣2 es)} ⊆ I |] ==>
      (fs = map Val ws -->
       P \<turnstile> (None,h⇣0,(vs,ls⇣0,C,M,pc)#frs) -jvm->
             (None,h⇣1,(rev ws @ vs,ls⇣1,C,M,pc+size(compEs⇣2 es))#frs))
      ∧
      (fs = map Val ws @ Throw xa # es' -->
       (∃pc⇣1. pc ≤ pc⇣1 ∧ pc⇣1 < pc + size(compEs⇣2 es) ∧
                ¬ caught P pc⇣1 h⇣1 xa (compxEs⇣2 es pc (size vs)) ∧
                P \<turnstile> (None,h⇣0,(vs,ls⇣0,C,M,pc)#frs) -jvm-> handle P C M xa h⇣1 vs ls⇣1 pc⇣1 frs)))"
  (is "_ ==> (!!C M pc ws xa es' vs frs I.
                  PROP ?Ps es h⇣0 ls⇣0 fs h⇣1 ls⇣1 C M pc ws xa es' vs frs I)")
proof (induct rule:eval⇣1_evals⇣1_inducts)
  case New⇣1 thus ?case by (clarsimp simp add:blank_def fun_eq_iff)
next
  case NewFail⇣1 thus ?case by(auto simp: handle_def pcs_def)
next
  case (Cast⇣1 e h⇣0 ls⇣0 a h⇣1 ls⇣1 D fs C')
  let ?pc = "pc + length(compE⇣2 e)"
  have "P \<turnstile> (None,h⇣0,(vs,ls⇣0,C,M,pc)#frs) -jvm->
             (None,h⇣1,(Addr a#vs,ls⇣1,C,M,?pc)#frs)" using Cast⇣1 by fastforce
  also have "P \<turnstile> … -jvm-> (None,h⇣1,(Addr a#vs,ls⇣1,C,M,?pc+1)#frs)"
    using Cast⇣1 by (auto simp add:cast_ok_def)
  finally show ?case by auto
next
  case (CastNull⇣1 e h⇣0 ls⇣0 h⇣1 ls⇣1 C')
  let ?pc = "pc + length(compE⇣2 e)"
  have "P \<turnstile> (None,h⇣0,(vs,ls⇣0,C,M,pc)#frs) -jvm->
            (None,h⇣1,(Null#vs,ls⇣1,C,M,?pc)#frs)"
    using CastNull⇣1 by fastforce
  also have "P \<turnstile> … -jvm-> (None,h⇣1,(Null#vs,ls⇣1,C,M,?pc+1)#frs)"
    using CastNull⇣1 by (auto simp add:cast_ok_def)
  finally show ?case by auto
next
  case (CastFail⇣1 e h⇣0 ls⇣0 a h⇣1 ls⇣1 D fs C')
  let ?pc = "pc + length(compE⇣2 e)"
  let ?xa = "addr_of_sys_xcpt ClassCast"
  have "P \<turnstile> (None,h⇣0,(vs,ls⇣0,C,M,pc)#frs) -jvm->
             (None,h⇣1,(Addr a#vs,ls⇣1,C,M,?pc)#frs)"
    using CastFail⇣1 by fastforce
  also have "P \<turnstile> … -jvm-> handle P C M ?xa h⇣1 (Addr a#vs) ls⇣1 ?pc frs"
    using CastFail⇣1 by (auto simp add:handle_def cast_ok_def)
  also have "handle P C M ?xa h⇣1 (Addr a#vs) ls⇣1 ?pc frs =
             handle P C M ?xa h⇣1 vs ls⇣1 ?pc frs"
    using CastFail⇣1.prems by(auto simp:handle_Cons)
  finally have exec: "P \<turnstile> (None,h⇣0,(vs,ls⇣0,C,M,pc)#frs) -jvm-> …".
  show ?case (is "?N ∧ (?eq --> (∃pc⇣1. ?H pc⇣1))")
  proof
    show ?N by simp
  next
    have "?eq --> ?H ?pc" using exec by auto
    thus "?eq --> (∃pc⇣1. ?H pc⇣1)" by blast
  qed
next
  case CastThrow⇣1 thus ?case by fastforce
next
  case Val⇣1 thus ?case by simp
next
  case Var⇣1 thus ?case by auto
next
  case (BinOp⇣1 e⇣1 h⇣0 ls⇣0 v⇣1 h⇣1 ls⇣1 e⇣2 v⇣2 h⇣2 ls⇣2 bop w)
  let ?pc⇣1 = "pc + length(compE⇣2 e⇣1)"
  let ?pc⇣2 = "?pc⇣1 + length(compE⇣2 e⇣2)"
  have IH⇣2: "PROP ?P e⇣2 h⇣1 ls⇣1 (Val v⇣2) h⇣2 ls⇣2 C M ?pc⇣1 v⇣2 xa (v⇣1#vs) frs
                     (I - pcs(compxE⇣2 e⇣1 pc (size vs)))" by fact
  have "P \<turnstile> (None,h⇣0,(vs,ls⇣0,C,M,pc)#frs) -jvm->
             (None,h⇣1,(v⇣1#vs,ls⇣1,C,M,?pc⇣1)#frs)" using BinOp⇣1 by fastforce
  also have "P \<turnstile> … -jvm-> (None,h⇣2,(v⇣2#v⇣1#vs,ls⇣2,C,M,?pc⇣2)#frs)"
    using BinOp⇣1.prems IH⇣2 by fastforce
  also have "P \<turnstile> … -jvm-> (None,h⇣2,(w#vs,ls⇣2,C,M,?pc⇣2+1)#frs)"
    using BinOp⇣1 by(cases bop) auto
  finally show ?case by (auto split: bop.splits simp:add_assoc)
next
  case BinOpThrow⇣1⇣1 thus ?case by(fastforce)
next
  case (BinOpThrow⇣2⇣1 e⇣1 h⇣0 ls⇣0 v⇣1 h⇣1 ls⇣1 e⇣2 e h⇣2 ls⇣2 bop)
  let ?pc = "pc + length(compE⇣2 e⇣1)"
  let ?σ⇣1 = "(None,h⇣1,(v⇣1#vs,ls⇣1,C,M,?pc)#frs)"
  have 1: "P \<turnstile> (None,h⇣0,(vs,ls⇣0,C,M,pc)#frs) -jvm-> ?σ⇣1"
    using BinOpThrow⇣2⇣1 by fastforce
  show ?case (is "?N ∧ (?eq --> (∃pc⇣2. ?H pc⇣2))")
  proof
    show ?N by simp
  next
    { assume ?eq
      moreover
      have "PROP ?P e⇣2 h⇣1 ls⇣1 (throw e) h⇣2 ls⇣2 C M ?pc v xa (v⇣1#vs) frs
                     (I - pcs(compxE⇣2 e⇣1 pc (size vs)))" by fact
      ultimately obtain pc⇣2 where
        pc⇣2: "?pc ≤ pc⇣2 ∧ pc⇣2 < ?pc + size(compE⇣2 e⇣2) ∧
              ¬ caught P pc⇣2 h⇣2 xa (compxE⇣2 e⇣2 ?pc (size vs + 1))" and
        2: "P \<turnstile> ?σ⇣1 -jvm-> handle P C M xa h⇣2 (v⇣1#vs) ls⇣2 pc⇣2 frs"
        using BinOpThrow⇣2⇣1.prems by fastforce
      have 3: "P \<turnstile> ?σ⇣1 -jvm-> handle P C M xa h⇣2 vs ls⇣2 pc⇣2 frs"
        using 2 BinOpThrow⇣2⇣1.prems pc⇣2 by(auto simp:handle_Cons)
      have "?H pc⇣2" using pc⇣2 jvm_trans[OF 1 3] by auto
      hence "∃pc⇣2. ?H pc⇣2" by iprover
    }
    thus "?eq --> (∃pc⇣2. ?H pc⇣2)" by iprover
  qed
next
  case (FAcc⇣1 e h⇣0 ls⇣0 a h⇣1 ls⇣1 C fs F D w)
  let ?pc = "pc + length(compE⇣2 e)"
  have "P \<turnstile> (None,h⇣0,(vs,ls⇣0,C,M,pc)#frs) -jvm->
             (None,h⇣1,(Addr a#vs,ls⇣1,C,M,?pc)#frs)" using FAcc⇣1 by fastforce
  also have "P \<turnstile> … -jvm-> (None,h⇣1,(w#vs,ls⇣1,C,M,?pc+1)#frs)"
    using FAcc⇣1 by auto
  finally show ?case by auto
next
  case (FAccNull⇣1 e h⇣0 ls⇣0 h⇣1 ls⇣1 F D)
  let ?pc = "pc + length(compE⇣2 e)"
  let ?xa = "addr_of_sys_xcpt NullPointer"
  have "P \<turnstile> (None,h⇣0,(vs,ls⇣0,C,M,pc)#frs) -jvm->
             (None,h⇣1,(Null#vs,ls⇣1,C,M,?pc)#frs)" using FAccNull⇣1 by fastforce
  also have "P \<turnstile> … -jvm-> handle P C M ?xa h⇣1 (Null#vs) ls⇣1 ?pc frs"
    using FAccNull⇣1.prems
    by(fastforce simp:split_beta handle_def simp del: split_paired_Ex)
  also have "handle P C M ?xa h⇣1 (Null#vs) ls⇣1 ?pc frs =
             handle P C M ?xa h⇣1 vs ls⇣1 ?pc frs"
    using FAccNull⇣1.prems by(auto simp add:handle_Cons)
  finally show ?case by (auto intro: exI[where x = ?pc])
next
  case FAccThrow⇣1 thus ?case by fastforce
next
  case (LAss⇣1 e h⇣0 ls⇣0 w h⇣1 ls⇣1 i ls⇣2)
  let ?pc = "pc + length(compE⇣2 e)"
  have "P \<turnstile> (None,h⇣0,(vs,ls⇣0,C,M,pc)#frs) -jvm->
             (None,h⇣1,(w#vs,ls⇣1,C,M,?pc)#frs)" using LAss⇣1 by fastforce
  also have "P \<turnstile> … -jvm-> (None,h⇣1,(Unit#vs,ls⇣2,C,M,?pc+2)#frs)"
    using LAss⇣1 by auto
  finally show ?case using LAss⇣1 by auto
next
  case LAssThrow⇣1 thus ?case by fastforce
next
  case (FAss⇣1 e⇣1 h⇣0 ls⇣0 a h⇣1 ls⇣1 e⇣2 w h⇣2 ls⇣2 C fs fs' F D h⇣2')
  let ?pc⇣1 = "pc + length(compE⇣2 e⇣1)"
  let ?pc⇣2 = "?pc⇣1 + length(compE⇣2 e⇣2)"
  have IH⇣2: "PROP ?P e⇣2 h⇣1 ls⇣1 (Val w) h⇣2 ls⇣2 C M ?pc⇣1 w xa (Addr a#vs) frs
                     (I - pcs(compxE⇣2 e⇣1 pc (size vs)))" by fact
  have "P \<turnstile> (None,h⇣0,(vs,ls⇣0,C,M,pc)#frs) -jvm->
             (None,h⇣1,(Addr a#vs,ls⇣1,C,M,?pc⇣1)#frs)" using FAss⇣1 by fastforce
  also have "P \<turnstile> … -jvm-> (None,h⇣2,(w#Addr a#vs,ls⇣2,C,M,?pc⇣2)#frs)"
    using FAss⇣1.prems IH⇣2 by fastforce
  also have "P \<turnstile> … -jvm-> (None,h⇣2',(Unit#vs,ls⇣2,C,M,?pc⇣2+2)#frs)"
    using FAss⇣1 by auto
  finally show ?case using FAss⇣1 by (auto simp:add_assoc)
next
  case (FAssNull⇣1 e⇣1 h⇣0 ls⇣0 h⇣1 ls⇣1 e⇣2 w h⇣2 ls⇣2 F D)
  let ?pc⇣1 = "pc + length(compE⇣2 e⇣1)"
  let ?pc⇣2 = "?pc⇣1 + length(compE⇣2 e⇣2)"
  let ?xa = "addr_of_sys_xcpt NullPointer"
  have IH⇣2: "PROP ?P e⇣2 h⇣1 ls⇣1 (Val w) h⇣2 ls⇣2 C M ?pc⇣1 w xa (Null#vs) frs
                     (I - pcs(compxE⇣2 e⇣1 pc (size vs)))" by fact
  have "P \<turnstile> (None,h⇣0,(vs,ls⇣0,C,M,pc)#frs) -jvm->
             (None,h⇣1,(Null#vs,ls⇣1,C,M,?pc⇣1)#frs)" using FAssNull⇣1 by fastforce
  also have "P \<turnstile> … -jvm-> (None,h⇣2,(w#Null#vs,ls⇣2,C,M,?pc⇣2)#frs)"
    using FAssNull⇣1.prems IH⇣2 by fastforce
  also have "P \<turnstile> … -jvm-> handle P C M ?xa h⇣2 (w#Null#vs) ls⇣2 ?pc⇣2 frs"
    using FAssNull⇣1.prems
    by(fastforce simp:split_beta handle_def simp del: split_paired_Ex)
  also have "handle P C M ?xa h⇣2 (w#Null#vs) ls⇣2 ?pc⇣2 frs =
             handle P C M ?xa h⇣2 vs ls⇣2 ?pc⇣2 frs"
    using FAssNull⇣1.prems by(auto simp add:handle_Cons)
  finally show ?case by (auto intro: exI[where x = ?pc⇣2])
next
  case (FAssThrow⇣2⇣1 e⇣1 h⇣0 ls⇣0 w h⇣1 ls⇣1 e⇣2 e' h⇣2 ls⇣2 F D)
  let ?pc⇣1 = "pc + length(compE⇣2 e⇣1)"
  let ?σ⇣1 = "(None,h⇣1,(w#vs,ls⇣1,C,M,?pc⇣1)#frs)"
  have 1: "P \<turnstile> (None,h⇣0,(vs,ls⇣0,C,M,pc)#frs) -jvm-> ?σ⇣1"
    using FAssThrow⇣2⇣1 by fastforce
  show ?case (is "?N ∧ (?eq --> (∃pc⇣2. ?H pc⇣2))")
  proof
    show ?N by simp
  next
    { assume ?eq
      moreover
      have "PROP ?P e⇣2 h⇣1 ls⇣1 (throw e') h⇣2 ls⇣2 C M ?pc⇣1 v xa (w#vs) frs
                    (I - pcs (compxE⇣2 e⇣1 pc (length vs)))" by fact
      ultimately obtain pc⇣2 where
        pc⇣2: "?pc⇣1 ≤ pc⇣2 ∧ pc⇣2 < ?pc⇣1 + size(compE⇣2 e⇣2) ∧
              ¬ caught P pc⇣2 h⇣2 xa (compxE⇣2 e⇣2 ?pc⇣1 (size vs + 1))" and
        2: "P \<turnstile> ?σ⇣1 -jvm-> handle P C M xa h⇣2 (w#vs) ls⇣2 pc⇣2 frs"
        using FAssThrow⇣2⇣1.prems by fastforce
      have 3: "P \<turnstile> ?σ⇣1 -jvm-> handle P C M xa h⇣2 vs ls⇣2 pc⇣2 frs"
        using 2 FAssThrow⇣2⇣1.prems pc⇣2 by(auto simp:handle_Cons)
      have "?H pc⇣2" using pc⇣2 jvm_trans[OF 1 3] by auto
      hence "∃pc⇣2. ?H pc⇣2" by iprover
    }
    thus "?eq --> (∃pc⇣2. ?H pc⇣2)" by iprover
  qed
next
  case FAssThrow⇣1⇣1 thus ?case by fastforce
next
  case (Call⇣1 e h⇣0 ls⇣0 a h⇣1 ls⇣1 es pvs h⇣2 ls⇣2 Ca fs M' Ts T body D ls⇣2' f h⇣3 ls⇣3)
  have "P⇣1 \<turnstile>⇩1 〈es,(h⇣1, ls⇣1)〉 [=>] 〈map Val pvs,(h⇣2, ls⇣2)〉" by fact
  hence [simp]: "length es = length pvs" by(auto dest:evals⇣1_preserves_elen)
  let ?σ⇣0 = "(None,h⇣0,(vs, ls⇣0, C,M,pc)#frs)"
  let ?pc⇣1 = "pc + length(compE⇣2 e)"
  let ?σ⇣1 = "(None,h⇣1,(Addr a # vs, ls⇣1, C,M,?pc⇣1)#frs)"
  let ?pc⇣2 = "?pc⇣1 + length(compEs⇣2 es)"
  let ?frs⇣2 = "(rev pvs @ Addr a # vs, ls⇣2, C,M,?pc⇣2)#frs"
  let ?σ⇣2 = "(None,h⇣2,?frs⇣2)"
  let ?frs⇣2' = "([], ls⇣2', D,M',0) # ?frs⇣2"
  let ?σ⇣2' = "(None, h⇣2, ?frs⇣2')"
  have IH_es: "PROP ?Ps es h⇣1 ls⇣1 (map Val pvs) h⇣2 ls⇣2 C M ?pc⇣1 pvs xa
                    (map Val pvs) (Addr a # vs) frs (I - pcs(compxE⇣2 e pc (size vs)))" by fact
  have "P \<turnstile> ?σ⇣0 -jvm-> ?σ⇣1" using Call⇣1 by fastforce
  also have "P \<turnstile> … -jvm-> ?σ⇣2" using IH_es Call⇣1.prems by fastforce
  also have "P \<turnstile> … -jvm-> ?σ⇣2'"
    using Call⇣1 by(auto simp add: nth_append compMb⇣2_def)
  finally have 1: "P \<turnstile> ?σ⇣0 -jvm-> ?σ⇣2'".
  have "P⇣1 \<turnstile> Ca sees M': Ts->T = body in D" by fact
  then have M'_in_D: "P⇣1 \<turnstile> D sees M': Ts->T = body in D"
    by(rule sees_method_idemp) 
  hence M'_code: "compP⇣2 P⇣1,D,M',0 \<rhd> compE⇣2 body @ [Return]"
    and M'_xtab: "compP⇣2 P⇣1,D,M' \<rhd> compxE⇣2 body 0 0/{..<size(compE⇣2 body)},0"
    by(rule beforeM, rule beforexM)
  have IH_body: "PROP ?P body h⇣2 ls⇣2' f h⇣3 ls⇣3 D M' 0 v xa [] ?frs⇣2 ({..<size(compE⇣2 body)})" by fact
  show ?case (is "?Norm ∧ ?Err")
  proof
    show ?Norm (is "?val --> ?trans")
    proof
      assume val: ?val
      note 1
      also have "P \<turnstile> ?σ⇣2' -jvm->
                     (None,h⇣3,([v],ls⇣3,D,M',size(compE⇣2 body))#?frs⇣2)"
        using val IH_body Call⇣1.prems M'_code M'_xtab
        by (fastforce simp del:split_paired_Ex)
      also have "P \<turnstile> … -jvm-> (None, h⇣3, (v # vs, ls⇣2, C,M,?pc⇣2+1)#frs)"
        using Call⇣1 M'_code M'_in_D by(auto simp: nth_append compMb⇣2_def)
      finally show ?trans by(simp add:add_assoc)
    qed
  next
    show ?Err (is "?throw --> (∃pc⇣2. ?H pc⇣2)")
    proof
      assume throw: ?throw
      with IH_body obtain pc⇣2 where
        pc⇣2: "0 ≤ pc⇣2 ∧ pc⇣2 < size(compE⇣2 body) ∧
              ¬ caught P pc⇣2 h⇣3 xa (compxE⇣2 body 0 0)" and
        2: "P \<turnstile> ?σ⇣2' -jvm-> handle P D M' xa h⇣3 [] ls⇣3 pc⇣2 ?frs⇣2"
        using Call⇣1.prems M'_code M'_xtab
        by (fastforce simp del:split_paired_Ex)
      have "handle P D M' xa h⇣3 [] ls⇣3 pc⇣2 ?frs⇣2 =
            handle P C M xa h⇣3 (rev pvs @ Addr a # vs) ls⇣2 ?pc⇣2 frs"
        using pc⇣2 M'_in_D by(auto simp add:handle_def)
      also have "… = handle P C M xa h⇣3 vs ls⇣2 ?pc⇣2 frs"
        using Call⇣1.prems by(auto simp add:handle_append handle_Cons)
      finally have "?H ?pc⇣2" using pc⇣2 jvm_trans[OF 1 2] by auto
      thus "∃pc⇣2. ?H pc⇣2" by iprover
    qed
  qed
next
  case (CallParamsThrow⇣1 e h⇣0 ls⇣0 w h⇣1 ls⇣1 es es' h⇣2 ls⇣2 pvs ex es'' M')
  let ?σ⇣0 = "(None,h⇣0,(vs, ls⇣0, C,M,pc)#frs)"
  let ?pc⇣1 = "pc + length(compE⇣2 e)"
  let ?σ⇣1 = "(None,h⇣1,(w # vs, ls⇣1, C,M,?pc⇣1)#frs)"
  let ?pc⇣2 = "?pc⇣1 + length(compEs⇣2 es)"
  have 1: "P \<turnstile> ?σ⇣0 -jvm-> ?σ⇣1" using CallParamsThrow⇣1 by fastforce
  show ?case (is "?N ∧ (?eq --> (∃pc⇣2. ?H pc⇣2))")
  proof
    show ?N by simp
  next
    { assume ?eq
      moreover
      have "PROP ?Ps es h⇣1 ls⇣1 es' h⇣2 ls⇣2 C M ?pc⇣1 pvs xa es'' (w#vs) frs
        (I - pcs (compxE⇣2 e pc (length vs)))" by fact
      ultimately have "∃pc⇣2.
        (?pc⇣1 ≤ pc⇣2 ∧ pc⇣2 < ?pc⇣1 + size(compEs⇣2 es) ∧
         ¬ caught P pc⇣2 h⇣2 xa (compxEs⇣2 es ?pc⇣1 (size vs + 1))) ∧
        P \<turnstile> ?σ⇣1 -jvm-> handle P C M xa h⇣2 (w#vs) ls⇣2 pc⇣2 frs"
        (is "∃pc⇣2. ?PC pc⇣2 ∧ ?Exec pc⇣2")
        using CallParamsThrow⇣1 by force
      then obtain pc⇣2 where pc⇣2: "?PC pc⇣2" and 2: "?Exec pc⇣2" by iprover
      have "?H pc⇣2" using pc⇣2 jvm_trans[OF 1 2] CallParamsThrow⇣1
        by(auto simp:handle_Cons)
      hence "∃pc⇣2. ?H pc⇣2" by iprover
    }
    thus "?eq --> (∃pc⇣2. ?H pc⇣2)" by iprover
  qed
next
  case (CallNull⇣1 e h⇣0 ls⇣0 h⇣1 ls⇣1 es pvs h⇣2 ls⇣2 M')
  have "P⇣1 \<turnstile>⇩1 〈es,(h⇣1, ls⇣1)〉 [=>] 〈map Val pvs,(h⇣2, ls⇣2)〉" by fact
  hence [simp]: "length es = length pvs" by(auto dest:evals⇣1_preserves_elen)
  let ?pc⇣1 = "pc + length(compE⇣2 e)"
  let ?pc⇣2 = "?pc⇣1 + length(compEs⇣2 es)"
  let ?xa = "addr_of_sys_xcpt NullPointer"
  have IH_es: "PROP ?Ps es h⇣1 ls⇣1 (map Val pvs) h⇣2 ls⇣2 C M ?pc⇣1 pvs xa
                    (map Val pvs) (Null#vs) frs (I - pcs(compxE⇣2 e pc (size vs)))" by fact
  have "P \<turnstile> (None,h⇣0,(vs,ls⇣0,C,M,pc)#frs) -jvm->
             (None,h⇣1,(Null#vs,ls⇣1,C,M,?pc⇣1)#frs)" using CallNull⇣1 by fastforce
  also have "P \<turnstile> … -jvm-> (None,h⇣2,(rev pvs@Null#vs,ls⇣2,C,M,?pc⇣2)#frs)"
    using CallNull⇣1 IH_es by fastforce
  also have "P \<turnstile> … -jvm-> handle P C M ?xa h⇣2 (rev pvs@Null#vs) ls⇣2 ?pc⇣2 frs"
    using CallNull⇣1.prems
    by(auto simp:split_beta handle_def nth_append simp del: split_paired_Ex)
  also have "handle P C M ?xa h⇣2 (rev pvs@Null#vs) ls⇣2 ?pc⇣2 frs =
             handle P C M ?xa h⇣2 vs ls⇣2 ?pc⇣2 frs"
    using CallNull⇣1.prems by(auto simp:handle_Cons handle_append)
  finally show ?case by (auto intro: exI[where x = ?pc⇣2])
next
  case CallObjThrow⇣1 thus ?case by fastforce
next
  case Block⇣1 thus ?case by auto
next
  case (Seq⇣1 e⇣1 h⇣0 ls⇣0 w h⇣1 ls⇣1 e⇣2 e⇣2' h⇣2 ls⇣2)
  let ?pc⇣1 = "pc + length(compE⇣2 e⇣1)"
  let ?σ⇣0 = "(None,h⇣0,(vs,ls⇣0,C,M,pc)#frs)"
  let ?σ⇣1 = "(None,h⇣1,(vs,ls⇣1,C,M,?pc⇣1+1)#frs)"
  have "P \<turnstile> ?σ⇣0 -jvm-> (None,h⇣1,(w#vs,ls⇣1,C,M,?pc⇣1)#frs)"
    using Seq⇣1 by fastforce
  also have "P \<turnstile> … -jvm-> ?σ⇣1" using Seq⇣1 by auto
  finally have eval⇣1: "P \<turnstile> ?σ⇣0 -jvm-> ?σ⇣1".
  let ?pc⇣2 = "?pc⇣1 + 1 + length(compE⇣2 e⇣2)"
  have IH⇣2: "PROP ?P e⇣2 h⇣1 ls⇣1 e⇣2' h⇣2 ls⇣2 C M (?pc⇣1+1) v xa vs frs
                     (I - pcs(compxE⇣2 e⇣1 pc (size vs)))" by fact
  show ?case (is "?Norm ∧ ?Err")
  proof
    show ?Norm (is "?val --> ?trans")
    proof
      assume val: ?val
      note eval⇣1
      also have "P \<turnstile> ?σ⇣1 -jvm-> (None,h⇣2,(v#vs,ls⇣2,C,M,?pc⇣2)#frs)"
        using val Seq⇣1.prems IH⇣2 by fastforce
      finally show ?trans by(simp add:add_assoc)
    qed
  next
    show ?Err (is "?throw --> (∃pc⇣2. ?H pc⇣2)")
    proof
      assume throw: ?throw
      then obtain pc⇣2 where
        pc⇣2: "?pc⇣1+1 ≤ pc⇣2 ∧ pc⇣2 < ?pc⇣2 ∧
              ¬ caught P pc⇣2 h⇣2 xa (compxE⇣2 e⇣2 (?pc⇣1+1) (size vs))" and
        eval⇣2: "P \<turnstile> ?σ⇣1 -jvm-> handle P C M xa h⇣2 vs ls⇣2 pc⇣2 frs"
        using IH⇣2 Seq⇣1.prems by fastforce
      have "?H pc⇣2" using pc⇣2 jvm_trans[OF eval⇣1 eval⇣2] by auto
      thus "∃pc⇣2. ?H pc⇣2" by iprover
    qed
  qed
next
  case SeqThrow⇣1 thus ?case by fastforce
next
  case (CondT⇣1 e h⇣0 ls⇣0 h⇣1 ls⇣1 e⇣1 e' h⇣2 ls⇣2 e⇣2)
  let ?pc⇣1 = "pc + length(compE⇣2 e)"
  let ?σ⇣0 = "(None,h⇣0,(vs,ls⇣0,C,M,pc)#frs)"
  let ?σ⇣1 = "(None,h⇣1,(vs,ls⇣1,C,M,?pc⇣1+1)#frs)"
  have "P \<turnstile> ?σ⇣0 -jvm-> (None,h⇣1,(Bool(True)#vs,ls⇣1,C,M,?pc⇣1)#frs)"
    using CondT⇣1 by (fastforce simp add: Int_Un_distrib)
  also have "P \<turnstile> … -jvm-> ?σ⇣1" using CondT⇣1 by auto
  finally have eval⇣1: "P \<turnstile> ?σ⇣0 -jvm-> ?σ⇣1".
  let ?pc⇣1' = "?pc⇣1 + 1 + length(compE⇣2 e⇣1)"
  let ?pc⇣2' = "?pc⇣1' + 1 + length(compE⇣2 e⇣2)"
  show ?case (is "?Norm ∧ ?Err")
  proof
    show ?Norm (is "?val --> ?trans")
    proof
      assume val: ?val
      note eval⇣1
      also have "P \<turnstile> ?σ⇣1 -jvm-> (None,h⇣2,(v#vs,ls⇣2,C,M,?pc⇣1')#frs)"
        using val CondT⇣1 by(fastforce simp:Int_Un_distrib)
      also have "P \<turnstile> … -jvm-> (None,h⇣2,(v#vs,ls⇣2,C,M,?pc⇣2')#frs)"
        using CondT⇣1 by(auto simp:add_assoc)
      finally show ?trans by(simp add:add_assoc)
    qed
  next
    show ?Err (is "?throw --> (∃pc⇣2. ?H pc⇣2)")
    proof
      let ?d = "size vs"
      let ?I = "I - pcs(compxE⇣2 e pc ?d) - pcs(compxE⇣2 e⇣2 (?pc⇣1'+1) ?d)"
      assume throw: ?throw
      moreover
      have "PROP ?P e⇣1 h⇣1 ls⇣1 e' h⇣2 ls⇣2 C M (?pc⇣1+1) v xa vs frs ?I" by fact
      ultimately obtain pc⇣2 where
        pc⇣2: "?pc⇣1+1 ≤ pc⇣2 ∧ pc⇣2 < ?pc⇣1' ∧
              ¬ caught P pc⇣2 h⇣2 xa (compxE⇣2 e⇣1 (?pc⇣1+1) (size vs))" and
        eval⇣2: "P \<turnstile> ?σ⇣1 -jvm-> handle P C M xa h⇣2 vs ls⇣2 pc⇣2 frs"
        using CondT⇣1.prems by (fastforce simp:Int_Un_distrib)
      have "?H pc⇣2" using pc⇣2 jvm_trans[OF eval⇣1 eval⇣2] by auto
      thus "∃pc⇣2. ?H pc⇣2" by iprover
    qed
  qed
next
  case (CondF⇣1 e h⇣0 ls⇣0 h⇣1 ls⇣1 e⇣2 e' h⇣2 ls⇣2 e⇣1)
  let ?pc⇣1 = "pc + length(compE⇣2 e)"
  let ?pc⇣2 = "?pc⇣1 + 1 + length(compE⇣2 e⇣1)+ 1"
  let ?pc⇣2' = "?pc⇣2 + length(compE⇣2 e⇣2)"
  let ?σ⇣0 = "(None,h⇣0,(vs,ls⇣0,C,M,pc)#frs)"
  let ?σ⇣1 = "(None,h⇣1,(vs,ls⇣1,C,M,?pc⇣2)#frs)"
  have "P \<turnstile> ?σ⇣0 -jvm-> (None,h⇣1,(Bool(False)#vs,ls⇣1,C,M,?pc⇣1)#frs)"
    using CondF⇣1 by (fastforce simp add: Int_Un_distrib)
  also have "P \<turnstile> … -jvm-> ?σ⇣1" using CondF⇣1 by auto
  finally have eval⇣1: "P \<turnstile> ?σ⇣0 -jvm-> ?σ⇣1".
  show ?case (is "?Norm ∧ ?Err")
  proof
    show ?Norm (is "?val --> ?trans")
    proof
      assume val: ?val
      note eval⇣1
      also have "P \<turnstile> ?σ⇣1 -jvm-> (None,h⇣2,(v#vs,ls⇣2,C,M,?pc⇣2')#frs)"
        using val CondF⇣1 by(fastforce simp:Int_Un_distrib)
      finally show ?trans by(simp add:add_assoc)
    qed
  next
    show ?Err (is "?throw --> (∃pc⇣2. ?H pc⇣2)")
    proof
      let ?d = "size vs"
      let ?I = "I - pcs(compxE⇣2 e pc ?d) - pcs(compxE⇣2 e⇣1 (?pc⇣1+1) ?d)"
      assume throw: ?throw
      moreover
      have "PROP ?P e⇣2 h⇣1 ls⇣1 e' h⇣2 ls⇣2 C M ?pc⇣2 v xa vs frs ?I" by fact
      ultimately obtain pc⇣2 where
        pc⇣2: "?pc⇣2 ≤ pc⇣2 ∧ pc⇣2 < ?pc⇣2' ∧
              ¬ caught P pc⇣2 h⇣2 xa (compxE⇣2 e⇣2 ?pc⇣2 ?d)" and
        eval⇣2: "P \<turnstile> ?σ⇣1 -jvm-> handle P C M xa h⇣2 vs ls⇣2 pc⇣2 frs"
        using CondF⇣1.prems by(fastforce simp:Int_Un_distrib)
      have "?H pc⇣2" using pc⇣2 jvm_trans[OF eval⇣1 eval⇣2] by auto
      thus "∃pc⇣2. ?H pc⇣2" by iprover
    qed
  qed
next
  case (CondThrow⇣1 e h⇣0 ls⇣0 f h⇣1 ls⇣1 e⇣1 e⇣2)
  let ?d = "size vs"
  let ?xt⇣1 = "compxE⇣2 e⇣1 (pc+size(compE⇣2 e)+1) ?d"
  let ?xt⇣2 = "compxE⇣2 e⇣2 (pc+size(compE⇣2 e)+size(compE⇣2 e⇣1)+2) ?d"
  let ?I = "I - (pcs ?xt⇣1 ∪ pcs ?xt⇣2)"
  have "pcs(compxE⇣2 e pc ?d) ∩ pcs(?xt⇣1 @ ?xt⇣2) = {}"
    using CondThrow⇣1.prems by (simp add:Int_Un_distrib)
  moreover have "PROP ?P e h⇣0 ls⇣0 (throw f) h⇣1 ls⇣1 C M pc v xa vs frs ?I" by fact
  ultimately show ?case using CondThrow⇣1.prems by fastforce
next
  case (WhileF⇣1 e h⇣0 ls⇣0 h⇣1 ls⇣1 c)
  let ?pc = "pc + length(compE⇣2 e)"
  let ?pc' = "?pc + length(compE⇣2 c) + 3"
  have "P \<turnstile> (None,h⇣0,(vs,ls⇣0,C,M,pc)#frs) -jvm->
            (None,h⇣1,(Bool False#vs,ls⇣1,C,M,?pc)#frs)"
    using WhileF⇣1 by fastforce
  also have "P \<turnstile> … -jvm-> (None,h⇣1,(vs,ls⇣1,C,M,?pc')#frs)"
    using WhileF⇣1 by (auto simp:add_assoc)
  also have "P \<turnstile> … -jvm-> (None,h⇣1,(Unit#vs,ls⇣1,C,M,?pc'+1)#frs)"
    using WhileF⇣1.prems by (auto simp:eval_nat_numeral)
  finally show ?case by (simp add:add_assoc eval_nat_numeral)
next
  case (WhileT⇣1 e h⇣0 ls⇣0 h⇣1 ls⇣1 c v⇣1 h⇣2 ls⇣2 e⇣3 h⇣3 ls⇣3)
  let ?pc = "pc + length(compE⇣2 e)"
  let ?pc' = "?pc + length(compE⇣2 c) + 1"
  let ?σ⇣0 = "(None,h⇣0,(vs,ls⇣0,C,M,pc)#frs)"
  let ?σ⇣2 = "(None,h⇣2,(vs,ls⇣2,C,M,pc)#frs)"
  have "P \<turnstile> ?σ⇣0 -jvm-> (None,h⇣1,(Bool True#vs,ls⇣1,C,M,?pc)#frs)"
    using WhileT⇣1 by fastforce
  also have "P \<turnstile> … -jvm-> (None,h⇣1,(vs,ls⇣1,C,M,?pc+1)#frs)"
    using WhileT⇣1.prems by auto
  also have "P \<turnstile> … -jvm-> (None,h⇣2,(v⇣1#vs,ls⇣2,C,M,?pc')#frs)"
    using WhileT⇣1 by(fastforce)
  also have "P \<turnstile> … -jvm-> ?σ⇣2" using WhileT⇣1.prems by auto
  finally have 1: "P \<turnstile> ?σ⇣0 -jvm-> ?σ⇣2".
  show ?case (is "?Norm ∧ ?Err")
  proof
    show ?Norm (is "?val --> ?trans")
    proof
      assume val: ?val
      note 1
      also have "P \<turnstile> ?σ⇣2 -jvm-> (None,h⇣3,(v#vs,ls⇣3,C,M,?pc'+3)#frs)"
        using val WhileT⇣1 by (auto simp add:add_assoc eval_nat_numeral)
      finally show ?trans by(simp add:add_assoc eval_nat_numeral)
    qed
  next
    show ?Err (is "?throw --> (∃pc⇣2. ?H pc⇣2)")
    proof
      assume throw: ?throw
      moreover
      have "PROP ?P (while (e) c) h⇣2 ls⇣2 e⇣3 h⇣3 ls⇣3 C M pc v xa vs frs I" by fact
      ultimately obtain pc⇣2 where
        pc⇣2: "pc ≤ pc⇣2 ∧ pc⇣2 < ?pc'+3 ∧
              ¬ caught P pc⇣2 h⇣3 xa (compxE⇣2 (while (e) c) pc (size vs))" and
        2: "P \<turnstile> ?σ⇣2 -jvm-> handle P C M xa h⇣3 vs ls⇣3 pc⇣2 frs"
        using WhileT⇣1.prems by (auto simp:add_assoc eval_nat_numeral)
      have "?H pc⇣2" using pc⇣2 jvm_trans[OF 1 2] by auto
      thus "∃pc⇣2. ?H pc⇣2" by iprover
    qed
  qed
next
  case WhileCondThrow⇣1 thus ?case by fastforce
next
  case (WhileBodyThrow⇣1 e h⇣0 ls⇣0 h⇣1 ls⇣1 c e' h⇣2 ls⇣2)
  let ?pc⇣1 = "pc + length(compE⇣2 e)"
  let ?σ⇣0 = "(None,h⇣0,(vs,ls⇣0,C,M,pc)#frs)"
  let ?σ⇣1 = "(None,h⇣1,(vs,ls⇣1,C,M,?pc⇣1+1)#frs)"
  have "P \<turnstile> ?σ⇣0 -jvm-> (None,h⇣1,(Bool(True)#vs,ls⇣1,C,M,?pc⇣1)#frs)"
    using WhileBodyThrow⇣1 by (fastforce simp add: Int_Un_distrib)
  also have "P \<turnstile> … -jvm-> ?σ⇣1" using  WhileBodyThrow⇣1 by auto
  finally have eval⇣1: "P \<turnstile> ?σ⇣0 -jvm-> ?σ⇣1".
  let ?pc⇣1' = "?pc⇣1 + 1 + length(compE⇣2 c)"
  show ?case (is "?Norm ∧ ?Err")
  proof
    show ?Norm by simp
  next
    show ?Err (is "?throw --> (∃pc⇣2. ?H pc⇣2)")
    proof
      assume throw: ?throw
      moreover
      have "PROP ?P c h⇣1 ls⇣1 (throw e') h⇣2 ls⇣2 C M (?pc⇣1+1) v xa vs frs
                    (I - pcs (compxE⇣2 e pc (size vs)))" by fact
      ultimately obtain pc⇣2 where
        pc⇣2: "?pc⇣1+1 ≤ pc⇣2 ∧ pc⇣2 < ?pc⇣1' ∧
              ¬ caught P pc⇣2 h⇣2 xa (compxE⇣2 c (?pc⇣1+1) (size vs))" and
        eval⇣2: "P \<turnstile> ?σ⇣1 -jvm-> handle P C M xa h⇣2 vs ls⇣2 pc⇣2 frs"
        using WhileBodyThrow⇣1.prems by (fastforce simp:Int_Un_distrib)
      have "?H pc⇣2" using pc⇣2 jvm_trans[OF eval⇣1 eval⇣2] by auto
      thus "∃pc⇣2. ?H pc⇣2" by iprover
    qed
  qed
next
  case (Throw⇣1 e h⇣0 ls⇣0 a h⇣1 ls⇣1)
  let ?pc = "pc + size(compE⇣2 e)"
  show ?case (is "?Norm ∧ ?Err")
  proof
    show ?Norm by simp
  next
    show ?Err (is "?throw --> (∃pc⇣1. ?H pc⇣1)")
    proof
      assume ?throw
      hence "P \<turnstile> (None, h⇣0, (vs, ls⇣0, C, M, pc) # frs) -jvm->
                 (None, h⇣1, (Addr xa#vs, ls⇣1, C, M, ?pc) # frs)"
        using Throw⇣1 by fastforce
      also have "P \<turnstile> … -jvm-> handle P C M xa h⇣1 (Addr xa#vs) ls⇣1 ?pc frs"
        using Throw⇣1.prems by(auto simp add:handle_def)
      also have "handle P C M xa h⇣1 (Addr xa#vs) ls⇣1 ?pc frs =
                 handle P C M xa h⇣1 vs ls⇣1 ?pc frs"
        using Throw⇣1.prems by(auto simp add:handle_Cons)
      finally have "?H ?pc" by simp
      thus "∃pc⇣1. ?H pc⇣1" by iprover
    qed
  qed
next
  case (ThrowNull⇣1 e h⇣0 ls⇣0 h⇣1 ls⇣1)
  let ?pc = "pc + size(compE⇣2 e)"
  let ?xa = "addr_of_sys_xcpt NullPointer"
  show ?case (is "?Norm ∧ ?Err")
  proof
    show ?Norm by simp
  next
    show ?Err (is "?throw --> (∃pc⇣1. ?H pc⇣1)")
    proof
      assume throw: ?throw
      have "P \<turnstile> (None, h⇣0, (vs, ls⇣0, C, M, pc) # frs) -jvm->
                 (None, h⇣1, (Null#vs, ls⇣1, C, M, ?pc) # frs)"
        using ThrowNull⇣1 by fastforce
      also have "P \<turnstile> … -jvm->  handle P C M ?xa h⇣1 (Null#vs) ls⇣1 ?pc frs"
        using ThrowNull⇣1.prems by(auto simp add:handle_def)
      also have "handle P C M ?xa h⇣1 (Null#vs) ls⇣1 ?pc frs =
                 handle P C M ?xa h⇣1 vs ls⇣1 ?pc frs"
        using ThrowNull⇣1.prems by(auto simp add:handle_Cons)
      finally have "?H ?pc" using throw by simp
      thus "∃pc⇣1. ?H pc⇣1" by iprover
    qed
  qed
next
  case ThrowThrow⇣1 thus ?case by fastforce
next
  case (Try⇣1 e⇣1 h⇣0 ls⇣0 v⇣1 h⇣1 ls⇣1 Ci i e⇣2)
  let ?pc⇣1 = "pc + length(compE⇣2 e⇣1)"
  let ?pc⇣1' = "?pc⇣1 + 2 + length(compE⇣2 e⇣2)"
  have "P,C,M \<rhd> compxE⇣2 (try e⇣1 catch(Ci i) e⇣2) pc (size vs) / I,size vs" by fact
  hence "P,C,M \<rhd> compxE⇣2 e⇣1 pc (size vs) /
                 {pc..<pc + length (compE⇣2 e⇣1)},size vs"
    using Try⇣1.prems by (fastforce simp:beforex_def split:split_if_asm)
  hence "P \<turnstile> (None,h⇣0,(vs,ls⇣0,C,M,pc)#frs) -jvm->
             (None,h⇣1,(v⇣1#vs,ls⇣1,C,M,?pc⇣1)#frs)" using Try⇣1 by auto
  also have "P \<turnstile> … -jvm-> (None,h⇣1,(v⇣1#vs,ls⇣1,C,M,?pc⇣1')#frs)"
    using Try⇣1.prems by auto
  finally show ?case by (auto simp:add_assoc)
next
  case (TryCatch⇣1 e⇣1 h⇣0 ls⇣0 a h⇣1 ls⇣1 D fs Ci i e⇣2 e⇣2' h⇣2 ls⇣2)
  let ?e = "try e⇣1 catch(Ci i) e⇣2"
  let ?xt = "compxE⇣2 ?e pc (size vs)"
  let ?σ⇣0 = "(None,h⇣0,(vs,ls⇣0,C,M,pc)#frs)"
  let ?ls⇣1 = "ls⇣1[i := Addr a]"
  let ?pc⇣1 = "pc + length(compE⇣2 e⇣1)"
  let ?pc⇣1' = "?pc⇣1 + 2"
  let ?σ⇣1 = "(None,h⇣1,(vs,?ls⇣1,C,M, ?pc⇣1') # frs)"
  have I: "{pc..<pc + length (compE⇣2 (try e⇣1 catch(Ci i) e⇣2))} ⊆ I"
   and beforex: "P,C,M \<rhd> ?xt/I,size vs" by fact+
  have "P \<turnstile> ?σ⇣0 -jvm-> (None,h⇣1,((Addr a)#vs,ls⇣1,C,M, ?pc⇣1+1) # frs)"
  proof -
    have "PROP ?P e⇣1 h⇣0 ls⇣0 (Throw a) h⇣1 ls⇣1 C M pc w a vs frs {pc..<pc + length (compE⇣2 e⇣1)}"
      by fact
    moreover have "P,C,M \<rhd> compxE⇣2 e⇣1 pc (size vs)/{pc..<?pc⇣1},size vs"
      using beforex I pcs_subset by(force elim!: beforex_appendD1)
    ultimately have
      "∃pc⇣1. pc ≤ pc⇣1 ∧ pc⇣1 < ?pc⇣1 ∧
             ¬ caught P pc⇣1 h⇣1 a (compxE⇣2 e⇣1 pc (size vs)) ∧
             P \<turnstile> ?σ⇣0 -jvm-> handle P C M a h⇣1 vs ls⇣1 pc⇣1 frs"
      using  TryCatch⇣1.prems by auto
    then obtain pc⇣1 where
      pc⇣1_in_e⇣1: "pc ≤ pc⇣1" "pc⇣1 < ?pc⇣1" and
      pc⇣1_not_caught: "¬ caught P pc⇣1 h⇣1 a (compxE⇣2 e⇣1 pc (size vs))" and
      0: "P \<turnstile> ?σ⇣0 -jvm-> handle P C M a h⇣1 vs ls⇣1 pc⇣1 frs" by iprover
    from beforex obtain xt⇣0 xt⇣1
      where ex_tab: "ex_table_of P C M = xt⇣0 @ ?xt @ xt⇣1"
      and disj: "pcs xt⇣0 ∩ I = {}" by(auto simp:beforex_def)
    have hp: "h⇣1 a = Some (D, fs)" "P⇣1 \<turnstile> D \<preceq>⇧* Ci" by fact+
    have "pc⇣1 ∉ pcs xt⇣0" using pc⇣1_in_e⇣1 I disj by auto
    with pc⇣1_in_e⇣1 pc⇣1_not_caught hp
    show ?thesis using ex_tab 0 by(simp add:handle_def matches_ex_entry_def)
  qed
  also have "P \<turnstile> … -jvm-> ?σ⇣1" using TryCatch⇣1 by auto
  finally have 1: "P \<turnstile> ?σ⇣0 -jvm-> ?σ⇣1" .
  let ?pc⇣2 = "?pc⇣1' + length(compE⇣2 e⇣2)"
  let ?I⇣2 = "{?pc⇣1' ..< ?pc⇣2}"
  have "P,C,M \<rhd> compxE⇣2 ?e pc (size vs) / I,size vs" by fact
  hence beforex⇣2: "P,C,M \<rhd> compxE⇣2 e⇣2 ?pc⇣1' (size vs) / ?I⇣2, size vs"
    using I pcs_subset[of _ ?pc⇣1'] by(auto elim!:beforex_appendD2)
  have IH⇣2: "PROP ?P e⇣2 h⇣1 ?ls⇣1 e⇣2' h⇣2 ls⇣2 C M ?pc⇣1' v xa vs frs ?I⇣2" by fact
  show ?case (is "?Norm ∧ ?Err")
  proof
    show ?Norm (is "?val --> ?trans")
    proof
      assume val: ?val
      note 1 also have "P \<turnstile> ?σ⇣1 -jvm-> (None,h⇣2,(v#vs,ls⇣2,C,M,?pc⇣2)#frs)"
        using val beforex⇣2 IH⇣2 TryCatch⇣1.prems by auto
      finally show ?trans by(simp add:add_assoc)
    qed
  next
    show ?Err (is "?throw --> (∃pc⇣2. ?H pc⇣2)")
    proof
      assume throw: ?throw
      then obtain pc⇣2 where
        pc⇣2: "?pc⇣1+2 ≤ pc⇣2 ∧ pc⇣2 < ?pc⇣2 ∧
              ¬ caught P pc⇣2 h⇣2 xa (compxE⇣2 e⇣2 ?pc⇣1' (size vs))" and
        2: "P \<turnstile> ?σ⇣1 -jvm-> handle P C M xa h⇣2 vs ls⇣2 pc⇣2 frs"
        using IH⇣2 beforex⇣2 TryCatch⇣1.prems by auto
      have "?H pc⇣2" using pc⇣2 jvm_trans[OF 1 2]
        by (simp add:match_ex_entry) (fastforce)
      thus "∃pc⇣2. ?H pc⇣2" by iprover
    qed
  qed
next
  case (TryThrow⇣1 e⇣1 h⇣0 ls⇣0 a h⇣1 ls⇣1 D fs Ci i e⇣2)
  let ?σ⇣0 = "(None,h⇣0,(vs,ls⇣0,C,M,pc)#frs)"
  let ?pc⇣1 = "pc + length(compE⇣2 e⇣1)"
  let ?e = "try e⇣1 catch(Ci i) e⇣2"
  let ?xt = "compxE⇣2 ?e pc (size vs)"
  have I: "{pc..<pc + length (compE⇣2 (try e⇣1 catch(Ci i) e⇣2))} ⊆ I"
   and beforex: "P,C,M \<rhd> ?xt/I,size vs" by fact+
  have "PROP ?P e⇣1 h⇣0 ls⇣0 (Throw a) h⇣1 ls⇣1 C M pc w a vs frs {pc..<pc + length (compE⇣2 e⇣1)}" by fact
  moreover have "P,C,M \<rhd> compxE⇣2 e⇣1 pc (size vs)/{pc..<?pc⇣1},size vs"
    using beforex I pcs_subset by(force elim!: beforex_appendD1)
    ultimately have
      "∃pc⇣1. pc ≤ pc⇣1 ∧ pc⇣1 < ?pc⇣1 ∧
             ¬ caught P pc⇣1 h⇣1 a (compxE⇣2 e⇣1 pc (size vs)) ∧
             P \<turnstile> ?σ⇣0 -jvm-> handle P C M a h⇣1 vs ls⇣1 pc⇣1 frs"
      using TryThrow⇣1.prems by auto
    then obtain pc⇣1 where
      pc⇣1_in_e⇣1: "pc ≤ pc⇣1" "pc⇣1 < ?pc⇣1" and
      pc⇣1_not_caught: "¬ caught P pc⇣1 h⇣1 a (compxE⇣2 e⇣1 pc (size vs))" and
      0: "P \<turnstile> ?σ⇣0 -jvm-> handle P C M a h⇣1 vs ls⇣1 pc⇣1 frs" by iprover
  show ?case (is "?N ∧ (?eq --> (∃pc⇣2. ?H pc⇣2))")
  proof
    show ?N by simp
  next
    { assume ?eq
      with TryThrow⇣1 pc⇣1_in_e⇣1 pc⇣1_not_caught 0
      have "?H pc⇣1" by (simp add:match_ex_entry) auto
      hence "∃pc⇣2. ?H pc⇣2" by iprover
    }
    thus "?eq --> (∃pc⇣2. ?H pc⇣2)" by iprover
  qed
next
  case Nil⇣1 thus ?case by simp
next
  case (Cons⇣1 e h⇣0 ls⇣0 v h⇣1 ls⇣1 es fs h⇣2 ls⇣2)
  let ?pc⇣1 = "pc + length(compE⇣2 e)"
  let ?σ⇣0 = "(None,h⇣0,(vs,ls⇣0,C,M,pc)#frs)"
  let ?σ⇣1 = "(None,h⇣1,(v#vs,ls⇣1,C,M,?pc⇣1)#frs)"
  have 1: "P \<turnstile> ?σ⇣0 -jvm-> ?σ⇣1" using Cons⇣1 by fastforce
  let ?pc⇣2 = "?pc⇣1 + length(compEs⇣2 es)"
  have IHs: "PROP ?Ps es h⇣1 ls⇣1 fs h⇣2 ls⇣2 C M ?pc⇣1 (tl ws) xa es' (v#vs) frs
    (I - pcs (compxE⇣2 e pc (length vs)))" by fact
  show ?case (is "?Norm ∧ ?Err")
  proof
    show ?Norm (is "?val --> ?trans")
    proof
      assume val: ?val
      note 1
      also have "P \<turnstile> ?σ⇣1 -jvm-> (None,h⇣2,(rev(ws) @ vs,ls⇣2,C,M,?pc⇣2)#frs)"
        using val IHs Cons⇣1.prems by fastforce
      finally show ?trans by(simp add:add_assoc)
    qed
  next
    show ?Err (is "?throw --> (∃pc⇣2. ?H pc⇣2)")
    proof
      assume throw: ?throw
      then obtain pc⇣2 where
        pc⇣2: "?pc⇣1 ≤ pc⇣2 ∧ pc⇣2 < ?pc⇣2 ∧
              ¬ caught P pc⇣2 h⇣2 xa (compxEs⇣2 es ?pc⇣1 (size vs + 1))" and
        2: "P \<turnstile> ?σ⇣1 -jvm-> handle P C M xa h⇣2 (v#vs) ls⇣2 pc⇣2 frs"
        using IHs Cons⇣1.prems
        by(fastforce simp:Cons_eq_append_conv neq_Nil_conv)
      have "?H pc⇣2" using Cons⇣1.prems pc⇣2 jvm_trans[OF 1 2]
        by (auto simp add: handle_Cons)
      thus "∃pc⇣2. ?H pc⇣2" by iprover
    qed
  qed
next
  case ConsThrow⇣1 thus ?case by (fastforce simp:Cons_eq_append_conv)
qed
lemma atLeast0AtMost[simp]: "{0::nat..n} = {..n}"
by auto
lemma atLeast0LessThan[simp]: "{0::nat..<n} = {..<n}"
by auto
fun exception :: "'a exp => addr option" where
  "exception (Throw a) = Some a"
| "exception e = None"
lemma comp⇣2_correct:
assumes method: "P⇣1 \<turnstile> C sees M:Ts->T = body in C"
    and eval:   "P⇣1 \<turnstile>⇩1 〈body,(h,ls)〉 => 〈e',(h',ls')〉"
shows "compP⇣2 P⇣1 \<turnstile> (None,h,[([],ls,C,M,0)]) -jvm-> (exception e',h',[])"
      (is "_ \<turnstile> ?σ⇣0 -jvm-> ?σ⇣1")
proof -
  let ?P = "compP⇣2 P⇣1"
  have code: "?P,C,M,0 \<rhd> compE⇣2 body" using beforeM[OF method] by auto
  have xtab: "?P,C,M \<rhd> compxE⇣2 body 0 (size[])/{..<size(compE⇣2 body)},size[]"
    using beforexM[OF method] by auto
  -- "Distinguish if e' is a value or an exception"
  { fix v assume [simp]: "e' = Val v"
    have "?P \<turnstile> ?σ⇣0 -jvm-> (None,h',[([v],ls',C,M,size(compE⇣2 body))])"
      using Jcc[OF eval code xtab] by auto
    also have "?P \<turnstile> … -jvm-> ?σ⇣1" using beforeM[OF method] by auto
    finally have ?thesis .
  }
  moreover
  { fix a assume [simp]: "e' = Throw a"
    obtain pc where pc: "0 ≤ pc ∧ pc < size(compE⇣2 body) ∧
          ¬ caught ?P pc h' a (compxE⇣2 body 0 0)"
    and 1: "?P \<turnstile> ?σ⇣0 -jvm-> handle ?P C M a h' [] ls' pc []"
      using Jcc[OF eval code xtab] by fastforce
    from pc have "handle ?P C M a h' [] ls' pc [] = ?σ⇣1" using xtab method
      by(auto simp:handle_def compMb⇣2_def)
    with 1 have ?thesis by simp
  } 
  ultimately show ?thesis using eval⇣1_final[OF eval] by(auto simp:final_def)
qed
end