module Implicit.Algo.Properties.WeakenSVar where
open import Implicit.Language.All
open import Implicit.Algo.Base
open import Implicit.Algo.Properties.Extension
open import Implicit.Algo.Properties.Shift
open import Implicit.Algo.Properties.Id
▶⨟=-Ω-exist : Γ ⨟ Δ ▶ k ,= T ⇘ Γ' ⨟ Δ'
→ Γ ⊆ Ω
→ Ω ⊆ Δ
→ ∃[ Ω' ](Γ ⨟ Ω ▶ k ,= T ⇘ Γ' ⨟ Ω' ×
Ω ⨟ Δ ▶ k ,= T ⇘ Ω' ⨟ Δ')
▶⨟=-Ω-exist {T = T} {Ω = Ω} (▶Z regA) ext1 ext2 = ⟨ (Ω ,= T) , ⟨ (▶Z regA) , (▶Z (⊆-⊢r regA ext1)) ⟩ ⟩
▶⨟=-Ω-exist (▶S^ new x) (evar ext1) (evar ext2) = ⟨ ▶⨟=-Ω-exist new ext1 ext2 .proj₁ ,^ ,
⟨ ▶S^ (▶⨟=-Ω-exist new ext1 ext2 .proj₂ .proj₁) x ,
▶S^ (▶⨟=-Ω-exist new ext1 ext2 .proj₂ .proj₂) x ⟩ ⟩
▶⨟=-Ω-exist (▶S^= new x x₁) (evar ext1) (evar-sol ext2 regA) = ⟨ ▶⨟=-Ω-exist new ext1 ext2 .proj₁ ,^ ,
⟨ ▶S^ (▶⨟=-Ω-exist new ext1 ext2 .proj₂ .proj₁) x ,
▶S^= (▶⨟=-Ω-exist new ext1 ext2 .proj₂ .proj₂) x x₁ ⟩ ⟩
▶⨟=-Ω-exist (▶S^= {B' = B'} new x x₁) (evar-sol ext1 regA) (svar ext2 regA₁) = ⟨ ▶⨟=-Ω-exist new ext1 ext2 .proj₁ ,= B' ,
⟨ ▶S^= (▶⨟=-Ω-exist new ext1 ext2 .proj₂ .proj₁) x x₁ ,
▶S= (▶⨟=-Ω-exist new ext1 ext2 .proj₂ .proj₂) x x₁ ⟩ ⟩
▶⨟=-Ω-exist (▶S∙ new x) (uvar ext1) (uvar ext2) = ⟨ ▶⨟=-Ω-exist new ext1 ext2 .proj₁ ,∙ ,
⟨ ▶S∙ (▶⨟=-Ω-exist new ext1 ext2 .proj₂ .proj₁) x ,
▶S∙ (▶⨟=-Ω-exist new ext1 ext2 .proj₂ .proj₂) x ⟩ ⟩
▶⨟=-Ω-exist (▶S= {B' = B'} new x x₁) (svar ext1 regA) (svar ext2 regA₁) = ⟨ ▶⨟=-Ω-exist new ext1 ext2 .proj₁ ,= B' ,
⟨ ▶S= (▶⨟=-Ω-exist new ext1 ext2 .proj₂ .proj₁) x x₁ ,
▶S= (▶⨟=-Ω-exist new ext1 ext2 .proj₂ .proj₂) x x₁ ⟩ ⟩
▶⨟=-Ω-exist (▶S⋈ {Γ' = Γ'} new) (mark regΓ) (mark regΓ₁) with refl ← ▶⨟=-unique new = ⟨ Γ' ⋈ , ⟨ ▶S⋈ new , ▶S⋈ new ⟩ ⟩
ss-weaken= : Γ ⊢ A ⌞ ≤ ⌝ B ⊣ Δ
→ Γ ⨟ Δ ▶ k ,= T ⇘ Γ' ⨟ Δ'
→ A ↑ty k ⇘ A'
→ B ↑ty k ⇘ B'
→ Γ' ⊢ A' ⌞ ≤ ⌝ B' ⊣ Δ'
ss-weaken= (s-int regΓ) new ↑ty-int ↑ty-int with refl ← ▶⨟=-unique new = s-int (sregular-weaken= regΓ (▶⨟=-▶=-l new))
ss-weaken= (s-var-∙ regΓ x) new ↑ty-var ↑ty-var with refl ← ▶⨟=-unique new = s-var-∙ (sregular-weaken= regΓ (▶⨟=-▶=-l new)) (∋∙-weaken= x (▶⨟=-▶=-l new))
ss-weaken= (s-ex-l^ inst) new ↑ty-var upB = s-ex-l^ (inst-weaken= inst new upB)
ss-weaken= (s-ex-r^ inst) new upA ↑ty-var = s-ex-r^ (inst-weaken= inst new upA)
ss-weaken= (s-ex-l= regΓ x-in) new ↑ty-var upB with refl ← ▶⨟=-unique new = s-ex-l= (sregular-weaken= regΓ (▶⨟=-▶=-l new)) (∋:=-weaken= x-in (▶⨟=-▶=-l new) upB)
ss-weaken= (s-ex-r= regΓ x-in) new upA ↑ty-var with refl ← ▶⨟=-unique new = s-ex-r= (sregular-weaken= regΓ (▶⨟=-▶=-l new)) (∋:=-weaken= x-in (▶⨟=-▶=-l new) upA)
ss-weaken= (s-arr ss ss₁) new (↑ty-arr upA upA₁) (↑ty-arr upB upB₁)
with ⟨ Ω' , ⟨ new1 , new2 ⟩ ⟩ ← ▶⨟=-Ω-exist new (ss-⊆ ss) (ss-⊆ ss₁)
= s-arr (ss-weaken= ss new1 upB upA) (ss-weaken= ss₁ new2 upA₁ upB₁)
ss-weaken= {T = T} (s-∀ ss) new (↑ty-∀ upA) (↑ty-∀ upB)
with ⟨ T' , upT ⟩ ← ↑ty0-total T = s-∀ (ss-weaken= ss (▶S∙ new upT) upA upB)
t-weaken= : Γ ⊢ Σ ⇒ e ⇒ A
→ Γ ▶ k ,= T ⇘ Γ'
→ Σ ↑tyᶜ k ⇘ Σ'
→ e ↑tyᵉ k ⇘ e'
→ A ↑ty k ⇘ A'
→ Γ' ⊢ Σ' ⇒ e' ⇒ A'
infs-weaken= : Γ ⊨ Σ ⟹ A
→ Γ ▶ k ,= T ⇘ Γ'
→ Σ ↑tyᶜ k ⇘ Σ'
→ A ↑ty k ⇘ A'
→ Γ' ⊨ Σ' ⟹ A'
infs-weaken= (infs-z regΓ regA) new (↑tyᶜ-τ up-t) upA
with refl ← ↑ty-unique up-t upA = infs-z (tregular-weaken= regΓ new) (⊢r-weaken= regA new upA)
infs-weaken= (infs-s ⊢e infs) new (↑tyᶜ-e up-e upΣ) (↑ty-arr upA upA₁) = infs-s (t-weaken= ⊢e new ↑tyᶜ-□ up-e upA) (infs-weaken= infs new upΣ upA₁)
s-weaken= : Γ ⊢ A ≤⁺ Σ ⊣ Δ ↪ B
→ Γ ⨟ Δ ▶ k ,= T ⇘ Γ' ⨟ Δ'
→ A ↑ty k ⇘ A'
→ Σ ↑tyᶜ k ⇘ Σ'
→ B ↑ty k ⇘ B'
→ Γ' ⊢ A' ≤⁺ Σ' ⊣ Δ' ↪ B'
t-weaken= (⊢lit regΓ) new ↑tyᶜ-□ ↑tyᵉ-lit ↑ty-int = ⊢lit (tregular-weaken= regΓ new)
t-weaken= (⊢var regΓ x∈Γ) new ↑tyᶜ-□ ↑tyᵉ-var upA = ⊢var (tregular-weaken= regΓ new) (∋⦂-weaken= x∈Γ new upA)
t-weaken= {k = k} (⊢ann {B = B} ⊢e) new ↑tyᶜ-□ (↑tyᵉ-⦂ upe up) upA
with refl ← ↑ty-unique up upA
with ⟨ B' , upB ⟩ ← ↑ty-total B k = ⊢ann (t-weaken= ⊢e new (↑tyᶜ-τ up) upe upB)
t-weaken= {k = k} (⊢app {A = A} ⊢e) new upΣ (↑tyᵉ-app upe upe₁) upA
with ⟨ A' , upA' ⟩ ← ↑ty-total A k = ⊢app (t-weaken= ⊢e new (↑tyᶜ-e upe₁ upΣ) upe (↑ty-arr upA' upA))
t-weaken= (⊢lam₁ ⊢e) new (↑tyᶜ-τ (↑ty-arr up-t up-t₁)) (↑tyᵉ-ƛ upe) (↑ty-arr upA upA₁)
with refl ← ↑ty-unique up-t upA
with refl ← ⊢id0 ⊢e
with refl ← ↑ty-unique up-t₁ upA₁
= ⊢lam₁ (t-weaken= ⊢e (▶S, new up-t) (↑tyᶜ-τ up-t₁) upe up-t₁)
t-weaken= (⊢lam₂ ⊢e up-c ⊢e₁) new (↑tyᶜ-e {Σ' = Σ'} up-e upΣ) (↑tyᵉ-ƛ upe) (↑ty-arr upA upA₁)
with ⟨ Σ″ , upΣ' ⟩ ← ↑tmᶜ0-total Σ'
= ⊢lam₂ (t-weaken= ⊢e new ↑tyᶜ-□ up-e upA) upΣ'
(t-weaken= ⊢e₁ (▶S, new upA) (↑tmᶜ-↑tyᶜ-comm' up-c upΣ upΣ') upe upA₁)
t-weaken= {k = k} (⊢sub {A = A} ⊢e ne gc s) new upΣ upe upA
with ⟨ A' , upA' ⟩ ← ↑ty-total A k = ⊢sub (t-weaken= ⊢e new ↑tyᶜ-□ upe upA') (nonempty-↑tyᶜ' ne upΣ) (gc-↑tyᵉ gc upe) (s-weaken= s (▶S⋈ (▶=-▶⨟= new)) upA' upΣ upA)
t-weaken= {T = T} (⊢tabs ⊢e) new ↑tyᶜ-□ (↑tyᵉ-Λ upe) (↑ty-∀ upA)
with ⟨ T' , upT ⟩ ← ↑ty0-total T = ⊢tabs (t-weaken= ⊢e (▶S∙ new upT) ↑tyᶜ-□ upe upA)
t-weaken= {T = T} (⊢tabs-τ ⊢e) new (↑tyᶜ-τ (↑ty-∀ upA')) (↑tyᵉ-Λ upe) (↑ty-∀ upA)
with ⟨ T' , upT ⟩ ← ↑ty0-total T
= ⊢tabs-τ (t-weaken= ⊢e (▶S∙ new upT) (↑tyᶜ-τ upA') upe upA)
t-weaken= {k = k} (⊢tapp {B = B} {B* = B*} ⊢e st regA s) newΓ upΣ (↑tyᵉ-⓪ upe upA₁) upA
with ⟨ B' , upB ⟩ ← ↑ty-total B (#S k)
with ⟨ B*' , upB* ⟩ ← ↑ty-total B* k
= ⊢tapp (t-weaken= ⊢e newΓ ↑tyᶜ-□ upe (↑ty-∀ upB)) (↑ty-st-comm0 st upA₁ upB upB*) (⊢r-weaken= regA newΓ upA₁) (s-weaken= s (▶=-▶⨟= (▶S⋈ newΓ)) upB* upΣ upA)
s-weaken= (s-empty regΓ cloA grd) new upA ↑tyᶜ-□ upB
with refl ← ▶⨟=-unique new = s-empty (sregular-weaken= regΓ (▶⨟=-▶=-l new)) (⊢c-weaken= cloA (▶⨟=-▶=-l new) upA) (≫-weaken= grd (▶⨟=-▶=-l new) upA upB)
s-weaken= (s-type ss) new upA (↑tyᶜ-τ up-t) upB
with refl ← ↑ty-unique up-t upB = s-type (ss-weaken= ss new upA up-t)
s-weaken= (s-term-c cloA ap ⊢e s) new (↑ty-arr upA upA₁) (↑tyᶜ-e up-e upΣ) (↑ty-arr upB upB₁)
with refl ← ⊢id0 ⊢e
= s-term-c (⊢c-weaken= cloA (▶⨟=-▶=-l new) upA) (≫-weaken= ap (▶⨟=-▶=-l new) upA upB) (t-weaken= ⊢e (▶=-𝕣 (▶⨟=-▶=-l new)) (↑tyᶜ-τ upB) up-e upB) (s-weaken= s new upA₁ upΣ upB₁)
s-weaken= (s-term-o opnA ⊢e ss s) new (↑ty-arr upA upA₁) (↑tyᶜ-e up-e upΣ) (↑ty-arr upB upB₁)
with ⟨ Ω' , ⟨ new1 , new2 ⟩ ⟩ ← ▶⨟=-Ω-exist new (ss-⊆ ss) (s-⊆ s)
= s-term-o (⊢o-weaken= opnA (▶⨟=-▶=-l new) upA)
(t-weaken= ⊢e (▶=-𝕣 (▶⨟=-▶=-l new)) ↑tyᶜ-□ up-e upB)
(ss-weaken= ss new1 upB upA)
(s-weaken= s new2 upA₁ upΣ upB₁)
s-weaken= {k = k} {T = T} (s-∀l {B = B} s upᶜ upᵉ upC upD) new (↑ty-∀ upA) (↑tyᶜ-e {e' = e'} {Σ' = Σ'} up-e upΣ) (↑ty-arr {A' = C'} {B' = D'} upC' upD')
with ⟨ T' , upT ⟩ ← ↑ty0-total T
with ⟨ B' , upB' ⟩ ← ↑ty-total B k
with ⟨ C″ , upC″ ⟩ ← ↑ty0-total C'
with ⟨ D″ , upD″ ⟩ ← ↑ty0-total D'
with ⟨ e″ , upe″ ⟩ ← ↑tyᵉ0-total e'
with ⟨ Σ″ , upΣ″ ⟩ ← ↑tyᶜ0-total Σ'
= s-∀l (s-weaken= s (▶S^= new upT upB') upA
(↑tyᶜ-comm0' (↑tyᶜ-e up-e upΣ) (↑tyᶜ-e upe″ upΣ″) (↑tyᶜ-e upᵉ upᶜ))
(↑ty-arr (↑ty-comm0' upC' upC″ upC) (↑ty-comm0' upD' upD″ upD))) upΣ″ upe″ upC″ upD″
s-weaken= {k = k} {T = T} (s-∀l-no s upᶜ upᵉ upC upD) new (↑ty-∀ upA) (↑tyᶜ-e {e' = e'} {Σ' = Σ'} up-e upΣ) (↑ty-arr {A' = C'} {B' = D'} upC' upD')
with ⟨ T' , upT ⟩ ← ↑ty0-total T
with ⟨ C″ , upC″ ⟩ ← ↑ty0-total C'
with ⟨ D″ , upD″ ⟩ ← ↑ty0-total D'
with ⟨ e″ , upe″ ⟩ ← ↑tyᵉ0-total e'
with ⟨ Σ″ , upΣ″ ⟩ ← ↑tyᶜ0-total Σ'
= s-∀l-no (s-weaken= s (▶S^ new upT) upA
(↑tyᶜ-comm0' (↑tyᶜ-e up-e upΣ) (↑tyᶜ-e upe″ upΣ″) (↑tyᶜ-e upᵉ upᶜ))
(↑ty-arr (↑ty-comm0' upC' upC″ upC) (↑ty-comm0' upD' upD″ upD))) upΣ″ upe″ upC″ upD″
s-weaken= {k = k} (s-svar-term {A = A} inΓ s) new ↑ty-var (↑tyᶜ-e up-e upΣ) (↑ty-arr upB upB₁)
with ⟨ A' , upA' ⟩ ← ↑ty-total A k
with refl ← ▶⨟=-unique new
= s-svar-term (∋:=-weaken= inΓ (▶⨟=-▶=-l new) upA') (s-weaken= s new upA' (↑tyᶜ-e up-e upΣ) (↑ty-arr upB upB₁))
s-weaken= (s-evar-infers infs inst) new ↑ty-var (↑tyᶜ-e up-e upΣ) upB
= s-evar-infers (infs-weaken= infs (▶=-𝕣 (▶⨟=-▶=-l new)) (↑tyᶜ-e up-e upΣ) upB) (inst-weaken= inst new upB)
s-weaken=0 : Γ ⊢ A ≤⁺ Σ ⊣ Δ ↪ B
→ ↑ty0 A ⇘ A'
→ ↑tyᶜ0 Σ ⇘ Σ'
→ ↑ty0 B ⇘ B'
→ Γ ⊢r T
→ Γ ,= T ⊢ A' ≤⁺ Σ' ⊣ Δ ,= T ↪ B'
s-weaken=0 s upA upΣ upB regT = s-weaken= s (▶Z regT) upA upΣ upB