Theory Eg1Eg2

theory Eg1Eg2
imports Eg1
        Eg2
        "../CompositionalRefinement"
begin

locale sifum_refinement_eg1_eg2 =
  A: sifum_example +
  C: sifum_example2

primrec Eg2_varC_of_Eg1 :: "Eg1.var  Eg2.varC"
where
  "Eg2_varC_of_Eg1 control_var = control_varC" |
  "Eg2_varC_of_Eg1 buffer = bufferC" |
  "Eg2_varC_of_Eg1 high_var = high_varC" |
  "Eg2_varC_of_Eg1 low_var = low_varC" |
  "Eg2_varC_of_Eg1 temp = tempC"

sublocale sifum_refinement_eg1_eg2  sifum_refinement dma dmaC 𝒞_vars 𝒞_varsC 𝒞 𝒞C A.evalw C.evalw undefined Eg2_varC_of_Eg1
  supply image_cong_simp [cong del] INF_cong_simp [cong] SUP_cong_simp [cong] subst_all [simp del]
  apply(unfold_locales)
           apply(erule C.eval_det, simp)
          apply(rule C.Var_finite)
         apply(simp add:𝒞_varsC_def split:if_splits)
        apply(simp add:𝒞_varsC_def dmaC_def)
       apply(simp add:𝒞_varsC_def dmaC_def)
      apply(rule inj_onI, simp)
      apply(case_tac x)
          apply(case_tac y, simp+)
         apply(case_tac y, simp+)
        apply(case_tac y, simp+)
       apply(case_tac y, simp+)
      apply(case_tac y, simp+)
     apply(case_tac xA)
         apply(clarsimp simp:dmaC_def dma_def dma_control_var_def dma_control_varC_def)+
    apply(case_tac xA)
        apply(clarsimp simp:𝒞_varsC_def 𝒞_vars_def)+
   apply(rule set_eqI, clarsimp)
   apply(case_tac x, clarsimp)
        apply(rule_tac x=control_var in rev_image_eqI, clarsimp+)
       apply(case_tac xa, clarsimp+)
          apply(case_tac xb, clarsimp+)
      apply(case_tac xa, clarsimp+)
         apply(case_tac xb, clarsimp+)
     apply(case_tac xa, clarsimp+)
        apply(case_tac xb, clarsimp+)
    apply(case_tac xa, clarsimp+)
       apply(case_tac xb, clarsimp+)
   apply(case_tac xa, clarsimp+)
  apply(simp add:𝒞C_def)
  done

context sifum_refinement_eg1_eg2
begin


