less prototype, less bad code implementation of CCHM type theory
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

342 lines
10 KiB

  1. {-# LANGUAGE LambdaCase #-}
  2. {-# LANGUAGE DeriveAnyClass #-}
  3. {-# LANGUAGE ScopedTypeVariables #-}
  4. module Elab.Eval where
  5. import Control.Monad.Reader
  6. import Control.Exception
  7. import qualified Data.Map.Strict as Map
  8. import qualified Data.Sequence as Seq
  9. import qualified Data.Set as Set
  10. import qualified Data.Text as T
  11. import Data.Sequence (Seq)
  12. import Data.Traversable
  13. import Data.Set (Set)
  14. import Data.Typeable
  15. import Data.Foldable
  16. import Data.IORef
  17. import Data.Maybe
  18. import Elab.Monad
  19. import Presyntax.Presyntax (Plicity(..))
  20. import Syntax.Pretty
  21. import Syntax
  22. import System.IO.Unsafe
  23. import {-# SOURCE #-} Elab.WiredIn
  24. import Prettyprinter
  25. eval :: Term -> ElabM Value
  26. eval t = asks (flip eval' t)
  27. forceIO :: MonadIO m => Value -> m Value
  28. forceIO vl@(VNe (HMeta (MV _ cell)) args) = do
  29. solved <- liftIO $ readIORef cell
  30. case solved of
  31. Just vl -> forceIO $ foldl applProj vl args
  32. Nothing -> pure vl
  33. forceIO x = pure x
  34. applProj :: Value -> Projection -> Value
  35. applProj fun (PApp p arg) = vApp p fun arg
  36. applProj fun (PIElim l x y i) = ielim l x y fun i
  37. applProj fun PProj1 = vProj1 fun
  38. applProj fun PProj2 = vProj2 fun
  39. force :: Value -> Value
  40. force = unsafePerformIO . forceIO
  41. -- everywhere force
  42. zonkIO :: Value -> IO Value
  43. zonkIO (VNe hd sp) = do
  44. sp' <- traverse zonkSp sp
  45. case hd of
  46. HMeta (MV _ cell) -> do
  47. solved <- liftIO $ readIORef cell
  48. case solved of
  49. Just vl -> zonkIO $ foldl applProj vl sp'
  50. Nothing -> pure $ VNe hd sp'
  51. hd -> pure $ VNe hd sp'
  52. where
  53. zonkSp (PApp p x) = PApp p <$> zonkIO x
  54. zonkSp (PIElim l x y i) = PIElim <$> zonkIO l <*> zonkIO x <*> zonkIO y <*> zonkIO i
  55. zonkSp PProj1 = pure PProj1
  56. zonkSp PProj2 = pure PProj2
  57. zonkIO (VLam p (Closure s k)) = pure $ VLam p (Closure s (zonk . k))
  58. zonkIO (VPi p d (Closure s k)) = VPi p <$> zonkIO d <*> pure (Closure s (zonk . k))
  59. zonkIO (VSigma d (Closure s k)) = VSigma <$> zonkIO d <*> pure (Closure s (zonk . k))
  60. zonkIO (VPair a b) = VPair <$> zonkIO a <*> zonkIO b
  61. zonkIO (VPath line x y) = VPath <$> zonkIO line <*> zonkIO x <*> zonkIO y
  62. zonkIO (VLine line f) = VLine <$> zonkIO line <*> zonkIO f
  63. -- Sorts
  64. zonkIO VType = pure VType
  65. zonkIO VTypeω = pure VTypeω
  66. zonkIO VI = pure VI
  67. zonkIO VI0 = pure VI0
  68. zonkIO VI1 = pure VI1
  69. zonkIO (VIAnd x y) = iand <$> zonkIO x <*> zonkIO y
  70. zonkIO (VIOr x y) = ior <$> zonkIO x <*> zonkIO y
  71. zonkIO (VINot x) = inot <$> zonkIO x
  72. zonk :: Value -> Value
  73. zonk = unsafePerformIO . zonkIO
  74. eval' :: ElabEnv -> Term -> Value
  75. eval' env (Ref x) =
  76. case Map.lookup x (getEnv env) of
  77. Just (_, vl) -> vl
  78. _ -> error "variable not in scope when evaluating"
  79. eval' env (App p f x) = vApp p (eval' env f) (eval' env x)
  80. eval' env (Lam p s t) =
  81. VLam p $ Closure s $ \a ->
  82. eval' env { getEnv = Map.insert (Bound s) (error "type of abs", a) (getEnv env) } t
  83. eval' env (Pi p s d t) =
  84. VPi p (eval' env d) $ Closure s $ \a ->
  85. eval' env { getEnv = (Map.insert (Bound s) (error "type of abs", a) (getEnv env))} t
  86. eval' _ (Meta m) = VNe (HMeta m) mempty
  87. eval' env (Sigma s d t) =
  88. VSigma (eval' env d) $ Closure s $ \a ->
  89. eval' env { getEnv = Map.insert (Bound s) (error "type of abs", a) (getEnv env) } t
  90. eval' e (Pair a b) = VPair (eval' e a) (eval' e b)
  91. eval' e (Proj1 a) = vProj1 (eval' e a)
  92. eval' e (Proj2 a) = vProj2 (eval' e a)
  93. eval' _ Type = VType
  94. eval' _ Typeω = VTypeω
  95. eval' _ I = VI
  96. eval' _ I0 = VI0
  97. eval' _ I1 = VI1
  98. eval' e (IAnd x y) = iand (eval' e x) (eval' e y)
  99. eval' e (IOr x y) = ior (eval' e x) (eval' e y)
  100. eval' e (INot x) = inot (eval' e x)
  101. eval' e (PathP l a b) = VPath (eval' e l) (eval' e a) (eval' e b)
  102. eval' e (IElim l x y f i) = ielim (eval' e l) (eval' e x) (eval' e y) (eval' e f) (eval' e i)
  103. eval' e (PathIntro p f) = VLine (eval' e p) (eval' e f)
  104. vApp :: Plicity -> Value -> Value -> Value
  105. vApp p (VLam p' k) arg
  106. | p == p' = clCont k arg
  107. | otherwise = error $ "wrong plicity " ++ show p ++ " vs " ++ show p' ++ " in app " ++ show (App p (quote (VLam p' k)) (quote arg))
  108. vApp p (VNe h sp) arg = VNe h (sp Seq.:|> PApp p arg)
  109. vApp _ x _ = error $ "can't apply " ++ show x
  110. (@@) :: Value -> Value -> Value
  111. (@@) = vApp Ex
  112. infixl 9 @@
  113. vProj1 :: Value -> Value
  114. vProj1 (VPair a _) = a
  115. vProj1 (VNe h sp) = VNe h (sp Seq.:|> PProj1)
  116. vProj1 x = error $ "can't proj1 " ++ show x
  117. vProj2 :: Value -> Value
  118. vProj2 (VPair _ b) = b
  119. vProj2 (VNe h sp) = VNe h (sp Seq.:|> PProj2)
  120. vProj2 x = error $ "can't proj2 " ++ show x
  121. data NotEqual = NotEqual Value Value
  122. deriving (Show, Typeable, Exception)
  123. unify' :: Value -> Value -> ElabM ()
  124. unify' topa topb = join $ go <$> forceIO topa <*> forceIO topb where
  125. go (VNe (HMeta mv) sp) rhs = solveMeta mv sp rhs
  126. go rhs (VNe (HMeta mv) sp) = solveMeta mv sp rhs
  127. go (VNe x a) (VNe x' a')
  128. | x == x', length a == length a' =
  129. traverse_ (uncurry unify'Spine) (Seq.zip a a')
  130. go (VNe _hd (_ Seq.:|> PIElim _l x y i)) rhs =
  131. case force i of
  132. VI0 -> unify' x rhs
  133. VI1 -> unify' y rhs
  134. _ -> fail
  135. go (VLam p (Closure _ k)) vl = do
  136. t <- VVar . Bound <$> newName
  137. unify' (k t) (vApp p vl t)
  138. go vl (VLam p (Closure _ k)) = do
  139. t <- VVar . Bound <$> newName
  140. unify' (vApp p vl t) (k t)
  141. go (VPair a b) vl = unify' a (vProj1 vl) *> unify' b (vProj2 vl)
  142. go vl (VPair a b) = unify' (vProj1 vl) a *> unify' (vProj2 vl) b
  143. go (VPi p d (Closure _ k)) (VPi p' d' (Closure _ k')) | p == p' = do
  144. t <- VVar . Bound <$> newName
  145. unify' d d'
  146. unify' (k t) (k' t)
  147. go (VSigma d (Closure _ k)) (VSigma d' (Closure _ k')) = do
  148. t <- VVar . Bound <$> newName
  149. unify' d d'
  150. unify' (k t) (k' t)
  151. go VType VType = pure ()
  152. go VTypeω VTypeω = pure ()
  153. go VI VI = pure ()
  154. go VI0 VI0 = pure ()
  155. go VI1 VI1 = pure ()
  156. go (VINot x) (VINot y) = unify' x y
  157. go (VIAnd x y) (VIAnd x' y') = unify' x x' *> unify' y y'
  158. go (VIOr x y) (VIOr x' y') = unify' x x' *> unify' y y'
  159. go (VPath l x y) (VPath l' x' y') = do
  160. unify' l l'
  161. unify' x x'
  162. unify' y y'
  163. go (VLine l p) p' = do
  164. n <- VVar . Bound <$> newName
  165. unify (p @@ n) (ielim l (l @@ VI0) (l @@ VI1) p' n)
  166. go p' (VLine l p) = do
  167. n <- VVar . Bound <$> newName
  168. unify (ielim l (l @@ VI0) (l @@ VI1) p' n) (p @@ n)
  169. go _ _ = fail
  170. fail = liftIO . throwIO $ NotEqual topa topb
  171. unify'Spine (PApp a v) (PApp a' v')
  172. | a == a' = unify' v v'
  173. unify'Spine PProj1 PProj1 = pure ()
  174. unify'Spine PProj2 PProj2 = pure ()
  175. unify'Spine (PIElim _ _ _ i) (PIElim _ _ _ j) = unify' i j
  176. unify'Spine _ _ = fail
  177. unify :: Value -> Value -> ElabM ()
  178. unify a b = unify' a b `catchElab` \(_ :: SomeException) -> liftIO $ throwIO (NotEqual a b)
  179. isConvertibleTo :: Value -> Value -> ElabM (Term -> Term)
  180. VPi Im d (Closure _v k) `isConvertibleTo` ty = do
  181. meta <- newMeta d
  182. cont <- k meta `isConvertibleTo` ty
  183. pure (\f -> cont (App Im f (quote meta)))
  184. VType `isConvertibleTo` VTypeω = pure id
  185. VPi p d (Closure _ k) `isConvertibleTo` VPi p' d' (Closure _ k') | p == p' = do
  186. wp <- d' `isConvertibleTo` d
  187. n <- newName
  188. wp_n <- eval (Lam Ex n (wp (Ref (Bound n))))
  189. wp' <- k (VVar (Bound n)) `isConvertibleTo` k' (wp_n @@ VVar (Bound n))
  190. pure (\f -> Lam p n (wp' (App p f (wp (Ref (Bound n))))))
  191. isConvertibleTo a b = do
  192. unify' a b
  193. pure id
  194. newMeta :: Value -> ElabM Value
  195. newMeta _dom = do
  196. n <- newName
  197. c <- liftIO $ newIORef Nothing
  198. let m = MV n c
  199. env <- asks getEnv
  200. t <- for (Map.toList env) $ \(n, _) -> pure $
  201. case n of
  202. Bound{} -> Just (PApp Ex (VVar n))
  203. _ -> Nothing
  204. pure (VNe (HMeta m) (Seq.fromList (catMaybes t)))
  205. newName :: MonadIO m => m T.Text
  206. newName = liftIO $ do
  207. x <- atomicModifyIORef _nameCounter $ \x -> (x + 1, x + 1)
  208. pure (T.pack (show x))
  209. _nameCounter :: IORef Int
  210. _nameCounter = unsafePerformIO $ newIORef 0
  211. {-# NOINLINE _nameCounter #-}
  212. solveMeta :: MV -> Seq Projection -> Value -> ElabM ()
  213. solveMeta m@(MV _ cell) sp rhs = do
  214. env <- ask
  215. names <- checkSpine Set.empty sp
  216. checkScope (Set.fromList (Bound <$> names)) rhs
  217. `withNote` hsep [prettyTm (quote (VNe (HMeta m) sp)), pretty '≡', prettyTm (quote rhs)]
  218. let tm = quote rhs
  219. lam = eval' env $ foldr (Lam Ex) tm names
  220. liftIO . atomicModifyIORef' cell $ \case
  221. Just _ -> error "filled cell in solvedMeta"
  222. Nothing -> (Just lam, ())
  223. checkScope :: Set Name -> Value -> ElabM ()
  224. checkScope scope (VNe h sp) =
  225. do
  226. case h of
  227. HVar v@Bound{} ->
  228. unless (v `Set.member` scope) . liftIO . throwIO $
  229. NotInScope v
  230. HVar{} -> pure ()
  231. HMeta{} -> pure ()
  232. traverse_ checkProj sp
  233. where
  234. checkProj (PApp _ t) = checkScope scope t
  235. checkProj (PIElim l x y i) = traverse_ (checkScope scope) [l, x, y, i]
  236. checkProj PProj1 = pure ()
  237. checkProj PProj2 = pure ()
  238. checkScope scope (VLam _ (Closure n k)) =
  239. checkScope (Set.insert (Bound n) scope) (k (VVar (Bound n)))
  240. checkScope scope (VPi _ d (Closure n k)) = do
  241. checkScope scope d
  242. checkScope (Set.insert (Bound n) scope) (k (VVar (Bound n)))
  243. checkScope scope (VSigma d (Closure n k)) = do
  244. checkScope scope d
  245. checkScope (Set.insert (Bound n) scope) (k (VVar (Bound n)))
  246. checkScope s (VPair a b) = traverse_ (checkScope s) [a, b]
  247. checkScope _ VType = pure ()
  248. checkScope _ VTypeω = pure ()
  249. checkScope _ VI = pure ()
  250. checkScope _ VI0 = pure ()
  251. checkScope _ VI1 = pure ()
  252. checkScope s (VIAnd x y) = traverse_ (checkScope s) [x, y]
  253. checkScope s (VIOr x y) = traverse_ (checkScope s) [x, y]
  254. checkScope s (VINot x) = checkScope s x
  255. checkScope s (VPath line a b) = traverse_ (checkScope s) [line, a, b]
  256. checkScope s (VLine _ line) = checkScope s line
  257. checkSpine :: Set Name -> Seq Projection -> ElabM [T.Text]
  258. checkSpine scope (PApp Ex (VVar n@(Bound t)) Seq.:<| xs)
  259. | n `Set.member` scope = liftIO . throwIO $ NonLinearSpine n
  260. | otherwise = (t:) <$> checkSpine scope xs
  261. checkSpine _ (p Seq.:<| _) = liftIO . throwIO $ SpineProj p
  262. checkSpine _ Seq.Empty = pure []
  263. newtype NonLinearSpine = NonLinearSpine { getDupeName :: Name }
  264. deriving (Show, Typeable, Exception)
  265. newtype SpineProjection = SpineProj { getSpineProjection :: Projection }
  266. deriving (Show, Typeable, Exception)