{-# OPTIONS --without-K #-} module Model.Term where open import Cats.Category open import Model.Size as MS using (_<_ ; ⟦_⟧Δ ; ⟦_⟧n ; ⟦_⟧σ) open import Model.Type as MT open import Util.HoTT.Equiv open import Util.Prelude hiding (id ; _∘_ ; _×_) open import Source.Size as SS using (v0 ; v1 ; ⋆) open import Source.Size.Substitution.Theory open import Source.Size.Substitution.Universe as SU using (Sub⊢ᵤ) open import Source.Term import Model.RGraph as RG import Source.Type as ST open Category._≅_ open MS.Size open MS._<_ open MS._≤_ open RG._⇒_ open SS.Size open SS.Ctx open ST.Ctx ⟦_⟧x : ∀ {Δ Γ x T} → Δ , Γ ⊢ₓ x ∶ T → ⟦ Γ ⟧Γ ⇒ ⟦ T ⟧T ⟦_⟧x {Γ = Γ ∙ T} zero = π₂ ⟦ Γ ⟧Γ ⟦ suc {U = U} x ⟧x = ⟦ x ⟧x ∘ π₁ ⟦ U ⟧T ⟦abs⟧ : ∀ Δ (Γ : ST.Ctx Δ) T U → ⟦ Γ ∙ T ⟧Γ ⇒ ⟦ U ⟧T → ⟦ Γ ⟧Γ ⇒ ⟦ T ⟧T ↝ ⟦ U ⟧T ⟦abs⟧ Δ Γ T U t = curry ⟦ Γ ⟧Γ ⟦ T ⟧T ⟦ U ⟧T t ⟦app⟧ : ∀ Δ (Γ : ST.Ctx Δ) T U → ⟦ Γ ⟧Γ ⇒ ⟦ T ⟧T ↝ ⟦ U ⟧T → ⟦ Γ ⟧Γ ⇒ ⟦ T ⟧T → ⟦ Γ ⟧Γ ⇒ ⟦ U ⟧T ⟦app⟧ Δ Γ T U t u = eval ⟦ T ⟧T ⟦ U ⟧T ∘ ⟨ t , u ⟩ ⟦absₛ⟧ : ∀ Δ n (Γ : ST.Ctx Δ) (T : ST.Type (Δ ∙ n)) → ⟦ Γ [ SU.Wk ]ᵤ ⟧Γ ⇒ ⟦ T ⟧T → ⟦ Γ ⟧Γ ⇒ ⟦ ST.Π n , T ⟧T ⟦absₛ⟧ Δ n Γ T t = MT.absₛ (t ∘ ⟦subΓ⟧ SU.Wk Γ .back) ⟦appₛ⟧ : ∀ Δ m n (Γ : ST.Ctx Δ) T → ⟦ Γ ⟧Γ ⇒ ⟦ ST.Π n , T ⟧T → m SS.< n → ⟦ Γ ⟧Γ ⇒ ⟦ T [ SU.Sing m ]ᵤ ⟧T ⟦appₛ⟧ Δ m n Γ T t m<n = ⟦subT⟧ (SU.Sing m<n) T .back ∘ MT.appₛ m<n t ⟦zero⟧ : ∀ Δ (Γ : ST.Ctx Δ) n → ⟦ Γ ⟧Γ ⇒ ⟦ ST.Nat n ⟧T ⟦zero⟧ Δ Γ n = record { fobj = λ {δ} γ → zero≤ (⟦ n ⟧n .fobj δ) ; feq = λ δ≈δ′ x≈y → refl } ⟦suc⟧ : ∀ Δ (Γ : ST.Ctx Δ) {m n} → m SS.< n → ⟦ Γ ⟧Γ ⇒ ⟦ ST.Nat m ⟧T → ⟦ Γ ⟧Γ ⇒ ⟦ ST.Nat n ⟧T ⟦suc⟧ Δ Γ m<n i = record { fobj = λ γ → suc≤ _ _ (MS.⟦<⟧ m<n) (i .fobj γ) ; feq = λ δ≈δ′ x≈y → cong suc (i .feq _ x≈y) } ⟦caseNat⟧ : ∀ Δ (Γ : ST.Ctx Δ) n T → ⟦ Γ ⟧Γ ⇒ ⟦ ST.Nat n ⟧T → ⟦ Γ ⟧Γ ⇒ ⟦ T ⟧T → ⟦ Γ ⟧Γ ⇒ ⟦ ST.Π n , ST.Nat v0 ST.⇒ T [ SU.Wk ]ᵤ ⟧T → ⟦ Γ ⟧Γ ⇒ ⟦ T ⟧T ⟦caseNat⟧ Δ Γ n T i z s = record { fobj = λ γ → caseℕ≤ (i .fobj γ) (z .fobj γ) λ m m<n i → ⟦subT⟧ SU.Wk T .forth .fobj (s .fobj γ .arr m m<n .fobj i) ; feq = λ {δ δ′} δ≈δ′ {γ γ′} γ≈γ′ → caseℕ≤-pres (⟦ T ⟧T .eq δ≈δ′) (i .fobj γ) (i .fobj γ′) (z .fobj γ) (z .fobj γ′) _ _ (i .feq _ γ≈γ′) (z .feq _ γ≈γ′) λ m m<n m′ m′<n′ j j′ j≡j′ → ⟦subT⟧ SU.Wk T .forth .feq _ (s .feq _ γ≈γ′ m m<n m′ m′<n′ j≡j′) } ⟦cons⟧ : ∀ Δ (Γ : ST.Ctx Δ) n → ⟦ Γ ⟧Γ ⇒ ⟦ ST.Nat ∞ ⟧T → ⟦ Γ ⟧Γ ⇒ ⟦ ST.Π n , ST.Stream v0 ⟧T → ⟦ Γ ⟧Γ ⇒ ⟦ ST.Stream n ⟧T ⟦cons⟧ Δ Γ n i is = record { fobj = λ γ → MT.cons (i .fobj γ .proj₁) (is .fobj γ .arr) ; feq = λ δ≈δ′ γ≈γ′ k k≤nδ k≤nδ′ → cons-≡⁺ (i .feq _ γ≈γ′) (λ m m<n m<n′ k k≤m → is .feq _ γ≈γ′ m m<n m m<n′ k k≤m k≤m) k k≤nδ k≤nδ′ } ⟦head⟧ : ∀ Δ (Γ : ST.Ctx Δ) n → ⟦ Γ ⟧Γ ⇒ ⟦ ST.Stream n ⟧T → ⟦ Γ ⟧Γ ⇒ ⟦ ST.Nat ∞ ⟧T ⟦head⟧ Δ Γ n is = record { fobj = λ γ → MT.head (is .fobj γ) , MS.<→≤ MS.zero<∞ ; feq = λ δ≈δ′ γ≈γ′ → head-≡⁺ (is .feq ⊤.tt γ≈γ′) } ⟦tail⟧ : ∀ Δ (Γ : ST.Ctx Δ) {m n} → m SS.< n → ⟦ Γ ⟧Γ ⇒ ⟦ ST.Stream n ⟧T → ⟦ Γ ⟧Γ ⇒ ⟦ ST.Stream m ⟧T ⟦tail⟧ Δ Γ m<n is = record { fobj = λ γ → MT.tail (is .fobj γ) _ (MS.⟦<⟧ m<n) ; feq = λ δ≈δ′ γ≈γ′ i i≤mδ i≤mδ′ → tail-≡⁺ (is .feq _ γ≈γ′) _ _ (MS.⟦<⟧ m<n) (MS.⟦<⟧ m<n) i i≤mδ i≤mδ′ } ⟦fix⟧ : ∀ Δ (Γ : ST.Ctx Δ) n T → n SS.< ⋆ → ⟦ Γ ⟧Γ ⇒ ⟦ ST.Π ⋆ , (ST.Π v0 , T [ SU.Skip ]ᵤ) ST.⇒ T ⟧T → ⟦ Γ ⟧Γ ⇒ ⟦ T [ SU.Sing n ]ᵤ ⟧T ⟦fix⟧ Δ Γ n T n<⋆ t = ⟦subT⟧ (SU.Sing n<⋆) T .back ∘ term⇒ module ⟦fix⟧ where go : Σ[ f ∈ (∀ n n<⋆ δ → ⟦ Γ ⟧Γ .Obj δ → ⟦ T ⟧T .Obj (δ , n , n<⋆)) ] Σ[ f-param ∈ (∀ n n′ n<⋆ n′<⋆ δ δ′ (γ : ⟦ Γ ⟧Γ .Obj δ) (γ′ : ⟦ Γ ⟧Γ .Obj δ′) → ⟦ Γ ⟧Γ .eq _ γ γ′ → ⟦ T ⟧T .eq _ (f n n<⋆ δ γ) (f n′ n′<⋆ δ′ γ′)) ] (∀ {n} → f n ≡ _) go = MS.<-indΣ′ (λ n → ∀ n<⋆ δ (γ : ⟦ Γ ⟧Γ .Obj δ) → ⟦ T ⟧T .Obj (δ , n , n<⋆)) (λ n m f g → ∀ n<⋆ m<⋆ δ δ′ γ γ′ (γ≈γ′ : ⟦ Γ ⟧Γ .eq _ γ γ′) → ⟦ T ⟧T .eq _ (f n<⋆ δ γ) (g m<⋆ δ′ γ′)) (λ n rec rec-resp n<⋆ δ γ → t .fobj γ .arr n n<⋆ .fobj (⟦∀⟧′-resp-≈⟦Type⟧ (⟦subT⟧ SU.Skip T) .back record { arr = λ m m<n → rec m m<n (MS.<-trans m<n n<⋆) δ γ ; param = λ m m<n m′ m′<n → rec-resp m m<n m′ m′<n _ _ δ δ γ γ (⟦ Γ ⟧Γ .eq-refl γ) })) λ n g g-resp m h h-resp g≈h n<⋆ m<⋆ δ δ′ γ γ′ γ≈γ′ → t .feq _ γ≈γ′ n n<⋆ m m<⋆ λ k k<n k′ k′<m → ⟦subT⟧ SU.Skip T .back .feq _ (g≈h k k<n k′ k′<m _ _ δ δ′ γ γ′ γ≈γ′) term : ∀ n n<⋆ δ → ⟦ Γ ⟧Γ .Obj δ → ⟦ T ⟧T .Obj (δ , n , n<⋆) term = go .proj₁ term-param : ∀ n n′ n<⋆ n′<⋆ δ δ′ (γ : ⟦ Γ ⟧Γ .Obj δ) (γ′ : ⟦ Γ ⟧Γ .Obj δ′) → ⟦ Γ ⟧Γ .eq _ γ γ′ → ⟦ T ⟧T .eq _ (term n n<⋆ δ γ) (term n′ n′<⋆ δ′ γ′) term-param = go .proj₂ .proj₁ term⇒ : ⟦ Γ ⟧Γ ⇒ subT ⟦ SU.Sing n<⋆ ⟧σ ⟦ T ⟧T term⇒ = record { fobj = term _ _ _ ; feq = λ δ≈δ′ → term-param _ _ _ _ _ _ _ _ } term-unfold₀ : ∀ {n} → term n ≡ λ n<⋆ δ γ → t .fobj γ .arr n n<⋆ .fobj (⟦∀⟧′-resp-≈⟦Type⟧ (⟦subT⟧ SU.Skip T) .back record { arr = λ m m<n → term m (MS.<-trans m<n n<⋆) δ γ ; param = λ m m<n m′ m′<n → term-param _ _ _ _ _ _ _ _ (⟦ Γ ⟧Γ .eq-refl γ) }) term-unfold₀ = go .proj₂ .proj₂ term-unfold : ∀ {n n<⋆ δ γ} → term n n<⋆ δ γ ≡ t .fobj γ .arr n n<⋆ .fobj (⟦∀⟧′-resp-≈⟦Type⟧ (⟦subT⟧ SU.Skip T) .back record { arr = λ m m<n → term m (MS.<-trans m<n n<⋆) δ γ ; param = λ m m<n m′ m′<n → term-param _ _ _ _ _ _ _ _ (⟦ Γ ⟧Γ .eq-refl γ) }) term-unfold {n} {n<⋆} {δ} {γ} = cong (λ f → f n<⋆ δ γ) term-unfold₀ ⟦_⟧t : ∀ {Δ Γ t T} → Δ , Γ ⊢ t ∶ T → ⟦ Γ ⟧Γ ⇒ ⟦ T ⟧T ⟦ var ⊢x ⟧t = ⟦ ⊢x ⟧x ⟦ abs {Δ = Δ} {Γ} {T} {t} {U} ⊢t ⟧t = ⟦abs⟧ Δ Γ T U ⟦ ⊢t ⟧t ⟦ app {Δ} {Γ} {T = T} {U = U} ⊢t ⊢u ⟧t = ⟦app⟧ Δ Γ T U ⟦ ⊢t ⟧t ⟦ ⊢u ⟧t ⟦ absₛ {Δ} {n} {T = T} ⊢t refl ⟧t = ⟦absₛ⟧ Δ n _ T ⟦ ⊢t ⟧t ⟦ appₛ {Δ} {m} {n} {Γ} {T = T} m<n ⊢t refl ⟧t = ⟦appₛ⟧ Δ m n Γ T ⟦ ⊢t ⟧t m<n ⟦ zero {Δ} {n} {Γ} n<⋆ ⟧t = ⟦zero⟧ Δ Γ n ⟦ suc {Δ} {Γ = Γ} n<⋆ m<n ⊢i ⟧t = ⟦suc⟧ Δ Γ m<n ⟦ ⊢i ⟧t ⟦ cons {Δ} {n} {Γ} n<⋆ ⊢i ⊢is ⟧t = ⟦cons⟧ Δ Γ n ⟦ ⊢i ⟧t ⟦ ⊢is ⟧t ⟦ head {Δ} {n} {Γ} n<⋆ ⊢is ⟧t = ⟦head⟧ Δ Γ n ⟦ ⊢is ⟧t ⟦ tail {Δ} {n} {m} {Γ} n<⋆ m<n ⊢is ⟧t = ⟦tail⟧ Δ Γ m<n ⟦ ⊢is ⟧t ⟦ caseNat {Δ} {n} {Γ} {T = T} n<⋆ ⊢i ⊢z ⊢s refl ⟧t = ⟦caseNat⟧ Δ Γ n T ⟦ ⊢i ⟧t ⟦ ⊢z ⟧t ⟦ ⊢s ⟧t ⟦ fix {Δ} {n} {Γ} {T = T} n<⋆ ⊢t refl refl ⟧t = ⟦fix⟧ Δ Γ n T n<⋆ ⟦ ⊢t ⟧t ⟦_⟧ν : ∀ {Δ} {Γ Ψ : ST.Ctx Δ} {ν} → ν ∶ Γ ⇛ Ψ → ⟦ Γ ⟧Γ ⇒ ⟦ Ψ ⟧Γ ⟦ [] ⟧ν = ! _ ⟦ Snoc ⊢ν ⊢t ⟧ν = ⟨ ⟦ ⊢ν ⟧ν , ⟦ ⊢t ⟧t ⟩