section {*L\_ATS\_Simulation\_Configuration\_WeakLRReach*}
theory
  L_ATS_Simulation_Configuration_WeakLRReach

imports
  L_ATS_Simulation_Configuration_Weak

begin

locale ATS_Simulation_Configuration_WeakReach =
  ATS_Simulation_Configuration_Weak
  "TSstructure1 :: 'TSstructure1 \<Rightarrow> bool"
  "configurations1 :: 'TSstructure1 \<Rightarrow> 'conf1 set"
  "initial_configurations1 :: 'TSstructure1 \<Rightarrow> 'conf1 set"
  "step_labels1 :: 'TSstructure1 \<Rightarrow> 'label1 set"
  "step_relation1 :: 'TSstructure1 \<Rightarrow> 'conf1 \<Rightarrow> 'label1 \<Rightarrow> 'conf1 \<Rightarrow> bool"
  "effects1 :: 'TSstructure1 \<Rightarrow> 'event1 set"
  "marking_condition1 :: 'TSstructure1 \<Rightarrow> ('label1,'conf1)derivation \<Rightarrow> bool"
  "marked_effect1 :: 'TSstructure1 \<Rightarrow> ('label1,'conf1)derivation \<Rightarrow> 'event1 set"
  "unmarked_effect1 :: 'TSstructure1 \<Rightarrow> ('label1,'conf1)derivation \<Rightarrow> 'event1 set"
  "TSstructure2 :: 'TSstructure2 \<Rightarrow> bool"
  "configurations2 :: 'TSstructure2 \<Rightarrow> 'conf2 set"
  "initial_configurations2 :: 'TSstructure2 \<Rightarrow> 'conf2 set"
  "step_labels2 :: 'TSstructure2 \<Rightarrow> 'label2 set"
  "step_relation2 :: 'TSstructure2 \<Rightarrow> 'conf2 \<Rightarrow> 'label2 \<Rightarrow> 'conf2 \<Rightarrow> bool"
  "effects2 :: 'TSstructure2 \<Rightarrow> 'event2 set"
  "marking_condition2 :: 'TSstructure2 \<Rightarrow> ('label2,'conf2)derivation \<Rightarrow> bool"
  "marked_effect2 :: 'TSstructure2 \<Rightarrow> ('label2,'conf2)derivation \<Rightarrow> 'event2 set"
  "unmarked_effect2 :: 'TSstructure2 \<Rightarrow> ('label2,'conf2)derivation \<Rightarrow> 'event2 set"
  "relation_configuration :: 'TSstructure1 \<Rightarrow> 'TSstructure2 \<Rightarrow> 'conf1 \<Rightarrow> 'conf2 \<Rightarrow> bool"
  "relation_initial_configuration :: 'TSstructure1 \<Rightarrow> 'TSstructure2 \<Rightarrow> 'conf1 \<Rightarrow> 'conf2 \<Rightarrow> bool"
  "relation_effect :: 'TSstructure1 \<Rightarrow> 'TSstructure2 \<Rightarrow> 'event1 \<Rightarrow> 'event2 \<Rightarrow> bool"
  "relation_TSstructure :: 'TSstructure1 \<Rightarrow> 'TSstructure2 \<Rightarrow> bool"
  "relation_initial_simulation :: 'TSstructure1 \<Rightarrow> 'TSstructure2 \<Rightarrow> 'conf1 \<Rightarrow> (nat \<Rightarrow> ('label2, 'conf2) derivation_configuration option) \<Rightarrow> bool"
  "relation_step_simulation :: 'TSstructure1 \<Rightarrow> 'TSstructure2 \<Rightarrow> 'conf1 \<Rightarrow> 'label1 \<Rightarrow> 'conf1 \<Rightarrow> 'conf2 \<Rightarrow> (nat \<Rightarrow> ('label2, 'conf2) derivation_configuration option) \<Rightarrow> bool"
  for
    TSstructure1 configurations1 initial_configurations1 step_labels1 step_relation1 effects1 marking_condition1 marked_effect1 unmarked_effect1 TSstructure2 configurations2 initial_configurations2 step_labels2 step_relation2 effects2 marking_condition2 marked_effect2 unmarked_effect2 relation_configuration relation_initial_configuration relation_effect relation_TSstructure relation_initial_simulation relation_step_simulation
    +

fixes relation_labelsLR :: "'TSstructure1 \<Rightarrow> 'TSstructure2 \<Rightarrow> 'label1 \<Rightarrow> 'label2 \<Rightarrow> bool"

