Library zoo_saturn.bag_1

Require Import zoo.prelude.
Require Import zoo.common.countable.
Require Import zoo.common.gmultiset.
Require Import zoo.common.list.
Require Import zoo.iris.base_logic.lib.twins.
Require Import zoo.base.
Require Export zoo_saturn.bag_1__code.
Require Import zoo_saturn.bag_1__types.
Require Import zoo.options.

Implicit Type front back : nat.
Implicit Type l slot : location.
Implicit Type slots : list location.
Implicit Type v t data : val.
Implicit Type vs : gmultiset val.
Implicit Type o : option val.
Implicit Type os : list (option val).

Class Bag1G Σ `{zoo۰G : !ZooG Σ} :=
  { #[local] bag_1۰G۰model۰G :: TwinsG Σ (leibnizO (gmultiset val))
  }.

Definition bag_1۰Σ :=
  #[twins۰Σ (leibnizO (gmultiset val))
  ].
#[global] Instance subGbag_1۰Σ Σ `{zoo۰G : !ZooG Σ} :
  subG bag_1۰Σ Σ
  Bag1G Σ.

Section consistent.
  #[local] Definition consistent vs os :=
    vs = ⋃+ (singletonMS <$> oflatten os).

  #[local] Lemma consistentlookup vs os i v :
    os !! i = Some $ Some v
    consistent vs os
    v vs.
  #[local] Lemma consistentinsert {vs os i} v :
    os !! i = Some None
    consistent vs os
    consistent ({[+v+]} vs) (<[i := Some v]> os).
  #[local] Lemma consistentremove vs os i v :
    os !! i = Some $ Some v
    consistent vs os
    consistent (vs {[+v+]}) (<[i := None]> os).
End consistent.

Opaque consistent.

Section bag_1۰G.
  Context `{bag_1۰G : Bag1G Σ}.

  Record metadata :=
    { metadata۰data : val
    ; metadata۰slots : list location
    ; metadata۰inv : namespace
    ; metadata۰model : gname
    }.
  Implicit Type γ : metadata.

  #[local] Instance metadataeq_dec : EqDecision metadata :=
    ltac:(solve_decision).
  #[local] Instance metadatacountable :
    Countable metadata.

  #[local] Definition model₁' γ_model vs :=
    twins۰twin₁ γ_model (DfracOwn 1) vs.
  #[local] Definition model₁ γ vs :=
    model₁' γ.(metadata۰model) vs.
  #[local] Definition model₂' γ_model vs :=
    twins۰twin₂ γ_model vs.
  #[local] Definition model₂ γ vs :=
    model₂' γ.(metadata۰model) vs.

  #[local] Definition inv۰inner l γ : iProp Σ :=
     front back vs os,
    l.[front] #front
    l.[back] #back
    model₂ γ vs
    consistent vs os
    [∗ list] slot; o γ.(metadata۰slots); os,
      slot ↦ᵣ (o : val).
  #[local] Instance : CustomIpat "inv۰inner" :=
    " ( %front & %back & %vs & %os & Hfront & Hback & Hmodel₂ & >%Hconsistent & Hslots ) ".
  #[local] Definition inv' l γ :=
    inv γ.(metadata۰inv) (inv۰inner l γ).
  Definition bag_1۰inv t ι : iProp Σ :=
     l γ,
    t = #l
    ι = γ.(metadata۰inv)
    0 < length γ.(metadata۰slots)
    l γ
    l.[data] γ.(metadata۰data)
    array۰model γ.(metadata۰data) DfracDiscarded (#*@{location} γ.(metadata۰slots))
    inv' l γ.
  #[local] Instance : CustomIpat "inv" :=
    " ( %l & %γ & -> & -> & %Hsz & #Hmeta & #Hdata & #Hdata_model & #Hinv ) ".

  Definition bag_1۰model t vs : iProp Σ :=
     l γ,
    t = #l
    l γ
    model₁ γ vs.
  #[local] Instance : CustomIpat "model" :=
    " ( %l{;_} & %γ{;_} & %Heq{} & #Hmeta_{} & Hmodel₁{_{}} ) ".

  #[global] Instance bag_1۰modeltimeless t vs :
    Timeless (bag_1۰model t vs).

  #[global] Instance bag_1۰invpersistent t ι :
    Persistent (bag_1۰inv t ι).

  #[local] Lemma modelalloc :
     |==>
       γ_model,
      model₁' γ_model
      model₂' γ_model .
  #[local] Lemma model₁exclusive γ vs1 vs2 :
    model₁ γ vs1 -∗
    model₁ γ vs2 -∗
    False.
  #[local] Lemma modelagree γ vs1 vs2 :
    model₁ γ vs1 -∗
    model₂ γ vs2 -∗
    vs1 = vs2.
  #[local] Lemma modelupdate {γ vs1 vs2} vs :
    model₁ γ vs1 -∗
    model₂ γ vs2 ==∗
      model₁ γ vs
      model₂ γ vs.

  Lemma bag_1۰modelexclusive t vs1 vs2 :
    bag_1۰model t vs1 -∗
    bag_1۰model t vs2 -∗
    False.

  Lemma bag_1٠createspec ι (sz : Z) :
    (0 < sz)%Z
    {{{
      True
    }}}
      bag_1٠create #sz
    {{{
      t
    , RET t;
      bag_1۰inv t ι
      bag_1۰model t
    }}}.

  #[local] Lemma bag_1٠push₁spec slot v l γ :
    slot γ.(metadata۰slots)
    <<<
      l γ
      inv' l γ
    | ∀∀ vs,
      bag_1۰model #l vs
    >>>
      bag_1٠push₁ #slot Some[ v ] @ γ.(metadata۰inv)
    <<<
      bag_1۰model #l ({[+v+]} vs)
    | RET ();
      True
    >>>.
  Lemma bag_1٠pushspec t ι v :
    <<<
      bag_1۰inv t ι
    | ∀∀ vs,
      bag_1۰model t vs
    >>>
      bag_1٠push t v @ ι
    <<<
      bag_1۰model t ({[+v+]} vs)
    | RET ();
      True
    >>>.

  #[local] Lemma bag_1٠pop₁spec slot l γ :
    slot γ.(metadata۰slots)
    <<<
      l γ
      inv' l γ
    | ∀∀ vs,
      bag_1۰model #l vs
    >>>
      bag_1٠pop₁ #slot @ γ.(metadata۰inv)
    <<<
      ∃∃ v vs',
      vs = {[+v+]} vs'
      bag_1۰model #l vs'
    | RET v;
      True
    >>>.
  Lemma bag_1٠popspec t ι :
    <<<
      bag_1۰inv t ι
    | ∀∀ vs,
      bag_1۰model t vs
    >>>
      bag_1٠pop t @ ι
    <<<
      ∃∃ v vs',
      vs = {[+v+]} vs'
      bag_1۰model t vs'
    | RET v;
      True
    >>>.
End bag_1۰G.

Require zoo_saturn.bag_1__opaque.

#[global] Opaque bag_1۰inv.
#[global] Opaque bag_1۰model.