{-# OPTIONS --without-K #-}
module IK.Norm.Properties.Completeness where


--
-- This module proves the soundness of evaluation (eval-sound),
-- from which the completeness of normalization (norm-complete) follows.
--

open import Data.Unit
  using ( ; tt)
open import Data.Product
  using (Σ ; _×_ ; _,_ ; )

open import Relation.Binary.PropositionalEquality

open import IK.Norm.Base

open import IK.Norm.NbE.Model
open import IK.Norm.NbE.Reification

open import IK.Term

-- soundness relation on semantic values
_≋_ : Tm' Γ a  Tm' Γ a  Set
_≋_ {Γ} {a = ι}      n       m
  = n  m
_≋_ {Γ} {a = a  b}  f       g
  = {Γ' : Ctx} (w : Γ  Γ')  {x y : Tm' Γ' a}
     Psh x  Psh y
     x  y  f w x  g w y
_≋_ {Γ} {a =  a}    b       c
  = let box' x = b ; box' y = c in x  y

-- soundness relation on semantic substitutions
data _≋ₛ_ : Sub' Γ Δ  Sub' Γ Δ  Set where
  []   : _≋ₛ_ {Γ = Γ} {Δ = []} tt tt
  _`,_ : {s : Sub' Γ Δ} {s' : Sub' Γ Δ} {x : Tm' Γ a} {y : Tm' Γ a}
        s ≋ₛ s'  x  y  (s , x) ≋ₛ (s' , y)
  lock : {s : Sub' Γ Δ} {s' : Sub' Γ Δ}
        s ≋ₛ s'  (e : LFExt Γ' (Γ #) (ΓR))
        _≋ₛ_ {Γ = Γ'} {Δ = Δ #} (lock s e)  (lock s' e)

------------------------
-- Properties of ≋ and ≋ₛ
------------------------

-- ≋ is symmetric
sym-≋ : {x y : Tm' Γ a}
       x  y  y  x
sym-≋ {a = ι}     n≡m
  = sym n≡m
sym-≋ {a = a  b} f≋g
  = λ w px' py' x'≋y'  sym-≋ {a = b} (f≋g w py' px' (sym-≋ {a = a} x'≋y'))
sym-≋ {a =  a}   b≋c
  = sym-≋ {a = a} b≋c

-- ≋ is transitive
trans-≋ : {x y z : Tm' Γ a}
   x  y  y  z  x  z
trans-≋ {a = ι}                 n≡m m≡o
  = trans n≡m m≡o
trans-≋ {a = a  b} {f} {g} {h} f≋g g≋h w {x = x} {y = y} px py x≋y
  = trans-≋ {a = b}
      (f≋g w px py x≋y)
      (g≋h w py py ((trans-≋ {a = a} (sym-≋ {a = a} x≋y) x≋y)))
trans-≋ {a =  a}               b≋c c≋d
  = trans-≋ {a = a} b≋c c≋d

-- WTH should this thing be called?
pseudo-refl-≋ : {x y : Tm' Γ a}
   x  y  x  x
pseudo-refl-≋ {a = a} x≋y = trans-≋ {a = a} x≋y (sym-≋ {a = a} x≋y)

-- ≋ₛ is symmetric
sym-≋ₛ : {s s' : Sub' Γ Δ}
       s ≋ₛ s'  s' ≋ₛ s
sym-≋ₛ {Δ = []}     s≋s'
  = s≋s'
sym-≋ₛ {Δ = Δ `, a} (s≋s' `, x≋y)
  = sym-≋ₛ s≋s' `, sym-≋ {a = a} x≋y
sym-≋ₛ {Δ = Δ #} (lock s≋s' e)
  = lock (sym-≋ₛ s≋s') e

-- ≋ₛ is transitive
trans-≋ₛ : {s s' s'' : Sub' Γ Δ}
     s ≋ₛ s'  s' ≋ₛ s''  s ≋ₛ s''
trans-≋ₛ {Δ = []}     s≋s'           s'≋s''
  = []
trans-≋ₛ {Δ = Δ `, a} (s≋s' `, x≋x') (s'≋s'' `, x'≋x'')
  = trans-≋ₛ s≋s' s'≋s'' `, trans-≋ {a = a} x≋x' x'≋x''
trans-≋ₛ {Δ = Δ #}    (lock s≋s' e)  (lock s'≋s'' e)
  = lock (trans-≋ₛ s≋s' s'≋s'') e

-- WTH should this thing be called?
pseudo-refl-≋ₛ : {s s' : Sub' Γ Δ}
   s ≋ₛ s'  s ≋ₛ s
pseudo-refl-≋ₛ x≋y = trans-≋ₛ x≋y (sym-≋ₛ x≋y)

-- wkTm' preserves the relation _≋_
wkTm'Pres≋ : {x : Tm' Γ a} {y : Tm' Γ a}
   (w : Γ  Δ)
   x  y
   wkTm' w x  wkTm' w y
wkTm'Pres≋ {a = ι}                     w n≡m
  = cong (wkNf w) n≡m
wkTm'Pres≋ {a = a  b} {x = f} {y = g} w f≋g
  = λ w' px py x≋y  f≋g (w  w') px py x≋y
wkTm'Pres≋ {a =  a}                   w b≋c
  = wkTm'Pres≋ {a = a} (keep# w) b≋c

-- wkSub' preserves the relation _≋_
wkSub'Pres≋ : {s s' : Sub' Γ Δ}
   (w : Γ  Γ')
   s ≋ₛ s'
   wkSub' w s ≋ₛ wkSub' w s'
wkSub'Pres≋ w []
  = []
wkSub'Pres≋ {Δ = Δ `, a} w (s≋s' `, x)
  = wkSub'Pres≋ w s≋s' `, wkTm'Pres≋ {a = a} w x
wkSub'Pres≋ w (lock s≋s e)
  = lock (wkSub'Pres≋ (sliceLeft e w) s≋s) (wkLFExt e w)

--------------------------------------
-- The Fundamental theorem of ≋ and ≋ₛ
--------------------------------------

private

  substVar'Pres≋ : (x : Var Γ a) {s s' : Sub' Δ Γ}
     s ≋ₛ s'
     substVar' x s  substVar' x s'
  substVar'Pres≋ zero     {s = _ , x} {s' = _ , y}  (_ `, x≋y)
    = x≋y
  substVar'Pres≋ (succ x) {s = s , _} {s' = s' , _} (s≋s' `, _)
    = substVar'Pres≋ x s≋s'

  unbox'Pres≋ : {b c : Box (Tm'- a) Γ}
     (e : LFExt Γ' (Γ #) ΓR)
     b  c
     unbox' b e  unbox' c e
  unbox'Pres≋ {a = a} e b≋c
    = wkTm'Pres≋ {a = a} (LFExtToWk e) b≋c

--
fund :  (t : Tm Γ a) {s s' : Sub' Δ Γ}
   Pshₛ s  Pshₛ s'
   s ≋ₛ s'  eval t s  eval t s'
fund (var x) ps ps' s≋s'
  = substVar'Pres≋ x s≋s'
fund (lam t) {s = s} {s' = s'} ps ps' s≋s' w px py x≋y
  = fund t
      (wkSub'PresPsh w s ps , px)
      (wkSub'PresPsh w s' ps' , py)
      (wkSub'Pres≋ w s≋s' `, x≋y)
fund (app t u) {s = s} {s' = s'} ps ps' s≋s'
  = fund t ps ps' s≋s' idWk (psh-eval u s ps) (psh-eval u s' ps') (fund u ps ps' s≋s')
fund (box t) ps ps' s≋s'
  = fund t ps ps' (lock s≋s' nil)
fund (unbox t nil) {s = lock s e} {s' = lock s' .e} ps ps' (lock s≋s' .e)
  = unbox'Pres≋ {b = eval t s} e (fund t ps ps' s≋s')
fund (unbox t (ext e)) (ps , _) (ps' , _) (s≋s' `, _)
  = fund (unbox t e) ps ps' s≋s'

--
fundₛ :  (s₀ : Sub Γ Δ) {s s' : Sub' Δ' Γ}
   Pshₛ s  Pshₛ s'
   s ≋ₛ s'  evalₛ s₀ s ≋ₛ evalₛ s₀ s'
fundₛ []          ps ps' s≋s'
  = []
fundₛ (s₀ `, t)   ps ps' s≋s'
  = (fundₛ s₀ ps ps' s≋s') `, fund t ps ps' s≋s'
fundₛ (lock s₀ (ext e)) {s = s , _} {s' = s' , _} (ps , _) (ps' , _) (s≋s' `, _)
  = fundₛ (lock s₀ e) ps ps' s≋s'
fundₛ (lock s₀ nil) {s = lock s e} {s' = lock s' e} ps ps' (lock s≋s' e)
  = lock (fundₛ s₀ ps ps' s≋s') e

--------------------------
-- Soundness of evaluation
--------------------------

coh-substVar-evalₛ : (x : Var Γ a) (s₀ : Sub Δ Γ) {s s' : Sub' Δ' Δ}
   Pshₛ s  Pshₛ s'  s ≋ₛ s'  substVar' x (evalₛ s₀ s')  eval (substVar s₀ x) s'
coh-substVar-evalₛ zero     (_ `, t) {s} {s'} ps ps' s≋s'
  = pseudo-refl-≋ {x = eval t s'} (sym-≋ {x = eval t s} (fund t ps ps' s≋s'))
coh-substVar-evalₛ (succ x) (s₀ `, _) ps ps' s≋s'
  = coh-substVar-evalₛ x s₀ ps ps' s≋s'

coh-substTm-evalₛ : (t : Tm Γ a) (s₀ : Sub Δ Γ) {s s' : Sub' Δ' Δ}
   Pshₛ s  Pshₛ s'  s ≋ₛ s'  eval t (evalₛ s₀ s')  eval (substTm s₀ t) s'
coh-substTm-evalₛ (var x)     s₀ ps ps' s≋s'
  = coh-substVar-evalₛ x s₀ ps ps' s≋s'
coh-substTm-evalₛ (lam t)     s₀ {s} {s'} ps ps' s≋s' w {x = x} {y} px py x≋y
  rewrite sym (nat-evalₛ w s₀ s' ps')
  = trans-≋ {z =  eval (substTm (wkSub fresh s₀ `, var zero) t) (wkSub' w s' , y)}
      ((subst  z  _  eval t (z , y))
        (trans
          (cong (evalₛ s₀) (sym (trimSub'PresId _)))
          (sym (coh-trimSub'-wkSub fresh s₀ (wkSub' w s' , y))))
        (fund t
          (psh-evalₛ s₀ _ (wkSub'PresPsh w s' ps') , px)
          (psh-evalₛ s₀ _ (wkSub'PresPsh w s' ps') , py)
          (fundₛ s₀
            (wkSub'PresPsh w s' ps')
            (wkSub'PresPsh w s' ps')
            (wkSub'Pres≋ w ((pseudo-refl-≋ₛ {s = s'} (sym-≋ₛ s≋s')))) `, x≋y))))
      ((coh-substTm-evalₛ t
        (keepₛ s₀)
        (wkSub'PresPsh w s ps , px)
        (wkSub'PresPsh w s' ps' , py)
        (wkSub'Pres≋ w s≋s' `, x≋y)))
coh-substTm-evalₛ (app t u)  s₀ ps ps' s≋s'
  = coh-substTm-evalₛ t s₀ ps ps' s≋s' idWk
      (psh-eval u _ (psh-evalₛ s₀ _ ps'))
      (psh-eval (substTm s₀ u) _ ps')
      (coh-substTm-evalₛ u s₀ ps ps' s≋s')
coh-substTm-evalₛ (box t)     s₀ ps ps' s≋s'
  = coh-substTm-evalₛ t (lock s₀ nil) ps ps' (lock s≋s' nil)
coh-substTm-evalₛ (unbox t (ext e)) (s₀ `, _) ps ps' s≋s'
  = coh-substTm-evalₛ (unbox t e) s₀ ps ps' s≋s'
coh-substTm-evalₛ (unbox t nil) (lock s₀ (ext e)) (ps , _) (ps' , _) (s≋s' `, _)
  = coh-substTm-evalₛ (unbox t nil) (lock s₀ e) ps ps' s≋s'
coh-substTm-evalₛ (unbox t nil) (lock s₀ nil) {s = lock s e} {s' = lock s' e'} ps ps' (lock s≋s' e')
  = unbox'Pres≋ {b = eval t (evalₛ s₀ s')} e' (coh-substTm-evalₛ t s₀ ps ps' s≋s')

private
  lemma1 : {t : Tm (ΓL #) a} (e : LFExt Γ (ΓL #) ΓR) {s s' : Sub' Δ Γ}
     Pshₛ s  Pshₛ s'
     s ≋ₛ s'
     eval (unbox (box t) e) s  eval t (trimSub' (LFExtToWk e) s')
  lemma1 {t = t} nil {s = lock s e} {s' = lock s' e} ps ps' (lock s≋s' e)
    with ←#IsPre# e | #→IsPost# e
  ... | refl | refl
    rewrite sym (nat-eval t (LFExtToWk e) (lock s nil) ps)
      | ExtIsProp (wkLFExt nil (LFExtToWk e)) e
        = fund t
               (wkSub'PresPsh (sliceLeft nil (LFExtToWk e)) s ps)
               (subst Pshₛ (sym (trimSub'PresId s')) ps')
               (lock lemma1-2 e)
    where
      lemma1-1' :  (e : LFExt Γ ΓL ΓR)  (p : ΓL  ←# Γ #)  sliceLeft nil (LFExtToWk (subst  ΓL  LFExt Γ ΓL ΓR) p e))  idWk
      lemma1-1' {Γ = Γ #}    nil     p    rewrite Ctx-K p = refl
      lemma1-1' {Γ = Γ `, a} (ext e) refl                 = lemma1-1' e refl
      lemma1-1 :  (e : LFExt Γ (←# Γ #) ΓR)  sliceLeft nil (LFExtToWk e)  idWk
      lemma1-1 e = lemma1-1' e refl
      lemma1-2 : wkSub' (sliceLeft nil (LFExtToWk e)) s ≋ₛ trimSub' idWk s'
      lemma1-2 rewrite lemma1-1 e
        | trimSub'PresId s'
        | wkSub'PresId s = s≋s'
  lemma1 {t = t} (ext e) (s  , _) (s' , _) (s≋s' `, _)
    = lemma1 {t = t} e s s' s≋s'

  lemma2 : {b c : Tm' Γ ( a)}
     b  c
     b  box' (unbox' c new)
  lemma2 {c = c} b≋c rewrite (let box' y = c in wkTm'PresId y)
      = b≋c

-- soundness of evaluation wrt single-step reduction
eval-sound-red : {t t' : Tm Γ a} {s s' : Sub' Δ Γ}
   t  t'
   Pshₛ s  Pshₛ s'  s ≋ₛ s'  eval t s  eval t' s'
eval-sound-red {Γ = Γ} {Δ = Δ} {t = app (lam {b = b} t) u} {s = s} {s' = s'} red-fun ps ps' s≋s'
  rewrite wkSub'PresId s
  | evalₛPresId s'
    = trans-≋ {Γ = Δ} {a = b}
      (fund t
            (ps , (psh-eval u s ps))
            (subst Pshₛ (sym (evalₛPresId s')) ps' , psh-eval u s' ps')
            (subst (s ≋ₛ_) (sym (evalₛPresId s')) s≋s' `, fund u ps ps' s≋s'))
      (coh-substTm-evalₛ t (idₛ `, u) {s} {s'} ps ps' s≋s')
eval-sound-red {t = t} {s = s} {s'} exp-fun  ps ps' s≋s' w {x = x} px py x≋y
  rewrite sym (rightIdWk w)
  | sym (cong  f  f idWk x) (nat-eval t w s ps))
  | sym (trimSub'PresId (wkSub' w s))
  | rightIdWk w
  | sym (coh-trimSub'-wkTm fresh (wkSub' w s , x) t)
    = fund (wkTm (drop idWk) t)
           (wkSub'PresPsh w s ps , px)
           (wkSub'PresPsh w s' ps' , py)
           (wkSub'Pres≋ w s≋s' `, x≋y)
           idWk
           px
           py
           x≋y
eval-sound-red {t = unbox (box t) e} {s = s} {s' = s'} red-box ps ps' s≋s'
  rewrite coh-trimSub'-wkTm (LFExtToWk e) s' t
  = lemma1 {t = t} e ps ps' s≋s'
eval-sound-red {t = t} {s = s} {s'} exp-box ps ps' s≋s'
  = lemma2 {b = eval t s} (fund t ps ps' s≋s')
eval-sound-red {t = t} {s = s} {s'} (cong-lam r) ps ps' s≋s' w {x = x} px py x≋y
  = eval-sound-red r
      (wkSub'PresPsh w s ps , px)
      (wkSub'PresPsh w s' ps' , py)
      ((wkSub'Pres≋ w s≋s') `, x≋y)
eval-sound-red {t = app t u} {t' = app t' u'} {s = s} {s' = s'} (cong-app1 r) ps ps' s≋s'
  = eval-sound-red r ps ps' s≋s'
      idWk
      (psh-eval u s ps)
      (psh-eval u s' ps')
      (fund u ps ps' s≋s')
eval-sound-red {t = app t u} {t' = app t' u'} {s = s} {s' = s'} (cong-app2 r) ps ps' s≋s'
  = fund t ps ps' s≋s' idWk (psh-eval u s ps) (psh-eval u' s' ps') (eval-sound-red r ps ps' s≋s')
eval-sound-red (cong-box r) ps ps' s≋s'
  = eval-sound-red r ps ps' (lock s≋s' nil)
eval-sound-red {s = lock s e} {s' = lock s' .e} (cong-unbox {t = t} {e = nil} r) ps ps' (lock s≋s' e)
  = unbox'Pres≋ {b = eval t s} e (eval-sound-red r ps ps' s≋s')
eval-sound-red {s = s , _} {s' = s' , _} (cong-unbox {t = t} {e = ext e} r) (ps , _) (ps' , _) (s≋s' `, _)
  = eval-sound-red (cong-unbox {e = e} r) ps ps' s≋s'

-- soundness of evaluation wrt multi-step reduction
eval-sound-red* : {t t' : Tm Γ a} {s s' : Sub' Δ Γ}
   t ⟶* t'
   Pshₛ s  Pshₛ s'  s ≋ₛ s'  eval t s  eval t' s'
eval-sound-red* {t = t} {t' = .t} ε        ps ps' s≋s'
  = fund t ps ps' s≋s'
eval-sound-red* {a = a} {t = t} {t' = t'} (r  rs) ps ps' s≋s'
  = trans-≋ {a = a} (eval-sound-red r ps ps' s≋s') (eval-sound-red* rs ps' ps' (pseudo-refl-≋ₛ (sym-≋ₛ s≋s')))

-- soundness of evaluation wrt conversion
eval-sound : {t t' : Tm Γ a} {s s' : Sub' Δ Γ}
   t  t'
   Pshₛ s  Pshₛ s'  s ≋ₛ s'  eval t s  eval t' s'
eval-sound {t = t} ε ps ps' s≋s'
  = eval-sound-red* {t = t} ⟶*-refl ps ps' s≋s'
eval-sound {a = a} (inj₁ r  t≈t') ps ps' s≋s'
  = trans-≋ {a = a} (eval-sound-red r ps ps' s≋s') (eval-sound t≈t' ps' ps' (pseudo-refl-≋ₛ (sym-≋ₛ s≋s')))
eval-sound {a = a} {t = t} {s = s} {s' = s'} (inj₂ r  t≈t') ps ps' s≋s'
  = trans-≋ {a = a}
      (sym-≋ {y = eval t s} (eval-sound-red r ps' ps (sym-≋ₛ s≋s')))
      (eval-sound t≈t' ps' ps' (pseudo-refl-≋ₛ (sym-≋ₛ s≋s')))

--------------------------------------------------------
-- Uniqueness of reification and soundness of reflection
--------------------------------------------------------

unique-reify : {x y : Tm' Γ a}
   x  y  reify x  reify y
sound-reflect : {n n' : Ne Γ a}
   n  n'  reflect n  reflect n'

unique-reify {a = ι}     n≡m = n≡m
unique-reify {a = a  b} f≋g = cong lam
  (unique-reify
    (f≋g fresh (psh-reflect {a = a} (var zero)) (psh-reflect {a = a} (var zero))
    (sound-reflect {a = a} refl)))
unique-reify {a =  a}   b≋c
  = cong box (unique-reify b≋c)

sound-reflect {a = ι}      n≡n'
  = cong up n≡n'
sound-reflect {a = a  b}  n≡n' w px py x≋y
  = sound-reflect {a = b} (cong₂ app (cong (wkNe w) n≡n') (unique-reify x≋y))
sound-reflect {a =  a}    n≡n'
  = sound-reflect {a = a} (cong₂ unbox n≡n' refl)

--------------------------------
-- Completeness of normalization
--------------------------------

idₛ'≋idₛ' : {Γ : Ctx}  idₛ' {Γ} ≋ₛ idₛ'
idₛ'≋idₛ' {[]}     = []
idₛ'≋idₛ' {Γ `, a} = (wkSub'Pres≋ fresh (idₛ'≋idₛ' {Γ})) `, (sound-reflect {a = a} refl)
idₛ'≋idₛ' {Γ #}    = lock idₛ'≋idₛ' nil

norm-complete-red* : {t t' : Tm Γ a}  t ⟶* t'  norm t  norm t'
norm-complete-red* {Γ = Γ} r = unique-reify (eval-sound-red* r (psh-idₛ' {Γ}) (psh-idₛ' {Γ}) idₛ'≋idₛ')

norm-complete : {t t' : Tm Γ a}  t  t'  norm t  norm t'
norm-complete {Γ = Γ} p = unique-reify (eval-sound p (psh-idₛ' {Γ}) (psh-idₛ' {Γ}) idₛ'≋idₛ')

Generated from commit 2fd14c996b195ef101dff8919e837907ca0a08aa.