vericert.hls.AssocMap




Definition reg := positive.

Module AssocMap := Maps.PTree.

Module AssocMapExt.

  #[export] Hint Resolve elements_correct elements_complete elements_keys_norepet : assocmap.
  #[export] Hint Resolve gso gss : assocmap.

  Section Operations.

    Variable A : Type.

    Definition get_default (a : A) (k : reg) (m : t A) : A :=
      match get k m with
      | None => a
      | Some v => v
      end.

    Fixpoint merge (m1 m2 : t A) : t A :=
      match m1, m2 with
      | Node l1 (Some a) r1, Node l2 _ r2 => Node (merge l1 l2) (Some a) (merge r1 r2)
      | Node l1 None r1, Node l2 o r2 => Node (merge l1 l2) o (merge r1 r2)
      | Leaf, _ => m2
      | _, _ => m1
      end.

    Lemma merge_base_1 :
      forall am,
      merge (empty A) am = am.

    Lemma merge_base_2 :
      forall am,
      merge am (empty A) = am.

    Lemma merge_add_assoc :
      forall r am am' v,
      merge (set r v am) am' = set r v (merge am am').

    Lemma merge_correct_1 :
      forall am bm k v,
      get k am = Some v ->
      get k (merge am bm) = Some v.

    Lemma merge_correct_2 :
      forall am bm k v,
      get k am = None ->
      get k bm = Some v ->
      get k (merge am bm) = Some v.

    Lemma merge_correct_3 :
      forall am bm k,
      get k am = None ->
      get k bm = None ->
      get k (merge am bm) = None.

    Definition merge_fold (am bm : t A) : t A :=
      fold_right (fun p a => set (fst p) (snd p) a) bm (elements am).

    Lemma add_assoc :
      forall (k : elt) (v : A) l bm,
      List.In (k, v) l ->
      list_norepet (List.map fst l) ->
      @get A k (fold_right (fun p a => set (fst p) (snd p) a) bm l) = Some v.

    Lemma not_in_assoc :
      forall k v l bm,
      ~ List.In k (List.map (@fst elt A) l) ->
      @get A k bm = Some v ->
      get k (fold_right (fun p a => set (fst p) (snd p) a) bm l) = Some v.

    Lemma elements_iff :
      forall am k,
      (exists v, get k am = Some v) <->
      List.In k (List.map (@fst _ A) (elements am)).

    #[local] Hint Resolve merge_base_1 : core.
    #[local] Hint Resolve merge_base_2 : core.
    #[local] Hint Resolve merge_add_assoc : core.
    #[local] Hint Resolve merge_correct_1 : core.
    #[local] Hint Resolve merge_correct_2 : core.
    #[local] Hint Resolve merge_correct_3 : core.
    #[local] Hint Resolve add_assoc : core.
    #[local] Hint Resolve not_in_assoc : core.
    #[local] Hint Resolve elements_iff : core.

    Lemma elements_correct' :
      forall am k,
      ~ (exists v, get k am = Some v) <->
      ~ List.In k (List.map (@fst _ A) (elements am)).

    Lemma elements_correct_none :
      forall am k,
      get k am = None ->
      ~ List.In k (List.map (@fst _ A) (elements am)).

    Lemma merge_fold_add :
      forall k v am bm,
      am ! k = Some v ->
      (merge_fold am bm) ! k = Some v.

    #[local] Hint Resolve elements_correct' : core.
    #[local] Hint Resolve elements_correct_none : core.
    #[local] Hint Resolve merge_fold_add : core.

    Lemma merge_fold_not_in :
      forall k v am bm,
      get k am = None ->
      get k bm = Some v ->
      get k (merge_fold am bm) = Some v.

    Lemma merge_fold_base :
      forall am,
      merge_fold (empty A) am = am.

  End Operations.

  #[export] Hint Resolve merge_base_1 : assocmap.
  #[export] Hint Resolve merge_base_2 : assocmap.
  #[export] Hint Resolve merge_add_assoc : assocmap.
  #[export] Hint Resolve merge_correct_1 : assocmap.
  #[export] Hint Resolve merge_correct_2 : assocmap.
  #[export] Hint Resolve merge_correct_3 : assocmap.
  #[export] Hint Resolve add_assoc : assocmap.
  #[export] Hint Resolve not_in_assoc : assocmap.
  #[export] Hint Resolve elements_iff : assocmap.
  #[export] Hint Resolve elements_correct' : assocmap.
  #[export] Hint Resolve merge_fold_not_in : assocmap.
  #[export] Hint Resolve merge_fold_base : assocmap.
  #[export] Hint Resolve elements_correct_none : assocmap.
  #[export] Hint Resolve merge_fold_add : assocmap.

End AssocMapExt.

Definition assocmap := AssocMap.t value.

Definition find_assocmap (n : nat) : reg -> assocmap -> value :=
  get_default value (ZToValue 0).

Definition empty_assocmap : assocmap := AssocMap.empty value.

Definition merge_assocmap : assocmap -> assocmap -> assocmap := merge value.


Notation "a ! b" := (AssocMap.get b a) (at level 1) : assocmap.
Notation "a # ( b , c )" := (find_assocmap c b a) (at level 1) : assocmap.
Notation "a # b" := (find_assocmap 32 b a) (at level 1) : assocmap.
Notation "a ## b" := (List.map (fun c => find_assocmap 32 c a) b) (at level 1) : assocmap.
Notation "a # b '<-' c" := (AssocMap.set b c a) (at level 1, b at next level) : assocmap.

Lemma find_get_assocmap :
  forall assoc r v,
  assoc ! r = Some v ->
  assoc # r = v.