(*
 * Copyright 2014, General Dynamics C4 Systems
 *
 * SPDX-License-Identifier: GPL-2.0-only
 *)

(*
    Properties of machine operations.
*)

theory Machine_R
imports Bits_R
begin

definition "irq_state_independent_H (P :: kernel_state \<Rightarrow> bool)\<equiv>
              \<forall>(f :: nat \<Rightarrow> nat) (s :: kernel_state). P s \<longrightarrow> P (s\<lparr>ksMachineState := ksMachineState s
                                \<lparr>irq_state := f (irq_state (ksMachineState s))\<rparr>\<rparr>)"

lemma irq_state_independent_HI[intro!, simp]:
  "\<lbrakk>\<And>s f. P (s\<lparr>ksMachineState := ksMachineState s
              \<lparr>irq_state := f (irq_state (ksMachineState s))\<rparr>\<rparr>) = P s\<rbrakk>
   \<Longrightarrow> irq_state_independent_H P"
  by (simp add: irq_state_independent_H_def)

context begin interpretation Arch . (*FIXME: arch_split*)

lemma dmo_getirq_inv[wp]:
  "irq_state_independent_H P \<Longrightarrow> \<lbrace>P\<rbrace> doMachineOp (getActiveIRQ in_kernel) \<lbrace>\<lambda>rv. P\<rbrace>"
  apply (simp add: getActiveIRQ_def doMachineOp_def split_def exec_gets
                   select_f_select[simplified liftM_def]
                   select_modify_comm gets_machine_state_modify)
  apply wp
  apply (clarsimp simp: irq_state_independent_H_def in_monad return_def split: if_splits)
  done

