module linear.Typing.Substitution where
open import Data.Nat
open import Data.Fin
open import Data.Vec hiding (map ; [_] ; _++_)
open import Data.Product hiding (swap)
open import Function
open import Relation.Binary.PropositionalEquality hiding ([_])
open import linear.Scope as Sc hiding (Weakening ; weakFin ; Substituting ; substFin ; copys ; Env ; withFreshVars)
open import linear.Type
open import linear.Context as C hiding (copys ; _++_)
open import linear.Language as L hiding (weakInfer ; weakCheck ; Env ; substInfer ; substCheck)
open import linear.Usage
open import linear.Usage.Functional
open import linear.Usage.Consumption hiding (_++_)
open import linear.Typing
open import linear.Typing.Functional
open import linear.Typing.Consumption
mutual
weakInfer : Weakening Infer L.weakInfer TInfer
weakInfer π (`var k) = `var (weakFin π k)
weakInfer π (`app t u) = `app (weakInfer π t) (weakCheck π u)
weakInfer π (`fst t) = `fst (weakInfer π t)
weakInfer π (`snd t) = `snd (weakInfer π t)
weakInfer π (`case t return Ο of l %% r) = `case weakInfer π t return Ο
of weakCheck (copy π) l
%% weakCheck (copy π) r
weakInfer π (`exfalso Ο t) = `exfalso Ο (weakInfer π t)
weakInfer π (`cut t) = `cut (weakCheck π t)
weakCheck : Weakening Check L.weakCheck TCheck
weakCheck π (`lam t) = `lam weakCheck (copy π) t
weakCheck {m = m} π (`let_β·=_`in_ {Ο} {Ο} {o} {rp} {Ξ΄} {rt} {Ξ} {ΞΈ} {ru} p t u) =
let P = Ξ» {Ξ³} (Ξ Ξβ² : Usages Ξ³) β Ξ β’ Ο β L.weakCheck (Sc.copys o m) ru β Ξβ²
ih = weakCheck (copys o π) u
cast = ++copys-elimβ P [[ Ξ΄ ]] ]] Ξ΄ [[ Ξ ΞΈ π
in `let p β·= weakInfer π t `in cast ih
weakCheck π `unit = `unit
weakCheck π (`prdβ t u) = `prdβ (weakCheck π t) (weakCheck π u)
weakCheck π (`prd& t u) = `prd& (weakCheck π t) (weakCheck π u)
weakCheck π (`inl t) = `inl weakCheck π t
weakCheck π (`inr t) = `inr weakCheck π t
weakCheck π (`neu t) = `neu weakInfer π t
substFin :
{k l : β} {Ξ³ : Context k} {Ξ Ξ : Usages Ξ³} {Ο : Type} {v : Fin k} {Ο : Sc.Env Infer k l}
{ΞΈ : Context l} {Ξ€β Ξ€β : Usages ΞΈ} β
Env TInfer Ξ€β Ο Ξ€β Ξ β Ξ β’ v β[ Ο ]β Ξ β
β Ξ» Ξ€β β Ξ€β β’ Sc.substFin L.fresheyInfer Ο v β Ο β Ξ€β Γ Env TInfer Ξ€β Ο Ξ€β Ξ
substFin (t β· Ο) z = , t , ββ· Ο
substFin ([v]β· Ο) z = , `var z , ]v[β· Ο
substFin (T β· Ο) (s v) =
let (ΞΈ , val , Οβ²) = substFin Ο v
(_ , cβ , cβ) = swap (consumptionInfer T) (consumptionInfer val)
in , framingInfer cβ val , framingInfer cβ T β· Οβ²
substFin ([v]β· Ο) (s v) = map ([ _ ] β·_) (map (weakInfer (insert _ finish)) [v]β·_) $ substFin Ο v
substFin (]v[β· Ο) (s v) = map (] _ [ β·_) (map (weakInfer (insert _ finish)) ]v[β·_) $ substFin Ο v
substFin (ββ· Ο) (s v) = map id (map id ββ·_) $ substFin Ο v
substLam :
{k l : β} {Ξ³ : Context k} {Ξ : Usages Ξ³} {Ο : Sc.Env Infer k l}
{ΞΈ : Context l} {Ξ€β Ξ€β : Usages ΞΈ} {Ο Ο : Type} {b : Check (suc k)} β
Ξ£[ Tβ β Usages (Ο β· ΞΈ) ] [ Ο ] β· Ξ€β β’ Ο β L.substCheck (vβ· Ο) b β Tβ
Γ Env TInfer Tβ (vβ· Ο) (] Ο [ β· Ξ€β) (] Ο [ β· Ξ) β
Ξ£[ Ξ€β β Usages ΞΈ ] Ξ€β β’ Ο βo Ο β L.substCheck Ο (`lam b) β Ξ€β
Γ Env TInfer Ξ€β Ο Ξ€β Ξ
substLam (._ , bΟ , ]v[β· Οβ²) = , `lam bΟ , Οβ²
substCase :
{k l : β} {Ξ³ : Context k} {Ξ : Usages Ξ³} {Ο : Sc.Env Infer k l}
{ΞΈ : Context l} {Ξ€β Ξ€β Ξ€β : Usages ΞΈ} {Οβ Οβ Ο : Type} (t : Infer k) {l r : Check (suc k)} β
Ξ€β β’ L.substInfer Ο t β Οβ β Οβ β Ξ€β β
Ξ£[ Tβ β Usages (Οβ β· ΞΈ) ] [ Οβ ] β· Ξ€β β’ Ο β L.substCheck (vβ· Ο) l β Tβ
Γ Env TInfer Tβ (vβ· Ο) (] Οβ [ β· Ξ€β) (] Οβ [ β· Ξ) β
Ξ£[ Tβ β Usages (Οβ β· ΞΈ) ] [ Οβ ] β· Ξ€β β’ Ο β L.substCheck (vβ· Ο) r β Tβ
Γ Env TInfer Tβ (vβ· Ο) (] Οβ [ β· Ξ€β) (] Οβ [ β· Ξ) β
Ξ£[ Ξ€β β Usages ΞΈ ] Ξ€β β’ L.substInfer Ο (`case t return Ο of l %% r) β Ο β Ξ€β
Γ Env TInfer Ξ€β Ο Ξ€β Ξ
substCase t tΟ (._ , lΟ , (]v[β· Οββ²)) (._ , rΟ , (]v[β· Οββ²))
rewrite sym (functionalEnvPre functionalInferPre _ Οββ² Οββ²) =
, `case tΟ return _ of lΟ %% rΟ , Οββ²
substLet :
{k l o : β} {Ξ³ : Context k} {Ξ : Usages Ξ³} {Ο : Sc.Env Infer k l} (Ξ΄ : Context o)
{ΞΈ : Context l} {Ξ€β : Usages ΞΈ} β
Ξ£[ Tβ β Usages (Ξ΄ C.++ ΞΈ) ] Env TInfer Tβ (Sc.withFreshVars o Ο) (]] Ξ΄ [[ ++ Ξ€β) (]] Ξ΄ [[ ++ Ξ) β
Ξ£[ Ξ€β β Usages ΞΈ ] Env TInfer Ξ€β Ο Ξ€β Ξ
substLet [] (Ξ€β , Οβ²) = , Οβ²
substLet (a β· Ξ΄) (._ , (]v[β· Οβ²)) = substLet Ξ΄ (, Οβ²)
mutual
substInfer : Substituting Infer Infer L.substInfer TInfer TInfer
substInfer Ο (`var x) = substFin Ο x
substInfer Ο (`app t u) =
let (ΞΈβ , tΟ , Οβ) = substInfer Ο t
(ΞΈβ , uΟ , Οβ) = substCheck Οβ u
in ΞΈβ , `app tΟ uΟ , Οβ
substInfer Ο (`fst t) =
let (ΞΈβ , tΟ , Οβ) = substInfer Ο t
in ΞΈβ , `fst tΟ , Οβ
substInfer Ο (`snd t) =
let (ΞΈβ , tΟ , Οβ) = substInfer Ο t
in ΞΈβ , `snd tΟ , Οβ
substInfer {t = `case rt return .Ο of rl %% rr} Ο (`case t return Ο of l %% r) =
let (ΞΈβ , tΟ , Οβ) = substInfer Ο t
in substCase rt tΟ (substCheck ([v]β· Οβ) l) (substCheck ([v]β· Οβ) r)
substInfer Ο (`exfalso Ο t) =
let (Ξβ , tΟ , Οβ) = substInfer Ο t
in Ξβ , `exfalso Ο tΟ , Οβ
substInfer Ο (`cut t) =
let (ΞΈβ , tΟ , Οβ) = substCheck Ο t
in ΞΈβ , `cut tΟ , Οβ
substCheck : Substituting Infer Check L.substCheck TInfer TCheck
substCheck Ο (`lam t) = substLam (substCheck ([v]β· Ο) t)
substCheck {t = `let _ β·= rt `in ru} Ο (`let p β·= t `in u) =
let Ξ΄ = patternContext p
(ΞΈβ , tΟ , Οβ) = substInfer Ο t
(ΞΈβ , uΟ , Οβ) = substCheck (withFreshVars Ξ΄ Οβ) u
(ΞΈβ , Ο) = substLet Ξ΄ (ΞΈβ , Οβ)
eq = functionalEnvPre functionalInferPre _ Οβ (withStaleVars (patternContext p) Ο)
in , `let p β·= tΟ `in subst (TCheck _ _ _) eq uΟ , Ο
substCheck Ο `unit = , `unit , Ο
substCheck Ο (`prdβ a b) =
let (ΞΈβ , aΟ , Οβ) = substCheck Ο a
(ΞΈβ , bΟ , Οβ) = substCheck Οβ b
in ΞΈβ , `prdβ aΟ bΟ , Οβ
substCheck Ο (`prd& a b) =
let (ΞΈβ , aΟ , Οβ) = substCheck Ο a
(ΞΈβ , bΟ , Οβ) = substCheck Ο b
eq = functionalEnvPre functionalInferPre _ Οβ Οβ
in , `prd& aΟ (subst (TCheck _ _ _) eq bΟ) , Οβ
substCheck Ο (`inl t) =
let (ΞΈβ , tΟ , Οβ) = substCheck Ο t
in ΞΈβ , `inl tΟ , Οβ
substCheck Ο (`inr t) =
let (ΞΈβ , tΟ , Οβ) = substCheck Ο t
in ΞΈβ , `inr tΟ , Οβ
substCheck Ο (`neu t) =
let (ΞΈβ , tΟ , Οβ) = substInfer Ο t
in ΞΈβ , `neu tΟ , Οβ