Theory TypeComp

Up to index of Isabelle/HOL/Jinja

theory TypeComp = Compiler + BVSpec:

(*  Title:      Jinja/Compiler/TypeComp.thy
    ID:         $Id: TypeComp.html 1910 2004-05-19 04:46:04Z kleing $
    Author:     Tobias Nipkow
    Copyright   TUM 2003
*)

header {* \isaheader{Preservation of Well-Typedness} *}
(*
ML{*add_path"../JVM/";add_path"../BV/";add_path"../DFA/"*}
*)

theory TypeComp = Compiler + BVSpec:

(*<*)
declare nth_append[simp]
(*>*)

constdefs
  ty :: "J1_prog => ty list => expr1 => ty"
  "ty P E e  ≡  THE T. P,E \<turnstile>1 e :: T"

  tyl:: "nat => ty list => nat set => tyl"
  "tyl m E A' ≡ map (λi. if i ∈ A' ∧ i < size E then OK(E!i) else Err) [0..m(]"

  tyi' :: "nat => ty list => ty list => nat set option => tyi'"
  "tyi' m ST E A ≡ case A of None => None | ⌊A'⌋ => Some(ST, tyl m E A')"

  after :: "J1_prog => nat => ty list => nat set option => ty list => expr1 => tyi'"
  "after P m E A ST e  ≡ tyi' m (ty P E e # ST) E (A \<squnion> \<A> e)"