assumes AX_relation_step_simulationReach: "
  relation_TSstructure G1 G2
  \<Longrightarrow> relation_configuration G1 G2 c1 c2
  \<Longrightarrow> e1 \<in> step_labels1 G1
  \<Longrightarrow> step_relation1 G1 c1 e1 c1'
  \<Longrightarrow> GR.derivation G2 d2
  \<Longrightarrow> GR.belongs G2 d2
  \<Longrightarrow> the(get_configuration(d2 0)) = c2
  \<Longrightarrow> relation_step_simulation G1 G2 c1 e1 c1' c2 d2
  \<Longrightarrow> maximum_of_domain d2 n
  \<Longrightarrow> relation_configuration G1 G2 c1' (the(get_configuration(d2 n)))
  \<Longrightarrow> (\<exists>k e2 c2.
        d2 k = Some (pair (Some e2) c2)
        \<and> relation_labelsLR G1 G2 e1 e2)
      \<or> (n=0
         \<and> (\<exists>d2' n2'.
             GR.derivation G2 d2'
             \<and> the(get_configuration(d2' 0)) = c2
             \<and> maximum_of_domain d2' n2'
             \<and> (\<exists>k e2 c2.
                 d2' k = Some (pair (Some e2) c2)
                 \<and> relation_labelsLR G1 G2 e1 e2)))"

context ATS_Simulation_Configuration_WeakReach begin

lemma ATS_Simulation_Configuration_WeakReach_simulation_derivation_exists_witness_EXTENDED_Reach: "
  relation_TSstructure G1 G2
  \<Longrightarrow> GL.derivation_initial G1 d1
  \<Longrightarrow> d1 x = Some (pair e1 c1)
  \<Longrightarrow> \<exists>d2 n2 f.
  GR.derivation_initial G2 d2
  \<and> maximum_of_domain d2 n2
  \<and> relation_initial_configuration G1 G2 (the (get_configuration (d1 0))) (the (get_configuration (d2 0)))
  \<and> relation_configuration G1 G2 c1 (the (get_configuration (d2 n2)))
  \<and> simulating_derivation G1 G2 d1 x d2 n2 f
  \<and> (\<forall>i\<le>x. \<forall>e1 c1. d1 i = Some (pair e1 c1) \<longrightarrow> (case e1 of None \<Rightarrow> True | Some e1' \<Rightarrow> \<exists>k d2'.
  GR.derivation G2 d2'
  \<and> the(get_configuration(d2' 0)) = the(get_configuration(d2 (f i)))
  \<and> (case ((get_label (derivation_append d2 d2' (f i) k))) of None \<Rightarrow> False | Some e2' \<Rightarrow> relation_labelsLR G1 G2 e1' e2')))"
  apply(induct x arbitrary: e1 c1)
   apply(rename_tac e1 c1)(*strict*)
   apply(clarsimp)
   apply(subgoal_tac "c1 \<in> initial_configurations1 G1")
    apply(rename_tac e1 c1)(*strict*)
    prefer 2
    apply(simp add: GL.derivation_initial_def)
   apply(rename_tac e1 c1)(*strict*)
   apply(subgoal_tac "\<exists>d2 n. GR.derivation_initial G2 d2 \<and> relation_initial_configuration G1 G2 c1 (the(get_configuration(d2 0))) \<and> relation_initial_simulation G1 G2 c1 d2 \<and> maximum_of_domain d2 n \<and> relation_configuration G1 G2 c1 (the(get_configuration(d2 n)))")
    apply(rename_tac e1 c1)(*strict*)
    prefer 2
    apply(rule AX_relation_initial_simulation)
     apply(rename_tac e1 c1)(*strict*)
     apply(force)
    apply(rename_tac e1 c1)(*strict*)
    apply(force)
   apply(rename_tac e1 c1)(*strict*)
   apply(clarsimp)
   apply(rename_tac e1 c1 d2 n)(*strict*)
   apply(rule_tac
      x="d2"
      in exI)
   apply(clarsimp)
   apply(rule_tac
      x="n"
      in exI)
   apply(clarsimp)
   apply(rule conjI)
    apply(rename_tac e1 c1 d2 n)(*strict*)
    apply(simp add: get_configuration_def)
   apply(rename_tac e1 c1 d2 n)(*strict*)
   apply(rule_tac
      x="\<lambda>x. n"
      in exI)
   apply(rule conjI)
    apply(rename_tac e1 c1 d2 n)(*strict*)
    apply(simp add: simulating_derivation_def)
    apply(rule conjI)
     apply(rename_tac e1 c1 d2 n)(*strict*)
     apply(simp add: simulating_derivation_I_def)
     apply(rule conjI)
      apply(rename_tac e1 c1 d2 n)(*strict*)
      apply(simp add: get_configuration_def)
      apply (metis GR.derivation_take_id_prime_prime GR.derivation_initial_is_derivation eq_imp_le)
     apply(rename_tac e1 c1 d2 n)(*strict*)
     apply(rule conjI)
      apply(rename_tac e1 c1 d2 n)(*strict*)
      apply(simp add: maximum_of_domain_def derivation_take_def get_configuration_def)
     apply(rename_tac e1 c1 d2 n)(*strict*)
     apply(simp add: maximum_of_domain_def)
    apply(rename_tac e1 c1 d2 n)(*strict*)
    apply(rule conjI)
     apply(rename_tac e1 c1 d2 n)(*strict*)
     apply(simp add: simulating_derivation_S_def)
    apply(rename_tac e1 c1 d2 n)(*strict*)
    apply(simp add: simulating_derivation_DEF_def)
    apply(rule conjI)
     apply(rename_tac e1 c1 d2 n)(*strict*)
     apply(simp add: maximum_of_domain_def)
    apply(rename_tac e1 c1 d2 n)(*strict*)
    apply(simp add: get_configuration_def)
   apply(rename_tac e1 c1 d2 n)(*strict*)
   apply(simp add: GL.derivation_initial_def)
  apply(rename_tac x e1 c1)(*strict*)
  apply(clarsimp)
  apply(subgoal_tac "\<exists>e1 e2 c1 c2. d1 x = Some (pair e1 c1) \<and> d1 (Suc x) = Some (pair (Some e2) c2) \<and> step_relation1 G1 c1 e2 c2")
   apply(rename_tac x e1 c1)(*strict*)
   prefer 2
   apply(rule_tac
      m="Suc x"
      in GL.step_detail_before_some_position)
     apply(rename_tac x e1 c1)(*strict*)
     apply(rule GL.derivation_initial_is_derivation)
     apply(force)
    apply(rename_tac x e1 c1)(*strict*)
    apply(simp add: maximum_of_domain_def)
   apply(rename_tac x e1 c1)(*strict*)
   apply(force)
  apply(rename_tac x e1 c1)(*strict*)
  apply(clarsimp)
  apply(rename_tac x c1 e1a e2 c1a)(*strict*)
  apply(erule_tac
      x="e1a"
      in meta_allE)
  apply(erule_tac
      x="c1a"
      in meta_allE)
  apply(clarsimp)
  apply(rename_tac x c1 e1a e2 c1a d2 n2 xa)(*strict*)
  apply(rename_tac f)
  apply(rename_tac x c1 e1a e2 c1a d2 n2 f)(*strict*)
  apply(subgoal_tac "\<exists>e c. d2 n2 = Some (pair e c)")
   apply(rename_tac x c1 e1a e2 c1a d2 n2 f)(*strict*)
   prefer 2
   apply(rule GR.some_position_has_details_before_max_dom)
     apply(rename_tac x c1 e1a e2 c1a d2 n2 f)(*strict*)
     apply(rule GR.derivation_initial_is_derivation)
     apply(force)
    apply(rename_tac x c1 e1a e2 c1a d2 n2 f)(*strict*)
    apply(force)
   apply(rename_tac x c1 e1a e2 c1a d2 n2 f)(*strict*)
   apply(force)
  apply(rename_tac x c1 e1a e2 c1a d2 n2 f)(*strict*)
  apply(clarsimp)
  apply(rename_tac x c1 e1a e2 c1a d2 n2 f e c)(*strict*)
  apply(subgoal_tac "\<exists>d2 n. GR.derivation G2 d2 \<and> GR.belongs G2 d2 \<and> the(get_configuration(d2 0)) = c \<and> relation_step_simulation G1 G2 c1a e2 c1 c d2 \<and> maximum_of_domain d2 n \<and> relation_configuration G1 G2 c1 (the(get_configuration(d2 n)))")
   apply(rename_tac x c1 e1a e2 c1a d2 n2 f e c)(*strict*)
   prefer 2
   apply(rule AX_relation_step_simulation)
      apply(rename_tac x c1 e1a e2 c1a d2 n2 f e c)(*strict*)
      apply(force)
     apply(rename_tac x c1 e1a e2 c1a d2 n2 f e c)(*strict*)
     apply(simp add: get_configuration_def)
    apply(rename_tac x c1 e1a e2 c1a d2 n2 f e c)(*strict*)
    apply (metis GL.belongs_step_labels GL.derivation_initial_belongs AX_TSstructure_relation_TSstructure1_belongs)
   apply(rename_tac x c1 e1a e2 c1a d2 n2 f e c)(*strict*)
   apply(force)
  apply(rename_tac x c1 e1a e2 c1a d2 n2 f e c)(*strict*)
  apply(clarsimp)
  apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n)(*strict*)
  apply(rule_tac
      x="derivation_append d2 d2a n2"
      in exI)
  apply(subgoal_tac "\<exists>c. d2a 0 = Some (pair None c)")
   apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n)(*strict*)
   apply(clarsimp)
   apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c)(*strict*)
   apply(rule context_conjI)
    apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c)(*strict*)
    apply(rule GR.derivation_append_preserves_derivation_initial)
      apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c)(*strict*)
      apply (metis AX_TSstructure_relation_TSstructure2_belongs)
     apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c)(*strict*)
     apply(force)
    apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c)(*strict*)
    apply(rule GR.derivation_append_preserves_derivation)
      apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c)(*strict*)
      apply (metis GR.derivation_initial_is_derivation)
     apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c)(*strict*)
     apply(force)
    apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c)(*strict*)
    apply(clarsimp)
    apply(simp add: get_configuration_def)
   apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c)(*strict*)
   apply(rule_tac
      x="n2+n"
      in exI)
   apply(rule context_conjI)
    apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c)(*strict*)
    apply (metis concat_has_max_dom)
   apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c)(*strict*)
   apply(rule context_conjI)
    apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c)(*strict*)
    apply(simp add: get_configuration_def derivation_append_def)
   apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c)(*strict*)
   apply(rule conjI)
    apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c)(*strict*)
    apply(simp add: get_configuration_def derivation_append_def)
    apply(clarsimp)
   apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c)(*strict*)
   apply(rule_tac
      x="\<lambda>z. if z<Suc x then f z else f x + n"
      in exI)
   apply(rule conjI)
    apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c)(*strict*)
    apply(simp add: simulating_derivation_def)
    apply(rule context_conjI)
     apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c)(*strict*)
     apply(clarsimp)
     apply(simp only: simulating_derivation_I_def)
     apply(erule exE)+
     apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c d2' na)(*strict*)
     apply(rule_tac
      x="d2'"
      in exI)
     apply(rule_tac
      x="na"
      in exI)
     apply(rule conjI)
      apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c d2' na)(*strict*)
      apply(force)
     apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c d2' na)(*strict*)
     apply(rule conjI)
      apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c d2' na)(*strict*)
      apply(force)
     apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c d2' na)(*strict*)
     apply(rule conjI)
      apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c d2' na)(*strict*)
      apply (metis (erased, hide_lams) GR.derivation_initial_is_derivation derivation_take_def derivation_take_derivation_append_ignore GR.derivation_take_id_prime GR.derivation_take_preserves_derivation_initial GR.maximum_of_domainUnique maximum_of_domain_def)
     apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c d2' na)(*strict*)
     apply(rule conjI)
      apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c d2' na)(*strict*)
      apply(force)
     apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c d2' na)(*strict*)
     apply (metis (erased, hide_lams) GR.derivation_append_derivation_take GR.derivation_initial_is_derivation derivation_take_def)
    apply(erule_tac
      x="x"
      in allE)
    apply(erule impE)
     apply(force)
    apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c)(*strict*)
    apply(rule propSym,rule context_conjI)
     apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c)(*strict*)
     apply(simp add: simulating_derivation_DEF_def)
     apply(clarsimp)
     apply(rename_tac x c1 e1a e2 c1a d2 f e d2a n c i)(*strict*)
     apply(rule conjI)
      apply(rename_tac x c1 e1a e2 c1a d2 f e d2a n c i)(*strict*)
      apply(clarsimp)
      apply(erule_tac
      x="i"
      in allE)
      apply(clarsimp)
      apply(rename_tac x c1 e1a e2 c1a d2 f e d2a n c i y)(*strict*)
      apply(subgoal_tac "f i \<le> f x")
       apply(rename_tac x c1 e1a e2 c1a d2 f e d2a n c i y)(*strict*)
       prefer 2
       apply(rule_tac
      d="d2"
      in GR.allPreMaxDomSome_prime)
         apply(rename_tac x c1 e1a e2 c1a d2 f e d2a n c i y)(*strict*)
         prefer 3
         apply(force)
        apply(rename_tac x c1 e1a e2 c1a d2 f e d2a n c i y)(*strict*)
        apply(rule GR.derivation_initial_is_derivation)
        apply(force)
       apply(rename_tac x c1 e1a e2 c1a d2 f e d2a n c i y)(*strict*)
       apply(force)
      apply(rename_tac x c1 e1a e2 c1a d2 f e d2a n c i y)(*strict*)
      apply(simp add: derivation_append_def)
     apply(rename_tac x c1 e1a e2 c1a d2 f e d2a n c i)(*strict*)
     apply(clarsimp)
     apply(rename_tac x c1 e1a e2 c1a d2 f e d2a n c)(*strict*)
     apply(erule disjE)
      apply(rename_tac x c1 e1a e2 c1a d2 f e d2a n c)(*strict*)
      apply(simp add: derivation_append_def maximum_of_domain_def)
     apply(rename_tac x c1 e1a e2 c1a d2 f e d2a n c)(*strict*)
     apply(subgoal_tac "get_configuration(derivation_append d2 d2a (f x) (f x + n)) = get_configuration(d2a n)")
      apply(rename_tac x c1 e1a e2 c1a d2 f e d2a n c)(*strict*)
      apply(simp add: get_configuration_def)
     apply(rename_tac x c1 e1a e2 c1a d2 f e d2a n c)(*strict*)
     apply(simp add: derivation_append_def)
     apply(clarsimp)
     apply(rename_tac x c1 e1a e2 c1a d2 f e d2a c)(*strict*)
     apply(simp add: get_configuration_def)
    apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c)(*strict*)
    apply(simp add: simulating_derivation_S_def)
    apply(erule conjE)+
    apply(rule allI)
    apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c i)(*strict*)
    apply(case_tac "i<x")
     apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c i)(*strict*)
     apply(rule conjI)
      apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c i)(*strict*)
      prefer 2
      apply(force)
     apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c i)(*strict*)
     apply(rule impI)
     apply(thin_tac "i<x")
     apply(erule_tac
      x="i"
      in allE)
     apply(erule impE)
      apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c i)(*strict*)
      apply(force)
     apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c i)(*strict*)
     apply(rule allI)+
     apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c i ei ci ei' ci')(*strict*)
     apply(rule impI)
     apply(erule_tac
      x="ei"
      in allE)
     apply(erule_tac
      x="ci"
      in allE)
     apply(erule_tac
      x="ei'"
      in allE)
     apply(erule_tac
      x="ci'"
      in allE)
     apply(erule impE)
      apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c i ei ci ei' ci')(*strict*)
      apply(force)
     apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c i ei ci ei' ci')(*strict*)
     apply(erule exE)
     apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c i ei ci ei' ci' d2')(*strict*)
     apply(rule_tac
      x="d2'"
      in exI)
     apply(subgoal_tac "f i \<le> n2")
      apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c i ei ci ei' ci' d2')(*strict*)
      prefer 2
      apply(simp add: simulating_derivation_DEF_def)
      apply(clarsimp)
      apply(rename_tac x c1 e1a e2 c1a d2 f e d2a n c i ei ci ei' ci' na)(*strict*)
      apply(erule_tac
      x="i"
      and P="\<lambda>i. i \<le> x \<longrightarrow> (\<exists>y. d2 (f i) = Some y) \<and> relation_configuration G1 G2 (the (get_configuration (d1 i))) (the (get_configuration (d2 (f i))))"
      in allE)
      apply(rename_tac x c1 e1a e2 c1a d2 f e d2a n c i ei ci ei' ci' na)(*strict*)
      apply(clarsimp)
      apply(rename_tac x c1 e1a e2 c1a d2 f e d2a n c i ei ci ei' ci' na y)(*strict*)
      apply(rule_tac
      d="d2"
      in GR.allPreMaxDomSome_prime)
        apply(rename_tac x c1 e1a e2 c1a d2 f e d2a n c i ei ci ei' ci' na y)(*strict*)
        prefer 3
        apply(force)
       apply(rename_tac x c1 e1a e2 c1a d2 f e d2a n c i ei ci ei' ci' na y)(*strict*)
       apply(rule GR.derivation_initial_is_derivation)
       apply(force)
      apply(rename_tac x c1 e1a e2 c1a d2 f e d2a n c i ei ci ei' ci' na y)(*strict*)
      apply(force)
     apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c i ei ci ei' ci' d2')(*strict*)
     apply(rule_tac
      t="derivation_append d2 d2a n2 (f i)"
      and s="d2 (f i)"
      in ssubst)
      apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c i ei ci ei' ci' d2')(*strict*)
      apply(simp add: derivation_append_def get_configuration_def)
     apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c i ei ci ei' ci' d2')(*strict*)
     apply(rule conjI)
      apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c i ei ci ei' ci' d2')(*strict*)
      apply(force)
     apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c i ei ci ei' ci' d2')(*strict*)
     apply(erule conjE)+
     apply(erule exE)+
     apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c i ei ci ei' ci' d2' na)(*strict*)
     apply(erule conjE)+
     apply(rule_tac
      x="na"
      in exI)
     apply(rule conjI)
      apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c i ei ci ei' ci' d2' na)(*strict*)
      apply(force)
     apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c i ei ci ei' ci' d2' na)(*strict*)
     apply(rule conjI)
      apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c i ei ci ei' ci' d2' na)(*strict*)
      apply(force)
     apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c i ei ci ei' ci' d2' na)(*strict*)
     apply(subgoal_tac "f i+na \<le> n2")
      apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c i ei ci ei' ci' d2' na)(*strict*)
      prefer 2
      apply(simp add: simulating_derivation_DEF_def)
      apply(clarsimp)
      apply(rename_tac x c1 e1a e2 c1a d2 f e d2a n c i ei ci ei' ci' na)(*strict*)
      apply(erule_tac
      x="Suc i"
      and P="\<lambda>i. i \<le> x \<longrightarrow> (\<exists>y. d2 (f i) = Some y) \<and> relation_configuration G1 G2 (the (get_configuration (d1 i))) (the (get_configuration (d2 (f i))))"
      in allE)
      apply(rename_tac x c1 e1a e2 c1a d2 f e d2a n c i ei ci ei' ci' na)(*strict*)
      apply(clarsimp)
      apply(rename_tac x c1 e1a e2 c1a d2 f e d2a n c i ei ci ei' ci' na y)(*strict*)
      apply(rule_tac
      d="d2"
      in GR.allPreMaxDomSome_prime)
        apply(rename_tac x c1 e1a e2 c1a d2 f e d2a n c i ei ci ei' ci' na y)(*strict*)
        prefer 3
        apply(force)
       apply(rename_tac x c1 e1a e2 c1a d2 f e d2a n c i ei ci ei' ci' na y)(*strict*)
       apply(rule GR.derivation_initial_is_derivation)
       apply(force)
      apply(rename_tac x c1 e1a e2 c1a d2 f e d2a n c i ei ci ei' ci' na y)(*strict*)
      apply(force)
     apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c i ei ci ei' ci' d2' na)(*strict*)
     apply(clarsimp)
     apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c i ei ci ei' ci' na)(*strict*)
     apply(rule ext)
     apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c i ei ci ei' ci' na xa)(*strict*)
     apply(simp add: derivation_take_def derivation_drop_def derivation_append_def)
    apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c i)(*strict*)
    apply(rule conjI)
     apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c i)(*strict*)
     apply(force)
    apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c i)(*strict*)
    apply(rule impI)
    apply(rule impI)
    apply(subgoal_tac "i=x")
     apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c i)(*strict*)
     prefer 2
     apply(force)
    apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c i)(*strict*)
    apply(thin_tac "\<not> i < x")
    apply(thin_tac "\<not> i < x")
    apply(thin_tac "i < Suc x")
    apply(rule allI)+
    apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c i ei ci ei' ci')(*strict*)
    apply(rule impI)
    apply(clarsimp)
    apply(rename_tac x d2 n2 f e d2a n c ei ci ei' ci')(*strict*)
    apply(subgoal_tac "f x=n2")
     apply(rename_tac x d2 n2 f e d2a n c ei ci ei' ci')(*strict*)
     prefer 2
     apply(simp add: simulating_derivation_DEF_def)
    apply(rename_tac x d2 n2 f e d2a n c ei ci ei' ci')(*strict*)
    apply(clarsimp)
    apply(rename_tac x d2 f e d2a n c ei ci ei' ci')(*strict*)
    apply(rule_tac
      t="(the (get_configuration (derivation_append d2 d2a (f x) (f x))))"
      and s="(the (get_configuration (Some (pair None c))))"
      in ssubst)
     apply(rename_tac x d2 f e d2a n c ei ci ei' ci')(*strict*)
     apply(simp add: get_configuration_def derivation_append_def)
    apply(rename_tac x d2 f e d2a n c ei ci ei' ci')(*strict*)
    apply(rule_tac
      t="derivation_take (derivation_drop (derivation_append d2 d2a (f x)) (f x)) n"
      and s="d2a"
      in ssubst)
     apply(rename_tac x d2 f e d2a n c ei ci ei' ci')(*strict*)
     apply(rule ext)
     apply(rename_tac x d2 f e d2a n c ei ci ei' ci' xa)(*strict*)
     apply(simp add: derivation_take_def derivation_drop_def derivation_append_def)
     apply(simp add: get_configuration_def)
     apply(clarsimp)
     apply (metis GR.allPreMaxDomSome_prime)
    apply(rename_tac x d2 f e d2a n c ei ci ei' ci')(*strict*)
    apply(rule conjI)
     apply(rename_tac x d2 f e d2a n c ei ci ei' ci')(*strict*)
     apply(force)
    apply(rename_tac x d2 f e d2a n c ei ci ei' ci')(*strict*)
    apply(force)
   apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c)(*strict*)
   prefer 2
   apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n)(*strict*)
   apply (metis GR.some_position_has_details_at_0)
  apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c)(*strict*)
  apply(subgoal_tac "(\<exists>k e2' c2'. d2a k = Some (pair (Some e2') c2') \<and> relation_labelsLR G1 G2 e2 e2') \<or> (n=0 \<and> (\<exists>d2' n2'. GR.derivation G2 d2' \<and> the(get_configuration(d2' 0)) = SSc \<and> maximum_of_domain d2' n2' \<and> (\<exists>k e2' c2'. d2' k = Some (pair (Some e2') c2' ) \<and> relation_labelsLR G1 G2 e2 e2')))" for SSc)
   apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c)(*strict*)
   prefer 2
   apply(rule AX_relation_step_simulationReach)
            apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c)(*strict*)
            apply(force)
           apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c)(*strict*)
           prefer 2
           apply (metis GL.belongs_step_labels GL.derivation_initial_belongs AX_TSstructure_relation_TSstructure1_belongs)
          apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c)(*strict*)
          prefer 2
          apply(force)
         apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c)(*strict*)
         apply(force)
        apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c)(*strict*)
        apply(force)
       apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c)(*strict*)
       apply(simp add: get_configuration_def)
      apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c)(*strict*)
      apply(simp add: get_configuration_def)
     apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c)(*strict*)
     apply(simp add: get_configuration_def)
    apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c)(*strict*)
    apply(force)
   apply(rename_tac x c1 e1a e2 c1a d2 n2 f e d2a n c)(*strict*)
   apply(force)
  apply(rule allI)
  apply(case_tac "i\<le>x")
   apply(erule_tac x="i" in allE)
   apply(clarsimp)
   apply(case_tac e1)
    apply(force)
   apply(clarsimp)
   apply(erule disjE)
    apply(clarsimp)
    apply(subgoal_tac "f i\<le>n2")
     apply(rule_tac x="k" in exI)
     apply(rule_tac x="d2'" in exI)
     apply(clarsimp)
     apply(rule conjI)
      apply(simp add: get_configuration_def derivation_append_def get_label_def)
     apply(simp add: get_configuration_def derivation_append_def get_label_def)
     apply(rule conjI)
      apply(force)
     apply(force)
    apply(simp add: simulating_derivation_def simulating_derivation_DEF_def)
    apply(clarsimp)
    apply (metis GR.allPreMaxDomSome_prime GR.derivation_initial_is_derivation option.distinct(1))
   apply(clarsimp)
   apply(subgoal_tac "f i\<le>n2")
    apply(case_tac "k\<le>f i")
     apply(rule_tac x="k" in exI)
     apply(rule_tac x="d2'" in exI)
     apply(clarsimp)
     apply(rule conjI)
      apply(simp add: get_configuration_def derivation_append_def get_label_def)
     apply(simp add: get_configuration_def derivation_append_def get_label_def)
    apply(rule_tac x="k" in exI)
    apply(rule_tac x="d2'" in exI)
    apply(clarsimp)
    apply(rule conjI)
     apply(simp add: get_configuration_def derivation_append_def get_label_def)
    apply(simp add: get_configuration_def derivation_append_def get_label_def)
   apply(simp add: simulating_derivation_def simulating_derivation_DEF_def)
   apply(clarsimp)
   apply (metis GR.allPreMaxDomSome_prime GR.derivation_initial_is_derivation option.distinct(1))
  apply(rule impI)
  apply(subgoal_tac "i=Suc x")
   prefer 2
   apply(force)
  apply(erule_tac x="x" in allE)
  apply(clarsimp)
  apply(subgoal_tac "n2= f x")
   prefer 2
   apply(simp add: simulating_derivation_def simulating_derivation_DEF_def)
  apply(clarsimp)
  apply(erule disjE)
   apply(clarsimp)
   apply(rule_tac
      x="f x+k"
      in exI)
   apply(rule_tac
      x="der1 (the (get_configuration (derivation_append d2 d2a (f x) ((f x) + n))))"
      in exI)
   apply(rule conjI)
    apply(rule GR.der1_is_derivation)
   apply(rule conjI)
    apply(simp add: der1_def get_configuration_def get_label_def derivation_append_def)
   apply(simp add: get_configuration_def get_label_def derivation_append_def)
   apply(case_tac k)
    apply(clarsimp)
   apply(clarsimp)
   apply(case_tac n)
    apply(clarsimp)
    apply(subgoal_tac "False")
     apply(force)
    apply (metis GR.derivationNoFromNone_prime GR.noSomeAfterMaxDom less_Suc_eq_0_disj)
   apply(clarsimp)
   apply(simp add: der1_def)
   apply(subgoal_tac "nat>nata")
    prefer 2
    apply(force)
   apply(clarsimp)
   apply(rule_tac
      m="Suc nat"
      and d="d2a"
      in GR.no_some_beyond_maximum_of_domain)
      apply(force)
     apply(force)
    apply(force)
   apply(force)
  apply(clarsimp)
  apply(rule_tac
      x="f x+k"
      in exI)
  apply(rule_tac
      x="d2'"
      in exI)
  apply(clarsimp)
  apply(rule conjI)
   apply(simp add: get_configuration_def)
   apply(simp add: derivation_append_def)
  apply(simp add: derivation_append_def)
  apply(case_tac k)
   apply(clarsimp)
   apply (metis GR.initialNotEdgeSome_prime)
  apply(clarsimp)
  apply(simp add: get_label_def)
  done

