# Theory TypeSafe

Up to index of Isabelle/HOL/Bali

theory TypeSafe
imports DefiniteAssignmentCorrect Conform
begin

    (*  Title:      HOL/Bali/TypeSafe.thy
        ID:         $Id: TypeSafe.thy,v 1.17 2005/09/22 21:56:23 nipkow Exp $
        Author:     David von Oheimb and Norbert Schirmer
    *)
    header {* The type soundness proof for Java *}

    theory TypeSafe imports DefiniteAssignmentCorrect Conform begin

    section "error free"

    lemma error_free_halloc:
      assumes halloc: "G\<turnstile>s0 \<midarrow>halloc oi\<succ>a-> s1" and
              error_free_s0: "error_free s0"
      shows "error_free s1"
    proof -
      from halloc error_free_s0
      obtain abrupt0 store0 abrupt1 store1
        where eqs: "s0=(abrupt0,store0)" "s1=(abrupt1,store1)" and
              halloc': "G\<turnstile>(abrupt0,store0) \<midarrow>halloc oi\<succ>a-> (abrupt1,store1)" and
              error_free_s0': "error_free (abrupt0,store0)"
        by (cases s0,cases s1) auto
      from halloc' error_free_s0'
      have "error_free (abrupt1,store1)"
      proof (induct)
        case Abrupt
        then show ?case .
      next
        case New
        then show ?case
          by (auto split: split_if_asm)
      qed
      with eqs
      show ?thesis
        by simp
    qed

    lemma error_free_sxalloc:
      assumes sxalloc: "G\<turnstile>s0 \<midarrow>sxalloc-> s1" and error_free_s0: "error_free s0"
      shows "error_free s1"
    proof -
      from sxalloc error_free_s0
      obtain abrupt0 store0 abrupt1 store1
        where eqs: "s0=(abrupt0,store0)" "s1=(abrupt1,store1)" and
              sxalloc': "G\<turnstile>(abrupt0,store0) \<midarrow>sxalloc-> (abrupt1,store1)" and
              error_free_s0': "error_free (abrupt0,store0)"
        by (cases s0,cases s1) auto
      from sxalloc' error_free_s0'
      have "error_free (abrupt1,store1)"
      proof (induct)
      qed (auto)
      with eqs
      show ?thesis
        by simp
    qed

    lemma error_free_check_field_access_eq:
     "error_free (check_field_access G accC statDeclC fn stat a s)
     ==> (check_field_access G accC statDeclC fn stat a s) = s"
    apply (cases s)
    apply (auto simp add: check_field_access_def Let_def error_free_def
                          abrupt_if_def
                split: split_if_asm)
    done

    lemma error_free_check_method_access_eq:
    "error_free (check_method_access G accC statT mode sig a' s)
     ==> (check_method_access G accC statT mode sig a' s) = s"
    apply (cases s)
    apply (auto simp add: check_method_access_def Let_def error_free_def
                          abrupt_if_def
                split: split_if_asm)
    done

    lemma error_free_FVar_lemma:
         "error_free s
           ==> error_free (abupd (if stat then id else np a) s)"
      by (case_tac s) (auto split: split_if)

    lemma error_free_init_lvars [simp,intro]:
    "error_free s ==>
      error_free (init_lvars G C sig mode a pvs s)"
    by (cases s) (auto simp add: init_lvars_def Let_def split: split_if)

    lemma error_free_LVar_lemma:
    "error_free s ==> error_free (assign (λv. supd lupd(vn\<mapsto>v)) w s)"
    by (cases s) simp

    lemma error_free_throw [simp,intro]:
      "error_free s ==> error_free (abupd (throw x) s)"
    by (cases s) (simp add: throw_def)

    section "result conformance"

    constdefs
      assign_conforms :: "st => (val => state => state) => ty => env_ => bool"
              ("_≤|_\<preceq>_::\<preceq>_"                                        [71,71,71,71] 70)
    "s≤|f\<preceq>T::\<preceq>E ≡
     (∀s' w. Norm s'::\<preceq>E --> fst E,s'\<turnstile>w::\<preceq>T --> s≤|s' --> assign f w (Norm s')::\<preceq>E) ∧
     (∀s' w. error_free s' --> (error_free (assign f w s')))"

    constdefs
      rconf :: "prog => lenv => st => term => vals => tys => bool"
              ("_,_,_\<turnstile>_\<succ>_::\<preceq>_"                               [71,71,71,71,71,71] 70)
      "G,L,s\<turnstile>t\<succ>v::\<preceq>T
        ≡ case T of
            Inl T  => if (∃ var. t=In2 var)
                      then (∀ n. (the_In2 t) = LVar n
                             --> (fst (the_In2 v) = the (locals s n)) ∧
                                 (locals s n ≠ None --> G,s\<turnstile>fst (the_In2 v)::\<preceq>T)) ∧
                          (¬ (∃ n. the_In2 t=LVar n) --> (G,s\<turnstile>fst (the_In2 v)::\<preceq>T))∧
                          (s≤|snd (the_In2 v)\<preceq>T::\<preceq>(G,L))
                      else G,s\<turnstile>the_In1 v::\<preceq>T
          | Inr Ts => list_all2 (conf G s) (the_In3 v) Ts"

    text {*
     With @{term rconf} we describe the conformance of the result value of a term.
     This definition gets rather complicated because of the relations between the
     injections of the different terms, types and values. The main case distinction
     is between single values and value lists. In case of value lists, every
     value has to conform to its type. For single values we have to do a further
     case distinction, between values of variables @{term "∃var. t=In2 var" } and
     ordinary values. Values of variables are modelled as pairs consisting of the
     current value and an update function which will perform an assignment to the
     variable. This stems form the decision, that we only have one evaluation rule
     for each kind of variable. The decision if we read or write to the
     variable is made by syntactic enclosing rules. So conformance of
     variable-values must ensure that both the current value and an update will
     conform to the type. With the introduction of definite assignment of local
     variables we have to do another case distinction. For the notion of conformance
     local variables are allowed to be @{term None}, since the definedness is not
     ensured by conformance but by definite assignment. Field and array variables
     must contain a value.
    *}

    lemma rconf_In1 [simp]:
     "G,L,s\<turnstile>In1 ec\<succ>In1 v ::\<preceq>Inl T  =  G,s\<turnstile>v::\<preceq>T"
    apply (unfold rconf_def)
    apply (simp (no_asm))
    done

    lemma rconf_In2_no_LVar [simp]:
     "∀ n. va≠LVar n ==>
       G,L,s\<turnstile>In2 va\<succ>In2 vf::\<preceq>Inl T  = (G,s\<turnstile>fst vf::\<preceq>T ∧ s≤|snd vf\<preceq>T::\<preceq>(G,L))"
    apply (unfold rconf_def)
    apply auto
    done

    lemma rconf_In2_LVar [simp]:
     "va=LVar n ==>
       G,L,s\<turnstile>In2 va\<succ>In2 vf::\<preceq>Inl T
        = ((fst vf = the (locals s n)) ∧
           (locals s n ≠ None --> G,s\<turnstile>fst vf::\<preceq>T) ∧ s≤|snd vf\<preceq>T::\<preceq>(G,L))"
    apply (unfold rconf_def)
    by simp

    lemma rconf_In3 [simp]:
     "G,L,s\<turnstile>In3 es\<succ>In3 vs::\<preceq>Inr Ts = list_all2 (λv T. G,s\<turnstile>v::\<preceq>T) vs Ts"
    apply (unfold rconf_def)
    apply (simp (no_asm))
    done

    section "fits and conf"

    (* unused *)
    lemma conf_fits: "G,s\<turnstile>v::\<preceq>T ==> G,s\<turnstile>v fits T"
    apply (unfold fits_def)
    apply clarify
    apply (erule swap, simp (no_asm_use))
    apply (drule conf_RefTD)
    apply auto
    done

    lemma fits_conf:
      "[|G,s\<turnstile>v::\<preceq>T; G\<turnstile>T\<preceq>? T'; G,s\<turnstile>v fits T'; ws_prog G|] ==> G,s\<turnstile>v::\<preceq>T'"
    apply (auto dest!: fitsD cast_PrimT2 cast_RefT2)
    apply (force dest: conf_RefTD intro: conf_AddrI)
    done

    lemma fits_Array:
     "[|G,s\<turnstile>v::\<preceq>T; G\<turnstile>T'.[]\<preceq>T.[]; G,s\<turnstile>v fits T'; ws_prog G|] ==> G,s\<turnstile>v::\<preceq>T'"
    apply (auto dest!: fitsD widen_ArrayPrimT widen_ArrayRefT)
    apply (force dest: conf_RefTD intro: conf_AddrI)
    done

    section "gext"

    lemma halloc_gext: "!!s1 s2. G\<turnstile>s1 \<midarrow>halloc oi\<succ>a-> s2 ==> snd s1≤|snd s2"
    apply (simp (no_asm_simp) only: split_tupled_all)
    apply (erule halloc.induct)
    apply  (auto dest!: new_AddrD)
    done

    lemma sxalloc_gext: "!!s1 s2. G\<turnstile>s1 \<midarrow>sxalloc-> s2 ==> snd s1≤|snd s2"
    apply (simp (no_asm_simp) only: split_tupled_all)
    apply (erule sxalloc.induct)
    apply   (auto dest!: halloc_gext)
    done

    lemma eval_gext_lemma [rule_format (no_asm)]:
     "G\<turnstile>s \<midarrow>t\<succ>-> (w,s') ==> snd s≤|snd s' ∧ (case w of
        In1 v => True
      | In2 vf => normal s --> (∀v x s. s≤|snd (assign (snd vf) v (x,s)))
      | In3 vs => True)"
    apply (erule eval_induct)
    prefer 26
      apply (case_tac "inited C (globs s0)", clarsimp, erule thin_rl) (* Init *)
    apply (auto del: conjI  dest!: not_initedD gext_new sxalloc_gext halloc_gext
     simp  add: lvar_def fvar_def2 avar_def2 init_lvars_def2
                check_field_access_def check_method_access_def Let_def
     split del: split_if_asm split add: sum3.split)
    (* 6 subgoals *)
    apply force+
    done

    lemma evar_gext_f:
      "G\<turnstile>Norm s1 \<midarrow>e=\<succ>vf -> s2 ==> s≤|snd (assign (snd vf) v (x,s))"
    apply (drule eval_gext_lemma [THEN conjunct2])
    apply auto
    done

    lemmas eval_gext = eval_gext_lemma [THEN conjunct1]

    lemma eval_gext': "G\<turnstile>(x1,s1) \<midarrow>t\<succ>-> (w,x2,s2) ==> s1≤|s2"
    apply (drule eval_gext)
    apply auto
    done

    lemma init_yields_initd: "G\<turnstile>Norm s1 \<midarrow>Init C-> s2 ==> initd C s2"
    apply (erule eval_cases , auto split del: split_if_asm)
    apply (case_tac "inited C (globs s1)")
    apply  (clarsimp split del: split_if_asm)+
    apply (drule eval_gext')+
    apply (drule init_class_obj_inited)
    apply (erule inited_gext)
    apply (simp (no_asm_use))
    done

    section "Lemmas"

    lemma obj_ty_obj_class1:
     "[|wf_prog G; is_type G (obj_ty obj)|] ==> is_class G (obj_class obj)"
    apply (case_tac "tag obj")
    apply (auto simp add: obj_ty_def obj_class_def)
    done

    lemma oconf_init_obj:
     "[|wf_prog G;
     (case r of Heap a => is_type G (obj_ty obj) | Stat C => is_class G C)
    |] ==> G,s\<turnstile>obj (|values:=init_vals (var_tys G (tag obj) r)|)),::\<preceq>\<surd>r"
    apply (auto intro!: oconf_init_obj_lemma unique_fields)
    done

    lemma conforms_newG: "[|globs s oref = None; (x, s)::\<preceq>(G,L);
      wf_prog G; case oref of Heap a => is_type G (obj_ty (|tag=oi,values=vs|)),)
                            | Stat C => is_class G C|] ==>
      (x, init_obj G oi oref s)::\<preceq>(G, L)"
    apply (unfold init_obj_def)
    apply (auto elim!: conforms_gupd dest!: oconf_init_obj
                )
    done

    lemma conforms_init_class_obj:
     "[|(x,s)::\<preceq>(G, L); wf_prog G; class G C=Some y; ¬ inited C (globs s)|] ==>
      (x,init_class_obj G C s)::\<preceq>(G, L)"
    apply (rule not_initedD [THEN conforms_newG])
    apply    (auto)
    done

    lemma fst_init_lvars[simp]:
     "fst (init_lvars G C sig (invmode m e) a' pvs (x,s)) =
      (if is_static m then x else (np a') x)"
    apply (simp (no_asm) add: init_lvars_def2)
    done

    lemma halloc_conforms: "!!s1. [|G\<turnstile>s1 \<midarrow>halloc oi\<succ>a-> s2; wf_prog G; s1::\<preceq>(G, L);
      is_type G (obj_ty (|tag=oi,values=fs|)),)|] ==> s2::\<preceq>(G, L)"
    apply (simp (no_asm_simp) only: split_tupled_all)
    apply (case_tac "aa")
    apply  (auto elim!: halloc_elim_cases dest!: new_AddrD
           intro!: conforms_newG [THEN conforms_xconf] conf_AddrI)
    done

    lemma halloc_type_sound:
    "!!s1. [|G\<turnstile>s1 \<midarrow>halloc oi\<succ>a-> (x,s); wf_prog G; s1::\<preceq>(G, L);
      T = obj_ty (|tag=oi,values=fs|)),; is_type G T|] ==>
      (x,s)::\<preceq>(G, L) ∧ (x = None --> G,s\<turnstile>Addr a::\<preceq>T)"
    apply (auto elim!: halloc_conforms)
    apply (case_tac "aa")
    apply (subst obj_ty_eq)
    apply  (auto elim!: halloc_elim_cases dest!: new_AddrD intro!: conf_AddrI)
    done

    lemma sxalloc_type_sound:
     "!!s1 s2. [|G\<turnstile>s1 \<midarrow>sxalloc-> s2; wf_prog G|] ==>
      case fst s1 of
        None => s2 = s1
      | Some abr => (case abr of
                       Xcpt x => (∃a. fst s2 = Some(Xcpt (Loc a)) ∧
                                      (∀L. s1::\<preceq>(G,L) --> s2::\<preceq>(G,L)))
                     | Jump j => s2 = s1
                     | Error e => s2 = s1)"
    apply (simp (no_asm_simp) only: split_tupled_all)
    apply (erule sxalloc.induct)
    apply   auto
    apply (rule halloc_conforms [THEN conforms_xconf])
    apply     (auto elim!: halloc_elim_cases dest!: new_AddrD intro!: conf_AddrI)
    done

    lemma wt_init_comp_ty:
    "is_acc_type G (pid C) T ==> (|prg=G,cls=C,lcl=L|)),\<turnstile>init_comp_ty T::\<surd>"
    apply (unfold init_comp_ty_def)
    apply (clarsimp simp add: accessible_in_RefT_simp
                              is_acc_type_def is_acc_class_def)
    done

    declare fun_upd_same [simp]

    declare fun_upd_apply [simp del]

    constdefs
      DynT_prop::"[prog,inv_mode,qtname,ref_ty] => bool"
                                                  ("_\<turnstile>_->_\<preceq>_"[71,71,71,71]70)
     "G\<turnstile>mode->D\<preceq>t ≡ mode = IntVir --> is_class G D ∧
                         (if (∃T. t=ArrayT T) then D=Object else G\<turnstile>Class D\<preceq>RefT t)"

    lemma DynT_propI:
     "[|(x,s)::\<preceq>(G, L); G,s\<turnstile>a'::\<preceq>RefT statT; wf_prog G; mode = IntVir --> a' ≠ Null|]
      ==>  G\<turnstile>mode->invocation_class mode s a' statT\<preceq>statT"
    proof (unfold DynT_prop_def)
      assume state_conform: "(x,s)::\<preceq>(G, L)"
         and      statT_a': "G,s\<turnstile>a'::\<preceq>RefT statT"
         and            wf: "wf_prog G"
         and          mode: "mode = IntVir --> a' ≠ Null"
      let ?invCls = "(invocation_class mode s a' statT)"
      let ?IntVir = "mode = IntVir"
      let ?Concl  = "λinvCls. is_class G invCls ∧
                              (if ∃T. statT = ArrayT T
                                      then invCls = Object
                                      else G\<turnstile>Class invCls\<preceq>RefT statT)"
      show "?IntVir --> ?Concl ?invCls"
      proof
        assume modeIntVir: ?IntVir
        with mode have not_Null: "a' ≠ Null" ..
        from statT_a' not_Null state_conform
        obtain a obj
          where obj_props:  "a' = Addr a" "globs s (Inl a) = Some obj"
                            "G\<turnstile>obj_ty obj\<preceq>RefT statT" "is_type G (obj_ty obj)"
          by (blast dest: conforms_RefTD)
        show "?Concl ?invCls"
        proof (cases "tag obj")
          case CInst
          with modeIntVir obj_props
          show ?thesis
            by (auto dest!: widen_Array2 split add: split_if)
        next
          case Arr
          from Arr obtain T where "obj_ty obj = T.[]" by (blast dest: obj_ty_Arr1)
          moreover from Arr have "obj_class obj = Object"
            by (blast dest: obj_class_Arr1)
          moreover note modeIntVir obj_props wf
          ultimately show ?thesis by (auto dest!: widen_Array )
        qed
      qed
    qed

    lemma invocation_methd:
    "[|wf_prog G; statT ≠ NullT;
     (∀ statC. statT = ClassT statC --> is_class G statC);
     (∀     I. statT = IfaceT I --> is_iface G I ∧ mode ≠ SuperM);
     (∀     T. statT = ArrayT T --> mode ≠ SuperM);
     G\<turnstile>mode->invocation_class mode s a' statT\<preceq>statT;
     dynlookup G statT (invocation_class mode s a' statT) sig = Some m |]
    ==> methd G (invocation_declclass G mode s a' statT sig) sig = Some m"
    proof -
      assume         wf: "wf_prog G"
         and  not_NullT: "statT ≠ NullT"
         and statC_prop: "(∀ statC. statT = ClassT statC --> is_class G statC)"
         and statI_prop: "(∀ I. statT = IfaceT I --> is_iface G I ∧ mode ≠ SuperM)"
         and statA_prop: "(∀     T. statT = ArrayT T --> mode ≠ SuperM)"
         and  invC_prop: "G\<turnstile>mode->invocation_class mode s a' statT\<preceq>statT"
         and  dynlookup: "dynlookup G statT (invocation_class mode s a' statT) sig
                          = Some m"
      show ?thesis
      proof (cases statT)
        case NullT
        with not_NullT show ?thesis by simp
      next
        case IfaceT
        with statI_prop obtain I
          where    statI: "statT = IfaceT I" and
                is_iface: "is_iface G I"     and
              not_SuperM: "mode ≠ SuperM" by blast

        show ?thesis
        proof (cases mode)
          case Static
          with wf dynlookup statI is_iface
          show ?thesis
            by (auto simp add: invocation_declclass_def dynlookup_def
                               dynimethd_def dynmethd_C_C
                        intro: dynmethd_declclass
                        dest!: wf_imethdsD
                         dest: table_of_map_SomeI
                        split: split_if_asm)
        next
          case SuperM
          with not_SuperM show ?thesis ..
        next
          case IntVir
          with wf dynlookup IfaceT invC_prop show ?thesis
            by (auto simp add: invocation_declclass_def dynlookup_def dynimethd_def
                               DynT_prop_def
                        intro: methd_declclass dynmethd_declclass
                        split: split_if_asm)
        qed
      next
        case ClassT
        show ?thesis
        proof (cases mode)
          case Static
          with wf ClassT dynlookup statC_prop
          show ?thesis by (auto simp add: invocation_declclass_def dynlookup_def
                                   intro: dynmethd_declclass)
        next
          case SuperM
          with wf ClassT dynlookup statC_prop
          show ?thesis by (auto simp add: invocation_declclass_def dynlookup_def
                                   intro: dynmethd_declclass)
        next
          case IntVir
          with wf ClassT dynlookup statC_prop invC_prop
          show ?thesis
            by (auto simp add: invocation_declclass_def dynlookup_def dynimethd_def
                               DynT_prop_def
                        intro: dynmethd_declclass)
        qed
      next
        case ArrayT
        show ?thesis
        proof (cases mode)
          case Static
          with wf ArrayT dynlookup show ?thesis
            by (auto simp add: invocation_declclass_def dynlookup_def
                               dynimethd_def dynmethd_C_C
                        intro: dynmethd_declclass
                         dest: table_of_map_SomeI)
        next
          case SuperM
          with ArrayT statA_prop show ?thesis by blast
        next
          case IntVir
          with wf ArrayT dynlookup invC_prop show ?thesis
            by (auto simp add: invocation_declclass_def dynlookup_def dynimethd_def
                               DynT_prop_def dynmethd_C_C
                        intro: dynmethd_declclass
                         dest: table_of_map_SomeI)
        qed
      qed
    qed

    lemma DynT_mheadsD:
    "[|G\<turnstile>invmode sm e->invC\<preceq>statT;
      wf_prog G; (|prg=G,cls=C,lcl=L|)),\<turnstile>e::-RefT statT;
      (statDeclT,sm) ∈ mheads G C statT sig;
      invC = invocation_class (invmode sm e) s a' statT;
      declC =invocation_declclass G (invmode sm e) s a' statT sig
     |] ==>
      ∃ dm.
      methd G declC sig = Some dm ∧ dynlookup G statT invC sig = Some dm  ∧
      G\<turnstile>resTy (mthd dm)\<preceq>resTy sm ∧
      wf_mdecl G declC (sig, mthd dm) ∧
      declC = declclass dm ∧
      is_static dm = is_static sm ∧
      is_class G invC ∧ is_class G declC  ∧ G\<turnstile>invC\<preceq>C declC ∧
      (if invmode sm e = IntVir
          then (∀ statC. statT=ClassT statC --> G\<turnstile>invC \<preceq>C statC)
          else (  (∃ statC. statT=ClassT statC ∧ G\<turnstile>statC\<preceq>C declC)
                ∨ (∀ statC. statT≠ClassT statC ∧ declC=Object)) ∧
                statDeclT = ClassT (declclass dm))"
    proof -
      assume invC_prop: "G\<turnstile>invmode sm e->invC\<preceq>statT"
         and        wf: "wf_prog G"
         and      wt_e: "(|prg=G,cls=C,lcl=L|)),\<turnstile>e::-RefT statT"
         and        sm: "(statDeclT,sm) ∈ mheads G C statT sig"
         and      invC: "invC = invocation_class (invmode sm e) s a' statT"
         and     declC: "declC =
                        invocation_declclass G (invmode sm e) s a' statT sig"
      from wt_e wf have type_statT: "is_type G (RefT statT)"
        by (auto dest: ty_expr_is_type)
      from sm have not_Null: "statT ≠ NullT" by auto
      from type_statT
      have wf_C: "(∀ statC. statT = ClassT statC --> is_class G statC)"
        by (auto)
      from type_statT wt_e
      have wf_I: "(∀I. statT = IfaceT I --> is_iface G I ∧
                                            invmode sm e ≠ SuperM)"
        by (auto dest: invocationTypeExpr_noClassD)
      from wt_e
      have wf_A: "(∀     T. statT = ArrayT T --> invmode sm e ≠ SuperM)"
        by (auto dest: invocationTypeExpr_noClassD)
      show ?thesis
      proof (cases "invmode sm e = IntVir")
        case True
        with invC_prop not_Null
        have invC_prop': " is_class G invC ∧
                          (if (∃T. statT=ArrayT T) then invC=Object
                                                  else G\<turnstile>Class invC\<preceq>RefT statT)"
          by (auto simp add: DynT_prop_def)
        from True
        have "¬ is_static sm"
          by (simp add: invmode_IntVir_eq member_is_static_simp)
        with invC_prop' not_Null
        have "G,statT \<turnstile> invC valid_lookup_cls_for (is_static sm)"
          by (cases statT) auto
        with sm wf type_statT obtain dm where
               dm: "dynlookup G statT invC sig = Some dm" and
          resT_dm: "G\<turnstile>resTy (mthd dm)\<preceq>resTy sm"      and
           static: "is_static dm = is_static sm"
          by  - (drule dynamic_mheadsD,force+)
        with declC invC not_Null
        have declC': "declC = (declclass dm)"
          by (auto simp add: invocation_declclass_def)
        with wf invC declC not_Null wf_C wf_I wf_A invC_prop dm
        have dm': "methd G declC sig = Some dm"
          by - (drule invocation_methd,auto)
        from wf dm invC_prop' declC' type_statT
        have declC_prop: "G\<turnstile>invC \<preceq>C declC ∧ is_class G declC"
          by (auto dest: dynlookup_declC)
        from wf dm' declC_prop declC'
        have wf_dm: "wf_mdecl G declC (sig,(mthd dm))"
          by (auto dest: methd_wf_mdecl)
        from invC_prop'
        have statC_prop: "(∀ statC. statT=ClassT statC --> G\<turnstile>invC \<preceq>C statC)"
          by auto
        from True dm' resT_dm wf_dm invC_prop' declC_prop statC_prop declC' static
             dm
        show ?thesis by auto
      next
        case False
        with type_statT wf invC not_Null wf_I wf_A
        have invC_prop': "is_class G invC ∧
                         ((∃ statC. statT=ClassT statC ∧ invC=statC) ∨
                          (∀ statC. statT≠ClassT statC ∧ invC=Object))"
            by (case_tac "statT") (auto simp add: invocation_class_def
                                           split: inv_mode.splits)
        with not_Null wf
        have dynlookup_static: "dynlookup G statT invC sig = methd G invC sig"
          by (case_tac "statT") (auto simp add: dynlookup_def dynmethd_C_C
                                                dynimethd_def)
        from sm wf wt_e not_Null False invC_prop' obtain "dm" where
                        dm: "methd G invC sig = Some dm"          and
            eq_declC_sm_dm:"statDeclT = ClassT (declclass dm)"  and
                 eq_mheads:"sm=mhead (mthd dm) "
          by - (drule static_mheadsD, (force dest: accmethd_SomeD)+)
        then have static: "is_static dm = is_static sm" by - (auto)
        with declC invC dynlookup_static dm
        have declC': "declC = (declclass dm)"
          by (auto simp add: invocation_declclass_def)
        from invC_prop' wf declC' dm
        have dm': "methd G declC sig = Some dm"
          by (auto intro: methd_declclass)
        from dynlookup_static dm
        have dm'': "dynlookup G statT invC sig = Some dm"
          by simp
        from wf dm invC_prop' declC' type_statT
        have declC_prop: "G\<turnstile>invC \<preceq>C declC ∧ is_class G declC"
          by (auto dest: methd_declC )
        then have declC_prop1: "invC=Object --> declC=Object"  by auto
        from wf dm' declC_prop declC'
        have wf_dm: "wf_mdecl G declC (sig,(mthd dm))"
          by (auto dest: methd_wf_mdecl)
        from invC_prop' declC_prop declC_prop1
        have statC_prop: "(   (∃ statC. statT=ClassT statC ∧ G\<turnstile>statC\<preceq>C declC)
                           ∨  (∀ statC. statT≠ClassT statC ∧ declC=Object))"
          by auto
        from False dm' dm'' wf_dm invC_prop' declC_prop statC_prop declC'
             eq_declC_sm_dm eq_mheads static
        show ?thesis by auto
      qed
    qed

    corollary DynT_mheadsE [consumes 7]:
    --{* Same as @{text DynT_mheadsD} but better suited for application in
    typesafety proof   *}
     assumes invC_compatible: "G\<turnstile>mode->invC\<preceq>statT"
         and wf: "wf_prog G"
         and wt_e: "(|prg=G,cls=C,lcl=L|)),\<turnstile>e::-RefT statT"
         and mheads: "(statDeclT,sm) ∈ mheads G C statT sig"
         and mode: "mode=invmode sm e"
         and invC: "invC = invocation_class mode s a' statT"
         and declC: "declC =invocation_declclass G mode s a' statT sig"
         and dm: "!! dm. [|methd G declC sig = Some dm;
                          dynlookup G statT invC sig = Some dm;
                          G\<turnstile>resTy (mthd dm)\<preceq>resTy sm;
                          wf_mdecl G declC (sig, mthd dm);
                          declC = declclass dm;
                          is_static dm = is_static sm;
                          is_class G invC; is_class G declC; G\<turnstile>invC\<preceq>C declC;
                          (if invmode sm e = IntVir
                          then (∀ statC. statT=ClassT statC --> G\<turnstile>invC \<preceq>C statC)
                          else (  (∃ statC. statT=ClassT statC ∧ G\<turnstile>statC\<preceq>C declC)
                                 ∨ (∀ statC. statT≠ClassT statC ∧ declC=Object)) ∧
                                 statDeclT = ClassT (declclass dm))|] ==> P"
       shows "P"
    proof -
        from invC_compatible mode have "G\<turnstile>invmode sm e->invC\<preceq>statT" by simp
        moreover note wf wt_e mheads
        moreover from invC mode
        have "invC = invocation_class (invmode sm e) s a' statT" by simp
        moreover from declC mode
        have "declC =invocation_declclass G (invmode sm e) s a' statT sig" by simp
        ultimately show ?thesis
          by (rule DynT_mheadsD [THEN exE,rule_format])
             (elim conjE,rule dm)
    qed

    lemma DynT_conf: "[|G\<turnstile>invocation_class mode s a' statT \<preceq>C declC; wf_prog G;
     isrtype G (statT);
     G,s\<turnstile>a'::\<preceq>RefT statT; mode = IntVir --> a' ≠ Null;
      mode ≠ IntVir -->    (∃ statC. statT=ClassT statC ∧ G\<turnstile>statC\<preceq>C declC)
                        ∨  (∀ statC. statT≠ClassT statC ∧ declC=Object)|]
     ==>G,s\<turnstile>a'::\<preceq> Class declC"
    apply (case_tac "mode = IntVir")
    apply (drule conf_RefTD)
    apply (force intro!: conf_AddrI
                simp add: obj_class_def split add: obj_tag.split_asm)
    apply  clarsimp
    apply  safe
    apply    (erule (1) widen.subcls [THEN conf_widen])
    apply    (erule wf_ws_prog)

    apply    (frule widen_Object) apply (erule wf_ws_prog)
    apply    (erule (1) conf_widen) apply (erule wf_ws_prog)
    done

    lemma Ass_lemma:
    "[| G\<turnstile>Norm s0 \<midarrow>var=\<succ>(w, f)-> Norm s1; G\<turnstile>Norm s1 \<midarrow>e-\<succ>v-> Norm s2;
       G,s2\<turnstile>v::\<preceq>eT;s1≤|s2 --> assign f v (Norm s2)::\<preceq>(G, L)|]
    ==> assign f v (Norm s2)::\<preceq>(G, L) ∧
          (normal (assign f v (Norm s2)) --> G,store (assign f v (Norm s2))\<turnstile>v::\<preceq>eT)"
    apply (drule_tac x = "None" and s = "s2" and v = "v" in evar_gext_f)
    apply (drule eval_gext', clarsimp)
    apply (erule conf_gext)
    apply simp
    done

    lemma Throw_lemma: "[|G\<turnstile>tn\<preceq>C SXcpt Throwable; wf_prog G; (x1,s1)::\<preceq>(G, L);
        x1 = None --> G,s1\<turnstile>a'::\<preceq> Class tn|] ==> (throw a' x1, s1)::\<preceq>(G, L)"
    apply (auto split add: split_abrupt_if simp add: throw_def2)
    apply (erule conforms_xconf)
    apply (frule conf_RefTD)
    apply (auto elim: widen.subcls [THEN conf_widen])
    done

    lemma Try_lemma: "[|G\<turnstile>obj_ty (the (globs s1' (Heap a)))\<preceq> Class tn;
     (Some (Xcpt (Loc a)), s1')::\<preceq>(G, L); wf_prog G|]
     ==> Norm (lupd(vn\<mapsto>Addr a) s1')::\<preceq>(G, L(vn\<mapsto>Class tn))"
    apply (rule conforms_allocL)
    apply  (erule conforms_NormI)
    apply (drule conforms_XcptLocD [THEN conf_RefTD],rule HOL.refl)
    apply (auto intro!: conf_AddrI)
    done

    lemma Fin_lemma:
    "[|G\<turnstile>Norm s1 \<midarrow>c2-> (x2,s2); wf_prog G; (Some a, s1)::\<preceq>(G, L); (x2,s2)::\<preceq>(G, L);
      dom (locals s1) ⊆ dom (locals s2)|]
    ==>  (abrupt_if True (Some a) x2, s2)::\<preceq>(G, L)"
    apply (auto elim: eval_gext' conforms_xgext split add: split_abrupt_if)
    done

    lemma FVar_lemma1:
    "[|table_of (DeclConcepts.fields G statC) (fn, statDeclC) = Some f ;
      x2 = None --> G,s2\<turnstile>a::\<preceq> Class statC; wf_prog G; G\<turnstile>statC\<preceq>C statDeclC;
      statDeclC ≠ Object;
      class G statDeclC = Some y; (x2,s2)::\<preceq>(G, L); s1≤|s2;
      inited statDeclC (globs s1);
      (if static f then id else np a) x2 = None|]
     ==>
      ∃obj. globs s2 (if static f then Inr statDeclC else Inl (the_Addr a))
                      = Some obj ∧
      var_tys G (tag obj)  (if static f then Inr statDeclC else Inl(the_Addr a))
              (Inl(fn,statDeclC)) = Some (type f)"
    apply (drule initedD)
    apply (frule subcls_is_class2, simp (no_asm_simp))
    apply (case_tac "static f")
    apply  clarsimp
    apply  (drule (1) rev_gext_objD, clarsimp)
    apply  (frule fields_declC, erule wf_ws_prog, simp (no_asm_simp))
    apply  (rule var_tys_Some_eq [THEN iffD2])
    apply  clarsimp
    apply  (erule fields_table_SomeI, simp (no_asm))
    apply clarsimp
    apply (drule conf_RefTD, clarsimp, rule var_tys_Some_eq [THEN iffD2])
    apply (auto dest!: widen_Array split add: obj_tag.split)
    apply (rule fields_table_SomeI)
    apply (auto elim!: fields_mono subcls_is_class2)
    done

    lemma FVar_lemma2: "error_free state
           ==> error_free
               (assign
                 (λv. supd
                       (upd_gobj
                         (if static field then Inr statDeclC
                          else Inl (the_Addr a))
                         (Inl (fn, statDeclC)) v))
                 w state)"
    proof -
      assume error_free: "error_free state"
      obtain a s where "state=(a,s)"
        by (cases state) simp
      with error_free
      show ?thesis
        by (cases a) auto
    qed

    declare split_paired_All [simp del] split_paired_Ex [simp del]
    declare split_if     [split del] split_if_asm     [split del]
            option.split [split del] option.split_asm [split del]
    ML_setup {*
    simpset_ref() := simpset() delloop "split_all_tac";
    claset_ref () := claset () delSWrapper "split_all_tac"
    *}
    lemma FVar_lemma:
    "[|((v, f), Norm s2') = fvar statDeclC (static field) fn a (x2, s2);
      G\<turnstile>statC\<preceq>C statDeclC;
      table_of (DeclConcepts.fields G statC) (fn, statDeclC) = Some field;
      wf_prog G;
      x2 = None --> G,s2\<turnstile>a::\<preceq>Class statC;
      statDeclC ≠ Object; class G statDeclC = Some y;
      (x2, s2)::\<preceq>(G, L); s1≤|s2; inited statDeclC (globs s1)|] ==>
      G,s2'\<turnstile>v::\<preceq>type field ∧ s2'≤|f\<preceq>type field::\<preceq>(G, L)"
    apply (unfold assign_conforms_def)
    apply (drule sym)
    apply (clarsimp simp add: fvar_def2)
    apply (drule (9) FVar_lemma1)
    apply (clarsimp)
    apply (drule (2) conforms_globsD [THEN oconf_lconf, THEN lconfD])
    apply clarsimp
    apply (rule conjI)
    apply   clarsimp
    apply   (drule (1) rev_gext_objD)
    apply   (force elim!: conforms_upd_gobj)

    apply   (blast intro: FVar_lemma2)
    done
    declare split_paired_All [simp] split_paired_Ex [simp]
    declare split_if     [split] split_if_asm     [split]
            option.split [split] option.split_asm [split]
    ML_setup {*
    claset_ref()  := claset() addSbefore ("split_all_tac", split_all_tac);
    simpset_ref() := simpset() addloop ("split_all_tac", split_all_tac)
    *}

    lemma AVar_lemma1: "[|globs s (Inl a) = Some obj;tag obj=Arr ty i;
     the_Intg i' in_bounds i; wf_prog G; G\<turnstile>ty.[]\<preceq>Tb.[]; Norm s::\<preceq>(G, L)
    |] ==> G,s\<turnstile>the ((values obj) (Inr (the_Intg i')))::\<preceq>Tb"
    apply (erule widen_Array_Array [THEN conf_widen])
    apply  (erule_tac [2] wf_ws_prog)
    apply (drule (1) conforms_globsD [THEN oconf_lconf, THEN lconfD])
    defer apply assumption
    apply (force intro: var_tys_Some_eq [THEN iffD2])
    done

    lemma obj_split: "∃ t vs. obj = (|tag=t,values=vs|)),"
      by (cases obj) auto

    lemma AVar_lemma2: "error_free state
           ==> error_free
               (assign
                 (λv (x, s').
                     ((raise_if (¬ G,s'\<turnstile>v fits T) ArrStore) x,
                      upd_gobj (Inl a) (Inr (the_Intg i)) v s'))
                 w state)"
    proof -
      assume error_free: "error_free state"
      obtain a s where "state=(a,s)"
        by (cases state) simp
      with error_free
      show ?thesis
        by (cases a) auto
    qed

    lemma AVar_lemma: "[|wf_prog G; G\<turnstile>(x1, s1) \<midarrow>e2-\<succ>i-> (x2, s2);
      ((v,f), Norm s2') = avar G i a (x2, s2); x1 = None --> G,s1\<turnstile>a::\<preceq>Ta.[];
      (x2, s2)::\<preceq>(G, L); s1≤|s2|] ==> G,s2'\<turnstile>v::\<preceq>Ta ∧ s2'≤|f\<preceq>Ta::\<preceq>(G, L)"
    apply (unfold assign_conforms_def)
    apply (drule sym)
    apply (clarsimp simp add: avar_def2)
    apply (drule (1) conf_gext)
    apply (drule conf_RefTD, clarsimp)
    apply (subgoal_tac "∃ t vs. obj = (|tag=t,values=vs|)),")
    defer
    apply   (rule obj_split)
    apply clarify
    apply (frule obj_ty_widenD)
    apply (auto dest!: widen_Class)
    apply   (force dest: AVar_lemma1)

    apply   (force elim!: fits_Array dest: gext_objD
             intro: var_tys_Some_eq [THEN iffD2] conforms_upd_gobj)
    done

    section "Call"

    lemma conforms_init_lvars_lemma: "[|wf_prog G;
      wf_mhead G P sig mh;
      list_all2 (conf G s) pvs pTsa; G\<turnstile>pTsa[\<preceq>](parTs sig)|] ==>
      G,s\<turnstile>empty (pars mh[\<mapsto>]pvs)
          [∼::\<preceq>]table_of lvars(pars mh[\<mapsto>]parTs sig)"
    apply (unfold wf_mhead_def)
    apply clarify
    apply (erule (1) wlconf_empty_vals [THEN wlconf_ext_list])
    apply (drule wf_ws_prog)
    apply (erule (2) conf_list_widen)
    done

    lemma lconf_map_lname [simp]:
      "G,s\<turnstile>(lname_case l1 l2)[::\<preceq>](lname_case L1 L2)
       =
      (G,s\<turnstile>l1[::\<preceq>]L1 ∧ G,s\<turnstile>(λx::unit . l2)[::\<preceq>](λx::unit. L2))"
    apply (unfold lconf_def)
    apply (auto split add: lname.splits)
    done

    lemma wlconf_map_lname [simp]:
      "G,s\<turnstile>(lname_case l1 l2)[∼::\<preceq>](lname_case L1 L2)
       =
      (G,s\<turnstile>l1[∼::\<preceq>]L1 ∧ G,s\<turnstile>(λx::unit . l2)[∼::\<preceq>](λx::unit. L2))"
    apply (unfold wlconf_def)
    apply (auto split add: lname.splits)
    done

    lemma lconf_map_ename [simp]:
      "G,s\<turnstile>(ename_case l1 l2)[::\<preceq>](ename_case L1 L2)
       =
      (G,s\<turnstile>l1[::\<preceq>]L1 ∧ G,s\<turnstile>(λx::unit. l2)[::\<preceq>](λx::unit. L2))"
    apply (unfold lconf_def)
    apply (auto split add: ename.splits)
    done

    lemma wlconf_map_ename [simp]:
      "G,s\<turnstile>(ename_case l1 l2)[∼::\<preceq>](ename_case L1 L2)
       =
      (G,s\<turnstile>l1[∼::\<preceq>]L1 ∧ G,s\<turnstile>(λx::unit. l2)[∼::\<preceq>](λx::unit. L2))"
    apply (unfold wlconf_def)
    apply (auto split add: ename.splits)
    done

    lemma defval_conf1 [rule_format (no_asm), elim]:
      "is_type G T --> (∃v∈Some (default_val T): G,s\<turnstile>v::\<preceq>T)"
    apply (unfold conf_def)
    apply (induct "T")
    apply (auto intro: prim_ty.induct)
    done

    lemma np_no_jump: "x≠Some (Jump j) ==> (np a') x ≠ Some (Jump j)"
    by (auto simp add: abrupt_if_def)

    declare split_paired_All [simp del] split_paired_Ex [simp del]
    declare split_if     [split del] split_if_asm     [split del]
            option.split [split del] option.split_asm [split del]
    ML_setup {*
    simpset_ref() := simpset() delloop "split_all_tac";
    claset_ref () := claset () delSWrapper "split_all_tac"
    *}
    lemma conforms_init_lvars:
    "[|wf_mhead G (pid declC) sig (mhead (mthd dm)); wf_prog G;
      list_all2 (conf G s) pvs pTsa; G\<turnstile>pTsa[\<preceq>](parTs sig);
      (x, s)::\<preceq>(G, L);
      methd G declC sig = Some dm;
      isrtype G statT;
      G\<turnstile>invC\<preceq>C declC;
      G,s\<turnstile>a'::\<preceq>RefT statT;
      invmode (mhd sm) e = IntVir --> a' ≠ Null;
      invmode (mhd sm) e ≠ IntVir -->
           (∃ statC. statT=ClassT statC ∧ G\<turnstile>statC\<preceq>C declC)
        ∨  (∀ statC. statT≠ClassT statC ∧ declC=Object);
      invC  = invocation_class (invmode (mhd sm) e) s a' statT;
      declC = invocation_declclass G (invmode (mhd sm) e) s a' statT sig;
      x≠Some (Jump Ret)
     |] ==>
      init_lvars G declC sig (invmode (mhd sm) e) a'
      pvs (x,s)::\<preceq>(G,λ k.
                    (case k of
                       EName e => (case e of
                                     VNam v
                                      => (table_of (lcls (mbody (mthd dm)))
                                            (pars (mthd dm)[\<mapsto>]parTs sig)) v
                                   | Res => Some (resTy (mthd dm)))
                     | This => if (is_static (mthd sm))
                                  then None else Some (Class declC)))"
    apply (simp add: init_lvars_def2)
    apply (rule conforms_set_locals)
    apply  (simp (no_asm_simp) split add: split_if)
    apply (drule  (4) DynT_conf)
    apply clarsimp
    (* apply intro *)
    apply (drule (3) conforms_init_lvars_lemma
                     [where ?lvars="(lcls (mbody (mthd dm)))"])
    apply (case_tac "dm",simp)
    apply (rule conjI)
    apply (unfold wlconf_def, clarify)
    apply   (clarsimp simp add: wf_mhead_def is_acc_type_def)
    apply   (case_tac "is_static sm")
    apply     simp
    apply     simp

    apply   simp
    apply   (case_tac "is_static sm")
    apply     simp
    apply     (simp add: np_no_jump)
    done
    declare split_paired_All [simp] split_paired_Ex [simp]
    declare split_if     [split] split_if_asm     [split]
            option.split [split] option.split_asm [split]
    ML_setup {*
    claset_ref()  := claset() addSbefore ("split_all_tac", split_all_tac);
    simpset_ref() := simpset() addloop ("split_all_tac", split_all_tac)
    *}

    subsection "accessibility"

    text {*
    \par
    *} (* dummy text command to break paragraph for latex;
                  large paragraphs exhaust memory of debian pdflatex *)

    theorem dynamic_field_access_ok:
      assumes wf: "wf_prog G" and
        not_Null: "¬ stat --> a≠Null" and
       conform_a: "G,(store s)\<turnstile>a::\<preceq> Class statC" and
       conform_s: "s::\<preceq>(G, L)" and
        normal_s: "normal s" and
            wt_e: "(|prg=G,cls=accC,lcl=L|)),\<turnstile>e::-Class statC" and
               f: "accfield G accC statC fn = Some f" and
            dynC: "if stat then dynC=declclass f
                           else dynC=obj_class (lookup_obj (store s) a)" and
            stat: "if stat then (is_static f) else (¬ is_static f)"
      shows "table_of (DeclConcepts.fields G dynC) (fn,declclass f) = Some (fld f)∧
             G\<turnstile>Field fn f in dynC dyn_accessible_from accC"
    proof (cases "stat")
      case True
      with stat have static: "(is_static f)" by simp
      from True dynC
      have dynC': "dynC=declclass f" by simp
      with f
      have "table_of (DeclConcepts.fields G statC) (fn,declclass f) = Some (fld f)"
        by (auto simp add: accfield_def Let_def intro!: table_of_remap_SomeD)
      moreover
      from wt_e wf have "is_class G statC"
        by (auto dest!: ty_expr_is_type)
      moreover note wf dynC'
      ultimately have
         "table_of (DeclConcepts.fields G dynC) (fn,declclass f) = Some (fld f)"
        by (auto dest: fields_declC)
      with dynC' f static wf
      show ?thesis
        by (auto dest: static_to_dynamic_accessible_from_static
                dest!: accfield_accessibleD )
    next
      case False
      with wf conform_a not_Null conform_s dynC
      obtain subclseq: "G\<turnstile>dynC \<preceq>C statC" and
        "is_class G dynC"
        by (auto dest!: conforms_RefTD [of _ _ _ _ "(fst s)" L]
                  dest: obj_ty_obj_class1
              simp add: obj_ty_obj_class )
      with wf f
      have "table_of (DeclConcepts.fields G dynC) (fn,declclass f) = Some (fld f)"
        by (auto simp add: accfield_def Let_def
                     dest: fields_mono
                    dest!: table_of_remap_SomeD)
      moreover
      from f subclseq
      have "G\<turnstile>Field fn f in dynC dyn_accessible_from accC"
        by (auto intro!: static_to_dynamic_accessible_from
                   dest: accfield_accessibleD)
      ultimately show ?thesis
        by blast
    qed

    lemma error_free_field_access:
      assumes accfield: "accfield G accC statC fn = Some (statDeclC, f)" and
                  wt_e: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>e::-Class statC" and
             eval_init: "G\<turnstile>Norm s0 \<midarrow>Init statDeclC-> s1" and
                eval_e: "G\<turnstile>s1 \<midarrow>e-\<succ>a-> s2" and
               conf_s2: "s2::\<preceq>(G, L)" and
                conf_a: "normal s2 ==> G, store s2\<turnstile>a::\<preceq>Class statC" and
                  fvar: "(v,s2')=fvar statDeclC (is_static f) fn a s2" and
                    wf: "wf_prog G"
      shows "check_field_access G accC statDeclC fn (is_static f) a s2' = s2'"
    proof -
      from fvar
      have store_s2': "store s2'=store s2"
        by (cases s2) (simp add: fvar_def2)
      with fvar conf_s2
      have conf_s2': "s2'::\<preceq>(G, L)"
        by (cases s2,cases "is_static f") (auto simp add: fvar_def2)
      from eval_init
      have initd_statDeclC_s1: "initd statDeclC s1"
        by (rule init_yields_initd)
      with eval_e store_s2'
      have initd_statDeclC_s2': "initd statDeclC s2'"
        by (auto dest: eval_gext intro: inited_gext)
      show ?thesis
      proof (cases "normal s2'")
        case False
        then show ?thesis
          by (auto simp add: check_field_access_def Let_def)
      next
        case True
        with fvar store_s2'
        have not_Null: "¬ (is_static f) --> a≠Null"
          by (cases s2) (auto simp add: fvar_def2)
        from True fvar store_s2'
        have "normal s2"
          by (cases s2,cases "is_static f") (auto simp add: fvar_def2)
        with conf_a store_s2'
        have conf_a': "G,store s2'\<turnstile>a::\<preceq>Class statC"
          by simp
        from conf_a' conf_s2' True initd_statDeclC_s2'
          dynamic_field_access_ok [OF wf not_Null conf_a' conf_s2'
                                       True wt_e accfield ]
        show ?thesis
          by  (cases "is_static f")
              (auto dest!: initedD
               simp add: check_field_access_def Let_def)
      qed
    qed

    lemma call_access_ok:
      assumes invC_prop: "G\<turnstile>invmode statM e->invC\<preceq>statT"
          and        wf: "wf_prog G"
          and      wt_e: "(|prg=G,cls=C,lcl=L|)),\<turnstile>e::-RefT statT"
          and     statM: "(statDeclT,statM) ∈ mheads G accC statT sig"
          and      invC: "invC = invocation_class (invmode statM e) s a statT"
      shows "∃ dynM. dynlookup G statT invC sig = Some dynM ∧
      G\<turnstile>Methd sig dynM in invC dyn_accessible_from accC"
    proof -
      from wt_e wf have type_statT: "is_type G (RefT statT)"
        by (auto dest: ty_expr_is_type)
      from statM have not_Null: "statT ≠ NullT" by auto
      from type_statT wt_e
      have wf_I: "(∀I. statT = IfaceT I --> is_iface G I ∧
                                            invmode statM e ≠ SuperM)"
        by (auto dest: invocationTypeExpr_noClassD)
      from wt_e
      have wf_A: "(∀     T. statT = ArrayT T --> invmode statM e ≠ SuperM)"
        by (auto dest: invocationTypeExpr_noClassD)
      show ?thesis
      proof (cases "invmode statM e = IntVir")
        case True
        with invC_prop not_Null
        have invC_prop': "is_class G invC ∧
                          (if (∃T. statT=ArrayT T) then invC=Object
                                                  else G\<turnstile>Class invC\<preceq>RefT statT)"
          by (auto simp add: DynT_prop_def)
        with True not_Null
        have "G,statT \<turnstile> invC valid_lookup_cls_for is_static statM"
         by (cases statT) (auto simp add: invmode_def)
        with statM type_statT wf
        show ?thesis
          by - (rule dynlookup_access,auto)
      next
        case False
        with type_statT wf invC not_Null wf_I wf_A
        have invC_prop': " is_class G invC ∧
                          ((∃ statC. statT=ClassT statC ∧ invC=statC) ∨
                          (∀ statC. statT≠ClassT statC ∧ invC=Object)) "
            by (case_tac "statT") (auto simp add: invocation_class_def
                                           split: inv_mode.splits)
        with not_Null wf
        have dynlookup_static: "dynlookup G statT invC sig = methd G invC sig"
          by (case_tac "statT") (auto simp add: dynlookup_def dynmethd_C_C
                                                dynimethd_def)
       from statM wf wt_e not_Null False invC_prop' obtain dynM where
                    "accmethd G accC invC sig = Some dynM"
         by (auto dest!: static_mheadsD)
       from invC_prop' False not_Null wf_I
       have "G,statT \<turnstile> invC valid_lookup_cls_for is_static statM"
         by (cases statT) (auto simp add: invmode_def)
       with statM type_statT wf
        show ?thesis
          by - (rule dynlookup_access,auto)
      qed
    qed

    lemma error_free_call_access:
      assumes
       eval_args: "G\<turnstile>s1 \<midarrow>args\<doteq>\<succ>vs-> s2" and
            wt_e: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>e::-(RefT statT)" and
           statM: "max_spec G accC statT (|name = mn, parTs = pTs|)),
                   = {((statDeclT, statM), pTs')}" and
         conf_s2: "s2::\<preceq>(G, L)" and
          conf_a: "normal s1 ==> G, store s1\<turnstile>a::\<preceq>RefT statT" and
         invProp: "normal s3 ==>
                    G\<turnstile>invmode statM e->invC\<preceq>statT" and
              s3: "s3=init_lvars G invDeclC (|name = mn, parTs = pTs'|)),
                            (invmode statM e) a vs s2" and
            invC: "invC = invocation_class (invmode statM e) (store s2) a statT"and
        invDeclC: "invDeclC = invocation_declclass G (invmode statM e) (store s2)
                                 a statT (|name = mn, parTs = pTs'|))," and
              wf: "wf_prog G"
      shows "check_method_access G accC statT (invmode statM e) (|name=mn,parTs=pTs'|)), a s3
       = s3"
    proof (cases "normal s2")
      case False
      with s3
      have "abrupt s3 = abrupt s2"
        by (auto simp add: init_lvars_def2)
      with False
      show ?thesis
        by (auto simp add: check_method_access_def Let_def)
    next
      case True
      note normal_s2 = True
      with eval_args
      have normal_s1: "normal s1"
        by (cases "normal s1") auto
      with conf_a eval_args
      have conf_a_s2: "G, store s2\<turnstile>a::\<preceq>RefT statT"
        by (auto dest: eval_gext intro: conf_gext)
      show ?thesis
      proof (cases "a=Null --> (is_static statM)")
        case False
        then obtain "¬ is_static statM" "a=Null"
          by blast
        with normal_s2 s3
        have "abrupt s3 = Some (Xcpt (Std NullPointer))"
          by (auto simp add: init_lvars_def2)
        then show ?thesis
          by (auto simp add: check_method_access_def Let_def)
      next
        case True
        from statM
        obtain
          statM': "(statDeclT,statM)∈mheads G accC statT (|name=mn,parTs=pTs'|)),"
          by (blast dest: max_spec2mheads)
        from True normal_s2 s3
        have "normal s3"
          by (auto simp add: init_lvars_def2)
        then have "G\<turnstile>invmode statM e->invC\<preceq>statT"
          by (rule invProp)
        with wt_e statM' wf invC
        obtain dynM where
          dynM: "dynlookup G statT invC  (|name=mn,parTs=pTs'|)), = Some dynM" and
          acc_dynM: "G \<turnstile>Methd  (|name=mn,parTs=pTs'|)), dynM
                              in invC dyn_accessible_from accC"
          by (force dest!: call_access_ok)
        moreover
        from s3 invC
        have invC': "invC=(invocation_class (invmode statM e) (store s3) a statT)"
          by (cases s2,cases "invmode statM e")
             (simp add: init_lvars_def2 del: invmode_Static_eq)+
        ultimately
        show ?thesis
          by (auto simp add: check_method_access_def Let_def)
      qed
    qed

    lemma map_upds_eq_length_append_simp:
      "!! tab qs. length ps = length qs ==>  tab(ps[\<mapsto>]qs@zs) = tab(ps[\<mapsto>]qs)"
    proof (induct ps)
      case Nil thus ?case by simp
    next
      case (Cons p ps tab qs)
      have "length (p#ps) = length qs" .
      then obtain q qs' where qs: "qs=q#qs'" and eq_length: "length ps=length qs'"
        by (cases qs) auto
      from eq_length have "(tab(p\<mapsto>q))(ps[\<mapsto>]qs'@zs)=(tab(p\<mapsto>q))(ps[\<mapsto>]qs')"
        by (rule Cons.hyps)
      with qs show ?case
        by simp
    qed

    lemma map_upds_upd_eq_length_simp:
      "!! tab qs x y. length ps = length qs
                      ==> tab(ps[\<mapsto>]qs)(x\<mapsto>y) = tab(ps@[x][\<mapsto>]qs@[y])"
    proof (induct "ps")
      case Nil thus ?case by simp
    next
      case (Cons p ps tab qs x y)
      have "length (p#ps) = length qs" .
      then obtain q qs' where qs: "qs=q#qs'" and eq_length: "length ps=length qs'"
        by (cases qs) auto
      from eq_length
      have "(tab(p\<mapsto>q))(ps[\<mapsto>]qs')(x\<mapsto>y) = (tab(p\<mapsto>q))(ps@[x][\<mapsto>]qs'@[y])"
        by (rule Cons.hyps)
      with qs show ?case
        by simp
    qed

    lemma map_upd_cong: "tab=tab'==> tab(x\<mapsto>y) = tab'(x\<mapsto>y)"
    by simp

    lemma map_upd_cong_ext: "tab z=tab' z==> (tab(x\<mapsto>y)) z = (tab'(x\<mapsto>y)) z"
    by (simp add: fun_upd_def)

    lemma map_upds_cong: "tab=tab'==> tab(xs[\<mapsto>]ys) = tab'(xs[\<mapsto>]ys)"
    by (cases xs) simp+

    lemma map_upds_cong_ext:
     "!! tab tab' ys. tab z=tab' z ==> (tab(xs[\<mapsto>]ys)) z = (tab'(xs[\<mapsto>]ys)) z"
    proof (induct xs)
      case Nil thus ?case by simp
    next
      case (Cons x xs tab tab' ys)
      note Hyps = this
      show ?case
      proof (cases ys)
        case Nil
        thus ?thesis by simp
      next
        case (Cons y ys')
        have "(tab(x\<mapsto>y)(xs[\<mapsto>]ys')) z = (tab'(x\<mapsto>y)(xs[\<mapsto>]ys')) z"
          by (iprover intro: Hyps map_upd_cong_ext)
        with Cons show ?thesis
          by simp
      qed
    qed

    lemma map_upd_override: "(tab(x\<mapsto>y)) x = (tab'(x\<mapsto>y)) x"
      by simp

    lemma map_upds_eq_length_suffix: "!! tab qs.
            length ps = length qs ==> tab(ps@xs[\<mapsto>]qs) = tab(ps[\<mapsto>]qs)(xs[\<mapsto>][])"
    proof (induct ps)
      case Nil thus ?case by simp
    next
      case (Cons p ps tab qs)
      then obtain q qs' where qs: "qs=q#qs'" and eq_length: "length ps=length qs'"
        by (cases qs) auto
      from eq_length
      have "tab(p\<mapsto>q)(ps @ xs[\<mapsto>]qs') = tab(p\<mapsto>q)(ps[\<mapsto>]qs')(xs[\<mapsto>][])"
        by (rule Cons.hyps)
      with qs show ?case
        by simp
    qed

    lemma map_upds_upds_eq_length_prefix_simp:
      "!! tab qs. length ps = length qs
                  ==> tab(ps[\<mapsto>]qs)(xs[\<mapsto>]ys) = tab(ps@xs[\<mapsto>]qs@ys)"
    proof (induct ps)
      case Nil thus ?case by simp
    next
      case (Cons p ps tab qs)
      then obtain q qs' where qs: "qs=q#qs'" and eq_length: "length ps=length qs'"
        by (cases qs) auto
      from eq_length
      have "tab(p\<mapsto>q)(ps[\<mapsto>]qs')(xs[\<mapsto>]ys) = tab(p\<mapsto>q)(ps @ xs[\<mapsto>](qs' @ ys))"
        by (rule Cons.hyps)
      with qs
      show ?case by simp
    qed

    lemma map_upd_cut_irrelevant:
    "[|(tab(x\<mapsto>y)) vn = Some el; (tab'(x\<mapsto>y)) vn = None|]
        ==> tab vn = Some el"
    by (cases "tab' vn = None") (simp add: fun_upd_def)+

    lemma map_upd_Some_expand:
    "[|tab vn = Some z|]
        ==> ∃ z. (tab(x\<mapsto>y)) vn = Some z"
    by (simp add: fun_upd_def)

    lemma map_upds_Some_expand:
    "!! tab ys z. [|tab vn = Some z|]
        ==> ∃ z. (tab(xs[\<mapsto>]ys)) vn = Some z"
    proof (induct xs)
      case Nil thus ?case by simp
    next
      case (Cons x xs tab ys z)
      have z: "tab vn = Some z" .
      show ?case
      proof (cases ys)
        case Nil
        with z show ?thesis by simp
      next
        case (Cons y ys')
        have ys: "ys = y#ys'".
        from z obtain z' where "(tab(x\<mapsto>y)) vn = Some z'"
          by (rule map_upd_Some_expand [of tab,elim_format]) blast
        hence "∃z. ((tab(x\<mapsto>y))(xs[\<mapsto>]ys')) vn = Some z"
          by (rule Cons.hyps)
        with ys show ?thesis
          by simp
      qed
    qed

    lemma map_upd_Some_swap:
     "(tab(r\<mapsto>w)(u\<mapsto>v)) vn = Some z ==> ∃ z. (tab(u\<mapsto>v)(r\<mapsto>w)) vn = Some z"
    by (simp add: fun_upd_def)

    lemma map_upd_None_swap:
     "(tab(r\<mapsto>w)(u\<mapsto>v)) vn = None ==> (tab(u\<mapsto>v)(r\<mapsto>w)) vn = None"
    by (simp add: fun_upd_def)

    lemma map_eq_upd_eq: "tab vn = tab' vn ==> (tab(x\<mapsto>y)) vn = (tab'(x\<mapsto>y)) vn"
    by (simp add: fun_upd_def)

    lemma map_upd_in_expansion_map_swap:
     "[|(tab(x\<mapsto>y)) vn = Some z;tab vn ≠ Some z|]
                     ==>  (tab'(x\<mapsto>y)) vn = Some z"
    by (simp add: fun_upd_def)

    lemma map_upds_in_expansion_map_swap:
     "!!tab tab' ys z. [|(tab(xs[\<mapsto>]ys)) vn = Some z;tab vn ≠ Some z|]
                     ==>  (tab'(xs[\<mapsto>]ys)) vn = Some z"
    proof (induct xs)
      case Nil thus ?case by simp
    next
      case (Cons x xs tab tab' ys z)
      have some: "(tab(x # xs[\<mapsto>]ys)) vn = Some z" .
      have tab_not_z: "tab vn ≠ Some z".
      show ?case
      proof (cases "ys")
        case Nil with some tab_not_z show ?thesis by simp
      next
        case (Cons y tl)
        have ys: "ys = y#tl".
        show ?thesis
        proof (cases "(tab(x\<mapsto>y)) vn ≠ Some z")
          case True
          with some ys have "(tab'(x\<mapsto>y)(xs[\<mapsto>]tl)) vn = Some z"
            by (fastsimp intro: Cons.hyps)
          with ys show ?thesis
            by simp
        next
          case False
          hence tabx_z: "(tab(x\<mapsto>y)) vn = Some z" by blast
          moreover
          from tabx_z tab_not_z
          have "(tab'(x\<mapsto>y)) vn = Some z"
            by (rule map_upd_in_expansion_map_swap)
          ultimately
          have "(tab(x\<mapsto>y)) vn =(tab'(x\<mapsto>y)) vn"
            by simp
          hence "(tab(x\<mapsto>y)(xs[\<mapsto>]tl)) vn = (tab'(x\<mapsto>y)(xs[\<mapsto>]tl)) vn"
            by (rule map_upds_cong_ext)
          with some ys
          show ?thesis
            by simp
        qed
      qed
    qed

    lemma map_upds_Some_swap:
     assumes r_u: "(tab(r\<mapsto>w)(u\<mapsto>v)(xs[\<mapsto>]ys)) vn = Some z"
        shows "∃ z. (tab(u\<mapsto>v)(r\<mapsto>w)(xs[\<mapsto>]ys)) vn = Some z"
    proof (cases "(tab(r\<mapsto>w)(u\<mapsto>v)) vn = Some z")
      case True
      then obtain z' where "(tab(u\<mapsto>v)(r\<mapsto>w)) vn = Some z'"
        by (rule map_upd_Some_swap [elim_format]) blast
      thus "∃ z. (tab(u\<mapsto>v)(r\<mapsto>w)(xs[\<mapsto>]ys)) vn = Some z"
        by (rule map_upds_Some_expand)
    next
      case False
      with r_u
      have "(tab(u\<mapsto>v)(r\<mapsto>w)(xs[\<mapsto>]ys)) vn = Some z"
        by (rule map_upds_in_expansion_map_swap)
      thus ?thesis
        by simp
    qed

    lemma map_upds_Some_insert:
      assumes z: "(tab(xs[\<mapsto>]ys)) vn = Some z"
        shows "∃ z. (tab(u\<mapsto>v)(xs[\<mapsto>]ys)) vn = Some z"
    proof (cases "∃ z. tab vn = Some z")
      case True
      then obtain z' where "tab vn = Some z'" by blast
      then obtain z'' where "(tab(u\<mapsto>v)) vn = Some z''"
        by (rule map_upd_Some_expand [elim_format]) blast
      thus ?thesis
        by (rule map_upds_Some_expand)
    next
      case False
      hence "tab vn ≠ Some z" by simp
      with z
      have "(tab(u\<mapsto>v)(xs[\<mapsto>]ys)) vn = Some z"
        by (rule map_upds_in_expansion_map_swap)
      thus ?thesis ..
    qed

    lemma map_upds_None_cut:
    assumes expand_None: "(tab(xs[\<mapsto>]ys)) vn = None"
      shows "tab vn = None"
    proof (cases "tab vn = None")
      case True thus ?thesis by simp
    next
      case False then obtain z where "tab vn = Some z" by blast
      then obtain z' where "(tab(xs[\<mapsto>]ys)) vn = Some z'"
        by (rule map_upds_Some_expand [where  ?tab="tab",elim_format]) blast
      with expand_None show ?thesis
        by simp
    qed

    lemma map_upds_cut_irrelevant:
    "!! tab tab' ys. [|(tab(xs[\<mapsto>]ys)) vn = Some el; (tab'(xs[\<mapsto>]ys)) vn = None|]
                      ==> tab vn = Some el"
    proof  (induct "xs")
      case Nil thus ?case by simp
    next
      case (Cons x xs tab tab' ys)
      have tab_vn: "(tab(x # xs[\<mapsto>]ys)) vn = Some el".
      have tab'_vn: "(tab'(x # xs[\<mapsto>]ys)) vn = None".
      show ?case
      proof (cases ys)
        case Nil
        with tab_vn show ?thesis by simp
      next
        case (Cons y tl)
        have ys: "ys=y#tl".
        with tab_vn tab'_vn
        have "(tab(x\<mapsto>y)) vn = Some el"
          by - (rule Cons.hyps,auto)
        moreover from tab'_vn ys
        have "(tab'(x\<mapsto>y)(xs[\<mapsto>]tl)) vn = None"
          by simp
        hence "(tab'(x\<mapsto>y)) vn = None"
          by (rule map_upds_None_cut)
        ultimately show "tab vn = Some el"
          by (rule map_upd_cut_irrelevant)
      qed
    qed

    lemma dom_vname_split:
     "dom (lname_case (ename_case (tab(x\<mapsto>y)(xs[\<mapsto>]ys)) a) b)
       = dom (lname_case (ename_case (tab(x\<mapsto>y)) a) b) ∪
         dom (lname_case (ename_case (tab(xs[\<mapsto>]ys)) a) b)"
      (is "?List x xs y ys = ?Hd x y ∪ ?Tl xs ys")
    proof
      show "?List x xs y ys ⊆ ?Hd x y ∪ ?Tl xs ys"
      proof
        fix el
        assume el_in_list: "el ∈ ?List x xs y ys"
        show "el ∈  ?Hd x y ∪ ?Tl xs ys"
        proof (cases el)
          case This
          with el_in_list show ?thesis by (simp add: dom_def)
        next
          case (EName en)
          show ?thesis
          proof (cases en)
            case Res
            with EName el_in_list show ?thesis by (simp add: dom_def)
          next
            case (VNam vn)
            with EName el_in_list show ?thesis
              by (auto simp add: dom_def dest: map_upds_cut_irrelevant)
          qed
        qed
      qed
    next
      show "?Hd x y ∪ ?Tl xs ys  ⊆ ?List x xs y ys"
      proof (rule subsetI)
        fix el
        assume  el_in_hd_tl: "el ∈  ?Hd x y ∪ ?Tl xs ys"
        show "el ∈ ?List x xs y ys"
        proof (cases el)
          case This
          with el_in_hd_tl show ?thesis by (simp add: dom_def)
        next
          case (EName en)
          show ?thesis
          proof (cases en)
            case Res
            with EName el_in_hd_tl show ?thesis by (simp add: dom_def)
          next
            case (VNam vn)
            with EName el_in_hd_tl show ?thesis
              by (auto simp add: dom_def intro: map_upds_Some_expand
                                                map_upds_Some_insert)
          qed
        qed
      qed
    qed

    lemma dom_map_upd: "!! tab. dom (tab(x\<mapsto>y)) = dom tab ∪ {x}"
    by (auto simp add: dom_def fun_upd_def)

    lemma dom_map_upds: "!! tab ys. length xs = length ys
      ==> dom (tab(xs[\<mapsto>]ys)) = dom tab ∪ set xs"
    proof (induct xs)
      case Nil thus ?case by (simp add: dom_def)
    next
      case (Cons x xs tab ys)
      note Hyp = Cons.hyps
      have len: "length (x#xs)=length ys".
      show ?case
      proof (cases ys)
        case Nil with len show ?thesis by simp
      next
        case (Cons y tl)
        with len have "dom (tab(x\<mapsto>y)(xs[\<mapsto>]tl)) = dom (tab(x\<mapsto>y)) ∪ set xs"
          by - (rule Hyp,simp)
        moreover
        have "dom (tab(x\<mapsto>hd ys)) = dom tab ∪ {x}"
          by (rule dom_map_upd)
        ultimately
        show ?thesis using Cons
          by simp
      qed
    qed

    lemma dom_ename_case_None_simp:
     "dom (ename_case vname_tab None) = VNam ` (dom vname_tab)"
      apply (auto simp add: dom_def image_def )
      apply (case_tac "x")
      apply auto
      done

    lemma dom_ename_case_Some_simp:
     "dom (ename_case vname_tab (Some a)) = VNam ` (dom vname_tab) ∪ {Res}"
      apply (auto simp add: dom_def image_def )
      apply (case_tac "x")
      apply auto
      done

    lemma dom_lname_case_None_simp:
      "dom (lname_case ename_tab None) = EName ` (dom ename_tab)"
      apply (auto simp add: dom_def image_def )
      apply (case_tac "x")
      apply auto
      done

    lemma dom_lname_case_Some_simp:
     "dom (lname_case ename_tab (Some a)) = EName ` (dom ename_tab) ∪ {This}"
      apply (auto simp add: dom_def image_def)
      apply (case_tac "x")
      apply auto
      done

    lemmas dom_lname_ename_case_simps =
         dom_ename_case_None_simp dom_ename_case_Some_simp
         dom_lname_case_None_simp dom_lname_case_Some_simp

    lemma image_comp:
     "f ` g ` A = (f o g) ` A"
    by (auto simp add: image_def)

    lemma dom_locals_init_lvars:
      assumes m: "m=(mthd (the (methd G C sig)))"
      assumes len: "length (pars m) = length pvs"
      shows "dom (locals (store (init_lvars G C sig (invmode m e) a pvs s)))
               = parameters m"
    proof -
      from m
      have static_m': "is_static m = static m"
        by simp
      from len
      have dom_vnames: "dom (empty(pars m[\<mapsto>]pvs))=set (pars m)"
        by (simp add: dom_map_upds)
      show ?thesis
      proof (cases "static m")
        case True
        with static_m' dom_vnames m
        show ?thesis
          by (cases s) (simp add: init_lvars_def Let_def parameters_def
                                  dom_lname_ename_case_simps image_comp)
      next
        case False
        with static_m' dom_vnames m
        show ?thesis
          by (cases s) (simp add: init_lvars_def Let_def parameters_def
                                  dom_lname_ename_case_simps image_comp)
      qed
    qed

    lemma da_e2_BinOp:
      assumes da: "(|prg=G,cls=accC,lcl=L|)),
                      \<turnstile>dom (locals (store s0)) »⟨BinOp binop e1 e2⟩e» A"
        and wt_e1: "(|prg=G,cls=accC,lcl=L|)),\<turnstile>e1::-e1T"
        and wt_e2: "(|prg=G,cls=accC,lcl=L|)),\<turnstile>e2::-e2T"
        and wt_binop: "wt_binop G binop e1T e2T"
        and conf_s0: "s0::\<preceq>(G,L)"
        and normal_s1: "normal s1"
        and eval_e1: "G\<turnstile>s0 \<midarrow>e1-\<succ>v1-> s1"
        and conf_v1: "G,store s1\<turnstile>v1::\<preceq>e1T"
        and wf: "wf_prog G"
      shows "∃ E2. (|prg=G,cls=accC,lcl=L|)),\<turnstile> dom (locals (store s1))
             »(if need_second_arg binop v1 then ⟨e2⟩e else ⟨Skip⟩s)» E2"
    proof -
      note inj_term_simps [simp]
      from da obtain E1 where
        da_e1: "(|prg=G,cls=accC,lcl=L|)), \<turnstile> dom (locals (store s0)) »⟨e1⟩e» E1"
        by cases simp+
      obtain E2 where
        "(|prg=G,cls=accC,lcl=L|)),\<turnstile> dom (locals (store s1))
          »(if need_second_arg binop v1 then ⟨e2⟩e else ⟨Skip⟩s)» E2"
      proof (cases "need_second_arg binop v1")
        case False
        obtain S where
          daSkip: "(|prg=G,cls=accC,lcl=L|)),
                      \<turnstile> dom (locals (store s1)) »⟨Skip⟩s» S"
          by (auto intro: da_Skip [simplified] assigned.select_convs)
        thus ?thesis
          using that by (simp add: False)
      next
        case True
        from eval_e1 have
          s0_s1:"dom (locals (store s0)) ⊆ dom (locals (store s1))"
          by (rule dom_locals_eval_mono_elim)
        {
          assume condAnd: "binop=CondAnd"
          have ?thesis
          proof -
            from da obtain E2' where
              "(|prg=G,cls=accC,lcl=L|)),
                 \<turnstile> dom (locals (store s0)) ∪ assigns_if True e1 »⟨e2⟩e» E2'"
              by cases (simp add: condAnd)+
            moreover
            have "dom (locals (store s0))
              ∪ assigns_if True e1 ⊆ dom (locals (store s1))"
            proof -
              from condAnd wt_binop have e1T: "e1T=PrimT Boolean"
                by simp
              with normal_s1 conf_v1 obtain b where "v1=Bool b"
                by (auto dest: conf_Boolean)
              with True condAnd
              have v1: "v1=Bool True"
                by simp
              from eval_e1 normal_s1
              have "assigns_if True e1 ⊆ dom (locals (store s1))"
                by (rule assigns_if_good_approx' [elim_format])
                   (insert wt_e1, simp_all add: e1T v1)
              with s0_s1 show ?thesis by (rule Un_least)
            qed
            ultimately
            show ?thesis
              using that by (cases rule: da_weakenE) (simp add: True)
          qed
        }
        moreover
        {
          assume condOr: "binop=CondOr"
          have ?thesis
            (* Beweis durch Analogie/Example/Pattern?, True->False; And->Or *)
          proof -
            from da obtain E2' where
              "(|prg=G,cls=accC,lcl=L|)),
                  \<turnstile> dom (locals (store s0)) ∪ assigns_if False e1 »⟨e2⟩e» E2'"
              by cases (simp add: condOr)+
            moreover
            have "dom (locals (store s0))
                         ∪ assigns_if False e1 ⊆ dom (locals (store s1))"
            proof -
              from condOr wt_binop have e1T: "e1T=PrimT Boolean"
                by simp
              with normal_s1 conf_v1 obtain b where "v1=Bool b"
                by (auto dest: conf_Boolean)
              with True condOr
              have v1: "v1=Bool False"
                by simp
              from eval_e1 normal_s1
              have "assigns_if False e1 ⊆ dom (locals (store s1))"
                by (rule assigns_if_good_approx' [elim_format])
                   (insert wt_e1, simp_all add: e1T v1)
              with s0_s1 show ?thesis by (rule Un_least)
            qed
            ultimately
            show ?thesis
              using that by (rule da_weakenE) (simp add: True)
          qed
        }
        moreover
        {
          assume notAndOr: "binop≠CondAnd" "binop≠CondOr"
          have ?thesis
          proof -
            from da notAndOr obtain E1' where
              da_e1: "(|prg=G,cls=accC,lcl=L|)),
                      \<turnstile> dom (locals (store s0)) »⟨e1⟩e» E1'"
              and da_e2: "(|prg=G,cls=accC,lcl=L|)),\<turnstile> nrm E1' »In1l e2» A"
              by cases simp+
            from eval_e1 wt_e1 da_e1 wf normal_s1
            have "nrm E1' ⊆ dom (locals (store s1))"
              by (cases rule: da_good_approxE') iprover
            with da_e2 show ?thesis
              using that by (rule da_weakenE) (simp add: True)
          qed
        }
        ultimately show ?thesis
          by (cases binop) auto
      qed
      thus ?thesis ..
    qed

    section "main proof of type safety"

    lemma eval_type_sound:
      assumes  eval: "G\<turnstile>s0 \<midarrow>t\<succ>-> (v,s1)"
       and      wt: "(|prg=G,cls=accC,lcl=L|)),\<turnstile>t::T"
       and      da: "(|prg=G,cls=accC,lcl=L|)),\<turnstile>dom (locals (store s0))»t»A"
       and      wf: "wf_prog G"
       and conf_s0: "s0::\<preceq>(G,L)"
      shows "s1::\<preceq>(G,L) ∧  (normal s1 --> G,L,store s1\<turnstile>t\<succ>v::\<preceq>T) ∧
             (error_free s0 = error_free s1)"
    proof -
      note inj_term_simps [simp]
      let ?TypeSafeObj = "λ s0 s1 t v.
              ∀  L accC T A. s0::\<preceq>(G,L) --> (|prg=G,cls=accC,lcl=L|)),\<turnstile>t::T
                          --> (|prg=G,cls=accC,lcl=L|)),\<turnstile>dom (locals (store s0))»t»A
                          --> s1::\<preceq>(G,L) ∧ (normal s1 --> G,L,store s1\<turnstile>t\<succ>v::\<preceq>T)
                              ∧ (error_free s0 = error_free s1)"
      from eval
      have "!! L accC T A. [|s0::\<preceq>(G,L);(|prg=G,cls=accC,lcl=L|)),\<turnstile>t::T;
                          (|prg=G,cls=accC,lcl=L|)),\<turnstile>dom (locals (store s0))»t»A|]
            ==> s1::\<preceq>(G,L) ∧ (normal s1 --> G,L,store s1\<turnstile>t\<succ>v::\<preceq>T)
                ∧ (error_free s0 = error_free s1)"
       (is "PROP ?TypeSafe s0 s1 t v"
        is "!! L accC T A. ?Conform L s0 ==> ?WellTyped L accC T t
                     ==> ?DefAss L accC s0 t A
                     ==> ?Conform L s1 ∧ ?ValueTyped L T s1 t v ∧
                         ?ErrorFree s0 s1")
      proof (induct)
        case (Abrupt s t xc L accC T A)
        have "(Some xc, s)::\<preceq>(G,L)" .
        then show "(Some xc, s)::\<preceq>(G,L) ∧
          (normal (Some xc, s)
          --> G,L,store (Some xc,s)\<turnstile>t\<succ>arbitrary3 t::\<preceq>T) ∧
          (error_free (Some xc, s) = error_free (Some xc, s))"
          by (simp)
      next
        case (Skip s L accC T A)
        have "Norm s::\<preceq>(G, L)" and
               "(|prg = G, cls = accC, lcl = L|)),\<turnstile>In1r Skip::T" .
        then show "Norm s::\<preceq>(G, L) ∧
                  (normal (Norm s) --> G,L,store (Norm s)\<turnstile>In1r Skip\<succ>♦::\<preceq>T) ∧
                  (error_free (Norm s) = error_free (Norm s))"
          by (simp)
      next
        case (Expr e s0 s1 v L accC T A)
        have "G\<turnstile>Norm s0 \<midarrow>e-\<succ>v-> s1" .
        have     hyp: "PROP ?TypeSafe (Norm s0) s1 (In1l e) (In1 v)" .
        have conf_s0: "Norm s0::\<preceq>(G, L)" .
        moreover
        have      wt: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>In1r (Expr e)::T" .
        then obtain eT
          where "(|prg = G, cls = accC, lcl = L|)),\<turnstile>In1l e::eT"
          by (rule wt_elim_cases) (blast)
        moreover
        from Expr.prems obtain E where
          "(|prg=G,cls=accC, lcl=L|)),\<turnstile>dom (locals (store ((Norm s0)::state)))»In1l e»E"
          by (elim da_elim_cases) simp
        ultimately
        obtain "s1::\<preceq>(G, L)" and "error_free s1"
          by (rule hyp [elim_format]) simp
        with wt
        show "s1::\<preceq>(G, L) ∧
              (normal s1 --> G,L,store s1\<turnstile>In1r (Expr e)\<succ>♦::\<preceq>T) ∧
              (error_free (Norm s0) = error_free s1)"
          by (simp)
      next
        case (Lab c l s0 s1 L accC T A)
        have     hyp: "PROP ?TypeSafe (Norm s0) s1 (In1r c) ♦" .
        have conf_s0: "Norm s0::\<preceq>(G, L)" .
        moreover
        have      wt: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>In1r (l• c)::T" .
        then have "(|prg = G, cls = accC, lcl = L|)),\<turnstile>c::\<surd>"
          by (rule wt_elim_cases) (blast)
        moreover from Lab.prems obtain C where
         "(|prg=G,cls=accC, lcl=L|)),\<turnstile>dom (locals (store ((Norm s0)::state)))»In1r c»C"
          by (elim da_elim_cases) simp
        ultimately
        obtain       conf_s1: "s1::\<preceq>(G, L)" and
               error_free_s1: "error_free s1"
          by (rule hyp [elim_format]) simp
        from conf_s1 have "abupd (absorb l) s1::\<preceq>(G, L)"
          by (cases s1) (auto intro: conforms_absorb)
        with wt error_free_s1
        show "abupd (absorb l) s1::\<preceq>(G, L) ∧
              (normal (abupd (absorb l) s1)
               --> G,L,store (abupd (absorb l) s1)\<turnstile>In1r (l• c)\<succ>♦::\<preceq>T) ∧
              (error_free (Norm s0) = error_free (abupd (absorb l) s1))"
          by (simp)
      next
        case (Comp c1 c2 s0 s1 s2 L accC T A)
        have eval_c1: "G\<turnstile>Norm s0 \<midarrow>c1-> s1" .
        have eval_c2: "G\<turnstile>s1 \<midarrow>c2-> s2" .
        have  hyp_c1: "PROP ?TypeSafe (Norm s0) s1 (In1r c1) ♦" .
        have  hyp_c2: "PROP ?TypeSafe s1        s2 (In1r c2) ♦" .
        have conf_s0: "Norm s0::\<preceq>(G, L)" .
        have      wt: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>In1r (c1;; c2)::T" .
        then obtain wt_c1: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>c1::\<surd>" and
                    wt_c2: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>c2::\<surd>"
          by (rule wt_elim_cases) (blast)
        from Comp.prems
        obtain C1 C2
          where da_c1: "(|prg=G, cls=accC, lcl=L|)),\<turnstile>
                          dom (locals (store ((Norm s0)::state))) »In1r c1» C1" and
                da_c2: "(|prg=G, cls=accC, lcl=L|)),\<turnstile>  nrm C1 »In1r c2» C2"
          by (elim da_elim_cases) simp
        from conf_s0 wt_c1 da_c1
        obtain conf_s1: "s1::\<preceq>(G, L)" and
               error_free_s1: "error_free s1"
          by (rule hyp_c1 [elim_format]) simp
        show "s2::\<preceq>(G, L) ∧
              (normal s2 --> G,L,store s2\<turnstile>In1r (c1;; c2)\<succ>♦::\<preceq>T) ∧
              (error_free (Norm s0) = error_free s2)"
        proof (cases "normal s1")
          case False
          with eval_c2 have "s2=s1" by auto
          with conf_s1 error_free_s1 False wt show ?thesis
            by simp
        next
          case True
          obtain C2' where
            "(|prg=G, cls=accC, lcl=L|)),\<turnstile> dom (locals (store s1)) »In1r c2» C2'"
          proof -
            from eval_c1 wt_c1 da_c1 wf True
            have "nrm C1 ⊆ dom (locals (store s1))"
              by (cases rule: da_good_approxE') iprover
            with da_c2 show ?thesis
              by (rule da_weakenE)
          qed
          with conf_s1 wt_c2
          obtain "s2::\<preceq>(G, L)" and "error_free s2"
            by (rule hyp_c2 [elim_format]) (simp add: error_free_s1)
          thus ?thesis
            using wt by simp
        qed
      next
        case (If b c1 c2 e s0 s1 s2 L accC T)
        have eval_e: "G\<turnstile>Norm s0 \<midarrow>e-\<succ>b-> s1" .
        have eval_then_else: "G\<turnstile>s1 \<midarrow>(if the_Bool b then c1 else c2)-> s2" .
        have hyp_e: "PROP ?TypeSafe (Norm s0) s1 (In1l e) (In1 b)" .
        have hyp_then_else:
                "PROP ?TypeSafe s1 s2 (In1r (if the_Bool b then c1 else c2)) ♦" .
        have conf_s0: "Norm s0::\<preceq>(G, L)" .
        have      wt: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>In1r (If(e) c1 Else c2)::T" .
        then obtain
                  wt_e: "(|prg=G, cls=accC, lcl=L|)),\<turnstile>e::-PrimT Boolean" and
          wt_then_else: "(|prg=G, cls=accC, lcl=L|)),\<turnstile>(if the_Bool b then c1 else c2)::\<surd>"
          (*
                    wt_c1: "(|prg=G, cls=accC, lcl=L|)),\<turnstile>c1::\<surd>" and
                    wt_c2: "(|prg=G, cls=accC, lcl=L|)),\<turnstile>c2::\<surd>"*)
          by (rule wt_elim_cases) (auto split add: split_if)
        from If.prems obtain E C where
          da_e: "(|prg=G,cls=accC,lcl=L|)),\<turnstile> dom (locals (store ((Norm s0)::state)))
                                           »In1l e» E" and
          da_then_else:
          "(|prg=G,cls=accC,lcl=L|)),\<turnstile>
             (dom (locals (store ((Norm s0)::state))) ∪ assigns_if (the_Bool b) e)
              »In1r (if the_Bool b then c1 else c2)» C"
         (*
         da_c1: "(|prg=G,cls=accC,lcl=L|)),\<turnstile> (dom (locals (store ((Norm s0)::state)))
                                          ∪ assigns_if True e) »In1r c1» C1" and
         da_c2: "(|prg=G,cls=accC,lcl=L|)),\<turnstile> (dom (locals (store ((Norm s0)::state)))
                                           ∪ assigns_if False e) »In1r c2» C2" *)
          by (elim da_elim_cases) (cases "the_Bool b",auto)
        from conf_s0 wt_e da_e
        obtain conf_s1: "s1::\<preceq>(G, L)" and error_free_s1: "error_free s1"
          by (rule hyp_e [elim_format]) simp
        show "s2::\<preceq>(G, L) ∧
               (normal s2 --> G,L,store s2\<turnstile>In1r (If(e) c1 Else c2)\<succ>♦::\<preceq>T) ∧
               (error_free (Norm s0) = error_free s2)"
        proof (cases "normal s1")
          case False
          with eval_then_else have "s2=s1" by auto
          with conf_s1 error_free_s1 False wt show ?thesis
            by simp
        next
          case True
          obtain C' where
            "(|prg=G,cls=accC,lcl=L|)),\<turnstile>
              (dom (locals (store s1)))»In1r (if the_Bool b then c1 else c2)» C'"
          proof -
            from eval_e have
              "dom (locals (store ((Norm s0)::state))) ⊆ dom (locals (store s1))"
              by (rule dom_locals_eval_mono_elim)
            moreover
            from eval_e True wt_e
            have "assigns_if (the_Bool b) e ⊆ dom (locals (store s1))"
              by (rule assigns_if_good_approx')
            ultimately
            have "dom (locals (store ((Norm s0)::state)))
                    ∪ assigns_if (the_Bool b) e ⊆ dom (locals (store s1))"
              by (rule Un_least)
            with da_then_else show ?thesis
              by (rule da_weakenE)
          qed
          with conf_s1 wt_then_else
          obtain "s2::\<preceq>(G, L)" and "error_free s2"
            by (rule hyp_then_else [elim_format]) (simp add: error_free_s1)
          with wt show ?thesis
            by simp
        qed
        -- {* Note that we don't have to show that @{term b} really is a boolean
              value. With @{term the_Bool} we enforce to get a value of boolean
              type. So execution will be type safe, even if b would be
              a string, for example. We might not expect such a behaviour to be
              called type safe. To remedy the situation we would have to change
              the evaulation rule, so that it only has a type safe evaluation if
              we actually get a boolean value for the condition. That b is actually
              a boolean value is part of @{term hyp_e}. See also Loop
           *}
      next
    -- {*
    \par
    *} (* dummy text command to break paragraph for latex;
                  large paragraphs exhaust memory of debian pdflatex *)
        case (Loop b c e l s0 s1 s2 s3 L accC T A)
        have eval_e: "G\<turnstile>Norm s0 \<midarrow>e-\<succ>b-> s1" .
        have hyp_e: "PROP ?TypeSafe (Norm s0) s1 (In1l e) (In1 b)" .
        have conf_s0: "Norm s0::\<preceq>(G, L)" .
        have      wt: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>In1r (l• While(e) c)::T" .
        then obtain wt_e: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>e::-PrimT Boolean" and
                    wt_c: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>c::\<surd>"
          by (rule wt_elim_cases) (blast)
        have da:"(|prg=G, cls=accC, lcl=L|)),
                \<turnstile> dom (locals(store ((Norm s0)::state))) »In1r (l• While(e) c)» A".
        then
        obtain E C where
          da_e: "(|prg=G, cls=accC, lcl=L|)),
                  \<turnstile> dom (locals (store ((Norm s0)::state))) »In1l e» E" and
          da_c: "(|prg=G, cls=accC, lcl=L|)),
                  \<turnstile> (dom (locals (store ((Norm s0)::state)))
                       ∪ assigns_if True e) »In1r c» C"
          by (rule da_elim_cases) simp
        from conf_s0 wt_e da_e
        obtain conf_s1: "s1::\<preceq>(G, L)" and error_free_s1: "error_free s1"
          by (rule hyp_e [elim_format]) simp
        show "s3::\<preceq>(G, L) ∧
              (normal s3 --> G,L,store s3\<turnstile>In1r (l• While(e) c)\<succ>♦::\<preceq>T) ∧
              (error_free (Norm s0) = error_free s3)"
        proof (cases "normal s1")
          case True
          note normal_s1 = this
          show ?thesis
          proof (cases "the_Bool b")
            case True
            with Loop.hyps  obtain
              eval_c: "G\<turnstile>s1 \<midarrow>c-> s2" and
              eval_while: "G\<turnstile>abupd (absorb (Cont l)) s2 \<midarrow>l• While(e) c-> s3"
              by simp
            have "?TypeSafeObj s1 s2 (In1r c) ♦"
              using Loop.hyps True by simp
            note hyp_c = this [rule_format]
            have "?TypeSafeObj (abupd (absorb (Cont l)) s2)
              s3 (In1r (l• While(e) c)) ♦"
              using Loop.hyps True by simp
            note hyp_w = this [rule_format]
            from eval_e have
              s0_s1: "dom (locals (store ((Norm s0)::state)))
                        ⊆ dom (locals (store s1))"
              by (rule dom_locals_eval_mono_elim)
            obtain C' where
              "(|prg=G, cls=accC, lcl=L|)),\<turnstile>(dom (locals (store s1)))»In1r c» C'"
            proof -
              note s0_s1
              moreover
              from eval_e normal_s1 wt_e
              have "assigns_if True e ⊆ dom (locals (store s1))"
                by (rule assigns_if_good_approx' [elim_format]) (simp add: True)
              ultimately
              have "dom (locals (store ((Norm s0)::state)))
                     ∪ assigns_if True e ⊆ dom (locals (store s1))"
                by (rule Un_least)
              with da_c show ?thesis
                by (rule da_weakenE)
            qed
            with conf_s1 wt_c
            obtain conf_s2:  "s2::\<preceq>(G, L)" and error_free_s2: "error_free s2"
              by (rule hyp_c [elim_format]) (simp add: error_free_s1)
            from error_free_s2
            have error_free_ab_s2: "error_free (abupd (absorb (Cont l)) s2)"
              by simp
            from conf_s2 have "abupd (absorb (Cont l)) s2 ::\<preceq>(G, L)"
              by (cases s2) (auto intro: conforms_absorb)
            moreover note wt
            moreover
            obtain A' where
              "(|prg=G,cls=accC,lcl=L|)),\<turnstile>
                  dom (locals(store (abupd (absorb (Cont l)) s2)))
                    »In1r (l• While(e) c)» A'"
            proof -
              note s0_s1
              also from eval_c
              have "dom (locals (store s1)) ⊆ dom (locals (store s2))"
                by (rule dom_locals_eval_mono_elim)
              also have "… ⊆ dom (locals (store (abupd (absorb (Cont l)) s2)))"
                by simp
              finally
              have "dom (locals (store ((Norm s0)::state))) ⊆ …" .
              with da show ?thesis
                by (rule da_weakenE)
            qed
            ultimately obtain "s3::\<preceq>(G, L)" and "error_free s3"
              by (rule hyp_w [elim_format]) (simp add: error_free_ab_s2)
            with wt show ?thesis
              by simp
          next
            case False
            with Loop.hyps have "s3=s1" by simp
            with conf_s1 error_free_s1 wt
            show ?thesis
              by simp
          qed
        next
          case False
          have "s3=s1"
          proof -
            from False obtain abr where abr: "abrupt s1 = Some abr"
              by (cases s1) auto
            from eval_e _ wt_e have no_jmp: "!! j. abrupt s1 ≠ Some (Jump j)"
              by (rule eval_expression_no_jump
                   [where ?Env="(|prg=G,cls=accC,lcl=L|)),",simplified])
                 (simp_all add: wf)

            show ?thesis
            proof (cases "the_Bool b")
              case True
              with Loop.hyps obtain
                eval_c: "G\<turnstile>s1 \<midarrow>c-> s2" and
                eval_while: "G\<turnstile>abupd (absorb (Cont l)) s2 \<midarrow>l• While(e) c-> s3"
                by simp
              from eval_c abr have "s2=s1" by auto
              moreover from calculation no_jmp have "abupd (absorb (Cont l)) s2=s2"
                by (cases s1) (simp add: absorb_def)
              ultimately show ?thesis
                using eval_while abr
                by auto
            next
              case False
              with Loop.hyps show ?thesis by simp
            qed
          qed
          with conf_s1 error_free_s1 wt
          show ?thesis
            by simp
        qed
      next
        case (Jmp j s L accC T A)
        have "Norm s::\<preceq>(G, L)" .
        moreover
        from Jmp.prems
        have "j=Ret --> Result ∈ dom (locals (store ((Norm s)::state)))"
          by (elim da_elim_cases)
        ultimately have "(Some (Jump j), s)::\<preceq>(G, L)" by auto
        then
        show "(Some (Jump j), s)::\<preceq>(G, L) ∧
               (normal (Some (Jump j), s)
               --> G,L,store (Some (Jump j), s)\<turnstile>In1r (Jmp j)\<succ>♦::\<preceq>T) ∧
               (error_free (Norm s) = error_free (Some (Jump j), s))"
          by simp
      next
        case (Throw a e s0 s1 L accC T A)
        have "G\<turnstile>Norm s0 \<midarrow>e-\<succ>a-> s1" .
        have hyp: "PROP ?TypeSafe (Norm s0) s1 (In1l e) (In1 a)" .
        have conf_s0: "Norm s0::\<preceq>(G, L)" .
        have      wt: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>In1r (Throw e)::T" .
        then obtain tn
          where      wt_e: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>e::-Class tn" and
                throwable: "G\<turnstile>tn\<preceq>C SXcpt Throwable"
          by (rule wt_elim_cases) (auto)
        from Throw.prems obtain E where
          da_e: "(|prg=G,cls=accC,lcl=L|)),
                 \<turnstile> dom (locals (store ((Norm s0)::state))) »In1l e» E"
          by (elim da_elim_cases) simp
        from conf_s0 wt_e da_e obtain
          "s1::\<preceq>(G, L)" and
          "(normal s1 --> G,store s1\<turnstile>a::\<preceq>Class tn)" and
          error_free_s1: "error_free s1"
          by (rule hyp [elim_format]) simp
        with wf throwable
        have "abupd (throw a) s1::\<preceq>(G, L)"
          by (cases s1) (auto dest: Throw_lemma)
        with wt error_free_s1
        show "abupd (throw a) s1::\<preceq>(G, L) ∧
                (normal (abupd (throw a) s1) -->
                G,L,store (abupd (throw a) s1)\<turnstile>In1r (Throw e)\<succ>♦::\<preceq>T) ∧
                (error_free (Norm s0) = error_free (abupd (throw a) s1))"
          by simp
      next
        case (Try catchC c1 c2 s0 s1 s2 s3 vn L accC T A)
        have eval_c1: "G\<turnstile>Norm s0 \<midarrow>c1-> s1" .
        have sx_alloc: "G\<turnstile>s1 \<midarrow>sxalloc-> s2" .
        have hyp_c1: "PROP ?TypeSafe (Norm s0) s1 (In1r c1) ♦" .
        have conf_s0:"Norm s0::\<preceq>(G, L)" .
        have      wt:"(|prg=G,cls=accC,lcl=L|)),\<turnstile>In1r (Try c1 Catch(catchC vn) c2)::T" .
        then obtain
          wt_c1: "(|prg=G,cls=accC,lcl=L|)),\<turnstile>c1::\<surd>" and
          wt_c2: "(|prg=G,cls=accC,lcl=L(VName vn\<mapsto>Class catchC)|)),\<turnstile>c2::\<surd>" and
          fresh_vn: "L(VName vn)=None"
          by (rule wt_elim_cases) simp
        from Try.prems obtain C1 C2 where
          da_c1: "(|prg=G,cls=accC,lcl=L|)),
                    \<turnstile> dom (locals (store ((Norm s0)::state))) »In1r c1» C1"  and
          da_c2:
           "(|prg=G,cls=accC,lcl=L(VName vn\<mapsto>Class catchC)|)),
            \<turnstile> (dom (locals (store ((Norm s0)::state))) ∪ {VName vn}) »In1r c2» C2"
          by (elim da_elim_cases) simp
        from conf_s0 wt_c1 da_c1
        obtain conf_s1: "s1::\<preceq>(G, L)" and error_free_s1: "error_free s1"
          by (rule hyp_c1 [elim_format]) simp
        from conf_s1 sx_alloc wf
        have conf_s2: "s2::\<preceq>(G, L)"
          by (auto dest: sxalloc_type_sound split: option.splits abrupt.splits)
        from sx_alloc error_free_s1
        have error_free_s2: "error_free s2"
          by (rule error_free_sxalloc)
        show "s3::\<preceq>(G, L) ∧
              (normal s3 --> G,L,store s3\<turnstile>In1r (Try c1 Catch(catchC vn) c2)\<succ>♦::\<preceq>T)∧
              (error_free (Norm s0) = error_free s3)"
        proof (cases "∃ x. abrupt s1 = Some (Xcpt x)")
          case False
          from sx_alloc wf
          have eq_s2_s1: "s2=s1"
            by (rule sxalloc_type_sound [elim_format])
               (insert False, auto split: option.splits abrupt.splits )
          with False
          have "¬  G,s2\<turnstile>catch catchC"
            by (simp add: catch_def)
          with Try
          have "s3=s2"
            by simp
          with wt conf_s1 error_free_s1 eq_s2_s1
          show ?thesis
            by simp
        next
          case True
          note exception_s1 = this
          show ?thesis
          proof (cases "G,s2\<turnstile>catch catchC")
            case False
            with Try
            have "s3=s2"
              by simp
            with wt conf_s2 error_free_s2
            show ?thesis
              by simp
          next
            case True
            with Try have "G\<turnstile>new_xcpt_var vn s2 \<midarrow>c2-> s3" by simp
            from True Try.hyps
            have "?TypeSafeObj (new_xcpt_var vn s2) s3 (In1r c2) ♦"
              by simp
            note hyp_c2 = this [rule_format]
            from exception_s1 sx_alloc wf
            obtain a
              where xcpt_s2: "abrupt s2 = Some (Xcpt (Loc a))"
              by (auto dest!: sxalloc_type_sound split: option.splits abrupt.splits)
            with True
            have "G\<turnstile>obj_ty (the (globs (store s2) (Heap a)))\<preceq>Class catchC"
              by (cases s2) simp
            with xcpt_s2 conf_s2 wf
            have "new_xcpt_var vn s2 ::\<preceq>(G, L(VName vn\<mapsto>Class catchC))"
              by (auto dest: Try_lemma)
            moreover note wt_c2
            moreover
            obtain C2' where
              "(|prg=G,cls=accC,lcl=L(VName vn\<mapsto>Class catchC)|)),
              \<turnstile> (dom (locals (store (new_xcpt_var vn s2)))) »In1r c2» C2'"
            proof -
              have "(dom (locals (store ((Norm s0)::state))) ∪ {VName vn})
                      ⊆ dom (locals (store (new_xcpt_var vn s2)))"
              proof -
                have "G\<turnstile>Norm s0 \<midarrow>c1-> s1" .
                hence "dom (locals (store ((Norm s0)::state)))
                        ⊆ dom (locals (store s1))"
                  by (rule dom_locals_eval_mono_elim)
                also
                from sx_alloc
                have "… ⊆ dom (locals (store s2))"
                  by (rule dom_locals_sxalloc_mono)
                also
                have "… ⊆ dom (locals (store (new_xcpt_var vn s2)))"
                  by (cases s2) (simp add: new_xcpt_var_def, blast)
                also
                have "{VName vn} ⊆ …"
                  by (cases s2) simp
                ultimately show ?thesis
                  by (rule Un_least)
              qed
              with da_c2 show ?thesis
                by (rule da_weakenE)
            qed
            ultimately
            obtain       conf_s3: "s3::\<preceq>(G, L(VName vn\<mapsto>Class catchC))" and
                   error_free_s3: "error_free s3"
              by (rule hyp_c2 [elim_format])
                 (cases s2, simp add: xcpt_s2 error_free_s2)
            from conf_s3 fresh_vn
            have "s3::\<preceq>(G,L)"
              by (blast intro: conforms_deallocL)
            with wt error_free_s3
            show ?thesis
              by simp
          qed
        qed
      next
    -- {*
    \par
    *} (* dummy text command to break paragraph for latex;
                  large paragraphs exhaust memory of debian pdflatex *)
        case (Fin c1 c2 s0 s1 s2 s3 x1 L accC T A)
        have eval_c1: "G\<turnstile>Norm s0 \<midarrow>c1-> (x1, s1)" .
        have eval_c2: "G\<turnstile>Norm s1 \<midarrow>c2-> s2" .
        have s3: "s3= (if ∃err. x1 = Some (Error err)
                         then (x1, s1)
                         else abupd (abrupt_if (x1 ≠ None) x1) s2)" .
        have  hyp_c1: "PROP ?TypeSafe (Norm s0) (x1,s1) (In1r c1) ♦" .
        have  hyp_c2: "PROP ?TypeSafe (Norm s1) s2      (In1r c2) ♦" .
        have conf_s0: "Norm s0::\<preceq>(G, L)" .
        have      wt: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>In1r (c1 Finally c2)::T" .
        then obtain
          wt_c1: "(|prg=G,cls=accC,lcl=L|)),\<turnstile>c1::\<surd>" and
          wt_c2: "(|prg=G,cls=accC,lcl=L|)),\<turnstile>c2::\<surd>"
          by (rule wt_elim_cases) blast
        from Fin.prems obtain C1 C2 where
          da_c1: "(|prg=G,cls=accC,lcl=L|)),
                   \<turnstile> dom (locals (store ((Norm s0)::state))) »In1r c1» C1" and
          da_c2: "(|prg=G,cls=accC,lcl=L|)),
                   \<turnstile> dom (locals (store ((Norm s0)::state))) »In1r c2» C2"
          by (elim da_elim_cases) simp
        from conf_s0 wt_c1 da_c1
        obtain conf_s1: "(x1,s1)::\<preceq>(G, L)" and error_free_s1: "error_free (x1,s1)"
          by (rule hyp_c1 [elim_format]) simp
        from conf_s1 have "Norm s1::\<preceq>(G, L)"
          by (rule conforms_NormI)
        moreover note wt_c2
        moreover obtain C2'
          where "(|prg=G,cls=accC,lcl=L|)),
                   \<turnstile> dom (locals (store ((Norm s1)::state))) »In1r c2» C2'"
        proof -
          from eval_c1
          have "dom (locals (store ((Norm s0)::state)))
                 ⊆ dom (locals (store (x1,s1)))"
            by (rule dom_locals_eval_mono_elim)
          hence "dom (locals (store ((Norm s0)::state)))
                  ⊆ dom (locals (store ((Norm s1)::state)))"
            by simp
          with da_c2 show ?thesis
            by (rule da_weakenE)
        qed
        ultimately
        obtain conf_s2: "s2::\<preceq>(G, L)" and error_free_s2: "error_free s2"
          by (rule hyp_c2 [elim_format]) simp
        from error_free_s1 s3
        have s3': "s3=abupd (abrupt_if (x1 ≠ None) x1) s2"
          by simp
        show "s3::\<preceq>(G, L) ∧
              (normal s3 --> G,L,store s3 \<turnstile>In1r (c1 Finally c2)\<succ>♦::\<preceq>T) ∧
              (error_free (Norm s0) = error_free s3)"
        proof (cases x1)
          case None with conf_s2 s3' wt show ?thesis by auto
        next
          case (Some x)
          from eval_c2 have
            "dom (locals (store ((Norm s1)::state))) ⊆ dom (locals (store s2))"
            by (rule dom_locals_eval_mono_elim)
          with Some eval_c2 wf conf_s1 conf_s2
          have conf: "(abrupt_if True (Some x) (abrupt s2), store s2)::\<preceq>(G, L)"
            by (cases s2) (auto dest: Fin_lemma)
          from Some error_free_s1
          have "¬ (∃ err. x=Error err)"
            by (simp add: error_free_def)
          with error_free_s2
          have "error_free (abrupt_if True (Some x) (abrupt s2), store s2)"
            by (cases s2) simp
          with Some wt conf s3' show ?thesis
            by (cases s2) auto
        qed
      next
        case (Init C c s0 s1 s2 s3 L accC T)
        have     cls: "the (class G C) = c" .
        have conf_s0: "Norm s0::\<preceq>(G, L)" .
        have      wt: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>In1r (Init C)::T" .
        with cls
        have cls_C: "class G C = Some c"
          by - (erule wt_elim_cases,auto)
        show "s3::\<preceq>(G, L) ∧ (normal s3 --> G,L,store s3\<turnstile>In1r (Init C)\<succ>♦::\<preceq>T) ∧
              (error_free (Norm s0) = error_free s3)"
        proof (cases "inited C (globs s0)")
          case True
          with Init.hyps have "s3 = Norm s0"
            by simp
          with conf_s0 wt show ?thesis
            by simp
        next
          case False
          with Init.hyps obtain
               eval_init_super:
               "G\<turnstile>Norm ((init_class_obj G C) s0)
                  \<midarrow>(if C = Object then Skip else Init (super c))-> s1" and
            eval_init: "G\<turnstile>(set_lvars empty) s1 \<midarrow>init c-> s2" and
            s3: "s3 = (set_lvars (locals (store s1))) s2"
            by simp
          have "?TypeSafeObj (Norm ((init_class_obj G C) s0)) s1
                          (In1r (if C = Object then Skip else Init (super c))) ♦"
            using False Init.hyps by simp
          note hyp_init_super = this [rule_format]
          have "?TypeSafeObj ((set_lvars empty) s1) s2 (In1r (init c)) ♦"
            using False Init.hyps by simp
          note hyp_init_c = this [rule_format]
          from conf_s0 wf cls_C False
          have "(Norm ((init_class_obj G C) s0))::\<preceq>(G, L)"
            by (auto dest: conforms_init_class_obj)
          moreover from wf cls_C have
            wt_init_super: "(|prg = G, cls = accC, lcl = L|)),
                             \<turnstile>(if C = Object then Skip else Init (super c))::\<surd>"
            by (cases "C=Object")
               (auto dest: wf_prog_cdecl wf_cdecl_supD is_acc_classD)
          moreover
          obtain S where
            da_init_super:
            "(|prg=G,cls=accC,lcl=L|)),
              \<turnstile> dom (locals (store ((Norm ((init_class_obj G C) s0))::state)))
                   »In1r (if C = Object then Skip else Init (super c))» S"
          proof (cases "C=Object")
            case True
            with da_Skip show ?thesis
              using that by (auto intro: assigned.select_convs)
          next
            case False
            with da_Init show ?thesis
              by - (rule that, auto intro: assigned.select_convs)
          qed
          ultimately
          obtain conf_s1: "s1::\<preceq>(G, L)" and error_free_s1: "error_free s1"
            by (rule hyp_init_super [elim_format]) simp
          from eval_init_super wt_init_super wf
          have s1_no_ret: "!! j. abrupt s1 ≠ Some (Jump j)"
            by - (rule eval_statement_no_jump [where ?Env="(|prg=G,cls=accC,lcl=L|)),"],
                  auto)
          with conf_s1
          have "(set_lvars empty) s1::\<preceq>(G, empty)"
            by (cases s1) (auto intro: conforms_set_locals)
          moreover
          from error_free_s1
          have error_free_empty: "error_free ((set_lvars empty) s1)"
            by simp
          from cls_C wf have wt_init_c: "(|prg=G, cls=C,lcl=empty|)),\<turnstile>(init c)::\<surd>"
            by (rule wf_prog_cdecl [THEN wf_cdecl_wt_init])
          moreover from cls_C wf obtain I
            where "(|prg=G,cls=C,lcl=empty|)),\<turnstile> {} »In1r (init c)» I"
            by (rule wf_prog_cdecl [THEN wf_cdeclE,simplified]) blast
           (*  simplified: to rewrite ⟨init c⟩ to In1r (init c) *)
          then obtain I' where
            "(|prg=G,cls=C,lcl=empty|)),\<turnstile>dom (locals (store ((set_lvars empty) s1)))
                »In1r (init c)» I'"
              by (rule da_weakenE) simp
          ultimately
          obtain conf_s2: "s2::\<preceq>(G, empty)" and error_free_s2: "error_free s2"
            by (rule hyp_init_c [elim_format]) (simp add: error_free_empty)
          have "abrupt s2 ≠ Some (Jump Ret)"
          proof -
            from s1_no_ret
            have "!! j. abrupt ((set_lvars empty) s1) ≠ Some (Jump j)"
              by simp
            moreover
            from cls_C wf have "jumpNestingOkS {} (init c)"
              by (rule wf_prog_cdecl [THEN wf_cdeclE])
            ultimately
            show ?thesis
              using eval_init wt_init_c wf
              by - (rule eval_statement_no_jump
                         [where ?Env="(|prg=G,cls=C,lcl=empty|)),"],simp+)
          qed
          with conf_s2 s3 conf_s1 eval_init
          have "s3::\<preceq>(G, L)"
            by (cases s2,cases s1) (force dest: conforms_return eval_gext')
          moreover from error_free_s2 s3
          have "error_free s3"
            by simp
          moreover note wt
          ultimately show ?thesis
            by simp
        qed
      next
        case (NewC C a s0 s1 s2 L accC T A)
        have         "G\<turnstile>Norm s0 \<midarrow>Init C-> s1" .
        have halloc: "G\<turnstile>s1 \<midarrow>halloc CInst C\<succ>a-> s2" .
        have hyp: "PROP ?TypeSafe (Norm s0) s1 (In1r (Init C)) ♦" .
        have conf_s0: "Norm s0::\<preceq>(G, L)" .
        moreover
        have      wt: "(|prg=G, cls=accC, lcl=L|)),\<turnstile>In1l (NewC C)::T" .
        then obtain is_cls_C: "is_class G C" and
                           T: "T=Inl (Class C)"
          by (rule wt_elim_cases) (auto dest: is_acc_classD)
        hence "(|prg=G, cls=accC, lcl=L|)),\<turnstile>Init C::\<surd>" by auto
        moreover obtain I where
          "(|prg=G,cls=accC,lcl=L|)),
              \<turnstile> dom (locals (store ((Norm s0)::state))) »In1r (Init C)» I"
          by (auto intro: da_Init [simplified] assigned.select_convs)
         (* simplified: to rewrite ⟨Init C⟩ to In1r (Init C) *)
        ultimately
        obtain conf_s1: "s1::\<preceq>(G, L)" and error_free_s1: "error_free s1"
          by (rule hyp [elim_format]) simp
        from conf_s1 halloc wf is_cls_C
        obtain halloc_type_safe: "s2::\<preceq>(G, L)"
                                 "(normal s2 --> G,store s2\<turnstile>Addr a::\<preceq>Class C)"
          by (cases s2) (auto dest!: halloc_type_sound)
        from halloc error_free_s1
        have "error_free s2"
          by (rule error_free_halloc)
        with halloc_type_safe T
        show "s2::\<preceq>(G, L) ∧
              (normal s2 --> G,L,store s2\<turnstile>In1l (NewC C)\<succ>In1 (Addr a)::\<preceq>T)  ∧
              (error_free (Norm s0) = error_free s2)"
          by auto
      next
        case (NewA elT a e i s0 s1 s2 s3 L accC T A)
        have eval_init: "G\<turnstile>Norm s0 \<midarrow>init_comp_ty elT-> s1" .
        have eval_e: "G\<turnstile>s1 \<midarrow>e-\<succ>i-> s2" .
        have halloc: "G\<turnstile>abupd (check_neg i) s2\<midarrow>halloc Arr elT (the_Intg i)\<succ>a-> s3".
        have hyp_init: "PROP ?TypeSafe (Norm s0) s1 (In1r (init_comp_ty elT)) ♦" .
        have hyp_size: "PROP ?TypeSafe s1 s2 (In1l e) (In1 i)" .
        have conf_s0: "Norm s0::\<preceq>(G, L)" .
        have     wt: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>In1l (New elT[e])::T" .
        then obtain
          wt_init: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>init_comp_ty elT::\<surd>" and
          wt_size: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>e::-PrimT Integer" and
                elT: "is_type G elT" and
               T: "T=Inl (elT.[])"
          by (rule wt_elim_cases) (auto intro: wt_init_comp_ty dest: is_acc_typeD)
        from NewA.prems
        have da_e:"(|prg=G,cls=accC,lcl=L|)),
                     \<turnstile> dom (locals (store ((Norm s0)::state))) »In1l e» A"
          by (elim da_elim_cases) simp
        obtain conf_s1: "s1::\<preceq>(G, L)" and error_free_s1: "error_free s1"
        proof -
          note conf_s0 wt_init
          moreover obtain I where
            "(|prg=G,cls=accC,lcl=L|)),
             \<turnstile> dom (locals (store ((Norm s0)::state))) »In1r (init_comp_ty elT)» I"
          proof (cases "∃C. elT = Class C")
            case True
            thus ?thesis
              by - (rule that, (auto intro: da_Init [simplified]
                                            assigned.select_convs
                                  simp add: init_comp_ty_def))
             (* simplified: to rewrite ⟨Init C⟩ to In1r (Init C) *)
          next
            case False
            thus ?thesis
            by - (rule that, (auto intro: da_Skip [simplified]
                                          assigned.select_convs
                               simp add: init_comp_ty_def))
             (* simplified: to rewrite ⟨Skip⟩ to In1r (Skip) *)
          qed
          ultimately show ?thesis
            by (rule hyp_init [elim_format]) auto
        qed
        obtain conf_s2: "s2::\<preceq>(G, L)" and error_free_s2: "error_free s2"
        proof -
          from eval_init
          have "dom (locals (store ((Norm s0)::state))) ⊆ dom (locals (store s1))"
            by (rule dom_locals_eval_mono_elim)
          with da_e
          obtain A' where
           "(|prg=G,cls=accC,lcl=L|)),
                \<turnstile> dom (locals (store s1)) »In1l e» A'"
            by (rule da_weakenE)
          with conf_s1 wt_size
          show ?thesis
            by (rule hyp_size [elim_format]) (simp add: that error_free_s1)
        qed
        from conf_s2 have "abupd (check_neg i) s2::\<preceq>(G, L)"
          by (cases s2) auto
        with halloc wf elT
        have halloc_type_safe:
              "s3::\<preceq>(G, L) ∧ (normal s3 --> G,store s3\<turnstile>Addr a::\<preceq>elT.[])"
          by (cases s3) (auto dest!: halloc_type_sound)
        from halloc error_free_s2
        have "error_free s3"
          by (auto dest: error_free_halloc)
        with halloc_type_safe T
        show "s3::\<preceq>(G, L) ∧
              (normal s3 --> G,L,store s3\<turnstile>In1l (New elT[e])\<succ>In1 (Addr a)::\<preceq>T) ∧
              (error_free (Norm s0) = error_free s3) "
          by simp
      next
    -- {*
    \par
    *} (* dummy text command to break paragraph for latex;
                  large paragraphs exhaust memory of debian pdflatex *)
        case (Cast castT e s0 s1 s2 v L accC T A)
        have "G\<turnstile>Norm s0 \<midarrow>e-\<succ>v-> s1" .
        have s2:"s2 = abupd (raise_if (¬ G,store s1\<turnstile>v fits castT) ClassCast) s1" .
        have hyp: "PROP ?TypeSafe (Norm s0) s1 (In1l e) (In1 v)" .
        have conf_s0: "Norm s0::\<preceq>(G, L)" .
        have      wt: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>In1l (Cast castT e)::T" .
        then obtain eT
          where wt_e: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>e::-eT" and
                  eT: "G\<turnstile>eT\<preceq>? castT" and
                   T: "T=Inl castT"
          by (rule wt_elim_cases) auto
        from Cast.prems
        have "(|prg=G,cls=accC,lcl=L|)),
                     \<turnstile> dom (locals (store ((Norm s0)::state))) »In1l e» A"
          by (elim da_elim_cases) simp
        with conf_s0 wt_e
        obtain conf_s1: "s1::\<preceq>(G, L)" and
               v_ok: "normal s1 --> G,store s1\<turnstile>v::\<preceq>eT" and
          error_free_s1: "error_free s1"
          by (rule hyp [elim_format]) simp
        from conf_s1 s2
        have conf_s2: "s2::\<preceq>(G, L)"
          by (cases s1) simp
        from error_free_s1 s2
        have error_free_s2: "error_free s2"
          by simp
        {
          assume norm_s2: "normal s2"
          have "G,L,store s2\<turnstile>In1l (Cast castT e)\<succ>In1 v::\<preceq>T"
          proof -
            from s2 norm_s2 have "normal s1"
              by (cases s1) simp
            with v_ok
            have "G,store s1\<turnstile>v::\<preceq>eT"
              by simp
            with eT wf s2 T norm_s2
            show ?thesis
              by (cases s1) (auto dest: fits_conf)
          qed
        }
        with conf_s2 error_free_s2
        show "s2::\<preceq>(G, L) ∧
               (normal s2 --> G,L,store s2\<turnstile>In1l (Cast castT e)\<succ>In1 v::\<preceq>T)  ∧
               (error_free (Norm s0) = error_free s2)"
          by blast
      next
        case (Inst instT b e s0 s1 v L accC T A)
        have hyp: "PROP ?TypeSafe (Norm s0) s1 (In1l e) (In1 v)" .
        have conf_s0: "Norm s0::\<preceq>(G, L)" .
        from Inst.prems obtain eT
        where wt_e: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>e::-RefT eT"  and
                 T: "T=Inl (PrimT Boolean)"
          by (elim wt_elim_cases) simp
        from Inst.prems
        have da_e: "(|prg=G,cls=accC,lcl=L|)),
                     \<turnstile> dom (locals (store ((Norm s0)::state))) »In1l e» A"
          by (elim da_elim_cases) simp
        from conf_s0 wt_e da_e
        obtain conf_s1: "s1::\<preceq>(G, L)" and
                  v_ok: "normal s1 --> G,store s1\<turnstile>v::\<preceq>RefT eT" and
          error_free_s1: "error_free s1"
          by (rule hyp [elim_format]) simp
        with T show ?case
          by simp
      next
        case (Lit s v L accC T A)
        then show ?case
          by (auto elim!: wt_elim_cases
                   intro: conf_litval simp add: empty_dt_def)
      next
        case (UnOp e s0 s1 unop v L accC T A)
        have hyp: "PROP ?TypeSafe (Norm s0) s1 (In1l e) (In1 v)" .
        have conf_s0: "Norm s0::\<preceq>(G, L)" .
        have      wt: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>In1l (UnOp unop e)::T" .
        then obtain eT
          where    wt_e: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>e::-eT" and
                wt_unop: "wt_unop unop eT" and
                      T: "T=Inl (PrimT (unop_type unop))"
          by (auto elim!: wt_elim_cases)
        from UnOp.prems obtain A where
           da_e: "(|prg=G,cls=accC,lcl=L|)),
                      \<turnstile> dom (locals (store ((Norm s0)::state))) »In1l e» A"
          by (elim da_elim_cases) simp
        from conf_s0 wt_e da_e
        obtain     conf_s1: "s1::\<preceq>(G, L)"  and
                      wt_v: "normal s1 --> G,store s1\<turnstile>v::\<preceq>eT" and
             error_free_s1: "error_free s1"
          by (rule hyp [elim_format]) simp
        from wt_v T wt_unop
        have "normal s1-->G,L,snd s1\<turnstile>In1l (UnOp unop e)\<succ>In1 (eval_unop unop v)::\<preceq>T"
          by (cases unop) auto
        with conf_s1 error_free_s1
        show "s1::\<preceq>(G, L) ∧
         (normal s1 --> G,L,snd s1\<turnstile>In1l (UnOp unop e)\<succ>In1 (eval_unop unop v)::\<preceq>T) ∧
         error_free (Norm s0) = error_free s1"
          by simp
      next
        case (BinOp binop e1 e2 s0 s1 s2 v1 v2 L accC T A)
        have eval_e1: "G\<turnstile>Norm s0 \<midarrow>e1-\<succ>v1-> s1" .
        have eval_e2: "G\<turnstile>s1 \<midarrow>(if need_second_arg binop v1 then In1l e2
                                 else In1r Skip)\<succ>-> (In1 v2, s2)" .
        have hyp_e1: "PROP ?TypeSafe (Norm s0) s1 (In1l e1) (In1 v1)" .
        have hyp_e2: "PROP ?TypeSafe       s1  s2
                       (if need_second_arg binop v1 then In1l e2 else In1r Skip)
                       (In1 v2)" .
        have conf_s0: "Norm s0::\<preceq>(G, L)" .
        have      wt: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>In1l (BinOp binop e1 e2)::T" .
        then obtain e1T e2T where
             wt_e1: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>e1::-e1T" and
             wt_e2: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>e2::-e2T" and
          wt_binop: "wt_binop G binop e1T e2T" and
                 T: "T=Inl (PrimT (binop_type binop))"
          by (elim wt_elim_cases) simp
        have wt_Skip: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>Skip::\<surd>"
          by simp
        obtain S where
          daSkip: "(|prg=G,cls=accC,lcl=L|)),
                      \<turnstile> dom (locals (store s1)) »In1r Skip» S"
          by (auto intro: da_Skip [simplified] assigned.select_convs)
        have da: "(|prg=G,cls=accC,lcl=L|)),\<turnstile> dom (locals (store ((Norm s0::state))))
                      »⟨BinOp binop e1 e2⟩e» A".
        then obtain E1 where
          da_e1: "(|prg=G,cls=accC,lcl=L|)),
                      \<turnstile> dom (locals (store ((Norm s0)::state))) »In1l e1» E1"
          by (elim da_elim_cases) simp+
        from conf_s0 wt_e1 da_e1
        obtain      conf_s1: "s1::\<preceq>(G, L)"  and
                      wt_v1: "normal s1 --> G,store s1\<turnstile>v1::\<preceq>e1T" and
              error_free_s1: "error_free s1"
          by (rule hyp_e1 [elim_format]) simp
        from wt_binop T
        have conf_v:
          "G,L,snd s2\<turnstile>In1l (BinOp binop e1 e2)\<succ>In1 (eval_binop binop v1 v2)::\<preceq>T"
          by (cases binop) auto
        -- {* Note that we don't use the information that v1 really is compatible
              with the expected type e1T and v2 is compatible with e2T,
              because @{text eval_binop} will anyway produce an output of
              the right type.
              So evaluating the addition of an integer with a string is type
              safe. This is a little bit annoying since we may regard such a
              behaviour as not type safe.
              If we want to avoid this we can redefine @{text eval_binop} so that
              it only produces a output of proper type if it is assigned to
              values of the expected types, and arbitrary if the inputs have
              unexpected types. The proof can easily be adapted since we
              have the hypothesis that the values have a proper type.
              This also applies to unary operations.
           *}
        from eval_e1 have
          s0_s1:"dom (locals (store ((Norm s0)::state))) ⊆ dom (locals (store s1))"
          by (rule dom_locals_eval_mono_elim)
        show "s2::\<preceq>(G, L) ∧
              (normal s2 -->
            G,L,snd s2\<turnstile>In1l (BinOp binop e1 e2)\<succ>In1 (eval_binop binop v1 v2)::\<preceq>T) ∧
              error_free (Norm s0) = error_free s2"
        proof (cases "normal s1")
          case False
          with eval_e2 have "s2=s1" by auto
          with conf_s1 error_free_s1 False show ?thesis
            by auto
        next
          case True
          note normal_s1 = this
          show ?thesis
          proof (cases "need_second_arg binop v1")
            case False
            with normal_s1 eval_e2 have "s2=s1"
              by (cases s1) (simp, elim eval_elim_cases,simp)
            with conf_s1 conf_v error_free_s1
            show ?thesis by simp
          next
            case True
            note need_second_arg = this
            with hyp_e2
            have hyp_e2': "PROP ?TypeSafe s1 s2 (In1l e2) (In1 v2)" by simp
            from da wt_e1 wt_e2 wt_binop conf_s0 normal_s1 eval_e1
              wt_v1 [rule_format,OF normal_s1] wf
            obtain E2 where
              "(|prg=G,cls=accC,lcl=L|)),\<turnstile> dom (locals (store s1)) »In1l e2» E2"
              by (rule da_e2_BinOp [elim_format])
                 (auto simp add: need_second_arg )
            with conf_s1 wt_e2
            obtain "s2::\<preceq>(G, L)" and "error_free s2"
              by (rule hyp_e2' [elim_format]) (simp add: error_free_s1)
            with conf_v show ?thesis by simp
          qed
        qed
      next
        case (Super s L accC T A)
        have conf_s: "Norm s::\<preceq>(G, L)" .
        have     wt: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>In1l Super::T" .
        then obtain C c where
                 C: "L This = Some (Class C)" and
           neq_Obj: "C≠Object" and
             cls_C: "class G C = Some c" and
                 T: "T=Inl (Class (super c))"
          by (rule wt_elim_cases) auto
        from Super.prems
        obtain "This ∈ dom (locals s)"
          by (elim da_elim_cases) simp
        with conf_s C  have "G,s\<turnstile>val_this s::\<preceq>Class C"
          by (auto dest: conforms_localD [THEN wlconfD])
        with neq_Obj cls_C wf
        have "G,s\<turnstile>val_this s::\<preceq>Class (super c)"
          by (auto intro: conf_widen
                    dest: subcls_direct[THEN widen.subcls])
        with T conf_s
        show "Norm s::\<preceq>(G, L) ∧
               (normal (Norm s) -->
                  G,L,store (Norm s)\<turnstile>In1l Super\<succ>In1 (val_this s)::\<preceq>T) ∧
               (error_free (Norm s) = error_free (Norm s))"
          by simp
      next
    -- {*
    \par
    *} (* dummy text command to break paragraph for latex;
                  large paragraphs exhaust memory of debian pdflatex *)
        case (Acc upd s0 s1 w v L accC T A)
        have hyp: "PROP ?TypeSafe (Norm s0) s1 (In2 v) (In2 (w,upd))" .
        have conf_s0: "Norm s0::\<preceq>(G, L)" .
        from Acc.prems obtain vT where
          wt_v: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>v::=vT" and
             T: "T=Inl vT"
          by (elim wt_elim_cases) simp
        from Acc.prems obtain V where
          da_v: "(|prg=G,cls=accC,lcl=L|)),
                      \<turnstile> dom (locals (store ((Norm s0)::state))) »In2 v» V"
          by (cases "∃ n. v=LVar n") (insert da.LVar,auto elim!: da_elim_cases)
        {
          fix n assume lvar: "v=LVar n"
          have "locals (store s1) n ≠ None"
          proof -
            from Acc.prems lvar have
              "n ∈ dom (locals s0)"
              by (cases "∃ n. v=LVar n") (auto elim!: da_elim_cases)
            also
            have "dom (locals s0) ⊆ dom (locals (store s1))"
            proof -
              have "G\<turnstile>Norm s0 \<midarrow>v=\<succ>(w, upd)-> s1" .
              thus ?thesis
                by (rule dom_locals_eval_mono_elim) simp
            qed
            finally show ?thesis
              by blast
          qed
        } note lvar_in_locals = this
        from conf_s0 wt_v da_v
        obtain conf_s1: "s1::\<preceq>(G, L)"
          and  conf_var: "(normal s1 --> G,L,store s1\<turnstile>In2 v\<succ>In2 (w, upd)::\<preceq>Inl vT)"
          and  error_free_s1: "error_free s1"
          by (rule hyp [elim_format]) simp
        from lvar_in_locals conf_var T
        have "(normal s1 --> G,L,store s1\<turnstile>In1l (Acc v)\<succ>In1 w::\<preceq>T)"
          by (cases "∃ n. v=LVar n") auto
        with conf_s1 error_free_s1 show ?case
          by simp
      next
        case (Ass e upd s0 s1 s2 v var w L accC T A)
        have eval_var: "G\<turnstile>Norm s0 \<midarrow>var=\<succ>(w, upd)-> s1" .
        have   eval_e: "G\<turnstile>s1 \<midarrow>e-\<succ>v-> s2" .
        have  hyp_var: "PROP ?TypeSafe (Norm s0) s1 (In2 var) (In2 (w,upd))" .
        have    hyp_e: "PROP ?TypeSafe s1 s2 (In1l e) (In1 v)" .
        have  conf_s0: "Norm s0::\<preceq>(G, L)" .
        have       wt: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>In1l (var:=e)::T" .
        then obtain varT eT where
             wt_var: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>var::=varT" and
               wt_e: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>e::-eT" and
              widen: "G\<turnstile>eT\<preceq>varT" and
                  T: "T=Inl eT"
          by (rule wt_elim_cases) auto
        show "assign upd v s2::\<preceq>(G, L) ∧
               (normal (assign upd v s2) -->
                G,L,store (assign upd v s2)\<turnstile>In1l (var:=e)\<succ>In1 v::\<preceq>T) ∧
          (error_free (Norm s0) = error_free (assign upd v s2))"
        proof (cases "∃ vn. var=LVar vn")
          case False
          with Ass.prems
          obtain V E where
            da_var: "(|prg=G,cls=accC,lcl=L|)),
                       \<turnstile> dom (locals (store ((Norm s0)::state))) »In2 var» V" and
            da_e:   "(|prg=G,cls=accC,lcl=L|)), \<turnstile> nrm V »In1l e» E"
            by (elim da_elim_cases) simp+
          from conf_s0 wt_var da_var
          obtain conf_s1: "s1::\<preceq>(G, L)"
            and  conf_var: "normal s1
                             --> G,L,store s1\<turnstile>In2 var\<succ>In2 (w, upd)::\<preceq>Inl varT"
            and  error_free_s1: "error_free s1"
            by (rule hyp_var [elim_format]) simp
          show ?thesis
          proof (cases "normal s1")
            case False
            with eval_e have "s2=s1" by auto
            with False have "assign upd v s2=s1"
              by simp
            with conf_s1 error_free_s1 False show ?thesis
              by auto
          next
            case True
            note normal_s1=this
            obtain A' where "(|prg=G,cls=accC,lcl=L|)),
                             \<turnstile> dom (locals (store s1)) »In1l e» A'"
            proof -
              from eval_var wt_var da_var wf normal_s1
              have "nrm V ⊆  dom (locals (store s1))"
                by (cases rule: da_good_approxE') iprover
              with da_e show ?thesis
                by (rule da_weakenE)
            qed
            with conf_s1 wt_e
            obtain conf_s2: "s2::\<preceq>(G, L)" and
              conf_v: "normal s2 --> G,store s2\<turnstile>v::\<preceq>eT" and
              error_free_s2: "error_free s2"
              by (rule hyp_e [elim_format]) (simp add: error_free_s1)
            show ?thesis
            proof (cases "normal s2")
              case False
              with conf_s2 error_free_s2
              show ?thesis
                by auto
            next
              case True
              from True conf_v
              have conf_v_eT: "G,store s2\<turnstile>v::\<preceq>eT"
                by simp
              with widen wf
              have conf_v_varT: "G,store s2\<turnstile>v::\<preceq>varT"
                by (auto intro: conf_widen)
              from normal_s1 conf_var
              have "G,L,store s1\<turnstile>In2 var\<succ>In2 (w, upd)::\<preceq>Inl varT"
                by simp
              then
              have conf_assign:  "store s1≤|upd\<preceq>varT::\<preceq>(G, L)"
                by (simp add: rconf_def)
              from conf_v_eT conf_v_varT conf_assign normal_s1 True wf eval_var
                eval_e T conf_s2 error_free_s2
              show ?thesis
                by (cases s1, cases s2)
                   (auto dest!: Ass_lemma simp add: assign_conforms_def)
            qed
          qed
        next
          case True
          then obtain vn where vn: "var=LVar vn"
            by blast
          with Ass.prems
          obtain E where
            da_e: "(|prg=G,cls=accC,lcl=L|)),
                       \<turnstile> dom (locals (store ((Norm s0)::state))) »In1l e» E"
            by (elim da_elim_cases) simp+
          from da.LVar vn obtain V where
            da_var: "(|prg=G,cls=accC,lcl=L|)),
                       \<turnstile> dom (locals (store ((Norm s0)::state))) »In2 var» V"
            by auto
          obtain E' where
            da_e': "(|prg=G,cls=accC,lcl=L|)),
                       \<turnstile> dom (locals (store s1)) »In1l e» E'"
          proof -
            have "dom (locals (store ((Norm s0)::state)))
                    ⊆ dom (locals (store (s1)))"
              by (rule dom_locals_eval_mono_elim)
            with da_e show ?thesis
              by (rule da_weakenE)
          qed
          from conf_s0 wt_var da_var
          obtain conf_s1: "s1::\<preceq>(G, L)"
            and  conf_var: "normal s1
                             --> G,L,store s1\<turnstile>In2 var\<succ>In2 (w, upd)::\<preceq>Inl varT"
            and  error_free_s1: "error_free s1"
            by (rule hyp_var [elim_format]) simp
          show ?thesis
          proof (cases "normal s1")
            case False
            with eval_e have "s2=s1" by auto
            with False have "assign upd v s2=s1"
              by simp
            with conf_s1 error_free_s1 False show ?thesis
              by auto
          next
            case True
            note normal_s1 = this
            from conf_s1 wt_e da_e'
            obtain conf_s2: "s2::\<preceq>(G, L)" and
              conf_v: "normal s2 --> G,store s2\<turnstile>v::\<preceq>eT" and
              error_free_s2: "error_free s2"
              by (rule hyp_e [elim_format]) (simp add: error_free_s1)
            show ?thesis
            proof (cases "normal s2")
              case False
              with conf_s2 error_free_s2
              show ?thesis
                by auto
            next
              case True
              from True conf_v
              have conf_v_eT: "G,store s2\<turnstile>v::\<preceq>eT"
                by simp
              with widen wf
              have conf_v_varT: "G,store s2\<turnstile>v::\<preceq>varT"
                by (auto intro: conf_widen)
              from normal_s1 conf_var
              have "G,L,store s1\<turnstile>In2 var\<succ>In2 (w, upd)::\<preceq>Inl varT"
                by simp
              then
              have conf_assign:  "store s1≤|upd\<preceq>varT::\<preceq>(G, L)"
                by (simp add: rconf_def)
              from conf_v_eT conf_v_varT conf_assign normal_s1 True wf eval_var
                eval_e T conf_s2 error_free_s2
              show ?thesis
                by (cases s1, cases s2)
                   (auto dest!: Ass_lemma simp add: assign_conforms_def)
            qed
          qed
        qed
      next
    -- {*
    \par
    *} (* dummy text command to break paragraph for latex;
                  large paragraphs exhaust memory of debian pdflatex *)
        case (Cond b e0 e1 e2 s0 s1 s2 v L accC T A)
        have eval_e0: "G\<turnstile>Norm s0 \<midarrow>e0-\<succ>b-> s1" .
        have eval_e1_e2: "G\<turnstile>s1 \<midarrow>(if the_Bool b then e1 else e2)-\<succ>v-> s2" .
        have hyp_e0: "PROP ?TypeSafe (Norm s0) s1 (In1l e0) (In1 b)" .
        have hyp_if: "PROP ?TypeSafe s1 s2
                           (In1l (if the_Bool b then e1 else e2)) (In1 v)" .
        have conf_s0: "Norm s0::\<preceq>(G, L)" .
        have wt: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>In1l (e0 ? e1 : e2)::T" .
        then obtain T1 T2 statT where
          wt_e0: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>e0::-PrimT Boolean" and
          wt_e1: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>e1::-T1" and
          wt_e2: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>e2::-T2" and
          statT: "G\<turnstile>T1\<preceq>T2 ∧ statT = T2  ∨  G\<turnstile>T2\<preceq>T1 ∧ statT =  T1" and
          T    : "T=Inl statT"
          by (rule wt_elim_cases) auto
        with Cond.prems obtain E0 E1 E2 where
             da_e0: "(|prg=G,cls=accC,lcl=L|)),
                      \<turnstile> dom (locals (store ((Norm s0)::state)))
                          »In1l e0» E0" and
             da_e1: "(|prg=G,cls=accC,lcl=L|)),
                      \<turnstile> (dom (locals (store ((Norm s0)::state)))
                             ∪ assigns_if True e0) »In1l e1» E1" and
             da_e2: "(|prg=G,cls=accC,lcl=L|)),
                      \<turnstile> (dom (locals (store ((Norm s0)::state)))
                            ∪ assigns_if False e0) »In1l e2» E2"
           by (elim da_elim_cases) simp+
        from conf_s0 wt_e0 da_e0
        obtain conf_s1: "s1::\<preceq>(G, L)" and error_free_s1: "error_free s1"
          by (rule hyp_e0 [elim_format]) simp
        show "s2::\<preceq>(G, L) ∧
               (normal s2 --> G,L,store s2\<turnstile>In1l (e0 ? e1 : e2)\<succ>In1 v::\<preceq>T) ∧
               (error_free (Norm s0) = error_free s2)"
        proof (cases "normal s1")
          case False
          with eval_e1_e2 have "s2=s1" by auto
          with conf_s1 error_free_s1 False show ?thesis
            by auto
        next
          case True
          have s0_s1: "dom (locals (store ((Norm s0)::state)))
                        ∪ assigns_if (the_Bool b) e0 ⊆ dom (locals (store s1))"
          proof -
            from eval_e0 have
              "dom (locals (store ((Norm s0)::state))) ⊆ dom (locals (store s1))"
              by (rule dom_locals_eval_mono_elim)
            moreover
            from eval_e0 True wt_e0
            have "assigns_if (the_Bool b) e0 ⊆ dom (locals (store s1))"
              by (rule assigns_if_good_approx')
            ultimately show ?thesis by (rule Un_least)
          qed
          show ?thesis
          proof (cases "the_Bool b")
            case True
            with hyp_if have hyp_e1: "PROP ?TypeSafe s1 s2 (In1l e1) (In1 v)"
              by simp
            from da_e1 s0_s1 True obtain E1' where
              "(|prg=G,cls=accC,lcl=L|)),\<turnstile> (dom (locals (store s1)))»In1l e1» E1'"
              by - (rule da_weakenE, auto iff del: Un_subset_iff)
            with conf_s1 wt_e1
            obtain
              "s2::\<preceq>(G, L)"
              "(normal s2 --> G,L,store s2\<turnstile>In1l e1\<succ>In1 v::\<preceq>Inl T1)"
              "error_free s2"
              by (rule hyp_e1 [elim_format]) (simp add: error_free_s1)
            moreover
            from statT
            have "G\<turnstile>T1\<preceq>statT"
              by auto
            ultimately show ?thesis
              using T wf by auto
          next
            case False
            with hyp_if have hyp_e2: "PROP ?TypeSafe s1 s2 (In1l e2) (In1 v)"
              by simp
            from da_e2 s0_s1 False obtain E2' where
              "(|prg=G,cls=accC,lcl=L|)),\<turnstile> (dom (locals (store s1)))»In1l e2» E2'"
              by - (rule da_weakenE, auto iff del: Un_subset_iff)
            with conf_s1 wt_e2
            obtain
              "s2::\<preceq>(G, L)"
              "(normal s2 --> G,L,store s2\<turnstile>In1l e2\<succ>In1 v::\<preceq>Inl T2)"
              "error_free s2"
              by (rule hyp_e2 [elim_format]) (simp add: error_free_s1)
            moreover
            from statT
            have "G\<turnstile>T2\<preceq>statT"
              by auto
            ultimately show ?thesis
              using T wf by auto
          qed
        qed
      next
        case (Call invDeclC a accC' args e mn mode pTs' s0 s1 s2 s3 s3' s4 statT
               v vs L accC T A)
        have eval_e: "G\<turnstile>Norm s0 \<midarrow>e-\<succ>a-> s1" .
        have eval_args: "G\<turnstile>s1 \<midarrow>args\<doteq>\<succ>vs-> s2" .
        have invDeclC: "invDeclC
                          = invocation_declclass G mode (store s2) a statT
                               (|name = mn, parTs = pTs'|))," .
        have init_lvars:
               "s3 = init_lvars G invDeclC (|name = mn, parTs = pTs'|)), mode a vs s2".
        have check: "s3' =
           check_method_access G accC' statT mode (|name = mn, parTs = pTs'|)), a s3" .
        have eval_methd:
               "G\<turnstile>s3' \<midarrow>Methd invDeclC (|name = mn, parTs = pTs'|)),-\<succ>v-> s4" .
        have     hyp_e: "PROP ?TypeSafe (Norm s0) s1 (In1l e) (In1 a)" .
        have  hyp_args: "PROP ?TypeSafe s1 s2 (In3 args) (In3 vs)" .
        have hyp_methd: "PROP ?TypeSafe s3' s4
                   (In1l (Methd invDeclC (|name = mn, parTs = pTs'|)),)) (In1 v)".
        have conf_s0: "Norm s0::\<preceq>(G, L)" .
        have      wt: "(|prg=G, cls=accC, lcl=L|)),
                        \<turnstile>In1l ({accC',statT,mode}e·mn( {pTs'}args))::T" .
        from wt obtain pTs statDeclT statM where
                     wt_e: "(|prg=G, cls=accC, lcl=L|)),\<turnstile>e::-RefT statT" and
                  wt_args: "(|prg=G, cls=accC, lcl=L|)),\<turnstile>args::\<doteq>pTs" and
                    statM: "max_spec G accC statT (|name=mn,parTs=pTs|)),
                             = {((statDeclT,statM),pTs')}" and
                     mode: "mode = invmode statM e" and
                        T: "T =Inl (resTy statM)" and
            eq_accC_accC': "accC=accC'"
          by (rule wt_elim_cases) fastsimp+
        from Call.prems obtain E where
          da_e: "(|prg=G,cls=accC,lcl=L|)),
                   \<turnstile> (dom (locals (store ((Norm s0)::state))))»In1l e» E" and
          da_args: "(|prg=G,cls=accC,lcl=L|)),\<turnstile> nrm E »In3 args» A"
          by (elim da_elim_cases) simp
        from conf_s0 wt_e da_e
        obtain conf_s1: "s1::\<preceq>(G, L)" and
               conf_a: "normal s1 ==> G, store s1\<turnstile>a::\<preceq>RefT statT" and
               error_free_s1: "error_free s1"
          by (rule hyp_e [elim_format]) simp
        {
          assume abnormal_s2: "¬ normal s2"
          have "set_lvars (locals (store s2)) s4 = s2"
          proof -
            from abnormal_s2 init_lvars
            obtain keep_abrupt: "abrupt s3 = abrupt s2" and
                 "store s3 = store (init_lvars G invDeclC (|name = mn, parTs = pTs'|)),
                                                mode a vs s2)"
              by (auto simp add: init_lvars_def2)
            moreover
            from keep_abrupt abnormal_s2 check
            have eq_s3'_s3: "s3'=s3"
              by (auto simp add: check_method_access_def Let_def)
            moreover
            from eq_s3'_s3 abnormal_s2 keep_abrupt eval_methd
            have "s4=s3'"
              by auto
            ultimately show
              "set_lvars (locals (store s2)) s4 = s2"
              by (cases s2,cases s3) (simp add: init_lvars_def2)
          qed
        } note propagate_abnormal_s2 = this
        show "(set_lvars (locals (store s2))) s4::\<preceq>(G, L) ∧
               (normal ((set_lvars (locals (store s2))) s4) -->
                 G,L,store ((set_lvars (locals (store s2))) s4)
                   \<turnstile>In1l ({accC',statT,mode}e·mn( {pTs'}args))\<succ>In1 v::\<preceq>T) ∧
               (error_free (Norm s0) =
                    error_free ((set_lvars (locals (store s2))) s4))"
        proof (cases "normal s1")
          case False
          with eval_args have "s2=s1" by auto
          with False propagate_abnormal_s2 conf_s1 error_free_s1
          show ?thesis
            by auto
        next
          case True
          note normal_s1 = this
          obtain A' where
            "(|prg=G,cls=accC,lcl=L|)),\<turnstile> dom (locals (store s1)) »In3 args» A'"
          proof -
            from eval_e wt_e da_e wf normal_s1
            have "nrm E ⊆  dom (locals (store s1))"
              by (cases rule: da_good_approxE') iprover
            with da_args show ?thesis
              by (rule da_weakenE)
          qed
          with conf_s1 wt_args
          obtain    conf_s2: "s2::\<preceq>(G, L)" and
                  conf_args: "normal s2
                             ==>  list_all2 (conf G (store s2)) vs pTs" and
              error_free_s2: "error_free s2"
            by (rule hyp_args [elim_format]) (simp add: error_free_s1)
          from error_free_s2 init_lvars
          have error_free_s3: "error_free s3"
            by (auto simp add: init_lvars_def2)
          from statM
          obtain
            statM': "(statDeclT,statM)∈mheads G accC statT (|name=mn,parTs=pTs'|))," and
            pTs_widen: "G\<turnstile>pTs[\<preceq>]pTs'"
            by (blast dest: max_spec2mheads)
          from check
          have eq_store_s3'_s3: "store s3'=store s3"
            by (cases s3) (simp add: check_method_access_def Let_def)
          obtain invC
            where invC: "invC = invocation_class mode (store s2) a statT"
            by simp
          with init_lvars
          have invC': "invC = (invocation_class mode (store s3) a statT)"
            by (cases s2,cases mode) (auto simp add: init_lvars_def2 )
          show ?thesis
          proof (cases "normal s2")
            case False
            with propagate_abnormal_s2 conf_s2 error_free_s2
            show ?thesis
              by auto
          next
            case True
            note normal_s2 = True
            with normal_s1 conf_a eval_args
            have conf_a_s2: "G, store s2\<turnstile>a::\<preceq>RefT statT"
              by (auto dest: eval_gext intro: conf_gext)
            show ?thesis
            proof (cases "a=Null --> is_static statM")
              case False
              then obtain not_static: "¬ is_static statM" and Null: "a=Null"
                by blast
              with normal_s2 init_lvars mode
              obtain np: "abrupt s3 = Some (Xcpt (Std NullPointer))" and
                         "store s3 = store (init_lvars G invDeclC
                                           (|name = mn, parTs = pTs'|)), mode a vs s2)"
                by (auto simp add: init_lvars_def2)
              moreover
              from np check
              have eq_s3'_s3: "s3'=s3"
                by (auto simp add: check_method_access_def Let_def)
              moreover
              from eq_s3'_s3 np eval_methd
              have "s4=s3'"
                by auto
              ultimately have
                "set_lvars (locals (store s2)) s4
                = (Some (Xcpt (Std NullPointer)),store s2)"
                by (cases s2,cases s3) (simp add: init_lvars_def2)
              with conf_s2 error_free_s2
              show ?thesis
                by (cases s2) (auto dest: conforms_NormI)
            next
              case True
              with mode have notNull: "mode = IntVir --> a ≠ Null"
                by (auto dest!: Null_staticD)
              with conf_s2 conf_a_s2 wf invC
              have dynT_prop: "G\<turnstile>mode->invC\<preceq>statT"
                by (cases s2) (auto intro: DynT_propI)
              with wt_e statM' invC mode wf
              obtain dynM where
                dynM: "dynlookup G statT invC  (|name=mn,parTs=pTs'|)), = Some dynM" and
                acc_dynM: "G \<turnstile>Methd  (|name=mn,parTs=pTs'|)), dynM
                                in invC dyn_accessible_from accC"
                by (force dest!: call_access_ok)
              with invC' check eq_accC_accC'
              have eq_s3'_s3: "s3'=s3"
                by (auto simp add: check_method_access_def Let_def)
              from dynT_prop wf wt_e statM' mode invC invDeclC dynM
              obtain
                wf_dynM: "wf_mdecl G invDeclC ((|name=mn,parTs=pTs'|)),,mthd dynM)" and
                  dynM': "methd G invDeclC (|name=mn,parTs=pTs'|)), = Some dynM" and
                iscls_invDeclC: "is_class G invDeclC" and
                     invDeclC': "invDeclC = declclass dynM" and
                  invC_widen: "G\<turnstile>invC\<preceq>C invDeclC" and
                 resTy_widen: "G\<turnstile>resTy dynM\<preceq>resTy statM" and
                is_static_eq: "is_static dynM = is_static statM" and
                involved_classes_prop:
                 "(if invmode statM e = IntVir
                   then ∀statC. statT = ClassT statC --> G\<turnstile>invC\<preceq>C statC
                   else ((∃statC. statT = ClassT statC ∧ G\<turnstile>statC\<preceq>C invDeclC) ∨
                         (∀statC. statT ≠ ClassT statC ∧ invDeclC = Object)) ∧
                          statDeclT = ClassT invDeclC)"
                by (cases rule: DynT_mheadsE) simp
              obtain L' where
               L':"L'=(λ k.
                     (case k of
                        EName e
                        => (case e of
                              VNam v
                              =>(table_of (lcls (mbody (mthd dynM)))
                                 (pars (mthd dynM)[\<mapsto>]pTs')) v
                            | Res => Some (resTy dynM))
                      | This => if is_static statM
                                then None else Some (Class invDeclC)))"
                by simp
              from wf_dynM [THEN wf_mdeclD1, THEN conjunct1] normal_s2 conf_s2 wt_e
                wf eval_args conf_a mode notNull wf_dynM involved_classes_prop
              have conf_s3: "s3::\<preceq>(G,L')"
                apply -
                   (* FIXME confomrs_init_lvars should be
                      adjusted to be more directy applicable *)
                apply (drule conforms_init_lvars [of G invDeclC
                        "(|name=mn,parTs=pTs'|))," dynM "store s2" vs pTs "abrupt s2"
                        L statT invC a "(statDeclT,statM)" e])
                apply (rule wf)
                apply (rule conf_args,assumption)
                apply (simp add: pTs_widen)
                apply (cases s2,simp)
                apply (rule dynM')
                apply (force dest: ty_expr_is_type)
                apply (rule invC_widen)
                apply (force intro: conf_gext dest: eval_gext)
                apply simp
                apply simp
                apply (simp add: invC)
                apply (simp add: invDeclC)
                apply (simp add: normal_s2)
                apply (cases s2, simp add: L' init_lvars
                                 cong add: lname.case_cong ename.case_cong)
                done
              with eq_s3'_s3
              have conf_s3': "s3'::\<preceq>(G,L')" by simp
              moreover
              from  is_static_eq wf_dynM L'
              obtain mthdT where
                "(|prg=G,cls=invDeclC,lcl=L'|)),
                   \<turnstile>Body invDeclC (stmt (mbody (mthd dynM)))::-mthdT" and
                mthdT_widen: "G\<turnstile>mthdT\<preceq>resTy dynM"
                by - (drule wf_mdecl_bodyD,
                     auto simp add: callee_lcl_def
                          cong add: lname.case_cong ename.case_cong)
              with dynM' iscls_invDeclC invDeclC'
              have
                "(|prg=G,cls=invDeclC,lcl=L'|)),
                   \<turnstile>(Methd invDeclC (|name = mn, parTs = pTs'|)),)::-mthdT"
                by (auto intro: wt.Methd)
              moreover
              obtain M where
                "(|prg=G,cls=invDeclC,lcl=L'|)),
                   \<turnstile> dom (locals (store s3'))
                      »In1l (Methd invDeclC (|name = mn, parTs = pTs'|)),)» M"
              proof -
                from wf_dynM
                obtain M' where
                  da_body:
                  "(|prg=G, cls=invDeclC
                   ,lcl=callee_lcl invDeclC (|name = mn, parTs = pTs'|)), (mthd dynM)
                   |)), \<turnstile> parameters (mthd dynM) »⟨stmt (mbody (mthd dynM))⟩» M'" and
                  res: "Result ∈ nrm M'"
                  by (rule wf_mdeclE) iprover
                from da_body is_static_eq L' have
                  "(|prg=G, cls=invDeclC,lcl=L'|)),
                     \<turnstile> parameters (mthd dynM) »⟨stmt (mbody (mthd dynM))⟩» M'"
                  by (simp add: callee_lcl_def
                      cong add: lname.case_cong ename.case_cong)
                moreover have "parameters (mthd dynM) ⊆  dom (locals (store s3'))"
                proof -
                  from is_static_eq
                  have "(invmode (mthd dynM) e) = (invmode statM e)"
                    by (simp add: invmode_def)
                  moreover
                  have "length (pars (mthd dynM)) = length vs"
                  proof -
                    from normal_s2 conf_args
                    have "length vs = length pTs"
                      by (simp add: list_all2_def)
                    also from pTs_widen
                    have "… = length pTs'"
                      by (simp add: widens_def list_all2_def)
                    also from wf_dynM
                    have "… = length (pars (mthd dynM))"
                      by (simp add: wf_mdecl_def wf_mhead_def)
                    finally show ?thesis ..
                  qed
                  moreover note init_lvars dynM' is_static_eq normal_s2 mode
                  ultimately
                  have "parameters (mthd dynM) = dom (locals (store s3))"
                    using dom_locals_init_lvars
                      [of "mthd dynM" G invDeclC "(|name=mn,parTs=pTs'|))," vs e a s2]
                    by simp
                  also from check
                  have "dom (locals (store s3)) ⊆  dom (locals (store s3'))"
                    by (simp add:  eq_s3'_s3)
                  finally show ?thesis .
                qed
                ultimately obtain M2 where
                  da:
                  "(|prg=G, cls=invDeclC,lcl=L'|)),
                    \<turnstile> dom (locals (store s3')) »⟨stmt (mbody (mthd dynM))⟩» M2" and
                  M2: "nrm M' ⊆ nrm M2"
                  by (rule da_weakenE)
                from res M2 have "Result ∈ nrm M2"
                  by blast
                moreover from wf_dynM
                have "jumpNestingOkS {Ret} (stmt (mbody (mthd dynM)))"
                  by (rule wf_mdeclE)
                ultimately
                obtain M3 where
                  "(|prg=G, cls=invDeclC,lcl=L'|)), \<turnstile> dom (locals (store s3'))
                         »⟨Body (declclass dynM) (stmt (mbody (mthd dynM)))⟩» M3"
                  using da
                  by (iprover intro: da.Body assigned.select_convs)
                from _ this [simplified]
                show ?thesis
                  by (rule da.Methd [simplified,elim_format])
                     (auto intro: dynM')
              qed
              ultimately obtain
                conf_s4: "s4::\<preceq>(G, L')" and
                conf_Res: "normal s4 --> G,store s4\<turnstile>v::\<preceq>mthdT" and
                error_free_s4: "error_free s4"
                by (rule hyp_methd [elim_format])
                   (simp add: error_free_s3 eq_s3'_s3)
              from init_lvars eval_methd eq_s3'_s3
              have "store s2≤|store s4"
                by (cases s2) (auto dest!: eval_gext simp add: init_lvars_def2 )
              moreover
              have "abrupt s4 ≠ Some (Jump Ret)"
              proof -
                from normal_s2 init_lvars
                have "abrupt s3 ≠ Some (Jump Ret)"
                  by (cases s2) (simp add: init_lvars_def2 abrupt_if_def)
                with check
                have "abrupt s3' ≠ Some (Jump Ret)"
                  by (cases s3) (auto simp add: check_method_access_def Let_def)
                with eval_methd
                show ?thesis
                  by (rule Methd_no_jump)
              qed
              ultimately
              have "(set_lvars (locals (store s2))) s4::\<preceq>(G, L)"
                using conf_s2 conf_s4
                by (cases s2,cases s4) (auto intro: conforms_return)
              moreover
              from conf_Res mthdT_widen resTy_widen wf
              have "normal s4
                      --> G,store s4\<turnstile>v::\<preceq>(resTy statM)"
                by (auto dest: widen_trans)
              then
              have "normal ((set_lvars (locals (store s2))) s4)
                 --> G,store((set_lvars (locals (store s2))) s4) \<turnstile>v::\<preceq>(resTy statM)"
                by (cases s4) auto
              moreover note error_free_s4 T
              ultimately
              show ?thesis
                by simp
            qed
          qed
        qed
      next
    -- {*
    \par
    *} (* dummy text command to break paragraph for latex;
                  large paragraphs exhaust memory of debian pdflatex *)
        case (Methd D s0 s1 sig v L accC T A)
        have "G\<turnstile>Norm s0 \<midarrow>body G D sig-\<succ>v-> s1" .
        have hyp:"PROP ?TypeSafe (Norm s0) s1 (In1l (body G D sig)) (In1 v)" .
        have conf_s0: "Norm s0::\<preceq>(G, L)" .
        have      wt: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>In1l (Methd D sig)::T" .
        then obtain m bodyT where
          D: "is_class G D" and
          m: "methd G D sig = Some m" and
          wt_body: "(|prg = G, cls = accC, lcl = L|)),
                      \<turnstile>Body (declclass m) (stmt (mbody (mthd m)))::-bodyT" and
          T: "T=Inl bodyT"
          by (rule wt_elim_cases) auto
        moreover
        from Methd.prems m have
           da_body: "(|prg=G,cls=accC,lcl=L|)),
                       \<turnstile> (dom (locals (store ((Norm s0)::state))))
                           »In1l (Body (declclass m) (stmt (mbody (mthd m))))» A"
          by - (erule da_elim_cases,simp)
        ultimately
        show "s1::\<preceq>(G, L) ∧
               (normal s1 --> G,L,snd s1\<turnstile>In1l (Methd D sig)\<succ>In1 v::\<preceq>T) ∧
               (error_free (Norm s0) = error_free s1)"
          using hyp [of _ _ "(Inl bodyT)"] conf_s0
          by (auto simp add: Let_def body_def)
      next
        case (Body D c s0 s1 s2 s3 L accC T A)
        have eval_init: "G\<turnstile>Norm s0 \<midarrow>Init D-> s1" .
        have eval_c: "G\<turnstile>s1 \<midarrow>c-> s2" .
        have hyp_init: "PROP ?TypeSafe (Norm s0) s1 (In1r (Init D)) ♦" .
        have hyp_c: "PROP ?TypeSafe s1 s2 (In1r c) ♦" .
        have conf_s0: "Norm s0::\<preceq>(G, L)" .
        have wt: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>In1l (Body D c)::T" .
        then obtain bodyT where
             iscls_D: "is_class G D" and
                wt_c: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>c::\<surd>" and
             resultT: "L Result = Some bodyT" and
          isty_bodyT: "is_type G bodyT" and (* ### not needed! remove from wt? *)
                   T: "T=Inl bodyT"
          by (rule wt_elim_cases) auto
        from Body.prems obtain C where
          da_c: "(|prg=G,cls=accC,lcl=L|)),
                       \<turnstile> (dom (locals (store ((Norm s0)::state))))»In1r c» C" and
          jmpOk: "jumpNestingOkS {Ret} c" and
          res: "Result ∈ nrm C"
          by (elim da_elim_cases) simp
        note conf_s0
        moreover from iscls_D
        have "(|prg=G, cls=accC, lcl=L|)),\<turnstile>Init D::\<surd>" by auto
        moreover obtain I where
          "(|prg=G,cls=accC,lcl=L|)),
              \<turnstile> dom (locals (store ((Norm s0)::state))) »In1r (Init D)» I"
          by (auto intro: da_Init [simplified] assigned.select_convs)
        ultimately obtain
          conf_s1: "s1::\<preceq>(G, L)" and error_free_s1:  "error_free s1"
           by (rule hyp_init [elim_format]) simp
        obtain C' where da_C': "(|prg=G,cls=accC,lcl=L|)),
                                 \<turnstile> (dom (locals (store s1)))»In1r c» C'"
                   and nrm_C': "nrm C ⊆ nrm C'"
        proof -
          from eval_init
          have "(dom (locals (store ((Norm s0)::state))))
                         ⊆ (dom (locals (store s1)))"
            by (rule dom_locals_eval_mono_elim)
          with da_c show ?thesis by (rule da_weakenE)
        qed
        from conf_s1 wt_c da_C'
        obtain conf_s2: "s2::\<preceq>(G, L)" and error_free_s2: "error_free s2"
          by (rule hyp_c [elim_format]) (simp add: error_free_s1)
        from conf_s2
        have "abupd (absorb Ret) s2::\<preceq>(G, L)"
          by (cases s2) (auto intro: conforms_absorb)
        moreover
        from error_free_s2
        have "error_free (abupd (absorb Ret) s2)"
          by simp
        moreover have "abrupt (abupd (absorb Ret) s3) ≠ Some (Jump Ret)"
          by (cases s3) (simp add: absorb_def)
        moreover have "s3=s2"
        proof -
          from iscls_D
          have wt_init: "(|prg=G, cls=accC, lcl=L|)),\<turnstile>(Init D)::\<surd>"
            by auto
          from eval_init wf
          have s1_no_jmp: "!! j. abrupt s1 ≠ Some (Jump j)"
            by - (rule eval_statement_no_jump [OF _ _ _ wt_init],auto)
          from eval_c _ wt_c wf
          have "!! j. abrupt s2 = Some (Jump j) ==> j=Ret"
            by (rule jumpNestingOk_evalE) (auto intro: jmpOk simp add: s1_no_jmp)
          moreover
          have "s3 =
                    (if ∃l. abrupt s2 = Some (Jump (Break l)) ∨
                            abrupt s2 = Some (Jump (Cont l))
                     then abupd (λx. Some (Error CrossMethodJump)) s2 else s2)" .
          ultimately show ?thesis
            by force
        qed
        moreover
        {
          assume normal_upd_s2:  "normal (abupd (absorb Ret) s2)"
          have "Result ∈ dom (locals (store s2))"
          proof -
            from normal_upd_s2
            have "normal s2 ∨ abrupt s2 = Some (Jump Ret)"
              by (cases s2) (simp add: absorb_def)
            thus ?thesis
            proof
              assume "normal s2"
              with eval_c wt_c da_C' wf res nrm_C'
              show ?thesis
                by (cases rule: da_good_approxE') blast
            next
              assume "abrupt s2 = Some (Jump Ret)"
              with conf_s2 show ?thesis
                by (cases s2) (auto dest: conforms_RetD simp add: dom_def)
            qed
          qed
        }
        moreover note T resultT
        ultimately
        show "abupd (absorb Ret) s3::\<preceq>(G, L) ∧
               (normal (abupd (absorb Ret) s3) -->
                 G,L,store (abupd (absorb Ret) s3)
                 \<turnstile>In1l (Body D c)\<succ>In1 (the (locals (store s2) Result))::\<preceq>T) ∧
              (error_free (Norm s0) = error_free (abupd (absorb Ret) s3)) "
          by (cases s2) (auto intro: conforms_locals)
      next
        case (LVar s vn L accC T)
        have conf_s: "Norm s::\<preceq>(G, L)" and
                 wt: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>In2 (LVar vn)::T" .
        then obtain vnT where
          vnT: "L vn = Some vnT" and
            T: "T=Inl vnT"
          by (auto elim!: wt_elim_cases)
        from conf_s vnT
        have conf_fst: "locals s vn ≠ None --> G,s\<turnstile>fst (lvar vn s)::\<preceq>vnT"
         by (auto elim: conforms_localD [THEN wlconfD]
                  simp add: lvar_def)
        moreover
        from conf_s conf_fst vnT
        have "s≤|snd (lvar vn s)\<preceq>vnT::\<preceq>(G, L)"
          by (auto elim: conforms_lupd simp add: assign_conforms_def lvar_def)
        moreover note conf_s T
        ultimately
        show "Norm s::\<preceq>(G, L) ∧
                     (normal (Norm s) -->
                        G,L,store (Norm s)\<turnstile>In2 (LVar vn)\<succ>In2 (lvar vn s)::\<preceq>T) ∧
                     (error_free (Norm s) = error_free (Norm s))"
          by (simp add: lvar_def)
      next
        case (FVar a accC e fn s0 s1 s2 s2' s3 stat statDeclC v L accC' T A)
        have eval_init: "G\<turnstile>Norm s0 \<midarrow>Init statDeclC-> s1" .
        have eval_e: "G\<turnstile>s1 \<midarrow>e-\<succ>a-> s2" .
        have fvar: "(v, s2') = fvar statDeclC stat fn a s2" .
        have check: "s3 = check_field_access G accC statDeclC fn stat a s2'" .
        have hyp_init: "PROP ?TypeSafe (Norm s0) s1 (In1r (Init statDeclC)) ♦" .
        have hyp_e: "PROP ?TypeSafe s1 s2 (In1l e) (In1 a)" .
        have conf_s0: "Norm s0::\<preceq>(G, L)" .
        have wt: "(|prg=G, cls=accC', lcl=L|)),\<turnstile>In2 ({accC,statDeclC,stat}e..fn)::T" .
        then obtain statC f where
                    wt_e: "(|prg=G, cls=accC, lcl=L|)),\<turnstile>e::-Class statC" and
                accfield: "accfield G accC statC fn = Some (statDeclC,f)" and
           eq_accC_accC': "accC=accC'" and
                    stat: "stat=is_static f" and
                       T: "T=(Inl (type f))"
          by (rule wt_elim_cases) (auto simp add: member_is_static_simp)
        from FVar.prems eq_accC_accC'
        have da_e: "(|prg=G, cls=accC, lcl=L|)),
                     \<turnstile> (dom (locals (store ((Norm s0)::state))))»In1l e» A"
          by (elim da_elim_cases) simp
        note conf_s0
        moreover
        from wf wt_e
        have iscls_statC: "is_class G statC"
          by (auto dest: ty_expr_is_type type_is_class)
        with wf accfield
        have iscls_statDeclC: "is_class G statDeclC"
          by (auto dest!: accfield_fields dest: fields_declC)
        hence "(|prg=G, cls=accC, lcl=L|)),\<turnstile>(Init statDeclC)::\<surd>"
          by simp
        moreover obtain I where
          "(|prg=G,cls=accC,lcl=L|)),
            \<turnstile> dom (locals (store ((Norm s0)::state))) »In1r (Init statDeclC)» I"
          by (auto intro: da_Init [simplified] assigned.select_convs)
        ultimately
        obtain conf_s1: "s1::\<preceq>(G, L)" and error_free_s1: "error_free s1"
          by (rule hyp_init [elim_format]) simp
        obtain A' where
          "(|prg=G, cls=accC, lcl=L|)), \<turnstile> (dom (locals (store s1)))»In1l e» A'"
        proof -
          from eval_init
          have "(dom (locals (store ((Norm s0)::state))))
                   ⊆ (dom (locals (store s1)))"
            by (rule dom_locals_eval_mono_elim)
          with da_e show ?thesis
            by (rule da_weakenE)
        qed
        with conf_s1 wt_e
        obtain       conf_s2: "s2::\<preceq>(G, L)" and
                      conf_a: "normal s2 --> G,store s2\<turnstile>a::\<preceq>Class statC" and
               error_free_s2: "error_free s2"
          by (rule hyp_e [elim_format]) (simp add: error_free_s1)
        from fvar
        have store_s2': "store s2'=store s2"
          by (cases s2) (simp add: fvar_def2)
        with fvar conf_s2
        have conf_s2': "s2'::\<preceq>(G, L)"
          by (cases s2,cases stat) (auto simp add: fvar_def2)
        from eval_init
        have initd_statDeclC_s1: "initd statDeclC s1"
          by (rule init_yields_initd)
        from accfield wt_e eval_init eval_e conf_s2 conf_a fvar stat check  wf
        have eq_s3_s2': "s3=s2'"
          by (auto dest!: error_free_field_access)
        have conf_v: "normal s2' ==>
               G,store s2'\<turnstile>fst v::\<preceq>type f ∧ store s2'≤|snd v\<preceq>type f::\<preceq>(G, L)"
        proof - (*###FVar_lemma should be adjusted to be more directy applicable *)
          assume normal: "normal s2'"
          obtain vv vf x2 store2 store2'
            where  v: "v=(vv,vf)" and
                  s2: "s2=(x2,store2)" and
             store2': "store s2' = store2'"
            by (cases v,cases s2,cases s2') blast
          from iscls_statDeclC obtain c
            where c: "class G statDeclC = Some c"
            by auto
          have "G,store2'\<turnstile>vv::\<preceq>type f ∧ store2'≤|vf\<preceq>type f::\<preceq>(G, L)"
          proof (rule FVar_lemma [of vv vf store2' statDeclC f fn a x2 store2
                                   statC G c L "store s1"])
            from v normal s2 fvar stat store2'
            show "((vv, vf), Norm store2') =
                   fvar statDeclC (static f) fn a (x2, store2)"
              by (auto simp add: member_is_static_simp)
            from accfield iscls_statC wf
            show "G\<turnstile>statC\<preceq>C statDeclC"
              by (auto dest!: accfield_fields dest: fields_declC)
            from accfield
            show fld: "table_of (DeclConcepts.fields G statC) (fn, statDeclC) = Some f"
              by (auto dest!: accfield_fields)
            from wf show "wf_prog G" .
            from conf_a s2 show "x2 = None --> G,store2\<turnstile>a::\<preceq>Class statC"
              by auto
            from fld wf iscls_statC
            show "statDeclC ≠ Object "
              by (cases "statDeclC=Object") (drule fields_declC,simp+)+
            from c show "class G statDeclC = Some c" .
            from conf_s2 s2 show "(x2, store2)::\<preceq>(G, L)" by simp
            from eval_e s2 show "snd s1≤|store2" by (auto dest: eval_gext)
            from initd_statDeclC_s1 show "inited statDeclC (globs (snd s1))"
              by simp
          qed
          with v s2 store2'
          show ?thesis
            by simp
        qed
        from fvar error_free_s2
        have "error_free s2'"
          by (cases s2)
             (auto simp add: fvar_def2 intro!: error_free_FVar_lemma)
        with conf_v T conf_s2' eq_s3_s2'
        show "s3::\<preceq>(G, L) ∧
              (normal s3
               --> G,L,store s3\<turnstile>In2 ({accC,statDeclC,stat}e..fn)\<succ>In2 v::\<preceq>T) ∧
              (error_free (Norm s0) = error_free s3)"
          by auto
      next
        case (AVar a e1 e2 i s0 s1 s2 s2' v L accC T A)
        have eval_e1: "G\<turnstile>Norm s0 \<midarrow>e1-\<succ>a-> s1" .
        have eval_e2: "G\<turnstile>s1 \<midarrow>e2-\<succ>i-> s2" .
        have hyp_e1: "PROP ?TypeSafe (Norm s0) s1 (In1l e1) (In1 a)" .
        have hyp_e2: "PROP ?TypeSafe s1 s2 (In1l e2) (In1 i)" .
        have avar: "(v, s2') = avar G i a s2" .
        have conf_s0: "Norm s0::\<preceq>(G, L)" .
        have wt:  "(|prg = G, cls = accC, lcl = L|)),\<turnstile>In2 (e1.[e2])::T" .
        then obtain elemT
           where wt_e1: "(|prg=G,cls=accC,lcl=L|)),\<turnstile>e1::-elemT.[]" and
                 wt_e2: "(|prg=G,cls=accC,lcl=L|)),\<turnstile>e2::-PrimT Integer" and
                     T: "T= Inl elemT"
          by (rule wt_elim_cases) auto
        from AVar.prems obtain E1 where
          da_e1: "(|prg=G,cls=accC,lcl=L|)),
                    \<turnstile> (dom (locals (store ((Norm s0)::state))))»In1l e1» E1" and
          da_e2: "(|prg=G,cls=accC,lcl=L|)),\<turnstile> nrm E1 »In1l e2» A"
          by (elim da_elim_cases) simp
        from conf_s0 wt_e1 da_e1
        obtain conf_s1: "s1::\<preceq>(G, L)" and
                conf_a: "(normal s1 --> G,store s1\<turnstile>a::\<preceq>elemT.[])" and
                error_free_s1: "error_free s1"
          by (rule hyp_e1 [elim_format]) simp
        show "s2'::\<preceq>(G, L) ∧
               (normal s2' --> G,L,store s2'\<turnstile>In2 (e1.[e2])\<succ>In2 v::\<preceq>T) ∧
               (error_free (Norm s0) = error_free s2') "
        proof (cases "normal s1")
          case False
          moreover
          from False eval_e2 have eq_s2_s1: "s2=s1" by auto
          moreover
          from eq_s2_s1 False have  "¬ normal s2" by simp
          then have "snd (avar G i a s2) = s2"
            by (cases s2) (simp add: avar_def2)
          with avar have "s2'=s2"
            by (cases "(avar G i a s2)") simp
          ultimately show ?thesis
            using conf_s1 error_free_s1
            by auto
        next
          case True
          obtain A' where
            "(|prg=G,cls=accC,lcl=L|)),\<turnstile> dom (locals (store s1)) »In1l e2» A'"
          proof -
            from eval_e1 wt_e1 da_e1 wf True
            have "nrm E1 ⊆ dom (locals (store s1))"
              by (cases rule: da_good_approxE') iprover
            with da_e2 show ?thesis
              by (rule da_weakenE)
          qed
          with conf_s1 wt_e2
          obtain conf_s2: "s2::\<preceq>(G, L)" and error_free_s2: "error_free s2"
            by (rule hyp_e2 [elim_format]) (simp add: error_free_s1)
          from avar
          have "store s2'=store s2"
            by (cases s2) (simp add: avar_def2)
          with avar conf_s2
          have conf_s2': "s2'::\<preceq>(G, L)"
            by (cases s2) (auto simp add: avar_def2)
          from avar error_free_s2
          have error_free_s2': "error_free s2'"
            by (cases s2) (auto simp add: avar_def2 )
          have "normal s2' ==>
            G,store s2'\<turnstile>fst v::\<preceq>elemT ∧ store s2'≤|snd v\<preceq>elemT::\<preceq>(G, L)"
          proof -(*###AVar_lemma should be adjusted to be more directy applicable *)
            assume normal: "normal s2'"
            show ?thesis
            proof -
              obtain vv vf x1 store1 x2 store2 store2'
                where  v: "v=(vv,vf)" and
                      s1: "s1=(x1,store1)" and
                      s2: "s2=(x2,store2)" and
                 store2': "store2'=store s2'"
                by (cases v,cases s1, cases s2, cases s2') blast
              have "G,store2'\<turnstile>vv::\<preceq>elemT ∧ store2'≤|vf\<preceq>elemT::\<preceq>(G, L)"
              proof (rule AVar_lemma [of G x1 store1 e2 i x2 store2 vv vf store2' a,
                                      OF wf])
                from s1 s2 eval_e2 show "G\<turnstile>(x1, store1) \<midarrow>e2-\<succ>i-> (x2, store2)"
                  by simp
                from v normal s2 store2' avar
                show "((vv, vf), Norm store2') = avar G i a (x2, store2)"
                  by auto
                from s2 conf_s2 show "(x2, store2)::\<preceq>(G, L)" by simp
                from s1 conf_a show  "x1 = None --> G,store1\<turnstile>a::\<preceq>elemT.[]" by simp
                from eval_e2 s1 s2 show "store1≤|store2" by (auto dest: eval_gext)
              qed
              with v s1 s2 store2'
              show ?thesis
                by simp
            qed
          qed
          with conf_s2' error_free_s2' T
          show ?thesis
            by auto
        qed
      next
        case (Nil s0 L accC T)
        then show ?case
          by (auto elim!: wt_elim_cases)
      next
    -- {*
    \par
    *} (* dummy text command to break paragraph for latex;
                  large paragraphs exhaust memory of debian pdflatex *)
        case (Cons e es s0 s1 s2 v vs L accC T A)
        have eval_e: "G\<turnstile>Norm s0 \<midarrow>e-\<succ>v-> s1" .
        have eval_es: "G\<turnstile>s1 \<midarrow>es\<doteq>\<succ>vs-> s2" .
        have hyp_e: "PROP ?TypeSafe (Norm s0) s1 (In1l e) (In1 v)" .
        have hyp_es: "PROP ?TypeSafe s1 s2 (In3 es) (In3 vs)" .
        have conf_s0: "Norm s0::\<preceq>(G, L)" .
        have wt: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>In3 (e # es)::T" .
        then obtain eT esT where
           wt_e: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>e::-eT" and
           wt_es: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>es::\<doteq>esT" and
           T: "T=Inr (eT#esT)"
          by (rule wt_elim_cases) blast
        from Cons.prems obtain E where
          da_e: "(|prg=G,cls=accC,lcl=L|)),
                    \<turnstile> (dom (locals (store ((Norm s0)::state))))»In1l e» E" and
          da_es: "(|prg=G,cls=accC,lcl=L|)),\<turnstile> nrm E »In3 es» A"
          by (elim da_elim_cases) simp
        from conf_s0 wt_e da_e
        obtain conf_s1: "s1::\<preceq>(G, L)" and error_free_s1: "error_free s1" and
          conf_v: "normal s1 --> G,store s1\<turnstile>v::\<preceq>eT"
          by (rule hyp_e [elim_format]) simp
        show
          "s2::\<preceq>(G, L) ∧
          (normal s2 --> G,L,store s2\<turnstile>In3 (e # es)\<succ>In3 (v # vs)::\<preceq>T) ∧
          (error_free (Norm s0) = error_free s2)"
        proof (cases "normal s1")
          case False
          with eval_es have "s2=s1" by auto
          with False conf_s1 error_free_s1
          show ?thesis
            by auto
        next
          case True
          obtain A' where
            "(|prg=G,cls=accC,lcl=L|)),\<turnstile> dom (locals (store s1)) »In3 es» A'"
          proof -
            from eval_e wt_e da_e wf True
            have "nrm E ⊆ dom (locals (store s1))"
              by (cases rule: da_good_approxE') iprover
            with da_es show ?thesis
              by (rule da_weakenE)
          qed
          with conf_s1 wt_es
          obtain conf_s2: "s2::\<preceq>(G, L)" and
               error_free_s2: "error_free s2" and
               conf_vs: "normal s2 --> list_all2 (conf G (store s2)) vs esT"
            by (rule hyp_es [elim_format]) (simp add: error_free_s1)
          moreover
          from True eval_es conf_v
          have conf_v': "G,store s2\<turnstile>v::\<preceq>eT"
            apply clarify
            apply (rule conf_gext)
            apply (auto dest: eval_gext)
            done
          ultimately show ?thesis using T by simp
        qed
      qed
      then show ?thesis .
    qed

    text {*

    *} (* dummy text command to break paragraph for latex;
                  large paragraphs exhaust memory of debian pdflatex *)

    corollary eval_type_soundE [consumes 5]:
      assumes eval: "G\<turnstile>s0 \<midarrow>t\<succ>-> (v, s1)"
      and     conf: "s0::\<preceq>(G, L)"
      and       wt: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>t::T"
      and       da: "(|prg = G, cls = accC, lcl = L|)),\<turnstile> dom (locals (snd s0)) »t» A"
      and       wf: "wf_prog G"
      and     elim: "[|s1::\<preceq>(G, L); normal s1 ==> G,L,snd s1\<turnstile>t\<succ>v::\<preceq>T;
                      error_free s0 = error_free s1|] ==> P"
      shows "P"
    using eval wt da wf conf
    by (rule eval_type_sound [elim_format]) (iprover intro: elim)

    corollary eval_ts:
     "[|G\<turnstile>s \<midarrow>e-\<succ>v -> s'; wf_prog G; s::\<preceq>(G,L); (|prg=G,cls=C,lcl=L|)),\<turnstile>e::-T;
       (|prg=G,cls=C,lcl=L|)),\<turnstile>dom (locals (store s))»In1l e»A|]
    ==>  s'::\<preceq>(G,L) ∧ (normal s' --> G,store s'\<turnstile>v::\<preceq>T) ∧
         (error_free s = error_free s')"
    apply (drule (4) eval_type_sound)
    apply clarsimp
    done

    corollary evals_ts:
    "[|G\<turnstile>s \<midarrow>es\<doteq>\<succ>vs-> s'; wf_prog G; s::\<preceq>(G,L); (|prg=G,cls=C,lcl=L|)),\<turnstile>es::\<doteq>Ts;
      (|prg=G,cls=C,lcl=L|)),\<turnstile>dom (locals (store s))»In3 es»A|]
    ==>  s'::\<preceq>(G,L) ∧ (normal s' --> list_all2 (conf G (store s')) vs Ts) ∧
         (error_free s = error_free s')"
    apply (drule (4) eval_type_sound)
    apply clarsimp
    done

    corollary evar_ts:
    "[|G\<turnstile>s \<midarrow>v=\<succ>vf-> s'; wf_prog G; s::\<preceq>(G,L); (|prg=G,cls=C,lcl=L|)),\<turnstile>v::=T;
     (|prg=G,cls=C,lcl=L|)),\<turnstile>dom (locals (store s))»In2 v»A|] ==>
      s'::\<preceq>(G,L) ∧ (normal s' --> G,L,(store s')\<turnstile>In2 v\<succ>In2 vf::\<preceq>Inl T) ∧
      (error_free s = error_free s')"
    apply (drule (4) eval_type_sound)
    apply clarsimp
    done

    theorem exec_ts:
    "[|G\<turnstile>s \<midarrow>c-> s'; wf_prog G; s::\<preceq>(G,L); (|prg=G,cls=C,lcl=L|)),\<turnstile>c::\<surd>;
     (|prg=G,cls=C,lcl=L|)),\<turnstile>dom (locals (store s))»In1r c»A|]
     ==> s'::\<preceq>(G,L) ∧ (error_free s --> error_free s')"
    apply (drule (4) eval_type_sound)
    apply clarsimp
    done

    lemma wf_eval_Fin:
      assumes wf:    "wf_prog G"
        and   wt_c1: "(|prg = G, cls = C, lcl = L|)),\<turnstile>In1r c1::Inl (PrimT Void)"
        and   da_c1: "(|prg=G,cls=C,lcl=L|)),\<turnstile>dom (locals (store (Norm s0)))»In1r c1»A"
        and conf_s0: "Norm s0::\<preceq>(G, L)"
        and eval_c1: "G\<turnstile>Norm s0 \<midarrow>c1-> (x1,s1)"
        and eval_c2: "G\<turnstile>Norm s1 \<midarrow>c2-> s2"
        and      s3: "s3=abupd (abrupt_if (x1≠None) x1) s2"
      shows "G\<turnstile>Norm s0 \<midarrow>c1 Finally c2-> s3"
    proof -
      from eval_c1 wt_c1 da_c1 wf conf_s0
      have "error_free (x1,s1)"
        by (auto dest: eval_type_sound)
      with eval_c1 eval_c2 s3
      show ?thesis
        by - (rule eval.Fin, auto simp add: error_free_def)
    qed

    subsection "Ideas for the future"

    text {* In the type soundness proof and the correctness proof of
    definite assignment we perform induction on the evaluation relation with the
    further preconditions that the term is welltyped and definitely assigned. During
    the proofs we have to establish the welltypedness and definite assignment of
    the subterms to be able to apply the induction hypothesis. So large parts of
    both proofs are the same work in propagating welltypedness and definite
    assignment. So we can derive a new induction rule for induction on the
    evaluation of a wellformed term, were these propagations is already done, once
    and forever.
    Then we can do the proofs with this rule and can enjoy the time we have saved.
    Here is a first and incomplete sketch of such a rule.*}
    theorem wellformed_eval_induct [consumes 4, case_names Abrupt Skip Expr Lab
                                    Comp If]:
      assumes  eval: "G\<turnstile>s0 \<midarrow>t\<succ>-> (v,s1)"
       and      wt: "(|prg=G,cls=accC,lcl=L|)),\<turnstile>t::T"
       and      da: "(|prg=G,cls=accC,lcl=L|)),\<turnstile>dom (locals (store s0))»t»A"
       and      wf: "wf_prog G"
       and  abrupt: "!! s t abr L accC T A.
                      [|(|prg=G,cls=accC,lcl=L|)),\<turnstile>t::T;
                       (|prg=G,cls=accC,lcl=L|)),\<turnstile>dom (locals (store (Some abr,s)))»t»A
                      |] ==> P L accC (Some abr, s) t (arbitrary3 t) (Some abr, s)"
       and    skip: "!! s L accC. P L accC (Norm s) ⟨Skip⟩s ♦ (Norm s)"
       and    expr: "!! e s0 s1 v L accC eT E.
                     [|(|prg=G,cls=accC,lcl=L|)),\<turnstile>e::-eT;
                      (|prg=G,cls=accC,lcl=L|)),
                         \<turnstile>dom (locals (store ((Norm s0)::state)))»⟨e⟩e»E;
                      P L accC (Norm s0) ⟨e⟩e ⌊v⌋e s1|]
                     ==>  P L accC (Norm s0) ⟨Expr e⟩s ♦ s1"
       and     lab: "!! c l s0 s1 L accC C.
                     [|(|prg=G,cls=accC,lcl=L|)),\<turnstile>c::\<surd>;
                      (|prg=G,cls=accC, lcl=L|)),
                         \<turnstile>dom (locals (store ((Norm s0)::state)))»⟨c⟩s»C;
                      P L accC (Norm s0) ⟨c⟩s ♦ s1|]
                      ==> P L accC (Norm s0) ⟨l• c⟩s ♦ (abupd (absorb l) s1)"
       and    comp: "!! c1 c2 s0 s1 s2 L accC C1.
                     [|G\<turnstile>Norm s0 \<midarrow>c1 -> s1;G\<turnstile>s1 \<midarrow>c2 -> s2;
                      (|prg=G,cls=accC,lcl=L|)),\<turnstile>c1::\<surd>;
                      (|prg=G,cls=accC,lcl=L|)),\<turnstile>c2::\<surd>;
                      (|prg=G,cls=accC,lcl=L|)),\<turnstile>
                         dom (locals (store ((Norm s0)::state))) »⟨c1⟩s» C1;
                      P L accC (Norm s0) ⟨c1⟩s ♦ s1;
                      !! Q. [|normal s1;
                             !! C2.[|(|prg=G,cls=accC,lcl=L|)),
                                      \<turnstile>dom (locals (store s1)) »⟨c2⟩s» C2;
                                   P L accC s1 ⟨c2⟩s ♦ s2|] ==> Q
                            |] ==> Q
                      |]==> P L accC (Norm s0) ⟨c1;; c2⟩s ♦ s2"
        and    if: "!! b c1 c2 e s0 s1 s2 L accC E.
                    [|G\<turnstile>Norm s0 \<midarrow>e-\<succ>b-> s1;
                     G\<turnstile>s1 \<midarrow>(if the_Bool b then c1 else c2)-> s2;
                     (|prg=G,cls=accC,lcl=L|)),\<turnstile>e::-PrimT Boolean;
                     (|prg=G, cls=accC, lcl=L|)),\<turnstile>(if the_Bool b then c1 else c2)::\<surd>;
                     (|prg=G,cls=accC,lcl=L|)),\<turnstile>
                         dom (locals (store ((Norm s0)::state))) »⟨e⟩e» E;
                     P L accC (Norm s0) ⟨e⟩e ⌊b⌋e s1;
                     !! Q. [|normal s1;
                            !! C. [|(|prg=G,cls=accC,lcl=L|)),\<turnstile> (dom (locals (store s1)))
                                       »⟨if the_Bool b then c1 else c2⟩s» C;
                                  P L accC s1 ⟨if the_Bool b then c1 else c2⟩s ♦ s2
                                  |] ==> Q
                           |] ==> Q
                    |] ==> P L accC (Norm s0) ⟨If(e) c1 Else c2⟩s ♦ s2"
       shows "P L accC s0 t v s1"
    proof -
      note inj_term_simps [simp]
      from eval
      show "!! L accC T A. [|(|prg=G,cls=accC,lcl=L|)),\<turnstile>t::T;
                           (|prg=G,cls=accC,lcl=L|)),\<turnstile>dom (locals (store s0))»t»A|]
            ==> P L accC s0 t v s1" (is "PROP ?Hyp s0 t v s1")
      proof (induct)
        case Abrupt with abrupt show ?case .
      next
        case Skip from skip show ?case by simp
      next
        case (Expr e s0 s1 v L accC T A)
        from Expr.prems obtain eT where
          "(|prg = G, cls = accC, lcl = L|)),\<turnstile>e::-eT"
          by (elim wt_elim_cases)
        moreover
        from Expr.prems obtain E where
          "(|prg=G,cls=accC, lcl=L|)),\<turnstile>dom (locals (store ((Norm s0)::state)))»⟨e⟩e»E"
          by (elim da_elim_cases) simp
        moreover from calculation
        have "P L accC (Norm s0) ⟨e⟩e ⌊v⌋e s1"
          by (rule Expr.hyps)
        ultimately show ?case
          by (rule expr)
      next
        case (Lab c l s0 s1 L accC T A)
        from Lab.prems
        have "(|prg = G, cls = accC, lcl = L|)),\<turnstile>c::\<surd>"
          by (elim wt_elim_cases)
        moreover
        from Lab.prems obtain C where
          "(|prg=G,cls=accC, lcl=L|)),\<turnstile>dom (locals (store ((Norm s0)::state)))»⟨c⟩s»C"
          by (elim da_elim_cases) simp
        moreover from calculation
        have "P L accC (Norm s0) ⟨c⟩s ♦ s1"
          by (rule  Lab.hyps)
        ultimately show ?case
          by (rule lab)
      next
        case (Comp c1 c2 s0 s1 s2 L accC T A)
        have eval_c1: "G\<turnstile>Norm s0 \<midarrow>c1-> s1" .
        have eval_c2: "G\<turnstile>s1 \<midarrow>c2-> s2" .
        from Comp.prems obtain
          wt_c1: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>c1::\<surd>" and
          wt_c2: "(|prg = G, cls = accC, lcl = L|)),\<turnstile>c2::\<surd>"
          by (elim wt_elim_cases)
        from Comp.prems
        obtain C1 C2
          where da_c1: "(|prg=G, cls=accC, lcl=L|)),\<turnstile>
                          dom (locals (store ((Norm s0)::state))) »⟨c1⟩s» C1" and
                da_c2: "(|prg=G, cls=accC, lcl=L|)),\<turnstile>  nrm C1 »⟨c2⟩s» C2"
          by (elim da_elim_cases) simp
        from wt_c1 da_c1
        have P_c1: "P L accC (Norm s0) ⟨c1⟩s ♦ s1"
          by (rule Comp.hyps)
        {
          fix Q
          assume normal_s1: "normal s1"
          assume elim: "!! C2'.
                        [|(|prg=G,cls=accC,lcl=L|)),\<turnstile>dom (locals (store s1))»⟨c2⟩s»C2';
                           P L accC s1 ⟨c2⟩s ♦ s2|] ==> Q"
          have Q
          proof -
            obtain C2' where
              da: "(|prg=G, cls=accC, lcl=L|)),\<turnstile> dom (locals (store s1)) »⟨c2⟩s» C2'"
            proof -
              from eval_c1 wt_c1 da_c1 wf normal_s1
              have "nrm C1 ⊆ dom (locals (store s1))"
                by (cases rule: da_good_approxE') iprover
              with da_c2 show ?thesis
                by (rule da_weakenE)
            qed
            with wt_c2 have "P L accC s1 ⟨c2⟩s ♦ s2"
              by (rule Comp.hyps)
            with da show ?thesis
              using elim by iprover
          qed
        }
        with eval_c1 eval_c2 wt_c1 wt_c2 da_c1 P_c1
        show ?case
          by (rule comp) iprover+
      next
        case (If b c1 c2 e s0 s1 s2 L accC T A)
        have eval_e: "G\<turnstile>Norm s0 \<midarrow>e-\<succ>b-> s1" .
        have eval_then_else: "G\<turnstile>s1 \<midarrow>(if the_Bool b then c1 else c2)-> s2" .
        from If.prems
        obtain
                  wt_e: "(|prg=G, cls=accC, lcl=L|)),\<turnstile>e::-PrimT Boolean" and
          wt_then_else: "(|prg=G, cls=accC, lcl=L|)),\<turnstile>(if the_Bool b then c1 else c2)::\<surd>"
          by (elim wt_elim_cases) (auto split add: split_if)
        from If.prems obtain E C where
          da_e: "(|prg=G,cls=accC,lcl=L|)),\<turnstile> dom (locals (store ((Norm s0)::state)))
                                           »⟨e⟩e» E" and
          da_then_else:
          "(|prg=G,cls=accC,lcl=L|)),\<turnstile>
             (dom (locals (store ((Norm s0)::state))) ∪ assigns_if (the_Bool b) e)
              »⟨if the_Bool b then c1 else c2⟩s» C"
          by (elim da_elim_cases) (cases "the_Bool b",auto)
        from wt_e da_e
        have P_e: "P L accC (Norm s0) ⟨e⟩e ⌊b⌋e s1"
          by (rule If.hyps)
        {
          fix Q
          assume normal_s1: "normal s1"
          assume elim: "!! C. [|(|prg=G,cls=accC,lcl=L|)),\<turnstile> (dom (locals (store s1)))
                                       »⟨if the_Bool b then c1 else c2⟩s» C;
                                  P L accC s1 ⟨if the_Bool b then c1 else c2⟩s ♦ s2
                                  |] ==> Q"
          have Q
          proof -
            obtain C' where
              da: "(|prg=G,cls=accC,lcl=L|)),\<turnstile>
                    (dom (locals (store s1)))»⟨if the_Bool b then c1 else c2⟩s » C'"
            proof -
              from eval_e have
                "dom (locals (store ((Norm s0)::state))) ⊆ dom (locals (store s1))"
                by (rule dom_locals_eval_mono_elim)
              moreover
              from eval_e normal_s1 wt_e
              have "assigns_if (the_Bool b) e ⊆ dom (locals (store s1))"
                by (rule assigns_if_good_approx')
              ultimately
              have "dom (locals (store ((Norm s0)::state)))
                ∪ assigns_if (the_Bool b) e ⊆ dom (locals (store s1))"
                by (rule Un_least)
              with da_then_else show ?thesis
                by (rule da_weakenE)
            qed
            with wt_then_else
            have "P L accC s1 ⟨if the_Bool b then c1 else c2⟩s ♦ s2"
              by (rule If.hyps)
            with da show ?thesis using elim by iprover
          qed
        }
        with eval_e eval_then_else wt_e wt_then_else da_e P_e
        show ?case
          by (rule if) iprover+
      next
        oops

    end

## error free

lemma error_free_halloc:

      [| G|-s0.0 -halloc oi>a-> s1.0; error_free s0.0 |] ==> error_free s1.0

lemma error_free_sxalloc:

      [| G|-s0.0 -sxalloc-> s1.0; error_free s0.0 |] ==> error_free s1.0

lemma error_free_check_field_access_eq:

      error_free (check_field_access G accC statDeclC fn stat a s)
      ==> check_field_access G accC statDeclC fn stat a s = s

lemma error_free_check_method_access_eq:

      error_free (check_method_access G accC statT mode sig a' s)
      ==> check_method_access G accC statT mode sig a' s = s

lemma error_free_FVar_lemma:

      error_free s ==> error_free (abupd (if stat then id else np a) s)

lemma error_free_init_lvars:

      error_free s ==> error_free (init_lvars G C sig mode a pvs s)

lemma error_free_LVar_lemma:

      error_free s ==> error_free (assign (%v. supd lupd(vn\<mapsto>v)) w s)

lemma error_free_throw:

      error_free s ==> error_free (abupd (throw x) s)

## result conformance

lemma rconf_In1:

      G,L,s\<turnstile>In1 ec\<succ>In1 v::\<preceq>Inl T =
      G,s\<turnstile>v::\<preceq>T

lemma rconf_In2_no_LVar:

      ∀n. va ≠ LVar n
      ==> G,L,s\<turnstile>In2 va\<succ>In2 vf::\<preceq>Inl T =
          (G,s\<turnstile>fst vf::\<preceq>T ∧ s≤|snd vf\<preceq>T::\<preceq>(G, L))

lemma rconf_In2_LVar:

      va = LVar n
      ==> G,L,s\<turnstile>In2 va\<succ>In2 vf::\<preceq>Inl T =
          (fst vf = the (locals s n) ∧
           (locals s n ≠ None --> G,s\<turnstile>fst vf::\<preceq>T) ∧
           s≤|snd vf\<preceq>T::\<preceq>(G, L))

lemma rconf_In3:

      G,L,s\<turnstile>In3 es\<succ>In3 vs::\<preceq>Inr Ts =
      list_all2 (conf G s) vs Ts

## fits and conf

lemma conf_fits:

      G,s\<turnstile>v::\<preceq>T ==> G,s\<turnstile>v fits T

lemma fits_conf:

      [| G,s\<turnstile>v::\<preceq>T; G|-T<=:? T'; G,s\<turnstile>v fits T';
         ws_prog G |]
      ==> G,s\<turnstile>v::\<preceq>T'

lemma fits_Array:

      [| G,s\<turnstile>v::\<preceq>T; G|-T'.[]<=:T.[]; G,s\<turnstile>v fits T';
         ws_prog G |]
      ==> G,s\<turnstile>v::\<preceq>T'

## gext

lemma halloc_gext:

      G|-s1.0 -halloc oi>a-> s2.0 ==> snd s1.0≤|snd s2.0

lemma sxalloc_gext:

      G|-s1.0 -sxalloc-> s2.0 ==> snd s1.0≤|snd s2.0

lemma eval_gext_lemma:

      G|-s -t>-> (w, s')
      ==> snd s≤|snd s' ∧
          (case w of
           In2 vf => normal s --> (∀v x s. s≤|snd (assign (snd vf) v (x, s)))
           | _ => True)

lemma evar_gext_f:

      G|-Norm s1.0 -e=>vf-> s2.0 ==> s≤|snd (assign (snd vf) v (x, s))

lemmas eval_gext:

      G1|-s1 -t1>-> (w1, s'1) ==> snd s1≤|snd s'1

lemmas eval_gext:

      G1|-s1 -t1>-> (w1, s'1) ==> snd s1≤|snd s'1

lemma eval_gext':

      G|-(x1.0, s1.0) -t>-> (w, x2.0, s2.0) ==> s1.0≤|s2.0

lemma init_yields_initd:

      G|-Norm s1.0 -Init C-> s2.0 ==> initd C s2.0

## Lemmas

lemma obj_ty_obj_class1:

      [| wf_prog G; is_type G (obj_ty obj) |] ==> is_class G (obj_class obj)

lemma oconf_init_obj:

      [| wf_prog G;
         case r of Inl a => is_type G (obj_ty obj) | Inr C => is_class G C |]
      ==> G,s\<turnstile>obj
          (| values := init_vals (var_tys G (obj.tag obj) r) |)::\<preceq>\<surd>r

lemma conforms_newG:

      [| globs s oref = None; (x, s)::\<preceq>(G, L); wf_prog G;
         case oref of Inl a => is_type G (obj_ty (| obj.tag = oi, values = vs |))
         | Inr C => is_class G C |]
      ==> (x, init_obj G oi oref s)::\<preceq>(G, L)

lemma conforms_init_class_obj:

      [| (x, s)::\<preceq>(G, L); wf_prog G; class G C = Some y;
         ¬ inited C (globs s) |]
      ==> (x, (init_class_obj G C) s)::\<preceq>(G, L)

lemma fst_init_lvars:

      fst (init_lvars G C sig (invmode m e) a' pvs (x, s)) =
      (if is_static m then x else (np a') x)

lemma halloc_conforms:

      [| G|-s1.0 -halloc oi>a-> s2.0; wf_prog G; s1.0::\<preceq>(G, L);
         is_type G (obj_ty (| obj.tag = oi, values = fs |)) |]
      ==> s2.0::\<preceq>(G, L)

lemma halloc_type_sound:

      [| G|-s1.0 -halloc oi>a-> (x, s); wf_prog G; s1.0::\<preceq>(G, L);
         T = obj_ty (| obj.tag = oi, values = fs |); is_type G T |]
      ==> (x, s)::\<preceq>(G, L) ∧ (x = None --> G,s\<turnstile>Addr a::\<preceq>T)

lemma sxalloc_type_sound:

      [| G|-s1.0 -sxalloc-> s2.0; wf_prog G |]
      ==> case fst s1.0 of None => s2.0 = s1.0
          | Some abr =>
              case abr of
              Xcpt x =>
                ∃a. fst s2.0 = Some (Xcpt (Loc a)) ∧
                    (∀L. s1.0::\<preceq>(G, L) --> s2.0::\<preceq>(G, L))
              | _ => s2.0 = s1.0

lemma wt_init_comp_ty:

      is_acc_type G (pid C) T ==> (| prg = G, cls = C, lcl = L |)|-init_comp_ty T:<>

lemma DynT_propI:

      [| (x, s)::\<preceq>(G, L); G,s\<turnstile>a'::\<preceq>RefT statT; wf_prog G;
         mode = IntVir --> a' ≠ Null |]
      ==> G\<turnstile>mode->invocation_class mode s a' statT\<preceq>statT

lemma invocation_methd:

      [| wf_prog G; statT ≠ NullT; ∀statC. statT = ClassT statC --> is_class G statC;
         ∀I. statT = IfaceT I --> is_iface G I ∧ mode ≠ SuperM;
         ∀T. statT = ArrayT T --> mode ≠ SuperM;
         G\<turnstile>mode->invocation_class mode s a' statT\<preceq>statT;
         dynlookup G statT (invocation_class mode s a' statT) sig = Some m |]
      ==> methd G (invocation_declclass G mode s a' statT sig) sig = Some m

lemma DynT_mheadsD:

      [| G\<turnstile>invmode sm e->invC\<preceq>statT; wf_prog G;
         (| prg = G, cls = C, lcl = L |)|-e:-RefT statT;
         (statDeclT, sm) ∈ mheads G C statT sig;
         invC = invocation_class (invmode sm e) s a' statT;
         declC = invocation_declclass G (invmode sm e) s a' statT sig |]
      ==> ∃dm. methd G declC sig = Some dm ∧
               dynlookup G statT invC sig = Some dm ∧
               G|-resTy (mthd dm)<=:resTy sm ∧
               wf_mdecl G declC (sig, mthd dm) ∧
               declC = declclass dm ∧
               is_static dm = is_static sm ∧
               is_class G invC ∧
               is_class G declC ∧
               G|-invC<=:C declC ∧
               (if invmode sm e = IntVir
                then ∀statC. statT = ClassT statC --> G|-invC<=:C statC
                else ((∃statC. statT = ClassT statC ∧ G|-statC<=:C declC) ∨
                      (∀statC. statT ≠ ClassT statC ∧ declC = Object)) ∧
                     statDeclT = ClassT (declclass dm))

corollary DynT_mheadsE:

      [| G\<turnstile>mode->invC\<preceq>statT; wf_prog G;
         (| prg = G, cls = C, lcl = L |)|-e:-RefT statT;
         (statDeclT, sm) ∈ mheads G C statT sig; mode = invmode sm e;
         invC = invocation_class mode s a' statT;
         declC = invocation_declclass G mode s a' statT sig;
         !!dm. [| methd G declC sig = Some dm; dynlookup G statT invC sig = Some dm;
                  G|-resTy (mthd dm)<=:resTy sm; wf_mdecl G declC (sig, mthd dm);
                  declC = declclass dm; is_static dm = is_static sm; is_class G invC;
                  is_class G declC; G|-invC<=:C declC;
                  if invmode sm e = IntVir
                  then ∀statC. statT = ClassT statC --> G|-invC<=:C statC
                  else ((∃statC. statT = ClassT statC ∧ G|-statC<=:C declC) ∨
                        (∀statC. statT ≠ ClassT statC ∧ declC = Object)) ∧
                       statDeclT = ClassT (declclass dm) |]
               ==> P |]
      ==> P

lemma DynT_conf:

      [| G|-invocation_class mode s a' statT<=:C declC; wf_prog G; isrtype G statT;
         G,s\<turnstile>a'::\<preceq>RefT statT; mode = IntVir --> a' ≠ Null;
         mode ≠ IntVir -->
         (∃statC. statT = ClassT statC ∧ G|-statC<=:C declC) ∨
         (∀statC. statT ≠ ClassT statC ∧ declC = Object) |]
      ==> G,s\<turnstile>a'::\<preceq>Class declC

lemma Ass_lemma:

      [| G|-Norm s0.0 -var=>(w, f)-> Norm s1.0; G|-Norm s1.0 -e->v-> Norm s2.0;
         G,s2.0\<turnstile>v::\<preceq>eT;
         s1.0≤|s2.0 --> assign f v (Norm s2.0)::\<preceq>(G, L) |]
      ==> assign f v (Norm s2.0)::\<preceq>(G, L) ∧
          (normal (assign f v (Norm s2.0)) -->
           G,snd (assign f v (Norm s2.0))\<turnstile>v::\<preceq>eT)

lemma Throw_lemma:

      [| G|-tn<=:C SXcpt Throwable; wf_prog G; (x1.0, s1.0)::\<preceq>(G, L);
         x1.0 = None --> G,s1.0\<turnstile>a'::\<preceq>Class tn |]
      ==> (throw a' x1.0, s1.0)::\<preceq>(G, L)

lemma Try_lemma:

      [| G|-obj_ty (the (globs s1' (Inl a)))<=:Class tn;
         (Some (Xcpt (Loc a)), s1')::\<preceq>(G, L); wf_prog G |]
      ==> Norm (lupd(vn\<mapsto>Addr a) s1')::\<preceq>(G, L(vn |-> Class tn))

lemma Fin_lemma:

      [| G|-Norm s1.0 -c2.0-> (x2.0, s2.0); wf_prog G;
         (Some a, s1.0)::\<preceq>(G, L); (x2.0, s2.0)::\<preceq>(G, L);
         dom (locals s1.0) ⊆ dom (locals s2.0) |]
      ==> (abrupt_if True (Some a) x2.0, s2.0)::\<preceq>(G, L)

lemma FVar_lemma1:

      [| table_of (DeclConcepts.fields G statC) (fn, statDeclC) = Some f;
         x2.0 = None --> G,s2.0\<turnstile>a::\<preceq>Class statC; wf_prog G;
         G|-statC<=:C statDeclC; statDeclC ≠ Object; class G statDeclC = Some y;
         (x2.0, s2.0)::\<preceq>(G, L); s1.0≤|s2.0; inited statDeclC (globs s1.0);
         (if static f then id else np a) x2.0 = None |]
      ==> ∃obj. globs s2.0 (if static f then Inr statDeclC else Inl (the_Addr a)) =
                Some obj ∧
                var_tys G (obj.tag obj)
                 (if static f then Inr statDeclC else Inl (the_Addr a))
                 (Inl (fn, statDeclC)) =
                Some (type f)

lemma FVar_lemma2:

      error_free state
      ==> error_free
           (assign
             (%v. supd (upd_gobj
                         (if static field then Inr statDeclC else Inl (the_Addr a))
                         (Inl (fn, statDeclC)) v))
             w state)

lemma FVar_lemma:

      [| ((v, f), Norm s2') = fvar statDeclC (static field) fn a (x2.0, s2.0);
         G|-statC<=:C statDeclC;
         table_of (DeclConcepts.fields G statC) (fn, statDeclC) = Some field;
         wf_prog G; x2.0 = None --> G,s2.0\<turnstile>a::\<preceq>Class statC;
         statDeclC ≠ Object; class G statDeclC = Some y;
         (x2.0, s2.0)::\<preceq>(G, L); s1.0≤|s2.0; inited statDeclC (globs s1.0) |]
      ==> G,s2'\<turnstile>v::\<preceq>type field ∧
          s2'≤|f\<preceq>type field::\<preceq>(G, L)

lemma AVar_lemma1:

      [| globs s (Inl a) = Some obj; obj.tag obj = Arr ty i; the_Intg i' in_bounds i;
         wf_prog G; G|-ty.[]<=:Tb.[]; Norm s::\<preceq>(G, L) |]
      ==> G,s\<turnstile>the (values obj (Inr (the_Intg i')))::\<preceq>Tb

lemma obj_split:

      ∃t vs. obj = (| obj.tag = t, values = vs |)

lemma AVar_lemma2:

      error_free state
      ==> error_free
           (assign
             (%v (x, s').
                 ((raise_if (¬ G,s'\<turnstile>v fits T) ArrStore) x,
                  upd_gobj (Inl a) (Inr (the_Intg i)) v s'))
             w state)

lemma AVar_lemma:

      [| wf_prog G; G|-(x1.0, s1.0) -e2.0->i-> (x2.0, s2.0);
         ((v, f), Norm s2') = avar G i a (x2.0, s2.0);
         x1.0 = None --> G,s1.0\<turnstile>a::\<preceq>Ta.[];
         (x2.0, s2.0)::\<preceq>(G, L); s1.0≤|s2.0 |]
      ==> G,s2'\<turnstile>v::\<preceq>Ta ∧ s2'≤|f\<preceq>Ta::\<preceq>(G, L)

## Call

lemma conforms_init_lvars_lemma:

      [| wf_prog G; wf_mhead G P sig mh; list_all2 (conf G s) pvs pTsa;
         G\<turnstile>pTsa[\<preceq>]parTs sig |]
      ==> G,s\<turnstile>[pars mh [|->] pvs][∼::\<preceq>]table_of lvars(pars mh [|->]
          parTs sig)

lemma lconf_map_lname:

      G,s\<turnstile>lname_case l1.0 l2.0[::\<preceq>]lname_case L1.0 L2.0 =
      (G,s\<turnstile>l1.0[::\<preceq>]L1.0 ∧
       G,s\<turnstile>(%x. l2.0)[::\<preceq>](%x. L2.0))

lemma wlconf_map_lname:

      G,s\<turnstile>lname_case l1.0 l2.0[∼::\<preceq>]lname_case L1.0 L2.0 =
      (G,s\<turnstile>l1.0[∼::\<preceq>]L1.0 ∧
       G,s\<turnstile>(%x. l2.0)[∼::\<preceq>](%x. L2.0))

lemma lconf_map_ename:

      G,s\<turnstile>ename_case l1.0 l2.0[::\<preceq>]ename_case L1.0 L2.0 =
      (G,s\<turnstile>l1.0[::\<preceq>]L1.0 ∧
       G,s\<turnstile>(%x. l2.0)[::\<preceq>](%x. L2.0))

lemma wlconf_map_ename:

      G,s\<turnstile>ename_case l1.0 l2.0[∼::\<preceq>]ename_case L1.0 L2.0 =
      (G,s\<turnstile>l1.0[∼::\<preceq>]L1.0 ∧
       G,s\<turnstile>(%x. l2.0)[∼::\<preceq>](%x. L2.0))

lemma defval_conf1:

      is_type G T ==> ? v:Some (default_val T): G,s\<turnstile>v::\<preceq>T

lemma np_no_jump:

      x ≠ Some (Jump j) ==> (np a') x ≠ Some (Jump j)

lemma conforms_init_lvars:

      [| wf_mhead G (pid declC) sig (mhead (mthd dm)); wf_prog G;
         list_all2 (conf G s) pvs pTsa; G\<turnstile>pTsa[\<preceq>]parTs sig;
         (x, s)::\<preceq>(G, L); methd G declC sig = Some dm; isrtype G statT;
         G|-invC<=:C declC; G,s\<turnstile>a'::\<preceq>RefT statT;
         invmode (mhd sm) e = IntVir --> a' ≠ Null;
         invmode (mhd sm) e ≠ IntVir -->
         (∃statC. statT = ClassT statC ∧ G|-statC<=:C declC) ∨
         (∀statC. statT ≠ ClassT statC ∧ declC = Object);
         invC = invocation_class (invmode (mhd sm) e) s a' statT;
         declC = invocation_declclass G (invmode (mhd sm) e) s a' statT sig;
         x ≠ Some (Jump Ret) |]
      ==> init_lvars G declC sig (invmode (mhd sm) e) a' pvs
           (x, s)::\<preceq>(G, lname_case
                                 (ename_case
                                   (table_of (lcls (mbody (mthd dm)))(pars (mthd dm)
                                    [|->] parTs sig))
                                   (Some (resTy (mthd dm))))
                                 (if is_static (mthd sm) then None
                                  else Some (Class declC)))

### accessibility

theorem dynamic_field_access_ok:

      [| wf_prog G; ¬ stat --> a ≠ Null; G,snd s\<turnstile>a::\<preceq>Class statC;
         s::\<preceq>(G, L); normal s;
         (| prg = G, cls = accC, lcl = L |)|-e:-Class statC;
         accfield G accC statC fn = Some f;
         if stat then dynC = declclass f else dynC = obj_class (lookup_obj (snd s) a);
         if stat then is_static f else ¬ is_static f |]
      ==> table_of (DeclConcepts.fields G dynC) (fn, declclass f) = Some (fld f) ∧
          G \<turnstile>Field fn f in dynC dyn_accessible_from accC

lemma error_free_field_access:

      [| accfield G accC statC fn = Some (statDeclC, f);
         (| prg = G, cls = accC, lcl = L |)|-e:-Class statC;
         G|-Norm s0.0 -Init statDeclC-> s1.0; G|-s1.0 -e->a-> s2.0;
         s2.0::\<preceq>(G, L);
         normal s2.0 ==> G,snd s2.0\<turnstile>a::\<preceq>Class statC;
         (v, s2') = fvar statDeclC (is_static f) fn a s2.0; wf_prog G |]
      ==> check_field_access G accC statDeclC fn (is_static f) a s2' = s2'

lemma call_access_ok:

      [| G\<turnstile>invmode statM e->invC\<preceq>statT; wf_prog G;
         (| prg = G, cls = C, lcl = L |)|-e:-RefT statT;
         (statDeclT, statM) ∈ mheads G accC statT sig;
         invC = invocation_class (invmode statM e) s a statT |]
      ==> ∃dynM. dynlookup G statT invC sig = Some dynM ∧
                 G \<turnstile>Methd sig dynM in invC dyn_accessible_from accC

lemma error_free_call_access:

      [| G|-s1.0 -args#>vs-> s2.0; (| prg = G, cls = accC, lcl = L |)|-e:-RefT statT;
         max_spec G accC statT (| name = mn, parTs = pTs |) =
         {((statDeclT, statM), pTs')};
         s2.0::\<preceq>(G, L);
         normal s1.0 ==> G,snd s1.0\<turnstile>a::\<preceq>RefT statT;
         normal s3.0 ==> G\<turnstile>invmode statM e->invC\<preceq>statT;
         s3.0 =
         init_lvars G invDeclC (| name = mn, parTs = pTs' |) (invmode statM e) a vs
          s2.0;
         invC = invocation_class (invmode statM e) (snd s2.0) a statT;
         invDeclC =
         invocation_declclass G (invmode statM e) (snd s2.0) a statT
          (| name = mn, parTs = pTs' |);
         wf_prog G |]
      ==> check_method_access G accC statT (invmode statM e)
           (| name = mn, parTs = pTs' |) a s3.0 =
          s3.0

lemma map_upds_eq_length_append_simp:

      length ps = length qs ==> tab(ps [|->] qs @ zs) = tab(ps [|->] qs)

lemma map_upds_upd_eq_length_simp:

      length ps = length qs
      ==> tab(ps [|->] qs, x |-> y) = tab(ps @ [x] [|->] qs @ [y])

lemma map_upd_cong:

      tab = tab' ==> tab(x |-> y) = tab'(x |-> y)

lemma map_upd_cong_ext:

      tab z = tab' z ==> (tab(x |-> y)) z = (tab'(x |-> y)) z

lemma map_upds_cong:

      tab = tab' ==> tab(xs [|->] ys) = tab'(xs [|->] ys)

lemma map_upds_cong_ext:

      tab z = tab' z ==> (tab(xs [|->] ys)) z = (tab'(xs [|->] ys)) z

lemma map_upd_override:

      (tab(x |-> y)) x = (tab'(x |-> y)) x

lemma map_upds_eq_length_suffix:

      length ps = length qs ==> tab(ps @ xs [|->] qs) = tab(ps [|->] qs, xs [|->] [])

lemma map_upds_upds_eq_length_prefix_simp:

      length ps = length qs
      ==> tab(ps [|->] qs, xs [|->] ys) = tab(ps @ xs [|->] qs @ ys)

lemma map_upd_cut_irrelevant:

      [| (tab(x |-> y)) vn = Some el; (tab'(x |-> y)) vn = None |]
      ==> tab vn = Some el

lemma map_upd_Some_expand:

      tab vn = Some z ==> ∃z. (tab(x |-> y)) vn = Some z

lemma map_upds_Some_expand:

      tab vn = Some z ==> ∃z. (tab(xs [|->] ys)) vn = Some z

lemma map_upd_Some_swap:

      (tab(r |-> w, u |-> v)) vn = Some z ==> ∃z. (tab(u |-> v, r |-> w)) vn = Some z

lemma map_upd_None_swap:

      (tab(r |-> w, u |-> v)) vn = None ==> (tab(u |-> v, r |-> w)) vn = None

lemma map_eq_upd_eq:

      tab vn = tab' vn ==> (tab(x |-> y)) vn = (tab'(x |-> y)) vn

lemma map_upd_in_expansion_map_swap:

      [| (tab(x |-> y)) vn = Some z; tab vn ≠ Some z |]
      ==> (tab'(x |-> y)) vn = Some z

lemma map_upds_in_expansion_map_swap:

      [| (tab(xs [|->] ys)) vn = Some z; tab vn ≠ Some z |]
      ==> (tab'(xs [|->] ys)) vn = Some z

lemma map_upds_Some_swap:

      (tab(r |-> w, u |-> v, xs [|->] ys)) vn = Some z
      ==> ∃z. (tab(u |-> v, r |-> w, xs [|->] ys)) vn = Some z

lemma map_upds_Some_insert:

      (tab(xs [|->] ys)) vn = Some z ==> ∃z. (tab(u |-> v, xs [|->] ys)) vn = Some z

lemma map_upds_None_cut:

      (tab(xs [|->] ys)) vn = None ==> tab vn = None

lemma map_upds_cut_irrelevant:

      [| (tab(xs [|->] ys)) vn = Some el; (tab'(xs [|->] ys)) vn = None |]
      ==> tab vn = Some el

lemma dom_vname_split:

      dom (lname_case (ename_case (tab(x |-> y, xs [|->] ys)) a) b) =
      dom (lname_case (ename_case (tab(x |-> y)) a) b) ∪
      dom (lname_case (ename_case (tab(xs [|->] ys)) a) b)

lemma dom_map_upd:

      dom (tab(x |-> y)) = dom tab ∪ {x}

lemma dom_map_upds:

      length xs = length ys ==> dom (tab(xs [|->] ys)) = dom tab ∪ set xs

lemma dom_ename_case_None_simp:

      dom (ename_case vname_tab None) = VNam ` dom vname_tab

lemma dom_ename_case_Some_simp:

      dom (ename_case vname_tab (Some a)) = VNam ` dom vname_tab ∪ {Res}

lemma dom_lname_case_None_simp:

      dom (lname_case ename_tab None) = EName ` dom ename_tab

lemma dom_lname_case_Some_simp:

      dom (lname_case ename_tab (Some a)) = EName ` dom ename_tab ∪ {This}

lemmas dom_lname_ename_case_simps:

      dom (ename_case vname_tab None) = VNam ` dom vname_tab

      dom (ename_case vname_tab (Some a)) = VNam ` dom vname_tab ∪ {Res}

      dom (lname_case ename_tab None) = EName ` dom ename_tab

      dom (lname_case ename_tab (Some a)) = EName ` dom ename_tab ∪ {This}

lemmas dom_lname_ename_case_simps:

      dom (ename_case vname_tab None) = VNam ` dom vname_tab

      dom (ename_case vname_tab (Some a)) = VNam ` dom vname_tab ∪ {Res}

      dom (lname_case ename_tab None) = EName ` dom ename_tab

      dom (lname_case ename_tab (Some a)) = EName ` dom ename_tab ∪ {This}

lemma image_comp:

      f ` g ` A = (f o g) ` A

lemma dom_locals_init_lvars:

      [| m = mthd (the (methd G C sig)); length (pars m) = length pvs |]
      ==> dom (locals (snd (init_lvars G C sig (invmode m e) a pvs s))) = parameters m

lemma da_e2_BinOp:

      [| (| prg = G, cls = accC,
            lcl = L |)\<turnstile> dom (locals
                                         (snd s0.0)) »In1l (BinOp binop e1.0 e2.0)» A;
         (| prg = G, cls = accC, lcl = L |)|-e1.0:-e1T;
         (| prg = G, cls = accC, lcl = L |)|-e2.0:-e2T; wt_binop G binop e1T e2T;
         s0.0::\<preceq>(G, L); normal s1.0; G|-s0.0 -e1.0->v1.0-> s1.0;
         G,snd s1.0\<turnstile>v1.0::\<preceq>e1T; wf_prog G |]
      ==> ∃E2. (| prg = G, cls = accC,
                  lcl = L |)\<turnstile> dom (locals
       (snd s1.0)) »(if need_second_arg binop v1.0 then In1l e2.0 else In1r Skip)» E2

## main proof of type safety

lemma eval_type_sound:

      [| G|-s0.0 -t>-> (v, s1.0); (| prg = G, cls = accC, lcl = L |)|-t::T;
         (| prg = G, cls = accC, lcl = L |)\<turnstile> dom (locals (snd s0.0)) »t» A;
         wf_prog G; s0.0::\<preceq>(G, L) |]
      ==> s1.0::\<preceq>(G, L) ∧
          (normal s1.0 --> G,L,snd s1.0\<turnstile>t\<succ>v::\<preceq>T) ∧
          error_free s0.0 = error_free s1.0

corollary eval_type_soundE:

      [| G|-s0.0 -t>-> (v, s1.0); s0.0::\<preceq>(G, L);
         (| prg = G, cls = accC, lcl = L |)|-t::T;
         (| prg = G, cls = accC, lcl = L |)\<turnstile> dom (locals (snd s0.0)) »t» A;
         wf_prog G;
         [| s1.0::\<preceq>(G, L);
            normal s1.0 ==> G,L,snd s1.0\<turnstile>t\<succ>v::\<preceq>T;
            error_free s0.0 = error_free s1.0 |]
         ==> P |]
      ==> P

corollary eval_ts:

      [| G|-s -e->v-> s'; wf_prog G; s::\<preceq>(G, L);
         (| prg = G, cls = C, lcl = L |)|-e:-T;
         (| prg = G, cls = C,
            lcl = L |)\<turnstile> dom (locals (snd s)) »In1l e» A |]
      ==> s'::\<preceq>(G, L) ∧
          (normal s' --> G,snd s'\<turnstile>v::\<preceq>T) ∧
          error_free s = error_free s'

corollary evals_ts:

      [| G|-s -es#>vs-> s'; wf_prog G; s::\<preceq>(G, L);
         (| prg = G, cls = C, lcl = L |)|-es:#Ts;
         (| prg = G, cls = C,
            lcl = L |)\<turnstile> dom (locals (snd s)) »In3 es» A |]
      ==> s'::\<preceq>(G, L) ∧
          (normal s' --> list_all2 (conf G (snd s')) vs Ts) ∧
          error_free s = error_free s'

corollary evar_ts:

      [| G|-s -v=>vf-> s'; wf_prog G; s::\<preceq>(G, L);
         (| prg = G, cls = C, lcl = L |)|-v:=T;
         (| prg = G, cls = C, lcl = L |)\<turnstile> dom (locals (snd s)) »In2 v» A |]
      ==> s'::\<preceq>(G, L) ∧
          (normal s' --> G,L,snd s'\<turnstile>In2 v\<succ>In2 vf::\<preceq>Inl T) ∧
          error_free s = error_free s'

theorem exec_ts:

      [| G|-s -c-> s'; wf_prog G; s::\<preceq>(G, L);
         (| prg = G, cls = C, lcl = L |)|-c:<>;
         (| prg = G, cls = C,
            lcl = L |)\<turnstile> dom (locals (snd s)) »In1r c» A |]
      ==> s'::\<preceq>(G, L) ∧ (error_free s --> error_free s')

lemma wf_eval_Fin:

      [| wf_prog G; (| prg = G, cls = C, lcl = L |)|-c1.0:<>;
         (| prg = G, cls = C,
            lcl = L |)\<turnstile> dom (locals (snd (Norm s0.0))) »In1r c1.0» A;
         Norm s0.0::\<preceq>(G, L); G|-Norm s0.0 -c1.0-> (x1.0, s1.0);
         G|-Norm s1.0 -c2.0-> s2.0;
         s3.0 = abupd (abrupt_if (x1.0 ≠ None) x1.0) s2.0 |]
      ==> G|-Norm s0.0 -c1.0 Finally c2.0-> s3.0

### Ideas for the future