open import Relation.Binary using (Decidable)
open import Relation.Binary.PropositionalEquality using (_≡_)
module Fundamental
  {{ Α : Set }} 
  {{ C : Set }} 
  {{ Var : Set }} 
  {{ decEqVar : Decidable (_≡_ {A = Var}) }}
  {{ Κ : Set }} 
  where
import SyntaxRew
open SyntaxRew
  {{ Α }} 
  {{ C }} 
  {{ Var }} 
  {{ decEqVar }} 
  {{ Κ }} 
import SmlSem
open SmlSem
  {{ Α }} 
  {{ C }} 
  {{ Var }} 
  {{ decEqVar }} 
  {{ Κ }} 
  using ( _+_⊢_∣_~>_∣_ ; sdec ; s∃R ; s⇒R ; s∀R ;
    _+_⊢_∣_~_∷_~>_∣_ ; unif ; s⇒L ; s∀L ;
    smldec-val-prog ;
    view-C ; view-C-dec )
import LogRel
open LogRel
  {{ Α }} 
  {{ C }} 
  {{ Var }} 
  {{ decEqVar }} 
  {{ Κ }} 
 
open import Relation.Binary.PropositionalEquality
open import Data.Product using (∃ ; ∃₂ ; ∃! ; _×_ ; _,_ )
{-# TERMINATING #-}
fundamental : {S : Sig} {P : Prog} {Γ Γ' : Ctx} {ê ê' : MT}  →
  S + P ⊢ Γ ∣ ê ~> Γ' ∣ ê' → logrel S P Γ' ê' ê
fundamentaldec : {S : Sig} {P : Prog} {Γ Γ' : Ctx} {ê : MT} {e e' : MT} {D : De} →
  S + P ⊢ Γ ∣ ê ~ e' ∷ D ~> Γ' ∣ e →
  logrelced S P Γ e' D →
  logreldec S P Γ' e' D e ê
fundamental (sdec {C = C} smldec κ∷DinP)
  with view-C-dec {C = C} refl smldec
... | e' , θ' , refl , smldec' = lift-ldecide (fundamentaldec smldec'
  (subst (λ x → logrelced _ _ _ _ x) unit-ε-De (ldecide⁻ {θ = ε} κ∷DinP (smldec-val-prog smldec'))))
  (subst (λ x → logrelced _ _ _ _ x) unit-ε-De  (ldecide⁻ κ∷DinP (smldec-val-prog smldec')))
fundamental (s∃R {C = C} {x} sml)
  with view-C {C = C} refl sml
... | e' , θ' , refl , sml'
  with view-C {C = < var x , ● >} refl sml'
... | M , θ'' , refl , sml''
  with θ'' {X = x}
... | M' , wfP = lift-∃R {C = C} (fundamental sml'') (wfP here)
fundamental (s⇒R {C = C} {κ = κ} sml) 
  with view-C {C = C} refl sml
... | e' , θ' , refl , sml' 
  with view-C {C = lam κ ● } refl sml'
... | e'' , θ'' , refl , sml'' = lift-⇒R (fundamental sml'')  
fundamental (s∀R {C = C} sml)
  with view-C {C = C} refl sml
... | e' , θ' , refl , sml'
  = lift-∀R (fundamental sml')
open import Function
fundamentaldec (unif σ eq z) lced = lift-linit eq lced
fundamentaldec (s⇒L {C = C} smldec) lced
  with view-C-dec {C = C} refl smldec
... | e , θ , refl , smldec'
  with fundamentaldec smldec (l⇒L⁻ lced (logrefl (logced-val-prog lced)))
... | ldec
    = lift-⇒L (logrefl (logced-val-prog lced)) ldec
fundamentaldec (s∀L {C = C} {x = x} smldec) lced
  with view-C-dec {C = C} refl smldec
... | e , θ , refl , smldec'
  with fundamentaldec smldec' (lced-∀inv lced)
... | ldec
  with θ {x}
... | M , wfP = lift-∀L' ( logdec-subst ldec) (wfP here)