module A201801.CMLAlternativeDerivations where

open import A201801.Prelude
open import A201801.Category
open import A201801.List
open import A201801.ListLemmas
open import A201801.AllList
open import A201801.CMLPropositions
import A201801.CMLStandardDerivations as CML
import A201801.CMLStandardDerivationsLemmas as CML


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


mutual
  infix 3 _⊢_valid[_]
  data _⊢_valid[_] : List Assert  Form  List Form  Set
    where
      vz :  {A Δ Γ}  Δ  A valid[ Γ , A ]

      wk :  {A B Δ Γ}  Δ  A valid[ Γ ]
                        Δ  A valid[ Γ , B ]

      cut :  {A B Δ Γ}  Δ  A valid[ Γ ]  Δ  B valid[ Γ , A ]
                         Δ  B valid[ Γ ]

      lam :  {A B Δ Γ}  Δ  B valid[ Γ , A ]
                         Δ  A  B valid[ Γ ]

      unlam :  {A B Δ Γ}  Δ  A  B valid[ Γ ]
                           Δ  B valid[ Γ , A ]

      box :  {A Ψ Δ Γ}  Δ  A valid[ Ψ ]
                         Δ  [ Ψ ] A valid[ Γ ]

      unbox :  {Δ Γ Ψ A}  Δ  [ Ψ ] A valid[ Γ ]  Δ  Ψ allvalid[ Γ ]
                           Δ  A valid[ Γ ]

      vau :  {A B Ψ Δ Γ}  Δ ,  Ψ  A   B valid[ Γ ]
                           Δ  B valid[ Γ , [ Ψ ] A ]

      unvau :  {A B Ψ Δ Γ}  Δ  B valid[ Γ , [ Ψ ] A ]
                             Δ ,  Ψ  A   B valid[ Γ ]

  infix 3 _⊢_allvalid[_]
  _⊢_allvalid[_] : List Assert  List Form  List Form  Set
  Δ  Ξ allvalid[ Γ ] = All (\ A  Δ  A valid[ Γ ]) Ξ


infix 3 _⊢_allvalid*
_⊢_allvalid* : List Assert  List Assert  Set
Δ  Ξ allvalid* = All (\ {  Γ  A   Δ  A valid[ Γ ] }) Ξ


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


wks :  {A Δ Γ Ξ}  Δ  Ξ allvalid[ Γ ]
                   Δ  Ξ allvalid[ Γ , A ]
wks ξ = maps wk ξ


lifts :  {A Δ Γ Ξ}  Δ  Ξ allvalid[ Γ ]
                     Δ  Ξ , A allvalid[ Γ , A ]
lifts ξ = wks ξ , vz


vars :  {Δ Γ Γ′}  Γ′  Γ
                   Δ  Γ allvalid[ Γ′ ]
vars done     = 
vars (drop η) = wks (vars η)
vars (keep η) = lifts (vars η)


ids :  {Δ Γ}  Δ  Γ allvalid[ Γ ]
ids = vars id


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


mwk :  {B Ψ A Δ Γ}  Δ  A valid[ Γ ]
                     Δ ,  Ψ  B   A valid[ Γ ]
mwk 𝒟 = unvau (wk 𝒟)


mwks :  {A Ψ Δ Γ Ξ}  Δ  Ξ allvalid[ Γ ]
                      Δ ,  Ψ  A   Ξ allvalid[ Γ ]
mwks ξ = maps mwk ξ


mwks* :  {A Ψ Δ Ξ}  Δ  Ξ allvalid*
                     Δ ,  Ψ  A   Ξ allvalid*
mwks* ξ = maps mwk ξ


mvz :  {A Ψ Δ Γ}  Δ ,  Ψ  A   Ψ allvalid[ Γ ]
                   Δ ,  Ψ  A   A valid[ Γ ]
mvz ψ = unbox (unvau vz) ψ


