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

module STLCSubst.Semantics.PER where


open import Level using (0ℓ)
open import Relation.Binary using (Rel; PartialSetoid; IsPartialEquivalence)
open import Relation.Binary.PropositionalEquality using (_≗_)

open import Lib
open import STLCSubst.Statics
open import STLCSubst.Statics.Properties
open import STLCSubst.Semantics.Definitions

Ty : Set₁
Ty = Rel D 0ℓ

infix 3 _≈_∈_ _∈!_
_≈_∈_ :  {} {A : Set }  A  A  Rel A 0ℓ  Set
x  y  R = R x y

_∈!_ :  {} {A : Set }  A  Rel A 0ℓ  Set
x ∈! R = x  x  R

Top : Rel Df 0ℓ
Top d d′ =  n   λ w  Rf n - d  w × Rf n - d′  w

Bot : Rel Dn 0ℓ
Bot e e′ =  n   λ u  Re n - e  u × Re n - e′  u

l∈Bot :  x  Bot (l x) (l x)
l∈Bot x n = v (n  x  1) , Rl n x , Rl n x

$∈Bot : e  e′  Bot   d  d′  Top  e $ d  e′ $ d′  Bot
$∈Bot e≈e′ d≈d′ n
  with e≈e′ n
     | d≈d′ n
...  | u , ↘u , ↘u′
     | w , ↘w , ↘w′ = u $ w , R$ n ↘u ↘w , R$ n ↘u′ ↘w′

record _∙_≈_∙_∈[_⟶_] f e f′ e′ S T : Set where
  field
    fe      : D
    f′e′    : D
    ↘fe     : f   S e  fe
    ↘f′e′   : f′   S e′  f′e′
    fe≈f′e′ :  T fe   T f′e′  Top

module FApp {f e f′ e′ S T} (eq : f  e  f′  e′ ∈[ S  T ]) = _∙_≈_∙_∈[_⟶_] eq

↓F∈Top : (∀ {e e′}  e  e′  Bot  f  e  f′  e′ ∈[ S  T ])   (S  T) f   (S  T) f′  Top
↓F∈Top f n = let w , ↘w , ↘w′ = fe≈f′e′ (suc n)
             in Λ w ,  n ↘fe ↘w ,  n ↘f′e′ ↘w′
  where open FApp (f (l∈Bot n))

ze∈Top :  N ze   N ze  Top
ze∈Top n = ze , Rze n , Rze n

su∈Top :  N a   N b  Top   N (su a)   N (su b)  Top
su∈Top a≈b n
  with a≈b n
...  | w , a↘ , b↘ = su w , Rsu n a↘ , Rsu n b↘


infix 3 _≈_∈^_ ↑_≈↑_∈_

_≈_∈^_ : D  D  Typ  Set
a  b ∈^ T =  T a   T b  Top

↑_≈↑_∈_ : Dn  Dn  Typ  Set
 e ≈↑ e′  T = e  e′  Bot

infix 4 _⊩_
record _⊩_ T (A : Ty) : Set where
  field
    ~⊆ :  {e e′}   e ≈↑ e′  T   T e   T e′  A
    ⊆^ :  {a b}  A a b  a  b ∈^ T

record [_∙_≈_∙_]∈_ (f a f′ a′ : D) (T : Ty) : Set where
  constructor
    _-_-_-_-_

  field
    fa fa′ : D
    ↘fa    : f  a  fa
    ↘fa′   : f′  a′  fa′
    fa≈fa′ : fa  fa′  T

module FAppIn {f a f′ a′ T} (r : [ f  a  f′  a′ ]∈ T) = [_∙_≈_∙_]∈_ r

infix 10 _⇒_
_⇒_ : Ty  Ty  Ty
(S  T) f f′ =
   {a a′}  a  a′  S  [ f  a  f′  a′ ]∈ T

F⊩ :  {A B}  S  A  U  B  S  U  A  B
F⊩ {S} {U} {A} {B} SA UB = record
  { ~⊆ = ~⊆
  ; ⊆^ = ⊆^
  }
  where module SA = _⊩_ SA
        module UB = _⊩_ UB

        ~⊆ :  e ≈↑ e′  S  U   (S  U) e   (S  U) e′  A  B
        ~⊆ e≈e′ a≈a′ = record
          { fa     = [ U ] _ $′  S _
          ; fa′    = [ U ] _ $′  S _
          ; ↘fa    = $∙ S U _ _
          ; ↘fa′   = $∙ S U _ _
          ; fa≈fa′ = UB.~⊆ λ n  let u , e↘ , e′↘ = e≈e′ n
                                     w , a↘ , a′↘ = SA.⊆^ a≈a′ n
                                 in u $ w , R$ n e↘ a↘ , R$ n e′↘ a′↘
          }

        ⊆^ : a  b  A  B  a  b ∈^ S  U
        ⊆^ a≈b n = let w , ↘w , ↘w′ = UB.⊆^ app.fa≈fa′ (suc n)
                   in Λ w ,  n app.↘fa ↘w ,  n app.↘fa′ ↘w′
          where app = a≈b (SA.~⊆ λ m  v (m  n  1) , Rl m n , Rl m n)
                module app = FAppIn app

