Theory Sep_Value

section ‹Values›
theory Sep_Value
imports 
  "../../lib/Monad"
begin

  subsection ‹Values and Addresses›
  datatype 'a val = PAIR (fst: "'a val") (snd: "'a val") | PRIMITIVE (the: 'a)
  hide_const (open) fst snd the
  define_lenses (open) val
  
  datatype va_item = PFST | PSND
  type_synonym vaddr = "va_item list"
  
  subsection ‹Focusing on Address›
  fun lens_of_item where
    "lens_of_item PFST = val.fstL"  
  | "lens_of_item PSND = val.sndL"
  
  definition "lens_of_vaddr vp = foldr (λi L. lens_of_item i L L) vp idL"
  
  lemma lens_of_vaddr_simps[simp]:
    "lens_of_vaddr [] = idL"
    "lens_of_vaddr (i#is) = lens_of_item i L lens_of_vaddr is"
    unfolding lens_of_vaddr_def
    by auto
    
  lemma ex_two_vals[simp, intro]: "a b::'a val. a  b" by auto

  lemma lens_of_item_rnl[simp, intro!]: "rnlens (lens_of_item i :: 'a val  'a val)"  
  proof -
    have A: "is_PAIR (PAIR undefined undefined :: 'a val)" by simp
  
    show ?thesis
      by (cases i) (auto intro!: rnlensI A)
  qed

  lemma lens_of_item_hlens[simp, intro!]: "hlens (lens_of_item i :: 'a val  'a val)"  
    by (cases i) (auto)
  
  
  lemma lens_of_vaddr_rnl[simp, intro!]: "rnlens (lens_of_vaddr vp)"
    by (induction vp) auto
  
  lemma lens_of_vaddr_hlens[simp, intro!]: "hlens (lens_of_vaddr vp)"
    by (induction vp) auto
    
  lemma lens_of_item_complete[simp, intro!]: "complete_lens (lens_of_item i)"
    apply (rule)
    apply (simp; fail)
    using val.discI(1)
    by (cases i; fastforce)
    
    
  subsection ‹Loading and Storing Address›
  definition "vload err a  zoom (lift_lens err (lens_of_vaddr a)) Monad.get"  
  definition "vstore err x a  zoom (lift_lens err (lens_of_vaddr a)) (Monad.set x)"

  
  subsection ‹GEP›
  
  definition "checked_gep err addr item  doM {
    let addr = addr@[item];
    use (lift_lens err (lens_of_vaddr addr));
    return addr
  }"
  
  
  subsection ‹Structure of Value›
  datatype 's vstruct = VS_PAIR "'s vstruct" "'s vstruct" | VS_PRIMITIVE 's
  
  locale structured_value_defs =
    fixes struct_of_primval :: "'a  's"
      and init_primval :: "'s  'a"
  begin
    fun struct_of_val :: "'a val  's vstruct" where
      "struct_of_val (PAIR a b) = VS_PAIR (struct_of_val a) (struct_of_val b)"
    | "struct_of_val (PRIMITIVE x) = VS_PRIMITIVE (struct_of_primval x)"

    fun init_val :: "'s vstruct  'a val" where
      "init_val (VS_PAIR sa sb) = PAIR (init_val sa) (init_val sb)"
    | "init_val (VS_PRIMITIVE ps) = PRIMITIVE (init_primval ps)"  
      
  end    
  
  lemmas structured_value_code[code] =
    structured_value_defs.struct_of_val.simps
    structured_value_defs.init_val.simps
  
  locale structured_value = structured_value_defs struct_of_primval init_primval 
    for struct_of_primval :: "'a  's"
      and init_primval :: "'s  'a" +
    assumes struct_of_init_primval[simp]: "struct_of_primval (init_primval s) = s"  
  begin
  
    lemma put_preserves_struct:
      assumes "pre_get (lens_of_vaddr a) s"
      assumes "struct_of_val (get' (lens_of_vaddr a) s) = struct_of_val x"
      shows "struct_of_val (put' (lens_of_vaddr a) x s) = struct_of_val s"
      using assms
    proof (induction a arbitrary: s)
      case Nil
      then show ?case by auto
    next
      case (Cons i as)
      then show ?case by (cases s; cases i; simp)
    qed
    
    lemma struct_of_init[simp]: "struct_of_val (init_val s) = s"
      by (induction s) (auto simp: )
    
    
  end
  
end