module Record.Algo.WellFormed where
open import Record.Prelude hiding (_≤?_) renaming (_≤_ to _≤n_)
open import Record.Common
open import Record.Properties
open import Record.Algo
open import Record.Algo.Properties
data _#_ : Type → Type → Set where
#-and-l : ∀ {A B C}
→ A # C
→ B # C
→ (A & B) # C
#-and-r : ∀ {A B C}
→ A # B
→ A # C
→ A # (B & C)
#-base-1 : ∀ {A B}
→ (Int `→ A) # (Float `→ B)
#-base-2 : ∀ {A B}
→ (Float `→ A) # (Int `→ B)
#-rcd : ∀ {x y A B}
→ x ≢ y
→ τ⟦ x ↦ A ⟧ # τ⟦ y ↦ B ⟧
#-inv-l : ∀ {A B C}
→ (A & B) # C
→ A # C
#-inv-l (#-and-l AB#C AB#C₁) = AB#C
#-inv-l (#-and-r AB#C AB#C₁) = #-and-r (#-inv-l AB#C) (#-inv-l AB#C₁)
#-inv-r : ∀ {A B C}
→ (A & B) # C
→ B # C
#-inv-r (#-and-l AB#C AB#C₁) = AB#C₁
#-inv-r (#-and-r AB#C AB#C₁) = #-and-r (#-inv-r AB#C) (#-inv-r AB#C₁)
data WF : Type → Set where
wf-int : WF Int
wf-float : WF Float
wf-top : WF Top
wf-arr : ∀ {A B} → WF A → WF B → WF (A `→ B)
wf-and : ∀ {A B} → WF A → WF B → (A#B : A # B) → WF (A & B)
wf-rcd : ∀ {l A} → WF A → WF (τ⟦ l ↦ A ⟧)
data WFG : Env → Set where
wfg-∅ : WFG ∅
wfg-, : ∀ {Γ A} → WFG Γ → WF A → WFG (Γ , A)
infix 3 _∉_
data _∉_ : Label → Record → Set where
notin-empty : ∀ {l}
→ l ∉ rnil
notin-cons : ∀ {l₁ l₂ rs e}
→ l₁ ≢ l₂
→ l₁ ∉ rs
→ l₁ ∉ r⟦ l₂ ↦ e ⟧ rs
data Value : Term → Set where
V-n : ∀ {c}
→ Value (𝕔 c)
V-ƛ : ∀ {e}
→ Value (ƛ e)
data WFE : Term → Set
data WFR : Record → Set
data WFE where
wfe-c : ∀ {n} → WFE (𝕔 n)
wfe-var : ∀ {x} → WFE (` x)
wfe-lam : ∀ {e} → WFE e → WFE (ƛ e)
wfe-app : ∀ {e₁ e₂} → WFE e₁ → WFE e₂ → Value e₂ → WFE (e₁ · e₂)
wfe-ann : ∀ {e A} → WFE e → WF A → WFE (e ⦂ A)
wfe-rcd : ∀ {rs} → WFR rs → WFE (𝕣 rs)
wfe-prj : ∀ {e l} → WFE e → WFE (e 𝕡 l)
data WFR where
wfr-nil : WFR rnil
wfr-cons : ∀ {e l rs}
→ WFE e
→ WFR rs
→ l ∉ rs
→ WFR (r⟦ l ↦ e ⟧ rs)
data WFΣ : Context → Set where
wfh-□ : WFΣ □
wfh-τ : ∀ {A} → WF A → WFΣ (τ A)
wfh-e : ∀ {e Σ} → WFΣ Σ → WFE e → Value e → WFΣ (⟦ e ⟧⇒ Σ)
wfh-l : ∀ {l Σ} → WFΣ Σ → WFΣ (⌊ l ⌋⇒ Σ)
∉-↑r : ∀ {rs l n}
→ l ∉ rs
→ l ∉ rs ↑r n
∉-↑r notin-empty = notin-empty
∉-↑r (notin-cons x ni) = notin-cons x (∉-↑r ni)
wf-↑ : ∀ {e n}
→ WFE e
→ WFE (e ↑ n)
wfr-↑r : ∀ {rs n}
→ WFR rs
→ WFR (rs ↑r n)
wfr-↑r wfr-nil = wfr-nil
wfr-↑r (wfr-cons x wfr wfl) = wfr-cons (wf-↑ x) (wfr-↑r wfr) (∉-↑r wfl)
v-↑ : ∀ {e n}
→ Value e
→ Value (e ↑ n)
v-↑ V-n = V-n
v-↑ V-ƛ = V-ƛ
wf-↑ wfe-c = wfe-c
wf-↑ wfe-var = wfe-var
wf-↑ (wfe-lam wfe) = wfe-lam (wf-↑ wfe)
wf-↑ (wfe-app wfe wfe₁ ve) = wfe-app (wf-↑ wfe) (wf-↑ wfe₁) (v-↑ ve)
wf-↑ (wfe-ann wfe x) = wfe-ann (wf-↑ wfe) x
wf-↑ (wfe-rcd x) = wfe-rcd (wfr-↑r x)
wf-↑ (wfe-prj wfe) = wfe-prj (wf-↑ wfe)
wf-⇧ : ∀ {Σ n}
→ WFΣ Σ
→ WFΣ (Σ ⇧ n)
wf-⇧ wfh-□ = wfh-□
wf-⇧ (wfh-τ x) = wfh-τ x
wf-⇧ (wfh-e wfh x ve) = wfh-e (wf-⇧ wfh) (wf-↑ x) (v-↑ ve)
wf-⇧ (wfh-l wfh) = wfh-l (wf-⇧ wfh)
x∈Γ-wf : ∀ {Γ x A}
→ WFG Γ
→ Γ ∋ x ⦂ A
→ WF A
x∈Γ-wf (wfg-, wfg x) Z = x
x∈Γ-wf (wfg-, wfg x) (S x∈Γ) = x∈Γ-wf wfg x∈Γ
⊢wf : ∀ {Γ Σ e A}
→ WFG Γ
→ WFΣ Σ
→ WFE e
→ Γ ⊢ Σ ⇒ e ⇒ A
→ WF A
≤wf : ∀ {Γ Σ A B}
→ WFG Γ
→ WFΣ Σ
→ WF A
→ Γ ⊢ A ≤ Σ ⇝ B
→ WF B
⊢r-wf : ∀ {Γ Σ rs A}
→ WFG Γ
→ WFΣ Σ
→ WFR rs
→ Γ ⊢r Σ ⇒ rs ⇒ A
→ WF A
⊢r-# : ∀ {Γ A Bs rs l}
→ rs ≢ rnil
→ Γ ⊢r □ ⇒ rs ⇒ Bs
→ l ∉ rs
→ τ⟦ l ↦ A ⟧ # Bs
⊢r-# ne ⊢nil notin = ⊥-elim (ne refl)
⊢r-# ne (⊢one x) (notin-cons x₁ notin) = #-rcd x₁
⊢r-# ne (⊢cons x ⊢rs x₁) (notin-cons x₂ notin) = #-and-r (#-rcd x₂) (⊢r-# x₁ ⊢rs notin)
⊢r-wf wfg wfh wfr ⊢nil = wf-top
⊢r-wf wfg wfh (wfr-cons x₁ wfr wfl) (⊢one x) = wf-rcd (⊢wf wfg wfh x₁ x)
⊢r-wf wfg wfh (wfr-cons x₂ wfr wfl) (⊢cons x ⊢r x₁) = wf-and (wf-rcd (⊢wf wfg wfh x₂ x)) (⊢r-wf wfg wfh wfr ⊢r) (⊢r-# x₁ ⊢r wfl)
≤wf wfg wfh wfA ≤int = wfA
≤wf wfg wfh wfA ≤float = wfA
≤wf wfg wfh wfA ≤top = wf-top
≤wf wfg wfh wfA ≤□ = wfA
≤wf wfg (wfh-τ (wf-arr x x₁)) (wf-arr wfA wfA₁) (≤arr s s₁) = wf-arr x x₁
≤wf wfg (wfh-τ (wf-rcd x)) (wf-rcd wfA) (≤rcd s) = wf-rcd (≤wf wfg (wfh-τ x) wfA s)
≤wf wfg (wfh-e wfh x₁ ve) (wf-arr wfA wfA₁) (≤hint x s) = wf-arr wfA (≤wf wfg wfh wfA₁ s)
≤wf wfg (wfh-l wfh) (wf-rcd wfA) (≤hint-l s) = wf-rcd (≤wf wfg wfh wfA s)
≤wf wfg wfh (wf-and wfA wfA₁ A#B) (≤and-l s x) = ≤wf wfg wfh wfA s
≤wf wfg wfh (wf-and wfA wfA₁ A#B) (≤and-r s x) = ≤wf wfg wfh wfA₁ s
≤wf wfg (wfh-τ (wf-and x x₁ A#B)) wfA (≤and s s₁) with ≤id-0 s | ≤id-0 s₁
... | refl | refl = wf-and x x₁ A#B
⊢wf wfg wfh wfe (⊢c {c = lit x}) = wf-int
⊢wf wfg wfh wfe (⊢c {c = flt x}) = wf-float
⊢wf wfg wfh wfe (⊢c {c = +s}) = wf-and (wf-arr wf-int (wf-arr wf-int wf-int)) (wf-arr wf-float (wf-arr wf-float wf-float)) #-base-1
⊢wf wfg wfh wfe (⊢c {c = +i x}) = wf-arr wf-int wf-int
⊢wf wfg wfh wfe (⊢c {c = +f x}) = wf-arr wf-float wf-float
⊢wf wfg wfh wfe (⊢var x∈Γ) = x∈Γ-wf wfg x∈Γ
⊢wf wfg wfh (wfe-ann wfe x) (⊢ann ⊢e) = x
⊢wf wfg wfh (wfe-app wfe wfe₁ ve) (⊢app ⊢e) with ⊢wf wfg (wfh-e wfh wfe₁ ve) wfe ⊢e
... | wf-arr r r₁ = r₁
⊢wf wfg (wfh-τ (wf-arr x x₁)) (wfe-lam wfe) (⊢lam₁ ⊢e) = wf-arr x (⊢wf (wfg-, wfg x) (wfh-τ x₁) wfe ⊢e)
⊢wf wfg (wfh-e wfh x ve) (wfe-lam wfe) (⊢lam₂ ⊢e ⊢e₁) =
wf-arr (⊢wf wfg wfh-□ x ⊢e) (⊢wf (wfg-, wfg (⊢wf wfg wfh-□ x ⊢e)) (wf-⇧ wfh) wfe ⊢e₁)
⊢wf wfg wfh wfe (⊢sub p-e ⊢e A≤Σ Σ≢□) = ≤wf wfg wfh (⊢wf wfg wfh-□ wfe ⊢e) A≤Σ
⊢wf wfg wfh (wfe-rcd x₁) (⊢rcd x) = ⊢r-wf wfg wfh x₁ x
⊢wf wfg wfh (wfe-prj wfe) (⊢prj ⊢e) with ⊢wf wfg (wfh-l wfh) wfe ⊢e
... | wf-rcd r = r
#-comm : ∀ {A B}
→ A # B
→ B # A
#-comm (#-and-l A#B A#B₁) = #-and-r (#-comm A#B) (#-comm A#B₁)
#-comm (#-and-r A#B A#B₁) = #-and-l (#-comm A#B) (#-comm A#B₁)
#-comm #-base-1 = #-base-2
#-comm #-base-2 = #-base-1
#-comm (#-rcd x) = #-rcd (λ x₂ → x (sym x₂))
wf-c : ∀ c
→ WF (c-τ c)
wf-c (lit x) = wf-int
wf-c (flt x) = wf-float
wf-c +s = wf-and (wf-arr wf-int (wf-arr wf-int wf-int))
(wf-arr wf-float (wf-arr wf-float wf-float)) #-base-1
wf-c (+i x) = wf-arr wf-int wf-int
wf-c (+f x) = wf-arr wf-float wf-float