{-# OPTIONS --allow-unsolved-metas #-}

module A201602.SimpleSTLC2 where

open import Data.Empty renaming ( to Ag-⊥ ; ⊥-elim to Ag-⊥-elim)
open import Data.Fin using (Fin ; zero ; suc ; raise)
open import Data.Nat using ( ; zero ; suc ; _+_)
open import Data.Product using (Σ ; _×_ ; _,_ ; proj₁ ; proj₂)
open import Data.Unit renaming ( to Ag-⊤ ; tt to Ag-top)

infixr 2 _∶_
infixr 1 _⊃_
infixr 0 _⊢_∷_ _⊢_∷_∷_


-- --------------------------------------------------------------------------
--
-- Well-scoped syntax


data Tm (m : ) : Set where
  var_  : Fin m  Tm m
  lam_  : Tm (suc m)  Tm m
  _$_   : Tm m  Tm m  Tm m
  ⟨_,_⟩ : Tm m  Tm m  Tm m
  fst_  : Tm m  Tm m
  snd_  : Tm m  Tm m
  !_    : Tm m  Tm m
  up_   : Tm m  Tm m
  dn_   : Tm m  Tm m
  efq_  : Tm m  Tm m
  top   : Tm m


#0 :  {m}  Fin (suc m)
#0 = zero

#1 :  {m}  Fin (suc (suc m))
#1 = suc #0

#2 :  {m}  Fin (suc (suc (suc m)))
#2 = suc #1


-- --------------------------------------------------------------------------
--
-- Types


data Ty : Set where
  _⊃_ : Ty  Ty  Ty
  _∧_ : Ty  Ty  Ty
  _∶_ : Tm 0  Ty  Ty
    : Ty
    : Ty


¬_ : Ty  Ty
¬ A = A  


-- --------------------------------------------------------------------------
--
-- Contexts


data Cx : Set where
     : Cx
  _,_ : Cx  Ty  Cx


nat : Cx  
nat        = zero
nat (Γ , x) = suc (nat Γ)


-- --------------------------------------------------------------------------
--
-- Context membership


data _∈_ (A : Ty) : Cx  Set where
  here :  {Γ}
       A  (Γ , A)

  there_ :  {Γ B}
       A  Γ
       A  (Γ , B)


fin :  {Γ A}  A  Γ  Fin (nat Γ)
fin here      = zero
fin (there i) = suc (fin i)


M#0 :  {Γ A}
     A  (Γ , A)
M#0 = here

M#1 :  {Γ A B}
     A  ((Γ , A) , B)
M#1 = there M#0

M#2 :  {Γ A B C}
     A  (((Γ , A) , B) , C)
M#2 = there M#1


-- --------------------------------------------------------------------------
--
-- Well-typed syntax


data _⊢_∷_ (Γ : Cx) : (t : Tm (nat Γ))  Ty  Set where
  Mvar_ :  {A}
       (i : A  Γ)
       Γ  var (fin i)  A

  Mlam_ :  {t : Tm (suc (nat Γ))} {A B}
       Γ , A  t  B
       Γ  lam t  (A  B)

  _M$_ :  {t s : Tm (nat Γ)} {A B}
       Γ  t  (A  B)     Γ  s  A
       Γ  t $ s  B

  ⟨_M,_⟩ :  {t s : Tm (nat Γ)} {A B}
       Γ  t  A     Γ  s  B
       Γ   t , s   (A  B)

  Mfst_ :  {t : Tm (nat Γ)} {A B}
       Γ  t  (A  B)
       Γ  fst t  A

  Msnd_ :  {t : Tm (nat Γ)} {A B}
       Γ  t  (A  B)
       Γ  snd t  B

  Mup_ :  {t : Tm (nat Γ)} {u : Tm 0} {A}
       Γ  t  u  A
       Γ  up t  ! u  u  A

  Mdn_ :  {t : Tm (nat Γ)} {u : Tm 0} {A}
       Γ  t  u  A
       Γ  dn t  A

  Mefq_ :  {t : Tm (nat Γ)} {A}
       Γ  t  
       Γ  efq t  A

  Mtop : Γ  top  


data _⊢_∷_∷_ (Γ : Cx) : (t₂ t : Tm (nat Γ))  Ty  Set where
  MMvar_ :  {A}
       (i : A  Γ)
       Γ  var (fin i)  var (fin i)  A

  MMlam_ :  {t₂ t : Tm (suc (nat Γ))} {A B}
       Γ , A  t₂  t  B
       Γ  lam t₂  lam t  (A  B)

  _MM$_ :  {t₂ t s₂ s : Tm (nat Γ)} {A B}
       Γ  t₂  t  (A  B)     Γ  s₂  s  A
       Γ  t₂ $ s₂  t $ s  B

  ⟨_MM,_⟩ :  {t₂ t s₂ s : Tm (nat Γ)} {A B}
       Γ  t₂  t  A     Γ  s₂  s  B
       Γ   t₂ , s₂    t , s   (A  B)

  MMfst_ :  {t₂ t : Tm (nat Γ)} {A B}
       Γ  t₂  t  (A  B)
       Γ  fst t₂  fst t  A

  MMsnd_ :  {t₂ t : Tm (nat Γ)} {A B}
       Γ  t₂  t  (A  B)
       Γ  snd t₂  snd t  B

  MMup_ :  {t₂ t : Tm (nat Γ)} {u : Tm 0} {A}
       Γ  t₂  t  u  A
       Γ  up t₂  up t  ! u  u  A

  MMdn_ :  {t₂ t : Tm (nat Γ)} {u : Tm 0} {A}
       Γ  t₂  t  u  A
       Γ  dn t₂  dn t  A

  MMefq_ :  {t₂ t : Tm (nat Γ)} {A}
       Γ  t₂  t  
       Γ  efq t₂  efq t  A

  MMtop : Γ  top  top  


data _⊢_∷_∷_∷_ (Γ : Cx) : (t₃ t₂ t : Tm (nat Γ))  Ty  Set where


-- --------------------------------------------------------------------------
--
-- Semantics


{-weak : ∀ {m}
    → (k : ℕ)    → Tm (0 + m)
    → Tm (k + m)
weak {m} k (var x) = var raise k x
weak k (lam t) = {!!}
weak k (t $ t₁) = {!!}
weak k ⟨ t , t₁ ⟩ = {!!}
weak k (fst t) = {!!}
weak k (snd t) = {!!}
weak k (! t) = {!!}
weak k (up t) = {!!}
weak k (dn t) = {!!}
weak k (efq t) = {!!}
weak k top = {!!}


weak⊢ : ∀ {Γ} {t : Tm 0} {A}
    → ∅ ⊢ t ∷ A
    → Γ ⊢ weak (nat Γ) t ∷ A
weak⊢ = {!!}-}


⟦_⟧T : Ty  Set
 A  B ⟧T =  A ⟧T   B ⟧T
 A  B ⟧T =  A ⟧T ×  B ⟧T
 t  A ⟧T =   t  A
  ⟧T    = Ag-⊤
  ⟧T    = Ag-⊥


⟦_⟧C : Cx  (Ty  Set)  Set
  ⟧C     V = Ag-⊤
 Γ , A ⟧C V =  Γ ⟧C V × V A


⟦_⟧∈ :  {Γ V A}  A  Γ   Γ ⟧C V  V A
 here ⟧∈    (γ , a) = a
 there i ⟧∈ (γ , b) =  i ⟧∈ γ


quot :  {Γ} {t : Tm (nat Γ)} {A}
     Γ  t  A
     Tm (nat Γ)
quot (Mvar_ i)  = var fin i
quot (Mlam D)   = lam quot D
quot (D M$ E)   = quot D $ quot E
quot  D M, E  =  quot D , quot E 
quot (Mfst D)   = fst quot D
quot (Msnd D)   = snd quot D
quot (Mup D)    = up (quot D)
quot (Mdn D)    = dn (quot D)
quot (Mefq D)   = efq quot D
quot Mtop       = top

Mquot :  {Γ} {t₂ t : Tm (nat Γ)} {A}
     Γ  t₂  t  A
     Tm (nat Γ)
Mquot = {!!}


lift : ∀{Γ A} {t : Tm (nat Γ)}
     (D : Γ  t  A)
     Γ  quot D  t  A
lift (Mvar i)   = MMvar i
lift (Mlam D)   = MMlam lift D
lift (D M$ E)   = lift D MM$ lift E
lift  D M, E  =  lift D MM, lift E 
lift (Mfst D)   = MMfst lift D
lift (Msnd D)   = MMsnd lift D
lift (Mup D)    = MMup lift D
lift (Mdn D)    = MMdn lift D
lift (Mefq D)   = MMefq lift D
lift Mtop       = MMtop

Mlift :  {Γ} {t₂ t : Tm (nat Γ)} {A}
     (D : Γ  t₂  t  A)
     Γ  Mquot D  t₂  t  A
Mlift = {!!}


drop :  {Γ} {t₂ t : Tm (nat Γ)} {A}
     Γ  t₂  t  A
     Γ  t  A
drop (MMvar i)   = Mvar i
drop (MMlam D)   = Mlam drop D
drop (D MM$ E)   = drop D M$ drop E
drop  D MM, E  =  drop D M, drop E 
drop (MMfst D)   = Mfst drop D
drop (MMsnd D)   = Msnd drop D
drop (MMup D)    = Mup drop D
drop (MMdn D)    = Mdn drop D
drop (MMefq D)   = Mefq drop D
drop MMtop       = Mtop

Mdrop :  {Γ} {t₃ t₂ t : Tm (nat Γ)} {A}
     Γ  t₃  t₂  t  A
     Γ  t₂  t  A
Mdrop = {!!}


pack :  {t : Tm 0} {u : Tm 0} {A}
       t  u  A
       t  u  A
pack = {!!}

unpack :  {t u : Tm 0} {A}
       t  u  A
       t  u  A
unpack = {!!}


check :  {Γ} {t : Tm (nat Γ)} {u : Tm 0} {A}
     Γ  t  u  A
       (! u)  u  A
check = {!!}


mutual
  ⟦_⟧ :  {Γ} {t : Tm (nat Γ)} {A}
       Γ  t  A      Γ ⟧C ⟦_⟧T
        A ⟧T
   Mvar i  γ     =  i ⟧∈ γ
   Mlam D  γ     = λ a   D  (γ , a)
   D M$ E  γ     =  D  γ ( E  γ)
    D M, E   γ =  D  γ ,  E  γ
   Mfst D  γ     = proj₁ ( D  γ)
   Msnd D  γ     = proj₂ ( D  γ)
   Mup D  γ      = check D
   Mdn D  γ      = M⟦ unpack {!!}  γ
   Mefq D  γ     = Ag-⊥-elim ( D  γ)
   Mtop    γ     = Ag-top

  M⟦_⟧ :  {Γ} {t₂ t : Tm 0} {A}
         t₂  t  A      Γ ⟧C ⟦_⟧T
        A ⟧T
  M⟦_⟧ = {!!}


{-
  Mup_ : ∀ {t u : Tm (nat Γ)} {A}
      → Γ ⊢ t ∷ u ∶ A
      → Γ ⊢ up t ∷ ! u ∶ u ∶ A

  Mdn_ : ∀ {t u : Tm (nat Γ)} {A}
      → Γ ⊢ t ∷ u ∶ A
      → Γ ⊢ dn t ∷ A
-}

-- --------------------------------------------------------------------------
--
-- Example


module Tms where
  -- ∅ ⊢ B ⊃ A ⊃ A
  H :  {Γ}  Tm (nat Γ)
  H = lam lam var #0

  -- ∅ ⊢ A ⊃ A
  I :  {Γ}  Tm (nat Γ)
  I = lam var #0

  -- A ⊢ A
  I′ :  {Γ}  Tm (suc (nat Γ))
  I′ = var #0

  -- ∅ ⊢ A ⊃ B ⊃ A
  K :  {Γ}  Tm (nat Γ)
  K = lam lam var #1

  -- ∅ ⊢ (A ⊃ B ⊃ C) ⊃ (A ⊃ B) ⊃ A ⊃ C
  S :  {Γ}  Tm (nat Γ)
  S = lam lam lam (((var #2) $ (var #0)) $ ((var #1) $ (var #0)))


module MTms where
  H :  {Γ A B}
       Γ  Tms.H  B  A  A
  H = Mlam Mlam Mvar M#0

  I :  {Γ A}
       Γ  Tms.I  A  A
  I = Mlam Mvar M#0

  I′ :  {Γ A}
       Γ , A  Tms.I′  A
  I′ = Mvar M#0

  K :  {Γ A B}
       Γ  Tms.K  A  B  A
  K = Mlam Mlam Mvar M#1

  S :  {Γ A B C}
       Γ  Tms.S  (A  B  C)  (A  B)  A  C
  S = Mlam Mlam Mlam (((Mvar M#2) M$ (Mvar M#0)) M$ ((Mvar M#1) M$ (Mvar M#0)))


module MMTms where
  H :  {Γ A B}
       Γ  Tms.H  Tms.H  B  A  A
  H = lift MTms.H

  I :  {Γ A}
       Γ  Tms.I  Tms.I  A  A
  I = lift MTms.I

  I′ :  {Γ A}
       Γ , A  Tms.I′  Tms.I′  A
  I′ = lift MTms.I′

  K :  {Γ A B}
       Γ  Tms.K  Tms.K  A  B  A
  K = lift MTms.K

  S :  {Γ A B C}
       Γ  Tms.S  Tms.S  (A  B  C)  (A  B)  A  C
  S = lift MTms.S


module S4 where
  K :  {Γ A B f x}
       Γ  lam lam ((var #1) $ (var #0))  (f  (A  B))  x  A  (f $ x)  B
  K = Mlam Mlam {!!}

  T :  {Γ A x}
       Γ  lam dn var #0  (x  A  A)
  T = Mlam Mdn Mvar M#0

  #4 :  {Γ A x}
       Γ  lam up var #0  (x  A  ! x  x  A)
  #4 = Mlam Mup Mvar M#0

  X1 :  {Γ A B x y}
       Γ  lam lam up  var #1 , var #0   (x  A  y  B  !  x , y    x , y   (A  B))
  X1 = Mlam Mlam Mup {!!}

module Example1 where
  E11 :  {Γ A x}
       Γ  lam dn var #0  (x  A  A)
  E11 = Mlam Mdn Mvar M#0

  E13 :  {Γ A B}
       Γ  lam lam  var #1 , var #0   lam lam  var #1 , var #0   (A  B  A  B)
  E13 = MMlam MMlam  MMvar M#1 MM, MMvar M#0