mlifts* :  {A Ψ Δ Ξ}  Δ  Ξ allvalid*
                       Δ ,  Ψ  A   Ξ ,  Ψ  A  allvalid*
mlifts* ξ = mwks* ξ , mvz ids


mvars* :  {Δ Δ′}  Δ′  Δ
                   Δ′  Δ allvalid*
mvars* done     = 
mvars* (drop η) = mwks* (mvars* η)
mvars* (keep η) = mlifts* (mvars* η)


mids* :  {Δ}  Δ  Δ allvalid*
mids* = mvars* id


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


vaus :  {Δ Γ Ξ Ψ A}  Δ ,  Ψ  A   Ξ allvalid[ Γ ]
                      Δ  Ξ allvalid[ Γ , [ Ψ ] A ]
vaus 𝒟 = maps vau 𝒟


-- NOTE: Interesting; similar shape to lift or cut

unnamed :  {Δ Γ Ξ Ψ A}  Δ ,  Ψ  A   Ξ allvalid[ Γ ]
                         Δ  Ξ , [ Ψ ] A allvalid[ Γ , [ Ψ ] A ]
unnamed 𝒟 = vaus 𝒟 , vz


mutual
  sub :  {Δ Γ Ξ A}  Δ  Ξ allvalid[ Γ ]  Δ  A valid[ Ξ ]
                     Δ  A valid[ Γ ]
  sub (ξ , 𝒞) vz          = 𝒞
  sub (ξ , 𝒞) (wk 𝒟)      = sub ξ 𝒟
  sub ξ       (cut 𝒟 )   = cut (sub ξ 𝒟) (sub (lifts ξ) )
  sub ξ       (lam 𝒟)     = lam (sub (lifts ξ) 𝒟)
  sub (ξ , 𝒞) (unlam 𝒟)   = cut 𝒞 (unlam (sub ξ 𝒟))
  sub ξ       (box 𝒟)     = box 𝒟
  sub ξ       (unbox 𝒟 ψ) = unbox (sub ξ 𝒟) (subs ξ ψ)
  sub (ξ , 𝒞) (vau 𝒟)     = cut 𝒞 (vau (sub (mwks ξ) 𝒟))
  sub ξ       (unvau 𝒟)   = unvau (sub (unnamed ξ) 𝒟)  -- NOTE: Interesting

  subs :  {Δ Γ Ξ Ψ}  Δ  Ξ allvalid[ Γ ]  Δ  Ψ allvalid[ Ξ ]
                      Δ  Ψ allvalid[ Γ ]
  subs ξ        = 
  subs ξ (ψ , 𝒟) = subs ξ ψ , sub ξ 𝒟


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


mutual
  msub :  {Δ Γ Ξ A}  Δ  Ξ allvalid*  Ξ  A valid[ Γ ]
                      Δ  A valid[ Γ ]
  msub ξ       vz          = vz
  msub ξ       (wk 𝒟)      = wk (msub ξ 𝒟)
  msub ξ       (cut 𝒟 )   = cut (msub ξ 𝒟) (msub ξ )
  msub ξ       (lam 𝒟)     = lam (msub ξ 𝒟)
  msub ξ       (unlam 𝒟)   = unlam (msub ξ 𝒟)
  msub ξ       (box 𝒟)     = box (msub ξ 𝒟)
  msub ξ       (unbox 𝒟 ψ) = unbox (msub ξ 𝒟) (msubs ξ ψ)
  msub ξ       (vau 𝒟)     = vau (msub (mlifts* ξ) 𝒟)
  msub (ξ , 𝒞) (unvau 𝒟)   = cut (box 𝒞) (msub ξ 𝒟)  -- NOTE: Interesting

  msubs :  {Δ Γ Ξ Ψ}  Δ  Ξ allvalid*  Ξ  Ψ allvalid[ Γ ]
                       Δ  Ψ allvalid[ Γ ]
  msubs ξ        = 
  msubs ξ (ψ , 𝒟) = msubs ξ ψ , msub ξ 𝒟


