module Implicit.Algo2Interm.Find where
open import Implicit.Language.All
open import Implicit.Interm.All
open import Implicit.Algo.All
open import Implicit.Algo2Interm.AlgoCounter.All
open import Implicit.Algo2Interm.Context2Counter
infs-isoinf : Γ ⊨ [ e ]↝ Σ ⟹ A ↡ j
→ □like j
infs-isoinf (infs-s ⊢e (infs-z regΓ regA)) = □like-Z
infs-isoinf (infs-s ⊢e (infs-s ⊢e₁ infs)) = □like-S (infs-isoinf (infs-s ⊢e infs))
ss-find-l : Γ ⊢ A ⌞ ≤⁺ ⌝ B ⊣ Δ
→ Γ ∋^ k
→ Δ ∋= k
→ k ε A
ss-find-l s inΓ inΔ = ^in-=out-ε (ss+-⊆/ s) inΓ inΔ
ss-find-r : Γ ⊢ A ⌞ ≤⁻ ⌝ B ⊣ Δ
→ Γ ∋^ k
→ Δ ∋= k
→ k ε B
ss-find-r s inΓ inΔ = ^in-=out-ε (ss--⊆/ s) inΓ inΔ
s-find : Γ ⊢ A ≤⁺ Σ ⊣ Δ ↪ B ↡ j
→ Γ ∋^ k
→ Δ ∋= k
→ find A k j
s-find (s-empty regΓ cloA x) inΓ inΔ = ⊥-elim (∋^-∋=-false inΓ inΔ)
s-find (s-type ss) inΓ inΔ = f-□ (ss-find-l ss inΓ inΔ)
s-find (s-term-c cloA ap ⊢e s) inΓ inΔ = f-arr-r (⊢c-^∈-¬ε cloA inΓ) (s-find s inΓ inΔ)
s-find {k = k} (s-term-o {A = A} opnA ⊢e ss s) inΓ inΔ with ε-dec {k = k} {A = A}
... | inj₁ inA = f-arr-l inA
... | inj₂ ¬inA = f-arr-r ¬inA (s-find s (⊆/-^in-^out (ss--⊆/ ss) ¬inA inΓ) inΔ)
s-find (s-∀l s upᶜ upᵉ upC upD) inΓ inΔ = f-∀ (s-find s (S^ inΓ) (S= inΔ))
s-find (s-∀l-no s upᶜ upᵉ upC upD) inΓ inΔ = f-∀ (s-find s (S^ inΓ) (S^ inΔ))
s-find (s-svar-term x s) inΓ inΔ = ⊥-elim (∋^-∋=-false inΓ inΔ)
s-find (s-evar-infers infs inst) inΓ inΔ
with ε-var ← ^in-=out-ε (ext-var (inst-⊆/x inst)) inΓ inΔ = f-iso (infs-isoinf infs)
s-find0 : Γ ,^ ⊢ A ≤⁺ [ e' ]↝ Σ' ⊣ Δ ,= B ↪ C `→ D ↡ j
→ ↑tyᵉ0 e ⇘ e'
→ ↑tyᶜ0 Σ ⇘ Σ'
→ find A #0 j
s-find0 s up1 up2 = s-find s Z Z
ss-¬ε+ : Γ ⊢ A ⌞ ≤⁺ ⌝ B ⊣ Δ
→ Γ ∋^ k
→ Δ ∋^ k
→ k ¬ε A
ss-¬ε- : Γ ⊢ A ⌞ ≤⁻ ⌝ B ⊣ Δ
→ Γ ∋^ k
→ Δ ∋^ k
→ k ¬ε B
ss-¬ε+ (s-int regΓ) inΓ inΔ = ¬ε-int
ss-¬ε+ (s-var-∙ regΓ x) inΓ inΔ = ¬ε-var (∋∙-∋^-≢ x inΓ)
ss-¬ε+ (s-ex-l^ inst) inΓ inΔ = ¬ε-var (∋=-∋^-≢ (inst-∋= inst) inΔ)
ss-¬ε+ (s-ex-l= regΓ x-in) inΓ inΔ = ¬ε-var (∋=-∋^-≢ (∋:=to∋= x-in) inΔ)
ss-¬ε+ (s-arr s s₁) inΓ inΔ = let inΩ = ⊆-∋^-middle inΓ inΔ (ss-⊆ s) (ss-⊆ s₁)
in ¬ε-arr (ss-¬ε- s inΓ inΩ) (ss-¬ε+ s₁ inΩ inΔ)
ss-¬ε+ (s-∀ s) inΓ inΔ = ¬ε-∀ (ss-¬ε+ s (S∙ inΓ) (S∙ inΔ))
ss-¬ε- (s-int regΓ) inΓ inΔ = ¬ε-int
ss-¬ε- (s-var-∙ regΓ x) inΓ inΔ = ¬ε-var (∋∙-∋^-≢ x inΓ)
ss-¬ε- (s-ex-r^ inst) inΓ inΔ = ¬ε-var (∋=-∋^-≢ (inst-∋= inst) inΔ)
ss-¬ε- (s-ex-r= regΓ x-in) inΓ inΔ = ¬ε-var (∋=-∋^-≢ (∋:=to∋= x-in) inΔ)
ss-¬ε- (s-arr s s₁) inΓ inΔ = let inΩ = ⊆-∋^-middle inΓ inΔ (ss-⊆ s) (ss-⊆ s₁) in ¬ε-arr (ss-¬ε+ s inΓ inΩ) (ss-¬ε- s₁ inΩ inΔ)
ss-¬ε- (s-∀ s) inΓ inΔ = ¬ε-∀ (ss-¬ε- s (S∙ inΓ) (S∙ inΔ))
s-¬ε : Γ ⊢ A ≤⁺ Σ ⊣ Δ ↪ B
→ Γ ∋^ k
→ Δ ∋^ k
→ k ¬ε A
s-¬ε (s-empty regΓ cloA grd) inΓ inΔ = ⊢c-^∈-¬ε cloA inΔ
s-¬ε (s-type ss) inΓ inΔ = ss-¬ε+ ss inΓ inΔ
s-¬ε (s-term-c cloA ap ⊢e s) inΓ inΔ = ¬ε-arr (⊢c-^∈-¬ε cloA inΓ) (s-¬ε s inΓ inΔ)
s-¬ε (s-term-o opnA ⊢e ss s) inΓ inΔ = let inΩ = ⊆-∋^-middle inΓ inΔ (ss-⊆ ss) (s-⊆ s)
in ¬ε-arr (ss-¬ε- ss inΓ inΩ) (s-¬ε s inΩ inΔ)
s-¬ε (s-∀l s upᶜ upᵉ upC upD) inΓ inΔ = ¬ε-∀ (s-¬ε s (S^ inΓ) (S= inΔ))
s-¬ε (s-∀l-no s upᶜ upᵉ upC upD) inΓ inΔ = ¬ε-∀ (s-¬ε s (S^ inΓ) (S^ inΔ))
s-¬ε (s-svar-term x s) inΓ inΔ = ¬ε-var (∋=-∋^-≢ (∋:=to∋= x) inΓ)
s-¬ε (s-evar-infers infs inst) inΓ inΔ = ¬ε-var (∋=-∋^-≢ (inst-∋= inst) inΔ)