Library zoo_saturn.inf_ws_deque_2

From zoo Require Import
  prelude.
From zoo.common Require Import
  countable
  relations.
From zoo.iris.bi Require Import
  big_op.
From zoo.iris.base_logic Require Import
  lib.auth_twins.
From zoo.language Require Import
  notations.
From zoo.diaframe Require Import
  diaframe.
From zoo_std Require Import
  option.
From zoo_saturn Require Export
  base
  inf_ws_deque_2__code.
From zoo_saturn Require Import
  inf_ws_deque_1.
From zoo Require Import
  options.

Import inf_ws_deque_1.base.

Implicit Types slot : location.
Implicit Types slots : list location.
Implicit Types v : val.
Implicit Types vs ws : list val.

Class InfWsDeque2G Σ `{zoo_G : !ZooG Σ} :=
  { #[local] inf_ws_deque_2_G_base_G :: InfWsDeque1G Σ
  ; #[local] inf_ws_deque_2_G_model_G :: AuthTwinsG Σ (leibnizO (list val)) suffix
  }.

Definition inf_ws_deque_2_Σ :=
  #[inf_ws_deque_1_Σ
  ; auth_twins_Σ (leibnizO (list val)) suffix
  ].
#[global] Instance subG_inf_ws_deque_2_Σ Σ `{zoo_G : !ZooG Σ} :
  subG inf_ws_deque_2_Σ Σ
  InfWsDeque2G Σ .

