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.

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