data _≈_∈N : Ty where
  ze-≈ : ze  ze ∈N
  su-≈ : a  a′ ∈N 
         -------------------
         su a  su a′ ∈N
  ↑N   :  {T′} 
         e  e′  Bot 
         -------------------
          T e   T′ e′ ∈N

⟦_⟧T : Typ  Ty
 N ⟧T     = _≈_∈N
 S  U ⟧T =  S ⟧T   U ⟧T

N-sym : a  b ∈N  b  a ∈N
N-sym ze-≈      = ze-≈
N-sym (su-≈ a≈b) = su-≈ (N-sym a≈b)
N-sym (↑N e≈e′) = ↑N  n  let u , ↘u , ↘u′ = e≈e′ n in u , ↘u′ , ↘u)

N-trans : a  a′ ∈N  a′  a″ ∈N  a  a″ ∈N
N-trans ze-≈      ze-≈       = ze-≈
N-trans (su-≈ eq) (su-≈ eq′) = su-≈ (N-trans eq eq′)
N-trans (↑N e≈e′) (↑N e′≈e″) = ↑N λ n  let u , ↘u   , e′↘ = e≈e′ n
                                            _ , e′↘′ , ↘u′ = e′≈e″ n
                                        in u , ↘u , subst (Re n - _ ↘_) (Re-det e′↘′ e′↘) ↘u′

⟦⟧-sym :  T  a  b   T ⟧T  b  a   T ⟧T
⟦⟧-sym N a≈b          = N-sym a≈b
⟦⟧-sym (S  U) a≈b ∈S = record
  { fa     = fa′
  ; fa′    = fa
  ; ↘fa    = ↘fa′
  ; ↘fa′   = ↘fa
  ; fa≈fa′ = ⟦⟧-sym U fa≈fa′
  }
  where open FAppIn (a≈b (⟦⟧-sym S ∈S))

⟦⟧-trans :  T  a  a′   T ⟧T  a′  a″   T ⟧T  a  a″   T ⟧T
⟦⟧-trans N eq eq′                = N-trans eq eq′
⟦⟧-trans (S  U) f≈f′ f′≈f″ x≈y = record
  { fa     = fxUf′x.fa
  ; fa′    = f′xUf″y.fa′
  ; ↘fa    = fxUf′x.↘fa
  ; ↘fa′   = f′xUf″y.↘fa′
  ; fa≈fa′ = trans′ fxUf′x.fa≈fa′
                    (subst  a   U ⟧T a _) (ap-det f′xUf″y.↘fa fxUf′x.↘fa′) f′xUf″y.fa≈fa′)
  }
  where trans′ :  {a b d}  a  b   U ⟧T  b  d   U ⟧T  a  d   U ⟧T
        trans′         = ⟦⟧-trans U
        xSx            = ⟦⟧-trans S x≈y (⟦⟧-sym S x≈y)
        module fxUf′x  = FAppIn (f≈f′ xSx)
        module f′xUf″y = FAppIn (f′≈f″ x≈y)

⟦⟧-PER :  T  IsPartialEquivalence  T ⟧T
⟦⟧-PER T = record
  { sym   = ⟦⟧-sym T
  ; trans = ⟦⟧-trans T
  }

⟦⟧-PartialSetoid : Typ  PartialSetoid _ _
⟦⟧-PartialSetoid T = record
  { _≈_                  =  T ⟧T
  ; isPartialEquivalence = ⟦⟧-PER T
  }

⟦⟧-refl :  T  a  b   T ⟧T  a  a   T ⟧T
⟦⟧-refl T a≈b = ⟦⟧-trans T a≈b (⟦⟧-sym T a≈b)

⟦⟧-refl′ :  T  a  b   T ⟧T  b  b   T ⟧T
⟦⟧-refl′ T a≈b = ⟦⟧-trans T (⟦⟧-sym T a≈b) a≈b


⊩⟦N⟧ : N   N ⟧T
⊩⟦N⟧ = record
  { ~⊆ = ↑N
  ; ⊆^ = ⊆^
  }
  where ⊆^ : a  b ∈N  a  b ∈^ N
        ⊆^ ze-≈ n           = ze , Rze n , Rze n
        ⊆^ (su-≈ a≈b) n
          with ⊆^ a≈b n
        ...  | w , ↘w , ↘w′ = su w , Rsu n ↘w , Rsu n ↘w′
        ⊆^ (↑N e≈e′) n
          with e≈e′ n
        ...  | u , e↘ , e′↘ = ne u , Rne n e↘ , Rne n e′↘