msubs* :  {Δ Ξ Ψ}  Δ  Ξ allvalid*  Ξ  Ψ allvalid*
                    Δ  Ψ allvalid*
msubs* ξ        = 
msubs* ξ (ψ , 𝒟) = msubs* ξ ψ , msub ξ 𝒟


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


var :  {Δ Γ A}  Γ  A
                 Δ  A valid[ Γ ]
var zero    = vz
var (suc i) = wk (var i)


app :  {Δ Γ A B}  Δ  A  B valid[ Γ ]  Δ  A valid[ Γ ]
                   Δ  B valid[ Γ ]
app 𝒟  = cut  (unlam 𝒟)


mvar :  {Δ Γ Ψ A}  Δ   Ψ  A   Δ  Ψ allvalid[ Γ ]
                    Δ  A valid[ Γ ]
mvar zero    ψ = mvz ψ
mvar (suc i) ψ = unvau (mvar i (vaus ψ))


letbox :  {Δ Γ Ψ A B}  Δ  [ Ψ ] A valid[ Γ ]  Δ ,  Ψ  A   B valid[ Γ ]
                        Δ  B valid[ Γ ]
letbox 𝒟  = cut 𝒟 (vau )


-- NOTE: Local completeness of [_]

rebox :  {Δ Γ Ψ A}  Δ  [ Ψ ] A valid[ Γ ]
                     Δ  [ Ψ ] A valid[ Γ ]
rebox 𝒟 = letbox 𝒟 (box (mvz ids))


-- NOTE: Local soundness of [_]

pseudomcut :  {Δ Γ Ψ A B}  Δ  A valid[ Ψ ]  Δ ,  Ψ  A   B valid[ Γ ]
                            Δ  B valid[ Γ ]
pseudomcut 𝒟  = letbox (box 𝒟) 


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


mutual
   :  {Δ Γ A}  Δ  A valid[ Γ ]
                 Δ CML.⊢ A valid[ Γ ]
   vz          = CML.vz
   (wk 𝒟)      = CML.wk ( 𝒟)
   (cut 𝒟 )   = CML.cut ( 𝒟) ( )
   (lam 𝒟)     = CML.lam ( 𝒟)
   (unlam 𝒟)   = CML.unlam ( 𝒟)
   (box 𝒟)     = CML.box ( 𝒟)
   (unbox 𝒟 ψ) = CML.unbox ( 𝒟) (↓ⁿ ψ)
   (vau 𝒟)     = CML.vau ( 𝒟)
   (unvau 𝒟)   = CML.unvau ( 𝒟)

  ↓ⁿ :  {Δ Γ Ξ}  Δ  Ξ allvalid[ Γ ]
                  Δ CML.⊢ Ξ allvalid[ Γ ]
  ↓ⁿ        = 
  ↓ⁿ (ξ , 𝒟) = ↓ⁿ ξ ,  𝒟


mutual
   :  {Δ Γ A}  Δ CML.⊢ A valid[ Γ ]
                 Δ  A valid[ Γ ]
   (CML.var i)      = var i
   (CML.lam 𝒟)      = lam ( 𝒟)
   (CML.app 𝒟 )    = app ( 𝒟) ( )
   (CML.mvar i ψ)   = mvar i (↑ⁿ ψ)
   (CML.box 𝒟)      = box ( 𝒟)
   (CML.letbox 𝒟 ) = letbox ( 𝒟) ( )

  ↑ⁿ :  {Δ Γ Ξ}  Δ CML.⊢ Ξ allvalid[ Γ ]
                  Δ  Ξ allvalid[ Γ ]
  ↑ⁿ        = 
  ↑ⁿ (ξ , 𝒟) = ↑ⁿ ξ ,  𝒟


lem-var :  {Δ Γ A}  (i : Γ  A)
                      {Δ} (var i)  CML.var i
