Library zoo_saturn.queue_mpmc_2

Require Import zoo.prelude.
Require Import zoo.common.countable.
Require Import zoo.common.relations.
Require Import zoo.iris.base_logic.lib.twins.
Require Import zoo.iris.base_logic.lib.auth_mono.
Require Import zoo.iris.base_logic.lib.auth_nat_max.
Require Import zoo.base.
Require Import zoo.program_logic.prophet_bool.
Require Import zoo_std.option.
Require Export zoo_saturn.queue_mpmc_2__code.
Require Import zoo_saturn.queue_mpmc_2__types.
Require Import zoo.options.

Implicit Type strong : bool.
Implicit Type l back back_prev : location.
Implicit Type backs : gmap location nat.
Implicit Type v w t pref suff 𝑚𝑜𝑣𝑒 : val.
Implicit Type o : option val.
Implicit Type vs vs_front vs_back move : list val.

Variant emptiness :=
  | Empty
  | Nonempty.
Implicit Type empty : emptiness.

#[local] Instance emptinessinhabited : Inhabited emptiness :=
  populate Empty.
#[local] Instance emptinesseq_dec : EqDecision emptiness :=
  ltac:(solve_decision).

Variant status :=
  | Stable empty
  | Unstable back move.
Implicit Type status : status.

#[local] Instance statusinhabited : Inhabited status :=
  populate (Stable inhabitant).
#[local] Instance statuseq_dec : EqDecision status :=
  ltac:(solve_decision).

Record state :=
  { state۰backs : gmap location nat
  ; state۰index : nat
  ; state۰status : status
  }.
Implicit Type state : state.

#[local] Definition state۰with_status state status :=
  {|state۰backs := state.(state۰backs)
  ; state۰index := state.(state۰index)
  ; state۰status := status
  |}.

Definition state۰wf backs i :=
  map_Forall (λ _ i_back, i_back i) backs.

#[local] Definition state۰le state1 state2 :=
  state1.(state۰backs) state2.(state۰backs)
  state1.(state۰index) state2.(state۰index).

#[local] Instance stateinhabited : Inhabited state :=
  populate
    {|state۰backs := inhabitant
    ; state۰index := inhabitant
    ; state۰status := inhabitant
    |}.

#[local] Instance state۰lereflexive :
  Reflexive state۰le.
#[local] Instance state۰letransitive :
  Transitive state۰le.

Variant step : relation state :=
  | stepempty state1 state2 :
      state1.(state۰status) = Stable Nonempty
      state2 = state۰with_status state1 (Stable Empty)
      step state1 state2
  | stepdestabilize state1 state2 back move :
      state1.(state۰status) = Stable Empty
      state2 = state۰with_status state1 (Unstable back move)
      step state1 state2
  | stepstabilize state1 state2 back move :
      state1.(state۰status) = Unstable back move
      state1.(state۰backs) !! back = None
      state2 =
        {|state۰backs := <[back := state1.(state۰index) + length move]> state1.(state۰backs)
        ; state۰index := state1.(state۰index) + length move
        ; state۰status := Stable Nonempty
        |}
      step state1 state2.
#[local] Hint Constructors step : core.

#[local] Definition steps :=
  rtc step.

#[local] Lemma stepmono state1 state2 :
  step state1 state2
  state۰le state1 state2.
#[local] Lemma stepsmono state1 state2 :
  steps state1 state2
  state۰le state1 state2.

Class QueueMpmc2G Σ `{zoo۰G : !ZooG Σ} :=
  { #[local] queue_mpmc_2۰G۰model۰G :: TwinsG Σ (leibnizO (list val))
  ; #[local] queue_mpmc_2۰G۰state۰G :: AuthMonoG (A := leibnizO state) Σ step
  ; #[local] queue_mpmc_2۰G۰front۰G :: AuthNatMaxG Σ
  }.

Definition queue_mpmc_2۰Σ :=
  #[twins۰Σ (leibnizO (list val))
  ; auth_mono۰Σ (A := leibnizO state) step
  ; auth_nat_max۰Σ
  ].
#[global] Instance subGqueue_mpmc_2۰Σ Σ `{zoo۰G : !ZooG Σ} :
  subG queue_mpmc_2۰Σ Σ
  QueueMpmc2G Σ.

