Theory Array_Map_Impl

theory Array_Map_Impl
imports Imp_Map_Spec Array_Blit
theory Array_Map_Impl
imports 
  "../Sep_Main" Imp_Map_Spec Array_Blit
  "~~/src/HOL/Library/Code_Target_Numeral"
begin
  subsection "Array Map"

  type_synonym 'v array_map = "'v option array"
  definition "iam_initial_size ≡ 8::nat"

  definition "iam_of_list l i ≡ if i<length l then l!i else None"

  definition is_iam :: "(nat\<rightharpoonup>'a) => ('a::heap) array_map => assn" where
    "is_iam m a ≡ ∃Al. a\<mapsto>al * \<up>(m=iam_of_list l)"

  definition iam_new_sz :: "nat => ('v::heap) array_map Heap"
    where "iam_new_sz sz ≡ Array.new sz None"

  definition iam_new :: "('v::heap) array_map Heap"
    where "iam_new ≡ iam_new_sz iam_initial_size"

  definition iam_lookup 
    :: "nat => ('v::heap) array_map => 'v option Heap"
    where "iam_lookup k a = do {
      l\<leftarrow>Array.len a;
      if k < l then Array.nth a k else return None
    }"

  lemma [code]: "iam_lookup k a ≡ nth_oo None a k"
    unfolding nth_oo_def iam_lookup_def .

  definition iam_delete
    :: "nat => ('v::heap) array_map => ('v::heap) array_map Heap"
  where "iam_delete k a = do {
      l\<leftarrow>Array.len a;
      if k < l then Array.upd k None a else return a
    }"

  lemma [code]: "iam_delete k a ≡ upd_oo (return a) k None a"
    unfolding upd_oo_def iam_delete_def .

  definition iam_update
    :: "nat => 'v::heap => 'v array_map => 'v array_map Heap"
    where "iam_update k v a = do {
      l\<leftarrow>Array.len a;
      a\<leftarrow>if k>=l then do {
          let newsz = max (k+1) (2 * l + 3);
          array_grow a newsz None
        } else return a;

      Array.upd k (Some v) a
    }"

  lemma [code]: "iam_update k v a = upd_oo 
    (do {
      l\<leftarrow>Array.len a;
      let newsz = max (k+1) (2 * l + 3);
      a\<leftarrow>array_grow a newsz None;
      Array.upd k (Some v) a
    })
    k (Some v) a"
  proof -
    have [simp]: 
      "!!x t e. do {
        l\<leftarrow>Array.len a;
        if x l then 
          t l 
        else do {
          l'\<leftarrow>Array.len a;
          e l l'
        } 
      }
      =
      do {
        l\<leftarrow>Array.len a;
        if x l then t l else e l l
      }"
      apply (auto 
        simp: bind_def execute_len 
        split: option.split
        intro!: ext
      )
      done
  
    show ?thesis
      unfolding upd_oo_def iam_update_def
      apply simp
      apply (rule cong[OF arg_cong, where f1=bind])
      apply simp
      apply (rule ext)
      apply auto
      done
  qed

  lemma precise_iam: "precise is_iam"
    apply rule
    by (auto simp add: is_iam_def dest: preciseD[OF snga_prec])

  lemma iam_new_abs: "iam_of_list (replicate n None) = Map.empty"
    unfolding iam_of_list_def[abs_def]
    by auto

  lemma iam_new_sz_rule: "<emp> iam_new_sz n < is_iam Map.empty >"
    unfolding iam_new_sz_def is_iam_def[abs_def]
    by (sep_auto simp: iam_new_abs)

  lemma iam_new_rule: "<emp> iam_new < is_iam Map.empty >"
    unfolding iam_new_def by (sep_auto heap: iam_new_sz_rule)

  lemma iam_lookup_abs1: "k<length l ==> iam_of_list l k = l!k"
    by (simp add: iam_of_list_def)
  lemma iam_lookup_abs2: "¬k<length l ==> iam_of_list l k = None"
    by (simp add: iam_of_list_def)

  lemma iam_lookup_rule: "< is_iam m p > 
    iam_lookup k p 
    <λr. is_iam m p * \<up>(r=m k) >"
    unfolding iam_lookup_def is_iam_def
    by (sep_auto simp: iam_lookup_abs1 iam_lookup_abs2)

  lemma iam_delete_abs1: "k<length l 
    ==> iam_of_list (l[k := None]) = iam_of_list l |` (- {k})"
    unfolding iam_of_list_def[abs_def]
    by (auto intro!: ext simp: restrict_map_def)

  lemma iam_delete_abs2: "¬k<length l 
    ==> iam_of_list l |` (- {k}) = iam_of_list l"
    unfolding iam_of_list_def[abs_def]
    by (auto intro!: ext simp: restrict_map_def)

  lemma iam_delete_rule: "< is_iam m p >
    iam_delete k p
    <λr. is_iam (m|`(-{k})) r>"
    unfolding is_iam_def iam_delete_def
    by (sep_auto simp: iam_delete_abs1 iam_delete_abs2)
    

  lemma iam_update_abs1: "iam_of_list (l@replicate n None) = iam_of_list l"
    unfolding iam_of_list_def[abs_def]
    by (auto intro!: ext simp: nth_append)

  lemma iam_update_abs2: "¬ length l ≤ k 
    ==> iam_of_list (l[k := Some v]) = iam_of_list l(k \<mapsto> v)"
    unfolding iam_of_list_def[abs_def]
    by auto

  lemma iam_update_rule:
    "< is_iam m p > iam_update k v p <λr. is_iam (m(k\<mapsto>v)) r>t"
    unfolding is_iam_def iam_update_def
    by (sep_auto 
      decon: decon_split_if 
      simp: iam_update_abs1 iam_update_abs2)
  
  interpretation iam: imp_map is_iam
    apply unfold_locales
    by (rule precise_iam)
  interpretation iam: imp_map_empty is_iam iam_new
    apply unfold_locales
    by (sep_auto heap: iam_new_rule)
  interpretation iam_sz: imp_map_empty is_iam "iam_new_sz sz"
    apply unfold_locales
    by (sep_auto heap: iam_new_sz_rule)
 
  interpretation iam: imp_map_lookup is_iam iam_lookup
    apply unfold_locales
    by (sep_auto heap: iam_lookup_rule)
  interpretation iam: imp_map_delete is_iam iam_delete
    apply unfold_locales
    by (sep_auto heap: iam_delete_rule)
  interpretation iam: imp_map_update is_iam iam_update
    apply unfold_locales
    by (sep_auto heap: iam_update_rule)

end