lem-var zero    = refl
lem-var (suc i) = CML.wk & lem-var i
                 CML.var  suc & id-ren∋ i


-- NOTE: Problematic

-- lem-mvar : ∀ {Δ Γ Ψ A} → (i : Δ ∋ ⟪ Ψ ⊫ A ⟫) (ψ : Δ CML.⊢ Ψ allvalid[ Γ ])
--                        → ↓ {Γ = Γ} (mvar i (↑ⁿ ψ)) ≡ CML.mvar i ψ
-- lem-mvar zero    ψ = {!!} -- CML.unbox (CML.unvau CML.vz) (↓ⁿ (↑ⁿ ψ)) ≡ CML.mvar zero ψ
-- lem-mvar (suc i) ψ = {!!} -- CML.unvau (↓ (mvar i (vaus (↑ⁿ ψ)))) ≡ CML.mvar (suc i) ψ


-- id↓↑ : ∀ {Δ Γ A} → (𝒟 : Δ CML.⊢ A valid[ Γ ])
--                  → (↓ ∘ ↑) 𝒟 ≡ 𝒟
-- id↓↑ (CML.var i)      = lem-var i
-- id↓↑ (CML.lam 𝒟)      = CML.lam & id↓↑ 𝒟
-- id↓↑ (CML.app 𝒟 ℰ)    = CML.app & ( id-cons-wk-sub CML.ids (↓ (↑ ℰ)) (↓ (↑ 𝒟))
--                                 ⋮ id-sub (↓ (↑ 𝒟))
--                                 ⋮ id↓↑ 𝒟
--                                 )
--                               ⊗ id↓↑ ℰ
-- id↓↑ (CML.mvar i ψ)   = lem-mvar i ψ
-- id↓↑ (CML.box 𝒟)      = CML.box & id↓↑ 𝒟
-- id↓↑ (CML.letbox 𝒟 ℰ) = CML.letbox & id↓↑ 𝒟 ⊗ ( id-cons-wk-sub (CML.mwks CML.ids) (CML.mwk (↓ (↑ 𝒟))) (↓ (↑ ℰ))
--                                             ⋮ (\ ξ′ → CML.sub ξ′ (↓ (↑ ℰ))) & id-mrens-ids (drop id)
--                                             ⋮ id-sub (↓ (↑ ℰ))
--                                             ⋮ id↓↑ ℰ
--                                             )


-- NOTE: Problematic

-- id↑↓ : ∀ {Δ Γ A} → (𝒟 : Δ ⊢ A valid[ Γ ])
--                  → (↑ ∘ ↓) 𝒟 ≡ 𝒟
-- id↑↓ vz          = refl
-- id↑↓ (wk 𝒟)      = {!!} -- ↑ (CML.wk (↓ 𝒟)) ≡ wk 𝒟
-- id↑↓ (cut 𝒟 ℰ)   = {!!} -- ↑ (CML.cut (↓ 𝒟) (↓ ℰ)) ≡ cut 𝒟 ℰ
-- id↑↓ (lam 𝒟)     = lam & id↑↓ 𝒟
-- id↑↓ (unlam 𝒟)   = {!!} -- app (↑ (CML.wk (↓ 𝒟))) vz ≡ unlam 𝒟
-- id↑↓ (box 𝒟)     = box & id↑↓ 𝒟
-- id↑↓ (unbox 𝒟 ψ) = {!!} -- letbox (↑ (↓ 𝒟)) (mvz (↑ⁿ (CML.mwks (↓ⁿ ψ)))) ≡ unbox 𝒟 ψ
-- id↑↓ (vau 𝒟)     = {!!} -- letbox vz (↑ (CML.wk (↓ 𝒟))) ≡ vau 𝒟
-- id↑↓ (unvau 𝒟)   = {!!} -- app (lam (↑ (CML.mwk (↓ 𝒟)))) (box (mvz (↑ⁿ CML.ids))) ≡ unvau 𝒟


-- TODO: Semantic equivalence


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