{-# OPTIONS --rewriting #-}

module A201801.CMTTTypes where

open import A201801.Prelude
open import A201801.Category
open import A201801.Vec
open import A201801.AllVec
open import A201801.CMTTScopes


--------------------------------------------------------------------------------


mutual
  infixr 8 _⊃_
  data Type : Set
    where
      ι_   : String → Type
      _⊃_  : Type → Type → Type
      [_]_ : ∀ {g} → Types g → Type → Type


  Types : Nat → Set
  Types g = Vec Type g


instance
  TypeVar : IsString Type
  TypeVar =
    record
      { Constraint = \ s → ⊤
      ; fromString = \ s → ι s
      }


--------------------------------------------------------------------------------


record Assert (g : Nat) : Set
  where
    constructor ⟪_⊫_⟫
    field
      Γ : Types g
      A : Type


Asserts : ∀ {d} → Scopes d → Set
Asserts σ = All Assert σ


--------------------------------------------------------------------------------


injι : ∀ {P₁ P₂} → ι P₁ ≡ ι P₂
                 → P₁ ≡ P₂
injι refl = refl


inj⊃₁ : ∀ {A₁ A₂ B₁ B₂} → A₁ ⊃ B₁ ≡ A₂ ⊃ B₂
                        → A₁ ≡ A₂
inj⊃₁ refl = refl


inj⊃₂ : ∀ {A₁ A₂ B₁ B₂} → A₁ ⊃ B₁ ≡ A₂ ⊃ B₂
                        → B₁ ≡ B₂
inj⊃₂ refl = refl


inj[]₀ : ∀ {n₁ n₂ A₁ A₂} → {Ψ₁ : Types n₁} {Ψ₂ : Types n₂}
                         → [ Ψ₁ ] A₁ ≡ [ Ψ₂ ] A₂
                         → n₁ ≡ n₂
inj[]₀ refl = refl


inj[]₁ : ∀ {n A₁ A₂} → {Ψ₁ Ψ₂ : Types n}
                     → [ Ψ₁ ] A₁ ≡ [ Ψ₂ ] A₂
                     → Ψ₁ ≡ Ψ₂
inj[]₁ refl = refl


inj[]₂ : ∀ {n A₁ A₂} → {Ψ₁ Ψ₂ : Types n}
                     → [ Ψ₁ ] A₁ ≡ [ Ψ₂ ] A₂
                     → A₁ ≡ A₂
inj[]₂ refl = refl


mutual
  _≟ₚ_ : (A₁ A₂ : Type) → Dec (A₁ ≡ A₂)
  (ι P₁)      ≟ₚ (ι P₂)      with P₁ ≟ₛ P₂
  ...                        | yes refl = yes refl
  ...                        | no P₁≢P₂ = no (P₁≢P₂ ∘ injι)
  (ι P₁)      ≟ₚ (A₂ ⊃ B₂)   = no (\ ())
  (ι P₁)      ≟ₚ ([ Ψ₂ ] A₂) = no (\ ())
  (A₁ ⊃ B₁)   ≟ₚ (ι P₂)      = no (\ ())
  (A₁ ⊃ B₁)   ≟ₚ (A₂ ⊃ B₂)   with A₁ ≟ₚ A₂ | B₁ ≟ₚ B₂
  ...                        | yes refl | yes refl = yes refl
  ...                        | yes refl | no B₁≢B₂ = no (B₁≢B₂ ∘ inj⊃₂)
  ...                        | no A₁≢A₂ | _        = no (A₁≢A₂ ∘ inj⊃₁)
  (A₁ ⊃ B₁)   ≟ₚ ([ Ψ₂ ] A₂) = no (\ ())
  ([ Ψ₁ ] A₁) ≟ₚ (ι P₂)      = no (\ ())
  ([ Ψ₁ ] A₁) ≟ₚ (A₂ ⊃ B₂)   = no (\ ())
  [_]_ {g₁} Ψ₁ A₁ ≟ₚ [_]_ {g₂} Ψ₂ A₂ with g₁ ≟ₙ g₂
  [_]_ {g}  Ψ₁ A₁ ≟ₚ [_]_ {.g} Ψ₂ A₂ | yes refl with Ψ₁ ≟ₚₛ Ψ₂ | A₁ ≟ₚ A₂
  [_]_ {g}  Ψ  A  ≟ₚ [_]_ {.g} .Ψ .A | yes refl | yes refl | yes refl = yes refl
  [_]_ {g}  Ψ  A₁ ≟ₚ [_]_ {.g} .Ψ A₂ | yes refl | yes refl | no A₁≢A₂ = no (A₁≢A₂ ∘ inj[]₂)
  [_]_ {g}  Ψ₁ A₁ ≟ₚ [_]_ {.g} Ψ₂ A₂ | yes refl | no Ψ₁≢Ψ₂ | _        = no (Ψ₁≢Ψ₂ ∘ inj[]₁)
  [_]_ {g₁} Ψ₁ A₁ ≟ₚ [_]_ {g₂} Ψ₂ A₂ | no g₁≢g₂ = no (g₁≢g₂ ∘ inj[]₀)

  _≟ₚₛ_ : ∀ {n} → (Ξ₁ Ξ₂ : Types n) → Dec (Ξ₁ ≡ Ξ₂)
  ∙         ≟ₚₛ ∙         = yes refl
  (Ξ₁ , A₁) ≟ₚₛ (Ξ₂ , A₂) with Ξ₁ ≟ₚₛ Ξ₂ | A₁ ≟ₚ A₂
  ...                     | yes refl | yes refl = yes refl
  ...                     | yes refl | no A₁≢A₂ = no (A₁≢A₂ ∘ inj,₂)
  ...                     | no Ξ₁≢Ξ₂ | _        = no (Ξ₁≢Ξ₂ ∘ inj,₁)


--------------------------------------------------------------------------------


_⊃⋯⊃_ : ∀ {n} → Types n → Type → Type
∙       ⊃⋯⊃ A = A
(Ξ , B) ⊃⋯⊃ A = Ξ ⊃⋯⊃ (B ⊃ A)


--------------------------------------------------------------------------------