lemma getActiveIRQ_masked:
  "\<lbrace>\<lambda>s. valid_irq_masks' table (irq_masks s)\<rbrace> getActiveIRQ in_kernel
  \<lbrace>\<lambda>rv s. \<forall>irq. rv = Some irq \<longrightarrow> table irq \<noteq> IRQInactive\<rbrace>"
  apply (simp add: getActiveIRQ_def)
  apply wp
  apply (clarsimp simp: valid_irq_masks'_def)
  done

lemma dmo_maskInterrupt:
  "\<lbrace>\<lambda>s. P (ksMachineState_update (irq_masks_update (\<lambda>t. t (irq := m))) s)\<rbrace>
  doMachineOp (maskInterrupt m irq) \<lbrace>\<lambda>_. P\<rbrace>"
  apply (simp add: doMachineOp_def split_def)
  apply wp
  apply (clarsimp simp: maskInterrupt_def in_monad)
  apply (erule rsubst [where P=P])
  apply simp
  done

lemma dmo_maskInterrupt_True:
  "\<lbrace>invs'\<rbrace> doMachineOp (maskInterrupt True irq) \<lbrace>\<lambda>_. invs'\<rbrace>"
  apply (wp dmo_maskInterrupt)
  apply (clarsimp simp: invs'_def valid_state'_def)
  apply (simp add: valid_irq_masks'_def valid_machine_state'_def
                   ct_not_inQ_def ct_idle_or_in_cur_domain'_def tcb_in_cur_domain'_def)
  done

lemma setIRQState_irq_states':
  "\<lbrace>valid_irq_states'\<rbrace>
      setIRQState state irq
   \<lbrace>\<lambda>rv. valid_irq_states'\<rbrace>"
  apply (simp add: setIRQState_def setInterruptState_def getInterruptState_def)
  apply (wp dmo_maskInterrupt)
  apply (simp add: valid_irq_masks'_def)
  done

lemma getActiveIRQ_le_maxIRQ:
  "\<lbrace>irqs_masked' and valid_irq_states'\<rbrace> doMachineOp (getActiveIRQ in_kernel) \<lbrace>\<lambda>rv s. \<forall>x. rv = Some x \<longrightarrow> x \<le> maxIRQ\<rbrace>"
  apply (simp add: doMachineOp_def split_def)
  apply wp
  apply clarsimp
  apply (drule use_valid, rule getActiveIRQ_le_maxIRQ')
   prefer 2
   apply simp
  apply (simp add: irqs_masked'_def valid_irq_states'_def)
  done

(* FIXME: follows already from getActiveIRQ_le_maxIRQ *)
lemma getActiveIRQ_neq_Some0xFF:
  "\<lbrace>\<top>\<rbrace> doMachineOp (getActiveIRQ in_kernel) \<lbrace>\<lambda>rv s. rv \<noteq> Some 0x3FF\<rbrace>"
  apply (simp add: doMachineOp_def split_def)
  apply wp
  apply clarsimp
  apply (drule use_valid, rule getActiveIRQ_neq_Some0xFF')
   apply auto
  done

end
end


(*
 * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
 *
 * SPDX-License-Identifier: BSD-2-Clause
 *)

theory list_reverse
imports "CParser.CTranslation" "$L4V_ARCH/imports/MachineWords"
begin

declare hrs_simps [simp add]
declare exists_left [simp add]
declare sep_conj_ac [simp add]

primrec
  list :: "machine_word list \<Rightarrow> machine_word ptr \<Rightarrow> heap_state \<Rightarrow> bool"
where
  "list [] i = (\<lambda>s. i=NULL \<and> \<box> s)"
| "list (x#xs) i = (\<lambda>s. i=Ptr x \<and> x\<noteq>0 \<and> (\<exists>j. ((i \<mapsto> j) \<and>\<^sup>* list xs (Ptr j)) s))"

lemma list_empty [simp]:
  shows "list xs NULL = (\<lambda>s. xs = [] \<and> \<box> s)"
  by (cases xs) (auto dest!: sep_conj_mapD)

declare sep_conj_com [simp del]
declare sep_conj_left_com [simp del]

external_file "list_reverse.c"
install_C_file memsafe "list_reverse.c"

thm list_reverse_global_addresses.reverse_body_def

lemma (in list_reverse_global_addresses)
  shows "reverse_spec"
apply (unfold reverse_spec_def)
apply (hoare_rule HoarePartial.ProcNoRec1)
apply (hoare_rule anno = "reverse_invs_body zs" in HoarePartial.annotateI)
 prefer 2
 apply (simp add: whileAnno_def reverse_invs_body_def)
apply(subst reverse_invs_body_def)
apply(unfold sep_app_def)
apply vcg
  apply (fold lift_def)
  apply(force simp: sep_conj_com)
 apply clarsimp
 apply(case_tac xs)
  apply clarsimp
 apply clarsimp
 apply sep_exists_tac
 apply clarsimp
 apply sep_point_tac
 apply rule
  apply(erule sep_map'_g)
 apply rule
  apply(erule sep_map'_ptr_safe)
 apply(rule_tac x="lista" in exI)
 apply (simp add: ucast_id)
 apply sep_exists_tac
 apply(rule_tac x=j in exI)
 apply simp
 apply(rule sep_heap_update_global)
 apply(erule sep_conj_impl)
  apply simp
 apply(sep_select_tac "list lista _")
 apply(erule sep_conj_impl)
  apply(subgoal_tac "lift a (Ptr aa) = ja")
   apply simp
  apply(erule_tac d=b in sep_map'_lift)
 apply simp
apply(simp add: sep_conj_com)
done

declare hrs_simps [simp del]

lemma (in list_reverse_global_addresses) mem_safe_reverse_invs_body:
  "mem_safe (reverse_invs_body \<alpha>) \<Gamma>"
apply(unfold reverse_invs_body_def creturn_def)
apply(subst mem_safe_restrict)
apply(rule intra_mem_safe)
apply(auto simp: whileAnno_def intra_sc)
done

declare hrs_simps [simp add]

lemma (in list_reverse_global_addresses) sep_frame_reverse_invs_body:
  "\<lbrakk> \<forall>\<sigma>. \<Gamma> \<turnstile> \<lbrace>\<sigma>. (P (f \<acute>(\<lambda>x. x)))\<^bsup>sep\<^esup> \<rbrace> reverse_invs_body \<alpha> \<lbrace> (Q (g \<sigma> \<acute>(\<lambda>x. x)))\<^bsup>sep\<^esup> \<rbrace>;
      htd_ind f; htd_ind g; \<forall>s. htd_ind (g s) \<rbrakk> \<Longrightarrow>
      \<forall>\<sigma>. \<Gamma> \<turnstile> \<lbrace>\<sigma>. (P (f \<acute>(\<lambda>x. x)) \<and>\<^sup>* R (h \<acute>(\<lambda>x. x)))\<^bsup>sep\<^esup> \<rbrace> reverse_invs_body \<alpha>
              \<lbrace> (Q (g \<sigma> \<acute>(\<lambda>x. x)) \<and>\<^sup>* R (h \<sigma>))\<^bsup>sep\<^esup> \<rbrace>"
apply(simp only: sep_app_def)
apply(rule sep_frame)
    apply simp+
apply(rule mem_safe_reverse_invs_body)
done

end


section \<open>Algorithms on Nondeterministic Generalized Büchi Automata\<close>

theory NGBA_Algorithms
imports
  NBA_Algorithms
  NGBA_Implement
  NBA_Combine
begin

  subsection \<open>Implementations\<close>

  context
  begin

    interpretation autoref_syn by this

    (* TODO: move *)
    lemma degen_param[param, autoref_rules]: "(degen, degen) \<in> \<langle>S \<rightarrow> bool_rel\<rangle> list_rel \<rightarrow> S \<times>\<^sub>r nat_rel \<rightarrow> bool_rel"
    proof (intro fun_relI)
      fix cs ds ak bl
      assume "(cs, ds) \<in> \<langle>S \<rightarrow> bool_rel\<rangle> list_rel" "(ak, bl) \<in>  S \<times>\<^sub>r nat_rel"
      then show "(degen cs ak, degen ds bl) \<in> bool_rel"
        unfolding degen_def list_rel_def fun_rel_def list_all2_conv_all_nth
        by (cases "snd ak < length cs") (auto 0 3)
    qed

    (* TODO: move *)
    lemmas [param] = null_transfer[unfolded pred_bool_Id, to_set]

    (* TODO: move *)
    lemma count_param[param, autoref_rules]: "(Degeneralization.count, Degeneralization.count) \<in>
      \<langle>A \<rightarrow> bool_rel\<rangle> list_rel \<rightarrow> A \<rightarrow> nat_rel \<rightarrow> nat_rel"
      unfolding count_def null_def[symmetric] by parametricity

    (* TODO: why do we need this? *)
    lemma degeneralize_alt_def: "degeneralize A = nba
      (ngba.alphabet A)
      ((\<lambda> p. (p, 0)) ` ngba.initial A)
      (\<lambda> a (p, k). (\<lambda> q. (q, Degeneralization.count (ngba.accepting A) p k)) ` ngba.transition A a p)
      (degen (ngba.accepting A))"
      unfolding degeneralization.degeneralize_def by auto

    schematic_goal ngba_degeneralize: "(?f :: ?'a, degeneralize) \<in> ?R"
      unfolding degeneralize_alt_def by autoref
    concrete_definition ngba_degeneralize uses ngba_degeneralize
    lemmas ngba_degeneralize_refine[autoref_rules] = ngba_degeneralize.refine

    schematic_goal nba_intersect':
      assumes [autoref_rules]: "(seq, HOL.eq) \<in> L \<rightarrow> L \<rightarrow> bool_rel"
      shows "(?f, intersect') \<in> \<langle>L, S\<rangle> nbai_nba_rel \<rightarrow> \<langle>L, T\<rangle> nbai_nba_rel \<rightarrow> \<langle>L, S \<times>\<^sub>r T\<rangle> ngbai_ngba_rel"
      unfolding intersection.product_def by autoref
    concrete_definition nba_intersect' uses nba_intersect'
    lemma nba_intersect'_refine[autoref_rules]:
      assumes "GEN_OP seq HOL.eq (L \<rightarrow> L \<rightarrow> bool_rel)"
      shows "(nba_intersect' seq, intersect') \<in>
        \<langle>L, S\<rangle> nbai_nba_rel \<rightarrow> \<langle>L, T\<rangle> nbai_nba_rel \<rightarrow> \<langle>L, S \<times>\<^sub>r T\<rangle> ngbai_ngba_rel"
      using nba_intersect'.refine assms unfolding autoref_tag_defs by this

  end

end


theory ValidState
imports Semantics
begin

lemma valid_state_valid_accounts : "valid_state state \<Longrightarrow> valid_map (accounts state)"
  apply (cases state)
  by simp

lemma valid_state_valid_choices : "valid_state state \<Longrightarrow> valid_map (choices state)"
  apply (cases state)
  by simp

lemma valid_state_valid_boundValues : "valid_state state \<Longrightarrow> valid_map (boundValues state)"
  apply (cases state)
  by simp

lemma refundOne_preserves_valid_map_accounts :
  "valid_map oldAccounts \<Longrightarrow>
   refundOne oldAccounts = Some ((party, money), newAccounts)
   \<Longrightarrow> valid_map newAccounts"
  apply (induction oldAccounts rule:refundOne.induct)
  apply (metis MList.sublist_valid Pair_inject option.inject refundOne.simps(1))
  by simp

lemma reductionStep_preserves_valid_state_Refund :
  "valid_state state \<Longrightarrow>
   reduceContractStep env state Close = Reduced wa ef newState newCont \<Longrightarrow>
   state = \<lparr>accounts = oldAccounts, choices = oldChoices, boundValues = oldBoundValues, minTime = oldMinTime\<rparr> \<Longrightarrow>
   newState = \<lparr>accounts = newAccounts, choices = newChoices, boundValues = newBoundValues, minTime = newMinTime\<rparr> \<Longrightarrow>
   valid_state newState"
  apply (cases "refundOne oldAccounts")
  using refundOne_preserves_valid_map_accounts by auto

lemma updateMoneyInAccount_preserves_valid_map :
  "valid_map accs \<Longrightarrow>
   valid_map (updateMoneyInAccount accId tok ammount accs)"
  using MList.delete_valid MList.insert_valid by force

lemma giveMoney_preserves_valid_map :
  "valid_map accs \<Longrightarrow>
   giveMoney src payee tok ammount accs = (a, newAccs) \<Longrightarrow>
   valid_map newAccs"
  apply (cases payee)
  using updateMoneyInAccount_preserves_valid_map by auto

lemma reductionStep_preserves_valid_state_Pay :
  "valid_state state \<Longrightarrow> reduceContractStep env state (Pay accId payee tok val cont) = Reduced wa ef newState newCont \<Longrightarrow>
   valid_state newState"
  apply (simp only:reduceContractStep.simps)
  apply (cases "evalValue env state val \<le> 0")
  apply simp
  apply (cases "giveMoney accId payee tok (min (moneyInAccount accId tok (accounts state)) (evalValue env state val))
           (updateMoneyInAccount accId tok (moneyInAccount accId tok (accounts state) - min (moneyInAccount accId tok (accounts state)) (evalValue env state val))
             (accounts state))")
  apply (simp only:Product_Type.prod.case if_False Let_def)
  by (metis ReduceStepResult.inject State.select_convs(1) State.select_convs(2) State.select_convs(3) State.surjective State.update_convs(1) giveMoney_preserves_valid_map updateMoneyInAccount_preserves_valid_map valid_state.simps)

lemma reductionStep_preserves_valid_state :
  "valid_state state \<Longrightarrow>
   reduceContractStep env state cont = Reduced wa ef newState newCont \<Longrightarrow>
   valid_state newState"
  apply (cases cont)
  apply (metis (full_types) State.surjective old.unit.exhaust reductionStep_preserves_valid_state_Refund)
  using reductionStep_preserves_valid_state_Pay apply blast
  apply simp
  apply (smt ReduceStepResult.distinct(1) ReduceStepResult.distinct(3) ReduceStepResult.inject case_prod_unfold reduceContractStep.simps(4))
  apply (cases "state")
  apply (cases "newState")
  apply simp
  apply (metis MList.insert_valid ReduceStepResult.inject State.ext_inject valid_map.simps)
  by simp

lemma reductionLoop_preserves_valid_state_aux :
  "(\<And>x11 x12 x13 x14 x xa.
       reduceContractStep env state contract = Reduced x11 x12 x13 x14 \<Longrightarrow>
       x = (if x11 = ReduceNoWarning then warnings else x11 # warnings) \<Longrightarrow>
       xa = (case x12 of ReduceNoPayment \<Rightarrow> payments | ReduceWithPayment payment \<Rightarrow> payment # payments) \<Longrightarrow>
       valid_state x13 \<Longrightarrow> reductionLoop True env x13 x14 x xa = ContractQuiescent newReduced newWa newPa newState newCont \<Longrightarrow> valid_state newState) \<Longrightarrow>
   valid_state state \<Longrightarrow> reductionLoop reduced env state contract warnings payments = ContractQuiescent newReduced newWa newPa newState newCont \<Longrightarrow> valid_state newState"
  apply (simp only:reductionLoop.simps [of True env state contract warnings payments])
  apply (cases "reduceContractStep env state contract")
  apply (simp only:HOL.Let_def reductionLoop.simps[of reduced])
  apply (metis (no_types, lifting) ReduceStepResult.simps(8) reductionStep_preserves_valid_state)
  by simp_all

lemma reductionLoop_preserves_valid_state :
  "valid_state state \<Longrightarrow>
   reductionLoop oldReduced env state cont wa pa =
     ContractQuiescent newReduced newWa newPa newState newCont \<Longrightarrow>
   valid_state newState"
  apply (induction oldReduced env state cont wa pa rule:reductionLoop.induct)
  using reductionLoop_preserves_valid_state_aux by blast

lemma applyCases_preserves_valid_state :
  "valid_state state \<Longrightarrow>
   applyCases env state input caseList = Applied wa newState newCont \<Longrightarrow>
   valid_state newState"
  apply (induction env state input caseList rule:applyCases.induct)
  apply (simp only:Let_def addMoneyToAccount.simps applyCases.simps valid_state.simps)
  apply (smt ApplyResult.inject State.select_convs(1) State.select_convs(2) State.select_convs(3) State.surjective State.update_convs(1) updateMoneyInAccount_preserves_valid_map)
  apply (simp only:Let_def applyCases.simps valid_state.simps)
  apply (metis ApplyResult.inject MList.insert_valid State.select_convs(1) State.select_convs(2) State.select_convs(3) State.surjective State.update_convs(2))
  apply (metis ApplyResult.inject applyCases.simps(3))
  by auto

lemma applyInput_preserves_valid_state :
  "valid_state state \<Longrightarrow>
   applyInput env state headInp redCon = Applied intWa intState intCont \<Longrightarrow>
   valid_state intState"
  apply (cases redCon)
  apply (simp only:applyInput.simps)
  apply simp
  apply simp
  apply simp
  apply (metis applyCases_preserves_valid_state applyInput.simps(1))
  apply simp
  by simp

lemma applyAllLoop_preserves_valid_state :
  "valid_state state \<Longrightarrow>
   applyAllLoop reduced env state cont inp wa pa = ApplyAllSuccess newReduced newWa newPa newState newCont \<Longrightarrow>
   valid_state newState"
  apply (induct reduced env state cont inp wa pa rule:applyAllLoop.induct)
  subgoal for reduced env state contract inputs warnings payments
    apply (simp only:applyAllLoop.simps [of reduced env state contract inputs warnings payments])
    apply (cases inputs)
    apply (simp only:list.case)
    apply (cases "reduceContractUntilQuiescent env state contract")
    apply (metis (no_types, lifting) ApplyAllResult.inject ReduceResult.simps(4) reduceContractUntilQuiescent.simps reductionLoop_preserves_valid_state)
    apply simp
    apply (simp only:list.case)
    apply (cases "reduceContractUntilQuiescent env state contract")
    apply (simp only:ReduceResult.case)
    subgoal for a list x11 x12 x13 x14 x15
      apply (cases "applyInput env x14 a x15")
      apply (simp only:ApplyResult.case)
      apply (metis applyInput_preserves_valid_state reduceContractUntilQuiescent.simps reductionLoop_preserves_valid_state)
      by simp
    by simp
  done

lemma applyAllInputs_preserves_valid_state :
  "valid_state state \<Longrightarrow>
   applyAllInputs env state cont inp = ApplyAllSuccess reduced wa pa newState newCont \<Longrightarrow>
   valid_state newState"
  by (metis applyAllInputs.simps applyAllLoop_preserves_valid_state)

lemma fixInterval_preserves_valid_state :
  "valid_state state \<Longrightarrow>
   fixInterval (a, b) state = IntervalTrimmed newEnv newState \<Longrightarrow>
   valid_state newState"
  apply (simp only:fixInterval.simps)
  apply (cases "b < a")
  apply simp
  apply (cases "b < minTime state")
  apply simp
  apply (simp del:valid_state.simps add:Let_def)
  by auto

lemma computeTransaction_preserves_valid_state_aux :
  "valid_state state \<Longrightarrow>
   computeTransaction  \<lparr>interval = intervalI, inputs = inputsI\<rparr> state cont
      = TransactionOutput \<lparr>txOutWarnings = txOutWarningsO, txOutPayments = txOutPaymentsO, txOutState = txOutStateO, txOutContract = txOutContractO\<rparr> \<Longrightarrow>
   valid_state (txOutStateO)"
  apply (simp only:computeTransaction.simps Let_def)
  apply (cases "fixInterval (interval \<lparr>interval = intervalI, inputs = inputsI\<rparr>) state")
  apply (simp only:IntervalResult.case)
  subgoal for env sta
    apply (cases "applyAllInputs env sta cont (inputs \<lparr>interval = intervalI, inputs = inputsI\<rparr>)")
    apply (simp only:ApplyAllResult.case)
    apply (metis TransactionOutput.distinct(1) TransactionOutput.inject(1) TransactionOutputRecord.select_convs(3) applyAllInputs.simps applyAllLoop_preserves_valid_state fixInterval_preserves_valid_state small_lazy'.cases)
    apply simp
    by simp
  by simp

lemma computeTransaction_preserves_valid_state :
  "valid_state state \<Longrightarrow> computeTransaction tran state cont = TransactionOutput out \<Longrightarrow> valid_state (txOutState out) "
  by (metis (full_types) Transaction.surjective TransactionOutputRecord.surjective computeTransaction_preserves_valid_state_aux old.unit.exhaust)

lemma playTraceAux_preserves_valid_state :
  "valid_state (txOutState txIn) \<Longrightarrow>
   playTraceAux txIn transList = TransactionOutput txOut \<Longrightarrow>
   valid_state (txOutState txOut)"
  apply (induction txIn transList rule:playTraceAux.induct)
  apply simp
  apply (cases txOut)
  apply (simp del:valid_state.simps computeTransaction.simps add:Let_def)
  by (smt TransactionOutput.case(1) TransactionOutput.case(2) TransactionOutput.exhaust computeTransaction_preserves_valid_state)

lemma empty_state_valid_state :
  "valid_state (emptyState sl)"
  by (metis MList.valid_empty State.select_convs(1) State.select_convs(2) State.select_convs(3) emptyState.elims valid_state.simps)

lemma playTrace_preserves_valid_state :
  "playTrace sl c transList = TransactionOutput txOut \<Longrightarrow>
   valid_state (txOutState txOut)"
  apply (simp only:playTrace.simps)
  by (metis MList.valid_empty State.select_convs(1) State.select_convs(2) State.select_convs(3) TransactionOutputRecord.select_convs(3) emptyState.elims playTraceAux_preserves_valid_state valid_state.simps)

end


section \<open>Array-Blocks --- Reasoning Setup\<close>
theory Sep_Array_Block_RS
imports "../basic/LLVM_Basic_Main" Sep_Block_Allocator_RS
begin

type_synonym 'aval ablock = "nat \<Rightarrow> 'aval"

instantiation baddr :: (this_addr) addr_algebra begin
  definition "abase \<equiv> \<lambda>BADDR i va \<Rightarrow> va=this_addr"
  definition "(~\<^sub>a) \<equiv> \<lambda>BADDR i1 va1 \<Rightarrow> \<lambda>BADDR i2 va2 \<Rightarrow> va1=this_addr \<and> va2=this_addr"
  definition "(-\<^sub>a) \<equiv> \<lambda>BADDR i1 va1 \<Rightarrow> \<lambda>BADDR i2 va2 \<Rightarrow> i1 - i2"
  definition "(+\<^sub>a) \<equiv> \<lambda>BADDR i va \<Rightarrow> \<lambda>j. BADDR (i+j) va"

  lemma abase_baddr_simp[simp]: "abase (BADDR i va) \<longleftrightarrow> va=this_addr"
    by (simp add: abase_baddr_def)
  lemma acompat_baddr_simp[simp]: "BADDR i1 va1 ~\<^sub>a BADDR i2 va2 \<longleftrightarrow> va1=this_addr \<and> va2=this_addr"
    by (simp add: acompat_baddr_def)
  lemma adiff_baddr_simp[simp]: "BADDR i1 va1 -\<^sub>a BADDR i2 va2 = i1 - i2"
    by (simp add: adiff_baddr_def)
  lemma aidx_baddr_simp[simp]: "BADDR i va +\<^sub>a j = BADDR (i+j) va"
    by (simp add: aidx_baddr_def)

  instance
    apply standard
    apply (intro part_equivpI sympI transpI)
    apply (auto
      simp: abase_baddr_def acompat_baddr_def adiff_baddr_def aidx_baddr_def
      split: baddr.splits)
    done

end

locale array_block2 = array_block1 static_err mem_err vload vstore vgep
    for static_err :: 'err
    and mem_err :: 'err
    and vload :: "'vaddr::this_addr \<Rightarrow> ('val,_,_,'val,'err) M"
    and vstore :: "'val \<Rightarrow> 'vaddr \<Rightarrow> (unit,_,_,'val,'err) M"
    and vgep :: "'vaddr \<Rightarrow> 'vidx \<Rightarrow> ('vaddr,_,_,'val,'err) M"

+ fixes \<alpha>v :: "'val \<Rightarrow> 'aval::unique_zero_sep_algebra"
    and vpto :: "'val \<Rightarrow> 'vaddr \<Rightarrow> 'aval \<Rightarrow> bool"
    and vcomplete :: "'aval \<Rightarrow> bool"

  assumes vload_rule: "notime.htriple \<alpha>v (vpto x va) (vload va) (\<lambda>r. \<up>(r=x) ** vpto x va)"
      and vstore_rule: "notime.htriple \<alpha>v (vpto xx va) (vstore x va) (\<lambda>_. vpto x va)"
      and vpto_notZ: "\<And>x a. \<not>vpto x a 0"
      and vcompleteD: "\<And>v v'. \<lbrakk>vcomplete v; v##v'\<rbrakk> \<Longrightarrow> v'=0"
      and vpto_this: "\<And>v av. vpto v this_addr av \<longleftrightarrow> av = \<alpha>v v"
      and \<alpha>v_complete: "\<And>v. vcomplete (\<alpha>v v)"

begin

  (*
  lemma is_arr_baddr_idx[simp]: "is_arr_baddr (idx_baddr a i) \<longleftrightarrow> is_arr_baddr a"
    by (auto simp: is_arr_baddr_def idx_baddr_def split: baddr.splits)

  lemma idx_baddr_add[simp]: "idx_baddr (idx_baddr a i) j = idx_baddr a (i+j)"
    by (auto simp: idx_baddr_def split: prod.splits baddr.splits)

  definition "idx_ptr \<equiv> \<lambda>RP_ADDR (ADDR bi ba) \<Rightarrow> \<lambda>i. RP_ADDR (ADDR bi (idx_baddr ba i)) | RP_NULL \<Rightarrow> \<lambda>i. RP_NULL"
  *)

  (* TODO: Rename to is_block_ptr! *)
  definition is_block_ptr :: "'vaddr baddr addr rptr \<Rightarrow> bool"
    where "is_block_ptr \<equiv> \<lambda>RP_ADDR (ADDR bi ba) \<Rightarrow> ba=this_addr | _ \<Rightarrow> False"

  (*definition "is_arr_ptr \<equiv> \<lambda>RP_ADDR (ADDR bi ba) \<Rightarrow> is_arr_baddr ba | _ \<Rightarrow> False"*)

  (*
  lemma is_arr_ptr_simps[simp]:
    "is_arr_ptr (RP_ADDR (ADDR bi ba)) = is_arr_baddr ba"
    "is_arr_ptr RP_NULL \<longleftrightarrow> False"
    by (auto simp: is_arr_ptr_def)
  *)

  lemma is_block_ptr_simps[simp]:
    "\<not>is_block_ptr RP_NULL"
    "is_block_ptr (RP_ADDR (ADDR bi ba)) \<longleftrightarrow> ba=this_addr"
    by (auto simp: is_block_ptr_def)

  lemma block_ptr_imp_abase[simp, intro]: "is_block_ptr p \<Longrightarrow> abase p"
    by (auto simp: is_block_ptr_def this_addr_baddr_def split: rptr.splits addr.splits)

  (*

  lemma idx_ptr_add[simp]: "idx_ptr (idx_ptr a i) j = idx_ptr a (i+j)"
    by (auto simp: idx_ptr_def split: rptr.splits addr.splits)

  lemma is_arr_ptr_idx[simp]: "is_arr_ptr (idx_ptr p i) \<longleftrightarrow> is_arr_ptr p"
    by (cases p) (auto simp: idx_ptr_def is_arr_ptr_def split: rptr.splits addr.splits)
  *)

  lemma \<alpha>v_notZ[simp]: "\<alpha>v v \<noteq> 0"
    using vpto_notZ vpto_this by fastforce

  definition "\<alpha> \<equiv> list\<alpha> \<alpha>v"

  definition pto :: "'val \<Rightarrow> 'vaddr baddr \<Rightarrow> 'aval ablock \<Rightarrow> bool"
    where "pto \<equiv> \<lambda>x. \<lambda>BADDR i va \<Rightarrow> \<lambda>s. \<exists>v. i\<ge>0 \<and> s=0(nat i:=v) \<and> vpto x va v"

  definition tag_of :: "'val block \<Rightarrow> int" where "tag_of \<equiv> int o length"

  definition "is_complete_tag ablk n \<equiv> 0\<le>n \<and> (\<forall>i. (ablk i \<noteq> 0 \<longleftrightarrow> i<nat n) \<and> (\<forall>i. ablk i \<noteq> 0 \<longrightarrow> vcomplete (ablk i)))"

  definition "array_lifter i \<equiv> idx_lifter (\<lambda>_. ()) \<alpha>v i"

  lemma array_lifter_simps[simp]:
    "sep_lifter.\<alpha>s (array_lifter i) = \<alpha>v"
    "sep_lifter.\<alpha>b (array_lifter i) = \<alpha>"
    "sep_lifter.L (array_lifter i) = idx\<^sub>L i"
    unfolding array_lifter_def \<alpha>_def by auto

  interpretation array_lifter: sep_lifter "array_lifter i" for i
    unfolding array_lifter_def by simp

  lemma pto_is_lift: "pto x = (\<lambda>BADDR i va \<Rightarrow> (\<up>(i\<ge>0) ** array_lifter.lift_assn (nat i) (vpto x va)))"
    unfolding array_lifter.lift_assn_def
    apply (rule ext)
    apply (clarsimp simp: array_lifter_def pto_def split: baddr.splits)
    apply (intro ext)
    apply (auto simp: sep_algebra_simps pred_lift_extract_simps)
    by (metis fun_upd_triv fun_upd_upd)

  lemma lift_is_pto: "i\<ge>0 \<Longrightarrow> array_lifter.lift_assn (nat i) (vpto x va) = pto x (BADDR i va)"
    by (simp add: pto_is_lift sep_algebra_simps pred_lift_extract_simps)

  declare vpto_notZ[simp]

  lemma load_rule: "notime.htriple \<alpha> (pto x va) (load va) (\<lambda>r. \<up>(r=x) ** pto x va)"
    unfolding load_def
    supply pto_is_lift[simp]
    apply (cases va; clarsimp simp: notime.htriple_extract_pre_pure sep_algebra_simps)
    using array_lifter.lift_operation[simplified, OF _ vload_rule, simplified]
    .

  lemma store_rule: "notime.htriple \<alpha> (pto xx va) (store x va) (\<lambda>_. pto x va)"
    unfolding store_def
    supply pto_is_lift[simp]
    apply (cases va; clarsimp simp: notime.htriple_extract_pre_pure sep_algebra_simps)
    using array_lifter.lift_operation[simplified, OF _ vstore_rule, simplified]
    .

  lemma load_pres_tag: "wlp (load a) (\<lambda>_ s'. tag_of s' = tag_of s) s"
    unfolding load_def
    apply (auto simp: wlp_def run_simps tag_of_def split: prod.splits option.splits baddr.splits)
    apply (rule mwp_trivI)
    by auto

  lemma store_pres_tag: "wlp (store a x) (\<lambda>_ s'. tag_of s' = tag_of s) s"
    unfolding store_def
    apply (auto simp: wlp_def run_simps tag_of_def split: prod.splits option.splits baddr.splits)
    apply (rule mwp_trivI)
    by auto

  lemma complete_tag:
    "\<lbrakk>is_complete_tag ablock (tag_of cblock); ablock ## f; \<alpha> cblock = ablock + f\<rbrakk> \<Longrightarrow> f = 0"
    apply (auto simp: is_complete_tag_def tag_of_def)
    by (smt \<alpha>_def disjoint_zero_sym list\<alpha>_in_range sep_add_disj_eq sep_disj_fun_def sep_disj_zero unique_zero vcompleteD)

  (* TODO: Move *)
  lemma Z_upd_eq_Z_iff[simp]: "0(i:=x) = 0 \<longleftrightarrow> x=0" by (auto simp: fun_eq_iff)

  lemma pto_notZ: "\<not> pto x a 0"
    apply (cases a)
    apply (auto simp: pto_def sep_algebra_simps)
    done

  lemma checked_idx_baddr_rule: "abase a
    \<Longrightarrow> notime.htriple \<alpha> (pto xx (a +\<^sub>a i)) (checked_idx_baddr a i) (\<lambda>r. \<up>(r=a +\<^sub>a i) ** pto xx (a +\<^sub>a i))"
    apply (rule notime.htripleI')
    unfolding checked_idx_baddr_def check_addr_def pto_is_lift
    apply (clarsimp simp: pred_lift_extract_simps split: baddr.splits)
    apply (frule (1) array_lifter.infer_pre_get_with_frame, simp, simp)
    apply (force simp: wpn_def run_simps aidx_baddr_def abase_baddr_def sep_algebra_simps split: prod.splits baddr.splits)
    done

  sublocale ba: block_allocator2 static_err mem_err load store check_addr \<alpha> pto tag_of is_complete_tag
    apply unfold_locales
    apply (rule load_rule)
    apply (rule store_rule)
    apply (rule load_pres_tag)
    apply (rule store_pres_tag)
    apply (rule complete_tag; assumption)
    apply (rule pto_notZ)
    done

  lemma list\<alpha>_rep_nn: "list\<alpha> \<alpha>v (replicate n v) n = 0"
    by (auto simp: list\<alpha>_def)

  lemma pto_this_exact: "pto x (BADDR i this_addr) = (\<up>(i\<ge>0) ** EXACT (0(nat i:=\<alpha>v x)))"
    by (auto simp: pto_def vpto_this pred_lift_extract_simps del: ext intro!: ext)

  lemma ba_pto_this_exact:
    "\<lbrakk>is_block_ptr p; i\<ge>0\<rbrakk>
    \<Longrightarrow> ba.pto x (p +\<^sub>a i) = EXACT (0(rptr_the_block_index p := (0(nat i:=\<alpha>v x),0)))"
    apply (auto
      simp: ba.pto_def aidx_baddr_def pto_this_exact this_addr_baddr_def
      simp: pred_lift_extract_simps is_block_ptr_def
      split: rptr.splits addr.splits baddr.splits)
    done

  lemma lift_pto_exact: "i\<ge>0 \<Longrightarrow> ba.block_lifter.lift_assn bi (pto v (this_addr +\<^sub>a i)) = EXACT (0(bi := (0(nat i:=\<alpha>v v),0)))"
    apply (auto
      simp:  aidx_baddr_def pto_this_exact this_addr_baddr_def
      simp: pred_lift_extract_simps is_block_ptr_def
      split: rptr.splits addr.splits baddr.splits)
    done

  (* TODO: Move *)
  lemma atLeast_lessThan_plus1:
    "l\<le>v \<Longrightarrow> {l..<1+v::int} = insert v {l..<v}"
    "l\<le>v \<Longrightarrow> {l..<v+1::int} = insert v {l..<v}"
    by auto

  lemma sep_set_img_int_range_to_nat: "(\<Union>*i\<in>{0..<int n}. f i) = (\<Union>*i\<in>{0..<n}. f (int i))"
    apply (induction n)
    apply (auto simp: atLeast_lessThan_plus1 atLeast0_lessThan_Suc)
    done

  lemma ba_block_alt:
    "ba.block (\<alpha> (init v n)) p = (\<up>(is_block_ptr p) ** (\<Union>*i\<in>{0..<int n}. ba.pto v (p +\<^sub>a i)))"
  proof -
    have ba_block_alt_aux: "(\<Union>*i\<in>{0..<int n}. EXACT (0(x1 := (0(nat i := \<alpha>v v), 0)))) = EXACT (0(x1 := (list\<alpha> \<alpha>v (replicate n v), 0)))"
      for x1::nat
      apply (induction n)
      supply replicate_Suc_conv_snoc[simp] replicate_Suc[simp del]
      subgoal by (auto simp: sep_algebra_simps del: ext intro!: ext)
      subgoal
        apply simp
        by (auto
          simp: list\<alpha>_snoc sep_algebra_simps sep_disj_fun_def atLeast0_lessThan_Suc atLeast_lessThan_plus1 sep_conj_def list\<alpha>_rep_nn
          cong del: if_cong
          del: ext intro!: ext)
      done

    have foo: "\<lbrakk>P=Q; Q \<Longrightarrow> X=Y\<rbrakk> \<Longrightarrow> (\<up>P**X) = (\<up>Q**Y)" for P Q X Y by auto
    have [simp]: "(\<Union>*x\<in>{0..<int n}. ba.pto v ((RP_ADDR (ADDR x1 (this_addr +\<^sub>a x)))))
      = (\<Union>*x\<in>{0..<int n}. EXACT (0(x1 := (0(nat x := \<alpha>v v), 0))))" for x1
      apply (rule sep_set_img_cong)
      apply (auto simp: lift_pto_exact)
      done

    note [simp del] = ba.pto_addr_eq

    show ?thesis
      unfolding init_def ba.block_def
      by (auto
        split: rptr.splits addr.splits
        simp: sep_algebra_simps
        simp: \<alpha>_def ba_block_alt_aux
        intro!: foo
        )
  qed

  lemma ba_block_exs_alt_aux:
    assumes "n\<ge>0"
    shows "(\<Union>*i\<in>{0..<n}. (EXS x. ba.pto x ((RP_ADDR (ADDR bi (this_addr +\<^sub>a i))))))
      = (EXS xs. \<up>(int (length xs) = n) ** EXACT (0(bi := (list\<alpha> \<alpha>v xs, 0))))"
    using assms
  proof (induction n rule: int_induct[where k=0])
    case base
    then show ?case by (auto simp: sep_algebra_simps pred_lift_extract_simps del: ext intro!: ext)
  next
    case (step1 n)

    note [simp] = \<open>0\<le>n\<close>
    note IH = step1.IH[simplified]

    have [simp]: "n+1\<noteq>0" using \<open>0\<le>n\<close> by linarith

    note replicate_Suc_conv_snoc[simp] replicate_Suc[simp del]
    show ?case
      apply (simp add: atLeast_lessThan_plus1)
      apply (simp add: IH)
      apply (rule ext)
      apply (auto simp: sep_algebra_simps pred_lift_extract_simps sep_disj_fun_def sep_conj_def list\<alpha>_at_len lift_pto_exact)
      subgoal for x xs
        apply (rule exI[where x="xs@[x]"])
        apply (auto del: ext intro!: ext simp: list\<alpha>_snoc sep_algebra_simps list\<alpha>_at_len
          simp: this_addr_baddr_def pto_this_exact
        )
        done
      subgoal for xs
        apply (rule exI[where x="last xs"])
        apply (rule exI[where x="butlast xs"]; simp)
        apply (cases xs rule: rev_cases)
        apply (auto simp: list\<alpha>_gt_len sep_algebra_simps list\<alpha>_snoc del: ext intro!: ext)
        done
      done
  next
    case (step2 n) thus ?case by (auto)
  qed

  lemma ba_block_exs_alt:
    "\<lbrakk>is_block_ptr p; n\<ge>0\<rbrakk> \<Longrightarrow> (\<Union>*i\<in>{0..<n}. EXS v. ba.pto v (p +\<^sub>a i)) = (EXS blk. \<up>(int (length blk) = n) ** ba.block (\<alpha> blk) p)"
    unfolding init_def ba.block_def
    supply [simp del] = ba.pto_addr_eq
    apply (cases p rule: ba.rptr_cases.cases; simp)
    apply (rule ext)
    apply (auto
      split: rptr.splits addr.splits
      simp: sep_algebra_simps pred_lift_extract_simps \<alpha>_def ba_block_exs_alt_aux
      )
    done

  lemma tag_of_init[simp]: "tag_of (init v n) = int n" by (auto simp: tag_of_def init_def)

  lemma ba_allocn_rule: "notime.htriple ba.\<alpha> \<box> (ba_allocn v n) (\<lambda>r. (\<Union>*i\<in>{0..<int n}. ba.pto v (r +\<^sub>a i)) ** ba.tag (int n) r ** \<up>(abase r))"
    unfolding ba_allocn_def
    apply (rule notime.cons_rule[OF ba.alloc_rule])
    apply simp
    apply (simp add: ba_block_alt sep_algebra_simps pred_lift_extract_simps)
    done

  lemma blk_complete_tag[simp]: "is_complete_tag (\<alpha> blk) (int (length blk))"
    by (auto simp: is_complete_tag_def \<alpha>_def list\<alpha>_def \<alpha>v_complete)

  (* TODO: is_base_ptr: This logic is already encoded in ba.tag! Try to get rid of is_base_ptr! *)
  lemma ba_tag_extr_baseptr: "ba.tag n p = (\<up>(is_block_ptr p \<and> 0\<le>n) ** ba.tag n p)"
    apply (rule ext)
    apply (auto simp: ba.tag_def sep_algebra_simps pred_lift_extract_simps split: addr.splits rptr.splits)
    apply (auto simp: tag_of_def)
    done

  lemma ba_freen_rule: "notime.htriple ba.\<alpha> ((\<Union>*i\<in>{0..<n}. EXS v. ba.pto v (p+\<^sub>ai)) \<and>* ba.tag n p) (ba.free p) (\<lambda>_. \<box>)"
    apply (subst ba_tag_extr_baseptr)
    apply (rule notime.htripleI')
    apply (clarsimp simp: sep_algebra_simps pred_lift_extract_simps)
    apply (simp add: ba_block_exs_alt)
    apply (clarsimp simp: sep_algebra_simps pred_lift_extract_simps)

    subgoal for pp s f blk
      supply R = ba.free_rule[of "\<alpha> blk" p "int (length blk)"]
      apply (rule R[THEN notime.htripleD', THEN notime.wp_monoI])
      apply assumption+
      apply (simp add: sep_algebra_simps)
      apply (simp add: sep_algebra_simps)
      done
    done

  lemma checked_idx_baddr_pres_tag: "wlp (checked_idx_baddr (BADDR a b) i) (\<lambda>_ s'. tag_of s' = tag_of sa) sa"
    by (auto simp: wlp_def checked_idx_baddr_def check_addr_def run_simps split: prod.splits baddr.splits)

  lemma checked_idx_ptr_rule: "abase p
    \<Longrightarrow> notime.htriple ba.\<alpha> (ba.pto xx (p +\<^sub>a i)) (checked_idx_ptr p i) (\<lambda>r. \<up>(r=p +\<^sub>a i) ** ba.pto xx (p +\<^sub>a i))"
    unfolding checked_idx_ptr_def
    apply (cases p rule: ba.rptr_cases.cases; simp add: zoom_bind)
    supply [vcg_rules] = ba.block_lifter.lift_operation[simplified, OF _ _ checked_idx_baddr_rule]
    supply [vcg_rules] = ba.block_lifter.lift_operation[simplified, OF _ _ notime_return_rule]
    supply [simp] = pto_notZ checked_idx_baddr_pres_tag abase_baddr_def
    supply [named_ss fri_prepare_simps] = aidx_baddr_simp
    supply [split] = baddr.splits
    apply vcg
    done

end

end


(*  Title:      HOL/Auth/n_mutualExFsm_on_ini.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_mutualExFsm Protocol Case Study*}

theory n_mutualExFsm_on_ini imports n_mutualExFsm_base
begin
lemma iniImply_inv__1:
assumes a1: "(\<exists> p__Inv0 p__Inv1. p__Inv0\<le>N\<and>p__Inv1\<le>N\<and>p__Inv0~=p__Inv1\<and>f=inv__1  p__Inv0 p__Inv1)"
and a2: "formEval (andList (allInitSpecs N)) s"
shows "formEval f s"
using a1 a2 by auto

lemma iniImply_inv__2:
assumes a1: "(\<exists> p__Inv0. p__Inv0\<le>N\<and>f=inv__2  p__Inv0)"
and a2: "formEval (andList (allInitSpecs N)) s"
shows "formEval f s"
using a1 a2 by auto

lemma iniImply_inv__3:
assumes a1: "(\<exists> p__Inv0 p__Inv1. p__Inv0\<le>N\<and>p__Inv1\<le>N\<and>p__Inv0~=p__Inv1\<and>f=inv__3  p__Inv0 p__Inv1)"
and a2: "formEval (andList (allInitSpecs N)) s"
shows "formEval f s"
using a1 a2 by auto

lemma iniImply_inv__4:
assumes a1: "(\<exists> p__Inv0. p__Inv0\<le>N\<and>f=inv__4  p__Inv0)"
and a2: "formEval (andList (allInitSpecs N)) s"
shows "formEval f s"
using a1 a2 by auto

lemma iniImply_inv__5:
assumes a1: "(\<exists> p__Inv0 p__Inv1. p__Inv0\<le>N\<and>p__Inv1\<le>N\<and>p__Inv0~=p__Inv1\<and>f=inv__5  p__Inv0 p__Inv1)"
and a2: "formEval (andList (allInitSpecs N)) s"
shows "formEval f s"
using a1 a2 by auto
end


theory flash109Rev imports flashPub
begin
section{*Main defintions*}
lemma NI_FAckVsInv109:
    (*Rule0VsPInv0*)

  shows  "invHoldForRule' s (inv109 ) (NI_FAck ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

      by( auto)

  lemma NI_InvVsInv109:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (NI_Inv  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_InvAck_1VsInv109:
    (*Rule2VsPInv0*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iRule2 \<le> N" and  a3:"iRule1~=iRule2  "

  shows  "invHoldForRule' s (inv109 ) (NI_InvAck_1  iRule1  iRule2 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1 a2 a3,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_InvAck_1_HomeVsInv109:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (NI_InvAck_1_Home  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_InvAck_2VsInv109:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (NI_InvAck_2 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Local_GetX_GetXVsInv109:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (NI_Local_GetX_GetX  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Local_GetX_Nak1VsInv109:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (NI_Local_GetX_Nak1  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Local_GetX_Nak2VsInv109:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (NI_Local_GetX_Nak2  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Local_GetX_Nak3VsInv109:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (NI_Local_GetX_Nak3  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Local_GetX_PutX1VsInv109:
  (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (NI_Local_GetX_PutX1 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply(cut_tac  a1 , auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma NI_Local_GetX_PutX2VsInv109:
  (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (NI_Local_GetX_PutX2 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply(cut_tac  a1 , auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma NI_Local_GetX_PutX3VsInv109:
  (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (NI_Local_GetX_PutX3 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply(cut_tac  a1 , auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma NI_Local_GetX_PutX4VsInv109:
  (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (NI_Local_GetX_PutX4 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply(cut_tac  a1 , auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma NI_Local_GetX_PutX5VsInv109:
  (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (NI_Local_GetX_PutX5 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply(cut_tac  a1 , auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma NI_Local_GetX_PutX6VsInv109:
  (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (NI_Local_GetX_PutX6 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply(cut_tac  a1 , auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma NI_Local_GetX_PutX7VsInv109:
  (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (NI_Local_GetX_PutX7 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply(cut_tac  a1 , auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma NI_Local_GetX_PutX8VsInv109:
  (*Rule2VsPInv0*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iRule2 \<le> N" and  a3:"iRule1~=iRule2  "

  shows  "invHoldForRule' s (inv109 ) (NI_Local_GetX_PutX8 N  iRule1  iRule2 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply(cut_tac  a1  a2  a3 , auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma NI_Local_GetX_PutX8_homeVsInv109:
  (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (NI_Local_GetX_PutX8_home N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply(cut_tac  a1 , auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma NI_Local_GetX_PutX9VsInv109:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (NI_Local_GetX_PutX9 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Local_GetX_PutX10VsInv109:
    (*Rule2VsPInv0*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iRule2 \<le> N" and  a3:"iRule1~=iRule2  "

  shows  "invHoldForRule' s (inv109 ) (NI_Local_GetX_PutX10 N  iRule1  iRule2 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1 a2 a3,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Local_GetX_PutX10_homeVsInv109:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (NI_Local_GetX_PutX10_home N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Local_GetX_PutX11VsInv109:
  (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (NI_Local_GetX_PutX11 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply(cut_tac  a1 , auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma NI_Local_Get_GetVsInv109:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (NI_Local_Get_Get  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Local_Get_Nak1VsInv109:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (NI_Local_Get_Nak1  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Local_Get_Nak2VsInv109:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (NI_Local_Get_Nak2  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Local_Get_Nak3VsInv109:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (NI_Local_Get_Nak3  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Local_Get_Put1VsInv109:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (NI_Local_Get_Put1 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Local_Get_Put2VsInv109:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (NI_Local_Get_Put2  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Local_Get_Put3VsInv109:
  (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (NI_Local_Get_Put3  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P3 s"

        apply(   cut_tac  a1 , simp)

        apply(rule_tac x=" (neg ( andForm ( eqn ( IVar ( Global ''Dir_Pending'') )  ( Const false ))    ( eqn ( IVar ( Para ''UniMsg_Cmd'' Home) )  ( Const UNI_GetX ))  ) ) " in exI,auto)

        done

       then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

        by blast

 qed
lemma NI_Local_PutVsInv109:
  (*Rule0VsPInv0*)
  shows  "invHoldForRule' s (inv109 ) (NI_Local_Put ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"formEval  ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true ))  s  \<or>formEval   (neg ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true )) )  s  "
	                      by auto

    moreover
                       {assume b1:"formEval ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true ))  s"

      have "?P1 s"

        apply(cut_tac  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast
    }

    moreover
                       {assume b1:"formEval  (neg ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true )) )  s"

      have "?P1 s"

        apply(cut_tac  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast
    }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_PutXAcksDoneVsInv109:
  (*Rule0VsPInv0*)
  shows  "invHoldForRule' s (inv109 ) (NI_Local_PutXAcksDone ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply( auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma NI_NakVsInv109:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (NI_Nak  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Nak_ClearVsInv109:
    (*Rule0VsPInv0*)

  shows  "invHoldForRule' s (inv109 ) (NI_Nak_Clear ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

      by( auto)

  lemma NI_Nak_HomeVsInv109:
  (*Rule0VsPInv0*)
  shows  "invHoldForRule' s (inv109 ) (NI_Nak_Home ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply( auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma NI_Remote_GetX_NakVsInv109:
    (*Rule2VsPInv0*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iRule2 \<le> N" and  a3:"iRule1~=iRule2  "

  shows  "invHoldForRule' s (inv109 ) (NI_Remote_GetX_Nak  iRule1  iRule2 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1 a2 a3,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Remote_GetX_Nak_HomeVsInv109:
  (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (NI_Remote_GetX_Nak_Home  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply(cut_tac  a1 , auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma NI_Remote_GetX_PutXVsInv109:
    (*Rule2VsPInv0*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iRule2 \<le> N" and  a3:"iRule1~=iRule2  "

  shows  "invHoldForRule' s (inv109 ) (NI_Remote_GetX_PutX  iRule1  iRule2 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1 a2 a3,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Remote_GetX_PutX_HomeVsInv109:
  (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (NI_Remote_GetX_PutX_Home  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply(cut_tac  a1 , auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma NI_Remote_Get_Nak1VsInv109:
  (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (NI_Remote_Get_Nak1  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply(cut_tac  a1 , auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma NI_Remote_Get_Nak2VsInv109:
    (*Rule2VsPInv0*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iRule2 \<le> N" and  a3:"iRule1~=iRule2  "

  shows  "invHoldForRule' s (inv109 ) (NI_Remote_Get_Nak2  iRule1  iRule2 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1 a2 a3,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Remote_Get_Put1VsInv109:
  (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (NI_Remote_Get_Put1  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply(cut_tac  a1 , auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma NI_Remote_Get_Put2VsInv109:
    (*Rule2VsPInv0*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iRule2 \<le> N" and  a3:"iRule1~=iRule2  "

  shows  "invHoldForRule' s (inv109 ) (NI_Remote_Get_Put2  iRule1  iRule2 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1 a2 a3,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Remote_PutVsInv109:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (NI_Remote_Put  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Remote_PutXVsInv109:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (NI_Remote_PutX  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_ReplaceVsInv109:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (NI_Replace  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_ReplaceHomeVsInv109:
    (*Rule0VsPInv0*)

  shows  "invHoldForRule' s (inv109 ) (NI_ReplaceHome ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

      by( auto)

  lemma NI_ReplaceHomeShrVldVsInv109:
    (*Rule0VsPInv0*)

  shows  "invHoldForRule' s (inv109 ) (NI_ReplaceHomeShrVld ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

      by( auto)

  lemma NI_ReplaceShrVldVsInv109:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (NI_ReplaceShrVld  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_ShWbVsInv109:
    (*Rule0VsPInv0*)

  shows  "invHoldForRule' s (inv109 ) (NI_ShWb N ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

      by( auto)

  lemma NI_WbVsInv109:
    (*Rule0VsPInv0*)

  shows  "invHoldForRule' s (inv109 ) (NI_Wb ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

      by( auto)

  lemma PI_Local_GetX_GetX1VsInv109:
  (*Rule0VsPInv0*)
  shows  "invHoldForRule' s (inv109 ) (PI_Local_GetX_GetX1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P3 s"

        apply(    simp)

        apply(rule_tac x=" (neg ( andForm ( eqn ( IVar ( Para ''CacheState'' Home) )  ( Const CACHE_S ))    ( eqn ( IVar ( Para ''CacheState'' Home) )  ( Const CACHE_I ))  ) ) " in exI,auto)

        done

       then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

        by blast

 qed
lemma PI_Local_GetX_GetX2VsInv109:
  (*Rule0VsPInv0*)
  shows  "invHoldForRule' s (inv109 ) (PI_Local_GetX_GetX2 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P3 s"

        apply(    simp)

        apply(rule_tac x=" (neg ( andForm ( eqn ( IVar ( Para ''CacheState'' Home) )  ( Const CACHE_S ))    ( eqn ( IVar ( Global ''Dir_Dirty'') )  ( Const true ))  ) ) " in exI,auto)

        done

       then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

        by blast

 qed
lemma PI_Local_GetX_PutX1VsInv109:
  (*Rule0VsPInv0*)
  shows  "invHoldForRule' s (inv109 ) (PI_Local_GetX_PutX1 N ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply( auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma PI_Local_GetX_PutX2VsInv109:
  (*Rule0VsPInv0*)
  shows  "invHoldForRule' s (inv109 ) (PI_Local_GetX_PutX2 N ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply( auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma PI_Local_GetX_PutX3VsInv109:
  (*Rule0VsPInv0*)
  shows  "invHoldForRule' s (inv109 ) (PI_Local_GetX_PutX3 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply( auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma PI_Local_GetX_PutX4VsInv109:
  (*Rule0VsPInv0*)
  shows  "invHoldForRule' s (inv109 ) (PI_Local_GetX_PutX4 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply( auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma PI_Local_Get_GetVsInv109:
  (*Rule0VsPInv0*)
  shows  "invHoldForRule' s (inv109 ) (PI_Local_Get_Get ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply( auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma PI_Local_Get_PutVsInv109:
  (*Rule0VsPInv0*)
  shows  "invHoldForRule' s (inv109 ) (PI_Local_Get_Put ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"formEval  ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true ))  s  \<or>formEval   (neg ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true )) )  s  "
	                      by auto

    moreover
                       {assume b1:"formEval ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true ))  s"

      have "?P1 s"

        apply(cut_tac  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast
    }

    moreover
                       {assume b1:"formEval  (neg ( eqn ( IVar ( Para ''InvMarked'' Home) )  ( Const true )) )  s"

      have "?P3 s"

        apply(   cut_tac  b1 , simp)

        apply(rule_tac x=" (neg ( andForm ( eqn ( IVar ( Para ''procCmd'' Home) )  ( Const NODE_None ))    ( eqn ( IVar ( Para ''UniMsg_Cmd'' Home) )  ( Const UNI_GetX ))  ) ) " in exI,auto)

        done

       then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast
    }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma PI_Local_PutXVsInv109:
  (*Rule0VsPInv0*)
  shows  "invHoldForRule' s (inv109 ) (PI_Local_PutX ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply( auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma PI_Local_ReplaceVsInv109:
  (*Rule0VsPInv0*)
  shows  "invHoldForRule' s (inv109 ) (PI_Local_Replace ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

      have "?P1 s"

        apply( auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma PI_Remote_GetVsInv109:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (PI_Remote_Get  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma PI_Remote_GetXVsInv109:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (PI_Remote_GetX  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma PI_Remote_PutXVsInv109:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (PI_Remote_PutX  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma PI_Remote_ReplaceVsInv109:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (PI_Remote_Replace  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma StoreVsInv109:
    (*Rule1VsPInv0*)
  assumes   a1:"iRule1 \<le> N"

  shows  "invHoldForRule' s (inv109 ) (Store  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma StoreHomeVsInv109:
    (*Rule0VsPInv0*)

  shows  "invHoldForRule' s (inv109 ) (StoreHome ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

      by( auto)

  end


(*  Title:      HOL/Auth/n_german_lemma_invs_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_invs_on_rules imports n_german_lemma_inv__1_on_rules n_german_lemma_inv__2_on_rules n_german_lemma_inv__3_on_rules n_german_lemma_inv__4_on_rules n_german_lemma_inv__5_on_rules n_german_lemma_inv__6_on_rules n_german_lemma_inv__7_on_rules n_german_lemma_inv__8_on_rules n_german_lemma_inv__9_on_rules n_german_lemma_inv__10_on_rules n_german_lemma_inv__11_on_rules n_german_lemma_inv__12_on_rules n_german_lemma_inv__13_on_rules n_german_lemma_inv__14_on_rules n_german_lemma_inv__15_on_rules n_german_lemma_inv__16_on_rules n_german_lemma_inv__17_on_rules n_german_lemma_inv__18_on_rules n_german_lemma_inv__19_on_rules n_german_lemma_inv__20_on_rules n_german_lemma_inv__21_on_rules n_german_lemma_inv__22_on_rules n_german_lemma_inv__23_on_rules n_german_lemma_inv__24_on_rules n_german_lemma_inv__25_on_rules n_german_lemma_inv__26_on_rules n_german_lemma_inv__27_on_rules n_german_lemma_inv__28_on_rules n_german_lemma_inv__29_on_rules n_german_lemma_inv__30_on_rules n_german_lemma_inv__31_on_rules n_german_lemma_inv__32_on_rules n_german_lemma_inv__33_on_rules n_german_lemma_inv__34_on_rules n_german_lemma_inv__35_on_rules n_german_lemma_inv__36_on_rules n_german_lemma_inv__37_on_rules n_german_lemma_inv__38_on_rules n_german_lemma_inv__39_on_rules n_german_lemma_inv__40_on_rules n_german_lemma_inv__41_on_rules n_german_lemma_inv__42_on_rules n_german_lemma_inv__43_on_rules n_german_lemma_inv__44_on_rules n_german_lemma_inv__45_on_rules n_german_lemma_inv__46_on_rules n_german_lemma_inv__47_on_rules n_german_lemma_inv__48_on_rules n_german_lemma_inv__49_on_rules n_german_lemma_inv__50_on_rules n_german_lemma_inv__51_on_rules n_german_lemma_inv__52_on_rules n_german_lemma_inv__53_on_rules n_german_lemma_inv__54_on_rules n_german_lemma_inv__55_on_rules n_german_lemma_inv__56_on_rules n_german_lemma_inv__57_on_rules n_german_lemma_inv__58_on_rules
begin
lemma invs_on_rules:
  assumes a1: "f \<in> invariants N" and a2: "r \<in> rules N"
  shows "invHoldForRule s f r (invariants N)"
  proof -
  have b1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__1  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__2  p__Inv0 p__Inv2)\<or>
    (f=inv__3  )\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__4  p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__5  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__6  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__7  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__8  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__9  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__10  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__11  p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__12  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__13  p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__14  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__15  p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__16  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__17  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__18  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__19  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__20  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__21  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__22  p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv1 p__Inv2. p__Inv0\<le>N\<and>p__Inv1\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv1\<and>p__Inv0~=p__Inv2\<and>p__Inv1~=p__Inv2\<and>f=inv__23  p__Inv0 p__Inv1 p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__24  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__25  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__26  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__27  p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__28  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__29  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__30  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__31  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__32  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__33  p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__34  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__35  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__36  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__37  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__38  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__39  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__40  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__41  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__42  p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__43  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__44  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__45  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__46  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__47  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__48  p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__49  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__50  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__51  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__52  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__53  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__54  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__55  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__56  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__57  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__58  p__Inv0 p__Inv2)"
  apply (cut_tac a1, auto) done
    moreover {
      assume c1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__1  p__Inv0 p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__1_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__2  p__Inv0 p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__2_on_rules) done
    }

    moreover {
      assume c1: "(f=inv__3  )"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__3_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__4  p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__4_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__5  p__Inv0 p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__5_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__6  p__Inv0 p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__6_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__7  p__Inv0 p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__7_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__8  p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__8_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__9  p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__9_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__10  p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__10_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__11  p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__11_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__12  p__Inv0 p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__12_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__13  p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__13_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__14  p__Inv0 p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__14_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__15  p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__15_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__16  p__Inv0 p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__16_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__17  p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__17_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__18  p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__18_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__19  p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__19_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__20  p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__20_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__21  p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__21_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__22  p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__22_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv0 p__Inv1 p__Inv2. p__Inv0\<le>N\<and>p__Inv1\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv1\<and>p__Inv0~=p__Inv2\<and>p__Inv1~=p__Inv2\<and>f=inv__23  p__Inv0 p__Inv1 p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__23_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__24  p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__24_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__25  p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__25_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__26  p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__26_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__27  p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__27_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__28  p__Inv0 p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__28_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__29  p__Inv0 p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__29_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__30  p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__30_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__31  p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__31_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__32  p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__32_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__33  p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__33_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__34  p__Inv0 p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__34_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__35  p__Inv0 p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__35_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__36  p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__36_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__37  p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__37_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__38  p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__38_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__39  p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__39_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__40  p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__40_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__41  p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__41_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__42  p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__42_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__43  p__Inv0 p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__43_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__44  p__Inv0 p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__44_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__45  p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__45_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__46  p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__46_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__47  p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__47_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__48  p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__48_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__49  p__Inv0 p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__49_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__50  p__Inv0 p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__50_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__51  p__Inv0 p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__51_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__52  p__Inv0 p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__52_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__53  p__Inv0 p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__53_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__54  p__Inv0 p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__54_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__55  p__Inv0 p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__55_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__56  p__Inv0 p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__56_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__57  p__Inv0 p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__57_on_rules) done
    }

    moreover {
      assume c1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__58  p__Inv0 p__Inv2)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac a2 c1, metis lemma_inv__58_on_rules) done
    }

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

end


(*  Title:      HOL/Auth/n_german_lemma_inv__40_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__40_on_rules imports n_german_lemma_on_inv__40
begin
section{*All lemmas on causal relation between inv__40*}
lemma lemma_inv__40_on_rules:
  assumes b1: "r \<in> rules N" and b2: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__40  p__Inv2)"
  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_SendReqS  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendReqE__part__0  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendReqE__part__1  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvReqS N i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvReqE 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__40) done
    }

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

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

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_SendReqE__part__1  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_SendReqE__part__1Vsinv__40) 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__40) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_RecvReqE N i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_RecvReqEVsinv__40) 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__40) 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__40) 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__40) 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__40) 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__40) 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__40) 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__40) 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__40) done
    }

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

end


(*  Title:      JinjaDCI/Compiler/PCompiler.thy

    Author:     Tobias Nipkow, Susannah Mansky
    Copyright   TUM 2003, UIUC 2019-20

    Based on the Jinja theory Common/PCompiler.thy by Tobias Nipkow
*)

section \<open> Program Compilation \<close>

theory PCompiler
imports "../Common/WellForm"
begin

definition compM :: "(staticb \<Rightarrow> 'a \<Rightarrow> 'b) \<Rightarrow> 'a mdecl \<Rightarrow> 'b mdecl"
where
  "compM f  \<equiv>  \<lambda>(M, b, Ts, T, m). (M, b, Ts, T, f b m)"

definition compC :: "(staticb \<Rightarrow> 'a \<Rightarrow> 'b) \<Rightarrow> 'a cdecl \<Rightarrow> 'b cdecl"
where
  "compC f  \<equiv>  \<lambda>(C,D,Fdecls,Mdecls). (C,D,Fdecls, map (compM f) Mdecls)"

definition compP :: "(staticb \<Rightarrow> 'a \<Rightarrow> 'b) \<Rightarrow> 'a prog \<Rightarrow> 'b prog"
where
  "compP f  \<equiv>  map (compC f)"

text\<open> Compilation preserves the program structure.  Therefore lookup
functions either commute with compilation (like method lookup) or are
preserved by it (like the subclass relation). \<close>

lemma map_of_map4:
  "map_of (map (\<lambda>(x,a,b,c).(x,a,b,f c)) ts) =
  map_option (\<lambda>(a,b,c).(a,b,f c)) \<circ> (map_of ts)"
(*<*)
apply(induct ts)
 apply simp
apply(rule ext)
apply fastforce
done
(*>*)

lemma map_of_map245:
  "map_of (map (\<lambda>(x,a,b,c,d).(x,a,b,c,f a c d)) ts) =
  map_option (\<lambda>(a,b,c,d).(a,b,c,f a c d)) \<circ> (map_of ts)"
(*<*)
apply(induct ts)
 apply simp
apply(rule ext)
apply fastforce
done
(*>*)

lemma class_compP:
  "class P C = Some (D, fs, ms)
  \<Longrightarrow> class (compP f P) C = Some (D, fs, map (compM f) ms)"
(*<*)by(simp add:class_def compP_def compC_def map_of_map4)(*>*)

lemma class_compPD:
  "class (compP f P) C = Some (D, fs, cms)
  \<Longrightarrow> \<exists>ms. class P C = Some(D,fs,ms) \<and> cms = map (compM f) ms"
(*<*)by(clarsimp simp add:class_def compP_def compC_def map_of_map4)(*>*)

lemma [simp]: "class (compP f P) C = map_option (\<lambda>c. snd(compC f (C,c))) (class P C)"
(*<*)
apply(simp add:compP_def compC_def class_def map_of_map4)
apply(simp add:split_def)
done
(*>*)

lemma sees_methods_compP:
  "P \<turnstile> C sees_methods Mm \<Longrightarrow>
  compP f P \<turnstile> C sees_methods (map_option (\<lambda>((b,Ts,T,m),D). ((b,Ts,T,f b m),D)) \<circ> Mm)"
(*<*)
apply(erule Methods.induct)
 apply(rule sees_methods_Object)
  apply(erule class_compP)
 apply(rule ext)
 apply(simp add:compM_def map_of_map245 option.map_comp)
 apply(case_tac "map_of ms x")
  apply simp
 apply fastforce
apply(rule sees_methods_rec)
   apply(erule class_compP)
  apply assumption
 apply assumption
apply(rule ext)
apply(simp add:map_add_def compM_def map_of_map245 option.map_comp split:option.split)
done
(*>*)

lemma sees_method_compP:
  "P \<turnstile> C sees M,b: Ts\<rightarrow>T = m in D \<Longrightarrow>
  compP f P \<turnstile> C sees M,b: Ts\<rightarrow>T = (f b m) in D"
(*<*)by(fastforce elim:sees_methods_compP simp add:Method_def)(*>*)

lemma [simp]:
  "P \<turnstile> C sees M,b: Ts\<rightarrow>T = m in D \<Longrightarrow>
  method (compP f P) C M = (D,b,Ts,T,f b m)"
(*<*)
apply(drule sees_method_compP)
apply(simp add:method_def)
apply(rule the_equality)
 apply simp
apply(fastforce dest:sees_method_fun)
done
(*>*)

lemma sees_methods_compPD:
  "\<lbrakk> cP \<turnstile> C sees_methods Mm'; cP = compP f P \<rbrakk> \<Longrightarrow>
  \<exists>Mm. P \<turnstile> C sees_methods Mm \<and>
        Mm' = (map_option (\<lambda>((b,Ts,T,m),D). ((b,Ts,T,f b m),D)) \<circ> Mm)"
(*<*)
apply(erule Methods.induct)
 apply(clarsimp simp:compC_def)
 apply(rule exI)
 apply(rule conjI, erule sees_methods_Object)
  apply(rule refl)
 apply(rule ext)
 apply(simp add:compM_def map_of_map245 option.map_comp)
 apply(case_tac "map_of b x")
  apply simp
 apply fastforce
apply(clarsimp simp:compC_def)
apply(rule exI, rule conjI)
 apply(erule (2) sees_methods_rec)
 apply(rule refl)
apply(rule ext)
apply(simp add:map_add_def compM_def map_of_map245 option.map_comp split:option.split)
done
(*>*)

lemma sees_method_compPD:
  "compP f P \<turnstile> C sees M,b: Ts\<rightarrow>T = fm in D \<Longrightarrow>
  \<exists>m. P \<turnstile> C sees M,b: Ts\<rightarrow>T = m in D \<and> f b m = fm"
(*<*)
apply(simp add:Method_def)
apply clarify
apply(drule sees_methods_compPD[OF _ refl])
apply clarsimp
apply blast
done
(*>*)

lemma [simp]: "subcls1(compP f P) = subcls1 P"
(*<*)
by(fastforce simp add: is_class_def compC_def intro:subcls1I order_antisym dest:subcls1D)
(*>*)

lemma compP_widen[simp]: "(compP f P \<turnstile> T \<le> T') = (P \<turnstile> T \<le> T')"
(*<*)by(cases T')(simp_all add:widen_Class)(*>*)

lemma [simp]: "(compP f P \<turnstile> Ts [\<le>] Ts') = (P \<turnstile> Ts [\<le>] Ts')"
(*<*)
apply(induct Ts)
 apply simp
apply(cases Ts')
 apply(auto simp:fun_of_def)
done
(*>*)

lemma [simp]: "is_type (compP f P) T = is_type P T"
(*<*)by(cases T) simp_all(*>*)

lemma [simp]: "(compP (f::staticb\<Rightarrow>'a\<Rightarrow>'b) P \<turnstile> C has_fields FDTs) = (P \<turnstile> C has_fields FDTs)"
(*<*)
 (is "?A = ?B")
proof
  { fix cP::"'b prog" assume "cP \<turnstile> C has_fields FDTs"
    hence "cP = compP f P \<Longrightarrow> P \<turnstile> C has_fields FDTs"
    proof induct
      case has_fields_Object
      thus ?case by(fast intro:Fields.has_fields_Object dest:class_compPD)
    next
      case has_fields_rec
      thus ?case by(fast intro:Fields.has_fields_rec dest:class_compPD)
    qed
  } note lem = this
  assume ?A
  with lem show ?B by blast
next
  assume ?B
  thus ?A
  proof induct
    case has_fields_Object
    thus ?case by(fast intro:Fields.has_fields_Object class_compP)
  next
    case has_fields_rec
    thus ?case by(fast intro:Fields.has_fields_rec class_compP)
  qed
qed
(*>*)

lemma fields_compP [simp]: "fields (compP f P) C = fields P C"
(*<*)by(simp add:fields_def)(*>*)

lemma ifields_compP [simp]: "ifields (compP f P) C = ifields P C"
(*<*)by(simp add:ifields_def)(*>*)

lemma blank_compP [simp]: "blank (compP f P) C = blank P C"
(*<*)by(simp add:blank_def)(*>*)

lemma isfields_compP [simp]: "isfields (compP f P) C = isfields P C"
(*<*)by(simp add:isfields_def)(*>*)

lemma sblank_compP [simp]: "sblank (compP f P) C = sblank P C"
(*<*)by(simp add:sblank_def)(*>*)

lemma sees_fields_compP [simp]: "(compP f P \<turnstile> C sees F,b:T in D) = (P \<turnstile> C sees F,b:T in D)"
(*<*)by(simp add:sees_field_def)(*>*)

lemma has_field_compP [simp]: "(compP f P \<turnstile> C has F,b:T in D) = (P \<turnstile> C has F,b:T in D)"
(*<*)by(simp add:has_field_def)(*>*)

lemma field_compP [simp]: "field (compP f P) F D = field P F D"
(*<*)by(simp add:field_def)(*>*)

subsection\<open>Invariance of @{term wf_prog} under compilation \<close>

lemma [iff]: "distinct_fst (map (compM f) ms) = distinct_fst ms"
(*<*)
apply(simp add:distinct_fst_def compM_def)
apply(induct ms)
apply (auto simp:image_iff)
done
(*>*)

lemma [iff]: "wf_syscls (compP f P) = wf_syscls P"
(*<*)by(simp add:wf_syscls_def compP_def compC_def image_def Bex_def)(*>*)

lemma [iff]: "wf_fdecl (compP f P) = wf_fdecl P"
(*<*)by(simp add:wf_fdecl_def)(*>*)

lemma wf_clinit_compM [iff]: "wf_clinit (map (compM f) ms) = wf_clinit ms"
(*<*)
apply(simp add: wf_clinit_def compM_def)
apply(rule iffI)
 apply clarsimp apply(rename_tac m)
 apply(rule_tac x = m in exI, simp+)
apply clarsimp apply(rename_tac m)
apply(rule_tac x = "f Static m" in exI, simp add: rev_image_eqI)
done
(*>*)

lemma set_compP:
 "((C,D,fs,ms') \<in> set(compP f P)) =
  (\<exists>ms. (C,D,fs,ms) \<in> set P \<and> ms' = map (compM f) ms)"
(*<*)by(fastforce simp add:compP_def compC_def image_iff Bex_def)(*>*)

lemma wf_cdecl_compPI:
  "\<lbrakk> \<And>C M b Ts T m.
     \<lbrakk> wf_mdecl wf\<^sub>1 P C (M,b,Ts,T,m); P \<turnstile> C sees M,b:Ts\<rightarrow>T = m in C \<rbrakk>
     \<Longrightarrow> wf_mdecl wf\<^sub>2 (compP f P) C (M,b,Ts,T, f b m);
    \<forall>x\<in>set P. wf_cdecl wf\<^sub>1 P x; x \<in> set (compP f P); wf_prog p P \<rbrakk>
  \<Longrightarrow> wf_cdecl wf\<^sub>2 (compP f P) x"
(*<*)
apply(clarsimp simp add:wf_cdecl_def Ball_def set_compP)
apply(rename_tac C D fs ms)
apply(rule conjI)
 apply (clarsimp simp:compM_def)
 apply (drule (2) mdecl_visible)
 apply simp
apply(clarify)
apply(drule sees_method_compPD[where f = f])
apply clarsimp
apply(fastforce simp:image_iff compM_def)
done
(*>*)

lemma wf_prog_compPI:
assumes lift:
  "\<And>C M b Ts T m.
    \<lbrakk> P \<turnstile> C sees M,b:Ts\<rightarrow>T = m in C; wf_mdecl wf\<^sub>1 P C (M,b,Ts,T,m) \<rbrakk>
    \<Longrightarrow> wf_mdecl wf\<^sub>2 (compP f P) C (M,b,Ts,T, f b m)"
and wf: "wf_prog wf\<^sub>1 P"
shows "wf_prog wf\<^sub>2 (compP f P)"
(*<*)
using wf
by (simp add:wf_prog_def) (blast intro:wf_cdecl_compPI lift wf)
(*>*)

end


(*
 * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
 *
 * SPDX-License-Identifier: BSD-2-Clause
 *)

(*
 * Test force/prevent heap abstraction.
 *)

theory heap_lift_force_prevent
imports "AutoCorres.AutoCorres"
begin

external_file "heap_lift_force_prevent.c"
install_C_file "heap_lift_force_prevent.c"

autocorres [
    no_heap_abs = unlifted_a unlifted_b,
    force_heap_abs = lifted_a lifted_b,
    ts_force nondet = unlifted_a unlifted_b lifted_a lifted_b
    ] "heap_lift_force_prevent.c"

context heap_lift_force_prevent begin

lemma heap_w32_hrs_mem [simp]:
    "\<lbrakk> is_valid_w32 (lift_global_heap s) p; heap_w32 (lift_global_heap s) p = a \<rbrakk>
      \<Longrightarrow> h_val (hrs_mem (t_hrs_' s)) p = a"
  by (fastforce simp: lifted_globals_ext_simps(3) lifted_globals_ext_simps(4) h_val_simple_lift)

lemma lifted_a_wp [wp]:
    "\<lbrace> \<lambda>s. is_valid_w32 s p \<and> (\<exists>a. heap_w32 s p = a \<and> P a s) \<rbrace> lifted_a' p \<lbrace> \<lambda>r s. P r s \<rbrace>"
  by (clarsimp simp: lifted_a'_def, wp, auto)

lemma unlifted_a_wp [wp]:
    "\<lbrace> \<lambda>s. c_guard p \<and> P (h_val (hrs_mem (t_hrs_' s)) p) s \<rbrace>
                  unlifted_a' p \<lbrace> \<lambda>r s. P r s \<rbrace>"
  by (clarsimp simp: unlifted_a'_def, wp, auto)

lemma lifted_b_wp [wp]:
    "\<lbrace> \<lambda>s. is_valid_w32 s p \<and> (\<exists>a. heap_w32 s p = a \<and> P (a * 3) s) \<rbrace> lifted_b' p \<lbrace> \<lambda>r s. P r s \<rbrace>"
  apply (clarsimp simp: lifted_b'_def)
  including no_pre apply wp
  apply (auto simp: simple_lift_c_guard lift_global_heap_def field_simps)
  done

lemma unlifted_b_wp [wp]:
    "\<lbrace> \<lambda>s. heap_ptr_valid (hrs_htd (t_hrs_' s)) p
           \<and> (\<forall>t. lift_global_heap t = lift_global_heap s \<longrightarrow> P (h_val (hrs_mem (t_hrs_' t)) p * 3) t) \<rbrace>
              unlifted_b' p \<lbrace> \<lambda>r s. P r s \<rbrace>"
  apply (clarsimp simp: unlifted_b'_def)
  apply wp
  apply (rule conjI)
   apply (metis simple_lift_c_guard simple_lift_def)
  apply clarsimp
  apply (rule conjI)
   apply (clarsimp simp: lift_global_heap_def )
   apply (unfold simple_lift_def)
   apply (clarsimp  split: option.splits)
  apply (clarsimp simp: field_simps)
  apply (erule allE, erule (1) impE)
  apply (subgoal_tac "h_val (hrs_mem (t_hrs_' s)) p = h_val (hrs_mem (t_hrs_' t)) p"
                     "heap_w32 (lift_global_heap s) p = h_val (hrs_mem (t_hrs_' t)) p")
    apply clarsimp
   apply (clarsimp simp: lift_global_heap_def)
   apply (drule fun_cong [where x = p])
   apply (clarsimp simp: simple_lift_def)
  apply (metis heap_w32_hrs_mem lifted_globals_ext_simps(4) simple_lift_def)
  done

end

end