lemma bisim_simple_ℛ:
  "bisim_simple (A.ℛ Γ 𝒮 P)"
  unfolding bisim_simple_def
  apply clarsimp
  apply(drule_tac lc="c1A, mds, mem1AA" and lc'="c2A, mds, mem2AA" in A.bisim_simple_ℛu)
  by simp

(* Don't know to what extent these helpers can be made generic enough to go into any parent theories.
   Again, mightn't be able to (or bother to) make some generic considering the aexp evaluator
   is going to be specific to each language. *)

lemma conc_only_vars_not_visible_abs:
  "(vC. vC  range Eg2_varC_of_Eg1  memC vC = memC' vC)  memA_of memC = memA_of memC'"
  by (simp add: memA_of_def)

lemma conc_only_var_assign_not_visible_abs:
  "vC e. vC  range Eg2_varC_of_Eg1  memA_of memC = memA_of (memC(vC := e))"
  using conc_only_vars_not_visible_abs
  by simp

lemma regC_is_not_the_varC_of_anything:
  "regC = Eg2_varC_of_Eg1 x  False"
  by (induct x, clarsimp+)

lemma regC_not_visible_abs:
  "regC  range Eg2_varC_of_Eg1"
  using regC_is_not_the_varC_of_anything
  by blast

(* This one's pretty specific to this refinement... *)
lemma regC_the_only_concrete_only_var:
  "vC  range Eg2_varC_of_Eg1  vC = regC"
  apply(case_tac vC)
       apply(erule rev_notE, clarsimp, rule_tac x=control_var in range_eqI, clarsimp)
      apply(erule rev_notE, clarsimp, rule_tac x=buffer in range_eqI, clarsimp)
     apply(erule rev_notE, clarsimp, rule_tac x=high_var in range_eqI, clarsimp)
    apply(erule rev_notE, clarsimp, rule_tac x=low_var in range_eqI, clarsimp)
   apply(erule rev_notE, clarsimp, rule_tac x=temp in range_eqI, clarsimp)
  apply clarsimp
  done

lemma NoRWA_implies_NoRWC:
  "x  mdsA_of mdsC AsmNoReadOrWrite 
   Eg2_varC_of_Eg1 x  mdsC AsmNoReadOrWrite"
  unfolding mdsA_of_def
  apply clarsimp
  apply (simp only: Eg2_varC_of_Eg1_def)
  apply clarsimp
  apply (simp add: f_inv_into_f)
  done

lemma NoWriteA_implies_NoWriteC:
  "x  mdsA_of mdsC AsmNoWrite 
   Eg2_varC_of_Eg1 x  mdsC AsmNoWrite"
  unfolding mdsA_of_def
  apply clarsimp
  apply (simp only: Eg2_varC_of_Eg1_def)
  apply clarsimp
  apply (simp add: f_inv_into_f)
  done

lemma assign_evalw_loadA:
  shows "(x  Eg1.Load y, mds, memA, Stop, mds, mem (x := mem y)A)  A.evalw"
  by (metis A.assign_evalw evA.simps(2))

lemma assign_evalw_loadC:
  shows "(x  Load y, mds, memC, Stop, mds, mem (x := mem y)C)  C.evalw"
  using C.unannotated[OF C.assign, where E="[]", simplified]
  apply(drule_tac x=x in meta_spec)
  apply(drule_tac x="Load y" in meta_spec)
  apply(drule_tac x=mds in meta_spec)
  apply(drule_tac x=mem in meta_spec)
  apply clarsimp
  done

lemma assign_evalw_constA:
  shows "(x  Eg1.Const c, mds, mem, Stop, mds, mem (x := c))  A.evalw"
  by (metis A.assign_evalw evA.simps(1))

lemma assign_evalw_constC:
  shows "(x  Const c, mds, mem, Stop, mds, mem (x := c))  C.evalw"
  using C.unannotated[OF C.assign, where E="[]", simplified]
  apply(drule_tac x=x in meta_spec)
  apply(drule_tac x="Const c" in meta_spec)
  apply(drule_tac x=mds in meta_spec)
  apply(drule_tac x=mem in meta_spec)
  apply clarsimp
  done

lemma if_seq_evalw_helperA:
  "(If B T E, mds, mem,
    if evB mem B then T else E, mds, memA)  A.evalw
    
   (If B T E ;; TAIL, mds, mem,
    if evB mem B then T ;; TAIL else E ;; TAIL, mds, memA)  A.evalw"
  using A.evalw.seq
  by auto

lemma if_seq_evalw_helperC:
  "(If B T E, mds, mem,
    if evBC mem B then T else E, mds, memC)  C.evalw
    
   (If B T E ;; TAIL, mds, mem,
    if evBC mem B then T ;; TAIL else E ;; TAIL, mds, memC)  C.evalw"
  using C.evalw.seq
  by auto

lemma mem_assign_refinement_helper_var:
  "memA_of (memC (Eg2_varC_of_Eg1 x := memC (Eg2_varC_of_Eg1 y)))
       = (memA_of memC) (x := (memA_of memC) y)"
  apply(clarsimp simp: memA_of_def)
  apply(rule ext, clarsimp)
  apply(cases x)
      apply(case_tac xA, clarsimp+)+
  done

lemma mem_assign_refinement_helper_const:
  "memA_of (memC (Eg2_varC_of_Eg1 x := c))
       = (memA_of memC) (x := c)"
  apply(clarsimp simp: memA_of_def)
  apply(rule ext, clarsimp)
  apply(cases x)
      apply(case_tac xA, clarsimp+)+
  done

lemma if_true_evalwC:
  shows "memC x = 0 
     ((If (Eq x 0) cC_then cC_else) ;; cC_tail, mdsC, memCC,
      (cC_then ;; cC_tail), mdsC, memCC)  C.evalw"
  using C.if_evalw C.evalw.seq evBC.simps by presburger

lemma if_false_evalwC:
  shows "memC x  0 
     ((If (Eq x 0) cC_then cC_else) ;; cC_tail, mdsC, memCC,
      (cC_else ;; cC_tail), mdsC, memCC)  C.evalw"
  using C.if_evalw C.evalw.seq evBC.simps by presburger


end

end