⊩⟦_⟧ :  T  T   T ⟧T
⊩⟦ N      = ⊩⟦N⟧
⊩⟦ S  U  = F⊩ ⊩⟦ S  ⊩⟦ U 

Bot⇒⟦⟧ :  T  e  e′  Bot   T e   T e′   T ⟧T
Bot⇒⟦⟧ T = _⊩_.~⊆ ⊩⟦ T 

⟦⟧⇒Top :  T   a  b   T ⟧T   T a   T b  Top
⟦⟧⇒Top T = _⊩_.⊆^ ⊩⟦ T 

infix 4 ⟦_⟧_≈⟦_⟧_∈s[_]_ ⟦_⟧[_]_≈⟦_⟧[_]_∈_
⟦_⟧ : Ctx  Rel Env 0ℓ
 Δ  ρ ρ′ =  {x T}  x  T  Δ  ρ x  ρ′ x   T ⟧T

⟦⟧-syms : ρ  ρ′   Γ   ρ′  ρ   Γ 
⟦⟧-syms ρ≈ρ′ {_} {T} T∈Γ = ⟦⟧-sym T (ρ≈ρ′ T∈Γ)

⟦⟧-transs : ρ  ρ′   Γ   ρ′  ρ″   Γ   ρ  ρ″   Γ 
⟦⟧-transs ρ≈ρ′ ρ′≈ρ″ {_} {T} T∈Γ = ⟦⟧-trans T (ρ≈ρ′ T∈Γ) (ρ′≈ρ″ T∈Γ)

⟦⟧-refls : ρ  ρ′   Γ   ρ  ρ   Γ 
⟦⟧-refls ρ≈ρ′ = ⟦⟧-transs ρ≈ρ′ (⟦⟧-syms ρ≈ρ′)

⟦⟧-refls′ : ρ  ρ′   Γ   ρ′  ρ′   Γ 
⟦⟧-refls′ ρ≈ρ′ = ⟦⟧-transs (⟦⟧-syms ρ≈ρ′) ρ≈ρ′

⟦⟧-transpˡ : ρ  ρ′   Γ   ρ  ρ″  ρ″  ρ′   Γ 
⟦⟧-transpˡ ρ≈ρ′ eq {x} T∈Γ
  rewrite sym (eq x) = ρ≈ρ′ T∈Γ

⟦⟧-transpʳ : ρ  ρ′   Γ   ρ′  ρ″  ρ  ρ″   Γ 
⟦⟧-transpʳ ρ≈ρ′ eq {x} T∈Γ
  rewrite sym (eq x) = ρ≈ρ′ T∈Γ

ctx-ext : ρ  ρ′   Γ   a  b   T ⟧T  ρ  a  ρ′  b   T  Γ 
ctx-ext ρ≈ aTb here       = aTb
ctx-ext ρ≈ aTb (there ∈Γ) = ρ≈ ∈Γ

⟦⟧-wk : Γ ⊢w ϕ  Δ  ρ  ρ′   Γ    ϕ ⟧w ρ   ϕ ⟧w ρ′   Δ 
⟦⟧-wk ⊢ϕ ρ≈ρ′ T∈Δ = ρ≈ρ′ (⊢ϕ T∈Δ)

record ⟦_⟧_≈⟦_⟧_∈s[_]_ σ ρ τ ρ′ (ϕ : Wk) Γ : Set where
  field
    {⟦σ⟧}  : Env
    {⟦τ⟧}  : Env
    {⟦σ⟧′} : Env
    {⟦τ⟧′} : Env
    ↘⟦σ⟧   :  σ [ ϕ ] ⟧s ρ  ⟦σ⟧
    ↘⟦σ⟧′  :  σ ⟧s  ϕ ⟧w ρ  ⟦σ⟧′
    ↘⟦τ⟧   :  τ [ ϕ ] ⟧s ρ′  ⟦τ⟧
    ↘⟦τ⟧′  :  τ ⟧s  ϕ ⟧w ρ′  ⟦τ⟧′
    σ≈σ′   : ⟦σ⟧  ⟦σ⟧′   Γ 
    σ≈τ    : ⟦σ⟧  ⟦τ⟧   Γ 
    τ≈τ′   : ⟦τ⟧  ⟦τ⟧′   Γ 

  σ≈τ′ : ⟦σ⟧  ⟦τ⟧′   Γ 
  σ≈τ′ = ⟦⟧-transs σ≈τ τ≈τ′

  τ≈σ′ : ⟦τ⟧  ⟦σ⟧′   Γ 
  τ≈σ′ = ⟦⟧-transs (⟦⟧-syms σ≈τ) σ≈σ′

  σ′≈τ′ : ⟦σ⟧′  ⟦τ⟧′   Γ 
  σ′≈τ′ = ⟦⟧-transs (⟦⟧-syms σ≈σ′) σ≈τ′

