{-# 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