{-# OPTIONS --without-K --safe #-}

module STLCSubst.Semantics.Definitions where

open import Relation.Binary.PropositionalEquality hiding ([_])

open import Lib

open import STLCSubst.Statics

mutual
  Env : Set
  Env =   D

  data D : Set where
    ze : D
    su : D  D
    Λ  : (t : Exp)  (ρ : Env)  D
      : (T : Typ)  (e : Dn)  D

  data Dn : Set where
    l   : (x : )  Dn
    rec : (T : Typ)  (z : Df)  (s : Exp)  (ρ : Env)  Dn  Dn
    _$_ : Dn  (d : Df)  Dn

  data Df : Set where
     : (T : Typ)  (a : D)  Df

infixl 10 [_]_$′_
pattern l′ T x          =  T (l x)
pattern rec′ T T′ z s ρ w =  T (rec T′ z s ρ w)
pattern [_]_$′_ T x y   =  T (_$_ x y)

variable
  a a′ a″    : D
  b b′ b″    : D
  f f′ f″    : D
  e e′ e″    : Dn
  d d′ d″ d‴ : Df
  ρ ρ′ ρ″    : Env

env-ext : Env  D  Env
env-ext ρ d zero = d
env-ext ρ d (suc x) = ρ x

instance
  Env-Extends : Extends Env D
  Env-Extends = record { _↦_ = env-ext }

ext-cong : ρ  ρ′  a  a′  ρ  a  ρ′  a′
ext-cong eq eq′ zero    = eq′
ext-cong eq eq′ (suc x) = eq x

drop : Env  Env
drop ρ n = ρ (suc n)

infix 4 _∙_↘_ ⟦_⟧_↘_ rec_,_,_,_,_↘_ ⟦_⟧s_↘_

mutual
  data _∙_↘_ : D  D  D  Set where
    Λ∙ :  t  ρ  a  b 
         ------------------
         Λ t ρ  a  b
    $∙ :  S T e a   (S  T) e  a   T (e $  S a)

  data ⟦_⟧_↘_ : Exp  Env  D  Set where
    ⟦v⟧   :  n 
             v n  ρ  ρ n
    ⟦ze⟧  :  ze  ρ  ze
    ⟦su⟧  :  t  ρ  a 
            -----------------
             su t  ρ  su a
    ⟦rec⟧ :  s  ρ  a′ 
             t  ρ  a 
            rec T , a′ , r , ρ , a  b 
            -----------------------
             rec T s r t  ρ  b
    ⟦Λ⟧   :  t 
             Λ t  ρ  Λ t ρ
    ⟦$⟧   :  r  ρ  f 
             s  ρ  a 
            f  a  b 
            ------------------------
             r $ s  ρ  b

  data rec_,_,_,_,_↘_ : Typ  D  Exp  Env  D  D  Set where
    rze : rec T , a′ , r , ρ , ze  a′
    rsu : rec T , a′ , r , ρ , a  b 
           r  ρ  a  b  b′ 
          ----------------------
          rec T , a′ , r , ρ , su a  b′
    rec : rec T , a′ , r , ρ ,  S e   T (rec T ( T a′) r ρ e)

⟦_⟧s_↘_ : Subst  Env  Env  Set
 σ ⟧s ρ  ρ′ =  x   σ x  ρ  ρ′ x

⟦⟧s-transp : (δ : Subst)  σ  δ   σ ⟧s ρ  ρ′   δ ⟧s ρ  ρ′
⟦⟧s-transp δ eq ↘ρ′ x
  with ↘ρ′ x
...  | ↘ρ′ rewrite eq x = ↘ρ′

⟦⟧s-transp-ret : ρ′  ρ″   σ ⟧s ρ  ρ′   σ ⟧s ρ  ρ″
⟦⟧s-transp-ret {_} {ρ″} eq ↘ρ′ x
  with ρ″ x | eq x
...  | _ | refl = ↘ρ′ x

⟦⟧s-ext :  σ ⟧s ρ  ρ′   t  ρ  a   σ  t ⟧s ρ  ρ′  a
⟦⟧s-ext ↘ρ′ ↘a zero    = ↘a
⟦⟧s-ext ↘ρ′ ↘a (suc x) = ↘ρ′ x

⟦_⟧w : Wk  Env  Env
 ϕ ⟧w ρ n = ρ (ϕ n)

⟦⟧s-conv : (ϕ : Wk)   conv ϕ ⟧s ρ  ρ′  ρ′   ϕ ⟧w ρ
⟦⟧s-conv {ρ′ = ρ′} ϕ ↘ρ′ x
  with ρ′ x | ↘ρ′ x
... | _ | ⟦v⟧ n = refl

⟦⟧s-id :  id ⟧s ρ  ρ
⟦⟧s-id {ρ} x = ⟦v⟧ x

⟦⟧w-comp :  ψ ϕ ρ   ψ ⟧w ( ϕ ⟧w ρ)   ψ  ϕ ⟧w ρ
⟦⟧w-comp ψ ϕ ρ x = refl

mutual
  ap-det : f  a  b  f  a  b′  b  b′
  ap-det (Λ∙ ↘b) (Λ∙ ↘b′)             = ⟦⟧-det ↘b ↘b′
  ap-det ($∙ S T e _) ($∙ .S .T .e _) = refl

  ⟦⟧-det :  t  ρ  a   t  ρ  b  a  b
  ⟦⟧-det (⟦v⟧ n) (⟦v⟧ .n)    = refl
  ⟦⟧-det ⟦ze⟧ ⟦ze⟧           = refl
  ⟦⟧-det (⟦su⟧ ↘a) (⟦su⟧ ↘b) = cong su (⟦⟧-det ↘a ↘b)
  ⟦⟧-det (⟦rec⟧ ↘a′ ↘a r↘) (⟦rec⟧ ↘b′ ↘b r↘′)
    rewrite ⟦⟧-det ↘a′ ↘b′
          | ⟦⟧-det ↘a ↘b
          | rec-det r↘ r↘′   = refl
  ⟦⟧-det (⟦Λ⟧ t) (⟦Λ⟧ .t)    = refl
  ⟦⟧-det (⟦$⟧ ↘f ↘a ↘b) (⟦$⟧ ↘f′ ↘a′ ↘b′)
    rewrite ⟦⟧-det ↘f ↘f′
          | ⟦⟧-det ↘a ↘a′
          | ap-det ↘b ↘b′    = refl

  rec-det : rec T , f , t , ρ , f″  a  rec T , f , t , ρ , f″  b  a  b
  rec-det rze rze         = refl
  rec-det (rsu ↘a ↘b) (rsu ↘a′ ↘b′)
    rewrite rec-det ↘a ↘a′
          | ⟦⟧-det ↘b ↘b′ = refl
  rec-det rec rec         = refl

⟦⟧s-det :  σ ⟧s ρ  ρ′   σ ⟧s ρ  ρ″  ρ′  ρ″
⟦⟧s-det ↘ρ′ ↘ρ″ x = ⟦⟧-det (↘ρ′ x) (↘ρ″ x)

infix 4 Rf_-_↘_ Re_-_↘_

mutual

  data Rf_-_↘_ :   Df  Nf  Set where
    Rze :  n 
          Rf n -  N ze  ze
    Rsu :  n 
          Rf n -  N a  w 
          --------------------
          Rf n -  N (su a)  su w
      :  n 
          f  l′ S n  a 
          Rf (suc n) -  T a  w 
          ---------------------
          Rf n -  (S  T) f  Λ w
    Rne :  n 
          Re n - e  u 
          ---------------------
          Rf n -  N ( T e)  ne u

  data Re_-_↘_ :   Dn  Ne  Set where
    Rl :  n x 
         Re n - l x  v (n  x  1)
    Rr :  n 
         Rf n - d′  w′ 
          s  ρ  l′ N n  l′ T (1 + n)  a 
         Rf (2 + n) -  T a  w″ 
         Re n - e  u 
         ----------------------------------
         Re n - rec T d′ s ρ e  rec T w′ w″ u
    R$ :  n 
         Re n - e  u 
         Rf n - d  w 
         ---------------------
         Re n - e $ d  u $ w

mutual
  Rf-det :  {n}  Rf n - d  w  Rf n - d  w′  w  w′
  Rf-det (Rze _) (Rze _)        = refl
  Rf-det (Rsu _ ↘w) (Rsu _ ↘w′) = cong su (Rf-det ↘w ↘w′)
  Rf-det ( _ ↘a ↘w) ( _ ↘a′ ↘w′)
    rewrite ap-det ↘a ↘a′       = cong Λ (Rf-det ↘w ↘w′)
  Rf-det (Rne _ ↘u) (Rne _ ↘u′) = cong ne (Re-det ↘u ↘u′)

  Re-det :  {n}  Re n - e  u  Re n - e  u′  u  u′
  Re-det (Rl _ x) (Rl _ .x) = refl
  Re-det (Rr _ ↘w ↘a ↘w′ ↘u) (Rr _ ↘w″ ↘a′ ↘w‴ ↘u′)
    rewrite Rf-det ↘w ↘w″
          | ⟦⟧-det ↘a ↘a′
          | Rf-det ↘w′ ↘w‴
          | Re-det ↘u ↘u′   = refl
  Re-det (R$ _ ↘u ↘w) (R$ _ ↘u′ ↘w′)
    rewrite Re-det ↘u ↘u′
          | Rf-det ↘w ↘w′   = refl

record Nbe n ρ t T w : Set where
  field
    ⟦t⟧  : D
    ↘⟦t⟧ :  t  ρ  ⟦t⟧
    ↓⟦t⟧ : Rf n -  T ⟦t⟧  w

InitialEnv : Ctx  Env
InitialEnv []      i       = ze
InitialEnv (T  Γ) zero    = l′ T (L.length Γ)
InitialEnv (T  Γ) (suc i) = InitialEnv Γ i