|
{-# LANGUAGE BlockArguments #-}
|
|
{-# LANGUAGE LambdaCase #-}
|
|
{-# LANGUAGE OverloadedStrings #-}
|
|
{-# LANGUAGE DerivingStrategies #-}
|
|
{-# LANGUAGE DeriveAnyClass #-}
|
|
{-# LANGUAGE ViewPatterns #-}
|
|
module Elab.WiredIn where
|
|
|
|
import Syntax
|
|
import Data.Map.Strict (Map)
|
|
import Data.Text (Text)
|
|
import qualified Data.Map.Strict as Map
|
|
import Control.Exception
|
|
import Data.Typeable
|
|
import qualified Presyntax.Presyntax as P
|
|
import Elab.Eval
|
|
import qualified Data.Sequence as Seq
|
|
import qualified Data.Text as T
|
|
|
|
wiType :: WiredIn -> NFType
|
|
wiType WiType = VType
|
|
wiType WiPretype = VTypeω
|
|
|
|
wiType WiInterval = VTypeω
|
|
wiType WiI0 = VI
|
|
wiType WiI1 = VI
|
|
|
|
wiType WiIAnd = VI ~> VI ~> VI
|
|
wiType WiIOr = VI ~> VI ~> VI
|
|
wiType WiINot = VI ~> VI
|
|
wiType WiPathP = dprod (VI ~> VTypeω) \a -> a @@ VI0 ~> a @@ VI1 ~> VType
|
|
|
|
wiType WiIsOne = VI ~> VTypeω
|
|
wiType WiItIsOne = VIsOne VI1
|
|
wiType WiIsOne1 = forAll VI \i -> forAll VI \j -> VIsOne i ~> VIsOne (ior i j)
|
|
wiType WiIsOne2 = forAll VI \i -> forAll VI \j -> VIsOne j ~> VIsOne (ior i j)
|
|
|
|
wiType WiPartial = VI ~> VType ~> VTypeω
|
|
wiType WiPartialP = dprod VI \x -> VPartial x VType ~> VTypeω
|
|
|
|
wiType WiSub = dprod VType \a -> dprod VI \phi -> VPartial phi a ~> VTypeω
|
|
wiType WiInS = forAll VType \a -> forAll VI \phi -> dprod a \u -> VSub a phi (VLam P.Ex (Closure "x" (const u)))
|
|
wiType WiOutS = forAll VType \a -> forAll VI \phi -> forAll (VPartial phi a) \u -> VSub a phi u ~> a
|
|
|
|
wiType WiComp = dprod (VI ~> VType) \a -> forAll VI \phi -> dprod (dprod VI \i -> VPartial phi (a @@ i)) \u -> VSub (a @@ VI0) phi (u @@ VI0) ~> a @@ VI1
|
|
|
|
wiValue :: WiredIn -> Value
|
|
wiValue WiType = VType
|
|
wiValue WiPretype = VTypeω
|
|
|
|
wiValue WiInterval = VI
|
|
wiValue WiI0 = VI0
|
|
wiValue WiI1 = VI1
|
|
|
|
wiValue WiIAnd = fun \x -> fun \y -> iand x y
|
|
wiValue WiIOr = fun \x -> fun \y -> ior x y
|
|
wiValue WiINot = fun inot
|
|
wiValue WiPathP = fun \a -> fun \x -> fun \y -> VPath a x y
|
|
|
|
wiValue WiIsOne = fun VIsOne
|
|
wiValue WiItIsOne = VItIsOne
|
|
wiValue WiIsOne1 = forallI \_ -> forallI \_ -> fun VIsOne1
|
|
wiValue WiIsOne2 = forallI \_ -> forallI \_ -> fun VIsOne2
|
|
|
|
wiValue WiPartial = fun \phi -> fun \r -> VPartial phi r
|
|
wiValue WiPartialP = fun \phi -> fun \r -> VPartialP phi r
|
|
wiValue WiSub = fun \a -> fun \phi -> fun \u -> VSub a phi u
|
|
wiValue WiInS = forallI \a -> forallI \phi -> fun \u -> VInc a phi u
|
|
wiValue WiOutS = forallI \a -> forallI \phi -> forallI \u -> fun \x -> outS a phi u x
|
|
-- wiValue WiComp = forAll (VI ~> VType) \a -> forAll VI \phi -> dprod (dprod VI \i -> VPartial phi (a @@ i)) \u -> VSub (a @@ VI0) phi (u @@ VI0) ~> a @@ VI1
|
|
wiValue WiComp = fun \a -> forallI \phi -> fun \u -> fun \x -> comp a phi u x
|
|
|
|
(~>) :: Value -> Value -> Value
|
|
a ~> b = VPi P.Ex a (Closure "_" (const b))
|
|
infixr 7 ~>
|
|
|
|
fun :: (Value -> Value) -> Value
|
|
fun k = VLam P.Ex $ Closure "x" (k . force)
|
|
|
|
forallI :: (Value -> Value) -> Value
|
|
forallI k = VLam P.Im $ Closure "x" (k . force)
|
|
|
|
dprod :: Value -> (Value -> Value) -> Value
|
|
dprod a b = VPi P.Ex a (Closure "x" b)
|
|
|
|
forAll :: Value -> (Value -> Value) -> Value
|
|
forAll a b = VPi P.Im a (Closure "x" b)
|
|
|
|
wiredInNames :: Map Text WiredIn
|
|
wiredInNames = Map.fromList
|
|
[ ("Pretype", WiPretype)
|
|
, ("Type", WiType)
|
|
, ("Interval", WiInterval)
|
|
, ("i0", WiI0)
|
|
, ("i1", WiI1)
|
|
, ("iand", WiIAnd)
|
|
, ("ior", WiIOr)
|
|
, ("inot", WiINot)
|
|
, ("PathP", WiPathP)
|
|
|
|
, ("IsOne", WiIsOne)
|
|
, ("itIs1", WiItIsOne)
|
|
, ("isOneL", WiIsOne1)
|
|
, ("isOneR", WiIsOne2)
|
|
|
|
, ("Partial", WiPartial)
|
|
, ("PartialP", WiPartialP)
|
|
, ("Sub", WiSub)
|
|
, ("inS", WiInS)
|
|
, ("outS", WiOutS)
|
|
|
|
, ("comp", WiComp)
|
|
]
|
|
|
|
newtype NoSuchPrimitive = NoSuchPrimitive { getUnknownPrim :: Text }
|
|
deriving (Show, Typeable)
|
|
deriving anyclass (Exception)
|
|
|
|
-- Interval operations
|
|
|
|
iand, ior :: Value -> Value -> Value
|
|
iand = \case
|
|
VI1 -> id
|
|
VI0 -> const VI0
|
|
VIAnd x y -> \case
|
|
VI0 -> VI0
|
|
VI1 -> VI1
|
|
z -> iand x (iand y z)
|
|
x -> \case
|
|
VI0 -> VI0
|
|
VI1 -> x
|
|
y -> VIAnd x y
|
|
|
|
ior = \case
|
|
VI0 -> id
|
|
VI1 -> const VI1
|
|
VIOr x y -> \case
|
|
VI1 -> VI1
|
|
VI0 -> VIOr x y
|
|
z -> ior x (ior y z)
|
|
x -> \case
|
|
VI1 -> VI1
|
|
VI0 -> x
|
|
y -> VIOr x y
|
|
|
|
inot :: Value -> Value
|
|
inot = \case
|
|
VI0 -> VI1
|
|
VI1 -> VI0
|
|
VIOr x y -> VIAnd (inot x) (inot y)
|
|
VIAnd x y -> VIOr (inot x) (inot y)
|
|
VINot x -> x
|
|
x -> VINot x
|
|
|
|
ielim :: Value -> Value -> Value -> Value -> NFEndp -> Value
|
|
ielim _line _left _right fn i =
|
|
case force fn of
|
|
VLine _ _ _ fun -> fun @@ i
|
|
VNe n sp -> VNe n (sp Seq.:|> PIElim _line _left _right i)
|
|
_ -> error $ "can't ielim " ++ show fn
|
|
|
|
outS :: NFSort -> NFEndp -> Value -> Value -> Value
|
|
outS _ (force -> VI1) u _ = u @@ VItIsOne
|
|
outS _ _phi _ (VInc _ _ x) = x
|
|
outS a phi u (VNe x sp) = VNe x (sp Seq.:|> POuc a phi u)
|
|
outS _ _ _ v = error $ "can't outS " ++ show v
|
|
|
|
-- Composition
|
|
comp :: NFLine -> NFEndp -> Value -> Value -> Value
|
|
comp _ VI1 u _ = u @@ VI1 @@ VItIsOne
|
|
comp a phi u (VInc _ _ a0) =
|
|
case a @@ VNe (HVar (Bound (T.pack "x"))) Seq.empty of
|
|
VPi{} ->
|
|
let
|
|
plic i = let VPi p _ _ = a @@ i in p
|
|
dom i = let VPi _ d _ = a @@ i in d
|
|
rng i = let VPi _ _ (Closure _ r) = a @@ i in r
|
|
|
|
y' i y = fill (fun (dom . inot)) VI0 (fun \_ -> fun \_ -> VSystem mempty) (VInc (dom VI0) phi y) i
|
|
ybar i y = y' (inot i) y
|
|
in VLam (plic VI1) . Closure "x" $ \arg ->
|
|
comp (fun \i -> rng i (ybar i arg))
|
|
phi
|
|
(system \i isone -> vApp (plic i) (u @@ i @@ isone) (ybar i arg))
|
|
(VInc (rng VI0 (ybar VI0 arg)) phi (vApp (plic VI0) a0 (ybar VI0 arg)))
|
|
VSigma{} ->
|
|
let
|
|
dom i = let VSigma d _ = a @@ i in d
|
|
rng i = let VSigma _ (Closure _ r) = a @@ i in r
|
|
|
|
w i = fill (fun dom) phi (system \i isone -> vProj1 (u @@ i @@ isone)) (VInc (dom VI0) phi (vProj1 a0)) i
|
|
c1 = comp (fun dom) phi (system \i isone -> vProj1 (u @@ i @@ isone)) (VInc (dom VI0) phi (vProj1 a0))
|
|
c2 = comp (fun (($ w VI1) . rng)) phi (system \i isone -> vProj1 (u @@ i @@ isone)) (VInc (rng VI0 (dom VI0)) phi (vProj2 a0))
|
|
in
|
|
VPair c1 c2
|
|
VPath{} ->
|
|
let
|
|
a' i = let VPath a _ _ = a @@ i in a
|
|
u' i = let VPath _ u _ = a @@ i in u
|
|
v' i = let VPath _ _ v = a @@ i in v
|
|
in
|
|
VLine (a' VI1 @@ VI1) (u' VI1) (v' VI1) $ fun \j ->
|
|
comp (fun a')
|
|
(phi `ior` j `ior` inot j)
|
|
(system \i isone -> mkVSystem (Map.fromList [ (phi, ielim (a' VI0) (u' VI0) (v' VI0) (u @@ i @@ isone) j)
|
|
, (j, v' i)
|
|
, (inot j, u' i)]))
|
|
(VInc (a' VI0 @@ VI0 @@ j) phi (ielim (a' VI0 @@ VI0) (u' VI0) (v' VI0) a0 j))
|
|
|
|
_ -> VComp a phi u a0
|
|
comp a phi u a0 = VComp a phi u a0
|
|
|
|
system :: (Value -> Value -> Value) -> Value
|
|
system k = fun \i -> fun \isone -> k i isone
|
|
|
|
fill :: NFLine -> NFEndp -> Value -> Value -> NFEndp -> Value
|
|
fill a phi u a0 j =
|
|
comp (fun \i -> a @@ (i `iand` j))
|
|
(phi `ior` inot j)
|
|
(fun \i -> fun \isone -> mkVSystem (Map.fromList [ (phi, u @@ (i `iand` j) @@ isone)
|
|
, (inot j, a0)]))
|
|
a0
|