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.

213 lines
6.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. evalWithEnv :: ElabEnv -> Term -> Value
  35. evalWithEnv env (Ref x) =
  36. case Map.lookup x (getEnv env) of
  37. Just (_, vl) -> vl
  38. _ -> error "variable not in scope when evaluating"
  39. evalWithEnv env (App p f x) = vApp p (evalWithEnv env f) (evalWithEnv env x)
  40. evalWithEnv env (Lam p s t) =
  41. VLam p $ Closure s $ \a ->
  42. evalWithEnv (ElabEnv (Map.insert (Bound s) (error "type of abs", a) (getEnv env))) t
  43. evalWithEnv env (Pi p s d t) =
  44. VPi p (evalWithEnv env d) $ Closure s $ \a ->
  45. evalWithEnv (ElabEnv (Map.insert (Bound s) (error "type of abs", a) (getEnv env))) t
  46. evalWithEnv _ (Meta m) = VNe (HMeta m) []
  47. evalWithEnv env (Sigma s d t) =
  48. VSigma (evalWithEnv env d) $ Closure s $ \a ->
  49. evalWithEnv (ElabEnv (Map.insert (Bound s) (error "type of abs", a) (getEnv env))) t
  50. evalWithEnv e (Pair a b) = VPair (evalWithEnv e a) (evalWithEnv e b)
  51. evalWithEnv e (Proj1 a) = vProj1 (evalWithEnv e a)
  52. evalWithEnv e (Proj2 a) = vProj2 (evalWithEnv e a)
  53. evalWithEnv _ Type = VType
  54. vApp :: Plicity -> Value -> Value -> Value
  55. vApp p (VLam p' k) arg = assert (p == p') $ clCont k arg
  56. vApp p (VNe h sp) arg = VNe h (PApp p arg:sp)
  57. vApp _ x _ = error $ "can't apply " ++ show x
  58. vProj1 :: Value -> Value
  59. vProj1 (VPair a _) = a
  60. vProj1 (VNe h sp) = VNe h (PProj1:sp)
  61. vProj1 x = error $ "can't proj1 " ++ show x
  62. vProj2 :: Value -> Value
  63. vProj2 (VPair _ b) = b
  64. vProj2 (VNe h sp) = VNe h (PProj2:sp)
  65. vProj2 x = error $ "can't proj2 " ++ show x
  66. data NotEqual = NotEqual Value Value
  67. deriving (Show, Typeable, Exception)
  68. unify :: Value -> Value -> ElabM ()
  69. unify topa topb = join $ go <$> forceIO topa <*> forceIO topb where
  70. go (VNe (HMeta mv) sp) rhs = solveMeta mv sp rhs
  71. go (VNe x a) (VNe x' a')
  72. | x == x', length a == length a' =
  73. traverse_ (uncurry unifySpine) (zip a a')
  74. | otherwise = fail
  75. go (VLam p (Closure _ k)) vl = do
  76. t <- VVar . Bound <$> newName
  77. unify (k t) (vApp p vl t)
  78. go vl (VLam p (Closure _ k)) = do
  79. t <- VVar . Bound <$> newName
  80. unify (vApp p vl t) (k t)
  81. go (VPair a b) vl = unify a (vProj1 vl) *> unify b (vProj2 vl)
  82. go vl (VPair a b) = unify (vProj1 vl) a *> unify (vProj2 vl) b
  83. go (VPi p d (Closure _ k)) (VPi p' d' (Closure _ k')) | p == p' = do
  84. t <- VVar . Bound <$> newName
  85. unify d d'
  86. unify (k t) (k' t)
  87. go (VSigma d (Closure _ k)) (VSigma d' (Closure _ k')) = do
  88. t <- VVar . Bound <$> newName
  89. unify d d'
  90. unify (k t) (k' t)
  91. go _ _ = fail
  92. fail = liftIO . throwIO $ NotEqual topa topb
  93. unifySpine (PApp a v) (PApp a' v')
  94. | a == a' = unify v v'
  95. unifySpine _ _ = fail
  96. isConvertibleTo :: Value -> Value -> ElabM (Term -> Term)
  97. VPi Im d (Closure _v k) `isConvertibleTo` ty = do
  98. meta <- newMeta d
  99. cont <- k meta `isConvertibleTo` ty
  100. pure (\f -> cont (App Ex f (quote meta)))
  101. isConvertibleTo a b = do
  102. unify a b
  103. pure id
  104. newMeta :: Value -> ElabM Value
  105. newMeta _dom = do
  106. n <- newName
  107. c <- liftIO $ newIORef Nothing
  108. let m = MV n c
  109. env <- asks getEnv
  110. t <- for (Map.toList env) $ \(n, (_, c)) -> pure $
  111. case c of
  112. VVar n' | n == n' -> Just (PApp Ex (VVar n'))
  113. _ -> Nothing
  114. pure (VNe (HMeta m) (catMaybes t))
  115. newName :: MonadIO m => m T.Text
  116. newName = liftIO $ do
  117. x <- atomicModifyIORef _nameCounter $ \x -> (x + 1, x + 1)
  118. pure (T.pack (show x))
  119. _nameCounter :: IORef Int
  120. _nameCounter = unsafePerformIO $ newIORef 0
  121. {-# NOINLINE _nameCounter #-}
  122. solveMeta :: MV -> [Projection] -> Value -> ElabM ()
  123. solveMeta m@(MV _ cell) sp rhs = do
  124. liftIO $ print (m, sp, rhs)
  125. names <- checkSpine Set.empty sp
  126. checkScope (Set.fromList (Bound <$> names)) rhs
  127. let tm = quote rhs
  128. lam = evalWithEnv emptyEnv $ foldr (Lam Ex) tm names
  129. liftIO . atomicModifyIORef' cell $ \case
  130. Just _ -> error "filled cell in solvedMeta"
  131. Nothing -> (Just lam, ())
  132. checkScope :: Set Name -> Value -> ElabM ()
  133. checkScope scope (VNe h sp) =
  134. do
  135. case h of
  136. HVar v ->
  137. unless (v `Set.member` scope) . liftIO . throwIO $
  138. NotInScope v
  139. HMeta{} -> pure ()
  140. traverse_ checkProj sp
  141. where
  142. checkProj (PApp _ t) = checkScope scope t
  143. checkProj PProj1 = pure ()
  144. checkProj PProj2 = pure ()
  145. checkScope scope (VLam _ (Closure n k)) =
  146. checkScope (Set.insert (Bound n) scope) (k (VVar (Bound n)))
  147. checkScope scope (VPi _ d (Closure n k)) = do
  148. checkScope scope d
  149. checkScope (Set.insert (Bound n) scope) (k (VVar (Bound n)))
  150. checkScope scope (VSigma d (Closure n k)) = do
  151. checkScope scope d
  152. checkScope (Set.insert (Bound n) scope) (k (VVar (Bound n)))
  153. checkScope s (VPair a b) = traverse_ (checkScope s) [a, b]
  154. checkScope _ VType = pure ()
  155. checkSpine :: Set Name -> [Projection] -> ElabM [T.Text]
  156. checkSpine scope (PApp Ex (VVar n@(Bound t)):xs)
  157. | n `Set.member` scope = liftIO . throwIO $ NonLinearSpine n
  158. | otherwise = (t:) <$> checkSpine scope xs
  159. checkSpine _ (p:_) = liftIO . throwIO $ SpineProj p
  160. checkSpine _ [] = pure []
  161. newtype NonLinearSpine = NonLinearSpine { getDupeName :: Name }
  162. deriving (Show, Typeable, Exception)
  163. newtype SpineProjection = SpineProj { getSpineProjection :: Projection }
  164. deriving (Show, Typeable, Exception)