module Implicit.Interm2Algo.FVClose where
open import Implicit.Language.All
data HClosed : Env n m → HitMis m → Set where
hclo-Z : HClosed ∅ ∅
hclo-S, : HClosed Γ H
→ HClosed (Γ , A) H
hclo-S^ : HClosed Γ H
→ HClosed (Γ ,^) (mis H)
hclo-S∙-hit : HClosed Γ H
→ HClosed (Γ ,∙) (hit H)
hclo-S∙-mis : HClosed Γ H
→ HClosed (Γ ,∙) (mis H)
hclo-S=-hit : HClosed Γ H
→ HClosed (Γ ,= A) (hit H)
hclo-S=-mis : HClosed Γ H
→ HClosed (Γ ,= A) (mis H)
hclo-S⋈ : HClosed Γ H
→ HClosed (Γ ⋈) H
data FClose (Γ : Env n m) (A : Type m) : Set where
f-close : ∀ {H}
→ (fv : A 𝕗𝕧 H)
→ (hclo : HClosed Γ H)
→ FClose Γ A
mkMis-hclose : ∀ {m} {Γ : Env n m}
→ HClosed Γ mkMis
mkMis-hclose {m = zero} {Γ = ∅} = hclo-Z
mkMis-hclose {m = zero} {Γ = Γ , A} = hclo-S, mkMis-hclose
mkMis-hclose {m = zero} {Γ = Γ ⋈} = hclo-S⋈ mkMis-hclose
mkMis-hclose {m = suc m} {Γ = Γ , A} = hclo-S, mkMis-hclose
mkMis-hclose {m = suc m} {Γ = Γ ,^} = hclo-S^ mkMis-hclose
mkMis-hclose {m = suc m} {Γ = Γ ,∙} = hclo-S∙-mis mkMis-hclose
mkMis-hclose {m = suc m} {Γ = Γ ,= A} = hclo-S=-mis mkMis-hclose
mkMis-hclose {m = suc m} {Γ = Γ ⋈} = hclo-S⋈ mkMis-hclose
∋∙-hclose : Γ ∋∙ X
→ HClosed Γ (mkHit X)
∋∙-hclose Z = hclo-S∙-hit mkMis-hclose
∋∙-hclose (S, inΓ) = hclo-S, (∋∙-hclose inΓ)
∋∙-hclose (S∙ inΓ) = hclo-S∙-mis (∋∙-hclose inΓ)
∋∙-hclose (S= inΓ) = hclo-S=-mis (∋∙-hclose inΓ)
∋∙-hclose (S^ inΓ) = hclo-S^ (∋∙-hclose inΓ)
∋∙-hclose (S⋈ inΓ) = hclo-S⋈ (∋∙-hclose inΓ)
∋=-hclose : Γ ∋= X
→ HClosed Γ (mkHit X)
∋=-hclose Z = hclo-S=-hit mkMis-hclose
∋=-hclose (S∙ inΓ) = hclo-S∙-mis (∋=-hclose inΓ)
∋=-hclose (S^ inΓ) = hclo-S^ (∋=-hclose inΓ)
∋=-hclose (S= inΓ) = hclo-S=-mis (∋=-hclose inΓ)
∋=-hclose (S, inΓ) = hclo-S, (∋=-hclose inΓ)
orHit-hclose : HClosed Γ H₁
→ HClosed Γ H₂
→ orHit H₁ H₂ H
→ HClosed Γ H
orHit-hclose hclo-Z hclo-Z Z = hclo-Z
orHit-hclose (hclo-S, hclo1) (hclo-S, hclo2) Z = hclo-S, hclo1
orHit-hclose (hclo-S⋈ hclo1) (hclo-S⋈ hclo2) Z = hclo-S⋈ hclo1
orHit-hclose (hclo-S, hclo1) (hclo-S, hclo2) (S-hm orh) = hclo-S, (orHit-hclose hclo1 hclo2 (S-hm orh))
orHit-hclose (hclo-S∙-hit hclo1) (hclo-S∙-mis hclo2) (S-hm orh) = hclo-S∙-hit (orHit-hclose hclo1 hclo2 orh)
orHit-hclose (hclo-S=-hit hclo1) (hclo-S=-mis hclo2) (S-hm orh) = hclo-S=-hit (orHit-hclose hclo1 hclo2 orh)
orHit-hclose (hclo-S⋈ hclo1) (hclo-S⋈ hclo2) (S-hm orh) = hclo-S⋈ (orHit-hclose hclo1 hclo2 (S-hm orh))
orHit-hclose (hclo-S, hclo1) (hclo-S, hclo2) (S-mh orh) = hclo-S, (orHit-hclose hclo1 hclo2 (S-mh orh))
orHit-hclose (hclo-S∙-mis hclo1) (hclo-S∙-hit hclo2) (S-mh orh) = hclo-S∙-hit (orHit-hclose hclo1 hclo2 orh)
orHit-hclose (hclo-S=-mis hclo1) (hclo-S=-hit hclo2) (S-mh orh) = hclo-S=-hit (orHit-hclose hclo1 hclo2 orh)
orHit-hclose (hclo-S⋈ hclo1) (hclo-S⋈ hclo2) (S-mh orh) = hclo-S⋈ (orHit-hclose hclo1 hclo2 (S-mh orh))
orHit-hclose (hclo-S, hclo1) (hclo-S, hclo2) (S-hh orh) = hclo-S, (orHit-hclose hclo1 hclo2 (S-hh orh))
orHit-hclose (hclo-S∙-hit hclo1) (hclo-S∙-hit hclo2) (S-hh orh) = hclo-S∙-hit (orHit-hclose hclo1 hclo2 orh)
orHit-hclose (hclo-S=-hit hclo1) (hclo-S=-hit hclo2) (S-hh orh) = hclo-S=-hit (orHit-hclose hclo1 hclo2 orh)
orHit-hclose (hclo-S⋈ hclo1) (hclo-S⋈ hclo2) (S-hh orh) = hclo-S⋈ (orHit-hclose hclo1 hclo2 (S-hh orh))
orHit-hclose (hclo-S, hclo1) (hclo-S, hclo2) (s-mm orh) = hclo-S, (orHit-hclose hclo1 hclo2 (s-mm orh))
orHit-hclose (hclo-S^ hclo1) (hclo-S^ hclo2) (s-mm orh) = hclo-S^ (orHit-hclose hclo1 hclo2 orh)
orHit-hclose (hclo-S∙-mis hclo1) (hclo-S∙-mis hclo2) (s-mm orh) = hclo-S∙-mis (orHit-hclose hclo1 hclo2 orh)
orHit-hclose (hclo-S=-mis hclo1) (hclo-S=-mis hclo2) (s-mm orh) = hclo-S=-mis (orHit-hclose hclo1 hclo2 orh)
orHit-hclose (hclo-S⋈ hclo1) (hclo-S⋈ hclo2) (s-mm orh) = hclo-S⋈ (orHit-hclose hclo1 hclo2 (s-mm orh))
⊢c-fclose : Γ ⊢c A → FClose Γ A
⊢c-fclose ⊢c-int = f-close fv-Int mkMis-hclose
⊢c-fclose (⊢c-var-∙ inΔ) = f-close fv-var (∋∙-hclose inΔ)
⊢c-fclose (⊢c-var-= inΔ) = f-close fv-var (∋=-hclose inΔ)
⊢c-fclose (⊢c-arr cloA cloA₁) with ⊢c-fclose cloA | ⊢c-fclose cloA₁
... | f-close {H = H₁} fv1 hclo1 | f-close {H = H₂} fv2 hclo2
with ⟨ H' , or-hit ⟩ ← orHit-total H₁ H₂ = f-close (fv-arr fv1 fv2 or-hit) (orHit-hclose hclo1 hclo2 or-hit)
⊢c-fclose (⊢c-∀ cloA) with ⊢c-fclose cloA
... | f-close fv (hclo-S∙-hit hclo) = f-close (fv-∀-h fv) hclo
... | f-close fv (hclo-S∙-mis hclo) = f-close (fv-∀-m fv) hclo