lemma ATS_Simulation_Configuration_WeakReach_simulation_derivation_exists_witness: "
  relation_TSstructure G1 G2
  \<Longrightarrow> GL.derivation_initial G1 d1
  \<Longrightarrow> d1 x = Some (pair e1 c1)
  \<Longrightarrow> \<exists>d2 n2 f.
  GR.derivation_initial G2 d2
  \<and> maximum_of_domain d2 n2
  \<and> relation_initial_configuration G1 G2 (the (get_configuration (d1 0))) (the (get_configuration (d2 0)))
  \<and> relation_configuration G1 G2 c1 (the (get_configuration (d2 n2)))
  \<and> simulating_derivation G1 G2 d1 x d2 n2 f
  \<and> (case e1 of None \<Rightarrow> True | Some e1' \<Rightarrow> \<exists>k d2'.
  GR.derivation G2 d2'
  \<and> the(get_configuration(d2' 0)) = the(get_configuration(d2 n2))
  \<and> (case ((get_label (derivation_append d2 d2' n2 k))) of None \<Rightarrow> False | Some e2' \<Rightarrow> relation_labelsLR G1 G2 e1' e2'))"
  apply(subgoal_tac "X" for X)
   prefer 2
   apply(rule ATS_Simulation_Configuration_WeakReach_simulation_derivation_exists_witness_EXTENDED_Reach)
     apply(force)
    apply(force)
   apply(force)
  apply(erule exE)+
  apply(rule_tac x="d2" in exI)
  apply(rule_tac x="n2" in exI)
  apply(rule_tac x="f" in exI)
  apply(clarsimp)
  apply(erule_tac x="x" in allE)
  apply(clarsimp)
  apply(case_tac e1)
   apply(force)
  apply(clarsimp)
  apply(rule_tac x="k" in exI)
  apply(rule_tac x="d2'" in exI)
  apply(clarsimp)
  apply(subgoal_tac "n2=f x")
   apply(clarsimp)
  apply(simp add: simulating_derivation_def simulating_derivation_DEF_def)
  done

theorem ATS_Simulation_Configuration_WeakReach_exists: "
  relation_TSstructure G1 G2
  \<Longrightarrow> GL.derivation_initial G1 d1
  \<Longrightarrow> d1 x = Some (pair e1 c1)
  \<Longrightarrow> \<exists>d2 n2 e2 c2.
  GR.derivation_initial G2 d2
  \<and> d2 n2 = Some (pair e2 c2)
  \<and> (case e1 of None \<Rightarrow> True
    | Some e1' \<Rightarrow>
      \<exists>k d2'.
      GR.derivation G2 d2'
      \<and> the(get_configuration(d2' 0)) = the(get_configuration(d2 n2))
      \<and> (case ((get_label (derivation_append d2 d2' n2 k))) of
          None \<Rightarrow> False
          | Some e2' \<Rightarrow> relation_labelsLR G1 G2 e1' e2'))"
  apply(subgoal_tac "\<exists>d2 n2 f. GR.derivation_initial G2 d2 \<and> maximum_of_domain d2 n2 \<and> relation_initial_configuration G1 G2 (the (get_configuration (d1 0))) (the (get_configuration (d2 0))) \<and> relation_configuration G1 G2 c1 (the (get_configuration (d2 n2))) \<and> simulating_derivation G1 G2 d1 x d2 n2 f \<and> (case e1 of None \<Rightarrow> True | Some e1' \<Rightarrow> \<exists>k d2'. GR.derivation G2 d2' \<and> the(get_configuration(d2' 0)) = the(get_configuration(d2 n2)) \<and> (case ((get_label (derivation_append d2 d2' n2 k))) of None \<Rightarrow> False | Some e2' \<Rightarrow> relation_labelsLR G1 G2 e1' e2'))")
   prefer 2
   apply(rule ATS_Simulation_Configuration_WeakReach_simulation_derivation_exists_witness)
     apply(force)
    apply(force)
   apply(force)
  apply(erule exE)+
  apply(rename_tac d2 n2 f)(*strict*)
  apply(erule conjE)+
  apply(case_tac e1)
   apply(rename_tac d2 n2 f)(*strict*)
   apply(clarsimp)
   apply(rule_tac
      x="d2"
      in exI)
   apply(clarsimp)
   apply(simp add: maximum_of_domain_def)
   apply(clarsimp)
   apply(rename_tac d2 n2 f y)(*strict*)
   apply(case_tac y)
   apply(rename_tac d2 n2 f y option b)(*strict*)
   apply(force)
  apply(rename_tac d2 n2 f a)(*strict*)
  apply(clarsimp)
  apply(rename_tac d2 n2 f a k d2')(*strict*)
  apply(rule_tac
      x="d2"
      in exI)
  apply(clarsimp)
  apply(rule_tac
      x="n2"
      in exI)
  apply(rule conjI)
   apply(rename_tac d2 n2 f a k d2')(*strict*)
   apply(simp add: maximum_of_domain_def)
   apply(clarsimp)
   apply(rename_tac d2 n2 f a k d2' y)(*strict*)
   apply(case_tac y)
   apply(rename_tac d2 n2 f a k d2' y option b)(*strict*)
   apply(force)
  apply(rename_tac d2 n2 f a k d2')(*strict*)
  apply(rule_tac
      x="k"
      in exI)
  apply(rule_tac
      x="d2'"
      in exI)
  apply(clarsimp)
  done

theorem ATS_Simulation_Configuration_WeakReach_exists_ALT: "
  relation_TSstructure G1 G2
  \<Longrightarrow> GL.derivation_initial G1 d1
  \<Longrightarrow> d1 x = Some (pair (Some e1) c1)
  \<Longrightarrow> \<exists>d2 n2 e2 c2.
  GR.derivation_initial G2 d2
  \<and> d2 n2 = Some (pair (Some e2) c2)
  \<and> relation_labelsLR G1 G2 e1 e2"
  apply(subgoal_tac "X" for X)
   prefer 2
   apply(rule ATS_Simulation_Configuration_WeakReach_exists)
     apply(force)
    apply(force)
   apply(force)
  apply(erule exE)+
  apply(rename_tac d2 n2 e2 c2)(*strict*)
  apply(clarsimp)
  apply(rename_tac d2 n2 e2 c2 k d2')(*strict*)
  apply(rule_tac x="derivation_append d2 d2' n2" in exI)
  apply(rule conjI)
   apply(rename_tac d2 n2 e2 c2 k d2')(*strict*)
   apply(rule GR.derivation_append_preserves_derivation_initial)
     apply(rename_tac d2 n2 e2 c2 k d2')(*strict*)
     apply (metis AX_TSstructure_relation_TSstructure2_belongs)
    apply(rename_tac d2 n2 e2 c2 k d2')(*strict*)
    apply(force)
   apply(rename_tac d2 n2 e2 c2 k d2')(*strict*)
   apply(rule GR.derivation_append_preserves_derivation)
     apply(rename_tac d2 n2 e2 c2 k d2')(*strict*)
     apply(simp add: GR.derivation_initial_def)
    apply(rename_tac d2 n2 e2 c2 k d2')(*strict*)
    apply(force)
   apply(rename_tac d2 n2 e2 c2 k d2')(*strict*)
   apply(clarsimp)
   apply(simp add: get_configuration_def)
   apply(case_tac "d2' 0")
    apply(rename_tac d2 n2 e2 c2 k d2')(*strict*)
    apply(clarsimp)
    apply(rename_tac d2 n2 e2 k d2')(*strict*)
    apply(simp add: GR.derivation_def GR.derivation_initial_def)
    apply(clarsimp)
    apply(erule_tac x="0" in allE)+
    apply(clarsimp)
   apply(rename_tac d2 n2 e2 c2 k d2' a)(*strict*)
   apply(clarsimp)
   apply(rename_tac d2 n2 e2 k d2' a)(*strict*)
   apply(case_tac a)
   apply(rename_tac d2 n2 e2 k d2' a option conf)(*strict*)
   apply(clarsimp)
   apply(rename_tac d2 n2 e2 k d2' option conf)(*strict*)
   apply(case_tac option)
    apply(rename_tac d2 n2 e2 k d2' option conf)(*strict*)
    apply(force)
   apply(rename_tac d2 n2 e2 k d2' option conf a)(*strict*)
   apply(clarsimp)
   apply(rename_tac d2 n2 e2 k d2' conf a)(*strict*)
   apply(simp add: GR.derivation_def GR.derivation_initial_def)
   apply(clarsimp)
   apply(erule_tac x="0" in allE)+
   apply(clarsimp)
  apply(rename_tac d2 n2 e2 c2 k d2')(*strict*)
  apply(rule_tac x="k" in exI)
  apply(simp add: get_label_def)
  apply(case_tac "derivation_append d2 d2' n2 k")
   apply(rename_tac d2 n2 e2 c2 k d2')(*strict*)
   apply(clarsimp)
  apply(rename_tac d2 n2 e2 c2 k d2' a)(*strict*)
  apply(clarsimp)
  apply(case_tac a)
  apply(rename_tac d2 n2 e2 c2 k d2' a option conf)(*strict*)
  apply(clarsimp)
  apply(rename_tac d2 n2 e2 c2 k d2' option conf)(*strict*)
  apply(case_tac option)
   apply(rename_tac d2 n2 e2 c2 k d2' option conf)(*strict*)
   apply(clarsimp)
  apply(rename_tac d2 n2 e2 c2 k d2' option conf a)(*strict*)
  apply(clarsimp)
  done

end

end


(*  Title:      Jinja/JVM/JVMExecInstrInductive.thy
    Author:     Susannah Mansky
    2018, UIUC
*)

section {* Inductive Program Execution in the JVM *}

theory JVMExecInstrInductive
imports JVMExec
begin

datatype step_input = StepI instr | StepC cname | StepT addr

inductive exec_step_ind :: "[step_input, jvm_prog, heap, val list, val list,
                  cname, mname, pc, init_call_status, frame list, sheap,jvm_state] \<Rightarrow> bool"
where
  exec_step_ind_Load:
"exec_step_ind (StepI (Load n)) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
   (None, h, ((loc ! n) # stk, loc, C\<^sub>0, M\<^sub>0, Suc pc, ics)#frs, sh)"

| exec_step_ind_Store:
"exec_step_ind (StepI (Store n)) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
   (None, h, (tl stk, loc[n:=hd stk], C\<^sub>0, M\<^sub>0, Suc pc, ics)#frs, sh)"

| exec_step_ind_Push:
"exec_step_ind (StepI (Push v)) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
   (None, h, (v # stk, loc, C\<^sub>0, M\<^sub>0, Suc pc, ics)#frs, sh)"

|  exec_step_ind_NewOOM_Called:
"new_Addr h = None
  \<Longrightarrow> exec_step_ind (StepI (New C)) P h stk loc C\<^sub>0 M\<^sub>0 pc Called frs sh
   (\<lfloor>addr_of_sys_xcpt OutOfMemory\<rfloor>, h, (stk, loc, C\<^sub>0, M\<^sub>0, pc, No_ics)#frs, sh)"

|  exec_step_ind_NewOOM_Done:
"\<lbrakk> sh C = Some(obj, Done); new_Addr h = None; ics \<noteq> Called \<rbrakk>
  \<Longrightarrow> exec_step_ind (StepI (New C)) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
   (\<lfloor>addr_of_sys_xcpt OutOfMemory\<rfloor>, h, (stk, loc, C\<^sub>0, M\<^sub>0, pc, ics)#frs, sh)"

|  exec_step_ind_New_Called:
"new_Addr h = Some a
  \<Longrightarrow> exec_step_ind (StepI (New C)) P h stk loc C\<^sub>0 M\<^sub>0 pc Called frs sh
   (None, h(a\<mapsto>blank P C), (Addr a#stk, loc, C\<^sub>0, M\<^sub>0, Suc pc, No_ics)#frs, sh)"

|  exec_step_ind_New_Done:
"\<lbrakk> sh C = Some(obj, Done); new_Addr h = Some a; ics \<noteq> Called \<rbrakk>
  \<Longrightarrow> exec_step_ind (StepI (New C)) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
   (None, h(a\<mapsto>blank P C), (Addr a#stk, loc, C\<^sub>0, M\<^sub>0, Suc pc, ics)#frs, sh)"

|  exec_step_ind_New_Init:
"\<lbrakk> \<forall>obj. sh C \<noteq> Some(obj, Done); ics \<noteq> Called \<rbrakk>
  \<Longrightarrow> exec_step_ind (StepI (New C)) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
   (None, h, (stk, loc, C\<^sub>0, M\<^sub>0, pc, Calling C)#frs, sh)"

| exec_step_ind_Getfield_Null:
"hd stk = Null
  \<Longrightarrow> exec_step_ind (StepI (Getfield F C)) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
   (\<lfloor>addr_of_sys_xcpt NullPointer\<rfloor>, h, (stk, loc, C\<^sub>0, M\<^sub>0, pc, ics)#frs, sh)"

| exec_step_ind_Getfield_NoField:
"\<lbrakk> v = hd stk; (D,fs) = the(h(the_Addr v)); v \<noteq> Null; \<not>(\<exists>t b. P \<turnstile> D has F,b:t in C) \<rbrakk>
  \<Longrightarrow> exec_step_ind (StepI (Getfield F C)) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
   (\<lfloor>addr_of_sys_xcpt NoSuchFieldError\<rfloor>, h, (stk, loc, C\<^sub>0, M\<^sub>0, pc, ics)#frs, sh)"

| exec_step_ind_Getfield_Static:
"\<lbrakk> v = hd stk; (D,fs) = the(h(the_Addr v)); v \<noteq> Null; P \<turnstile> D has F,Static:t in C \<rbrakk>
  \<Longrightarrow> exec_step_ind (StepI (Getfield F C)) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
   (\<lfloor>addr_of_sys_xcpt IncompatibleClassChangeError\<rfloor>, h, (stk, loc, C\<^sub>0, M\<^sub>0, pc, ics)#frs, sh)"

| exec_step_ind_Getfield:
"\<lbrakk> v = hd stk; (D,fs) = the(h(the_Addr v)); (D',b,t) = field P C F; v \<noteq> Null;
   P \<turnstile> D has F,NonStatic:t in C \<rbrakk>
  \<Longrightarrow> exec_step_ind (StepI (Getfield F C)) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
   (None, h, (the(fs(F,C))#(tl stk), loc, C\<^sub>0, M\<^sub>0, pc+1, ics)#frs, sh)"

| exec_step_ind_Getstatic_NoField:
"\<not>(\<exists>t b. P \<turnstile> C has F,b:t in D)
  \<Longrightarrow> exec_step_ind (StepI (Getstatic C F D)) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
    (\<lfloor>addr_of_sys_xcpt NoSuchFieldError\<rfloor>, h, (stk, loc, C\<^sub>0, M\<^sub>0, pc, ics)#frs, sh)"

| exec_step_ind_Getstatic_NonStatic:
"P \<turnstile> C has F,NonStatic:t in D
  \<Longrightarrow> exec_step_ind (StepI (Getstatic C F D)) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
    (\<lfloor>addr_of_sys_xcpt IncompatibleClassChangeError\<rfloor>, h, (stk, loc, C\<^sub>0, M\<^sub>0, pc, ics)#frs, sh)"

| exec_step_ind_Getstatic_Called:
"\<lbrakk> (D',b,t) = field P D F; P \<turnstile> C has F,Static:t in D;
   the(sh D') = (sfs,i);
   v = the (sfs F) \<rbrakk>
  \<Longrightarrow> exec_step_ind (StepI (Getstatic C F D)) P h stk loc C\<^sub>0 M\<^sub>0 pc Called frs sh
    (None, h, (v#stk, loc, C\<^sub>0, M\<^sub>0, Suc pc, No_ics)#frs, sh)"

| exec_step_ind_Getstatic_Done:
"\<lbrakk> (D',b,t) = field P D F; P \<turnstile> C has F,Static:t in D;
   ics \<noteq> Called; sh D' = Some(sfs,Done);
   v = the (sfs F) \<rbrakk>
  \<Longrightarrow> exec_step_ind (StepI (Getstatic C F D)) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
    (None, h, (v#stk, loc, C\<^sub>0, M\<^sub>0, Suc pc, ics)#frs, sh)"

| exec_step_ind_Getstatic_Init:
"\<lbrakk> (D',b,t) = field P D F; P \<turnstile> C has F,Static:t in D;
   \<forall>sfs. sh D' \<noteq> Some(sfs,Done); ics \<noteq> Called \<rbrakk>
  \<Longrightarrow> exec_step_ind (StepI (Getstatic C F D)) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
    (None, h, (stk, loc, C\<^sub>0, M\<^sub>0, pc, Calling D')#frs, sh)"

| exec_step_ind_Putfield_Null:
"hd(tl stk) = Null
  \<Longrightarrow> exec_step_ind (StepI (Putfield F C)) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
  (\<lfloor>addr_of_sys_xcpt NullPointer\<rfloor>, h, (stk, loc, C\<^sub>0, M\<^sub>0, pc, ics)#frs, sh)"

| exec_step_ind_Putfield_NoField:
"\<lbrakk> r = hd(tl stk); a = the_Addr r; (D,fs) = the (h a); r \<noteq> Null; \<not>(\<exists>t b. P \<turnstile> D has F,b:t in C) \<rbrakk>
  \<Longrightarrow> exec_step_ind (StepI (Putfield F C)) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
  (\<lfloor>addr_of_sys_xcpt NoSuchFieldError\<rfloor>, h, (stk, loc, C\<^sub>0, M\<^sub>0, pc, ics)#frs, sh)"

| exec_step_ind_Putfield_Static:
"\<lbrakk> r = hd(tl stk); a = the_Addr r; (D,fs) = the (h a); r \<noteq> Null; P \<turnstile> D has F,Static:t in C \<rbrakk>
  \<Longrightarrow> exec_step_ind (StepI (Putfield F C)) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
  (\<lfloor>addr_of_sys_xcpt IncompatibleClassChangeError\<rfloor>, h, (stk, loc, C\<^sub>0, M\<^sub>0, pc, ics)#frs, sh)"

| exec_step_ind_Putfield:
"\<lbrakk> v = hd stk; r = hd(tl stk); a = the_Addr r; (D,fs) = the (h a); (D',b,t) = field P C F;
   r \<noteq> Null; P \<turnstile> D has F,NonStatic:t in C \<rbrakk>
  \<Longrightarrow> exec_step_ind (StepI (Putfield F C)) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
  (None, h(a \<mapsto> (D, fs((F,C) \<mapsto> v))), (tl (tl stk), loc, C\<^sub>0, M\<^sub>0, pc+1, ics)#frs, sh)"

| exec_step_ind_Putstatic_NoField:
"\<not>(\<exists>t b. P \<turnstile> C has F,b:t in D)
  \<Longrightarrow> exec_step_ind (StepI (Putstatic C F D)) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
    (\<lfloor>addr_of_sys_xcpt NoSuchFieldError\<rfloor>, h, (stk, loc, C\<^sub>0, M\<^sub>0, pc, ics)#frs, sh)"

| exec_step_ind_Putstatic_NonStatic:
"P \<turnstile> C has F,NonStatic:t in D
  \<Longrightarrow> exec_step_ind (StepI (Putstatic C F D)) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
    (\<lfloor>addr_of_sys_xcpt IncompatibleClassChangeError\<rfloor>, h, (stk, loc, C\<^sub>0, M\<^sub>0, pc, ics)#frs, sh)"

| exec_step_ind_Putstatic_Called:
"\<lbrakk> (D',b,t) = field P D F; P \<turnstile> C has F,Static:t in D; the(sh D') = (sfs, i) \<rbrakk>
  \<Longrightarrow> exec_step_ind (StepI (Putstatic C F D)) P h stk loc C\<^sub>0 M\<^sub>0 pc Called frs sh
    (None, h, (tl stk, loc, C\<^sub>0, M\<^sub>0, Suc pc, No_ics)#frs, sh(D':=Some ((sfs(F \<mapsto> hd stk)), i)))"

| exec_step_ind_Putstatic_Done:
"\<lbrakk> (D',b,t) = field P D F; P \<turnstile> C has F,Static:t in D;
   ics \<noteq> Called; sh D' = Some (sfs, Done) \<rbrakk>
  \<Longrightarrow> exec_step_ind (StepI (Putstatic C F D)) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
    (None, h, (tl stk, loc, C\<^sub>0, M\<^sub>0, Suc pc, ics)#frs, sh(D':=Some ((sfs(F \<mapsto> hd stk)), Done)))"

| exec_step_ind_Putstatic_Init:
"\<lbrakk> (D',b,t) = field P D F; P \<turnstile> C has F,Static:t in D;
   \<forall>sfs. sh D' \<noteq> Some (sfs, Done); ics \<noteq> Called \<rbrakk>
  \<Longrightarrow> exec_step_ind (StepI (Putstatic C F D)) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
    (None, h, (stk, loc, C\<^sub>0, M\<^sub>0, pc, Calling D')#frs, sh)"

| exec_step_ind_Checkcast:
"cast_ok P C h (hd stk)
  \<Longrightarrow> exec_step_ind (StepI (Checkcast C)) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
    (None, h, (stk, loc, C\<^sub>0, M\<^sub>0, Suc pc, ics)#frs, sh)"

| exec_step_ind_Checkcast_Error:
"\<not>cast_ok P C h (hd stk)
  \<Longrightarrow> exec_step_ind (StepI (Checkcast C)) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
    (\<lfloor>addr_of_sys_xcpt ClassCast\<rfloor>, h, (stk, loc, C\<^sub>0, M\<^sub>0, pc, ics)#frs, sh)"

| exec_step_ind_Invoke_Null:
"stk!n = Null
  \<Longrightarrow> exec_step_ind (StepI (Invoke M n)) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
    (\<lfloor>addr_of_sys_xcpt NullPointer\<rfloor>, h, (stk, loc, C\<^sub>0, M\<^sub>0, pc, ics)#frs, sh)"

| exec_step_ind_Invoke_NoMethod:
"\<lbrakk> r = stk!n; C = fst(the(h(the_Addr r))); r \<noteq> Null;
   \<not>(\<exists>Ts T m D b. P \<turnstile> C sees M,b:Ts \<rightarrow> T = m in D) \<rbrakk>
  \<Longrightarrow> exec_step_ind (StepI (Invoke M n)) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
    (\<lfloor>addr_of_sys_xcpt NoSuchMethodError\<rfloor>, h, (stk, loc, C\<^sub>0, M\<^sub>0, pc, ics)#frs, sh)"

| exec_step_ind_Invoke_Static:
"\<lbrakk> r = stk!n; C = fst(the(h(the_Addr r)));
   (D,b,Ts,T,mxs,mxl\<^sub>0,ins,xt)= method P C M; r \<noteq> Null;
   P \<turnstile> C sees M,Static:Ts \<rightarrow> T = m in D \<rbrakk>
  \<Longrightarrow> exec_step_ind (StepI (Invoke M n)) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
    (\<lfloor>addr_of_sys_xcpt IncompatibleClassChangeError\<rfloor>, h, (stk, loc, C\<^sub>0, M\<^sub>0, pc, ics)#frs, sh)"

| exec_step_ind_Invoke:
"\<lbrakk> ps = take n stk; r = stk!n; C = fst(the(h(the_Addr r)));
   (D,b,Ts,T,mxs,mxl\<^sub>0,ins,xt)= method P C M; r \<noteq> Null;
   P \<turnstile> C sees M,NonStatic:Ts \<rightarrow> T = m in D;
   f' = ([],[r]@(rev ps)@(replicate mxl\<^sub>0 undefined),D,M,0,No_ics) \<rbrakk>
  \<Longrightarrow> exec_step_ind (StepI (Invoke M n)) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
    (None, h, f'#(stk, loc, C\<^sub>0, M\<^sub>0, pc, ics)#frs, sh)"

| exec_step_ind_Invokestatic_NoMethod:
"\<lbrakk> (D,b,Ts,T,mxs,mxl\<^sub>0,ins,xt)= method P C M; \<not>(\<exists>Ts T m D b. P \<turnstile> C sees M,b:Ts \<rightarrow> T = m in D) \<rbrakk>
  \<Longrightarrow> exec_step_ind (StepI (Invokestatic C M n)) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
    (\<lfloor>addr_of_sys_xcpt NoSuchMethodError\<rfloor>, h, (stk, loc, C\<^sub>0, M\<^sub>0, pc, ics)#frs, sh)"

| exec_step_ind_Invokestatic_NonStatic:
"\<lbrakk> (D,b,Ts,T,mxs,mxl\<^sub>0,ins,xt)= method P C M; P \<turnstile> C sees M,NonStatic:Ts \<rightarrow> T = m in D \<rbrakk>
  \<Longrightarrow> exec_step_ind (StepI (Invokestatic C M n)) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
    (\<lfloor>addr_of_sys_xcpt IncompatibleClassChangeError\<rfloor>, h, (stk, loc, C\<^sub>0, M\<^sub>0, pc, ics)#frs, sh)"

| exec_step_ind_Invokestatic_Called:
"\<lbrakk> ps  = take n stk; (D,b,Ts,T,mxs,mxl\<^sub>0,ins,xt) = method P C M;
   P \<turnstile> C sees M,Static:Ts \<rightarrow> T = m in D;
   f'  = ([],(rev ps)@(replicate mxl\<^sub>0 undefined),D,M,0,No_ics) \<rbrakk>
  \<Longrightarrow> exec_step_ind (StepI (Invokestatic C M n)) P h stk loc C\<^sub>0 M\<^sub>0 pc Called frs sh
    (None, h, f'#(stk, loc, C\<^sub>0, M\<^sub>0, pc, No_ics)#frs, sh)"

| exec_step_ind_Invokestatic_Done:
"\<lbrakk> ps  = take n stk; (D,b,Ts,T,mxs,mxl\<^sub>0,ins,xt) = method P C M;
   P \<turnstile> C sees M,Static:Ts \<rightarrow> T = m in D;
   ics \<noteq> Called; sh D = Some (sfs, Done);
   f'  = ([],(rev ps)@(replicate mxl\<^sub>0 undefined),D,M,0,No_ics) \<rbrakk>
  \<Longrightarrow> exec_step_ind (StepI (Invokestatic C M n)) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
    (None, h, f'#(stk, loc, C\<^sub>0, M\<^sub>0, pc, ics)#frs, sh)"

| exec_step_ind_Invokestatic_Init:
"\<lbrakk> (D,b,Ts,T,mxs,mxl\<^sub>0,ins,xt) = method P C M;
   P \<turnstile> C sees M,Static:Ts \<rightarrow> T = m in D;
   \<forall>sfs. sh D \<noteq> Some (sfs, Done); ics \<noteq> Called \<rbrakk>
  \<Longrightarrow> exec_step_ind (StepI (Invokestatic C M n)) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
    (None, h, (stk, loc, C\<^sub>0, M\<^sub>0, pc, Calling D)#frs, sh)"

| exec_step_ind_Return_Last_Init:
 "exec_step_ind (StepI Return) P h stk\<^sub>0 loc\<^sub>0 C\<^sub>0 clinit pc ics [] sh
    (None, h, [], sh(C\<^sub>0:=Some(fst(the(sh C\<^sub>0)), Done)))"

| exec_step_ind_Return_Last:
 "M\<^sub>0 \<noteq> clinit
   \<Longrightarrow> exec_step_ind (StepI Return) P h stk\<^sub>0 loc\<^sub>0 C\<^sub>0 M\<^sub>0 pc ics [] sh (None, h, [], sh)"

| exec_step_ind_Return_Init:
 "\<lbrakk> (D,b,Ts,T,m) = method P C\<^sub>0 clinit \<rbrakk>
   \<Longrightarrow> exec_step_ind (StepI Return) P h stk\<^sub>0 loc\<^sub>0 C\<^sub>0 clinit pc ics ((stk',loc',C',m',pc',ics')#frs') sh
     (None, h, (stk',loc',C',m',pc',ics')#frs', sh(C\<^sub>0:=Some(fst(the(sh C\<^sub>0)), Done)))"

| exec_step_ind_Return_NonStatic:
 "\<lbrakk> (D,NonStatic,Ts,T,m) = method P C\<^sub>0 M\<^sub>0; M\<^sub>0 \<noteq> clinit \<rbrakk>
   \<Longrightarrow> exec_step_ind (StepI Return) P h stk\<^sub>0 loc\<^sub>0 C\<^sub>0 M\<^sub>0 pc ics ((stk',loc',C',m',pc',ics')#frs') sh
     (None, h, ((hd stk\<^sub>0)#(drop (length Ts + 1) stk'),loc',C',m',Suc pc',ics')#frs', sh)"

| exec_step_ind_Return_Static:
 "\<lbrakk> (D,Static,Ts,T,m) = method P C\<^sub>0 M\<^sub>0; M\<^sub>0 \<noteq> clinit \<rbrakk>
   \<Longrightarrow> exec_step_ind (StepI Return) P h stk\<^sub>0 loc\<^sub>0 C\<^sub>0 M\<^sub>0 pc ics ((stk',loc',C',m',pc',ics')#frs') sh
     (None, h, ((hd stk\<^sub>0)#(drop (length Ts) stk'),loc',C',m',Suc pc',ics')#frs', sh)"

| exec_step_ind_Pop:
"exec_step_ind (StepI Pop) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
  (None, h, (tl stk, loc, C\<^sub>0, M\<^sub>0, Suc pc, ics)#frs, sh)"

| exec_step_ind_IAdd:
"exec_step_ind (StepI IAdd) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
  (None, h, (Intg (the_Intg (hd (tl stk)) + the_Intg (hd stk))#(tl (tl stk)), loc, C\<^sub>0, M\<^sub>0, Suc pc, ics)#frs, sh)"

| exec_step_ind_IfFalse_False:
"hd stk = Bool False
  \<Longrightarrow> exec_step_ind (StepI (IfFalse i)) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
    (None, h, (tl stk, loc, C\<^sub>0, M\<^sub>0, nat(int pc+i), ics)#frs, sh)"

| exec_step_ind_IfFalse_nFalse:
"hd stk \<noteq> Bool False
  \<Longrightarrow> exec_step_ind (StepI (IfFalse i)) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
    (None, h, (tl stk, loc, C\<^sub>0, M\<^sub>0, Suc pc, ics)#frs, sh)"

| exec_step_ind_CmpEq:
"exec_step_ind (StepI CmpEq) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
    (None, h, (Bool (hd (tl stk) = hd stk) # tl (tl stk), loc, C\<^sub>0, M\<^sub>0, Suc pc, ics)#frs, sh)"

| exec_step_ind_Goto:
"exec_step_ind (StepI (Goto i)) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
   (None, h, (stk, loc, C\<^sub>0, M\<^sub>0, nat(int pc+i), ics)#frs, sh)"

| exec_step_ind_Throw:
"hd stk \<noteq> Null
  \<Longrightarrow> exec_step_ind (StepI Throw) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
    (\<lfloor>the_Addr (hd stk)\<rfloor>, h, (stk, loc, C\<^sub>0, M\<^sub>0, pc, ics)#frs, sh)"

| exec_step_ind_Throw_Null:
"hd stk = Null
  \<Longrightarrow> exec_step_ind (StepI Throw) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
    (\<lfloor>addr_of_sys_xcpt NullPointer\<rfloor>, h, (stk, loc, C\<^sub>0, M\<^sub>0, pc, ics)#frs, sh)"

| exec_step_ind_Init_None_Called:
"\<lbrakk> sh C = None; ics = Called \<rbrakk>
  \<Longrightarrow> exec_step_ind (StepC C) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
    (None, h, (stk, loc, C\<^sub>0, M\<^sub>0, pc, Calling C)#frs, sh(C := Some (sblank P C, Prepared)))"

| exec_step_ind_Init_None_nCalled:
"\<lbrakk> sh C = None; ics \<noteq> Called \<rbrakk>
  \<Longrightarrow> exec_step_ind (StepC C) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
    (None, h, (stk, loc, C\<^sub>0, M\<^sub>0, pc, ICalling C)#frs, sh(C := Some (sblank P C, Prepared)))"

| exec_step_ind_Init_Done:
"sh C = Some (sfs, Done)
  \<Longrightarrow> exec_step_ind (StepC C) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
    (None, h, (stk, loc, C\<^sub>0, M\<^sub>0, pc, ics)#frs, sh)"

| exec_step_ind_Init_Processing:
"sh C = Some (sfs, Processing)
  \<Longrightarrow> exec_step_ind (StepC C) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
    (None, h, (stk, loc, C\<^sub>0, M\<^sub>0, pc, ics)#frs, sh)"

| exec_step_ind_Init_Error:
"\<lbrakk> sh C = Some (sfs, Error); (stk',loc',D',M',pc',ics') = create_init_frame P C \<rbrakk>
  \<Longrightarrow> exec_step_ind (StepC C) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
    (None, h, (stk',loc',D',M',pc',Throwing (addr_of_sys_xcpt NoClassDefFoundError))
                            #(stk, loc, C\<^sub>0, M\<^sub>0, pc, ics)#frs, sh)"

| exec_step_ind_Init_Prepared_Object:
"\<lbrakk> sh C = Some (sfs, Prepared);
   sh' = sh(C:=Some(fst(the(sh C)), Processing));
   C = Object \<rbrakk>
  \<Longrightarrow> exec_step_ind (StepC C) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
    (None, h, create_init_frame P C#(stk, loc, C\<^sub>0, M\<^sub>0, pc, ics)#frs, sh')"

| exec_step_ind_Init_Prepared_nObject:
"\<lbrakk> sh C = Some (sfs, Prepared); (stk',loc',C',m',pc',ics') = create_init_frame P C;
   sh' = sh(C:=Some(fst(the(sh C)), Processing));
   C \<noteq> Object; D = fst(the(class P C)) \<rbrakk>
  \<Longrightarrow> exec_step_ind (StepC C) P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh
    (None, h, (stk',loc',C',m',pc',ICalling D)#(stk, loc, C\<^sub>0, M\<^sub>0, pc, ics)#frs, sh')"

| exec_step_ind_InitThrow_Init:
"ics' \<noteq> Called
  \<Longrightarrow> exec_step_ind (StepT a) P h stk loc C\<^sub>0 M\<^sub>0 pc ics ((stk',loc',C',clinit,pc',ics')#frs') sh
    (None, h, (stk',loc',C',clinit,pc',Throwing a)#frs', (sh(C\<^sub>0:=Some(fst(the(sh C\<^sub>0)), Error))))"

| exec_step_ind_InitThrow_Called:
"exec_step_ind (StepT a) P h stk loc C\<^sub>0 M\<^sub>0 pc ics ((stk',loc',C',m',pc',Called)#frs') sh
    (\<lfloor>a\<rfloor>, h, (stk',loc',C',m',pc',No_ics)#frs', (sh(C\<^sub>0:=Some(fst(the(sh C\<^sub>0)), Error))))"

| exec_step_ind_InitThrow_Other:
"\<lbrakk> ics' \<noteq> Called; m' \<noteq> clinit \<rbrakk>
  \<Longrightarrow> exec_step_ind (StepT a) P h stk loc C\<^sub>0 M\<^sub>0 pc ics ((stk',loc',C',m',pc',ics')#frs') sh
    (\<lfloor>a\<rfloor>, h, (stk',loc',C',m',pc',ics')#frs', (sh(C\<^sub>0:=Some(fst(the(sh C\<^sub>0)), Error))))"

| exec_step_ind_InitThrow_Last:
"exec_step_ind (StepT a) P h stk loc C\<^sub>0 M\<^sub>0 pc ics [] sh
    (\<lfloor>a\<rfloor>, h, [], (sh(C\<^sub>0:=Some(fst(the(sh C\<^sub>0)), Error))))"

(** ******* **)

inductive_cases exec_step_ind_cases [cases set]:
 "exec_step_ind (StepI (Load n)) P h stk loc C M pc ics frs sh \<sigma>"
 "exec_step_ind (StepI (Store n)) P h stk loc C M pc ics frs sh \<sigma>"
 "exec_step_ind (StepI (Push v)) P h stk loc C M pc ics frs sh \<sigma>"
 "exec_step_ind (StepI (New C)) P h stk loc C M pc ics frs sh \<sigma>"
 "exec_step_ind (StepI (Getfield F C)) P h stk loc C M pc ics frs sh \<sigma>"
 "exec_step_ind (StepI (Getstatic C F D)) P h stk loc C M pc ics frs sh \<sigma>"
 "exec_step_ind (StepI (Putfield F C)) P h stk loc C M pc ics frs sh \<sigma>"
 "exec_step_ind (StepI (Putstatic C F D)) P h stk loc C M pc ics frs sh \<sigma>"
 "exec_step_ind (StepI (Checkcast C)) P h stk loc C M pc ics frs sh \<sigma>"
 "exec_step_ind (StepI (Invoke M n)) P h stk loc C M pc ics frs sh \<sigma>"
 "exec_step_ind (StepI (Invokestatic C M n)) P h stk loc C M pc ics frs sh \<sigma>"
 "exec_step_ind (StepI Return) P h stk loc C M pc ics frs sh \<sigma>"
 "exec_step_ind (StepI Pop) P h stk loc C M pc ics frs sh \<sigma>"
 "exec_step_ind (StepI IAdd) P h stk loc C M pc ics frs sh \<sigma>"
 "exec_step_ind (StepI (IfFalse i)) P h stk loc C M pc ics frs sh \<sigma>"
 "exec_step_ind (StepI CmpEq) P h stk loc C M pc ics frs sh \<sigma>"
 "exec_step_ind (StepI (Goto i)) P h stk loc C M pc ics frs sh \<sigma>"
 "exec_step_ind (StepI Throw) P h stk loc C M pc ics frs sh \<sigma>"
 "exec_step_ind (StepC C) P h stk loc C M pc ics frs sh \<sigma>"
 "exec_step_ind (StepT a) P h stk loc C M pc ics frs sh \<sigma>"

(* HERE: MOVE *)
fun exec_step_input :: "[jvm_prog, cname, mname, pc, init_call_status]
   \<Rightarrow> step_input \<times> init_call_status" where
"exec_step_input P C M pc (Calling C') = (StepC C', Called)" |
"exec_step_input P C M pc (ICalling C') = (StepC C', No_ics)" |
"exec_step_input P C M pc (Throwing a) = (StepT a, Throwing a)" |
"exec_step_input P C M pc ics = (StepI (instrs_of P C M ! pc), ics)"

lemma exec_step_imp_exec_step_ind:
assumes "exec_step P h stk loc C M pc ics frs sh = (xp', h', frs', sh')"
  and "exec_step_input P C M pc ics = (si, ics')"
shows "exec_step_ind si P h stk loc C M pc ics' frs sh (xp', h', frs', sh')"
proof(cases si)
  case (StepT a)
  then have exec_Throwing:
    "exec_Throwing a P h stk loc C M pc (Throwing a) frs sh = (xp', h', frs', sh')"
    "ics = ics'" using assms by(cases ics, auto)+
  then obtain stk' loc' C' m' pc' ics' where lets: "(stk',loc',C',m',pc',ics') = hd frs"
     by(cases "hd frs", simp)
  then show ?thesis using exec_step_ind_InitThrow_Init exec_step_ind_InitThrow_Called
    exec_step_ind_InitThrow_Other exec_step_ind_InitThrow_Last StepT exec_Throwing
   by(cases frs; cases "m' = clinit"; cases ics', auto)
next
  case (StepC C1)
  obtain D b Ts T m where lets: "method P C1 clinit = (D,b,Ts,T,m)" by(cases "method P C1 clinit")
  then obtain mxs mxl\<^sub>0 ins xt where m: "m = (mxs,mxl\<^sub>0,ins,xt)" by(cases m)
  show ?thesis
  proof(cases "sh C1")
    case None then show ?thesis
     using exec_step_ind_Init_None_Called exec_step_ind_Init_None_nCalled StepC assms
       by(cases ics, auto)
  next
    case (Some a)
    then obtain sfs i where sfsi: "a = (sfs,i)" by(cases a)
    then show ?thesis using exec_step_ind_Init_Done exec_step_ind_Init_Processing
    exec_step_ind_Init_Error m lets Some StepC assms
    proof(cases i)
      case Prepared
      show ?thesis
      using exec_step_ind_Init_Prepared_Object[where P=P] exec_step_ind_Init_Prepared_nObject
       sfsi m lets Prepared Some StepC assms by(cases ics, auto split: if_split_asm)
    qed(cases ics, auto)+
  qed
next
  case (StepI i)
  then have exec_instr: "exec_instr i P h stk loc C M pc ics' frs sh = (xp', h', frs', sh')"
    "ics = ics'" using assms by(cases ics, auto)+
  show ?thesis
  proof(cases i)
    case (Load x1) then show ?thesis using exec_instr exec_step_ind_Load StepI by auto
  next
    case (Store x2) then show ?thesis using exec_instr exec_step_ind_Store StepI by auto
  next
    case (Push x3) then show ?thesis using exec_instr exec_step_ind_Push StepI by auto
  next
    case (New C1)
    then obtain sfs i where sfsi: "the(sh C1) = (sfs,i)" by(cases "the(sh C1)")
    then show ?thesis using exec_step_ind_New_Called exec_step_ind_NewOOM_Called
       exec_step_ind_New_Done exec_step_ind_NewOOM_Done
       exec_step_ind_New_Init sfsi New StepI exec_instr by(cases ics; cases i, auto)
  next
    case (Getfield F1 C1)
    then obtain D fs D' b t where lets: "the(h(the_Addr (hd stk))) = (D,fs)"
      "field P C1 F1 = (D',b,t)" by(cases "the(h(the_Addr (hd stk)))", cases "field P C1 F1")
    then have "\<And>b' t'. P \<turnstile> D has F1,b':t' in C1 \<Longrightarrow> (D', b, t) = (C1, b', t')"
      using field_def2 has_field_idemp has_field_sees by fastforce
    then show ?thesis using exec_step_ind_Getfield_Null exec_step_ind_Getfield_NoField
       exec_step_ind_Getfield_Static lets Getfield StepI exec_instr
      by(cases b, auto split: if_split_asm) (metis Suc_eq_plus1 exec_step_ind_Getfield)+
  next
    case (Getstatic C1 F1 D1)
    then obtain D' b t where lets: "field P D1 F1 = (D',b,t)" by(cases "field P D1 F1")
    then have field: "\<And>b' t'. P \<turnstile> C1 has F1,b':t' in D1 \<Longrightarrow> (D', b, t) = (D1, b', t')"
      using field_def2 has_field_idemp has_field_sees by fastforce
    show ?thesis
    proof(cases b)
      case NonStatic then show ?thesis
       using exec_step_ind_Getstatic_NoField exec_step_ind_Getstatic_NonStatic
        field lets Getstatic exec_instr StepI by(auto split: if_split_asm) fastforce
    next
      case Static show ?thesis
      proof(cases "ics = Called")
        case True then show ?thesis using exec_step_ind_Getstatic_NoField
          exec_step_ind_Getstatic_Called exec_step_ind_Getstatic_Init
          Static field lets Getstatic exec_instr StepI
         by(cases "the(sh D1)", cases ics, auto split: if_split_asm) metis
      next
        case False
        then have nCalled: "ics \<noteq> Called" by simp
        show ?thesis
        proof(cases "sh D1")
          case None
          then have nDone: "\<forall>sfs. sh D1 \<noteq> Some(sfs, Done)" by simp
          then show ?thesis using exec_step_ind_Getstatic_NoField
            exec_step_ind_Getstatic_Init[where sh=sh, OF _ _ nDone nCalled]
            field lets None False Static Getstatic exec_instr StepI
           by(cases ics, auto split: if_split_asm) metis+
        next
          case (Some a)
          then obtain sfs i where sfsi: "a=(sfs,i)" by(cases a)
          show ?thesis using exec_step_ind_Getstatic_NoField
            exec_step_ind_Getstatic_Init sfsi False Static Some field lets Getstatic exec_instr
          proof(cases "i = Done")
            case True then show ?thesis using exec_step_ind_Getstatic_NoField
              exec_step_ind_Getstatic_Done[OF _ _ nCalled] exec_step_ind_Getstatic_Init
              sfsi False Static Some field lets Getstatic exec_instr StepI
             by(cases ics, auto split: if_split_asm) metis+
          next
            case nD: False
            then have nDone: "\<forall>sfs. sh D1 \<noteq> Some(sfs, Done)" using sfsi Some by simp
            show ?thesis using nD
            proof(cases i)
              case Processing then show ?thesis using exec_step_ind_Getstatic_NoField
                exec_step_ind_Getstatic_Init[where sh=sh, OF _ _ nDone nCalled]
                sfsi False Static Some field lets Getstatic exec_instr StepI
               by(cases ics, auto split: if_split_asm) metis+
            next
              case Prepared then show ?thesis using exec_step_ind_Getstatic_NoField
                exec_step_ind_Getstatic_Init[where sh=sh, OF _ _ nDone nCalled]
                sfsi False Static Some field lets Getstatic exec_instr StepI
               by(cases ics, auto split: if_split_asm) metis+
            next
              case Error then show ?thesis using exec_step_ind_Getstatic_NoField
                exec_step_ind_Getstatic_Init[where sh=sh, OF _ _ nDone nCalled]
                sfsi False Static Some field lets Getstatic exec_instr StepI
               by(cases ics, auto split: if_split_asm) metis+
            qed(simp)
          qed
        qed
      qed
    qed
  next
    case (Putfield F1 C1)
    then obtain D fs D' b t where lets: "the(h(the_Addr (hd(tl stk)))) = (D,fs)"
      "field P C1 F1 = (D',b,t)" by(cases "the(h(the_Addr (hd(tl stk))))", cases "field P C1 F1")
    then have "\<And>b' t'. P \<turnstile> D has F1,b':t' in C1 \<Longrightarrow> (D', b, t) = (C1, b', t')"
      using field_def2 has_field_idemp has_field_sees by fastforce
    then show ?thesis using exec_step_ind_Putfield_Null exec_step_ind_Putfield_NoField
       exec_step_ind_Putfield_Static lets Putfield exec_instr StepI
      by(cases b, auto split: if_split_asm) (metis Suc_eq_plus1 exec_step_ind_Putfield)+
  next
    case (Putstatic C1 F1 D1)
    then obtain D' b t where lets: "field P D1 F1 = (D',b,t)" by(cases "field P D1 F1")
    then have field: "\<And>b' t'. P \<turnstile> C1 has F1,b':t' in D1 \<Longrightarrow> (D', b, t) = (D1, b', t')"
      using field_def2 has_field_idemp has_field_sees by fastforce
    show ?thesis
    proof(cases b)
      case NonStatic then show ?thesis
       using exec_step_ind_Putstatic_NoField exec_step_ind_Putstatic_NonStatic
        field lets Putstatic exec_instr StepI by(auto split: if_split_asm) fastforce
    next
      case Static show ?thesis
      proof(cases "ics = Called")
        case True then show ?thesis using exec_step_ind_Putstatic_NoField
          exec_step_ind_Putstatic_Called exec_step_ind_Putstatic_Init
          Static field lets Putstatic exec_instr StepI
         by(cases "the(sh D1)", cases ics, auto split: if_split_asm) metis
      next
        case False
        then have nCalled: "ics \<noteq> Called" by simp
        show ?thesis
        proof(cases "sh D1")
          case None
          then have nDone: "\<forall>sfs. sh D1 \<noteq> Some(sfs, Done)" by simp
          then show ?thesis using exec_step_ind_Putstatic_NoField
            exec_step_ind_Putstatic_Init[where sh=sh, OF _ _ nDone nCalled]
            field lets None False Static Putstatic exec_instr StepI
           by(cases ics, auto split: if_split_asm) metis+
        next
          case (Some a)
          then obtain sfs i where sfsi: "a=(sfs,i)" by(cases a)
          show ?thesis using exec_step_ind_Putstatic_NoField
            exec_step_ind_Putstatic_Init sfsi False Static Some field lets Putstatic exec_instr
          proof(cases "i = Done")
            case True then show ?thesis using exec_step_ind_Putstatic_NoField
              exec_step_ind_Putstatic_Done[OF _ _ nCalled] exec_step_ind_Putstatic_Init
              sfsi False Static Some field lets Putstatic exec_instr StepI
             by(cases ics, auto split: if_split_asm) metis+
          next
            case nD: False
            then have nDone: "\<forall>sfs. sh D1 \<noteq> Some(sfs, Done)" using sfsi Some by simp
            show ?thesis using nD
            proof(cases i)
              case Processing then show ?thesis using exec_step_ind_Putstatic_NoField
                exec_step_ind_Putstatic_Init[where sh=sh, OF _ _ nDone nCalled]
                sfsi False Static Some field lets Putstatic exec_instr StepI
               by(cases ics, auto split: if_split_asm) metis+
            next
              case Prepared then show ?thesis using exec_step_ind_Putstatic_NoField
                exec_step_ind_Putstatic_Init[where sh=sh, OF _ _ nDone nCalled]
                sfsi False Static Some field lets Putstatic exec_instr StepI
               by(cases ics, auto split: if_split_asm) metis+
            next
              case Error then show ?thesis using exec_step_ind_Putstatic_NoField
                exec_step_ind_Putstatic_Init[where sh=sh, OF _ _ nDone nCalled]
                sfsi False Static Some field lets Putstatic exec_instr StepI
               by(cases ics, auto split: if_split_asm) metis+
            qed(simp)
          qed
        qed
      qed
    qed
  next
    case (Checkcast x9) then show ?thesis
     using exec_step_ind_Checkcast exec_step_ind_Checkcast_Error exec_instr StepI
       by(auto split: if_split_asm)
  next
    case (Invoke M1 n) show ?thesis
    proof(cases "stk!n = Null")
      case True then show ?thesis using exec_step_ind_Invoke_Null Invoke exec_instr StepI
       by clarsimp
    next
      case False
      let ?C = "cname_of h (the_Addr (stk ! n))"
      obtain D b Ts T m where method: "method P ?C M1 = (D,b,Ts,T,m)" by(cases "method P ?C M1")
      then obtain mxs mxl\<^sub>0 ins xt where "m = (mxs,mxl\<^sub>0,ins,xt)" by(cases m)
      then show ?thesis using exec_step_ind_Invoke_NoMethod
        exec_step_ind_Invoke_Static exec_step_ind_Invoke method False Invoke exec_instr StepI
       by(cases b; auto split: if_split_asm)
    qed
  next
    case (Invokestatic C1 M1 n)
    obtain D b Ts T m where lets: "method P C1 M1 = (D,b,Ts,T,m)" by(cases "method P C1 M1")
    then obtain mxs mxl\<^sub>0 ins xt where m: "m = (mxs,mxl\<^sub>0,ins,xt)" by(cases m)
    have method: "\<And>b' Ts' t' m' D'. P \<turnstile> C1 sees M1,b':Ts' \<rightarrow> t' = m' in D'
     \<Longrightarrow> (D,b,Ts,T,m) = (D',b',Ts',t',m')" using lets by auto
    show ?thesis
    proof(cases b)
      case NonStatic then show ?thesis
       using exec_step_ind_Invokestatic_NoMethod exec_step_ind_Invokestatic_NonStatic
        m method lets Invokestatic exec_instr StepI  by(auto split: if_split_asm)
    next
      case Static show ?thesis
      proof(cases "ics = Called")
        case True then show ?thesis using exec_step_ind_Invokestatic_NoMethod
          exec_step_ind_Invokestatic_Called exec_step_ind_Invokestatic_Init
          Static m method lets Invokestatic exec_instr StepI
         by(cases ics, auto split: if_split_asm)
      next
        case False
        then have nCalled: "ics \<noteq> Called" by simp
        show ?thesis
        proof(cases "sh D")
          case None
          then have nDone: "\<forall>sfs. sh D \<noteq> Some(sfs, Done)" by simp
          show ?thesis using exec_step_ind_Invokestatic_NoMethod
            exec_step_ind_Invokestatic_Init[where sh=sh, OF _ _ nDone nCalled]
            method m lets None False Static Invokestatic exec_instr StepI
           by(cases ics, auto split: if_split_asm)
        next
          case (Some a)
          then obtain sfs i where sfsi: "a=(sfs,i)" by(cases a)
          show ?thesis using exec_step_ind_Invokestatic_NoMethod
            exec_step_ind_Invokestatic_Init sfsi False Static Some method lets Invokestatic exec_instr
          proof(cases "i = Done")
            case True then show ?thesis using exec_step_ind_Invokestatic_NoMethod
              exec_step_ind_Invokestatic_Done[OF _ _ _ nCalled] exec_step_ind_Invokestatic_Init
              sfsi False Static Some m method lets Invokestatic exec_instr StepI
             by(cases ics, auto split: if_split_asm)
          next
            case nD: False
            then have nDone: "\<forall>sfs. sh D \<noteq> Some(sfs, Done)" using sfsi Some by simp
            show ?thesis using nD
            proof(cases i)
              case Processing then show ?thesis using exec_step_ind_Invokestatic_NoMethod
                exec_step_ind_Invokestatic_Init[where sh=sh, OF _ _ nDone nCalled]
                sfsi False Static Some m method lets Invokestatic exec_instr StepI
               by(cases ics, auto split: if_split_asm)
            next
              case Prepared then show ?thesis using exec_step_ind_Invokestatic_NoMethod
                exec_step_ind_Invokestatic_Init[where sh=sh, OF _ _ nDone nCalled]
                sfsi False Static Some m method lets Invokestatic exec_instr StepI
               by(cases ics, auto split: if_split_asm)
            next
              case Error then show ?thesis using exec_step_ind_Invokestatic_NoMethod
                exec_step_ind_Invokestatic_Init[where sh=sh, OF _ _ nDone nCalled]
                sfsi False Static Some m method lets Invokestatic exec_instr StepI
               by(cases ics, auto split: if_split_asm)
            qed(simp)
          qed
        qed
      qed
    qed
  next
    case Return
    obtain D b Ts T m where method: "method P C M = (D,b,Ts,T,m)" by(cases "method P C M")
    then obtain mxs mxl\<^sub>0 ins xt where "m = (mxs,mxl\<^sub>0,ins,xt)" by(cases m)
    then show ?thesis using exec_step_ind_Return_Last_Init exec_step_ind_Return_Last
      exec_step_ind_Return_Init exec_step_ind_Return_NonStatic exec_step_ind_Return_Static
       method Return exec_instr StepI
      by(cases b; cases frs; cases "M = clinit"; cases ics, auto split: if_split_asm)
  next
    case Pop then show ?thesis using exec_instr StepI exec_step_ind_Pop by auto
  next
    case IAdd then show ?thesis using exec_instr StepI exec_step_ind_IAdd by auto
  next
    case (Goto x15) then show ?thesis using exec_instr StepI exec_step_ind_Goto by auto
  next
    case CmpEq then show ?thesis using exec_instr StepI exec_step_ind_CmpEq by auto
  next
    case (IfFalse x17) then show ?thesis using exec_instr StepI exec_step_ind_IfFalse_nFalse
    proof(cases "hd stk")
      case (Bool b) then show ?thesis using exec_step_ind_IfFalse_False
       exec_step_ind_IfFalse_nFalse IfFalse exec_instr StepI by(cases b, auto)
    qed(auto)
  next
    case Throw then show ?thesis
     using exec_instr StepI exec_step_ind_Throw exec_step_ind_Throw_Null
       by(cases "hd stk = Null", auto)
  qed
qed

lemma exec_step_ind_imp_exec_step:
assumes "exec_step_ind si P h stk loc C M pc ics' frs sh (xp', h', frs', sh')"
shows "\<And>ics. exec_step_input P C M pc ics = (si, ics')
 \<Longrightarrow> exec_step P h stk loc C M pc ics frs sh = (xp', h', frs', sh')"
using assms
proof(induct rule: exec_step_ind.induct)
  case (exec_step_ind_NewOOM_Done sh C obj h ics P stk loc C\<^sub>0 M\<^sub>0 pc frs)
  then show ?case by(cases ics, auto)
next
  case (exec_step_ind_New_Done sh C obj h a ics P stk loc C\<^sub>0 M\<^sub>0 pc frs)
  then show ?case by(cases ics, auto)
next
  case (exec_step_ind_New_Init sh C ics P h stk loc C\<^sub>0 M\<^sub>0 pc frs)
  then show ?case by(cases "snd(the(sh C))"; cases ics, auto)
next
  case (exec_step_ind_Getfield_NoField v stk D fs h P F C loc C\<^sub>0 M\<^sub>0 pc ics frs sh)
  then show ?case by(cases "the (h (the_Addr (hd stk)))", cases ics, auto)
next
  case (exec_step_ind_Getfield_Static v stk D fs h P F t C loc C\<^sub>0 M\<^sub>0 pc ics frs sh)
  then show ?case
   by(cases "the (h (the_Addr (hd stk)))", cases "field P C F", cases "fst(snd(field P C F))",
      cases ics, auto dest: has_field_sees[OF has_field_idemp])
next
  case (exec_step_ind_Getfield v stk D fs h D' b t P C F loc C\<^sub>0 M\<^sub>0 pc ics frs sh)
  then show ?case by(cases "the (h (the_Addr (hd stk)))", cases "field P C F",
                     cases ics, auto) (fastforce dest: has_field_sees[OF has_field_idemp])+
next
  case (exec_step_ind_Getstatic_NonStatic P C F t D h stk loc C\<^sub>0 M\<^sub>0 pc ics1 frs sh)
  then show ?case by(cases "field P D F", cases "fst(snd(field P D F))";
                     cases ics, auto) (fastforce dest: has_field_sees[OF has_field_idemp])+
next
  case (exec_step_ind_Getstatic_Called D' b t P D F C ics ics' v h stk loc C\<^sub>0 M\<^sub>0 pc frs)
  then show ?case by(cases "field P D F", cases "fst(snd(field P D F))",
                     cases ics, auto) (fastforce dest: has_field_sees[OF has_field_idemp])+
next
  case (exec_step_ind_Getstatic_Done D' b t P D F C ics sh sfs v h stk loc C\<^sub>0 M\<^sub>0 pc frs)
  then show ?case by(cases "field P D F", cases "fst(snd(field P D F))"; cases ics,
                     auto dest: has_field_sees[OF has_field_idemp])
next
  case (exec_step_ind_Getstatic_Init D' b t P D F C sh ics h stk loc C\<^sub>0 M\<^sub>0 pc frs)
  then show ?case
   by(cases "field P D F", cases "fst(snd(field P D F))"; cases ics; cases "snd(the(sh D'))",
      auto dest: has_field_sees[OF has_field_idemp])
next
  case (exec_step_ind_Putfield_NoField r stk a D fs h P F C loc C\<^sub>0 M\<^sub>0 pc ics frs sh)
  then show ?case by(cases "the (h (the_Addr (hd(tl stk))))", cases ics, auto)
next
  case (exec_step_ind_Putfield_Static r stk a D fs h P F t C loc C\<^sub>0 M\<^sub>0 pc ics frs sh)
  then show ?case
   by(cases "the (h (the_Addr (hd(tl stk))))", cases "field P C F", cases "fst(snd(field P C F))",
      cases ics, auto dest: has_field_sees[OF has_field_idemp])
next
  case (exec_step_ind_Putfield v stk r a D fs h D' b t P C F loc C\<^sub>0 M\<^sub>0 pc ics frs sh)
  then show ?case by(cases "the (h (the_Addr (hd(tl stk))))", cases "field P C F",
                     cases ics, auto) (fastforce dest: has_field_sees[OF has_field_idemp])+
next
  case (exec_step_ind_Putstatic_NonStatic P C F t D h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh)
  then show ?case by(cases "field P D F", cases "fst(snd(field P D F))";
                     cases ics, auto) (fastforce dest: has_field_sees[OF has_field_idemp])+
next
  case (exec_step_ind_Putstatic_Called D' b t P D F C sh sfs i h stk loc C\<^sub>0 M\<^sub>0 pc frs ics')
  then show ?case by(cases "field P D F", cases "fst(snd(field P D F))",
                     cases ics', auto dest: has_field_sees[OF has_field_idemp])
next
  case (exec_step_ind_Putstatic_Done D' b t P D F C ics sh sfs h stk loc C\<^sub>0 M\<^sub>0 pc frs)
  then show ?case by(cases "field P D F", cases "fst(snd(field P D F))"; cases ics,
                     auto dest: has_field_sees[OF has_field_idemp])
next
  case (exec_step_ind_Putstatic_Init D' b t P D F C sh ics h stk loc C\<^sub>0 M\<^sub>0 pc frs)
  then show ?case
   by(cases "field P D F", cases "fst(snd(field P D F))"; cases ics; cases "snd(the(sh D'))",
      auto dest: has_field_sees[OF has_field_idemp])
next
  case (exec_step_ind_Invoke ps n stk r C h D b Ts T mxs mxl\<^sub>0 ins xt P M m f' loc C\<^sub>0 M\<^sub>0 pc ics frs sh)
  then show ?case by(cases ics, fastforce+)
next
  case (exec_step_ind_Invokestatic_Called ps n stk D b Ts T mxs mxl\<^sub>0 ins xt P C M m ics ics' sh)
  then show ?case by(cases ics, fastforce+)
next
  case (exec_step_ind_Invokestatic_Done ps n stk D b Ts T mxs mxl\<^sub>0 ins xt P C M m ics sh sfs f')
  then show ?case by(cases ics, auto) fastforce+
next
  case (exec_step_ind_Invokestatic_Init D b Ts T mxs mxl\<^sub>0 ins xt P C M m sh ics n h stk loc C\<^sub>0 M\<^sub>0 pc frs)
  then show ?case by(cases ics; cases "snd(the(sh D))", auto) fastforce+
next
  case (exec_step_ind_Return_Last ics P h stk\<^sub>0 loc\<^sub>0 C\<^sub>0 M\<^sub>0 pc sh)
  then show ?case by(cases ics, auto)
next
  case (exec_step_ind_Return_NonStatic D Ts T m P C\<^sub>0 M\<^sub>0 ics h stk\<^sub>0 loc\<^sub>0 pc stk' loc' C' m' pc' ics' frs' sh)
  then show ?case by(cases "method P C\<^sub>0 M\<^sub>0", cases ics, auto)
next
  case (exec_step_ind_Return_Static D Ts T m P C\<^sub>0 M\<^sub>0 ics h stk\<^sub>0 loc\<^sub>0 pc stk' loc' C' m' pc' ics' frs' sh)
  then show ?case by(cases "method P C\<^sub>0 M\<^sub>0", cases ics, auto)
next
  case (exec_step_ind_IfFalse_nFalse stk i P h loc C\<^sub>0 M\<^sub>0 pc ics frs sh)
  then show ?case by(cases "hd stk"; cases ics, auto)
next
  case (exec_step_ind_Throw_Null stk P h loc C\<^sub>0 M\<^sub>0 pc ics frs sh)
  then show ?case by(cases "hd stk"; cases ics, auto)
next
  case (exec_step_ind_Init_None_nCalled sh C ics P h stk loc C\<^sub>0 M\<^sub>0 pc frs)
  then show ?case by(cases ics, auto)
next
  case (exec_step_ind_Init_Error sh C sfs stk' loc' D' M' pc' ics' P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs)
  then show ?case by(cases "method P C clinit", cases ics, auto)
next
  case (exec_step_ind_Init_Prepared_nObject sh C sfs stk' loc' C' m' pc' ics' P sh' D h stk loc C\<^sub>0 M\<^sub>0 pc ics frs)
  then show ?case by(cases "method P C clinit", cases ics, auto)
next
  case (exec_step_ind_InitThrow_Other ics' a P h stk loc C\<^sub>0 M\<^sub>0 pc ics stk' loc' C' m' pc' frs' sh)
  then show ?case by(cases ics; cases ics', auto)
next
  case (exec_step_ind_InitThrow_Init ics' a P h stk loc C\<^sub>0 M\<^sub>0 pc ics stk' loc' C' pc' frs' sh)
  then show ?case by(cases ics'; cases ics, auto)
next
  case (exec_step_ind_InitThrow_Called a P h stk loc C\<^sub>0 M\<^sub>0 pc ics stk' loc' C' m' pc' frs' sh ics')
  then show ?case by(cases ics', auto)
(***)
next
  case (exec_step_ind_Load n P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh)
  then show ?case by(cases ics, auto)
next
  case (exec_step_ind_Store n P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh)
  then show ?case by(cases ics, auto)
next
  case (exec_step_ind_Push v P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh)
  then show ?case by(cases ics, auto)
next
  case (exec_step_ind_NewOOM_Called h C P stk loc C\<^sub>0 M\<^sub>0 pc frs sh ics')
  then show ?case by(cases ics', auto)
next
  case (exec_step_ind_New_Called h a C P stk loc C\<^sub>0 M\<^sub>0 pc frs sh ics')
  then show ?case by(cases ics', auto)
next
  case (exec_step_ind_Getfield_Null stk F C P h loc C\<^sub>0 M\<^sub>0 pc ics frs sh)
  then show ?case by(cases ics, auto)
next
  case (exec_step_ind_Getstatic_NoField P C F D h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh)
  then show ?case by(cases ics, auto)
next
  case (exec_step_ind_Putfield_Null stk F C P h loc C\<^sub>0 M\<^sub>0 pc ics frs sh)
  then show ?case by(cases ics, auto)
next
  case (exec_step_ind_Putstatic_NoField P C F D h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh)
  then show ?case by(cases ics, auto)
next
  case (exec_step_ind_Checkcast P C h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh)
  then show ?case by(cases ics, auto)
next
  case (exec_step_ind_Checkcast_Error P C h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh)
  then show ?case by(cases ics, auto)
next
  case (exec_step_ind_Invoke_Null stk n M P h loc C\<^sub>0 M\<^sub>0 pc ics frs sh)
  then show ?case by(cases ics, auto)
next
  case (exec_step_ind_Invoke_NoMethod r stk n C h P M loc C\<^sub>0 M\<^sub>0 pc ics frs sh)
  then show ?case by(cases ics, auto)
next
  case (exec_step_ind_Invoke_Static r stk n C h D b Ts T mxs mxl\<^sub>0 ins xt P M m loc C\<^sub>0 M\<^sub>0 pc ics frs sh)
  then show ?case by(cases ics, auto)
next
  case (exec_step_ind_Invokestatic_NoMethod D b Ts T mxs mxl\<^sub>0 ins xt P C M n h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh)
  then show ?case by(cases ics, auto)
next
  case (exec_step_ind_Invokestatic_NonStatic D b Ts T mxs mxl\<^sub>0 ins xt P C M m n h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh)
  then show ?case by(cases ics, auto)
next
  case (exec_step_ind_Return_Last_Init P h stk\<^sub>0 loc\<^sub>0 C\<^sub>0 M\<^sub>0 pc sh)
  then show ?case by(cases ics, auto)
next
  case (exec_step_ind_Return_Init D b Ts T m P C\<^sub>0 M\<^sub>0 h stk\<^sub>0 loc\<^sub>0 pc stk' loc' C' m' pc' ics' frs' sh)
  then show ?case by(cases ics, auto)
next
  case (exec_step_ind_Pop P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh)
  then show ?case by(cases ics, auto)
next
  case (exec_step_ind_IAdd P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh)
  then show ?case by(cases ics, auto)
next
  case (exec_step_ind_IfFalse_False stk i P h loc C\<^sub>0 M\<^sub>0 pc ics frs sh)
  then show ?case by(cases ics, auto)
next
  case (exec_step_ind_CmpEq P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh)
  then show ?case by(cases ics, auto)
next
  case (exec_step_ind_Goto i P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs sh)
  then show ?case by(cases ics, auto)
next
  case (exec_step_ind_Throw stk a P h loc C\<^sub>0 M\<^sub>0 pc ics frs sh)
  then show ?case by(cases ics, auto)
next
  case (exec_step_ind_Init_None_Called sh C ics P h stk loc C\<^sub>0 M\<^sub>0 pc frs)
  then show ?case by(cases ics, auto)
next
  case (exec_step_ind_Init_Done sh C sfs P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs)
  then show ?case by(cases ics, auto)
next
  case (exec_step_ind_Init_Processing sh C sfs P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs)
  then show ?case by(cases ics, auto)
next
  case (exec_step_ind_Init_Prepared_Object sh C sfs sh' P h stk loc C\<^sub>0 M\<^sub>0 pc ics frs)
  then show ?case by(cases ics, auto)
next
  case (exec_step_ind_InitThrow_Last a P h stk loc C\<^sub>0 M\<^sub>0 pc ics sh)
  then show ?case by(cases ics, auto)
qed

lemma exec_step_ind_equiv:
 "exec_step_input P C M pc ics = (si, ics')
  \<Longrightarrow> exec_step P h stk loc C M pc ics frs sh = (xp', h', frs', sh')
    = exec_step_ind si P h stk loc C M pc ics' frs sh (xp', h', frs', sh')"
 using exec_step_imp_exec_step_ind exec_step_ind_imp_exec_step by meson

end