module linear.Typing.Consumption where
open import Data.Nat
open import Data.Vec hiding (_++_)
open import Data.Product
open import Function
open import linear.Type
open import linear.Context hiding (_++_)
open import linear.Typing
open import linear.Usage hiding ([_] ; _++_)
open import linear.Usage.Consumption
import Relation.Binary.PropositionalEquality as PEq
mutual
consumptionInfer : Consumption TInfer
consumptionInfer (`var k) = consumptionFin k
consumptionInfer (`app t u) = trans (consumptionInfer t) (consumptionCheck u)
consumptionInfer (`fst t) = consumptionInfer t
consumptionInfer (`snd t) = consumptionInfer t
consumptionInfer (`case t return σ of l %% r) =
trans (consumptionInfer t) $ truncate [ _ ] $ consumptionCheck l
consumptionInfer (`exfalso σ t) = consumptionInfer t
consumptionInfer (`cut t) = consumptionCheck t
consumptionCheck : Consumption TCheck
consumptionCheck (`lam t) = truncate [ _ ] $ consumptionCheck t
consumptionCheck (`let p ∷= t `in u) =
trans (consumptionInfer t) $ truncate (patternContext p) $ consumptionCheck u
consumptionCheck `unit = refl _
consumptionCheck (`prd⊗ a b) = trans (consumptionCheck a) (consumptionCheck b)
consumptionCheck (`prd& a b) = consumptionCheck a
consumptionCheck (`inl t) = consumptionCheck t
consumptionCheck (`inr t) = consumptionCheck t
consumptionCheck (`neu t) = consumptionInfer t
mutual
framingInfer : Framing TInfer
framingInfer c (`var k) = `var (framingFin c k)
framingInfer c (`app t u) =
let (_ , c₁ , c₂) = divide c (consumptionInfer t) (consumptionCheck u)
in `app (framingInfer c₁ t) (framingCheck c₂ u)
framingInfer c (`fst t) = `fst framingInfer c t
framingInfer c (`snd t) = `snd framingInfer c t
framingInfer c (`case t return σ of l %% r) =
let (_ , c₁ , c₂) = divide c (consumptionInfer t) (truncate [ _ ] (consumptionCheck l))
in `case framingInfer c₁ t return σ of framingCheck (_ ∷ c₂) l %% framingCheck (_ ∷ c₂) r
framingInfer c (`exfalso σ t) = `exfalso σ (framingInfer c t)
framingInfer c (`cut t) = `cut (framingCheck c t)
framingCheck : Framing TCheck
framingCheck c (`lam t) = `lam framingCheck (_ ∷ c) t
framingCheck c (`let p ∷= t `in u) =
let (_ , c₁ , c₂) = divide c (consumptionInfer t) (truncate (patternContext p) (consumptionCheck u))
in `let p ∷= framingInfer c₁ t `in framingCheck (pure (patternContext p) ++ c₂) u
framingCheck c `unit = PEq.subst (TCheck _ _ _) (equality c) `unit
framingCheck c (`prd⊗ a b) =
let (_ , c₁ , c₂) = divide c (consumptionCheck a) (consumptionCheck b)
in `prd⊗ (framingCheck c₁ a) (framingCheck c₂ b)
framingCheck c (`prd& a b) = `prd& (framingCheck c a) (framingCheck c b)
framingCheck c (`inl t) = `inl framingCheck c t
framingCheck c (`inr t) = `inr framingCheck c t
framingCheck c (`neu t) = `neu framingInfer c t