Guarantees by Construction (Mechanization)

Jules Jacobs

From iris.algebra Require Import excl gmap.

Definition map_Excl `{Countable K} {V} (m : gmap K V) : gmap K (excl V) :=
  Excl <$> m.

Global Instance : Params (@map_Excl) 4 := {}.

Section map_Excl.
  Context `{Countable K} {V : ofe}.
  Implicit Type m : gmap K V.

  Global Instance map_excl_proper : Proper (() ==> ()) (map_Excl (K:=K) (V:=V)).
  Proof. solve_proper. Qed.

  Lemma map_Excl_valid m :  (map_Excl m).
  Proof. intros i. rewrite /map_Excl lookup_fmap. destruct (m !! i); done. Qed.
  Lemma map_Excl_empty : map_Excl  = (ε : gmap K (excl V)).
  Proof. rewrite /map_Excl fmap_empty. done. Qed.
  Lemma map_Excl_empty_inv m : map_Excl m   -> m = .
  Proof.
    rewrite /map_Excl. intros G.
    apply map_empty_equiv_eq in G.
    eapply fmap_empty_iff. done.
  Qed.

  Lemma map_Excl_injective m1 m2 :
    map_Excl m1  map_Excl m2 -> m1  m2.
  Proof.
    rewrite /map_Excl.
    intros Hm i.
    specialize (Hm i).
    rewrite !lookup_fmap in Hm.
    destruct (m1 !! i),(m2 !! i); simpl in *; inversion Hm; subst; try done.
    inversion H2. subst. rewrite H3. done.
  Qed.
  Lemma map_Excl_insert m k v :
    map_Excl (<[ k := v ]> m) = <[ k := Excl v ]> $ map_Excl m.
  Proof.
    rewrite /map_Excl fmap_insert //.
  Qed.
  Lemma map_Excl_insert_op m k v :
    m !! k = None ->
    map_Excl (<[ k := v ]> m) = {[ k := Excl v ]}  map_Excl m.
  Proof.
    intros HH.
    rewrite /map_Excl fmap_insert insert_singleton_op //
            lookup_fmap HH //.
  Qed.
  Lemma map_Excl_union m1 m2 :
    m1 ## m2 -> map_Excl (m1  m2)  map_Excl m1  map_Excl m2.
  Proof.
    induction m1 using map_ind; intros; decompose_map_disjoint.
    - by rewrite map_Excl_empty !left_id_L.
    - assert ((m  m2) !! i = None).
      { rewrite lookup_union H0 H1 //. }
      rewrite -insert_union_l !map_Excl_insert_op // IHm1 // assoc //.
  Qed.
  Lemma map_Excl_valid_op m1 m2 :  (map_Excl m1  map_Excl m2)  m1 ## m2.
  Proof.
    split; last first.
    { intros. rewrite -map_Excl_union //. apply map_Excl_valid. }
    induction m1 as [|k x m1 Hm1 IH] using map_ind.
    { intros _. apply map_disjoint_empty_l. }
    rewrite map_Excl_insert_op // -assoc. intros Hvalid.
    apply map_disjoint_insert_l_2; last by eapply IH, cmra_valid_op_r.
    apply eq_None_not_Some; intros [x' Hm2].
    move: (Hvalid k).
    by rewrite !lookup_op /map_Excl lookup_singleton !lookup_fmap Hm1 Hm2.
  Qed.
  Lemma map_Excl_singleton_op_inv m me k x :
    map_Excl m  {[ k := Excl x ]}  me ->
     m', m  <[ k := x ]> m'  me  map_Excl m'  m' !! k = None.
  Proof.
    rewrite /map_Excl. intros HH.
    exists (delete k m).
    assert (m !! k  Some x).
    { specialize (HH k).
      revert HH. rewrite lookup_fmap lookup_op lookup_singleton.
      case: (m!!k); case:(me!!k); simpl; intros; inversion HH; subst;
      inversion H2; subst. rewrite H3. done. }
    split_and!.
    - intros i.
      destruct (decide (k = i)); subst.
      + rewrite lookup_insert //.
      + rewrite lookup_insert_ne // lookup_delete_ne //.
    - intros i.
      specialize (HH i).
      destruct (decide (k = i)); subst.
      + rewrite lookup_fmap lookup_delete.
        revert HH. rewrite !lookup_fmap lookup_op lookup_singleton H0 /=.
        case: (me !! i); eauto.
        intros a HH. inversion HH. subst. inversion H3.
      + rewrite lookup_fmap lookup_delete_ne //.
        revert HH. rewrite lookup_fmap lookup_op lookup_singleton_ne //.
        case: (me !! i); simpl; intros; inversion HH; subst; eauto.
        rewrite H3. done.
    - rewrite lookup_delete //.
  Qed.
  Lemma map_Excl_union_inv m me1 me2 :
    map_Excl m  me1  me2 ->
     m1 m2, m  m1  m2  me1  map_Excl m1  me2  map_Excl m2  m1 ## m2.
  Proof.
    revert m. induction me1 as [|k xe me1 Hx IH] using map_ind; intros m.
    - rewrite left_id_L. intros Hr1.
      exists ,m.
      rewrite left_id_L map_Excl_empty. split_and!; try solve_map_disjoint.
    - rewrite insert_singleton_op // -assoc.
      destruct xe as [x|].
      + intros (m' & Hr1 & ? & ?)%map_Excl_singleton_op_inv.
        setoid_rewrite Hr1.
        destruct (IH m') as (m1 & m2 & Hr2 & Hr3 & Hr4 & ?); first done.
        exists (<[ k := x]> m1),m2.
        assert (m' !! k  None) as H1'. { rewrite H1 //. }
        rewrite ->Hr2 in H1'.
        apply None_equiv_eq in H1'.
        apply lookup_union_None in H1' as [].
        repeat split.
        * rewrite Hr2. rewrite insert_union_l //.
        * rewrite map_Excl_insert_op //. rewrite Hr3 //.
        * done.
        * by apply map_disjoint_insert_l.
      + intros Hm. assert ( (ExclBot : excl V)) as [].
        eapply (singleton_valid k), (cmra_valid_op_l _ (me1  me2)).
        rewrite -Hm. apply map_Excl_valid.
  Qed.
  Lemma map_Excl_disjoint m1 m2 :
    m1 ## m2 <-> map_Excl m1 ## map_Excl m2.
  Proof.
    split; first apply map_disjoint_fmap.
    unfold map_Excl. intros G ?. specialize (G i).
    rewrite !lookup_fmap in G.
    destruct (m1 !! i),(m2 !! i); done.
  Qed.
  Lemma map_Excl_singleton (a : K) (b : V) :
    map_Excl {[ a := b ]} = {[ a := Excl b ]}.
  Proof.
    rewrite /map_Excl map_fmap_singleton //.
  Qed.
  Lemma map_Excl_singleton_inv a b m :
    map_Excl m  {[ a := Excl b ]} -> m  {[ a := b ]}.
  Proof.
    intros HH.
    intros i.
    specialize (HH i).
    destruct (decide (i = a)); subst.
    - rewrite lookup_singleton. rewrite lookup_fmap in HH.
      rewrite lookup_singleton in HH.
      inversion HH. subst. inversion H2. subst.
      destruct (m !! a) eqn:E; simpl in *.
      + inversion HH; subst.
        inversion H5; subst. rewrite H6. done.
      + inversion HH.
    - rewrite lookup_singleton_ne //.
      rewrite lookup_singleton_ne // in HH.
      unfold map_Excl in HH.
      rewrite lookup_fmap in HH.
      inversion HH. symmetry in H1.
      apply fmap_None in H1. rewrite H1 //.
  Qed.
End map_Excl.