#[local] Fixpoint suffix۰to_val (i : nat) vs : val :=
  match vs with
  | []
      Front[ #i ]
  | v :: vs
      Cons[ #i, v, suffix۰to_val ˖i vs ]
  end.

#[local] Lemma suffix۰to_valgenerative i1 vs1 i2 vs2 :
  suffix۰to_val i1 vs1 suffix۰to_val i2 vs2
  suffix۰to_val i1 vs1 = suffix۰to_val i2 vs2.

#[local] Instance suffix۰to_valinj2 :
  Inj2 (=) (=) (=) suffix۰to_val.
#[local] Instance suffix۰to_valinj2' :
  Inj2 (=) (=) (≈) suffix۰to_val.

#[local] Fixpoint prefix۰to_val (i : nat) back vs : val :=
  match vs with
  | []
      #back
  | v :: vs
      Snoc[ #(i + ˖(length vs)), v, prefix۰to_val i back vs ]
  end.

#[local] Lemma prefix۰to_valgenerative i1 back1 vs1 i2 back2 vs2 :
  prefix۰to_val i1 back1 vs1 prefix۰to_val i2 back2 vs2
  prefix۰to_val i1 back1 vs1 = prefix۰to_val i2 back2 vs2.

#[local] Lemma prefix۰to_valinj i1 back1 vs1 i2 back2 vs2 :
  prefix۰to_val i1 back1 vs1 = prefix۰to_val i2 back2 vs2
    (vs1 [] i1 = i2)
    back1 = back2
    vs1 = vs2.
#[local] Lemma prefix۰to_valinj' i1 back1 vs1 i2 back2 vs2 :
  prefix۰to_val i1 back1 vs1 prefix۰to_val i2 back2 vs2
    (vs1 [] i1 = i2)
    back1 = back2
    vs1 = vs2.

Section queue_mpmc_2۰G.
  Context `{queue_mpmc_2۰G : QueueMpmc2G Σ}.

  Record metadata :=
    { metadata۰inv : namespace
    ; metadata۰model : gname
    ; metadata۰state : gname
    ; metadata۰front : 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₁ γ :=
    model₁' γ.(metadata۰model).
  #[local] Definition model₂' γ_model vs :=
    twins۰twin₂ γ_model vs.
  #[local] Definition model₂ γ :=
    model₂' γ.(metadata۰model).

  #[local] Definition state۰auth' γ_state backs i status : iProp Σ :=
    auth_mono۰auth _ γ_state (DfracOwn 1)
      {|state۰backs := backs
      ; state۰index := i
      ; state۰status := status
      |}
    state۰wf backs i.
  #[local] Instance : CustomIpat "state۰auth" :=
    " ( Hauth & %Hwf ) ".
  #[local] Definition state۰auth γ backs i status :=
    state۰auth' γ.(metadata۰state) backs i status.
  #[local] Definition state۰lb γ backs i status :=
    auth_mono۰lb _ γ.(metadata۰state)
      {|state۰backs := backs
      ; state۰index := i
      ; state۰status := status
      |}.
  #[local] Definition state۰seen γ back i_prev back_prev move : iProp Σ :=
     backs,
    state۰lb γ backs i_prev (Unstable back move)
    backs !! back_prev = Some i_prev.
  #[local] Instance : CustomIpat "state۰seen" :=
    " ( %backs{} & #Hstate_lb & %Hbacks{}_lookup ) ".
  #[local] Definition state۰at γ back i_back : iProp Σ :=
     backs i status,
    state۰lb γ backs i status
    backs !! back = Some i_back
    i_back i.
  #[local] Instance : CustomIpat "state۰at" :=
    " ( %backs{} & %i{} & %status{} & #Hstate_lb{_{}} & %Hbacks{}_lookup & %Hi{} ) ".

  #[local] Definition front۰auth' γ_front i :=
    auth_nat_max۰auth γ_front (DfracOwn 1) i.
  #[local] Definition front۰auth γ i :=
    front۰auth' γ.(metadata۰front) i.
  #[local] Definition front۰lb γ i :=
    auth_nat_max۰lb γ.(metadata۰front) i.

  #[local] Definition move۰model₁ 𝑚𝑜𝑣𝑒 i_prev back_prev move : iProp Σ :=
      𝑚𝑜𝑣𝑒 = §Used%V
     𝑚𝑜𝑣𝑒 = prefix۰to_val i_prev back_prev move
      0 < length move
      back_prev ↦ₕ Header §Back 2.
  #[local] Instance : CustomIpat "move۰model₁" :=
    " [ -> | ( -> & % & #Hback{}_prev_header ) ] ".
  #[local] Definition move۰model₂ γ back 𝑚𝑜𝑣𝑒 : iProp Σ :=
     backs_prev i_prev back_prev move,
    state۰lb γ backs_prev i_prev (Unstable back move)
    move۰model₁ 𝑚𝑜𝑣𝑒 i_prev back_prev move.
  #[local] Instance : CustomIpat "move۰model₂" :=
    " ( %backs{}_prev & %i{}_prev{_{!}} & %back{}_prev{_{!}} & %move{}{_{!}} & #Hstate_lb_unstable{_{}} & H𝑚𝑜𝑣𝑒{} ) ".

  #[local] Definition back۰model₁ back (i : nat) : iProp Σ :=
    back ↦ₕ Header §Back 2
    back.[index] #i.
  #[local] Instance : CustomIpat "back۰model₁" :=
    " ( { {!} _ ; #Hback{}_header ; #Hback_header } & #Hback{}_index{_{!}} ) ".
  #[local] Definition back۰model₂ back (i : nat) 𝑚𝑜𝑣𝑒 : iProp Σ :=
    back۰model₁ back i
    back.[move] 𝑚𝑜𝑣𝑒.
  #[local] Instance : CustomIpat "back۰model₂" :=
    " ( { {only_move} _ ; (:back۰model₁ // /!/) } & Hback{}_move{_{suff}} ) ".
  #[local] Definition back۰model₃ γ back i : iProp Σ :=
     𝑚𝑜𝑣𝑒,
    back۰model₂ back i 𝑚𝑜𝑣𝑒
    move۰model₂ γ back 𝑚𝑜𝑣𝑒.
  #[local] Instance : CustomIpat "back۰model₃" :=
    " ( %𝑚𝑜𝑣𝑒{} & (:back۰model₂) & H𝑚𝑜𝑣𝑒{} ) ".

  #[local] Definition inv۰status۰stable γ i vs_front i_back back vs_back vs empty : iProp Σ :=
    i_back = i
    vs = vs_front ++ reverse vs_back
    if empty then vs_front = [] else 0 < length vs_front
    state۰at γ back i_back.
  #[local] Instance : CustomIpat "inv۰status۰stable" :=
    " ( {>;}-> & {>;}%Hvs{} & {>;}{{empty}->;%Hempty{};%Hempty} & {>;}#Hstate_at{_{}} ) ".
  #[local] Definition inv۰status۰unstable strong γ backs i vs_front i_back back vs_back vs back_ move : iProp Σ :=
     back_prev,
    back_ = back
    i_back = (i + length move)%nat
    vs_front = []
    vs_back = []
    vs = reverse move
    0 < length move
    state۰at γ back_prev i
    back۰model₂ back i_back (prefix۰to_val i back_prev move)
    if strong then
      backs !! back = None
      back_prev ↦ₕ Header §Back 2
    else
      True.
  #[local] Instance : CustomIpat "inv۰status۰unstable" :=
    " ( %back{}_prev & {>;}-> & {>;}-> & {>;}{{lazy}%Hvs_front{};->} & {>;}{{lazy}%Hvs_back{};->} & {>;}-> & {>;}% & {>;}#Hstate_at_back{}_prev & Hback{} & { {strong} %Hbacks{}_lookup & #Hback{}_prev_header ; _ } ) ".
  #[local] Definition inv۰status strong γ backs i status vs_front i_back back vs_back vs : iProp Σ :=
    match status with
    | Stable empty
        inv۰status۰stable γ i vs_front i_back back vs_back vs empty
    | Unstable back_ move
        inv۰status۰unstable strong γ backs i vs_front i_back back vs_back vs back_ move
    end.

  #[local] Definition inv۰inner strong l γ : iProp Σ :=
     backs i status i_front vs_front i_back back vs_back vs,
    l.[front] suffix۰to_val i_front vs_front
    front۰auth γ i_front
    l.[back] prefix۰to_val i_back back vs_back
    ([∗ map] back i backs, back۰model₃ γ back i)
    model₂ γ vs
    state۰auth γ backs i status
    (i_front + length vs_front)%nat = ˖i
    inv۰status strong γ backs i status vs_front i_back back vs_back vs.
  #[local] Instance : CustomIpat "inv۰inner" :=
    " ( %backs{} & %i{} & %status{} & %i_front{} & %vs_front{} & %i_back{} & %back{} & %vs_back{} & %vs{} & Hl_front & {>;}Hfront_auth & Hl_back & Hbacks & Hmodel₂ & {>;}Hstate_auth & {>;}%Hfront{} & Hstatus ) ".
  #[local] Definition inv' l γ : iProp Σ :=
    inv γ.(metadata۰inv) (inv۰inner false l γ).
  Definition queue_mpmc_2۰inv t ι : iProp Σ :=
     l γ,
    t = #l
    ι = γ.(metadata۰inv)
    l γ
    inv' l γ.
  #[local] Instance : CustomIpat "inv" :=
    " ( %l & %γ & -> & -> & #Hmeta & #Hinv ) ".

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

  #[local] Instance state۰authtimeless γ backs i status :
    Timeless (state۰auth γ backs i status).
  #[local] Instance state۰attimeless γ back i_back :
    Timeless (state۰at γ back i_back).
  #[global] Instance queue_mpmc_2۰modeltimeless t vs :
    Timeless (queue_mpmc_2۰model t vs).

  #[local] Instance state۰atpersistent γ back i_back :
    Persistent (state۰at γ back i_back).
  #[global] Instance queue_mpmc_2۰invpersistent t ι :
    Persistent (queue_mpmc_2۰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.

  #[local] Lemma statealloc back :
     |==>
       γ_state,
      state۰auth' γ_state 0 (Unstable back []).
  #[local] Lemma state۰authwf γ backs i status :
    state۰auth γ backs i status
    state۰wf backs i.
  #[local] Lemma state۰lbget γ backs i status :
    state۰auth γ backs i status
    state۰lb γ backs i status.
  #[local] Lemma state۰atget {γ backs i status} back i_back :
    backs !! back = Some i_back
    state۰auth γ backs i status
    state۰at γ back i_back.
  #[local] Lemma state۰lbvalid γ backs1 i1 status1 backs2 i2 status2 :
    state۰auth γ backs1 i1 status1 -∗
    state۰lb γ backs2 i2 status2 -∗
      backs2 backs1
      i2 i1.
  #[local] Lemma state۰lbvalidUnstable γ backs1 i1 status1 backs2 i2 back2 move2 :
    state۰auth γ backs1 i1 status1 -∗
    state۰lb γ backs2 i2 (Unstable back2 move2) -∗
        backs1 = backs2
        i1 = i2
        status1 = Unstable back2 move2
       backs1 !! back2 = Some (i2 + length move2)%nat
        i2 + length move2 i1
        state۰at γ back2 (i2 + length move2).
  #[local] Lemma state۰lblookup {γ backs1 i1 status1 backs2 i2 status2} back i_back :
    backs2 !! back = Some i_back
    state۰auth γ backs1 i1 status1 -∗
    state۰lb γ backs2 i2 status2 -∗
    backs1 !! back = Some i_back.
  #[local] Lemma state۰seenvalid γ backs i status back i_prev back_prev move :
    state۰auth γ backs i status -∗
    state۰seen γ back i_prev back_prev move -∗
      backs !! back_prev = Some i_prev
      ( i = i_prev
        status = Unstable back move
       backs !! back = Some (i_prev + length move)%nat
        i_prev + length move i
        state۰at γ back (i_prev + length move)
      ).
  #[local] Lemma state۰atvalid γ backs i status back i_back :
    state۰auth γ backs i status -∗
    state۰at γ back i_back -∗
      backs !! back = Some i_back
      i_back i.
  #[local] Lemma state۰lbstabilized γ backs1 i1 status1 backs2 i2 back2 move2 :
    ( status1 Unstable back2 move2
     i2 + length move2 i1
      0 < length move2
    )
    state۰auth γ backs1 i1 status1 -∗
    state۰lb γ backs2 i2 (Unstable back2 move2) -∗
      backs1 !! back2 = Some (i2 + length move2)%nat
      state۰at γ back2 (i2 + length move2).
  #[local] Lemma state۰lbunstabilized γ backs1 i1 status1 backs2 i2 back2 move2 :
    i1 < i2 + length move2
    state۰auth γ backs1 i1 status1 -∗
    state۰lb γ backs2 i2 (Unstable back2 move2) -∗
      backs1 = backs2
      i1 = i2
      status1 = Unstable back2 move2.
  #[local] Lemma statestabilize γ backs i back move :
    backs !! back = None
    state۰auth γ backs i (Unstable back move) |==>
      state۰auth γ (<[back := i + length move]> backs) (i + length move) (Stable Nonempty)
      state۰lb γ (<[back := i + length move]> backs) (i + length move) (Stable Nonempty)
      state۰at γ back (i + length move).
  #[local] Lemma stateempty γ backs i :
    state۰auth γ backs i (Stable Nonempty) |==>
    state۰auth γ backs i (Stable Empty).
  #[local] Lemma statedestabilize {γ backs i} back move :
    state۰auth γ backs i (Stable Empty) |==>
    state۰auth γ backs i (Unstable back move).

  #[local] Lemma frontalloc :
     |==>
       γ_front,
      front۰auth' γ_front 1.
  #[local] Lemma front۰lbget γ i :
    front۰auth γ i
    front۰lb γ i.
  #[local] Lemma front۰lbvalid γ i1 i2 :
    front۰auth γ i1 -∗
    front۰lb γ i2 -∗
    i2 i1.
  #[local] Lemma frontupdate γ i :
    front۰auth γ i |==>
    front۰auth γ ˖i.

  Opaque state۰auth.
  Opaque state۰at.

  #[local] Lemma inv۰statusweaken γ backs i status vs_front i_back back vs_back vs :
    inv۰status true γ backs i status vs_front i_back back vs_back vs
    inv۰status false γ backs i status vs_front i_back back vs_back vs.
  #[local] Lemma inv۰statusStable strong γ backs i status vs_front i_back back vs_back vs :
    ( strong = true is_Some (backs !! back)
     0 < length vs_front
     0 < length vs_back
    )
    inv۰status strong γ backs i status vs_front i_back back vs_back vs
       empty,
      status = Stable empty
      inv۰status۰stable γ i vs_front i_back back vs_back vs empty.

  #[local] Lemma inv۰innerstrengthen l γ :
    inv۰inner false l γ
    inv۰inner true l γ.

  #[local] Lemma inv'state۰at {l γ} back i_back :
    inv' l γ -∗
    state۰at γ back i_back ={}=∗
    back۰model₁ back i_back.

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

  #[local] Lemma queue_mpmc_2٠suffix_indexspec (i : nat) vs :
    {{{
      True
    }}}
      queue_mpmc_2٠suffix_index (suffix۰to_val i vs)
    {{{
      RET #i;
      True
    }}}.

  #[local] Lemma queue_mpmc_2٠prefix_indexspec (i : nat) back vs :
    {{{
      back ↦ₕ Header §Back 2
      back.[index] #i
    }}}
      queue_mpmc_2٠prefix_index (prefix۰to_val i back vs)
    {{{
      RET #(i + length vs);
      True
    }}}.

  #[local] Lemma queue_mpmc_2٠rev₁spec i vs1 vs2 back :
    0 < length vs1
    {{{
      back ↦ₕ Header §Back 2
    }}}
      queue_mpmc_2٠rev₁ (suffix۰to_val (i + ˖(length vs2)) vs1) (prefix۰to_val i back vs2)
    {{{
      RET suffix۰to_val ˖i (reverse vs2 ++ vs1);
      True
    }}}.
  #[local] Lemma queue_mpmc_2٠revspec i back vs :
    0 < length vs
    {{{
      back ↦ₕ Header §Back 2
    }}}
      queue_mpmc_2٠rev (prefix۰to_val i back vs)
    {{{
      RET suffix۰to_val ˖i (reverse vs);
      True
    }}}.

  Lemma queue_mpmc_2٠createspec ι :
    {{{
      True
    }}}
      queue_mpmc_2٠create ()
    {{{
      t
    , RET t;
      queue_mpmc_2۰inv t ι
      queue_mpmc_2۰model t []
    }}}.

  #[local] Lemma frontspec_strong {l γ} i_front i_back :
    {{{
      inv' l γ
      match i_front with
      | None
          True
      | Some i_front
          front۰lb γ i_front
      end
      match i_back with
      | None
          True
      | Some i_back
           back,
          state۰at γ back i_back
      end
    }}}
      (#l).{front}
    {{{
      i_front' vs_front'
    , RET suffix۰to_val i_front' vs_front';
      front۰lb γ i_front'
      match i_front with
      | None
          True
      | Some i_front
          i_front i_front'
      end
      match i_back with
      | None
          True
      | Some i_back
           i',
          i_back i'
          (i_front' + length vs_front')%nat = ˖i'
      end
    }}}.
  #[local] Lemma frontspec l γ :
    {{{
      inv' l γ
    }}}
      (#l).{front}
    {{{
      i_front' vs_front'
    , RET suffix۰to_val i_front' vs_front';
      front۰lb γ i_front'
    }}}.

  #[local] Lemma movespec l γ backs back i move :
    {{{
      inv' l γ
      state۰lb γ backs i (Unstable back move)
    }}}
      (#back).{move}
    {{{
      𝑚𝑜𝑣𝑒
    , RET 𝑚𝑜𝑣𝑒;
        𝑚𝑜𝑣𝑒 = §Used%V
       backs i back_prev move,
        𝑚𝑜𝑣𝑒 = prefix۰to_val i back_prev move
        0 < length move
        state۰lb γ backs i (Unstable back move)
    }}}.

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

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

  #[local] Lemma queue_mpmc_2٠finishspec {l γ} i_back back :
    {{{
      inv' l γ
      state۰at γ back i_back
    }}}
      queue_mpmc_2٠finish #back
    {{{
      RET ();
      True
    }}}.

  #[local] Lemma queue_mpmc_2٠helpspec {l γ backs i back_prev back} move :
    0 < length move
    {{{
      inv' l γ
      state۰lb γ backs i (Unstable back move)
      back_prev ↦ₕ Header §Back 2
    }}}
      queue_mpmc_2٠help #l #back #(i + length move) (prefix۰to_val i back_prev move)
    {{{
      RET ();
      True
    }}}.

  #[local] Lemma queue_mpmc_2٠pushspecaux l γ v :
     (
       back i ws (j : Z),
      <<<
        j = (i + length ws)
        inv' l γ
        state۰at γ back i
      | ∀∀ vs,
        model₁ γ vs
      >>>
        queue_mpmc_2٠push_aux #l v #j (prefix۰to_val i back ws) @ γ.(metadata۰inv)
      <<<
        model₁ γ (vs ++ [v])
      | RET ();
        True
      >>>
    ) (
      <<<
        inv' l γ
      | ∀∀ vs,
        model₁ γ vs
      >>>
        queue_mpmc_2٠push #l v @ γ.(metadata۰inv)
      <<<
        model₁ γ (vs ++ [v])
      | RET ();
        True
      >>>
    ).
  Lemma queue_mpmc_2٠pushspec t v ι :
    <<<
      queue_mpmc_2۰inv t ι
    | ∀∀ vs,
      queue_mpmc_2۰model t vs
    >>>
      queue_mpmc_2٠push t v @ ι
    <<<
      queue_mpmc_2۰model t (vs ++ [v])
    | RET ();
      True
    >>>.

  #[local] Lemma queue_mpmc_2٠popspecaux l γ :
     (
       i_front vs_front,
      <<<
        inv' l γ
        front۰lb γ i_front
      | ∀∀ vs,
        model₁ γ vs
      >>>
        queue_mpmc_2٠pop_1 #l (suffix۰to_val i_front vs_front) @ γ.(metadata۰inv)
      <<<
        ∃∃ o,
        match o with
        | None
            model₁ γ vs
        | Some v
             vs',
            vs = v :: vs'
            model₁ γ vs'
        end
      | RET o;
        True
      >>>
    ) (
       (i_front : nat) backs back i back_prev move,
      <<<
        i_front ˖i
        1 < length move
        inv' l γ
        state۰lb γ backs i (Unstable back move)
        back_prev ↦ₕ Header §Back 2
      | ∀∀ vs,
        model₁ γ vs
      >>>
        queue_mpmc_2٠pop_2 #l Front[ #i_front ] #back (prefix۰to_val i back_prev move) @ γ.(metadata۰inv)
      <<<
        ∃∃ o,
        match o with
        | None
            model₁ γ vs
        | Some v
             vs',
            vs = v :: vs'
            model₁ γ vs'
        end
      | RET o;
        True
      >>>
    ) (
       i_front,
      <<<
        inv' l γ
      | ∀∀ vs,
        model₁ γ vs
      >>>
        queue_mpmc_2٠pop_3 #l Front[ #i_front ] @ γ.(metadata۰inv)
      <<<
        ∃∃ o,
        match o with
        | None
            model₁ γ vs
        | Some v
             vs',
            vs = v :: vs'
            model₁ γ vs'
        end
      | RET o;
        True
      >>>
    ) (
      <<<
        inv' l γ
      | ∀∀ vs,
        model₁ γ vs
      >>>
        queue_mpmc_2٠pop #l @ γ.(metadata۰inv)
      <<<
        ∃∃ o,
        match o with
        | None
            model₁ γ vs
        | Some v
             vs',
            vs = v :: vs'
            model₁ γ vs'
        end
      | RET o;
        True
      >>>
    ).
  Lemma queue_mpmc_2٠popspec t ι :
    <<<
      queue_mpmc_2۰inv t ι
    | ∀∀ vs,
      queue_mpmc_2۰model t vs
    >>>
      queue_mpmc_2٠pop t @ ι
    <<<
      ∃∃ o,
      match o with
      | None
          queue_mpmc_2۰model t vs
      | Some v
           vs',
          vs = v :: vs'
          queue_mpmc_2۰model t vs'
      end
    | RET o;
      True
    >>>.
End queue_mpmc_2۰G.

Require zoo_saturn.queue_mpmc_2__opaque.

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