module linear.Typing.Inversion where
open import Data.Nat
open import Data.Vec hiding (map ; [_] ; _++_)
open import Data.Product
open import linear.Type
open import linear.Context hiding (_++_)
open import linear.Language
open import linear.Usage
open import linear.Typing
app-inv :
{n : ℕ} {γ : Context n} {t : Infer n} {u : Check n} {Γ Δ : Usages γ} {τ : Type} →
Γ ⊢ `app t u ∈ τ ⊠ Δ → Σ[ θ ∈ Usages γ ] Σ[ σ ∈ Type ] Γ ⊢ t ∈ σ ─o τ ⊠ θ × θ ⊢ σ ∋ u ⊠ Δ
app-inv (`app t u) = , , t , u
fst-inv :
{n : ℕ} {γ : Context n} {t : Infer n} {Γ Δ : Usages γ} {σ : Type} →
Γ ⊢ `fst t ∈ σ ⊠ Δ → Σ[ τ ∈ Type ] Γ ⊢ t ∈ σ & τ ⊠ Δ
fst-inv (`fst t) = , t
snd-inv :
{n : ℕ} {γ : Context n} {t : Infer n} {Γ Δ : Usages γ} {τ : Type} →
Γ ⊢ `snd t ∈ τ ⊠ Δ → Σ[ σ ∈ Type ] Γ ⊢ t ∈ σ & τ ⊠ Δ
snd-inv (`snd t) = , t
exfalso-inv :
{n : ℕ} {γ : Context n} {t : Infer n} {Γ Δ : Usages γ} {σ τ : Type} →
Γ ⊢ `exfalso σ t ∈ τ ⊠ Δ → Γ ⊢ t ∈ 𝟘 ⊠ Δ
exfalso-inv (`exfalso σ t) = t
case-inv :
{n : ℕ} {γ : Context n} {t : Infer n} {l r : Check (suc n)} {Γ Δ : Usages γ} {ν₁ ν₂ : Type} →
Γ ⊢ `case t return ν₁ of l %% r ∈ ν₂ ⊠ Δ →
Σ[ θ ∈ Usages γ ] Σ[ σ ∈ Type ] Σ[ τ ∈ Type ]
Γ ⊢ t ∈ σ ⊕ τ ⊠ θ × [ σ ] ∷ θ ⊢ ν₁ ∋ l ⊠ ] σ [ ∷ Δ × [ τ ] ∷ θ ⊢ ν₁ ∋ r ⊠ ] τ [ ∷ Δ
case-inv (`case t return ν of l %% r) = , , , t , l , r
neu-inv :
{n : ℕ} {γ : Context n} {t : Infer n} {Γ Δ : Usages γ} {σ : Type} →
Γ ⊢ σ ∋ `neu t ⊠ Δ → Γ ⊢ t ∈ σ ⊠ Δ
neu-inv (`neu t) = t
lam-inv :
{n : ℕ} {γ : Context n} {t : Check (suc n)} {Γ Δ : Usages γ} {σ τ : Type} →
Γ ⊢ σ ─o τ ∋ `lam t ⊠ Δ → [ σ ] ∷ Γ ⊢ τ ∋ t ⊠ ] σ [ ∷ Δ
lam-inv (`lam t) = t
let-inv :
{n o : ℕ} {γ : Context n} {p : Pattern o} {t : Infer n} {u : Check (o + n)}
{Γ Δ : Usages γ} {τ : Type} → Γ ⊢ τ ∋ `let p ∷= t `in u ⊠ Δ →
Σ[ θ ∈ Usages γ ] Σ[ σ ∈ Type ] Σ[ δ ∈ Context o ]
Γ ⊢ t ∈ σ ⊠ θ × σ ∋ p ↝ δ × [[ δ ]] ++ θ ⊢ τ ∋ u ⊠ ]] δ [[ ++ Δ
let-inv (`let p ∷= t `in u) = , , , t , p , u
prd⊗-inv :
{n : ℕ} {γ : Context n} {t u : Check n} {Γ Δ : Usages γ} {σ τ : Type} →
Γ ⊢ σ ⊗ τ ∋ `prd t u ⊠ Δ → Σ[ θ ∈ Usages γ ] Γ ⊢ σ ∋ t ⊠ θ × θ ⊢ τ ∋ u ⊠ Δ
prd⊗-inv (`prd⊗ t u) = , t , u
prd&-inv :
{n : ℕ} {γ : Context n} {t u : Check n} {Γ Δ : Usages γ} {σ τ : Type} →
Γ ⊢ σ & τ ∋ `prd t u ⊠ Δ → Γ ⊢ σ ∋ t ⊠ Δ × Γ ⊢ τ ∋ u ⊠ Δ
prd&-inv (`prd& t u) = t , u
app-inv-function :
{n : ℕ} {γ : Context n} {t : Infer n} {u : Check n} {Γ Δ : Usages γ} {τ : Type} →
(p : Γ ⊢ `app t u ∈ τ ⊠ Δ) → let (θ , σ , _) = app-inv p in Γ ⊢ t ∈ σ ─o τ ⊠ θ
app-inv-function p = let (_ , _ , T , _) = app-inv p in T
app-inv-argument :
{n : ℕ} {γ : Context n} {t : Infer n} {u : Check n} {Γ Δ : Usages γ} {τ : Type} →
(p : Γ ⊢ `app t u ∈ τ ⊠ Δ) → let (θ , σ , _) = app-inv p in θ ⊢ σ ∋ u ⊠ Δ
app-inv-argument p = let (_ , _ , _ , U) = app-inv p in U
case-inv-scrutinee :
{n : ℕ} {γ : Context n} {t : Infer n} {l r : Check (suc n)} {Γ Δ : Usages γ} {ν₁ ν₂ : Type} →
(p : Γ ⊢ `case t return ν₁ of l %% r ∈ ν₂ ⊠ Δ) →
let (θ , σ , τ , _) = case-inv p in Γ ⊢ t ∈ σ ⊕ τ ⊠ θ
case-inv-scrutinee p = let (_ , _ , _ , T , _) = case-inv p in T
case-inv-left :
{n : ℕ} {γ : Context n} {t : Infer n} {l r : Check (suc n)} {Γ Δ : Usages γ} {ν₁ ν₂ : Type} →
(p : Γ ⊢ `case t return ν₁ of l %% r ∈ ν₂ ⊠ Δ) →
let (θ , σ , τ , _) = case-inv p in [ σ ] ∷ θ ⊢ ν₁ ∋ l ⊠ ] σ [ ∷ Δ
case-inv-left p = let (_ , _ , _ , _ , L , _) = case-inv p in L
case-inv-right :
{n : ℕ} {γ : Context n} {t : Infer n} {l r : Check (suc n)} {Γ Δ : Usages γ} {ν₁ ν₂ : Type} →
(p : Γ ⊢ `case t return ν₁ of l %% r ∈ ν₂ ⊠ Δ) →
let (θ , σ , τ , _) = case-inv p in [ τ ] ∷ θ ⊢ ν₁ ∋ r ⊠ ] τ [ ∷ Δ
case-inv-right p = let (_ , _ , _ , _ , _ , R) = case-inv p in R
let-inv-bound :
{n o : ℕ} {γ : Context n} {p : Pattern o} {t : Infer n} {u : Check (o + n)}
{Γ Δ : Usages γ} {τ : Type} (p : Γ ⊢ τ ∋ `let p ∷= t `in u ⊠ Δ) →
let (θ , σ , _) = let-inv p in Γ ⊢ t ∈ σ ⊠ θ
let-inv-bound p = let (_ , _ , _ , T , _) = let-inv p in T
let-inv-pattern :
{n o : ℕ} {γ : Context n} {p : Pattern o} {t : Infer n} {u : Check (o + n)}
{Γ Δ : Usages γ} {τ : Type} (d : Γ ⊢ τ ∋ `let p ∷= t `in u ⊠ Δ) →
let (_ , σ , δ , _) = let-inv d in σ ∋ p ↝ δ
let-inv-pattern p = let (_ , _ , _ , _ , P , _) = let-inv p in P
let-inv-body :
{n o : ℕ} {γ : Context n} {p : Pattern o} {t : Infer n} {u : Check (o + n)}
{Γ Δ : Usages γ} {τ : Type} (p : Γ ⊢ τ ∋ `let p ∷= t `in u ⊠ Δ) →
let (θ , σ , δ , _) = let-inv p in [[ δ ]] ++ θ ⊢ τ ∋ u ⊠ ]] δ [[ ++ Δ
let-inv-body p = let (_ , _ , _ , _ , _ , U) = let-inv p in U
prd-inv-fst :
{n : ℕ} {γ : Context n} {t u : Check n} {Γ Δ : Usages γ} {σ τ : Type} →
(p : Γ ⊢ σ ⊗ τ ∋ `prd t u ⊠ Δ) → let (θ , _) = prd⊗-inv p in Γ ⊢ σ ∋ t ⊠ θ
prd-inv-fst p = let (_ , T , _) = prd⊗-inv p in T
prd-inv-snd :
{n : ℕ} {γ : Context n} {t u : Check n} {Γ Δ : Usages γ} {σ τ : Type} →
(p : Γ ⊢ σ ⊗ τ ∋ `prd t u ⊠ Δ) → let (θ , _) = prd⊗-inv p in θ ⊢ τ ∋ u ⊠ Δ
prd-inv-snd p = let (_ , _ , U) = prd⊗-inv p in U