locale (open) TC0 =
  fixes P and mxl

  fixes ty :: "ty list => expr1 => ty"
  defines "ty E e ≡ TypeComp.ty P E e"

  fixes tyl:: "ty list => nat set => tyl"
  defines tyl: "tyl E A' ≡ TypeComp.tyl mxl E A'"

  fixes tyi' :: "ty list => ty list => nat set option => tyi'"
  defines tyi': "tyi' ST E A ≡ TypeComp.tyi' mxl ST E A"

  fixes after :: "ty list => nat set option => ty list => expr1 => tyi'"
  defines after: "after E A ST e ≡ TypeComp.after P mxl E A ST e"

  notes after_def = TypeComp.after_def [of P mxl, folded after ty_def tyi']
  notes tyi'_def = TypeComp.tyi'_def [of mxl, folded tyl tyi']
  notes tyl_def = TypeComp.tyl_def [of mxl, folded tyl]

lemma (in TC0) ty_def2 [simp]: "P,E \<turnstile>1 e :: T ==> ty E e = T"
(*<*)
apply(unfold ty_def TypeComp.ty_def)
apply(blast intro: the_equality WT1_unique)
done
(*>*)


lemma (in TC0) [simp]: "tyi' ST E None = None"
(*<*)by(simp add:tyi'_def)(*>*)


lemma (in TC0) tyl_app_diff[simp]:
 "tyl (E@[T]) (A - {size E}) = tyl E A"
(*<*)by(auto simp add:tyl_def hyperset_defs)(*>*)


lemma (in TC0) tyi'_app_diff[simp]:
 "tyi' ST (E @ [T]) (A \<ominus> size E) = tyi' ST E A"
(*<*)by(auto simp add:tyi'_def hyperset_defs)(*>*)


lemma (in TC0) tyl_antimono:
 "A ⊆ A' ==> P \<turnstile> tyl E A' [≤\<top>] tyl E A"
(*<*)by(auto simp:tyl_def list_all2_conv_all_nth)(*>*)


lemma (in TC0) tyi'_antimono:
 "A ⊆ A' ==> P \<turnstile> tyi' ST E ⌊A'⌋ ≤' tyi' ST E ⌊A⌋"
(*<*)by(auto simp:tyi'_def tyl_def list_all2_conv_all_nth)(*>*)


lemma (in TC0) tyl_env_antimono:
 "P \<turnstile> tyl (E@[T]) A [≤\<top>] tyl E A" 
(*<*)by(auto simp:tyl_def list_all2_conv_all_nth)(*>*)


lemma (in TC0) tyi'_env_antimono:
 "P \<turnstile> tyi' ST (E@[T]) A ≤' tyi' ST E A" 
(*<*)by(auto simp:tyi'_def tyl_def list_all2_conv_all_nth)(*>*)


lemma (in TC0) tyi'_incr:
 "P \<turnstile> tyi' ST (E @ [T]) ⌊insert (size E) A⌋ ≤' tyi' ST E ⌊A⌋"
(*<*)by(auto simp:tyi'_def tyl_def list_all2_conv_all_nth)(*>*)


lemma (in TC0) tyl_incr:
 "P \<turnstile> tyl (E @ [T]) (insert (size E) A) [≤\<top>] tyl E A"
(*<*)by(auto simp: hyperset_defs tyl_def list_all2_conv_all_nth)(*>*)


lemma (in TC0) tyl_in_types:
 "set E ⊆ types P ==> tyl E A ∈ list mxl (err (types P))"
(*<*)by(auto simp add:tyl_def intro!:listI dest!: nth_mem)(*>*)


consts
 compT :: "J1_prog => nat => ty list => nat hyperset => ty list => expr1 => tyi' list"
 compTs :: "J1_prog => nat => ty list => nat hyperset => ty list => expr1 list => tyi' list"

primrec
"compT P m E A ST (new C) = []"
"compT P m E A ST (Cast C e) =  
   compT P m E A ST e @ [after P m E A ST e]"
"compT P m E A ST (Val v) = []"
"compT P m E A ST (e1 «bop» e2) =
  (let ST1 = ty P E e1#ST; A1 = A \<squnion> \<A> e1 in
   compT P m E A ST e1 @ [after P m E A ST e1] @
   compT P m E A1 ST1 e2 @ [after P m E A1 ST1 e2])"
"compT P m E A ST (Var i) = []"
"compT P m E A ST (i := e) = compT P m E A ST e @
   [after P m E A ST e, tyi' m ST E (A \<squnion> \<A> e \<squnion> ⌊{i}⌋)]"
"compT P m E A ST (e\<bullet>F{D}) = 
   compT P m E A ST e @ [after P m E A ST e]"
"compT P m E A ST (e1\<bullet>F{D} := e2) =
  (let ST1 = ty P E e1#ST; A1 = A \<squnion> \<A> e1; A2 = A1 \<squnion> \<A> e2 in
   compT P m E A ST e1 @ [after P m E A ST e1] @
   compT P m E A1 ST1 e2 @ [after P m E A1 ST1 e2] @
   [tyi' m ST E A2])"
"compT P m E A ST {i:T; e} = compT P m (E@[T]) (A\<ominus>i) ST e"
"compT P m E A ST (e1;;e2) =
  (let A1 = A \<squnion> \<A> e1 in
   compT P m E A ST e1 @ [after P m E A ST e1, tyi' m ST E A1] @
   compT P m E A1 ST e2)"
"compT P m E A ST (if (e) e1 else e2) =
   (let A0 = A \<squnion> \<A> e; τ = tyi' m ST E A0 in
    compT P m E A ST e @ [after P m E A ST e, τ] @
    compT P m E A0 ST e1 @ [after P m E A0 ST e1, τ] @
    compT P m E A0 ST e2)"
"compT P m E A ST (while (e) c) =
   (let A0 = A \<squnion> \<A> e;  A1 = A0 \<squnion> \<A> c; τ = tyi' m ST E A0 in
    compT P m E A ST e @ [after P m E A ST e, τ] @
    compT P m E A0 ST c @ [after P m E A0 ST c, tyi' m ST E A1, tyi' m ST E A0])"
"compT P m E A ST (throw e) = compT P m E A ST e @ [after P m E A ST e]"
"compT P m E A ST (e\<bullet>M(es)) =
   compT P m E A ST e @ [after P m E A ST e] @
   compTs P m E (A \<squnion> \<A> e) (ty P E e # ST) es"
"compT P m E A ST (try e1 catch(C i) e2) =
   compT P m E A ST e1 @ [after P m E A ST e1] @
   [tyi' m (Class C#ST) E A, tyi' m ST (E@[Class C]) (A \<squnion> ⌊{i}⌋)] @
   compT P m (E@[Class C]) (A \<squnion> ⌊{i}⌋) ST e2"
"compTs P m E A ST [] = []"
"compTs P m E A ST (e#es) = compT P m E A ST e @ [after P m E A ST e] @
                            compTs P m E (A \<squnion> (\<A> e)) (ty P E e # ST) es"

constdefs
  compTa :: "J1_prog => nat => ty list => nat hyperset => ty list => expr1 => tyi' list"
  "compTa P mxl E A ST e ≡ compT P mxl E A ST e @ [after P mxl E A ST e]"

locale (open) TC1 = TC0 +
  fixes compT :: "ty list => nat hyperset => ty list => expr1 => tyi' list"
  defines compT: "compT E A ST e ≡ TypeComp.compT P mxl E A ST e"

  fixes compTs :: "ty list => nat hyperset => ty list => expr1 list => tyi' list"
  defines compTs: "compTs E A ST es ≡ TypeComp.compTs P mxl E A ST es"

  fixes compTa :: "ty list => nat hyperset => ty list => expr1 => tyi' list"
  defines compTa: "compTa E A ST e ≡ TypeComp.compTa P mxl E A ST e"

  notes compT_simps[simp] = TypeComp.compT_compTs.simps [of P mxl,
        folded compT compTs ty_def tyi' after]
  notes compTa_def = TypeComp.compTa_def[of P mxl,
        folded compTa compT after]

lemma compE2_not_Nil[simp]: "compE2 e ≠ []"
(*<*)by(induct e) auto(*>*)


lemma (in TC1) compT_sizes[simp]:
shows "!!E A ST. size(compT E A ST e) = size(compE2 e) - 1"
and "!!E A ST. size(compTs E A ST es) = size(compEs2 es)"
(*<*)
apply(induct e and es)
apply(auto split:bop.splits nat_diff_split)
done
(*>*)


lemma (in TC1) [simp]: "!!ST E. ⌊τ⌋ ∉ set (compT E None ST e)"
and [simp]: "!!ST E. ⌊τ⌋ ∉ set (compTs E None ST es)"
(*<*)by(induct e and es) (simp_all add:after_def)(*>*)


lemma (in TC0) pair_eq_tyi'_conv:
  "(⌊(ST, LT)⌋ = tyi' ST0 E A) =
  (case A of None => False | Some A => (ST = ST0 ∧ LT = tyl E A))"
(*<*)by(simp add:tyi'_def)(*>*)


lemma (in TC0) pair_conv_tyi':
  "⌊(ST, tyl E A)⌋ = tyi' ST E ⌊A⌋"
(*<*)by(simp add:tyi'_def)(*>*)

(*<*)
declare (in TC0)
  tyi'_antimono [intro!] after_def[simp]
  pair_conv_tyi'[simp] pair_eq_tyi'_conv[simp]
(*>*)


lemma (in TC1) compT_LT_prefix:
 "!!E A ST0. [| ⌊(ST,LT)⌋ ∈ set(compT E A ST0 e); \<B> e (size E) |]
               ==> P \<turnstile> ⌊(ST,LT)⌋ ≤' tyi' ST E A"
and
 "!!E A ST0. [| ⌊(ST,LT)⌋ ∈ set(compTs E A ST0 es); \<B>s es (size E) |]
               ==> P \<turnstile> ⌊(ST,LT)⌋ ≤' tyi' ST E A"
(*<*)
proof(induct e and es)
  case FAss thus ?case by(fastsimp simp:hyperset_defs elim!:sup_state_opt_trans)
next
  case BinOp thus ?case
    by(fastsimp simp:hyperset_defs elim!:sup_state_opt_trans split:bop.splits)
next
  case Seq thus ?case by(fastsimp simp:hyperset_defs elim!:sup_state_opt_trans)
next
  case While thus ?case by(fastsimp simp:hyperset_defs elim!:sup_state_opt_trans)
next
  case Cond thus ?case by(fastsimp simp:hyperset_defs elim!:sup_state_opt_trans)
next
  case Block thus ?case
    by(force simp add:hyperset_defs tyi'_def simp del:pair_conv_tyi'
             elim!:sup_state_opt_trans)
next
  case Call thus ?case by(fastsimp simp:hyperset_defs elim!:sup_state_opt_trans)
next
  case Cons_exp thus ?case
    by(fastsimp simp:hyperset_defs elim!:sup_state_opt_trans)
next
  case TryCatch thus ?case
    by(fastsimp simp:hyperset_defs intro!:(* tyi'_env_antimono *) tyi'_incr
                elim!:sup_state_opt_trans)
qed (auto simp:hyperset_defs)

declare (in TC0)
  tyi'_antimono [rule del] after_def[simp del]
  pair_conv_tyi'[simp del] pair_eq_tyi'_conv[simp del]
(*>*)


lemma [iff]: "OK None ∈ states P mxs mxl"
(*<*)by(simp add: JVM_states_unfold)(*>*)

lemma (in TC0) after_in_states:
 "[| wf_prog p P; P,E \<turnstile>1 e :: T; set E ⊆ types P; set ST ⊆ types P;
    size ST + max_stack e ≤ mxs |]
 ==> OK (after E A ST e) ∈ states P mxs mxl"
(*<*)
apply(subgoal_tac "size ST + 1 ≤ mxs")
 apply(simp add:after_def tyi'_def JVM_states_unfold tyl_in_types)
 apply(blast intro!:listI WT1_is_type)
using max_stack1[of e] apply simp
done
(*>*)


lemma (in TC0) OK_tyi'_in_statesI[simp]:
  "[| set E ⊆ types P; set ST ⊆ types P; size ST ≤ mxs |]
  ==> OK (tyi' ST E A) ∈ states P mxs mxl"
(*<*)
apply(simp add:tyi'_def JVM_states_unfold tyl_in_types)
apply(blast intro!:listI)
done
(*>*)


lemma is_class_type_aux: "is_class P C ==> is_type P (Class C)"
(*<*)by(simp)(*>*)

(*<*)
declare is_type_simps[simp del] subsetI[rule del]
(*>*)

theorem (in TC1) compT_states:
assumes wf: "wf_prog p P"
shows "!!E T A ST.
  [| P,E \<turnstile>1 e :: T; set E ⊆ types P; set ST ⊆ types P;
    size ST + max_stack e ≤ mxs; size E + max_vars e ≤ mxl |]
  ==> OK ` set(compT E A ST e) ⊆ states P mxs mxl"
(*<*)(is "!!E T A ST. PROP ?P e E T A ST")(*>*)

and "!!E Ts A ST.
  [| P,E \<turnstile>1 es[::]Ts;  set E ⊆ types P; set ST ⊆ types P;
    size ST + max_stacks es ≤ mxs; size E + max_varss es ≤ mxl |]
  ==> OK ` set(compTs E A ST es) ⊆ states P mxs mxl"
(*<*)(is "!!E Ts A ST. PROP ?Ps es E Ts A ST")
proof(induct e and es)
  case new thus ?case by(simp)
next
  case (Cast C e) thus ?case by (auto simp:after_in_states[OF wf])
next
  case Val thus  ?case by(simp)
next
  case Var thus ?case by(simp)
next
  case LAss thus ?case  by(auto simp:after_in_states[OF wf])
next
  case FAcc thus ?case by(auto simp:after_in_states[OF wf])
next
  case FAss thus ?case
    by(auto simp:image_Un WT1_is_type[OF wf] after_in_states[OF wf])
next
  case Seq thus ?case
    by(auto simp:image_Un after_in_states[OF wf])
next
  case BinOp thus ?case
    by(auto simp:image_Un WT1_is_type[OF wf] after_in_states[OF wf])
next
  case Cond thus ?case
    by(force simp:image_Un WT1_is_type[OF wf] after_in_states[OF wf])
next
  case While thus ?case
    by(auto simp:image_Un WT1_is_type[OF wf] after_in_states[OF wf])
next
  case Block thus ?case by(auto)
next
  case (TryCatch e1 C i e2)
  moreover have "size ST + 1 ≤ mxs" using TryCatch.prems max_stack1[of e1] by auto
  ultimately show ?case  
    by(auto simp:image_Un WT1_is_type[OF wf] after_in_states[OF wf]
                  is_class_type_aux)
next
  case Nil_exp thus ?case by simp
next
  case Cons_exp thus ?case
    by(auto simp:image_Un  WT1_is_type[OF wf] after_in_states[OF wf])
next
  case throw thus ?case
    by(auto simp: WT1_is_type[OF wf] after_in_states[OF wf])
next
  case Call thus ?case
    by(auto simp:image_Un WT1_is_type[OF wf] after_in_states[OF wf])
qed

declare is_type_simps[simp] subsetI[intro!]
(*>*)


constdefs
  shift :: "nat => ex_table => ex_table"
  "shift n xt ≡ map (λ(from,to,C,handler,depth). (from+n,to+n,C,handler+n,depth)) xt"


lemma [simp]: "shift 0 xt = xt"
(*<*)by(induct xt)(auto simp:shift_def)(*>*)

lemma [simp]: "shift n [] = []"
(*<*)by(simp add:shift_def)(*>*)

lemma [simp]: "shift n (xt1 @ xt2) = shift n xt1 @ shift n xt2"
(*<*)by(simp add:shift_def)(*>*)

lemma [simp]: "shift m (shift n xt) = shift (m+n) xt"
(*<*)by(induct xt)(auto simp:shift_def)(*>*)

lemma [simp]: "pcs (shift n xt) = {pc+n|pc. pc ∈ pcs xt}"
(*<*)
apply(auto simp:shift_def pcs_def)
apply(rule_tac x = "x-n" in exI)
apply (force split:nat_diff_split)
done
(*>*)


lemma shift_compxE2:
shows "!!pc pc' d. shift pc (compxE2 e pc' d) = compxE2 e (pc' + pc) d"
and  "!!pc pc' d. shift pc (compxEs2 es pc' d) = compxEs2 es (pc' + pc) d"
(*<*)
apply(induct e and es)
apply(auto simp:shift_def add_ac)
done
(*>*)


lemma compxE2_size_convs[simp]:
shows "n ≠ 0 ==> compxE2 e n d = shift n (compxE2 e 0 d)"
and "n ≠ 0 ==> compxEs2 es n d = shift n (compxEs2 es 0 d)"
(*<*)by(simp_all add:shift_compxE2)(*>*)


constdefs
  wt_instrs :: "'m prog => ty => pc => instr list => ex_table => tyi' list => bool"
  ("(_,_,_ \<turnstile>/ _, _ /[::]/ _)" [50,50,50,50,50,51] 50)
  "P,T,mxs \<turnstile> is,xt [::] τs ≡
  size is < size τs ∧ pcs xt ⊆ {0..size is(} ∧
  (∀pc< size is. P,T,mxs,size τs,xt \<turnstile> is!pc,pc :: τs)"

locale (open) TC2 = TC1 +
  fixes Tr and mxs
  fixes wt_instrs :: "instr list => ex_table => tyi' list => bool"
                     ("(\<turnstile> _, _ /[::]/ _)" [0,0,51] 50)
  defines wt_instrs: "\<turnstile> is,xt [::] τs ≡ P,Tr,mxs \<turnstile> is,xt [::] τs"

  notes wt_instrs_def = TypeComp.wt_instrs_def[of P Tr mxs, folded wt_instrs]

(*<*)
lemmas (in TC2) wt_defs =
  wt_instrs_def wt_instr_def app_def eff_def norm_eff_def
(*>*)


lemma (in TC2) [simp]: "τs ≠ [] ==> \<turnstile> [],[] [::] τs"
(*<*)by(simp add:wt_defs)(*>*)


lemma [simp]: "eff i P pc et None = []"
(*<*)by (simp add: Effect.eff_def)(*>*)

(*<*)
declare split_comp_eq[simp del]
(*>*)

lemma wt_instr_appR:
 "[| P,T,m,mpc,xt \<turnstile> is!pc,pc :: τs;
    pc < size is; size is < size τs; mpc ≤ size τs; mpc ≤ mpc' |]
  ==> P,T,m,mpc',xt \<turnstile> is!pc,pc :: τs@τs'"
(*<*)by (fastsimp simp:wt_instr_def app_def)(*>*)


lemma relevant_entries_shift [simp]:
  "relevant_entries P i (pc+n) (shift n xt) = shift n (relevant_entries P i pc xt)"
(*<*)
  apply (induct xt)
  apply (unfold relevant_entries_def shift_def) 
   apply simp
  apply (auto simp add: is_relevant_entry_def)
  done
(*>*)


lemma [simp]:
  "xcpt_eff i P (pc+n) τ (shift n xt) =
   map (λ(pc,τ). (pc + n, τ)) (xcpt_eff i P pc τ xt)"
(*<*)
apply(simp add: xcpt_eff_def)
apply(cases τ)
apply(auto simp add: shift_def map_compose [symmetric])
done
(*>*)


lemma  [simp]:
  "appi (i, P, pc, m, T, τ) ==>
   eff i P (pc+n) (shift n xt) (Some τ) =
   map (λ(pc,τ). (pc+n,τ)) (eff i P pc xt (Some τ))"
(*<*)
apply(simp add:eff_def norm_eff_def)
apply(cases "i",auto)
apply arith
apply arith
done
(*>*)


lemma [simp]:
  "xcpt_app i P (pc+n) mxs (shift n xt) τ = xcpt_app i P pc mxs xt τ"
(*<*)by (simp add: xcpt_app_def) (auto simp add: shift_def)(*>*)


lemma wt_instr_appL:
  "[| P,T,m,mpc,xt \<turnstile> i,pc :: τs; pc < size τs; mpc ≤ size τs |]
  ==> P,T,m,mpc + size τs',shift (size τs') xt \<turnstile> i,pc+size τs' :: τs'@τs"
(*<*)
apply(auto simp:wt_instr_def app_def)
prefer 2 apply(fast)
prefer 2 apply(fast)
apply(cases "i",auto)
done
(*>*)


lemma wt_instr_Cons:
  "[| P,T,m,mpc - 1,[] \<turnstile> i,pc - 1 :: τs;
     0 < pc; 0 < mpc; pc < size τs + 1; mpc ≤ size τs + 1 |]
  ==> P,T,m,mpc,[] \<turnstile> i,pc :: τ#τs"
(*<*)
apply(drule wt_instr_appL[where τs' = "[τ]"])
apply arith
apply arith
apply (simp split:nat_diff_split_asm)
done
(*>*)


lemma wt_instr_append:
  "[| P,T,m,mpc - size τs',[] \<turnstile> i,pc - size τs' :: τs;
     size τs' ≤ pc; size τs' ≤ mpc; pc < size τs + size τs'; mpc ≤ size τs + size τs' |]
  ==> P,T,m,mpc,[] \<turnstile> i,pc :: τs'@τs"
(*<*)
apply(drule wt_instr_appL[where τs' = τs'])
apply arith
apply arith
apply (simp split:nat_diff_split_asm)
done
(*>*)


lemma xcpt_app_pcs:
  "pc ∉ pcs xt ==> xcpt_app i P pc mxs xt τ"
(*<*)
by (auto simp add: xcpt_app_def relevant_entries_def is_relevant_entry_def pcs_def)
(*>*)


lemma xcpt_eff_pcs:
  "pc ∉ pcs xt ==> xcpt_eff i P pc τ xt = []"
(*<*)
by (cases τ)
   (auto simp add: is_relevant_entry_def xcpt_eff_def relevant_entries_def pcs_def
           intro!: filter_False)
(*>*)


lemma pcs_shift:
  "pc < n ==> pc ∉ pcs (shift n xt)" 
(*<*)by (auto simp add: shift_def pcs_def)(*>*)


lemma wt_instr_appRx:
  "[| P,T,m,mpc,xt \<turnstile> is!pc,pc :: τs; pc < size is; size is < size τs; mpc ≤ size τs |]
  ==> P,T,m,mpc,xt @ shift (size is) xt' \<turnstile> is!pc,pc :: τs"
(*<*)by (auto simp:wt_instr_def eff_def app_def xcpt_app_pcs xcpt_eff_pcs)(*>*)


lemma wt_instr_appLx: 
  "[| P,T,m,mpc,xt \<turnstile> i,pc :: τs; pc ∉ pcs xt' |]
  ==> P,T,m,mpc,xt'@xt \<turnstile> i,pc :: τs"
(*<*)by (auto simp:wt_instr_def app_def eff_def xcpt_app_pcs xcpt_eff_pcs)(*>*)


lemma (in TC2) wt_instrs_extR:
  "\<turnstile> is,xt [::] τs ==> \<turnstile> is,xt [::] τs @ τs'"
(*<*)by(auto simp add:wt_instrs_def wt_instr_appR)(*>*)


lemma (in TC2) wt_instrs_ext:
  "[| \<turnstile> is1,xt1 [::] τs1@τs2; \<turnstile> is2,xt2 [::] τs2; size τs1 = size is1 |]
  ==> \<turnstile> is1@is2, xt1 @ shift (size is1) xt2 [::] τs1@τs2"
(*<*)
apply(clarsimp simp:wt_instrs_def)
apply(rule conjI, fastsimp)
apply(rule conjI, fastsimp)
apply clarsimp
apply(rule conjI, fastsimp simp:wt_instr_appRx)
apply clarsimp
apply(erule_tac x = "pc - size is1" in allE)+
apply(erule impE,arith)
apply(drule_tac τs' = "τs1" in wt_instr_appL)
  apply arith
 apply simp
apply(fastsimp simp add:add_commute intro!: wt_instr_appLx)
done
(*>*)

corollary (in TC2) wt_instrs_ext2:
  "[| \<turnstile> is2,xt2 [::] τs2; \<turnstile> is1,xt1 [::] τs1@τs2; size τs1 = size is1 |]
  ==> \<turnstile> is1@is2, xt1 @ shift (size is1) xt2 [::] τs1@τs2"
(*<*)by(rule wt_instrs_ext)(*>*)


corollary (in TC2) wt_instrs_ext_prefix [trans]:
  "[| \<turnstile> is1,xt1 [::] τs1@τs2; \<turnstile> is2,xt2 [::] τs3;
     size τs1 = size is1; τs3 ≤ τs2 |]
  ==> \<turnstile> is1@is2, xt1 @ shift (size is1) xt2 [::] τs1@τs2"
(*<*)by(bestsimp simp:prefix_def elim: wt_instrs_ext dest:wt_instrs_extR)(*>*)


corollary (in TC2) wt_instrs_app:
  assumes is1: "\<turnstile> is1,xt1 [::] τs1@[τ]"
  assumes is2: "\<turnstile> is2,xt2 [::] τ#τs2"
  assumes s: "size τs1 = size is1"
  shows "\<turnstile> is1@is2, xt1@shift (size is1) xt2 [::] τs1@τ#τs2"
(*<*)
proof -
  from is1 have "\<turnstile> is1,xt1 [::] (τs1@[τ])@τs2"
    by (rule wt_instrs_extR)
  hence "\<turnstile> is1,xt1 [::] τs1@τ#τs2" by simp
  from this is2 s show ?thesis by (rule wt_instrs_ext) 
qed
(*>*)


corollary (in TC2) wt_instrs_app_last[trans]:
  "[| \<turnstile> is2,xt2 [::] τ#τs2; \<turnstile> is1,xt1 [::] τs1;
     last τs1 = τ;  size τs1 = size is1+1 |]
  ==> \<turnstile> is1@is2, xt1@shift (size is1) xt2 [::] τs1@τs2"
(*<*)
apply(cases τs1 rule:rev_cases)
 apply simp
apply(simp add:wt_instrs_app)
done
(*>*)


corollary (in TC2) wt_instrs_append_last[trans]:
  "[| \<turnstile> is,xt [::] τs; P,Tr,mxs,mpc,[] \<turnstile> i,pc :: τs;
     pc = size is; mpc = size τs; size is + 1 < size τs |]
  ==> \<turnstile> is@[i],xt [::] τs"
(*<*)
apply(clarsimp simp add:wt_instrs_def)
apply(rule conjI, fastsimp)
apply(fastsimp intro!:wt_instr_appLx[where xt = "[]",simplified]
               dest!:less_antisym)
done
(*>*)


(*<*)
ML_setup {* simpset_ref() := simpset() delloop "split_all_tac" *}
(*>*)


corollary (in TC2) wt_instrs_app2:
  "[| \<turnstile> is2,xt2 [::] τ'#τs2;  \<turnstile> is1,xt1 [::] τ#τs1@[τ'];
     xt' = xt1 @ shift (size is1) xt2;  size τs1+1 = size is1 |]
  ==> \<turnstile> is1@is2,xt' [::] τ#τs1@τ'#τs2"
(*<*)using wt_instrs_app[where ?τs1.0 = "τ # τs1"] by simp (*>*)


corollary (in TC2) wt_instrs_app2_simp[trans,simp]:
  "[| \<turnstile> is2,xt2 [::] τ'#τs2;  \<turnstile> is1,xt1 [::] τ#τs1@[τ']; size τs1+1 = size is1 |]
  ==> \<turnstile> is1@is2, xt1@shift (size is1) xt2 [::] τ#τs1@τ'#τs2"
(*<*)using wt_instrs_app[where ?τs1.0 = "τ # τs1"] by simp(*>*)


corollary (in TC2) wt_instrs_Cons[simp]:
  "[| τs ≠ []; \<turnstile> [i],[] [::] [τ,τ']; \<turnstile> is,xt [::] τ'#τs |]
  ==> \<turnstile> i#is,shift 1 xt [::] τ#τ'#τs"
(*<*)
using wt_instrs_app2[where ?is1.0 = "[i]" and ?τs1.0 = "[]" and ?is2.0 = "is"
                      and ?xt1.0 = "[]"]
by simp

ML_setup
  {*simpset_ref() := simpset() addloop ("split_all_tac", split_all_tac)*}
(*>*)


corollary (in TC2) wt_instrs_Cons2[trans]:
  assumes τs: "\<turnstile> is,xt [::] τs"
  assumes i: "P,Tr,mxs,mpc,[] \<turnstile> i,0 :: τ#τs"
  assumes mpc: "mpc = size τs + 1"
  shows "\<turnstile> i#is,shift 1 xt [::] τ#τs"
(*<*)
proof -
  from τs have "τs ≠ []" by (auto simp: wt_instrs_def)
  with mpc i have "\<turnstile> [i],[] [::] [τ]@τs" by (simp add: wt_instrs_def)
  with τs show ?thesis by (fastsimp dest: wt_instrs_ext)
qed
(*>*)


lemma (in TC2) wt_instrs_last_incr[trans]:
  "[| \<turnstile> is,xt [::] τs@[τ]; P \<turnstile> τ ≤' τ' |] ==> \<turnstile> is,xt [::] τs@[τ']"
(*<*)
apply(clarsimp simp add:wt_instrs_def wt_instr_def)
apply(rule conjI)
apply(fastsimp)
apply(clarsimp)
apply(rename_tac pc' tau')
apply(erule allE, erule (1) impE)
apply(clarsimp)
apply(drule (1) bspec)
apply(clarsimp)
apply(subgoal_tac "pc' = size τs")
prefer 2
apply(clarsimp simp:app_def)
apply(drule (1) bspec)
apply(clarsimp)
apply(auto elim!:sup_state_opt_trans)
done
(*>*)


lemma [iff]: "xcpt_app i P pc mxs [] τ"
(*<*)by (simp add: xcpt_app_def relevant_entries_def)(*>*)


lemma [simp]: "xcpt_eff i P pc τ [] = []"
(*<*)by (simp add: xcpt_eff_def relevant_entries_def)(*>*)


lemma (in TC2) wt_New:
  "[| is_class P C; size ST < mxs |] ==>
   \<turnstile> [New C],[] [::] [tyi' ST E A, tyi' (Class C#ST) E A]"
(*<*)by(simp add:wt_defs tyi'_def)(*>*)


lemma (in TC2) wt_Cast:
  "is_class P C ==>
   \<turnstile> [Checkcast C],[] [::] [tyi' (Class D # ST) E A, tyi' (Class C # ST) E A]"
(*<*)by(simp add: tyi'_def wt_defs)(*>*)


lemma (in TC2) wt_Push:
  "[| size ST < mxs; typeof v = Some T |]
  ==> \<turnstile> [Push v],[] [::] [tyi' ST E A, tyi' (T#ST) E A]"
(*<*)by(simp add: tyi'_def wt_defs)(*>*)


lemma (in TC2) wt_Pop:
 "\<turnstile> [Pop],[] [::] (tyi' (T#ST) E A # tyi' ST E A # τs)"
(*<*)by(simp add: tyi'_def wt_defs)(*>*)


lemma (in TC2) wt_CmpEq:
  "[| P \<turnstile> T1 ≤ T2 ∨ P \<turnstile> T2 ≤ T1|]
  ==> \<turnstile> [CmpEq],[] [::] [tyi' (T2 # T1 # ST) E A, tyi' (Boolean # ST) E A]"
(*<*) by(auto simp:tyi'_def wt_defs elim!: refTE not_refTE) (*>*)


lemma (in TC2) wt_IAdd:
  "\<turnstile> [IAdd],[] [::] [tyi' (Integer#Integer#ST) E A, tyi' (Integer#ST) E A]"
(*<*)by(simp add:tyi'_def wt_defs)(*>*)


lemma (in TC2) wt_Load:
  "[| size ST < mxs; size E ≤ mxl; i ∈∈ A; i < size E |]
  ==> \<turnstile> [Load i],[] [::] [tyi' ST E A, tyi' (E!i # ST) E A]"
(*<*)by(auto simp add:tyi'_def wt_defs tyl_def hyperset_defs)(*>*)


lemma (in TC2) wt_Store:
 "[| P \<turnstile> T ≤ E!i; i < size E; size E ≤ mxl |] ==>
  \<turnstile> [Store i],[] [::] [tyi' (T#ST) E A, tyi' ST E (⌊{i}⌋ \<squnion> A)]"
(*<*)
by(auto simp:hyperset_defs nth_list_update tyi'_def wt_defs tyl_def
        intro:list_all2_all_nthI)
(*>*)


lemma (in TC2) wt_Get:
 "[| P \<turnstile> C sees F:T in D |] ==>
  \<turnstile> [Getfield F D],[] [::] [tyi' (Class C # ST) E A, tyi' (T # ST) E A]"
(*<*)by(auto simp: tyi'_def wt_defs dest: sees_field_idemp sees_field_decl_above)(*>*)


lemma (in TC2) wt_Put:
  "[| P \<turnstile> C sees F:T in D; P \<turnstile> T' ≤ T |] ==>
  \<turnstile> [Putfield F D],[] [::] [tyi' (T' # Class C # ST) E A, tyi' ST E A]"
(*<*)by(auto intro: sees_field_idemp sees_field_decl_above simp: tyi'_def wt_defs)(*>*)


lemma (in TC2) wt_Throw:
  "\<turnstile> [Throw],[] [::] [tyi' (Class C # ST) E A, τ']"
(*<*)by(auto simp: tyi'_def wt_defs)(*>*)


lemma (in TC2) wt_IfFalse:
  "[| 2 ≤ i; nat i < size τs + 2; P \<turnstile> tyi' ST E A ≤' τs ! nat(i - 2) |]
  ==> \<turnstile> [IfFalse i],[] [::] tyi' (Boolean # ST) E A # tyi' ST E A # τs"
(*<*)
apply(clarsimp simp add: tyi'_def wt_defs)
apply(auto simp add: nth_Cons split:nat.split)
apply arith
apply(simp add:nat_diff_distrib)
done
(*>*)


lemma wt_Goto:
 "[| 0 ≤ int pc + i; nat (int pc + i) < size τs; size τs ≤ mpc;
    P \<turnstile> τs!pc ≤' τs ! nat (int pc + i) |]
 ==> P,T,mxs,mpc,[] \<turnstile> Goto i,pc :: τs"
(*<*)by(clarsimp simp add: TC2.wt_defs)(*>*)


lemma (in TC2) wt_Invoke:
  "[| size es = size Ts'; P \<turnstile> C sees M: Ts->T = m in D; P \<turnstile> Ts' [≤] Ts |]
  ==> \<turnstile> [Invoke M (size es)],[] [::] [tyi' (rev Ts' @ Class C # ST) E A, tyi' (T#ST) E A]"
(*<*)by(fastsimp simp add: tyi'_def wt_defs)(*>*)

(*<*)
ML_setup {* simpset_ref() := simpset() delloop "split_all_tac"*}
(*>*)


corollary (in TC2) wt_instrs_app3[simp]:
  "[| \<turnstile> is2,[] [::] (τ' # τs2);  \<turnstile> is1,xt1 [::] τ # τs1 @ [τ']; size τs1+1 = size is1|]
  ==> \<turnstile> (is1 @ is2),xt1 [::] τ # τs1 @ τ' # τs2"
(*<*)using wt_instrs_app2[where ?xt2.0 = "[]"] by (simp add:shift_def)(*>*)


corollary (in TC2) wt_instrs_Cons3[simp]:
  "[| τs ≠ []; \<turnstile> [i],[] [::] [τ,τ']; \<turnstile> is,[] [::] τ'#τs |]
  ==> \<turnstile> (i # is),[] [::] τ # τ' # τs"
(*<*)
using wt_instrs_Cons[where ?xt = "[]"]
by (simp add:shift_def)

ML_setup
  {* simpset_ref() := simpset() addloop ("split_all_tac", split_all_tac) *}
(*>*)

(*<*)
declare nth_append[simp del]
(*>*)

lemma (in TC2) wt_instrs_xapp[trans]:
  "[| \<turnstile> is1 @ is2, xt [::] τs1 @ tyi' (Class C # ST) E A # τs2;
     ∀τ ∈ set τs1. ∀ST' LT'. τ = Some(ST',LT') --> 
      size ST ≤ size ST' ∧ P \<turnstile> Some (drop (size ST' - size ST) ST',LT') ≤' tyi' ST E A;
     size is1 = size τs1; is_class P C; size ST < mxs  |] ==>
  \<turnstile> is1 @ is2, xt @ [(0,size is1 - 1,C,size is1,size ST)] [::] τs1 @ tyi' (Class C # ST) E A # τs2"
(*<*)
apply(simp add:wt_instrs_def)
apply(rule conjI)
 apply(clarsimp)
 apply arith
apply clarsimp
apply(erule allE, erule (1) impE)
apply(clarsimp simp add: wt_instr_def app_def eff_def)
apply(rule conjI)
 apply (thin_tac "∀x∈ ?A ∪ ?B. ?P x")
 apply (thin_tac "∀x∈ ?A ∪ ?B. ?P x")
 apply (clarsimp simp add: xcpt_app_def relevant_entries_def)
 apply (simp add: nth_append is_relevant_entry_def split: split_if_asm)
  apply (drule_tac x="τs1!pc" in bspec)
   apply (blast intro: nth_mem) 
  apply fastsimp   
 apply arith
apply (rule conjI)
 apply clarsimp
 apply (erule disjE, blast)
 apply (erule disjE, blast)
 apply (clarsimp simp add: xcpt_eff_def relevant_entries_def split: split_if_asm)
apply clarsimp
apply (erule disjE, blast)
apply (erule disjE, blast)
apply (clarsimp simp add: xcpt_eff_def relevant_entries_def split: split_if_asm)
apply (simp add: nth_append is_relevant_entry_def split: split_if_asm)
 apply (drule_tac x = "τs1!pc" in bspec)
  apply (blast intro: nth_mem) 
 apply (fastsimp simp add: tyi'_def)
apply arith
done

declare nth_append[simp]
(*>*)

lemma drop_Cons_Suc:
  "!!xs. drop n xs = y#ys ==> drop (Suc n) xs = ys"
  apply (induct n)
   apply simp
  apply (simp add: drop_Suc)
  done

lemma drop_mess:
  "[|Suc (length xs0) ≤ length xs; drop (length xs - Suc (length xs0)) xs = x # xs0|] 
  ==> drop (length xs - length xs0) xs = xs0"
apply (cases xs)
 apply simp
apply (simp add: Suc_diff_le)
apply (case_tac "length list - length xs0")
 apply simp
apply (simp add: drop_Cons_Suc)
done

(*<*)
declare (in TC0)
  after_def[simp] pair_eq_tyi'_conv[simp]
(*>*)

lemma (in TC1) compT_ST_prefix:
 "!!E A ST0. ⌊(ST,LT)⌋ ∈ set(compT E A ST0 e) ==> 
  size ST0 ≤ size ST ∧ drop (size ST - size ST0) ST = ST0"
and
 "!!E A ST0. ⌊(ST,LT)⌋ ∈ set(compTs E A ST0 es) ==> 
  size ST0 ≤ size ST ∧ drop (size ST - size ST0) ST = ST0"
(*<*)
proof(induct e and es)
  case (FAss e1 F D e2)
  moreover {
    let ?ST0 = "ty E e1 # ST0"
    fix A assume "⌊(ST, LT)⌋ ∈ set (compT E A ?ST0 e2)"
    with FAss
    have "length ?ST0 ≤ length ST ∧ drop (size ST - size ?ST0) ST = ?ST0" by blast
    hence ?case  by (clarsimp simp add: drop_mess)
  }
  ultimately show ?case by auto
next
  case TryCatch thus ?case by auto
next
  case Block thus ?case by auto
next
  case Seq thus ?case by auto
next
  case While thus ?case by auto
next
  case Cond thus ?case by auto
next
  case (Call e M es)
  moreover {
    let ?ST0 = "ty E e # ST0"
    fix A assume "⌊(ST, LT)⌋ ∈ set (compTs E A ?ST0 es)"
    with Call
    have "length ?ST0 ≤ length ST ∧ drop (size ST - size ?ST0) ST = ?ST0" by blast
    hence ?case  by (clarsimp simp add: drop_mess)
  }
  ultimately show ?case by auto
next
  case (Cons_exp e es)
  moreover {
    let ?ST0 = "ty E e # ST0"
    fix A assume "⌊(ST, LT)⌋ ∈ set (compTs E A ?ST0 es)"
    with Cons_exp
    have "length ?ST0 ≤ length ST ∧ drop (size ST - size ?ST0) ST = ?ST0" by blast
    hence ?case  by (clarsimp simp add: drop_mess)
  }
  ultimately show ?case by auto
next
  case (BinOp e1 bop e2)
  moreover {
    let ?ST0 = "ty E e1 # ST0"
    fix A assume "⌊(ST, LT)⌋ ∈ set (compT E A ?ST0 e2)"
    with BinOp 
    have "length ?ST0 ≤ length ST ∧ drop (size ST - size ?ST0) ST = ?ST0" by blast
    hence ?case by (clarsimp simp add: drop_mess)
  }
  ultimately show ?case by auto
next
  case new thus ?case by auto
next
  case Val thus ?case by auto    
next
  case Cast thus ?case by auto
next
  case Var thus ?case by auto
next
  case LAss thus ?case by auto
next
  case throw thus ?case by auto
next
  case FAcc thus ?case by auto
next
  case Nil_exp thus ?case by auto
qed 

declare (in TC0) 
  after_def[simp del] pair_eq_tyi'_conv[simp del]
(*>*)

(* FIXME *)
lemma fun_of_simp [simp]: "fun_of S x y = ((x,y) ∈ S)" 
(*<*) by (simp add: fun_of_def)(*>*)

theorem (in TC2) compT_wt_instrs: "!!E T A ST.
  [| P,E \<turnstile>1 e :: T; \<D> e A; \<B> e (size E); 
    size ST + max_stack e ≤ mxs; size E + max_vars e ≤ mxl |]
  ==> \<turnstile> compE2 e, compxE2 e 0 (size ST) [::]
                 tyi' ST E A # compT E A ST e @ [after E A ST e]"
(*<*)(is "!!E T A ST. PROP ?P e E T A ST")(*>*)

and "!!E Ts A ST.
  [| P,E \<turnstile>1 es[::]Ts;  \<D>s es A; \<B>s es (size E); 
    size ST + max_stacks es ≤ mxs; size E + max_varss es ≤ mxl |]
  ==> let τs = tyi' ST E A # compTs E A ST es in
       \<turnstile> compEs2 es,compxEs2 es 0 (size ST) [::] τs ∧
       last τs = tyi' (rev Ts @ ST) E (A \<squnion> \<A>s es)"
(*<*)
(is "!!E Ts A ST. PROP ?Ps es E Ts A ST")
proof(induct e and es)
  case (TryCatch e1 C i e2)
  hence [simp]: "i = size E" by simp
  have wt1: "P,E \<turnstile>1 e1 :: T" and wt2: "P,E@[Class C] \<turnstile>1 e2 :: T"
    and class: "is_class P C" using TryCatch by auto
  let ?A1 = "A \<squnion> \<A> e1" let ?Ai = "A \<squnion> ⌊{i}⌋" let ?Ei = "E @ [Class C]"
  let ?τ = "tyi' ST E A" let ?τs1 = "compT E A ST e1"
  let ?τ1 = "tyi' (T#ST) E ?A1" let ?τ2 = "tyi' (Class C#ST) E A"
  let ?τ3 = "tyi' ST ?Ei ?Ai" let ?τs2 = "compT ?Ei ?Ai ST e2"
  let ?τ2' = "tyi' (T#ST) ?Ei (?Ai \<squnion> \<A> e2)"
  let ?τ' = "tyi' (T#ST) E (A \<squnion> \<A> e1 \<sqinter> (\<A> e2 \<ominus> i))"
  let ?go = "Goto (int(size(compE2 e2)) + 2)"
  have "PROP ?P e2 ?Ei T ?Ai ST".
  hence "\<turnstile> compE2 e2,compxE2 e2 0 (size ST) [::] (?τ3 # ?τs2) @ [?τ2']"
    using TryCatch.prems by(auto simp:after_def)
  also have "?Ai \<squnion> \<A> e2 = (A \<squnion> \<A> e2) \<squnion> ⌊{size E}⌋"
    by(fastsimp simp:hyperset_defs)
  also have "P \<turnstile> tyi' (T#ST) ?Ei … ≤' tyi' (T#ST) E (A \<squnion> \<A> e2)"
    by(simp add:hyperset_defs tyl_incr tyi'_def)
  also have "P \<turnstile> … ≤' tyi' (T#ST) E (A \<squnion> \<A> e1 \<sqinter> (\<A> e2 \<ominus> i))"
    by(auto intro!: tyl_antimono simp:hyperset_defs tyi'_def)
  also have "(?τ3 # ?τs2) @ [?τ'] = ?τ3 # ?τs2 @ [?τ']" by simp
  also have "\<turnstile> [Store i],[] [::] ?τ2 # [] @ [?τ3]"
    using TryCatch.prems
    by(auto simp:nth_list_update wt_defs tyi'_def tyl_def
      list_all2_conv_all_nth hyperset_defs)
  also have "[] @ (?τ3 # ?τs2 @ [?τ']) = (?τ3 # ?τs2 @ [?τ'])" by simp
  also have "P,Tr,mxs,size(compE2 e2)+3,[] \<turnstile> ?go,0 :: ?τ1#?τ2#?τ3#?τs2 @ [?τ']"
    by (auto simp: hyperset_defs tyi'_def wt_defs nth_Cons nat_add_distrib
      fun_of_def intro: tyl_antimono list_all2_refl split:nat.split)
  also have "\<turnstile> compE2 e1,compxE2 e1 0 (size ST) [::] ?τ # ?τs1 @ [?τ1]"
    using TryCatch by(auto simp:after_def)
  also have "?τ # ?τs1 @ ?τ1 # ?τ2 # ?τ3 # ?τs2 @ [?τ'] =
             (?τ # ?τs1 @ [?τ1]) @ ?τ2 # ?τ3 # ?τs2 @ [?τ']" by simp
  also have "compE2 e1 @ ?go  # [Store i] @ compE2 e2 =
             (compE2 e1 @ [?go]) @ (Store i # compE2 e2)" by simp
  also 
  let "?Q τ" = "∀ST' LT'. τ = ⌊(ST', LT')⌋ --> 
    size ST ≤ size ST' ∧ P \<turnstile> Some (drop (size ST' - size ST) ST',LT') ≤' tyi' ST E A"
  {
    have "?Q (tyi' ST E A)" by (clarsimp simp add: tyi'_def)
    moreover have "?Q (tyi' (T # ST) E ?A1)" 
      by (fastsimp simp add: tyi'_def hyperset_defs intro!: tyl_antimono)
    moreover have "!!τ. τ ∈ set (compT E A ST e1) ==> ?Q τ" using TryCatch.prems
      by clarsimp (frule compT_ST_prefix,
                   fastsimp dest!: compT_LT_prefix simp add: tyi'_def)
    ultimately
    have "∀τ∈set (tyi' ST E A # compT E A ST e1 @ [tyi' (T # ST) E ?A1]). ?Q τ" 
      by auto
  }
  also from TryCatch.prems max_stack1[of e1] have "size ST + 1 ≤ mxs" by auto
  ultimately show ?case using wt1 wt2 TryCatch.prems class
    by (simp add:after_def)
next
  case new thus ?case by(auto simp add:after_def wt_New)
next
  case (BinOp e1 bop e2) 
  let ?op = "case bop of Eq => [CmpEq] | Add => [IAdd]"
  have T: "P,E \<turnstile>1 e1 «bop» e2 :: T" .
  then obtain T1 T2 where T1: "P,E \<turnstile>1 e1 :: T1" and T2: "P,E \<turnstile>1 e2 :: T2" and 
    bopT: "case bop of Eq => (P \<turnstile> T1 ≤ T2 ∨ P \<turnstile> T2 ≤ T1) ∧ T = Boolean 
                    | Add => T1 = Integer ∧ T2 = Integer ∧ T = Integer" by auto
  let ?A1 = "A \<squnion> \<A> e1" let ?A2 = "?A1 \<squnion> \<A> e2"
  let ?τ = "tyi' ST E A" let ?τs1 = "compT E A ST e1"
  let ?τ1 = "tyi' (T1#ST) E ?A1" let ?τs2 = "compT E ?A1 (T1#ST) e2"
  let ?τ2 = "tyi' (T2#T1#ST) E ?A2" let ?τ' = "tyi' (T#ST) E ?A2"
  from bopT have "\<turnstile> ?op,[] [::] [?τ2,?τ']" 
    by (cases bop) (auto simp add: wt_CmpEq wt_IAdd)
  also have "PROP ?P e2 E T2 ?A1 (T1#ST)" .
  with BinOp.prems T2 
  have "\<turnstile> compE2 e2, compxE2 e2 0 (size (T1#ST)) [::] ?τ1#?τs2@[?τ2]" 
    by (auto simp: after_def)
  also from BinOp T1 have "\<turnstile> compE2 e1, compxE2 e1 0 (size ST) [::] ?τ#?τs1@[?τ1]" 
    by (auto simp: after_def)
  finally show ?case using T T1 T2 by (simp add: after_def hyperUn_assoc)
next
  case (Cons_exp e es)
  have "P,E \<turnstile>1 e # es [::] Ts" .
  then obtain Te Ts' where 
    Te: "P,E \<turnstile>1 e :: Te" and Ts': "P,E \<turnstile>1 es [::] Ts'" and
    Ts: "Ts = Te#Ts'" by auto
  let ?Ae = "A \<squnion> \<A> e"  
  let ?τ = "tyi' ST E A" let ?τse = "compT E A ST e"  
  let ?τe = "tyi' (Te#ST) E ?Ae" let ?τs' = "compTs E ?Ae (Te#ST) es"
  let ?τs = "?τ # ?τse @ (?τe # ?τs')"
  have Ps: "PROP ?Ps es E Ts' ?Ae (Te#ST)" .
  with Cons_exp.prems Te Ts'
  have "\<turnstile> compEs2 es, compxEs2 es 0 (size (Te#ST)) [::] ?τe#?τs'" by (simp add: after_def)
  also from Cons_exp Te have "\<turnstile> compE2 e, compxE2 e 0 (size ST) [::] ?τ#?τse@[?τe]" 
    by (auto simp: after_def)
  moreover
  from Ps Cons_exp.prems Te Ts' Ts
  have "last ?τs = tyi' (rev Ts@ST) E (?Ae \<squnion> \<A>s es)" by simp
  ultimately show ?case using Te by (simp add: after_def hyperUn_assoc)
next
  case (FAss e1 F D e2)
  hence Void: "P,E \<turnstile>1 e1\<bullet>F{D} := e2 :: Void" by auto
  then obtain C T T' where    
    C: "P,E \<turnstile>1 e1 :: Class C" and sees: "P \<turnstile> C sees F:T in D" and
    T': "P,E \<turnstile>1 e2 :: T'" and T'_T: "P \<turnstile> T' ≤ T" by auto
  let ?A1 = "A \<squnion> \<A> e1" let ?A2 = "?A1 \<squnion> \<A> e2"  
  let ?τ = "tyi' ST E A" let ?τs1 = "compT E A ST e1"
  let ?τ1 = "tyi' (Class C#ST) E ?A1" let ?τs2 = "compT E ?A1 (Class C#ST) e2"
  let ?τ2 = "tyi' (T'#Class C#ST) E ?A2" let ?τ3 = "tyi' ST E ?A2"
  let ?τ' = "tyi' (Void#ST) E ?A2"
  from FAss.prems sees T'_T 
  have "\<turnstile> [Putfield F D,Push Unit],[] [::] [?τ2,?τ3,?τ']"
    by (fastsimp simp add: wt_Push wt_Put)
  also have "PROP ?P e2 E T' ?A1 (Class C#ST)".
  with FAss.prems T' 
  have "\<turnstile> compE2 e2, compxE2 e2 0 (size ST+1) [::] ?τ1#?τs2@[?τ2]"
    by (auto simp add: after_def hyperUn_assoc) 
  also from FAss C have "\<turnstile> compE2 e1, compxE2 e1 0 (size ST) [::] ?τ#?τs1@[?τ1]" 
    by (auto simp add: after_def)
  finally show ?case using Void C T' by (simp add: after_def hyperUn_assoc) 
next
  case Val thus ?case by(auto simp:after_def wt_Push)
next
  case Cast thus ?case by (auto simp:after_def wt_Cast)
next
  case (Block i Ti e)
  let ?τs = "tyi' ST E A # compT (E @ [Ti]) (A\<ominus>i) ST e"
  have IH: "PROP ?P e (E@[Ti]) T (A\<ominus>i) ST" .
  hence "\<turnstile> compE2 e, compxE2 e 0 (size ST) [::]
         ?τs @ [tyi' (T#ST) (E@[Ti]) (A\<ominus>(size E) \<squnion> \<A> e)]"
    using Block.prems by (auto simp add: after_def)
  also have "P \<turnstile> tyi' (T # ST) (E@[Ti]) (A \<ominus> size E \<squnion> \<A> e) ≤'
                 tyi' (T # ST) (E@[Ti]) ((A \<squnion> \<A> e) \<ominus> size E)"
     by(auto simp add:hyperset_defs intro: tyi'_antimono)
  also have "… = tyi' (T # ST) E (A \<squnion> \<A> e)" by simp
  also have "P \<turnstile> … ≤' tyi' (T # ST) E (A \<squnion> (\<A> e \<ominus> i))"
     by(auto simp add:hyperset_defs intro: tyi'_antimono)
  finally show ?case using Block.prems by(simp add: after_def)
next
  case Var thus ?case by(auto simp:after_def wt_Load)
next
  case FAcc thus ?case by(auto simp:after_def wt_Get)
next
  case (LAss i e) thus ?case using max_stack1[of e]
    by(auto simp: hyper_insert_comm after_def wt_Store wt_Push)
next
  case Nil_exp thus ?case by auto
next
  case throw thus ?case by(auto simp add: after_def wt_Throw)
next
  case (While e c)
  obtain Tc where wte: "P,E \<turnstile>1 e :: Boolean" and wtc: "P,E \<turnstile>1 c :: Tc"
    and [simp]: "T = Void" using While by auto
  have [simp]: "ty E (while (e) c) = Void" using While by simp
  let ?A0 = "A \<squnion> \<A> e" let ?A1 = "?A0 \<squnion> \<A> c"
  let ?τ = "tyi' ST E A" let ?τse = "compT E A ST e"
  let ?τe = "tyi' (Boolean#ST) E ?A0" let ?τ1 = "tyi' ST E ?A0"
  let ?τsc = "compT E ?A0 ST c" let ?τc = "tyi' (Tc#ST) E ?A1"
  let ?τ2 = "tyi' ST E ?A1" let ?τ' = "tyi' (Void#ST) E ?A0"
  let ?τs = "(?τ # ?τse @ [?τe]) @ ?τ1 # ?τsc @ [?τc, ?τ2, ?τ1, ?τ']"
  have "\<turnstile> [],[] [::] [] @ ?τs" by(simp add:wt_instrs_def)
  also
  have "PROP ?P e E Boolean A ST" .
  hence "\<turnstile> compE2 e,compxE2 e 0 (size ST) [::] ?τ # ?τse @ [?τe]"
    using While.prems by (auto simp:after_def)
  also
  have "[] @ ?τs = (?τ # ?τse) @ ?τe # ?τ1 # ?τsc @ [?τc,?τ2,?τ1,?τ']" by simp
  also
  let ?ne = "size(compE2 e)"  let ?nc = "size(compE2 c)"
  let ?if = "IfFalse (int ?nc + 3)"
  have "\<turnstile> [?if],[] [::] ?τe # ?τ1 # ?τsc @ [?τc, ?τ2, ?τ1, ?τ']"
    by(simp add: wt_instr_Cons wt_instr_append wt_IfFalse
                 nat_add_distrib split: nat_diff_split)
  also
  have "(?τ # ?τse) @ (?τe # ?τ1 # ?τsc @ [?τc, ?τ2, ?τ1, ?τ']) = ?τs" by simp
  also
  have "PROP ?P c E Tc ?A0 ST" .
  hence "\<turnstile> compE2 c,compxE2 c 0 (size ST) [::] ?τ1 # ?τsc @ [?τc]"
    using While.prems wtc by (auto simp:after_def)
  also have "?τs = (?τ # ?τse @ [?τe,?τ1] @ ?τsc) @ [?τc,?τ2,?τ1,?τ']" by simp
  also have "\<turnstile> [Pop],[] [::] [?τc, ?τ2]"  by(simp add:wt_Pop)
  also have "(?τ # ?τse @ [?τe,?τ1] @ ?τsc) @ [?τc,?τ2,?τ1,?τ'] = ?τs" by simp
  also let ?go = "Goto (-int(?nc+?ne+2))"
  have "P \<turnstile> ?τ2 ≤' ?τ" by(fastsimp intro: tyi'_antimono simp: hyperset_defs)
  hence "P,Tr,mxs,size ?τs,[] \<turnstile> ?go,?ne+?nc+2 :: ?τs"
    by(simp add: wt_Goto split: nat_diff_split)
  also have "?τs = (?τ # ?τse @ [?τe,?τ1] @ ?τsc @ [?τc, ?τ2]) @ [?τ1, ?τ']"
    by simp
  also have "\<turnstile> [Push Unit],[] [::] [?τ1,?τ']"
    using While.prems max_stack1[of c] by(auto simp add:wt_Push)
  finally show ?case using wtc wte
    by(simp add:after_def) (simp add:nat_number)
next
  case (Cond e e1 e2)
  obtain T1 T2 where wte: "P,E \<turnstile>1 e :: Boolean"
    and wt1: "P,E \<turnstile>1 e1 :: T1" and wt2: "P,E \<turnstile>1 e2 :: T2"
    and sub1: "P \<turnstile> T1 ≤ T" and sub2: "P \<turnstile> T2 ≤ T"
    using Cond by auto
  have [simp]: "ty E (if (e) e1 else e2) = T" using Cond by simp
  let ?A0 = "A \<squnion> \<A> e" let ?A2 = "?A0 \<squnion> \<A> e2" let ?A1 = "?A0 \<squnion> \<A> e1"
  let ?A' = "?A0 \<squnion> \<A> e1 \<sqinter> \<A> e2"
  let ?τ2 = "tyi' ST E ?A0" let ?τ' = "tyi' (T#ST) E ?A'"
  let ?τs2 = "compT E ?A0 ST e2"
  have "PROP ?P e2 E T2 ?A0 ST" .
  hence "\<turnstile> compE2 e2, compxE2 e2 0 (size ST) [::] (?τ2#?τs2) @ [tyi' (T2#ST) E ?A2]"
    using Cond.prems wt2 by(auto simp add:after_def)
  also have "P \<turnstile> tyi' (T2#ST) E ?A2 ≤' ?τ'" using sub2
    by(auto simp add: hyperset_defs tyi'_def intro!: tyl_antimono)
  also
  let ?τ3 = "tyi' (T1 # ST) E ?A1"
  let ?g2 = "Goto(int (size (compE2 e2) + 1))"
  have "P,Tr,mxs,size(compE2 e2)+2,[] \<turnstile> ?g2,0 :: ?τ3#(?τ2#?τs2)@[?τ']"
    by(auto simp: hyperset_defs wt_defs nth_Cons tyi'_def
             split:nat.split intro!: tyl_antimono)
  also
  let ?τs1 = "compT E ?A0 ST e1"
  have "PROP ?P e1 E T1 ?A0 ST" .
  hence "\<turnstile> compE2 e1,compxE2 e1 0 (size ST) [::] ?τ2 # ?τs1 @ [?τ3]"
    using Cond.prems wt1 by(auto simp add:after_def)
  also
  let ?τs12 = "?τ2 # ?τs1 @ ?τ3 # (?τ2 # ?τs2) @ [?τ']"
  let ?τ1 = "tyi' (Boolean#ST) E ?A0"
  let ?g1 = "IfFalse(int (size (compE2 e1) + 2))"
  let ?code = "compE2 e1 @ ?g2 # compE2 e2"
  have "\<turnstile> [?g1],[] [::] [?τ1] @ ?τs12"
    by(simp add: wt_IfFalse nat_add_distrib split:nat_diff_split)
  also (wt_instrs_ext2) have "[?τ1] @ ?τs12 = ?τ1 # ?τs12" by simp also
  let ?τ = "tyi' ST E A"
  have "PROP ?P e E Boolean A ST" .
  hence "\<turnstile> compE2 e, compxE2 e 0 (size ST) [::] ?τ # compT E A ST e @ [?τ1]"
    using Cond.prems wte by(auto simp add:after_def)
  finally show ?case using wte wt1 wt2 by(simp add:after_def hyperUn_assoc)
next
  case (Call e M es)
  obtain C D Ts m Ts' where C: "P,E \<turnstile>1 e :: Class C"
    and method: "P \<turnstile> C sees M:Ts -> T = m in D"
    and wtes: "P,E \<turnstile>1 es [::] Ts'" and subs: "P \<turnstile> Ts' [≤] Ts"
    using Call.prems by auto
  from wtes have same_size: "size es = size Ts'" by(rule WTs1_same_size)
  let ?A0 = "A \<squnion> \<A> e" let ?A1 = "?A0 \<squnion> \<A>s es"
  let ?τ = "tyi' ST E A" let ?τse = "compT E A ST e"
  let ?τe = "tyi' (Class C # ST) E ?A0"
  let ?τses = "compTs E ?A0 (Class C # ST) es"
  let ?τ1 = "tyi' (rev Ts' @ Class C # ST) E ?A1"
  let ?τ' = "tyi' (T # ST) E ?A1"
  have "\<turnstile> [Invoke M (size es)],[] [::] [?τ1,?τ']"
    by(rule wt_Invoke[OF same_size method subs])
  also
  have "PROP ?Ps es E Ts' ?A0 (Class C # ST)".
  hence "\<turnstile> compEs2 es,compxEs2 es 0 (size ST+1) [::] ?τe # ?τses"
        "last (?τe # ?τses) = ?τ1"
    using Call.prems wtes by(auto simp add:after_def)
  also have "(?τe # ?τses) @ [?τ'] = ?τe # ?τses @ [?τ']" by simp
  also have "\<turnstile> compE2 e,compxE2 e 0 (size ST) [::] ?τ # ?τse @ [?τe]"
    using Call C by(auto simp add:after_def)
  finally show ?case using Call.prems C by(simp add:after_def hyperUn_assoc)
next
  case Seq thus ?case
    by(auto simp:after_def)
      (fastsimp simp:wt_Push wt_Pop hyperUn_assoc
                intro:wt_instrs_app2 wt_instrs_Cons)
qed
(*>*)


lemma [simp]: "types (compP f P) = types P"
(*<*)by auto(*>*)

lemma [simp]: "states (compP f P) mxs mxl = states P mxs mxl"
(*<*)by (simp add: JVM_states_unfold)(*>*)

lemma [simp]: "appi (i, compP f P, pc, mpc, T, τ) = appi (i, P, pc, mpc, T, τ)"
(*<*)
  apply (cases τ)  
  apply (cases i)
  apply auto
   apply (fastsimp dest!: sees_method_compPD)
  apply (force dest: sees_method_compP)
  done
(*>*)
  
lemma [simp]: "is_relevant_entry (compP f P) i = is_relevant_entry P i"
(*<*)
  apply (rule ext)+
  apply (unfold is_relevant_entry_def)
  apply (cases i)
  apply auto
  done
(*>*)

lemma [simp]: "relevant_entries (compP f P) i pc xt = relevant_entries P i pc xt"
(*<*) by (simp add: relevant_entries_def)(*>*)

lemma [simp]: "app i (compP f P) mpc T pc mxl xt τ = app i P mpc T pc mxl xt τ"
(*<*)
  apply (simp add: app_def xcpt_app_def eff_def xcpt_eff_def norm_eff_def)
  apply (fastsimp simp add: image_def)
  done
(*>*)

lemma [simp]: "app i P mpc T pc mxl xt τ ==> eff i (compP f P) pc xt τ = eff i P pc xt τ"
(*<*)
  apply (clarsimp simp add: eff_def norm_eff_def xcpt_eff_def app_def)
  apply (cases i)
  apply auto
  done
(*>*)

lemma [simp]: "subtype (compP f P) = subtype P"
(*<*)
  apply (rule ext)+
  apply (simp)
  done
(*>*)
  
lemma [simp]: "compP f P \<turnstile> τ ≤' τ' = P \<turnstile> τ ≤' τ'"
(*<*) by (simp add: sup_state_opt_def sup_state_def sup_ty_opt_def)(*>*)

lemma [simp]: "compP f P,T,mpc,mxl,xt \<turnstile> i,pc :: τs = P,T,mpc,mxl,xt \<turnstile> i,pc :: τs"
(*<*)by (simp add: wt_instr_def cong: conj_cong)(*>*)

declare TC1.compT_sizes[simp]  TC0.ty_def2[simp]

lemma compT_method:
fixes e and A and C and Ts and mxl0
defines [simp]: "E ≡ Class C # Ts"
    and [simp]: "A ≡ ⌊{..size Ts}⌋"
    and [simp]: "A' ≡ A \<squnion> \<A> e"
    and [simp]: "mxs ≡ max_stack e"
    and [simp]: "mxl0 ≡ max_vars e"
    and [simp]: "mxl ≡ 1 + size Ts + mxl0"
shows "[| wf_prog p P; P,E \<turnstile>1 e :: T; \<D> e A; \<B> e (size E); 
          set E ⊆ types P; P \<turnstile> T ≤ T' |] ==>
   wt_method (compP2 P) C Ts T' mxs mxl0 (compE2 e @ [Return]) (compxE2 e 0 0)
      (tyi' mxl [] E A # compTa P mxl E A [] e)"
(*<*)
apply(simp add:wt_method_def compTa_def after_def)
apply(rule conjI)
apply(simp add:check_types_def TC0.OK_tyi'_in_statesI)
apply(rule conjI)
apply(drule (1) WT1_is_type)
apply simp
apply(insert max_stack1[of e])
apply(fastsimp intro!: TC0.OK_tyi'_in_statesI)
apply(erule (1) TC1.compT_states)
apply simp
apply simp
apply simp
apply simp
apply(rule conjI)
apply(fastsimp simp add:wt_start_def tyi'_def tyl_def list_all2_conv_all_nth nth_Cons split:nat.split dest:less_antisym)
apply (frule (1) TC2.compT_wt_instrs
 [where ST = "[]" and mxs = "max_stack e" and mxl = "1 + size Ts + max_vars e"])
apply simp
apply simp
apply simp
apply simp
apply (clarsimp simp:wt_instrs_def after_def)
apply(rule conjI)
apply clarsimp apply (fastsimp)
apply(clarsimp)
apply(drule (1) less_antisym)
apply(thin_tac "∀x. ?P x")
apply(clarsimp simp:TC2.wt_defs xcpt_app_pcs xcpt_eff_pcs tyi'_def)
apply(cases "size (compE2 e)")
 apply (simp del: compxE2_size_convs nth_append  add: neq_Nil_conv)
apply (simp)
done
(*>*)


constdefs
  compTP :: "J1_prog => tyP"
  "compTP P C M  ≡
  let (D,Ts,T,e) = method P C M;
       E = Class C # Ts;
       A = ⌊{..size Ts}⌋;
       mxl = 1 + size Ts + max_vars e
  in  (tyi' mxl [] E A # compTa P mxl E A [] e)"

theorem wt_compP2:
  "wf_J1_prog P ==> wf_jvm_prog (compP2 P)"
(*<*)
  apply (simp add: wf_jvm_prog_def wf_jvm_prog_phi_def)
  apply(rule_tac x = "compTP P" in exI)
  apply (rule wf_prog_compPI)
   prefer 2 apply assumption
  apply (clarsimp simp add: wf_mdecl_def)
  apply (simp add: compTP_def)
  apply (rule compT_method [simplified])
       apply assumption+
    apply (drule (1) sees_wf_mdecl)
    apply (simp add: wf_mdecl_def)
   apply (blast intro: sees_method_is_class)
  apply assumption
  done
(*>*)


theorem wt_J2JVM:
  "wf_J_prog P ==> wf_jvm_prog (J2JVM P)"
(*<*)
apply(simp only:o_def J2JVM_def)
apply(blast intro:wt_compP2 compP1_pres_wf)
done
(*>*)


end

lemma ty_def2:

  WT1 P E e T ==> ty P E e = T

lemma

  tyi' mxl ST E None = None

lemma tyl_app_diff:

  tyl mxl (E @ [T]) (A - {length E}) = tyl mxl E A

lemma tyi'_app_diff:

  tyi' mxl ST (E @ [T]) (A \<ominus> length E) = tyi' mxl ST E A

lemma tyl_antimono:

  A <= A' ==> P |- tyl mxl E A' [<=T] tyl mxl E A

lemma tyi'_antimono:

  A <= A' ==> P |- tyi' mxl ST EA'⌋ <=' tyi' mxl ST EA

lemma tyl_env_antimono:

  P |- tyl mxl (E @ [T]) A [<=T] tyl mxl E A

lemma tyi'_env_antimono:

  P |- tyi' mxl ST (E @ [T]) A <=' tyi' mxl ST E A

lemma tyi'_incr:

  P |- tyi' mxl ST (E @ [T]) ⌊insert (length E) A⌋ <=' tyi' mxl ST EA

lemma tyl_incr:

  P |- tyl mxl (E @ [T]) (insert (length E) A) [<=T] tyl mxl E A

lemma tyl_in_types:

  set E <= types P ==> tyl mxl E A : list mxl (err (types P))

lemma compE2_not_Nil:

  compE2 e ~= []

lemma

  length (compT P mxl E A ST e) = length (compE2 e) - 1

and

  length (compTs P mxl E A ST es) = length (compEs2 es)

lemma

τ⌋ ~: set (compT P mxl E None ST e)

and

τ⌋ ~: set (compTs P mxl E None ST es)

lemma pair_eq_tyi'_conv:

  (⌊(ST, LT)⌋ = tyi' mxl ST0 E A) =
  (case A of None => False | ⌊A⌋ => ST = ST0 & LT = tyl mxl E A)

lemma pair_conv_tyi':

  ⌊(ST, tyl mxl E A)⌋ = tyi' mxl ST EA

lemma compT_LT_prefix:

  [| ⌊(ST, LT)⌋ : set (compT P mxl E A ST0 e); \<B> e (length E) |]
  ==> P |- ⌊(ST, LT)⌋ <=' tyi' mxl ST E A

and

  [| ⌊(ST, LT)⌋ : set (compTs P mxl E A ST0 es); \<B>s es (length E) |]
  ==> P |- ⌊(ST, LT)⌋ <=' tyi' mxl ST E A

lemma

  OK None : states P mxs mxl

lemma after_in_states:

  [| wf_prog p P; WT1 P E e T; set E <= types P; set ST <= types P;
     length ST + max_stack e <= mxs |]
  ==> OK (after P mxl E A ST e) : states P mxs mxl

lemma OK_tyi'_in_statesI:

  [| set E <= types P; set ST <= types P; length ST <= mxs |]
  ==> OK (tyi' mxl ST E A) : states P mxs mxl

lemma is_class_type_aux:

  is_class P C ==> is_type P (Class C)

theorem

  [| wf_prog p P; WT1 P E e T; set E <= types P; set ST <= types P;
     length ST + max_stack e <= mxs; length E + max_vars e <= mxl |]
  ==> OK ` set (compT P mxl E A ST e) <= states P mxs mxl

and

  [| wf_prog p P; WTs1 P E es Ts; set E <= types P; set ST <= types P;
     length ST + max_stacks es <= mxs; length E + max_varss es <= mxl |]
  ==> OK ` set (compTs P mxl E A ST es) <= states P mxs mxl

lemma

  shift 0 xt = xt

lemma

  shift n [] = []

lemma

  shift n (xt1 @ xt2) = shift n xt1 @ shift n xt2

lemma

  shift m (shift n xt) = shift (m + n) xt

lemma

  pcs (shift n xt) = {pc + n |pc. pc : pcs xt}

lemma

  shift pc (compxE2 e pc' d) = compxE2 e (pc' + pc) d

and

  shift pc (compxEs2 es pc' d) = compxEs2 es (pc' + pc) d

lemma

  n ~= 0 ==> compxE2 e n d = shift n (compxE2 e 0 d)

and

  n ~= 0 ==> compxEs2 es n d = shift n (compxEs2 es 0 d)

lemmas wt_defs:

  P,Tr,mxs \<turnstile> is, xt [::] τs ==
  length is < length τs &
  pcs xt <= {0..length is(} &
  (ALL pc<length is. P,Tr,mxs,length τs,xt \<turnstile> is ! pc,pc :: τs)
  P,T,mxs,mpc,xt \<turnstile> i,pc :: τs ==
  app i P mxs T pc mpc xt (τs ! pc) &
  (ALL (pc', τ'):set (eff i P pc xt (τs ! pc)). P |- τ' <=' τs ! pc')
  app i P mxs Tr pc mpc xt t ==
  case t of None => True
  | ⌊τ⌋ =>
      appi (i, P, pc, mxs, Tr, τ) &
      xcpt_app i P pc mxs xt τ & (ALL (pc', τ'):set (eff i P pc xt t). pc' < mpc)
  eff i P pc et t ==
  case t of None => [] | ⌊τ⌋ => norm_eff i P pc τ @ xcpt_eff i P pc τ et
  norm_eff i P pc τ == map (%pc'. (pc', ⌊effi (i, P, τ)⌋)) (succs i τ pc)

lemma

  τs ~= [] ==> P,Tr,mxs \<turnstile> [], [] [::] τs

lemma

  eff i P pc et None = []

lemma wt_instr_appR:

  [| P,T,m,mpc,xt \<turnstile> is ! pc,pc :: τs; pc < length is;
     length is < length τs; mpc <= length τs; mpc <= mpc' |]
  ==> P,T,m,mpc',xt \<turnstile> is ! pc,pc :: τs @ τs'

lemma relevant_entries_shift:

  relevant_entries P i (pc + n) (shift n xt) =
  shift n (relevant_entries P i pc xt)

lemma

  xcpt_eff i P (pc + n) τ (shift n xt) =
  map (%(pc, τ). (pc + n, τ)) (xcpt_eff i P pc τ xt)

lemma

  appi (i, P, pc, m, T, τ)
  ==> eff i P (pc + n) (shift n xt) ⌊τ⌋ =
      map (%(pc, τ). (pc + n, τ)) (eff i P pc xtτ⌋)

lemma

  xcpt_app i P (pc + n) mxs (shift n xt) τ = xcpt_app i P pc mxs xt τ

lemma wt_instr_appL:

  [| P,T,m,mpc,xt \<turnstile> i,pc :: τs; pc < length τs; mpc <= length τs |]
  ==> P,T,m,mpc +
            length
             τs',shift (length τs') xt \<turnstile> i,pc + length τs' :: τs' @ τs

lemma wt_instr_Cons:

  [| P,T,m,mpc - 1,[] \<turnstile> i,pc - 1 :: τs; 0 < pc; 0 < mpc;
     pc < length τs + 1; mpc <= length τs + 1 |]
  ==> P,T,m,mpc,[] \<turnstile> i,pc :: τ # τs

lemma wt_instr_append:

  [| P,T,m,mpc - length τs',[] \<turnstile> i,pc - length τs' :: τs;
     length τs' <= pc; length τs' <= mpc; pc < length τs + length τs';
     mpc <= length τs + length τs' |]
  ==> P,T,m,mpc,[] \<turnstile> i,pc :: τs' @ τs

lemma xcpt_app_pcs:

  pc ~: pcs xt ==> xcpt_app i P pc mxs xt τ

lemma xcpt_eff_pcs:

  pc ~: pcs xt ==> xcpt_eff i P pc τ xt = []

lemma pcs_shift:

  pc < n ==> pc ~: pcs (shift n xt)

lemma wt_instr_appRx:

  [| P,T,m,mpc,xt \<turnstile> is ! pc,pc :: τs; pc < length is;
     length is < length τs; mpc <= length τs |]
  ==> P,T,m,mpc,xt @ shift (length is) xt' \<turnstile> is ! pc,pc :: τs

lemma wt_instr_appLx:

  [| P,T,m,mpc,xt \<turnstile> i,pc :: τs; pc ~: pcs xt' |]
  ==> P,T,m,mpc,xt' @ xt \<turnstile> i,pc :: τs

lemma wt_instrs_extR:

  P,Tr,mxs \<turnstile> is, xt [::] τs
  ==> P,Tr,mxs \<turnstile> is, xt [::] τs @ τs'

lemma wt_instrs_ext:

  [| P,Tr,mxs \<turnstile> is1, xt1 [::] τs1 @ τs2;
     P,Tr,mxs \<turnstile> is2, xt2 [::] τs2; length τs1 = length is1 |]
  ==> P,Tr,mxs \<turnstile> is1 @ is2, xt1 @ shift (length is1) xt2 [::] τs1 @ τs2

corollary wt_instrs_ext2:

  [| P,Tr,mxs \<turnstile> is2, xt2 [::] τs2;
     P,Tr,mxs \<turnstile> is1, xt1 [::] τs1 @ τs2; length τs1 = length is1 |]
  ==> P,Tr,mxs \<turnstile> is1 @ is2, xt1 @ shift (length is1) xt2 [::] τs1 @ τs2

corollary wt_instrs_ext_prefix:

  [| P,Tr,mxs \<turnstile> is1, xt1 [::] τs1 @ τs2;
     P,Tr,mxs \<turnstile> is2, xt2 [::] τs3; length τs1 = length is1;
     τs3 <= τs2 |]
  ==> P,Tr,mxs \<turnstile> is1 @ is2, xt1 @ shift (length is1) xt2 [::] τs1 @ τs2

corollary

  [| P,Tr,mxs \<turnstile> is1, xt1 [::] τs1 @ [τ];
     P,Tr,mxs \<turnstile> is2, xt2 [::] τ # τs2; length τs1 = length is1 |]
  ==> P,Tr,mxs \<turnstile> is1 @ is2, xt1 @ shift (length is1) xt2 [::]
      τs1 @ τ # τs2

corollary wt_instrs_app_last:

  [| P,Tr,mxs \<turnstile> is2, xt2 [::] τ # τs2;
     P,Tr,mxs \<turnstile> is1, xt1 [::] τs1; last τs1 = τ;
     length τs1 = length is1 + 1 |]
  ==> P,Tr,mxs \<turnstile> is1 @ is2, xt1 @ shift (length is1) xt2 [::] τs1 @ τs2

corollary wt_instrs_append_last:

  [| P,Tr,mxs \<turnstile> is, xt [::] τs;
     P,Tr,mxs,mpc,[] \<turnstile> i,pc :: τs; pc = length is; mpc = length τs;
     length is + 1 < length τs |]
  ==> P,Tr,mxs \<turnstile> is @ [i], xt [::] τs

corollary wt_instrs_app2:

  [| P,Tr,mxs \<turnstile> is2, xt2 [::] τ' # τs2;
     P,Tr,mxs \<turnstile> is1, xt1 [::] τ # τs1 @ [τ'];
     xt' = xt1 @ shift (length is1) xt2; length τs1 + 1 = length is1 |]
  ==> P,Tr,mxs \<turnstile> is1 @ is2, xt' [::] τ # τs1 @ τ' # τs2

corollary wt_instrs_app2_simp:

  [| P,Tr,mxs \<turnstile> is2, xt2 [::] τ' # τs2;
     P,Tr,mxs \<turnstile> is1, xt1 [::] τ # τs1 @ [τ'];
     length τs1 + 1 = length is1 |]
  ==> P,Tr,mxs \<turnstile> is1 @ is2, xt1 @ shift (length is1) xt2 [::]
      τ # τs1 @ τ' # τs2

corollary wt_instrs_Cons:

  [| τs ~= []; P,Tr,mxs \<turnstile> [i], [] [::] [τ, τ'];
     P,Tr,mxs \<turnstile> is, xt [::] τ' # τs |]
  ==> P,Tr,mxs \<turnstile> i # is, shift 1 xt [::] τ # τ' # τs

corollary

  [| P,Tr,mxs \<turnstile> is, xt [::] τs;
     P,Tr,mxs,mpc,[] \<turnstile> i,0 :: τ # τs; mpc = length τs + 1 |]
  ==> P,Tr,mxs \<turnstile> i # is, shift 1 xt [::] τ # τs

lemma wt_instrs_last_incr:

  [| P,Tr,mxs \<turnstile> is, xt [::] τs @ [τ]; P |- τ <=' τ' |]
  ==> P,Tr,mxs \<turnstile> is, xt [::] τs @ [τ']

lemma

  xcpt_app i P pc mxs [] τ

lemma

  xcpt_eff i P pc τ [] = []

lemma wt_New:

  [| is_class P C; length ST < mxs |]
  ==> P,Tr,mxs \<turnstile> [New C], [] [::]
      [tyi' mxl ST E A, tyi' mxl (Class C # ST) E A]

lemma wt_Cast:

  is_class P C
  ==> P,Tr,mxs \<turnstile> [Checkcast C], [] [::]
      [tyi' mxl (Class D # ST) E A, tyi' mxl (Class C # ST) E A]

lemma wt_Push:

  [| length ST < mxs; typeof v = ⌊T⌋ |]
  ==> P,Tr,mxs \<turnstile> [Push v], [] [::]
      [tyi' mxl ST E A, tyi' mxl (T # ST) E A]

lemma wt_Pop:

  P,Tr,mxs \<turnstile> [Pop], [] [::]
  tyi' mxl (T # ST) E A # tyi' mxl ST E A # τs

lemma wt_CmpEq:

  widen P T1 T2 | widen P T2 T1
  ==> P,Tr,mxs \<turnstile> [CmpEq], [] [::]
      [tyi' mxl (T2 # T1 # ST) E A, tyi' mxl (Boolean # ST) E A]

lemma wt_IAdd:

  P,Tr,mxs \<turnstile> [IAdd], [] [::]
  [tyi' mxl (Integer # Integer # ST) E A, tyi' mxl (Integer # ST) E A]

lemma wt_Load:

  [| length ST < mxs; length E <= mxl; i ∈∈ A; i < length E |]
  ==> P,Tr,mxs \<turnstile> [Load i], [] [::]
      [tyi' mxl ST E A, tyi' mxl (E ! i # ST) E A]

lemma wt_Store:

  [| widen P T (E ! i); i < length E; length E <= mxl |]
  ==> P,Tr,mxs \<turnstile> [Store i], [] [::]
      [tyi' mxl (T # ST) E A, tyi' mxl ST E (⌊{i}⌋ \<squnion> A)]

lemma wt_Get:

  P \<turnstile> C sees F:T in D
  ==> P,Tr,mxs \<turnstile> [Getfield F D], [] [::]
      [tyi' mxl (Class C # ST) E A, tyi' mxl (T # ST) E A]

lemma wt_Put:

  [| P \<turnstile> C sees F:T in D; widen P T' T |]
  ==> P,Tr,mxs \<turnstile> [Putfield F D], [] [::]
      [tyi' mxl (T' # Class C # ST) E A, tyi' mxl ST E A]

lemma wt_Throw:

  P,Tr,mxs \<turnstile> [Throw], [] [::] [tyi' mxl (Class C # ST) E A, τ']

lemma wt_IfFalse:

  [| 2 <= i; nat i < length τs + 2; P |- tyi' mxl ST E A <=' τs ! nat (i - 2) |]
  ==> P,Tr,mxs \<turnstile> [IfFalse i], [] [::]
      tyi' mxl (Boolean # ST) E A # tyi' mxl ST E A # τs

lemma wt_Goto:

  [| 0 <= int pc + i; nat (int pc + i) < length τs; length τs <= mpc;
     P |- τs ! pc <=' τs ! nat (int pc + i) |]
  ==> P,T,mxs,mpc,[] \<turnstile> Goto i,pc :: τs

lemma wt_Invoke:

  [| size es = length Ts'; P \<turnstile> C sees M: Ts->T = m in D;
     widens P Ts' Ts |]
  ==> P,Tr,mxs \<turnstile> [Invoke M (size es)], [] [::]
      [tyi' mxl (rev Ts' @ Class C # ST) E A, tyi' mxl (T # ST) E A]

corollary wt_instrs_app3:

  [| P,Tr,mxs \<turnstile> is2, [] [::] τ' # τs2;
     P,Tr,mxs \<turnstile> is1, xt1 [::] τ # τs1 @ [τ'];
     length τs1 + 1 = length is1 |]
  ==> P,Tr,mxs \<turnstile> is1 @ is2, xt1 [::] τ # τs1 @ τ' # τs2

corollary wt_instrs_Cons3:

  [| τs ~= []; P,Tr,mxs \<turnstile> [i], [] [::] [τ, τ'];
     P,Tr,mxs \<turnstile> is, [] [::] τ' # τs |]
  ==> P,Tr,mxs \<turnstile> i # is, [] [::] τ # τ' # τs

lemma wt_instrs_xapp:

  [| P,Tr,mxs \<turnstile> is1 @ is2, xt [::]
     τs1 @ tyi' mxl (Class C # ST) E A # τs2;
     ALL τ:set τs1.
        ALL ST' LT'.
           τ = ⌊(ST', LT')⌋ -->
           length ST <= length ST' &
           P |- ⌊(drop (length ST' - length ST) ST', LT')⌋ <=' tyi' mxl ST E A;
     length is1 = length τs1; is_class P C; length ST < mxs |]
  ==> P,Tr,mxs \<turnstile>
      is1 @ is2, xt @ [(0, length is1 - 1, C, length is1, length ST)] [::]
      τs1 @ tyi' mxl (Class C # ST) E A # τs2

lemma drop_Cons_Suc:

  drop n xs = y # ys ==> drop (Suc n) xs = ys

lemma drop_mess:

  [| Suc (length xs0) <= length xs;
     drop (length xs - Suc (length xs0)) xs = x # xs0 |]
  ==> drop (length xs - length xs0) xs = xs0

lemma compT_ST_prefix:

  ⌊(ST, LT)⌋ : set (compT P mxl E A ST0 e)
  ==> length ST0 <= length ST & drop (length ST - length ST0) ST = ST0

and

  ⌊(ST, LT)⌋ : set (compTs P mxl E A ST0 es)
  ==> length ST0 <= length ST & drop (length ST - length ST0) ST = ST0

lemma fun_of_simp:

  fun_of S x y = ((x, y) : S)

theorem compT_wt_instrs:

  [| WT1 P E e T; \<D> e A; \<B> e (length E); length ST + max_stack e <= mxs;
     length E + max_vars e <= mxl |]
  ==> P,Tr,mxs \<turnstile> compE2 e, compxE2 e 0 (length ST) [::]
      tyi' mxl ST E A # compT P mxl E A ST e @ [after P mxl E A ST e]

and

  [| WTs1 P E es Ts; \<D>s es A; \<B>s es (length E);
     length ST + max_stacks es <= mxs; length E + max_varss es <= mxl |]
  ==> let τs = tyi' mxl ST E A # compTs P mxl E A ST es
      in P,Tr,mxs \<turnstile> compEs2 es, compxEs2 es 0 (length ST) [::] τs &
         last τs = tyi' mxl (rev Ts @ ST) E (A \<squnion> \<A>s es)

lemma

  types (compP f P) = types P

lemma

  states (compP f P) mxs mxl = states P mxs mxl

lemma

  appi (i, compP f P, pc, mpc, T, τ) = appi (i, P, pc, mpc, T, τ)

lemma

  is_relevant_entry (compP f P) i = is_relevant_entry P i

lemma

  relevant_entries (compP f P) i pc xt = relevant_entries P i pc xt

lemma

  app i (compP f P) mpc T pc mxl xt τ = app i P mpc T pc mxl xt τ

lemma

  app i P mpc T pc mxl xt τ ==> eff i (compP f P) pc xt τ = eff i P pc xt τ

lemma

  subtype (compP f P) = subtype P

lemma

  compP f P |- τ <=' τ' = P |- τ <=' τ'

lemma

  compP f P,T,mpc,mxl,xt \<turnstile> i,pc :: τs =
  P,T,mpc,mxl,xt \<turnstile> i,pc :: τs

lemma

  [| wf_prog p P; WT1 P (Class C # Ts) e T; \<D> e ⌊{..length Ts}⌋;
     \<B> e (length (Class C # Ts)); set (Class C # Ts) <= types P;
     widen P T T' |]
  ==> wt_method (compP2 P) C Ts T' (max_stack e) (max_vars e)
       (compE2 e @ [Return]) (compxE2 e 0 0)
       (tyi' (1 + length Ts + max_vars e) [] (Class C # Ts) ⌊{..length Ts}⌋ #
        compTa P (1 + length Ts + max_vars e) (Class C # Ts) ⌊{..length Ts}⌋ [] e)

theorem wt_compP2:

  wf_J1_prog P ==> wf_jvm_prog (compP2 P)

theorem wt_J2JVM:

  wf_J_prog P ==> wf_jvm_prog (J2JVM P)