Module base.
  Section inf_ws_deque_2_G.
    Context `{inf_ws_deque_2_G : InfWsDeque2G Σ}.

    Implicit Types t : location.

    Record inf_ws_deque_2_name :=
      { inf_ws_deque_2_name_base : inf_ws_deque_1_name
      ; inf_ws_deque_2_name_model : auth_twins_name
      }.
    Implicit Type γ : inf_ws_deque_2_name.

    #[global] Instance inf_ws_deque_2_name_eq_dec : EqDecision inf_ws_deque_2_name :=
      ltac:(solve_decision).
    #[global] Instance inf_ws_deque_2_name_countable :
      Countable inf_ws_deque_2_name.

    #[local] Definition model₁' γ_model vs :=
      auth_twins_twin1 _ γ_model vs.
    #[local] Definition model₁ γ :=
      model₁' γ.(inf_ws_deque_2_name_model).
    #[local] Definition model₂' γ_model vs :=
      auth_twins_twin2 _ γ_model vs.
    #[local] Definition model₂ γ :=
      model₂' γ.(inf_ws_deque_2_name_model).

    #[local] Definition owner' γ_owner ws :=
      auth_twins_auth _ γ_owner ws.
    #[local] Definition owner γ :=
      owner' γ.(inf_ws_deque_2_name_model).

    #[local] Definition inv_inner γ : iProp Σ :=
       vs slots,
      inf_ws_deque_1_model γ.(inf_ws_deque_2_name_base) (#*@{location} slots)
      model₂ γ vs
      [∗ list] slot; v slots; vs, slot ↦ᵣ v.
    #[local] Instance : CustomIpat "inv_inner" :=
      " ( %vs{} & %slots{} & >Hbase_model & >Hmodel₂ & >Hslots ) ".
    Definition inf_ws_deque_2_inv t γ ι : iProp Σ :=
      inf_ws_deque_1_inv t γ.(inf_ws_deque_2_name_base) (ι.@"base")
      inv (ι.@"inv") (inv_inner γ).
    #[local] Instance : CustomIpat "inv" :=
      " ( #Hbase_inv & #Hinv ) ".

    Definition inf_ws_deque_2_model :=
      model₁.
    #[local] Instance : CustomIpat "model" :=
      " Hmodel₁{_{}} ".

    Definition inf_ws_deque_2_owner γ ws : iProp Σ :=
       slots_owner,
      inf_ws_deque_1_owner γ.(inf_ws_deque_2_name_base) (#*@{location} slots_owner)
      owner γ ws.
    #[local] Instance : CustomIpat "owner" :=
      " ( %slots_owner{_{}} & Hbase_owner{_{}} & Howner{_{}} ) ".

    #[global] Instance inf_ws_deque_2_model_timeless γ vs :
      Timeless (inf_ws_deque_2_model γ vs).
    #[global] Instance inf_ws_deque_2_owner_timeless γ ws :
      Timeless (inf_ws_deque_2_owner γ ws).

    #[global] Instance inf_ws_deque_2_inv_persistent t γ ι :
      Persistent (inf_ws_deque_2_inv t γ ι).

    #[local] Lemma model_owner_alloc :
       |==>
         γ_model,
        model₁' γ_model []
        model₂' γ_model []
        owner' γ_model [].
    #[local] Lemma model₁_valid γ ws vs :
      owner γ ws -∗
      model₁ γ vs -∗
      vs `suffix_of` ws.
    #[local] Lemma model₁_exclusive γ vs1 vs2 :
      model₁ γ vs1 -∗
      model₁ γ vs2 -∗
      False.
    #[local] Lemma model_agree γ vs1 vs2 :
      model₁ γ vs1 -∗
      model₂ γ vs2 -∗
      vs1 = vs2.
    #[local] Lemma model_owner_agree γ ws vs1 vs2 :
      owner γ ws -∗
      model₁ γ vs1 -∗
      model₂ γ vs2 -∗
        vs1 `suffix_of` ws
        vs1 = vs2.
    #[local] Lemma model_push {γ ws vs1 vs2} v :
      owner γ ws -∗
      model₁ γ vs1 -∗
      model₂ γ vs2 ==∗
        owner γ (vs1 ++ [v])
        model₁ γ (vs1 ++ [v])
        model₂ γ (vs1 ++ [v]).
    #[local] Lemma model_steal γ vs1 vs2 :
      model₁ γ vs1 -∗
      model₂ γ vs2 ==∗
        model₁ γ (tail vs1)
        model₂ γ (tail vs1).
    #[local] Lemma model_pop γ ws vs1 vs2 :
      owner γ ws -∗
      model₁ γ vs1 -∗
      model₂ γ vs2 ==∗
        owner γ (removelast vs1)
        model₁ γ (removelast vs1)
        model₂ γ (removelast vs1).

    #[local] Lemma owner_update γ ws vs :
      owner γ ws -∗
      model₁ γ vs -∗
      model₂ γ vs ==∗
        owner γ vs
        model₁ γ vs
        model₂ γ vs.
    #[local] Lemma owner_exclusive γ ws1 ws2 :
      owner γ ws1 -∗
      owner γ ws2 -∗
      False.

    Lemma inf_ws_deque_2_model_exclusive γ vs1 vs2 :
      inf_ws_deque_2_model γ vs1 -∗
      inf_ws_deque_2_model γ vs2 -∗
      False.

    Lemma inf_ws_deque_2_owner_exclusive γ ws1 ws2 :
      inf_ws_deque_2_owner γ ws1 -∗
      inf_ws_deque_2_owner γ ws2 -∗
      False.
    Lemma inf_ws_deque_2_owner_model γ ws vs :
      inf_ws_deque_2_owner γ ws -∗
      inf_ws_deque_2_model γ vs -∗
      vs `suffix_of` ws.

    Lemma inf_ws_deque_2٠create𑁒spec ι :
      {{{
        True
      }}}
        inf_ws_deque_2٠create ()
      {{{
        t γ
      , RET #t;
        meta_token t
        inf_ws_deque_2_inv t γ ι
        inf_ws_deque_2_model γ []
        inf_ws_deque_2_owner γ []
      }}}.

    Lemma inf_ws_deque_2٠size𑁒spec t γ ι ws :
      <<<
        inf_ws_deque_2_inv t γ ι
        inf_ws_deque_2_owner γ ws
      | ∀∀ vs,
        inf_ws_deque_2_model γ vs
      >>>
        inf_ws_deque_2٠size #t @ ι
      <<<
        vs `suffix_of` ws
        inf_ws_deque_2_model γ vs
      | RET #(length vs);
        inf_ws_deque_2_owner γ vs
      >>>.

    Lemma inf_ws_deque_2٠is_empty𑁒spec t γ ι ws :
      <<<
        inf_ws_deque_2_inv t γ ι
        inf_ws_deque_2_owner γ ws
      | ∀∀ vs,
        inf_ws_deque_2_model γ vs
      >>>
        inf_ws_deque_2٠is_empty #t @ ι
      <<<
        vs `suffix_of` ws
        inf_ws_deque_2_model γ vs
      | RET #(bool_decide (vs = []%list));
        inf_ws_deque_2_owner γ vs
      >>>.

    Lemma inf_ws_deque_2٠push𑁒spec t γ ι ws v :
      <<<
        inf_ws_deque_2_inv t γ ι
        inf_ws_deque_2_owner γ ws
      | ∀∀ vs,
        inf_ws_deque_2_model γ vs
      >>>
        inf_ws_deque_2٠push #t v @ ι
      <<<
        vs `suffix_of` ws
        inf_ws_deque_2_model γ (vs ++ [v])
      | RET ();
        inf_ws_deque_2_owner γ (vs ++ [v])
      >>>.

    Lemma inf_ws_deque_2٠steal𑁒spec t γ ι :
      <<<
        inf_ws_deque_2_inv t γ ι
      | ∀∀ vs,
        inf_ws_deque_2_model γ vs
      >>>
        inf_ws_deque_2٠steal #t @ ι
      <<<
        inf_ws_deque_2_model γ (tail vs)
      | RET head vs;
        True
      >>>.

    Lemma inf_ws_deque_2٠pop𑁒spec t γ ι ws :
      <<<
        inf_ws_deque_2_inv t γ ι
        inf_ws_deque_2_owner γ ws
      | ∀∀ vs,
        inf_ws_deque_2_model γ vs
      >>>
        inf_ws_deque_2٠pop #t @ ι
      <<<
        ∃∃ o ws',
        vs `suffix_of` ws
        match o with
        | None
            vs = []
            ws' = []
            inf_ws_deque_2_model γ []
        | Some v
             vs',
            vs = vs' ++ [v]
            ws' = vs'
            inf_ws_deque_2_model γ vs'
        end
      | RET o;
        inf_ws_deque_2_owner γ ws'
      >>>.
  End inf_ws_deque_2_G.

  #[global] Opaque inf_ws_deque_2_inv.
  #[global] Opaque inf_ws_deque_2_model.
  #[global] Opaque inf_ws_deque_2_owner.
End base.

From zoo_saturn Require
  inf_ws_deque_2__opaque.

Section inf_ws_deque_2_G.
  Context `{inf_ws_deque_2_G : InfWsDeque2G Σ}.

  Implicit Types 𝑡 : location.
  Implicit Types t : val.

  Definition inf_ws_deque_2_inv t ι : iProp Σ :=
     𝑡 γ,
    t = #𝑡
    meta 𝑡 nroot γ
    base.inf_ws_deque_2_inv 𝑡 γ ι.
  #[local] Instance : CustomIpat "inv" :=
    " ( %𝑡{} & %γ{} & {%Heq{};->} & #Hmeta{_{}} & Hinv{_{}} ) ".

  Definition inf_ws_deque_2_model t vs : iProp Σ :=
     𝑡 γ,
    t = #𝑡
    meta 𝑡 nroot γ
    base.inf_ws_deque_2_model γ vs.
  #[local] Instance : CustomIpat "model" :=
    " ( %𝑡{} & %γ{} & {%Heq{};->} & #Hmeta{_{}} & Hmodel{_{}} ) ".

  Definition inf_ws_deque_2_owner t ws : iProp Σ :=
     𝑡 γ,
    t = #𝑡
    meta 𝑡 nroot γ
    base.inf_ws_deque_2_owner γ ws.
  #[local] Instance : CustomIpat "owner" :=
    " ( %𝑡{} & %γ{} & {%Heq{};->} & #Hmeta{_{}} & Howner{_{}} ) ".

  #[global] Instance inf_ws_deque_2_model_timeless γ vs :
    Timeless (inf_ws_deque_2_model γ vs).
  #[global] Instance inf_ws_deque_2_owner_timeless γ ws :
    Timeless (inf_ws_deque_2_owner γ ws).

  #[global] Instance inf_ws_deque_2_inv_persistent t ι :
    Persistent (inf_ws_deque_2_inv t ι).

  Lemma inf_ws_deque_2_model_exclusive t vs1 vs2 :
    inf_ws_deque_2_model t vs1 -∗
    inf_ws_deque_2_model t vs2 -∗
    False.

  Lemma inf_ws_deque_2_owner_exclusive t ws1 ws2 :
    inf_ws_deque_2_owner t ws1 -∗
    inf_ws_deque_2_owner t ws2 -∗
    False.
  Lemma inf_ws_deque_2_owner_model γ ws vs :
    inf_ws_deque_2_owner γ ws -∗
    inf_ws_deque_2_model γ vs -∗
    vs `suffix_of` ws.

  Lemma inf_ws_deque_2٠create𑁒spec ι :
    {{{
      True
    }}}
      inf_ws_deque_2٠create ()
    {{{
      t
    , RET t;
      inf_ws_deque_2_inv t ι
      inf_ws_deque_2_model t []
      inf_ws_deque_2_owner t []
    }}}.

  Lemma inf_ws_deque_2٠size𑁒spec t ι ws :
    <<<
      inf_ws_deque_2_inv t ι
      inf_ws_deque_2_owner t ws
    | ∀∀ vs,
      inf_ws_deque_2_model t vs
    >>>
      inf_ws_deque_2٠size t @ ι
    <<<
      vs `suffix_of` ws
      inf_ws_deque_2_model t vs
    | RET #(length vs);
      inf_ws_deque_2_owner t vs
    >>>.

  Lemma inf_ws_deque_2٠is_empty𑁒spec t ι ws :
    <<<
      inf_ws_deque_2_inv t ι
      inf_ws_deque_2_owner t ws
    | ∀∀ vs,
      inf_ws_deque_2_model t vs
    >>>
      inf_ws_deque_2٠is_empty t @ ι
    <<<
      vs `suffix_of` ws
      inf_ws_deque_2_model t vs
    | RET #(bool_decide (vs = []%list));
      inf_ws_deque_2_owner t vs
    >>>.

  Lemma inf_ws_deque_2٠push𑁒spec t ι ws v :
    <<<
      inf_ws_deque_2_inv t ι
      inf_ws_deque_2_owner t ws
    | ∀∀ vs,
      inf_ws_deque_2_model t vs
    >>>
      inf_ws_deque_2٠push t v @ ι
    <<<
      vs `suffix_of` ws
      inf_ws_deque_2_model t (vs ++ [v])
    | RET ();
      inf_ws_deque_2_owner t (vs ++ [v])
    >>>.

  Lemma inf_ws_deque_2٠steal𑁒spec t ι :
    <<<
      inf_ws_deque_2_inv t ι
    | ∀∀ vs,
      inf_ws_deque_2_model t vs
    >>>
      inf_ws_deque_2٠steal t @ ι
    <<<
      inf_ws_deque_2_model t (tail vs)
    | RET head vs;
      True
    >>>.

  Lemma inf_ws_deque_2٠pop𑁒spec t ι ws :
    <<<
      inf_ws_deque_2_inv t ι
      inf_ws_deque_2_owner t ws
    | ∀∀ vs,
      inf_ws_deque_2_model t vs
    >>>
      inf_ws_deque_2٠pop t @ ι
    <<<
      ∃∃ o ws',
      vs `suffix_of` ws
      match o with
      | None
          vs = []
          ws' = []
          inf_ws_deque_2_model t []
      | Some v
           vs',
          vs = vs' ++ [v]
          ws' = vs'
          inf_ws_deque_2_model t vs'
      end
    | RET o;
      inf_ws_deque_2_owner t ws'
    >>>.
End inf_ws_deque_2_G.

#[global] Opaque inf_ws_deque_2_inv.
#[global] Opaque inf_ws_deque_2_model.
#[global] Opaque inf_ws_deque_2_owner.