module Stack where

open import Prelude public


-- Stacks, or snoc-lists.

data Stack (X : Set) : Set where
  ∅   : Stack X
  _,_ : Stack X → X → Stack X


-- Stack membership, or de Bruijn indices.

module _ {X : Set} where
  infix 3 _∈_
  data _∈_ (A : X) : Stack X → Set where
    top : ∀ {Γ}   → A ∈ Γ , A
    pop : ∀ {Γ B} → A ∈ Γ → A ∈ Γ , B

  ⌊_⌋∈ : ∀ {Γ A} → A ∈ Γ → Nat
  ⌊ top ⌋∈   = zero
  ⌊ pop i ⌋∈ = suc ⌊ i ⌋∈

  i₀ : ∀ {Γ A} → A ∈ Γ , A
  i₀ = top

  i₁ : ∀ {Γ A B} → A ∈ Γ , A , B
  i₁ = pop i₀

  i₂ : ∀ {Γ A B C} → A ∈ Γ , A , B , C
  i₂ = pop i₁


-- Stack inclusion, or order-preserving embeddings.

module _ {X : Set} where
  infix 3 _⊆_
  data _⊆_ : Stack X → Stack X → Set where
    bot  : ∀ {Γ}      → ∅ ⊆ Γ
    skip : ∀ {Γ Γ′ A} → Γ ⊆ Γ′ → Γ ⊆ Γ′ , A
    keep : ∀ {Γ Γ′ A} → Γ ⊆ Γ′ → Γ , A ⊆ Γ′ , A

  refl⊆ : ∀ {Γ} → Γ ⊆ Γ
  refl⊆ {∅}     = bot
  refl⊆ {Γ , A} = keep refl⊆

  trans⊆ : ∀ {Γ Γ′ Γ″} → Γ ⊆ Γ′ → Γ′ ⊆ Γ″ → Γ ⊆ Γ″
  trans⊆ bot      η′        = bot
  trans⊆ η        (skip η′) = skip (trans⊆ η η′)
  trans⊆ (skip η) (keep η′) = skip (trans⊆ η η′)
  trans⊆ (keep η) (keep η′) = keep (trans⊆ η η′)

  weak⊆ : ∀ {Γ A} → Γ ⊆ Γ , A
  weak⊆ = skip refl⊆


-- Monotonicity of stack membership with respect to stack inclusion.

module _ {X : Set} where
  mono∈ : ∀ {Γ Γ′ : Stack X} {A} → Γ ⊆ Γ′ → A ∈ Γ → A ∈ Γ′
  mono∈ bot      ()
  mono∈ (skip η) i       = pop (mono∈ η i)
  mono∈ (keep η) top     = top
  mono∈ (keep η) (pop i) = pop (mono∈ η i)


-- Pairs of stacks.

infixl 4 _⁏_
record Stack² (X Y : Set) : Set where
  constructor _⁏_
  field
    π₁ : Stack X
    π₂ : Stack Y

open Stack² public


-- Stack pair inclusion.

module _ {X Y : Set} where
  infix 3 _⊆²_
  _⊆²_ : Stack² X Y → Stack² X Y → Set
  Γ ⁏ Δ ⊆² Γ′ ⁏ Δ′ = Γ ⊆ Γ′ ∧ Δ ⊆ Δ′

  refl⊆² : ∀ {Γ Δ} → Γ ⁏ Δ ⊆² Γ ⁏ Δ
  refl⊆² = refl⊆ , refl⊆

  trans⊆² : ∀ {Γ Γ′ Γ″ Δ Δ′ Δ″} → Γ ⁏ Δ ⊆² Γ′ ⁏ Δ′ → Γ′ ⁏ Δ′ ⊆² Γ″ ⁏ Δ″ → Γ ⁏ Δ ⊆² Γ″ ⁏ Δ″
  trans⊆² (η , ρ) (η′ , ρ′) = trans⊆ η η′ , trans⊆ ρ ρ′