------------------------------------------------------------------------
-- Lemmas related to Allowed-literal
------------------------------------------------------------------------

open import Definition.Typed.Restrictions
open import Graded.Modality

module Definition.Untyped.Allowed-literal
  {a} {M : Set a}
  {š•„ : Modality M}
  (R : Type-restrictions š•„)
  where

open Type-restrictions R

open import Definition.Untyped M
open import Definition.Untyped.Properties M

open import Tools.Empty
open import Tools.Function
open import Tools.Nat
open import Tools.Product as Σ
open import Tools.PropositionalEquality
open import Tools.Relation
open import Tools.Sum

private variable
  m m₁ mā‚‚ n : Nat
  X         : Set _
  ξ         : DExt _ _ _
  t         : Term _
  l         : Lvl _

opaque
  unfolding Allowed-literal

  -- If l is an allowed literal, then l is a literal.

  Allowed-literal→Level-literal : Allowed-literal l → Level-literal l
  Allowed-literal→Level-literal {l = Ļ‰įµ˜+ _}   _           = Ļ‰įµ˜+
  Allowed-literal→Level-literal {l = level _} (t-lit , _) = level t-lit

opaque
  unfolding Allowed-literal→Level-literal Level-literal→Universe-level

  -- A function that converts from Allowed-literal to Universe-level.

  Allowed-literal→Universe-level : Allowed-literal l → Universe-level
  Allowed-literal→Universe-level {l} =
    Level-literal→Universe-level {l = l} āˆ˜ā†’
    Allowed-literal→Level-literal

opaque
  unfolding Allowed-literal→Level-literal

  -- Irrelevance for Allowed-literal→Level-literal.

  Allowed-literal→Level-literal-irrelevance :
    {l₁ lā‚‚ : Allowed-literal l} →
    Allowed-literal→Level-literal l₁ ≔
    Allowed-literal→Level-literal lā‚‚
  Allowed-literal→Level-literal-irrelevance {l = Ļ‰įµ˜+ _}   = refl
  Allowed-literal→Level-literal-irrelevance {l = level _} =
    cong level Level-literal-propositional

opaque
  unfolding Allowed-literal→Universe-level

  -- Irrelevance for Allowed-literal→Universe-level.

  Allowed-literal→Universe-level-irrelevance :
    {l₁ lā‚‚ : Allowed-literal l} →
    Allowed-literal→Universe-level l₁ ≔
    Allowed-literal→Universe-level lā‚‚
  Allowed-literal→Universe-level-irrelevance =
    cong Level-literal→Universe-level
      Allowed-literal→Level-literal-irrelevance

opaque
  unfolding Allowed-literal

  -- The literal Ļ‰įµ˜+Ā m is allowed if and only if Omega-plus-allowed
  -- holds.

  Allowed-literal-Ļ‰įµ˜+-⇔ :
    Allowed-literal {n = n} (Ļ‰įµ˜+ m) ⇔ Omega-plus-allowed
  Allowed-literal-Ļ‰įµ˜+-⇔ = id⇔

opaque

  -- The literal Ļ‰įµ˜+Ā mā‚‚ is allowed if Ļ‰įµ˜+Ā m₁ is.

  Allowed-literal-Ļ‰įµ˜+-→-Allowed-literal-Ļ‰įµ˜+ :
    Allowed-literal {n = n} (Ļ‰įµ˜+ m₁) → Allowed-literal {n = n} (Ļ‰įµ˜+ mā‚‚)
  Allowed-literal-Ļ‰įµ˜+-→-Allowed-literal-Ļ‰įµ˜+ {m₁} {mā‚‚} =
    Allowed-literal (Ļ‰įµ˜+ m₁)  ā‡”āŸØ Allowed-literal-Ļ‰įµ˜+-⇔ āŸ©ā†’
    Omega-plus-allowed        ā‡”Ė˜āŸØ Allowed-literal-Ļ‰įµ˜+-⇔ āŸ©ā†’
    Allowed-literal (Ļ‰įµ˜+ mā‚‚)  ā–”

opaque
  unfolding Allowed-literal

  -- The level levelĀ t is allowed as a literal if and only if it is a
  -- literal and Level is not allowed.

  Allowed-literal-level-⇔ :
    Allowed-literal (level t) ⇔ (Level-literal t Ɨ ¬ Level-allowed)
  Allowed-literal-level-⇔ = id⇔

opaque
  unfolding Allowed-literal Level-literal-1ᵘ+-⇔

  -- The level 1ᵘ+ l is an allowed literal if and only if l is.

  Allowed-literal-1ᵘ+-⇔ :
    Allowed-literal (1ᵘ+ l) ⇔ Allowed-literal l
  Allowed-literal-1ᵘ+-⇔ {l = Ļ‰įµ˜+ _}   = id⇔
  Allowed-literal-1ᵘ+-⇔ {l = level _} =
    Level-literal-1ᵘ+-⇔ Ɨ-cong-⇔ id⇔

opaque
  unfolding Allowed-literal inline

  -- The level inline ξ l is an allowed literal if l is.

  Allowed-literal-inline :
    Allowed-literal l → Allowed-literal (inline ξ l)
  Allowed-literal-inline {l = Ļ‰įµ˜+ _}   = idį¶ 
  Allowed-literal-inline {l = level _} =
    Σ.map Level-literal-inline idᶠ

opaque

  -- If Level is allowed and l is allowed as a literal, then l is
  -- infinite.

  Allowed-literal→Infinite :
    Level-allowed → Allowed-literal l → Infinite l
  Allowed-literal→Infinite {l = Ļ‰įµ˜+ _}   _   _   = Ļ‰įµ˜+
  Allowed-literal→Infinite {l = level _} ok₁ okā‚‚ =
    ⊄-elim (Allowed-literal-level-⇔ .proj₁ okā‚‚ .projā‚‚ ok₁)

opaque

  -- If Level is allowed and Allowed-literalĀ (levelĀ t) holds, then
  -- anything can be derived.

  Level-allowed→Allowed-literal→ :
    Level-allowed → Allowed-literal (level t) → X
  Level-allowed→Allowed-literal→ okᓸ ok =
    case Allowed-literal→Infinite okᓸ ok of Ī» ()

opaque

  -- If l is an allowed literal, then either Level is not allowed or l
  -- is infinite.

  Allowed-literal→¬Level-allowedāŠŽInfinite :
    Allowed-literal l → ¬ Level-allowed āŠŽ Infinite l
  Allowed-literal→¬Level-allowedāŠŽInfinite {l = Ļ‰įµ˜+ m}   _  = injā‚‚ Ļ‰įµ˜+
  Allowed-literal→¬Level-allowedāŠŽInfinite {l = level t} ok =
    inj₁ (Allowed-literal-level-⇔ .proj₁ ok .projā‚‚)