module A201706.IS4NormalisationNoTerms where

open import A201706.IS4SemanticsNoTerms public


-- Absolute values.

infix 3 _⊨_
_⊨_ : Cx  Ty  Set₁
Δ  Γ  A =  {{_ : Model}} {w : World} 
               (∀ {w′ : World}  w′ Я w  w′ ⟪⊢⟫⋆ Δ) 
               (∀ {w′ : World}  w′ Я w  w′ ⟪⊩⟫⋆ Δ) 
               w ⊩⋆ Γ 
               w  A


-- Soundness.

⟦_⟧ :  {Δ Γ A}  Δ  Γ  A  Δ  Γ  A
 var 𝒾                  δ₁ δ₂ γ = lookup⊩ γ 𝒾
 mvar 𝒾                 δ₁ δ₂ γ = mlookup⟪⊩⟫ (δ₂ reflЯ) 𝒾
 lam {A = A} {B} 𝒟      δ₁ δ₂ γ = return {A  B}
                                      λ θ a 
                                         𝒟   ζ  δ₁ (transЯ ζ (⊒→Я θ)))
                                               ζ  δ₂ (transЯ ζ (⊒→Я θ)))
                                              (mono⊩⋆ θ γ , a)
 app {A = A} {B} 𝒟     δ₁ δ₂ γ = bind {A  B} {B} ( 𝒟  δ₁ δ₂ γ)
                                      λ θ f 
                                        f refl⊒ (mono⊩ {A} θ (   δ₁ δ₂ γ))
 box {A = A} 𝒟          δ₁ δ₂ γ = return { A}
                                      λ ζ 
                                        mgraft⟨⊢⟩ (δ₁ ζ) 𝒟 ,
                                         𝒟   ζ′  δ₁ (transЯ ζ′ ζ))
                                               ζ′  δ₂ (transЯ ζ′ ζ))
                                              
 unbox {A = A} {C} 𝒟   δ₁ δ₂ γ = bind { A} {C} ( 𝒟  δ₁ δ₂ γ)
                                      λ θ q 
                                            ζ  δ₁ (transЯ ζ (⊒→Я θ)) , π₁ (q ζ))
                                               ζ  δ₂ (transЯ ζ (⊒→Я θ)) , π₂ (q ζ))
                                              (mono⊩⋆ θ γ)


-- Canonical model.

instance
  canon : Model
  canon = record
    { World  = Cx
    ; _⊒_    = λ { (Δ′  Γ′) (Δ  Γ)  Δ′  Δ  Γ′  Γ }
    ; refl⊒  = refl⊇ , refl⊇
    ; trans⊒ = λ { (ζ′ , η′) (ζ , η)  trans⊇ ζ′ ζ , trans⊇ η′ η }
    ; _Я_    = λ { (Δ′  Γ′) (Δ  Γ)  Δ′  Δ }
    ; reflЯ  = refl⊇
    ; transЯ = trans⊇
    ; G      = _⊢ⁿᵉ 
    ; monoG  = λ { (ζ , η) 𝒟  mono⊢ⁿᵉ ζ η 𝒟 }
    ; ⊒→Я   = π₁
    ; peek   = id
    }

mutual
  reifyᶜ :  {A Δ Γ}  Δ  Γ  A  Δ  Γ ⊢ⁿᶠ A
  reifyᶜ {}      κ = κ (refl⊇ , refl⊇)
                        λ θ a 
                          neⁿᶠ a
  reifyᶜ {A  B} κ = κ (refl⊇ , refl⊇)
                        λ θ f 
                          lamⁿᶠ (reifyᶜ (f (refl⊇ , weak refl⊇)  varⁿᵉ zero ⟧ᶜ))
  reifyᶜ { A}    κ = κ (refl⊇ , refl⊇)
                        λ {w″} θ q 
                          boxⁿᶠ (π₁ (q {w′ = w″} refl⊇))

  ⟦_⟧ᶜ :  {A Δ Γ}  Δ  Γ ⊢ⁿᵉ A  Δ  Γ  A
  ⟦_⟧ᶜ {}      𝒟 = return {} 𝒟
  ⟦_⟧ᶜ {A  B} 𝒟 = return {A  B}
                      λ { (ζ , η) a 
                         appⁿᵉ (mono⊢ⁿᵉ ζ η 𝒟) (reifyᶜ a) ⟧ᶜ }
  ⟦_⟧ᶜ { A}    𝒟 = λ { (ζ , η) κ 
                      neⁿᶠ (unboxⁿᵉ (mono⊢ⁿᵉ ζ η 𝒟)
                                    (κ (weak refl⊇ , refl⊇)
                                       λ ζ′ 
                                         mvar (mono∋ ζ′ zero) ,
                                          mvarⁿᵉ (mono∋ ζ′ zero) ⟧ᶜ)) }


-- TODO: Needs a name.

refl⊩⋆ :  {Γ : Ty⋆} {Δ : BoxTy⋆}  Δ  Γ ⊩⋆ Γ
refl⊩⋆ {}     = 
refl⊩⋆ {Γ , A} = mono⊩⋆ (refl⊇ , weak refl⊇) refl⊩⋆ ,  varⁿᵉ zero ⟧ᶜ

mrefl⟪⊩⟫⋆ :  {Δ : BoxTy⋆} {Γ : Ty⋆}  Δ  Γ ⟪⊩⟫⋆ Δ
mrefl⟪⊩⟫⋆ {}       = 
mrefl⟪⊩⟫⋆ {Δ ,  A} = mono⟪⊩⟫⋆ (weak refl⊇ , refl⊇) mrefl⟪⊩⟫⋆ ,  mvarⁿᵉ zero ⟧ᶜ


-- Completeness.

reify :  {Δ Γ A}  Δ  Γ  A  Δ  Γ ⊢ⁿᶠ A
reify 𝔞 = reifyᶜ (𝔞  ζ  mono⟨⊢⟩⋆ ζ mrefl⟨⊢⟩⋆)
                     ζ  mono⟪⊩⟫⋆ (ζ , refl⊇) mrefl⟪⊩⟫⋆)
                    refl⊩⋆)


-- Normalisation.

nbe :  {Δ Γ A}  Δ  Γ  A  Δ  Γ ⊢ⁿᶠ A
nbe = reify  ⟦_⟧