Library zoo_saturn.bstack_mpmc

Require Import zoo.prelude.
Require Import zoo.common.countable.
Require Import zoo.iris.base_logic.lib.twins.
Require Import zoo.base.
Require Import zoo_std.option.
Require Export zoo_saturn.bstack_mpmc__code.
Require Import zoo_saturn.bstack_mpmc__types.
Require Import zoo.options.

Implicit Type b : bool.
Implicit Type cap sz : nat.
Implicit Type l : location.
Implicit Type v t front : val.
Implicit Type vs : list val.

Class BstackMpmcG Σ `{zoo۰G : !ZooG Σ} :=
  { #[local] bstack_mpmc۰G۰model۰G :: TwinsG Σ (leibnizO (list val))
  }.

Definition bstack_mpmc۰Σ :=
  #[twins۰Σ (leibnizO (list val))
  ].
#[global] Instance subGbstack_mpmc۰Σ Σ `{zoo۰G : !ZooG Σ} :
  subG bstack_mpmc۰Σ Σ
  BstackMpmcG Σ.

Section bstack_mpmc۰G.
  Context `{bstack_mpmc۰G : BstackMpmcG Σ}.

  Record metadata :=
    { metadata۰capacity : nat
    ; metadata۰model : gname
    }.
  Implicit Type γ : metadata.

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

  #[local] Fixpoint list۰to_val sz vs :=
    match vs with
    | []
        §Nil%V
    | v :: vs
        Cons[ #sz, v, list۰to_val (sz - 1) vs ]%V
    end.

  #[local] Instance list۰to_valinjsimilar sz :
    Inj (=) (≈@{val}) (list۰to_val sz).
  #[local] Instance list۰to_valinj sz :
    Inj (=) (=) (list۰to_val sz).

  Lemma list۰to_valinj' vs1 vs2 :
    list۰to_val (length vs1) vs1 list۰to_val (length vs2) vs2
    vs1 = vs2.

  #[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 Σ :=
     vs,
    l.[front] list۰to_val (length vs) vs
    model₂ γ vs.
  #[local] Instance : CustomIpat "inv۰inner" :=
    " ( %vs{} & Hl_front & Hmodel₂ ) ".
  Definition bstack_mpmc۰inv t ι cap : iProp Σ :=
     l γ,
    t = #l
    l γ
    cap = γ.(metadata۰capacity)
    0 < γ.(metadata۰capacity)
    l.[capacity] #γ.(metadata۰capacity)
    inv ι (inv۰inner l γ).
  #[local] Instance : CustomIpat "inv" :=
    " ( %l & %γ & -> & #Hmeta & -> & %Hcapacity & #Hl_capacity & #Hinv ) ".

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

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

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

  #[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 bstack_mpmc۰modelvalid t ι cap vs :
    bstack_mpmc۰inv t ι cap -∗
    bstack_mpmc۰model t vs -∗
    length vs cap.
  Lemma bstack_mpmc۰modelexclusive t vs1 vs2 :
    bstack_mpmc۰model t vs1 -∗
    bstack_mpmc۰model t vs2 -∗
    False.

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

  Lemma bstack_mpmc٠sizespec t ι cap :
    <<<
      bstack_mpmc۰inv t ι cap
    | ∀∀ vs,
      bstack_mpmc۰model t vs
    >>>
      bstack_mpmc٠size t @ ι
    <<<
      bstack_mpmc۰model t vs
    | RET #(length vs);
      True
    >>>.

  Lemma bstack_mpmc٠is_emptyspec t ι cap :
    <<<
      bstack_mpmc۰inv t ι cap
    | ∀∀ vs,
      bstack_mpmc۰model t vs
    >>>
      bstack_mpmc٠is_empty t @ ι
    <<<
      bstack_mpmc۰model t vs
    | RET #(bool_decide (vs = []%list));
      True
    >>>.

  #[local] Lemma bstack_mpmc٠push_aux_pushspec t ι cap v :
     (
       (sz : Z) front ws,
      <<<
        sz = length ws
        front = list۰to_val (length ws) ws
        length ws < cap
        bstack_mpmc۰inv t ι cap
      | ∀∀ vs,
        bstack_mpmc۰model t vs
      >>>
        bstack_mpmc٠push_aux t #sz v front @ ι
      <<<
        ∃∃ b,
        b = bool_decide (length vs < cap)
        bstack_mpmc۰model t (if b then v :: vs else vs)
      | RET #b;
        True
      >>>
    ) (
      <<<
        bstack_mpmc۰inv t ι cap
      | ∀∀ vs,
        bstack_mpmc۰model t vs
      >>>
        bstack_mpmc٠push t v @ ι
      <<<
        ∃∃ b,
        b = bool_decide (length vs < cap)
        bstack_mpmc۰model t (if b then v :: vs else vs)
      | RET #b;
        True
      >>>
    ).
  Lemma bstack_mpmc٠pushspec t ι cap v :
    <<<
      bstack_mpmc۰inv t ι cap
    | ∀∀ vs,
      bstack_mpmc۰model t vs
    >>>
      bstack_mpmc٠push t v @ ι
    <<<
      ∃∃ b,
      b = bool_decide (length vs < cap)
      bstack_mpmc۰model t (if b then v :: vs else vs)
    | RET #b;
      True
    >>>.

  Lemma bstack_mpmc٠popspec t ι cap :
    <<<
      bstack_mpmc۰inv t ι cap
    | ∀∀ vs,
      bstack_mpmc۰model t vs
    >>>
      bstack_mpmc٠pop t @ ι
    <<<
      bstack_mpmc۰model t (tail vs)
    | RET head vs;
      True
    >>>.
End bstack_mpmc۰G.

Require zoo_saturn.bstack_mpmc__opaque.

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