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.

246 lines
7.0 KiB

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