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.

137 lines
4.2 KiB

  1. {-# LANGUAGE DeriveAnyClass #-}
  2. {-# LANGUAGE GeneralizedNewtypeDeriving #-}
  3. {-# LANGUAGE DerivingVia #-}
  4. {-# LANGUAGE DeriveAnyClass #-}
  5. module Elab.Monad where
  6. import Control.Monad.Reader
  7. import Control.Exception
  8. import Data.Text.Prettyprint.Doc.Render.Terminal (AnsiStyle)
  9. import qualified Data.Map.Strict as Map
  10. import Data.Text.Prettyprint.Doc
  11. import Data.Map.Strict (Map)
  12. import Data.Text (Text)
  13. import Data.Typeable
  14. import qualified Presyntax.Presyntax as P
  15. import Syntax.Pretty (getNameText)
  16. import Syntax
  17. data ElabEnv =
  18. ElabEnv { getEnv :: Map Name (NFType, Value)
  19. , nameMap :: Map Text Name
  20. , pingPong :: Int
  21. , commHook :: Value -> IO ()
  22. , currentSpan :: Maybe (P.Posn, P.Posn)
  23. , whereBound :: Map Name (P.Posn, P.Posn)
  24. }
  25. newtype ElabM a = ElabM { runElab :: ElabEnv -> IO a }
  26. deriving (Functor, Applicative, Monad, MonadReader ElabEnv, MonadIO)
  27. via ReaderT ElabEnv IO
  28. emptyEnv :: ElabEnv
  29. emptyEnv = ElabEnv mempty mempty 0 (const (pure ())) Nothing mempty
  30. assume :: Name -> Value -> ElabM a -> ElabM a
  31. assume nm ty = local go where
  32. go x = x { getEnv = Map.insert nm (ty, VVar nm) (getEnv x)
  33. , nameMap = Map.insert (getNameText nm) nm (nameMap x)
  34. , whereBound = maybe (whereBound x) (flip (Map.insert nm) (whereBound x)) (currentSpan x)
  35. }
  36. assumes :: [Name] -> Value -> ElabM a -> ElabM a
  37. assumes nm ty = local go where
  38. go x = x { getEnv = Map.union (Map.fromList (map (\v -> (v, (ty, VVar v))) nm)) (getEnv x)
  39. , nameMap = Map.union (Map.fromList (map ((,) <$> getNameText <*> id) nm)) (nameMap x)
  40. , whereBound = maybe (whereBound x) (\l -> Map.union (Map.fromList (zip nm (repeat l))) (whereBound x)) (currentSpan x)
  41. }
  42. define :: Name -> Value -> Value -> ElabM a -> ElabM a
  43. define nm ty vl = local go where
  44. go x = x { getEnv = Map.insert nm (ty, vl) (getEnv x), nameMap = Map.insert (getNameText nm) nm (nameMap x) }
  45. getValue :: Name -> ElabM Value
  46. getValue nm = do
  47. vl <- asks (Map.lookup nm . getEnv)
  48. case vl of
  49. Just v -> pure (snd v)
  50. Nothing -> throwElab $ NotInScope nm
  51. getNfType :: Name -> ElabM NFType
  52. getNfType nm = do
  53. vl <- asks (Map.lookup nm . getEnv)
  54. case vl of
  55. Just v -> pure (fst v)
  56. Nothing -> throwElab $ NotInScope nm
  57. getNameFor :: Text -> ElabM Name
  58. getNameFor x = do
  59. vl <- asks (Map.lookup x . nameMap)
  60. case vl of
  61. Just v -> pure v
  62. Nothing -> liftIO . throwIO $ NotInScope (Bound x)
  63. switch :: ElabM a -> ElabM a
  64. switch k =
  65. do
  66. depth <- asks pingPong
  67. when (depth >= 128) $ throwElab StackOverflow
  68. local go k
  69. where go e = e { pingPong = pingPong e + 1 }
  70. newtype NotInScope = NotInScope { nameNotInScope :: Name }
  71. deriving (Show, Typeable)
  72. deriving anyclass (Exception)
  73. data AttachedNote = AttachedNote { getNote :: Doc AnsiStyle, getExc :: SomeException }
  74. deriving (Show, Typeable)
  75. deriving anyclass (Exception)
  76. withNote :: ElabM a -> Doc AnsiStyle -> ElabM a
  77. withNote k note = do
  78. env <- ask
  79. liftIO $
  80. runElab k env
  81. `catch` \e -> throwIO (AttachedNote note e)
  82. data WhileChecking = WhileChecking { startPos :: P.Posn, endPos :: P.Posn, exc :: SomeException }
  83. deriving (Show, Typeable, Exception)
  84. withSpan :: P.Posn -> P.Posn -> ElabM a -> ElabM a
  85. withSpan a b k = do
  86. env <- ask
  87. liftIO $
  88. runElab k env{ currentSpan = Just (a, b) }
  89. `catches` [ Handler $ \e@WhileChecking{} -> throwIO e
  90. , Handler $ \e -> throwIO (WhileChecking a b e)
  91. ]
  92. data SeeAlso = SeeAlso { saStartPos :: P.Posn, saEndPos :: P.Posn, saExc :: SomeException }
  93. deriving (Show, Typeable, Exception)
  94. seeAlso :: ElabM a -> Name -> ElabM a
  95. seeAlso k nm = do
  96. env <- ask
  97. case Map.lookup nm (whereBound env) of
  98. Just l ->
  99. liftIO $ runElab k env
  100. `catch` \e -> throwIO (SeeAlso (fst l) (snd l) e)
  101. Nothing -> k
  102. catchElab :: Exception e => ElabM a -> (e -> ElabM a) -> ElabM a
  103. catchElab k h = do
  104. env <- ask
  105. liftIO $ runElab k env `catch` \e -> runElab (h e) env
  106. tryElab :: Exception e => ElabM a -> ElabM (Either e a)
  107. tryElab k = do
  108. env <- ask
  109. liftIO $ (Right <$> runElab k env) `catch` \e -> pure (Left e)
  110. throwElab :: Exception e => e -> ElabM a
  111. throwElab = liftIO . throwIO