theory JVMCFG_wf imports JVMInterpretation "../Basic/CFGExit_wf" begin

section \<open>Instantiation of the \<open>CFG_wf\<close> locale\<close>

subsection \<open>Variables and Values\<close>

datatype jinja_var = HeapVar "addr" | Stk "nat" "nat" | Loc "nat" "nat"
datatype jinja_val = Object "obj option" | Primitive "val"

fun state_val :: "state \<Rightarrow> jinja_var \<Rightarrow> jinja_val"
where
  "state_val (h, stk, loc) (HeapVar a) = Object (h a)"
| "state_val (h, stk, loc) (Stk cd idx) = Primitive (stk (cd, idx))"
| "state_val (h, stk, loc) (Loc cd idx) = Primitive (loc (cd, idx))"

subsection \<open>The \<open>Def\<close> and \<open>Use\<close> sets\<close>

inductive_set Def :: "wf_jvmprog \<Rightarrow> j_node \<Rightarrow> jinja_var set"
  for P :: "wf_jvmprog"
  and n :: "j_node"
where
  Def_Load:
  "\<lbrakk> n = (_ (C, M, pc)#cs,None _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Load idx;
  cd = length cs;
  i = stkLength P C M pc\<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Def P n"

| Def_Store:
  "\<lbrakk> n = (_ (C, M, pc)#cs,None _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Store idx;
  cd = length cs \<rbrakk>
  \<Longrightarrow> Loc cd idx \<in> Def P n"

| Def_Push:
  "\<lbrakk> n = (_ (C, M, pc)#cs,None _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Push v;
  cd = length cs;
  i = stkLength P C M pc \<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Def P n"

| Def_New_Normal_Stk:
  "\<lbrakk> n = (_ (C, M, pc)#cs,\<lfloor>(cs',False)\<rfloor> _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = New Cl;
  cd = length cs;
  i = stkLength P C M pc \<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Def P n"

| Def_New_Normal_Heap:
  "\<lbrakk> n = (_ (C, M, pc)#cs,\<lfloor>(cs',False)\<rfloor> _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = New Cl \<rbrakk>
  \<Longrightarrow> HeapVar a \<in> Def P n"

| Def_Exc_Stk:
  "\<lbrakk> n = (_ (C, M, pc)#cs,\<lfloor>(cs',True)\<rfloor> _);
  cs' \<noteq> [];
  cd = length cs' - 1;
  (C',M',pc') = hd cs';
  i = stkLength P C' M' pc' - 1\<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Def P n"

| Def_Getfield_Stk:
  "\<lbrakk> n = (_ (C, M, pc)#cs,\<lfloor>(cs',False)\<rfloor> _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Getfield Fd Cl;
  cd = length cs;
  i = stkLength P C M pc - 1 \<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Def P n"

| Def_Putfield_Heap:
  "\<lbrakk> n = (_ (C, M, pc)#cs,\<lfloor>(cs',False)\<rfloor> _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Putfield Fd Cl \<rbrakk>
  \<Longrightarrow> HeapVar a \<in> Def P n"

| Def_Invoke_Loc:
  "\<lbrakk> n = (_ (C, M, pc)#cs,\<lfloor>(cs',False)\<rfloor> _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Invoke M' n';
  cs' \<noteq> [];
  hd cs' = (C',M',0);
  i < locLength P C' M' 0;
  cd = Suc (length cs) \<rbrakk>
  \<Longrightarrow> Loc cd i \<in> Def P n"

| Def_Return_Stk:
  "\<lbrakk> n = (_ (C, M, pc)#(D,M',pc')#cs,None _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Return;
  cd = length cs;
  i = stkLength P D M' (Suc pc') - 1 \<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Def P n"

| Def_IAdd_Stk:
  "\<lbrakk> n = (_ (C, M, pc)#cs,None _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = IAdd;
  cd = length cs;
  i = stkLength P C M pc - 2 \<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Def P n"

| Def_CmpEq_Stk:
  "\<lbrakk> n = (_ (C, M, pc)#cs,None _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = CmpEq;
  cd = length cs;
  i = stkLength P C M pc - 2 \<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Def P n"

inductive_set Use :: "wf_jvmprog \<Rightarrow> j_node \<Rightarrow> jinja_var set"
  for P :: "wf_jvmprog"
  and n :: "j_node"
where
  Use_Load:
  "\<lbrakk> n = (_ (C, M, pc)#cs,None _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Load idx;
  cd = length cs \<rbrakk>
  \<Longrightarrow> (Loc cd idx) \<in> Use P n"

| Use_Store:
  "\<lbrakk> n = (_ (C, M, pc)#cs,None _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Store idx;
  cd = length cs;
  Suc i = (stkLength P C M pc) \<rbrakk>
  \<Longrightarrow> (Stk cd i) \<in> Use P n"

