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.

70 lines
2.1 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 qualified Data.Map.Strict as Map
  9. import Data.Map.Strict (Map)
  10. import Data.Text (Text)
  11. import Data.Typeable
  12. import Syntax
  13. import qualified Data.Text as T
  14. data ElabEnv = ElabEnv { getEnv :: Map Name (NFType, Value), nameMap :: Map Text Name, pingPong :: Int }
  15. newtype ElabM a = ElabM { runElab :: ElabEnv -> IO a }
  16. deriving (Functor, Applicative, Monad, MonadReader ElabEnv, MonadIO)
  17. via ReaderT ElabEnv IO
  18. newtype NotInScope = NotInScope { nameNotInScope :: Name }
  19. deriving (Show, Typeable)
  20. deriving anyclass (Exception)
  21. emptyEnv :: ElabEnv
  22. emptyEnv = ElabEnv mempty (Map.singleton (T.pack "Type") (Builtin (T.pack "Type") WiType)) 0
  23. assume :: Name -> Value -> ElabM a -> ElabM a
  24. assume nm ty = local go where
  25. go x = x { getEnv = Map.insert nm (ty, VVar nm) (getEnv x), nameMap = Map.insert (getNameText nm) nm (nameMap x) }
  26. getNameText :: Name -> Text
  27. getNameText (Bound x) = x
  28. getNameText (Defined x) = x
  29. getNameText (Builtin x _) = x
  30. define :: Name -> Value -> Value -> ElabM a -> ElabM a
  31. define nm ty vl = local go where
  32. go x = x { getEnv = Map.insert nm (ty, vl) (getEnv x), nameMap = Map.insert (getNameText nm) nm (nameMap x) }
  33. getValue :: Name -> ElabM Value
  34. getValue nm = do
  35. vl <- asks (Map.lookup nm . getEnv)
  36. case vl of
  37. Just v -> pure (snd v)
  38. Nothing -> liftIO . throwIO $ NotInScope nm
  39. getNfType :: Name -> ElabM NFType
  40. getNfType nm = do
  41. vl <- asks (Map.lookup nm . getEnv)
  42. case vl of
  43. Just v -> pure (fst v)
  44. Nothing -> liftIO . throwIO $ NotInScope nm
  45. getNameFor :: Text -> ElabM Name
  46. getNameFor x = do
  47. vl <- asks (Map.lookup x . nameMap)
  48. case vl of
  49. Just v -> pure v
  50. Nothing -> liftIO . throwIO $ NotInScope (Bound x)
  51. switch :: ElabM a -> ElabM a
  52. switch k =
  53. do
  54. depth <- asks pingPong
  55. when (depth >= 128) $ liftIO $ throwIO StackOverflow
  56. local go k
  57. where go e = e { pingPong = pingPong e + 1 }