module Intps {σ ρ τ ρ′ ϕ Γ} (r :  σ  ρ ≈⟦ τ  ρ′ ∈s[ ϕ ] Γ) = ⟦_⟧_≈⟦_⟧_∈s[_]_ r

infix 4 _⊨_≈_∶_ _⊨_∶_  _⊨s_≈_∶_ _⊨s_∶_

_⊨s_≈_∶_ : Ctx  Subst  Subst  Ctx  Set
Γ ⊨s σ  τ  Δ =  {Γ′ ϕ ρ ρ′}  Γ′ ⊢w ϕ  Γ  ρ  ρ′   Γ′    σ  ρ ≈⟦ τ  ρ′ ∈s[ ϕ ] Δ

_⊨s_∶_ : Ctx  Subst  Ctx  Set
Γ ⊨s σ  Δ = Γ ⊨s σ  σ  Δ


record ⟦_⟧[_]_≈⟦_⟧[_]_∈_ s σ ρ u τ ρ′ T : Set where
  field
    {⟦s⟧}  : D
    {⟦s⟧′} : D
    {⟦t⟧}  : D
    {⟦t⟧′} : D
    {⟦σ⟧}  : Env
    {⟦τ⟧}  : Env
    ↘⟦s⟧   :  s [ σ ]  ρ  ⟦s⟧
    ↘⟦σ⟧   :  σ ⟧s ρ  ⟦σ⟧
    ↘⟦s⟧′  :  s  ⟦σ⟧  ⟦s⟧′
    ↘⟦t⟧   :  u [ τ ]  ρ′  ⟦t⟧
    ↘⟦τ⟧   :  τ ⟧s ρ′  ⟦τ⟧
    ↘⟦t⟧′  :  u  ⟦τ⟧  ⟦t⟧′
    s≈s′   : ⟦s⟧  ⟦s⟧′   T ⟧T
    s≈t    : ⟦s⟧  ⟦t⟧   T ⟧T
    t≈t′   : ⟦t⟧  ⟦t⟧′   T ⟧T

  s≈t′ : ⟦s⟧  ⟦t⟧′   T ⟧T
  s≈t′ = ⟦⟧-trans T s≈t t≈t′

  t≈s′ : ⟦t⟧  ⟦s⟧′   T ⟧T
  t≈s′ = ⟦⟧-trans T (⟦⟧-sym T s≈t) s≈s′

  s′≈t′ : ⟦s⟧′  ⟦t⟧′   T ⟧T
  s′≈t′ = ⟦⟧-trans T (⟦⟧-sym T s≈s′) s≈t′

module Intp {s σ ρ u σ′ ρ′ T} (r :  s ⟧[ σ ] ρ ≈⟦ u ⟧[ σ′ ] ρ′  T) = ⟦_⟧[_]_≈⟦_⟧[_]_∈_ r

record ⟦_⟧_≈⟦_⟧_∈[_]w_ s ρ u ρ′ ϕ T : Set where
  field
    {⟦s⟧}  : D
    {⟦s⟧′} : D
    {⟦t⟧}  : D
    {⟦t⟧′} : D
    ↘⟦s⟧   :  s [ ϕ ]  ρ  ⟦s⟧
    ↘⟦s⟧′  :  s   ϕ ⟧w ρ  ⟦s⟧′
    ↘⟦t⟧   :  u [ ϕ ]  ρ′  ⟦t⟧
    ↘⟦t⟧′  :  u   ϕ ⟧w ρ′  ⟦t⟧′
    s≈s′   : ⟦s⟧  ⟦s⟧′   T ⟧T
    s≈t    : ⟦s⟧  ⟦t⟧   T ⟧T
    t≈t′   : ⟦t⟧  ⟦t⟧′   T ⟧T

module Intpw {s ρ u ρ′ ϕ T} (r :  s  ρ ≈⟦ u  ρ′ ∈[ ϕ ]w T) = ⟦_⟧_≈⟦_⟧_∈[_]w_ r


_⊨_≈_∶_ : Ctx  Exp  Exp  Typ  Set
Γ  t  t′  T =  {Γ′ σ σ′ ρ ρ′}  Γ′ ⊨s σ  σ′  Γ  ρ  ρ′   Γ′    t ⟧[ σ ] ρ ≈⟦ t′ ⟧[ σ′ ] ρ′  T

_⊨_∶_ : Ctx  Exp  Typ  Set
Γ  t  T = Γ  t  t  T