| Use_New:
  "\<lbrakk> n = (_ (C, M, pc)#cs,x _);
  x = None \<or> x = \<lfloor>(cs',False)\<rfloor>;
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = New Cl \<rbrakk>
  \<Longrightarrow> HeapVar a \<in> Use P n"

| Use_Getfield_Stk:
  "\<lbrakk> n = (_ (C, M, pc)#cs,x _);
  x = None \<or> x = \<lfloor>(cs',False)\<rfloor>;
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Getfield Fd Cl;
  cd = length cs;
  Suc i = stkLength P C M pc \<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Use P n"

| Use_Getfield_Heap:
  "\<lbrakk> n = (_ (C, M, pc)#cs,\<lfloor>(cs',False)\<rfloor> _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Getfield Fd Cl \<rbrakk>
  \<Longrightarrow> HeapVar a \<in> Use P n"

| Use_Putfield_Stk_Pred:
  "\<lbrakk> n = (_ (C, M, pc)#cs,None _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Putfield Fd Cl;
  cd = length cs;
  i = stkLength P C M pc - 2 \<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Use P n"

| Use_Putfield_Stk_Update:
  "\<lbrakk> n = (_ (C, M, pc)#cs,\<lfloor>(cs',False)\<rfloor> _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Putfield Fd Cl;
  cd = length cs;
  i = stkLength P C M pc - 2 \<or> i = stkLength P C M pc - 1 \<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Use P n"

| Use_Putfield_Heap:
  "\<lbrakk> n = (_ (C, M, pc)#cs,\<lfloor>(cs',False)\<rfloor> _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Putfield Fd Cl \<rbrakk>
  \<Longrightarrow> HeapVar a \<in> Use P n"

| Use_Checkcast_Stk:
  "\<lbrakk> n = (_ (C, M, pc)#cs,x _);
  x = None \<or> x = \<lfloor>(cs',False)\<rfloor>;
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Checkcast Cl;
  cd = length cs;
  i = stkLength P C M pc - Suc 0 \<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Use P n"

| Use_Checkcast_Heap:
  "\<lbrakk> n = (_ (C, M, pc)#cs,None _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Checkcast Cl \<rbrakk>
  \<Longrightarrow> HeapVar a \<in> Use P n"

| Use_Invoke_Stk_Pred:
  "\<lbrakk> n = (_ (C, M, pc)#cs,None _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Invoke M' n';
  cd = length cs;
  i = stkLength P C M pc - Suc n' \<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Use P n"

| Use_Invoke_Heap_Pred:
  "\<lbrakk> n = (_ (C, M, pc)#cs,None _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Invoke M' n' \<rbrakk>
  \<Longrightarrow> HeapVar a \<in> Use P n"

| Use_Invoke_Stk_Update:
  "\<lbrakk> n = (_ (C, M, pc)#cs,\<lfloor>(cs',False)\<rfloor> _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Invoke M' n';
  cd = length cs;
  i < stkLength P C M pc;
  i \<ge> stkLength P C M pc - Suc n' \<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Use P n"

| Use_Return_Stk:
  "\<lbrakk> n = (_ (C, M, pc)#(D,M',pc')#cs,None _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Return;
  cd = Suc (length cs);
  i = stkLength P C M pc - 1 \<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Use P n"

| Use_IAdd_Stk:
  "\<lbrakk> n = (_ (C, M, pc)#cs,None _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = IAdd;
  cd = length cs;
  i = stkLength P C M pc - 1 \<or> i = stkLength P C M pc - 2 \<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Use P n"

| Use_IfFalse_Stk:
  "\<lbrakk> n = (_ (C, M, pc)#cs,None _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = (IfFalse b);
  cd = length cs;
  i = stkLength P C M pc - 1 \<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Use P n"

| Use_CmpEq_Stk:
  "\<lbrakk> n = (_ (C, M, pc)#cs,None _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = CmpEq;
  cd = length cs;
  i = stkLength P C M pc - 1 \<or> i = stkLength P C M pc - 2 \<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Use P n"

| Use_Throw_Stk:
  "\<lbrakk> n = (_ (C, M, pc)#cs,x _);
  x = None \<or> x = \<lfloor>(cs',True)\<rfloor>;
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Throw;
  cd = length cs;
  i = stkLength P C M pc - 1 \<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Use P n"

| Use_Throw_Heap:
  "\<lbrakk> n = (_ (C, M, pc)#cs,x _);
  x = None \<or> x = \<lfloor>(cs',True)\<rfloor>;
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Throw \<rbrakk>
  \<Longrightarrow> HeapVar a \<in> Use P n"

declare correct_state_def [simp del]

lemma edge_transfer_uses_only_Use:
  "\<lbrakk>valid_edge (P,C0,Main) a; \<forall>V \<in> Use P (sourcenode a). state_val s V = state_val s' V\<rbrakk>
  \<Longrightarrow> \<forall>V \<in> Def P (sourcenode a). state_val (BasicDefs.transfer (kind a) s) V =
                                  state_val (BasicDefs.transfer (kind a) s') V"
proof
  fix V
  assume ve: "valid_edge (P, C0, Main) a"
    and use_eq: "\<forall>V\<in>Use P (sourcenode a). state_val s V = state_val s' V"
    and v_in_def: "V \<in> Def P (sourcenode a)"
  obtain h stk loc where [simp]: "s = (h,stk,loc)" by (cases s, fastforce)
  obtain h' stk' loc' where [simp]: "s' = (h',stk',loc')" by (cases s', fastforce)
  note P_wf = wf_jvmprog_is_wf [of P]
  from ve
  have ex_edge: "(P,C0,Main) \<turnstile> (sourcenode a)-kind a\<rightarrow>(targetnode a)"
    and vn: "valid_node (P,C0,Main) (sourcenode a)"
    by simp_all
  show "state_val (transfer (kind a) s) V = state_val (transfer (kind a) s') V"
  proof (cases "sourcenode a")
    case [simp]: (Node cs x)
    from vn ex_edge have "cs \<noteq> []"
      by (cases x, auto elim: JVM_CFG.cases)
    then obtain C M pc cs' where [simp]: "cs = (C, M, pc)#cs'" by (cases cs, fastforce+)
    with vn obtain ST LT where wt: "((P\<^bsub>\<Phi>\<^esub>) C M ! pc) = \<lfloor>(ST,LT)\<rfloor>"
      by (cases cs', (cases x, auto)+)
    show ?thesis
    proof (cases "instrs_of (P\<^bsub>wf\<^esub>) C M ! pc")
      case [simp]: (Load n)
      from ex_edge have [simp]: "x = None"
        by (auto elim!: JVM_CFG.cases)
      hence "Loc (length cs') n \<in> Use P (sourcenode a)"
        by (auto intro!: Use_Load)
      with use_eq have "state_val s (Loc (length cs') n) = state_val s' (Loc (length cs') n)"
        by (simp del: state_val.simps)
      with v_in_def ex_edge show ?thesis
        by (auto elim!: Def.cases
                  elim: JVM_CFG.cases
                  simp: split_beta)
    next
      case [simp]: (Store n)
      from ex_edge have [simp]:"x = None"
        by (auto elim!: JVM_CFG.cases)
      have "ST \<noteq> []"
      proof -
        from vn
        obtain Ts T mxs mxl "is" xt
          where C_sees_M: "P\<^bsub>wf\<^esub> \<turnstile> C sees M: Ts\<rightarrow>T = (mxs, mxl, is, xt) in C"
          by (cases cs', auto)
        with vn
        have "pc < length is"
          by (cases cs', auto dest: sees_method_fun)
        from P_wf C_sees_M
        have "wt_method (P\<^bsub>wf\<^esub>) C Ts T mxs mxl is xt (P\<^bsub>\<Phi>\<^esub> C M)"
          by (auto dest: sees_wf_mdecl simp: wf_jvm_prog_phi_def wf_mdecl_def)
        with Store C_sees_M wt \<open>pc < length is\<close>
        show ?thesis
          by (fastforce simp: wt_method_def)
      qed
      then obtain ST1 STr where [simp]: "ST = ST1#STr"
        by (cases ST, fastforce+)
      from wt
        have "Stk (length cs') (length ST - 1) \<in> Use P (sourcenode a)"
          (is "?stk_top \<in> ?Use_src")
          by -(rule Use_Store, fastforce+)
      with use_eq have "state_val s ?stk_top = state_val s' ?stk_top"
        by (simp del: state_val.simps)
      with v_in_def ex_edge wt show ?thesis
        by (auto elim!: Def.cases
                  elim: JVM_CFG.cases
                  simp: split_beta)
    next
      case [simp]: (Push val)
      from ex_edge have "x = None"
        by (auto elim!: JVM_CFG.cases)
      with v_in_def ex_edge show ?thesis
        by (auto elim!: Def.cases
                  elim: JVM_CFG.cases)
    next
      case [simp]: (New Cl)
      show ?thesis
      proof (cases x)
        case None
        with v_in_def have False
          by (auto elim: Def.cases)
        thus ?thesis by simp
      next
        case (Some x')
        then obtain cs'' xf where [simp]: "x = \<lfloor>(cs'',xf)\<rfloor>"
          by (cases x', fastforce)
        have "\<not> xf \<longrightarrow> (\<forall>addr. HeapVar addr \<in> Use P (sourcenode a))"
          by (fastforce intro: Use_New)
        with use_eq
        have "\<not> xf \<longrightarrow> (\<forall>addr. state_val s (HeapVar addr) = state_val s' (HeapVar addr))"
          by (simp del: state_val.simps)
        hence "\<not> xf \<longrightarrow> h = h'"
          by (auto intro: ext)
        with v_in_def ex_edge show ?thesis
          by (auto elim!: Def.cases
                    elim: JVM_CFG.cases)
      qed
    next
      case [simp]: (Getfield Fd Cl)
      show ?thesis
      proof (cases x)
        case None
        with v_in_def have False
          by (auto elim: Def.cases)
        thus ?thesis by simp
      next
        case (Some x')
        then obtain cs'' xf where [simp]: "x = \<lfloor>(cs'',xf)\<rfloor>"
          by (cases x', fastforce)
        have "ST \<noteq> []"
        proof -
          from vn obtain T Ts mxs mxl "is" xt
            where sees_M: "(P\<^bsub>wf\<^esub>) \<turnstile> C sees M:Ts\<rightarrow>T = (mxs,mxl,is,xt) in C"
            by (cases cs', auto)
          with vn
          have "pc < length is"
            by (cases cs', auto dest: sees_method_fun)
          from P_wf sees_M have "wt_method (P\<^bsub>wf\<^esub>) C Ts T mxs mxl is xt (P\<^bsub>\<Phi>\<^esub> C M)"
            by (auto dest: sees_wf_mdecl simp: wf_jvm_prog_phi_def wf_mdecl_def)
          with Getfield sees_M wt \<open>pc < length is\<close> show ?thesis
            by (fastforce simp: wt_method_def)
        qed
        then obtain ST1 STr where [simp]: "ST = ST1#STr" by (cases ST, fastforce)
        from wt
        have "\<not> xf \<longrightarrow> (Stk (length cs') (length ST - 1) \<in> Use P (sourcenode a))"
          (is "?xf \<longrightarrow> ?stk_top \<in> ?Use_src")
          by (auto intro!: Use_Getfield_Stk)
        with use_eq
        have stk_top_eq: "\<not> xf \<longrightarrow> state_val s ?stk_top = state_val s' ?stk_top"
          by (simp del: state_val.simps)
        have "\<not> xf \<longrightarrow> (\<forall>addr. HeapVar addr \<in> Use P (sourcenode a))"
          by (auto intro!: Use_Getfield_Heap)
        with use_eq
        have "\<not> xf \<longrightarrow> (\<forall>addr. state_val s (HeapVar addr) = state_val s' (HeapVar addr))"
          by (simp del: state_val.simps)
        hence "\<not> xf \<longrightarrow> h = h'"
          by (auto intro: ext)
        with ex_edge v_in_def stk_top_eq wt
        show ?thesis
          by (auto elim!: Def.cases
                    elim: JVM_CFG.cases
                    simp: split_beta)
      qed
    next
      case [simp]: (Putfield Fd Cl)
      show ?thesis
      proof (cases x)
        case None
        with v_in_def have False
          by (auto elim: Def.cases)
        thus ?thesis by simp
      next
        case (Some x')
        then obtain cs'' xf where [simp]: "x = \<lfloor>(cs'',xf)\<rfloor>"
          by (cases x', fastforce)
        have "length ST > 1"
        proof -
          from vn obtain T Ts mxs mxl "is" xt
            where sees_M: "(P\<^bsub>wf\<^esub>) \<turnstile> C sees M:Ts\<rightarrow>T = (mxs,mxl,is,xt) in C"
            by (cases cs', auto)
          with vn
          have "pc < length is"
            by (cases cs', auto dest: sees_method_fun)
          from P_wf sees_M have "wt_method (P\<^bsub>wf\<^esub>) C Ts T mxs mxl is xt (P\<^bsub>\<Phi>\<^esub> C M)"
            by (auto dest: sees_wf_mdecl simp: wf_jvm_prog_phi_def wf_mdecl_def)
          with Putfield sees_M \<open>pc < length is\<close> wt show ?thesis
            by (fastforce simp: wt_method_def)
        qed
        then obtain ST1 STr' where "ST = ST1#STr' \<and> length STr' > 0"
          by (cases ST, fastforce+)
        then obtain ST2 STr where [simp]: "ST = ST1#ST2#STr"
          by (cases STr', fastforce+)
        from wt
        have "\<not> xf \<longrightarrow> (Stk (length cs') (length ST - 1) \<in> Use P (sourcenode a))"
          (is "?xf \<longrightarrow> ?stk_top \<in> ?Use_src")
          by (fastforce intro: Use_Putfield_Stk_Update)
        with use_eq have stk_top:"(\<not> xf) \<longrightarrow> state_val s ?stk_top = state_val s' ?stk_top"
          by (simp del: state_val.simps)
        from wt
        have "\<not> xf \<longrightarrow> (Stk (length cs') (length ST - 2) \<in> Use P (sourcenode a))"
          (is "?xf \<longrightarrow> ?stk_nxt \<in> ?Use_src")
          by (fastforce intro: Use_Putfield_Stk_Update)
        with use_eq
        have stk_nxt:"(\<not> xf) \<longrightarrow> state_val s ?stk_nxt = state_val s' ?stk_nxt"
          by (simp del: state_val.simps)
        have "\<not> xf \<longrightarrow> (\<forall>addr. HeapVar addr \<in> Use P (sourcenode a))"
          by (fastforce intro: Use_Putfield_Heap)
        with use_eq
        have "\<not> xf \<longrightarrow> (\<forall>addr. state_val s (HeapVar addr) = state_val s' (HeapVar addr))"
          by (simp del: state_val.simps)
        hence "\<not> xf \<longrightarrow> h = h'"
          by (auto intro: ext)
        with ex_edge v_in_def stk_top stk_nxt wt show ?thesis
          by (auto elim!: Def.cases
                   elim: JVM_CFG.cases
                   simp: split_beta)
      qed
    next
      case [simp]: (Checkcast Cl)
      show ?thesis
      proof (cases x)
        case None
        with v_in_def have False
          by (auto elim: Def.cases)
        thus ?thesis by simp
      next
        case (Some x')
        with ex_edge obtain cs''
          where "x = \<lfloor>(cs'',True)\<rfloor>"
          by (auto elim!: JVM_CFG.cases)
        with v_in_def ex_edge show ?thesis
          by (auto elim!: Def.cases
                    elim: JVM_CFG.cases)
      qed
    next
      case [simp]: (Invoke M' n')
      show ?thesis
      proof (cases x)
        case None
        with v_in_def have False
          by (auto elim: Def.cases)
        thus ?thesis by simp
      next
        case (Some x')
        then obtain cs'' xf where [simp]: "x = \<lfloor>(cs'',xf)\<rfloor>"
          by (cases x', fastforce)
        show ?thesis
        proof (cases xf)
          case True
          with v_in_def ex_edge show ?thesis
            by (auto elim!: Def.cases
                      elim: JVM_CFG.cases)
        next
          case [simp]: False
          have "length ST > n'"
          proof -
            from vn obtain T Ts mxs mxl "is" xt
              where sees_M: "(P\<^bsub>wf\<^esub>) \<turnstile> C sees M:Ts\<rightarrow>T = (mxs,mxl,is,xt) in C"
              by (cases cs', auto)
            with vn
            have "pc < length is"
              by (cases cs', auto dest: sees_method_fun)
            from P_wf sees_M have "wt_method (P\<^bsub>wf\<^esub>) C Ts T mxs mxl is xt (P\<^bsub>\<Phi>\<^esub> C M)"
              by (auto dest: sees_wf_mdecl simp: wf_jvm_prog_phi_def wf_mdecl_def)
            with Invoke sees_M \<open>pc < length is\<close> wt show ?thesis
              by (fastforce simp: wt_method_def)
          qed
          moreover obtain STn where "STn = take n' ST" by fastforce
          moreover obtain STs where "STs = ST ! n'" by fastforce
          moreover obtain STr where "STr = drop (Suc n') ST" by fastforce
          ultimately have [simp]:" ST = STn@STs#STr \<and> length STn = n'"
            by (auto simp: id_take_nth_drop)
          from wt
          have "\<forall>i. i \<le> n' \<longrightarrow> Stk (length cs') (length ST - Suc i) \<in> Use P (sourcenode a)"
            by (fastforce intro: Use_Invoke_Stk_Update)
          with use_eq
          have
            "\<forall>i. i \<le> n' \<longrightarrow> state_val s (Stk (length cs') (length ST - Suc i)) =
                           state_val s' (Stk (length cs') (length ST - Suc i))"
            by (simp del: state_val.simps)
          hence stk_eq:
            "\<forall>i. i \<le> n' \<longrightarrow> state_val s (Stk (length cs') (i + length STr)) =
                           state_val s' (Stk (length cs') (i + length STr))"
            by (clarsimp, erule_tac x="n' - i" in allE, auto simp: add.commute)
          from ex_edge obtain C'
            where trg: "targetnode a = (_ (C',M',0)#(C, M, pc)#cs',None _)"
            by (fastforce elim: JVM_CFG.cases)
          with ex_edge stk_eq v_in_def wt
          show ?thesis
            by (auto elim!: Def.cases) (erule JVM_CFG.cases, auto simp: split_beta add.commute)
        qed
      qed
    next
      case [simp]: Return
      show ?thesis
      proof (cases x)
        case [simp]: None
        show ?thesis
        proof (cases cs')
          case Nil
          with v_in_def show ?thesis
            by (auto elim!: Def.cases)
        next
          case (Cons aa list)
          then obtain C' M' pc' cs'' where [simp]: "cs' = (C',M',pc')#cs''"
            by (cases aa, fastforce)
          from wt
          have "Stk (length cs') (length ST - 1) \<in> Use P (sourcenode a)"
            by (fastforce intro: Use_Return_Stk)
          with use_eq
          have "state_val s (Stk (length cs') (length ST - 1)) =
                state_val s' (Stk (length cs') (length ST - 1))"
            by (simp del: state_val.simps)
          with v_in_def ex_edge wt show ?thesis
            by (auto elim!: Def.cases
                      elim: JVM_CFG.cases
                      simp: split_beta)
        qed
      next
        case (Some x')
        with ex_edge show ?thesis
          by (auto elim: JVM_CFG.cases)
      qed
    next
      case Pop
      with v_in_def ex_edge show ?thesis
        by (auto elim!: Def.cases elim: JVM_CFG.cases)
    next
      case [simp]: IAdd
      show ?thesis
      proof (cases x)
        case [simp]: None
        from wt
        have "Stk (length cs') (length ST - 1) \<in> Use P (sourcenode a)"
          (is "?stk_top \<in> ?Use")
          by (auto intro!: Use_IAdd_Stk)
        with use_eq
        have stk_top:"state_val s ?stk_top = state_val s' ?stk_top"
          by (simp del: state_val.simps)
        from wt
        have "Stk (length cs') (length ST - 2) \<in> Use P (sourcenode a)"
          (is "?stk_snd \<in> ?Use")
          by (auto intro!: Use_IAdd_Stk)
        with use_eq
        have stk_snd:"state_val s ?stk_snd = state_val s' ?stk_snd"
          by (simp del: state_val.simps)
        with v_in_def ex_edge stk_top wt show ?thesis
          by (auto elim!: Def.cases
                    elim: JVM_CFG.cases
                    simp: split_beta)
      next
        case (Some x')
        with ex_edge show ?thesis
          by (auto elim: JVM_CFG.cases)
      qed
    next
      case [simp]: (IfFalse b)
      show ?thesis
      proof (cases x)
        case [simp]: None
        from wt
        have "Stk (length cs') (length ST - 1) \<in> Use P (sourcenode a)"
          (is "?stk_top \<in> ?Use")
          by (auto intro!: Use_IfFalse_Stk)
        with use_eq
        have stk_top:"state_val s ?stk_top = state_val s' ?stk_top"
          by (simp del: state_val.simps)
        with v_in_def ex_edge wt show ?thesis
          by (auto elim!: Def.cases)
      next
        case (Some x')
        with ex_edge show ?thesis
          by (auto elim: JVM_CFG.cases)
      qed
    next
      case [simp]: CmpEq
      show ?thesis
      proof (cases x)
        case [simp]: None
        have "Stk (length cs') (stkLength P C M pc - 1) \<in> Use P (sourcenode a)"
          (is "?stk_top \<in> ?Use")
          by (auto intro!: Use_CmpEq_Stk)
        with use_eq
        have stk_top:"state_val s ?stk_top = state_val s' ?stk_top"
          by (simp del: state_val.simps)
        have "Stk (length cs') (stkLength P C M pc - 2) \<in> Use P (sourcenode a)"
          (is "?stk_snd \<in> ?Use")
          by (auto intro!: Use_CmpEq_Stk)
        with use_eq
        have stk_snd:"state_val s ?stk_snd = state_val s' ?stk_snd"
          by (simp del: state_val.simps)
        with v_in_def ex_edge stk_top wt show ?thesis
          by (auto elim!: Def.cases
                    elim: JVM_CFG.cases)
      next
        case (Some x')
        with ex_edge show ?thesis
          by (auto elim: JVM_CFG.cases)
      qed
    next
      case (Goto i)
      with ex_edge v_in_def show ?thesis
        by (auto elim!: Def.cases
                  elim: JVM_CFG.cases)
    next
      case [simp]: Throw
      show ?thesis
      proof (cases x)
        case [simp]: None
        have "Stk (length cs') (stkLength P C M pc - 1) \<in> Use P (sourcenode a)"
          (is "?stk_top \<in> ?Use")
          by (auto intro!: Use_Throw_Stk)
        with use_eq
        have stk_top:"state_val s ?stk_top = state_val s' ?stk_top"
          by (simp del: state_val.simps)
        with v_in_def show ?thesis
          by (auto elim!: Def.cases)
      next
        case (Some x')
        then obtain cs'' xf where [simp]: "x = \<lfloor>(cs'',xf)\<rfloor>"
          by (cases x', fastforce)
        hence "xf \<longrightarrow> Stk (length cs') (stkLength P C M pc - 1) \<in> Use P (sourcenode a)"
          (is "xf \<longrightarrow> ?stk_top \<in> ?Use")
          by (fastforce intro: Use_Throw_Stk)
        with use_eq
        have stk_top:"xf \<longrightarrow> state_val s ?stk_top = state_val s' ?stk_top"
          by (simp del: state_val.simps)
        with v_in_def ex_edge show ?thesis
          by (auto elim!: Def.cases
                    elim: JVM_CFG.cases)
      qed
    qed
  next
    case Entry
    with vn v_in_def show ?thesis
      by -(erule Def.cases, auto)
  qed
qed

lemma CFG_edge_Uses_pred_equal:
  "\<lbrakk> valid_edge (P,C0,Main) a;
  pred (kind a) s;
  \<forall>V \<in> Use P (sourcenode a). state_val s V = state_val s' V\<rbrakk>
  \<Longrightarrow> pred (kind a) s'"
proof -
  assume ve: "valid_edge (P,C0,Main) a"
    and pred: "pred (kind a) s"
    and use_eq: "\<forall>V\<in>Use P (sourcenode a). state_val s V = state_val s' V"
  obtain h stk loc where [simp]: "s = (h,stk,loc)" by (cases s, blast)
  obtain h' stk' loc' where [simp]: "s' = (h',stk',loc')" by (cases s', blast)
  from ve
  have vn: "valid_node (P,C0,Main) (sourcenode a)"
    and ex_edge: "(P,C0,Main) \<turnstile> (sourcenode a)-kind a\<rightarrow>(targetnode a)"
    by simp_all
  note P_wf = wf_jvmprog_is_wf [of P]
  show "pred (kind a) s'"
  proof (cases "sourcenode a")
    case [simp]: (Node cs x)
    from ve have "cs \<noteq> []"
      by (cases x, auto elim: JVM_CFG.cases)
    then obtain C M pc cs' where [simp]: "cs = (C, M, pc)#cs'" by (cases cs, fastforce+)
    from vn obtain ST LT where wt: "((P\<^bsub>\<Phi>\<^esub>) C M ! pc) = \<lfloor>(ST,LT)\<rfloor>"
      by (cases cs', (cases x, auto)+)
    show ?thesis
    proof (cases "instrs_of (P\<^bsub>wf\<^esub>) C M ! pc")
      case (Load nat)
      with ex_edge show ?thesis
        by (auto elim: JVM_CFG.cases)
    next
      case (Store nat)
      with ex_edge show ?thesis
        by (auto elim: JVM_CFG.cases)
    next
      case (Push val)
      with ex_edge show ?thesis
        by (auto elim: JVM_CFG.cases)
    next
      case [simp]: (New Cl)
      show ?thesis
      proof (cases x)
        case None
        hence "\<forall>addr. HeapVar addr \<in> Use P (sourcenode a)"
          by (auto intro!: Use_New)
        with use_eq have "\<forall>addr. state_val s (HeapVar addr) = state_val s' (HeapVar addr)"
          by (simp del: state_val.simps)
        hence "h = h'"
          by (auto intro: ext)
        with ex_edge pred show ?thesis
          by (auto elim!: JVM_CFG.cases)
      next
        case (Some x')
        with ex_edge show ?thesis
          by (auto elim: JVM_CFG.cases)
      qed
    next
      case [simp]: (Getfield Fd Cl)
      have "ST \<noteq> []"
      proof -
        from vn obtain T Ts mxs mxl "is" xt
          where sees_M: "(P\<^bsub>wf\<^esub>) \<turnstile> C sees M:Ts\<rightarrow>T = (mxs,mxl,is,xt) in C"
          by (cases cs', (cases x, auto)+)
        with vn
        have "pc < length is"
          by (cases cs', (cases x, auto dest: sees_method_fun)+)
        from P_wf sees_M have "wt_method (P\<^bsub>wf\<^esub>) C Ts T mxs mxl is xt (P\<^bsub>\<Phi>\<^esub> C M)"
          by (auto dest: sees_wf_mdecl simp: wf_jvm_prog_phi_def wf_mdecl_def)
        with Getfield wt sees_M \<open>pc < length is\<close> show ?thesis
          by (fastforce simp: wt_method_def)
      qed
      then obtain ST1 STr where [simp]: "ST = ST1#STr" by (cases ST, fastforce+)
      show ?thesis
      proof (cases x)
        case [simp]: None
        from wt
        have "Stk (length cs') (length ST - 1) \<in> Use P (sourcenode a)"
          (is "?stk_top \<in> ?Use")
          by (fastforce intro: Use_Getfield_Stk)
        with use_eq have "state_val s ?stk_top = state_val s' ?stk_top"
          by (simp del: state_val.simps)
        with ex_edge pred wt show ?thesis
          by (auto elim: JVM_CFG.cases)
      next
        case (Some x')
        with ex_edge show ?thesis
          by (auto elim: JVM_CFG.cases)
      qed
    next
      case [simp]: (Putfield Fd Cl)
      have "length ST > 1"
      proof -
        from vn obtain T Ts mxs mxl "is" xt
          where sees_M: "(P\<^bsub>wf\<^esub>) \<turnstile> C sees M:Ts\<rightarrow>T = (mxs,mxl,is,xt) in C"
          by (cases cs', (cases x, auto)+)
        with vn
        have "pc < length is"
          by (cases cs', (cases x, auto dest: sees_method_fun)+)
        from P_wf sees_M have "wt_method (P\<^bsub>wf\<^esub>) C Ts T mxs mxl is xt (P\<^bsub>\<Phi>\<^esub> C M)"
          by (auto dest: sees_wf_mdecl simp: wf_jvm_prog_phi_def wf_mdecl_def)
        with Putfield wt sees_M \<open>pc < length is\<close> show ?thesis
          by (fastforce simp: wt_method_def)
      qed
      then obtain ST1 STr' where "ST = ST1#STr' \<and> STr' \<noteq> []" by (cases ST, fastforce+)
      then obtain ST2 STr where [simp]: "ST = ST1#ST2#STr" by (cases STr', fastforce+)
      show ?thesis
      proof (cases x)
        case [simp]: None
        with wt
        have "Stk (length cs') (length ST - 2) \<in> Use P (sourcenode a)"
          (is "?stk_top \<in> ?Use")
          by (fastforce intro: Use_Putfield_Stk_Pred)
        with use_eq have "state_val s ?stk_top = state_val s' ?stk_top"
          by (simp del: state_val.simps)
        with ex_edge pred wt show ?thesis
          by (auto elim: JVM_CFG.cases)
      next
        case (Some x')
        with ex_edge show ?thesis
          by (auto elim: JVM_CFG.cases)
      qed
    next
      case [simp]: (Checkcast Cl)
      have "ST \<noteq> []"
      proof -
        from vn obtain T Ts mxs mxl "is" xt
          where sees_M: "(P\<^bsub>wf\<^esub>) \<turnstile> C sees M:Ts\<rightarrow>T = (mxs,mxl,is,xt) in C"
          by (cases cs', (cases x, auto)+)
        with vn
        have "pc < length is"
          by (cases cs', (cases x, auto dest: sees_method_fun)+)
        from P_wf sees_M have "wt_method (P\<^bsub>wf\<^esub>) C Ts T mxs mxl is xt (P\<^bsub>\<Phi>\<^esub> C M)"
          by (auto dest: sees_wf_mdecl simp: wf_jvm_prog_phi_def wf_mdecl_def)
        with Checkcast wt sees_M \<open>pc < length is\<close> show ?thesis
          by (fastforce simp: wt_method_def)
      qed
      then obtain ST1 STr where [simp]: "ST = ST1#STr" by (cases ST, fastforce+)
      show ?thesis
      proof (cases x)
        case [simp]: None
        from wt
        have "Stk (length cs') (stkLength P C M pc - Suc 0) \<in> Use P (sourcenode a)"
          (is "?stk_top \<in> ?Use")
          by (fastforce intro: Use_Checkcast_Stk)
        with use_eq
        have stk_top: "state_val s ?stk_top = state_val s' ?stk_top"
          by (simp del: state_val.simps)
        have "\<forall>addr. HeapVar addr \<in> Use P (sourcenode a)"
          by (fastforce intro: Use_Checkcast_Heap)
        with use_eq
        have "\<forall>addr. state_val s (HeapVar addr) = state_val s' (HeapVar addr)"
          by (simp del: state_val.simps)
        hence "h = h'"
          by (auto intro: ext)
        with ex_edge stk_top pred wt show ?thesis
          by (auto elim: JVM_CFG.cases)
      next
        case (Some x')
        with ex_edge show ?thesis
          by (auto elim: JVM_CFG.cases)
      qed
    next
      case [simp]: (Invoke M' n')
      have "length ST > n'"
      proof -
        from vn obtain T Ts mxs mxl "is" xt
          where sees_M: "(P\<^bsub>wf\<^esub>) \<turnstile> C sees M:Ts\<rightarrow>T = (mxs,mxl,is,xt) in C"
          by (cases cs', (cases x, auto)+)
        with vn
        have "pc < length is"
          by (cases cs', (cases x, auto dest: sees_method_fun)+)
        from P_wf sees_M have "wt_method (P\<^bsub>wf\<^esub>) C Ts T mxs mxl is xt (P\<^bsub>\<Phi>\<^esub> C M)"
          by (auto dest: sees_wf_mdecl simp: wf_jvm_prog_phi_def wf_mdecl_def)
        with Invoke wt sees_M \<open>pc < length is\<close> show ?thesis
          by (fastforce simp: wt_method_def)
      qed
      moreover obtain STn where "STn = take n' ST" by fastforce
      moreover obtain STs where "STs = ST ! n'" by fastforce
      moreover obtain STr where "STr = drop (Suc n') ST" by fastforce
      ultimately have [simp]:" ST = STn@STs#STr \<and> length STn = n'"
        by (auto simp: id_take_nth_drop)
      show ?thesis
      proof (cases x)
        case [simp]: None
        with wt
        have "Stk (length cs') (stkLength P C M pc - Suc n') \<in> Use P (sourcenode a)"
          (is "?stk_top \<in> ?Use")
          by (fastforce intro: Use_Invoke_Stk_Pred)
        with use_eq
        have stk_top: "state_val s ?stk_top = state_val s' ?stk_top"
          by (simp del: state_val.simps)
        have "\<forall>addr. HeapVar addr \<in> Use P (sourcenode a)"
          by (fastforce intro: Use_Invoke_Heap_Pred)
        with use_eq
        have "\<forall>addr. state_val s (HeapVar addr) = state_val s' (HeapVar addr)"
          by (simp del: state_val.simps)
        hence "h = h'"
          by (auto intro: ext)
        with ex_edge stk_top pred wt show ?thesis
          by (auto elim: JVM_CFG.cases)
      next
        case (Some x')
        with ex_edge show ?thesis
          by (auto elim: JVM_CFG.cases)
      qed
    next
      case Return
      with ex_edge show ?thesis
        by (auto elim: JVM_CFG.cases)
    next
      case Pop
      with ex_edge show ?thesis
        by (auto elim: JVM_CFG.cases)
    next
      case IAdd
      with ex_edge show ?thesis
        by (auto elim: JVM_CFG.cases)
    next
      case [simp]: (IfFalse b)
      show ?thesis
      proof (cases x)
        case [simp]: None
        have "Stk (length cs') (stkLength P C M pc - 1) \<in> Use P (sourcenode a)"
          (is "?stk_top \<in> ?Use")
          by (fastforce intro: Use_IfFalse_Stk)
        with use_eq
        have "state_val s ?stk_top = state_val s' ?stk_top"
          by (simp del: state_val.simps)
        with ex_edge pred wt show ?thesis
          by (auto elim: JVM_CFG.cases)
      next
        case (Some x')
        with ex_edge show ?thesis
          by (auto elim: JVM_CFG.cases)
      qed
    next
      case CmpEq
      with ex_edge show ?thesis
        by (auto elim: JVM_CFG.cases)
    next
      case (Goto i)
      with ex_edge show ?thesis
        by (auto elim: JVM_CFG.cases)
    next
      case [simp]: Throw
      have "ST \<noteq> []"
      proof -
        from vn obtain T Ts mxs mxl "is" xt
          where sees_M: "(P\<^bsub>wf\<^esub>) \<turnstile> C sees M:Ts\<rightarrow>T = (mxs,mxl,is,xt) in C"
          by (cases cs', (cases x, auto)+)
        with vn
        have "pc < length is"
          by (cases cs', (cases x, auto dest: sees_method_fun)+)
        from P_wf sees_M have "wt_method (P\<^bsub>wf\<^esub>) C Ts T mxs mxl is xt (P\<^bsub>\<Phi>\<^esub> C M)"
          by (auto dest: sees_wf_mdecl simp: wf_jvm_prog_phi_def wf_mdecl_def)
        with Throw wt sees_M \<open>pc < length is\<close> show ?thesis
          by (fastforce simp: wt_method_def)
      qed
      then obtain ST1 STr where [simp]: "ST = ST1#STr" by (cases ST, fastforce+)
      show ?thesis
      proof (cases x)
        case [simp]: None
        from wt
        have "Stk (length cs') (stkLength P C M pc - 1) \<in> Use P (sourcenode a)"
          (is "?stk_top \<in> ?Use")
          by (fastforce intro: Use_Throw_Stk)
        with use_eq
        have stk_top: "state_val s ?stk_top = state_val s' ?stk_top"
          by (simp del: state_val.simps)
        have "\<forall>addr. HeapVar addr \<in> Use P (sourcenode a)"
          by (fastforce intro: Use_Throw_Heap)
        with use_eq
        have "\<forall>addr. state_val s (HeapVar addr) = state_val s' (HeapVar addr)"
          by (simp del: state_val.simps)
        hence "h = h'"
          by (auto intro: ext)
        with ex_edge pred stk_top wt show ?thesis
          by (auto elim!: JVM_CFG.cases)
      next
        case (Some x')
        with ex_edge show ?thesis
          by (auto elim: JVM_CFG.cases)
      qed
    qed
  next
    case Entry
    with ex_edge pred show ?thesis
      by (auto elim: JVM_CFG.cases)
  qed
qed

lemma edge_no_Def_equal:
  "\<lbrakk> valid_edge (P, C0, Main) a;
     V \<notin> Def P (sourcenode a) \<rbrakk>
  \<Longrightarrow> state_val (transfer (kind a) s) V = state_val s V"
proof -
  assume ve:"valid_edge (P, C0, Main) a"
    and v_not_def: "V \<notin> Def P (sourcenode a)"
  obtain h stk loc where [simp]: "(s::state) = (h, stk, loc)" by (cases s, blast)
  from ve have vn: "valid_node (P, C0, Main) (sourcenode a)"
    and ex_edge: "(P, C0, Main) \<turnstile> (sourcenode a)-kind a\<rightarrow>(targetnode a)"
    by simp_all
  show "state_val (transfer (kind a) s) V = state_val s V"
  proof (cases "sourcenode a")
    case [simp]: (Node cs x)
    with ve have "cs \<noteq> []"
      by (cases x, auto elim: JVM_CFG.cases)
    then obtain C M pc cs' where [simp]: "cs = (C, M, pc)#cs'" by (cases cs, fastforce+)
    with vn obtain ST LT where wt: "((P\<^bsub>\<Phi>\<^esub>) C M ! pc) = \<lfloor>(ST,LT)\<rfloor>"
      by (cases cs', (cases x, auto)+)
    show ?thesis
    proof (cases "instrs_of (P\<^bsub>wf\<^esub>) C M ! pc")
      case [simp]: (Load nat)
      from ex_edge have "x = None"
        by (auto elim: JVM_CFG.cases)
      with v_not_def have "V \<noteq> Stk (length cs') (stkLength P C M pc)"
        by (auto intro!: Def_Load)
      with ex_edge show ?thesis
        by (auto elim!: JVM_CFG.cases, cases V, auto)
    next
      case [simp]: (Store nat)
      with ex_edge have "x = None"
        by (auto elim: JVM_CFG.cases)
      with v_not_def have "V \<noteq> Loc (length cs') nat"
        by (auto intro!: Def_Store)
      with ex_edge show ?thesis
        by (auto elim!: JVM_CFG.cases, cases V, auto)
    next
      case [simp]: (Push val)
      with ex_edge have "x = None"
        by (auto elim: JVM_CFG.cases)
      with v_not_def have "V \<noteq> Stk (length cs') (stkLength P C M pc)"
        by (auto intro!: Def_Push)
      with ex_edge show ?thesis
        by (auto elim!: JVM_CFG.cases, cases V, auto)
    next
      case [simp]: (New Cl)
      show ?thesis
      proof (cases x)
        case None
        with ex_edge show ?thesis
          by (auto elim: JVM_CFG.cases)
      next
        case (Some x')
        then obtain cs'' xf where [simp]: "x = \<lfloor>(cs'',xf)\<rfloor>"
          by (cases x', fastforce)
        with ex_edge v_not_def show ?thesis
          apply (auto elim!: JVM_CFG.cases)
            apply (cases V, auto intro!: Def_New_Normal_Stk Def_New_Normal_Heap)
           by (cases V, auto intro!: Def_Exc_Stk)+
     qed
   next
     case [simp]: (Getfield F Cl)
     show ?thesis
     proof (cases x)
       case None
       with ex_edge show ?thesis
         by (auto elim: JVM_CFG.cases)
     next
       case (Some x')
       then obtain cs'' xf where [simp]: "x = \<lfloor>(cs'',xf)\<rfloor>"
         by (cases x', fastforce)
       with ex_edge v_not_def show ?thesis
         apply (auto elim!: JVM_CFG.cases simp: split_beta)
           apply (cases V, auto intro!: Def_Getfield_Stk)
          by (cases V, auto intro!: Def_Exc_Stk)+
     qed
   next
     case [simp]: (Putfield Fd Cl)
     show ?thesis
     proof (cases x)
       case None
       with ex_edge show ?thesis
         by (auto elim: JVM_CFG.cases)
     next
       case (Some x')
       then obtain cs'' xf where [simp]: "x = \<lfloor>(cs'',xf)\<rfloor>"
         by (cases x', fastforce)
       with ex_edge v_not_def show ?thesis
         apply (auto elim!: JVM_CFG.cases simp: split_beta)
           apply (cases V, auto intro!: Def_Putfield_Heap)
          by (cases V, auto intro!: Def_Exc_Stk)+
     qed
   next
     case [simp]: (Checkcast Cl)
     show ?thesis
     proof (cases x)
       case None
       with ex_edge show ?thesis
         by (auto elim: JVM_CFG.cases)
     next
       case (Some x')
       then obtain cs'' xf where [simp]: "x = \<lfloor>(cs'',xf)\<rfloor>"
         by (cases x', fastforce)
       with ex_edge v_not_def show ?thesis
         apply (auto elim!: JVM_CFG.cases)
          by (cases V, auto intro!: Def_Exc_Stk)+
     qed
   next
     case [simp]: (Invoke M' n')
     show ?thesis
     proof (cases x)
       case None
       with ex_edge show ?thesis
         by (auto elim: JVM_CFG.cases)
     next
       case (Some x')
       then obtain cs'' xf where [simp]: "x = \<lfloor>(cs'',xf)\<rfloor>"
         by (cases x', fastforce)
       from ex_edge v_not_def show ?thesis
         apply (auto elim!: JVM_CFG.cases)
           apply (cases V, auto intro!: Def_Invoke_Loc)
          by (cases V, auto intro!: Def_Exc_Stk)+
     qed
   next
     case Return
     with ex_edge v_not_def show ?thesis
       apply (auto elim!: JVM_CFG.cases)
       by (cases V, auto intro!: Def_Return_Stk)
   next
     case Pop
     with ex_edge show ?thesis
       by (auto elim: JVM_CFG.cases)
   next
     case IAdd
     with ex_edge v_not_def show ?thesis
       apply (auto elim!: JVM_CFG.cases)
       by (cases V, auto intro!: Def_IAdd_Stk)
   next
     case (IfFalse b)
     with ex_edge show ?thesis
       by (auto elim: JVM_CFG.cases)
   next
     case CmpEq
     with ex_edge v_not_def show ?thesis
       apply (auto elim!: JVM_CFG.cases)
       by (cases V, auto intro!: Def_CmpEq_Stk)
   next
     case (Goto i)
     with ex_edge show ?thesis
       by (auto elim: JVM_CFG.cases)
   next
     case [simp]: Throw
     show ?thesis
     proof (cases x)
       case None
       with ex_edge show ?thesis
         by (auto elim: JVM_CFG.cases)
     next
       case (Some x')
       then obtain cs'' xf where [simp]: "x = \<lfloor>(cs'',xf)\<rfloor>"
         by (cases x', fastforce)
       from ex_edge v_not_def show ?thesis
         apply (auto elim!: JVM_CFG.cases)
          by (cases V, auto intro!: Def_Exc_Stk)+
      qed
    qed
  next
    case Entry
    with ex_edge show ?thesis
      by (auto elim: JVM_CFG.cases)
  qed
qed

interpretation JVM_CFG_wf: CFG_wf
  "sourcenode" "targetnode" "kind" "valid_edge prog" "(_Entry_)"
  "Def (fst prog)" "Use (fst prog)" "state_val"
  for prog
proof (unfold_locales)
  show "Def (fst prog) (_Entry_) = {} \<and> Use (fst prog) (_Entry_) = {}"
    by (auto elim: Def.cases Use.cases)
next
  fix a V s
  assume ve:"valid_edge prog a"
    and v_not_def: "V \<notin> Def (fst prog) (sourcenode a)"
  thus "state_val (transfer (kind a) s) V = state_val s V"
    by -(cases prog,
    rule edge_no_Def_equal [of "fst prog" "fst (snd prog)" "snd (snd prog)"], auto)
next
  fix a s s'
  assume ve: "valid_edge prog a"
    and use_eq: "\<forall>V\<in>Use (fst prog) (sourcenode a). state_val s V = state_val s' V"
  thus "\<forall>V\<in>Def (fst prog) (sourcenode a).
    state_val (transfer (kind a) s) V = state_val (transfer (kind a) s') V"
    by -(cases prog,
      rule edge_transfer_uses_only_Use [of "fst prog" "fst(snd prog)" "snd(snd prog)"], auto)
next
  fix a s s'
  assume ve: "valid_edge prog a"
    and pred: "pred (kind a) s"
    and use_eq: "\<forall>V\<in>Use (fst prog) (sourcenode a). state_val s V = state_val s' V"
  thus "pred (kind a) s'"
    by -(cases prog,
      rule CFG_edge_Uses_pred_equal [of "fst prog" "fst(snd prog)" "snd(snd prog)"], auto)
next
  fix a a'
  assume ve_a: "valid_edge prog a"
    and ve_a': "valid_edge prog a'"
    and src_eq: "sourcenode a = sourcenode a'"
    and trg_neq: "targetnode a \<noteq> targetnode a'"
  hence "prog \<turnstile> (sourcenode a)-kind a\<rightarrow>(targetnode a)"
    and "prog \<turnstile> (sourcenode a')-kind a'\<rightarrow>(targetnode a')"
    by simp_all
  with src_eq trg_neq
  show "\<exists>Q Q'. kind a = (Q)\<^sub>\<surd> \<and> kind a' = (Q')\<^sub>\<surd> \<and> (\<forall>s. (Q s \<longrightarrow> \<not> Q' s) \<and> (Q' s \<longrightarrow> \<not> Q s))"
    apply (cases prog, auto)
    apply (erule JVM_CFG.cases, erule_tac [!] JVM_CFG.cases)
    (* This takes veeery long! *)
    by simp_all
qed

interpretation JVM_CFGExit_wf: CFGExit_wf
  "sourcenode" "targetnode" "kind" "valid_edge prog" "(_Entry_)"
  "Def (fst prog)" "Use (fst prog)" "state_val" "(_Exit_)"
proof
  show "Def (fst prog) (_Exit_) = {} \<and> Use (fst prog) (_Exit_) = {}"
    by(fastforce elim:Def.cases Use.cases)
qed

end


(*  Title:      HOL/Auth/n_germanSimp_lemma_inv__17_on_rules.thy
    Author:     Yongjian Li and Kaiqiang Duan, State Key Lab of Computer Science, Institute of Software, Chinese Academy of Sciences
    Copyright    2016 State Key Lab of Computer Science, Institute of Software, Chinese Academy of Sciences
*)

header{*The n_germanSimp Protocol Case Study*}

theory n_germanSimp_lemma_inv__17_on_rules imports n_germanSimp_lemma_on_inv__17
begin
section{*All lemmas on causal relation between inv__17*}
lemma lemma_inv__17_on_rules:
  assumes b1: "r \<in> rules N" and b2: "(\<exists> p__Inv4. p__Inv4\<le>N\<and>f=inv__17  p__Inv4)"
  shows "invHoldForRule s f r (invariants N)"
  proof -
  have c1: "(\<exists> i d. i\<le>N\<and>d\<le>N\<and>r=n_Store  i d)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvReqS N i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvReqE__part__0 N i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvReqE__part__1 N i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendInv__part__0  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendInv__part__1  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendInvAck  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvInvAck  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendGntS  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendGntE N i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvGntS  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvGntE  i)"
  apply (cut_tac b1, auto) done
    moreover {
      assume d1: "(\<exists> i d. i\<le>N\<and>d\<le>N\<and>r=n_Store  i d)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_StoreVsinv__17) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_RecvReqS N i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_RecvReqSVsinv__17) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_RecvReqE__part__0 N i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_RecvReqE__part__0Vsinv__17) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_RecvReqE__part__1 N i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_RecvReqE__part__1Vsinv__17) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_SendInv__part__0  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_SendInv__part__0Vsinv__17) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_SendInv__part__1  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_SendInv__part__1Vsinv__17) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_SendInvAck  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_SendInvAckVsinv__17) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_RecvInvAck  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_RecvInvAckVsinv__17) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_SendGntS  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_SendGntSVsinv__17) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_SendGntE N i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_SendGntEVsinv__17) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_RecvGntS  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_RecvGntSVsinv__17) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_RecvGntE  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_RecvGntEVsinv__17) done
    }

  ultimately show "invHoldForRule s f r (invariants N)"
  by satx
qed

end


(*  Title:      HOL/Auth/n_flash_lemma_on_inv__55.thy
    Author:     Yongjian Li and Kaiqiang Duan, State Key Lab of Computer Science, Institute of Software, Chinese Academy of Sciences
    Copyright    2016 State Key Lab of Computer Science, Institute of Software, Chinese Academy of Sciences
*)

header{*The n_flash Protocol Case Study*}

theory n_flash_lemma_on_inv__55 imports n_flash_base
begin
section{*All lemmas on causal relation between inv__55 and some rule r*}
lemma n_NI_Remote_Get_Nak_HomeVsinv__55:
assumes a1: "(\<exists> dst. dst\<le>N\<and>r=n_NI_Remote_Get_Nak_Home  dst)" and
a2: "(f=inv__55  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain dst where a1:"dst\<le>N\<and>r=n_NI_Remote_Get_Nak_Home  dst" apply fastforce done
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_NI_Remote_Get_PutVsinv__55:
assumes a1: "(\<exists> src dst. src\<le>N\<and>dst\<le>N\<and>src~=dst\<and>r=n_NI_Remote_Get_Put  src dst)" and
a2: "(f=inv__55  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain src dst where a1:"src\<le>N\<and>dst\<le>N\<and>src~=dst\<and>r=n_NI_Remote_Get_Put  src dst" apply fastforce done
  have "?P3 s"
  apply (cut_tac a1 a2 , simp, rule_tac x="(neg (andForm (eqn (IVar (Field (Para (Field (Ident ''Sta'') ''Proc'') dst) ''CacheState'')) (Const CACHE_E)) (eqn (IVar (Field (Field (Ident ''Sta'') ''HomeUniMsg'') ''Cmd'')) (Const UNI_Put))))" in exI, auto) done
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_NI_Remote_Get_Put_HomeVsinv__55:
assumes a1: "(\<exists> dst. dst\<le>N\<and>r=n_NI_Remote_Get_Put_Home  dst)" and
a2: "(f=inv__55  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain dst where a1:"dst\<le>N\<and>r=n_NI_Remote_Get_Put_Home  dst" apply fastforce done
  have "?P3 s"
  apply (cut_tac a1 a2 , simp, rule_tac x="(neg (andForm (eqn (IVar (Field (Field (Ident ''Sta'') ''HomeUniMsg'') ''Cmd'')) (Const UNI_Get)) (eqn (IVar (Field (Field (Ident ''Sta'') ''ShWbMsg'') ''Cmd'')) (Const SHWB_ShWb))))" in exI, auto) done
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_NI_Remote_GetX_Nak_HomeVsinv__55:
assumes a1: "(\<exists> dst. dst\<le>N\<and>r=n_NI_Remote_GetX_Nak_Home  dst)" and
a2: "(f=inv__55  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain dst where a1:"dst\<le>N\<and>r=n_NI_Remote_GetX_Nak_Home  dst" apply fastforce done
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_NI_Remote_GetX_PutXVsinv__55:
assumes a1: "(\<exists> src dst. src\<le>N\<and>dst\<le>N\<and>src~=dst\<and>r=n_NI_Remote_GetX_PutX  src dst)" and
a2: "(f=inv__55  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain src dst where a1:"src\<le>N\<and>dst\<le>N\<and>src~=dst\<and>r=n_NI_Remote_GetX_PutX  src dst" apply fastforce done
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_NI_Remote_GetX_PutX_HomeVsinv__55:
assumes a1: "(\<exists> dst. dst\<le>N\<and>r=n_NI_Remote_GetX_PutX_Home  dst)" and
a2: "(f=inv__55  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain dst where a1:"dst\<le>N\<and>r=n_NI_Remote_GetX_PutX_Home  dst" apply fastforce done
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_PI_Local_Get_GetVsinv__55:
assumes a1: "(r=n_PI_Local_Get_Get  )" and
a2: "(f=inv__55  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_PI_Local_GetX_GetX__part__0Vsinv__55:
assumes a1: "(r=n_PI_Local_GetX_GetX__part__0  )" and
a2: "(f=inv__55  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_PI_Local_GetX_GetX__part__1Vsinv__55:
assumes a1: "(r=n_PI_Local_GetX_GetX__part__1  )" and
a2: "(f=inv__55  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_NI_Nak_HomeVsinv__55:
assumes a1: "(r=n_NI_Nak_Home  )" and
a2: "(f=inv__55  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_NI_Local_PutVsinv__55:
assumes a1: "(r=n_NI_Local_Put  )" and
a2: "(f=inv__55  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_NI_Local_PutXAcksDoneVsinv__55:
assumes a1: "(r=n_NI_Local_PutXAcksDone  )" and
a2: "(f=inv__55  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_NI_FAckVsinv__55:
assumes a1: "(r=n_NI_FAck  )" and
a2: "(f=inv__55  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_NI_ShWbVsinv__55:
assumes a1: "(r=n_NI_ShWb N )" and
a2: "(f=inv__55  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_NI_Local_Get_Get__part__1Vsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_Get_Get__part__1  src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_PI_Remote_GetVsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_PI_Remote_Get  src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_GetX_PutX_9__part__0Vsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_PutX_9__part__0 N src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_PI_Local_GetX_PutX__part__0Vsinv__55:
  assumes a1: "r=n_PI_Local_GetX_PutX__part__0  " and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_WbVsinv__55:
  assumes a1: "r=n_NI_Wb  " and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_StoreVsinv__55:
  assumes a1: "\<exists> src data. src\<le>N\<and>data\<le>N\<and>r=n_Store  src data" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_GetX_PutX_5Vsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_PutX_5 N src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_GetX_GetX__part__1Vsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_GetX__part__1  src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_InvAck_3Vsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_InvAck_3 N src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_GetX_PutX_8_Home_NODE_GetVsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_PutX_8_Home_NODE_Get N src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_GetX_PutX_7_NODE_Get__part__1Vsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_PutX_7_NODE_Get__part__1 N src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_InvAck_1Vsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_InvAck_1 N src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_PI_Remote_ReplaceVsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_PI_Remote_Replace  src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_Store_HomeVsinv__55:
  assumes a1: "\<exists> data. data\<le>N\<and>r=n_Store_Home  data" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_GetX_PutX_3Vsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_PutX_3 N src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_PI_Local_ReplaceVsinv__55:
  assumes a1: "r=n_PI_Local_Replace  " and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_GetX_Nak__part__1Vsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_Nak__part__1  src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_Get_Nak__part__1Vsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_Get_Nak__part__1  src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_Get_Get__part__0Vsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_Get_Get__part__0  src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_InvAck_existsVsinv__55:
  assumes a1: "\<exists> src pp. src\<le>N\<and>pp\<le>N\<and>src~=pp\<and>r=n_NI_InvAck_exists  src pp" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_GetX_Nak__part__2Vsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_Nak__part__2  src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_PI_Remote_PutXVsinv__55:
  assumes a1: "\<exists> dst. dst\<le>N\<and>r=n_PI_Remote_PutX  dst" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_Get_Put_HeadVsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_Get_Put_Head N src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_InvVsinv__55:
  assumes a1: "\<exists> dst. dst\<le>N\<and>r=n_NI_Inv  dst" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_PI_Local_PutXVsinv__55:
  assumes a1: "r=n_PI_Local_PutX  " and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_Get_Nak__part__2Vsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_Get_Nak__part__2  src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_GetX_GetX__part__0Vsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_GetX__part__0  src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_GetX_PutX_6Vsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_PutX_6 N src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_PI_Local_Get_PutVsinv__55:
  assumes a1: "r=n_PI_Local_Get_Put  " and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_PI_Local_GetX_PutX_HeadVld__part__0Vsinv__55:
  assumes a1: "r=n_PI_Local_GetX_PutX_HeadVld__part__0 N " and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_GetX_PutX_11Vsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_PutX_11 N src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_ReplaceVsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Replace  src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_GetX_PutX_1Vsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_PutX_1 N src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_GetX_PutX_8_HomeVsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_PutX_8_Home N src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_GetX_PutX_7__part__0Vsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_PutX_7__part__0 N src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Remote_GetX_NakVsinv__55:
  assumes a1: "\<exists> src dst. src\<le>N\<and>dst\<le>N\<and>src~=dst\<and>r=n_NI_Remote_GetX_Nak  src dst" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_NakVsinv__55:
  assumes a1: "\<exists> dst. dst\<le>N\<and>r=n_NI_Nak  dst" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_GetX_PutX_9__part__1Vsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_PutX_9__part__1 N src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_PI_Remote_GetXVsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_PI_Remote_GetX  src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_PI_Local_GetX_PutX__part__1Vsinv__55:
  assumes a1: "r=n_PI_Local_GetX_PutX__part__1  " and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Remote_PutXVsinv__55:
  assumes a1: "\<exists> dst. dst\<le>N\<and>r=n_NI_Remote_PutX  dst" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Remote_PutVsinv__55:
  assumes a1: "\<exists> dst. dst\<le>N\<and>r=n_NI_Remote_Put  dst" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_GetX_PutX_10Vsinv__55:
  assumes a1: "\<exists> src pp. src\<le>N\<and>pp\<le>N\<and>src~=pp\<and>r=n_NI_Local_GetX_PutX_10 N src pp" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_GetX_PutX_8Vsinv__55:
  assumes a1: "\<exists> src pp. src\<le>N\<and>pp\<le>N\<and>src~=pp\<and>r=n_NI_Local_GetX_PutX_8 N src pp" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_Get_PutVsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_Get_Put  src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_GetX_PutX_8_NODE_GetVsinv__55:
  assumes a1: "\<exists> src pp. src\<le>N\<and>pp\<le>N\<and>src~=pp\<and>r=n_NI_Local_GetX_PutX_8_NODE_Get N src pp" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_GetX_PutX_2Vsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_PutX_2 N src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_GetX_Nak__part__0Vsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_Nak__part__0  src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_InvAck_exists_HomeVsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_InvAck_exists_Home  src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Replace_HomeVsinv__55:
  assumes a1: "r=n_NI_Replace_Home  " and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_GetX_PutX_7__part__1Vsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_PutX_7__part__1 N src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Remote_Get_NakVsinv__55:
  assumes a1: "\<exists> src dst. src\<le>N\<and>dst\<le>N\<and>src~=dst\<and>r=n_NI_Remote_Get_Nak  src dst" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Nak_ClearVsinv__55:
  assumes a1: "r=n_NI_Nak_Clear  " and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_Get_Put_DirtyVsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_Get_Put_Dirty  src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_Get_Nak__part__0Vsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_Get_Nak__part__0  src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_GetX_PutX_10_HomeVsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_PutX_10_Home N src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_InvAck_2Vsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_InvAck_2 N src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_PI_Local_GetX_PutX_HeadVld__part__1Vsinv__55:
  assumes a1: "r=n_PI_Local_GetX_PutX_HeadVld__part__1 N " and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_GetX_PutX_4Vsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_PutX_4 N src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_GetX_PutX_7_NODE_Get__part__0Vsinv__55:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_PutX_7_NODE_Get__part__0 N src" and
  a2: "(f=inv__55  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

end


(*  Title:      HOL/Auth/n_german_lemma_inv__34_on_rules.thy
    Author:     Yongjian Li and Kaiqiang Duan, State Key Lab of Computer Science, Institute of Software, Chinese Academy of Sciences
    Copyright    2016 State Key Lab of Computer Science, Institute of Software, Chinese Academy of Sciences
*)

header{*The n_german Protocol Case Study*}

theory n_german_lemma_inv__34_on_rules imports n_german_lemma_on_inv__34
begin
section{*All lemmas on causal relation between inv__34*}
lemma lemma_inv__34_on_rules:
  assumes b1: "r \<in> rules N" and b2: "(\<exists> p__Inv4. p__Inv4\<le>N\<and>f=inv__34  p__Inv4)"
  shows "invHoldForRule s f r (invariants N)"
  proof -
  have c1: "(\<exists> j. j\<le>N\<and>r=n_SendReqS  j)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendReqEI  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendReqES  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvReq N i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendInvE  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendInvS  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendInvAck  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvInvAck  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendGntS  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendGntE N i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvGntS  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvGntE  i)\<or>
    (\<exists> i d. i\<le>N\<and>d\<le>N\<and>r=n_Store  i d)"
  apply (cut_tac b1, auto) done
    moreover {
      assume d1: "(\<exists> j. j\<le>N\<and>r=n_SendReqS  j)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_SendReqSVsinv__34) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_SendReqEI  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_SendReqEIVsinv__34) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_SendReqES  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_SendReqESVsinv__34) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_RecvReq N i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_RecvReqVsinv__34) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_SendInvE  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_SendInvEVsinv__34) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_SendInvS  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_SendInvSVsinv__34) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_SendInvAck  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_SendInvAckVsinv__34) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_RecvInvAck  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_RecvInvAckVsinv__34) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_SendGntS  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_SendGntSVsinv__34) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_SendGntE N i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_SendGntEVsinv__34) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_RecvGntS  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_RecvGntSVsinv__34) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_RecvGntE  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_RecvGntEVsinv__34) done
    }

    moreover {
      assume d1: "(\<exists> i d. i\<le>N\<and>d\<le>N\<and>r=n_Store  i d)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_StoreVsinv__34) done
    }

  ultimately show "invHoldForRule s f r (invariants N)"
  by satx
qed

end


(*  Title:      JinjaThreads/J/JWellForm.thy
    Author:     Tobias Nipkow, Andreas Lochbihler
*)

section \<open>Well-formedness Constraints\<close>

theory JWellForm
imports
  WWellForm
  WellType
  DefAss
begin

definition wf_J_mdecl :: "'addr J_prog \<Rightarrow> cname \<Rightarrow> 'addr J_mb mdecl \<Rightarrow> bool"
where
  "wf_J_mdecl P C  \<equiv>  \<lambda>(M,Ts,T,(pns,body)).
  length Ts = length pns \<and>
  distinct pns \<and>
  this \<notin> set pns \<and>
  (\<exists>T'. P,[this\<mapsto>Class C,pns[\<mapsto>]Ts] \<turnstile> body :: T' \<and> P \<turnstile> T' \<le> T) \<and>
  \<D> body \<lfloor>{this} \<union> set pns\<rfloor>"

lemma wf_J_mdecl[simp]:
  "wf_J_mdecl P C (M,Ts,T,pns,body) \<equiv>
  (length Ts = length pns \<and>
  distinct pns \<and>
  this \<notin> set pns \<and>
  (\<exists>T'. P,[this\<mapsto>Class C,pns[\<mapsto>]Ts] \<turnstile> body :: T' \<and> P \<turnstile> T' \<le> T) \<and>
  \<D> body \<lfloor>{this} \<union> set pns\<rfloor>)"
(*<*)by(simp add:wf_J_mdecl_def)(*>*)

abbreviation wf_J_prog :: "'addr J_prog \<Rightarrow> bool"
where "wf_J_prog == wf_prog wf_J_mdecl"

lemma wf_prog_wwf_prog: "wf_J_prog P \<Longrightarrow> wwf_J_prog P"
by(erule wf_prog_lift)(erule wf_mdecl_wwf_mdecl)

subsection \<open>Code generation\<close>

definition typeable_with :: "'addr J_prog \<Rightarrow> env \<Rightarrow> 'addr expr \<Rightarrow> ty \<Rightarrow> bool"
where [simp]: "typeable_with P E e T \<longleftrightarrow> (\<exists>T'. P,E \<turnstile> e ::' T' \<and> P \<turnstile> T' \<le> T)"

definition wf_J_mdecl' :: "'addr J_prog \<Rightarrow> cname \<Rightarrow> 'addr J_mb mdecl \<Rightarrow> bool"
where
  "wf_J_mdecl' P C  \<equiv>  \<lambda>(M,Ts,T,(pns,body)).
  length Ts = length pns \<and>
  distinct pns \<and>
  this \<notin> set pns \<and>
  typeable_with P [this\<mapsto>Class C,pns[\<mapsto>]Ts] body T \<and>
  \<D> body \<lfloor>{this} \<union> set pns\<rfloor>"

definition wf_J_prog' :: "'addr J_prog \<Rightarrow> bool"
where "wf_J_prog' = wf_prog wf_J_mdecl'"

lemma wf_J_prog_wf_J_prog':
  "wf_J_prog P \<Longrightarrow> wf_J_prog' P"
unfolding wf_J_prog'_def
apply(erule wf_prog_lift)
apply(clarsimp simp add: wf_J_mdecl'_def)
apply(drule (1) WT_into_WT_code)
apply(auto simp add: ran_def map_upds_def dest!: map_of_SomeD set_zip_rightD)
done

lemma wf_J_prog'_wf_J_prog:
  "wf_J_prog' P \<Longrightarrow> wf_J_prog P"
unfolding wf_J_prog'_def
apply(erule wf_prog_lift)
apply(clarsimp simp add: wf_J_mdecl'_def)
apply(drule (1) WT_code_into_WT)
apply(auto simp add: ran_def map_upds_def dest!: map_of_SomeD set_zip_rightD)
done

lemma wf_J_prog_eq_wf_J_prog' [code_unfold]:
  "wf_J_prog = wf_J_prog'"
by(blast intro: ext wf_J_prog'_wf_J_prog wf_J_prog_wf_J_prog' del: equalityI)

code_pred
  (modes: i \<Rightarrow> i \<Rightarrow> i \<Rightarrow> i \<Rightarrow> bool)
  [inductify]
  typeable_with
.

text \<open>Formal code generation test\<close>
ML_val \<open>@{code wf_J_prog'}\<close>

end


(*  Title:       variants/b_fwdrreps/Aodv_Message.thy
    License:     BSD 2-Clause. See LICENSE.
    Author:      Timothy Bourke, Inria
*)

section "AODV protocol messages"

theory B_Aodv_Message
imports B_Fwdrreps
begin

datatype msg =
    Rreq nat rreqid ip sqn k ip sqn ip
  | Rrep nat ip sqn ip ip
  | Rerr "ip \<rightharpoonup> sqn" ip
  | Newpkt data ip
  | Pkt data ip ip

instantiation msg :: msg
begin
  definition newpkt_def [simp]: "newpkt \<equiv> \<lambda>(d, dip). Newpkt d dip"
  definition eq_newpkt_def: "eq_newpkt m \<equiv> case m of Newpkt d dip \<Rightarrow> True | _ \<Rightarrow> False"

  instance by intro_classes (simp add: eq_newpkt_def)
end

text \<open>The @{type msg} type models the different messages used within AODV.
      The instantiation as a @{class msg} is a technicality due to the special
      treatment of @{term newpkt} messages in the AWN SOS rules.
      This use of classes allows a clean separation of the AWN-specific definitions
      and these AODV-specific definitions.\<close>

definition rreq :: "nat \<times> rreqid \<times> ip \<times> sqn \<times> k \<times> ip \<times> sqn \<times> ip \<Rightarrow> msg"
  where "rreq \<equiv> \<lambda>(hops, rreqid, dip, dsn, dsk, oip, osn, sip).
                    Rreq hops rreqid dip dsn dsk oip osn sip"

lemma rreq_simp [simp]:
  "rreq(hops, rreqid, dip, dsn, dsk, oip, osn, sip) =  Rreq hops rreqid dip dsn dsk oip osn sip"
  unfolding rreq_def by simp

definition rrep :: "nat \<times> ip \<times> sqn \<times> ip \<times> ip \<Rightarrow> msg"
  where "rrep \<equiv> \<lambda>(hops, dip, dsn, oip, sip). Rrep hops dip dsn oip sip"

lemma rrep_simp [simp]:
  "rrep(hops, dip, dsn, oip, sip) = Rrep hops dip dsn oip sip"
  unfolding rrep_def by simp

definition rerr :: "(ip \<rightharpoonup> sqn) \<times> ip \<Rightarrow> msg"
  where "rerr \<equiv> \<lambda>(dests, sip). Rerr dests sip"

lemma rerr_simp [simp]:
  "rerr(dests, sip) = Rerr dests sip"
  unfolding rerr_def by simp

lemma not_eq_newpkt_rreq [simp]: "\<not>eq_newpkt (Rreq hops rreqid dip dsn dsk oip osn sip)"
  unfolding eq_newpkt_def by simp

lemma not_eq_newpkt_rrep [simp]: "\<not>eq_newpkt (Rrep hops dip dsn oip sip)"
  unfolding eq_newpkt_def by simp

lemma not_eq_newpkt_rerr [simp]: "\<not>eq_newpkt (Rerr dests sip)"
  unfolding eq_newpkt_def by simp

lemma not_eq_newpkt_pkt [simp]: "\<not>eq_newpkt (Pkt d dip sip)"
  unfolding eq_newpkt_def by simp

definition pkt :: "data \<times> ip \<times> ip \<Rightarrow> msg"
  where "pkt \<equiv> \<lambda>(d, dip, sip). Pkt d dip sip"

lemma pkt_simp [simp]:
  "pkt(d, dip, sip) = Pkt d dip sip"
  unfolding pkt_def by simp

end