Abbie's Haskell compiler
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.

252 lines
8.8 KiB

  1. {-# LANGUAGE DeriveAnyClass #-}
  2. {-# LANGUAGE DeriveGeneric #-}
  3. {-# LANGUAGE DerivingVia #-}
  4. {-# LANGUAGE NamedFieldPuns #-}
  5. {-# LANGUAGE FlexibleContexts #-}
  6. {-# LANGUAGE RankNTypes #-}
  7. module Rename.Rename where
  8. import Ahc.Data.Lens
  9. import Control.Monad.IO.Class
  10. import Control.Monad.Reader
  11. import Control.Concurrent
  12. import Control.Exception
  13. import qualified Data.HashMap.Strict as HashMap
  14. import Data.HashMap.Strict (HashMap)
  15. import Data.ByteString (ByteString)
  16. import Data.Text (Text)
  17. import Debug.Trace
  18. import Development.Shake ( Action, askOracle )
  19. import Development.Shake.Classes
  20. import Errors
  21. import qualified Frontend.Syntax as Fe
  22. import Frontend.Parser.Posn
  23. import Frontend.Syntax.Var
  24. import Frontend.Syntax
  25. import GHC.Generics
  26. import Main.Queries
  27. import Rename.Types
  28. import Text.Show.Pretty
  29. import Control.Applicative
  30. newtype Rename a = RenameM { runRename :: RenameCtx -> Action a }
  31. deriving (Functor, Applicative, Monad, MonadIO, MonadReader RenameCtx)
  32. via ReaderT RenameCtx Action
  33. liftAct :: Action a -> Rename a
  34. liftAct a = RenameM $ \x -> a
  35. data RenameCtx =
  36. RenameCtx
  37. { rcOurModId :: ModuleId
  38. , rcOurFilePath :: String
  39. , rcScope :: Scope
  40. , rcThisModule :: MVar Scope
  41. , rcSpanStart :: Posn
  42. , rcSpanEnd :: Posn
  43. }
  44. _rcScope :: Lens' RenameCtx Scope
  45. _rcScope = lens rcScope (\s x -> s { rcScope = x })
  46. renamerSourcePos :: Posn -> Posn -> RenameCtx -> RenameCtx
  47. renamerSourcePos start end x = x { rcSpanStart = start, rcSpanEnd = end }
  48. renameModule :: FeModule ParsedVar -> Rename RenamedMod
  49. renameModule Fe.Module{moduleExports, moduleImports, moduleItems, Fe.moduleName} = do
  50. (imports, scopes) <- fmap unzip $ traverse importModule moduleImports
  51. our_mod_id <- asks rcOurModId
  52. local (extendBy (mconcat scopes)) $ do
  53. items <- renameModuleBody moduleItems
  54. this_mod <- liftIO . readMVar =<< asks rcThisModule
  55. liftIO $ print this_mod
  56. export <- traverse (renameModVarList this_mod) moduleExports
  57. our_mod_name <- makeVariable Rename.Types.Module moduleName
  58. let
  59. scope = restrictToModVarList export this_mod
  60. rnm_mod = Fe.Module { Fe.moduleName = our_mod_name
  61. , moduleExports = export
  62. , moduleImports = imports
  63. , moduleItems = items
  64. }
  65. pure (RnmMod rnm_mod scope)
  66. restrictToModVarList :: Maybe [NamespacedItem FqVar] -> Scope -> Scope
  67. restrictToModVarList Nothing x = x
  68. restrictToModVarList (Just xs) sc = foldr del sc xs where
  69. del :: NamespacedItem FqVar -> Scope -> Scope
  70. del (IEVar n) = over scopeNames (HashMap.delete (fqVarName n))
  71. del (IECon n) = over scopeNames (HashMap.delete (fqVarName n)) . over scopeTypes (HashMap.delete (fqVarName n))
  72. del (IEModule n) = over scopeNamespaces (HashMap.delete (fqVarName n))
  73. renameModVarList :: Scope -> [NamespacedItem ParsedVar] -> Rename [NamespacedItem FqVar]
  74. renameModVarList sc (x:xs) =
  75. case x of
  76. IEVar pv ->
  77. case HashMap.lookup (varId pv) (sc ^. scopeNames) of
  78. Just [t] -> (IEVar t:) <$> renameModVarList sc xs
  79. _ -> notInScope pv
  80. IECon pv ->
  81. case HashMap.lookup (varId pv) (sc ^. scopeNames) <|> HashMap.lookup (varId pv) (sc ^. scopeTypes) of
  82. Just [t] -> (IECon t:) <$> renameModVarList sc xs
  83. _ -> notInScope pv
  84. IEModule pv ->
  85. case HashMap.lookup (varId pv) (sc ^. scopeNamespaces) of
  86. Just (t, _) -> (IEModule t:) <$> renameModVarList sc xs
  87. _ -> notInScope pv
  88. renameModVarList sc [] = pure []
  89. renameModuleBody :: [ModuleItem ParsedVar] -> Rename [ModuleItem FqVar]
  90. renameModuleBody = wrap where
  91. wrap [] = pure []
  92. wrap xs = do
  93. var <- asks rcThisModule
  94. go xs
  95. go [] = pure []
  96. go (ModDecl (TySig vars tipe begin end) begin' end':items) = local (renamerSourcePos begin end) $ do
  97. tipe <- renameTypeToplevel tipe
  98. vars <- traverse (makeVariable_unique Variable scopeNames) vars
  99. r <- go items
  100. insertVariables scopeNames vars $
  101. pure (ModDecl (TySig (map snd vars) tipe begin end) begin' end':r)
  102. go (x:items) = error $ "show item: " ++ ppShow x
  103. renameTypeToplevel :: FeType ParsedVar -> Rename (FeType FqVar)
  104. renameTypeToplevel (Tytup xs) = Tytup <$> traverse renameTypeToplevel xs
  105. renameTypeToplevel (SPType ty s e) =
  106. SPType <$> local (renamerSourcePos s e) (renameTypeToplevel ty)
  107. <*> pure s
  108. <*> pure e
  109. -- rename units to units
  110. renameTypeToplevel (Tycon (BuiltinId _ (BuiltinTuple 0) _ _)) = pure (Tytup [])
  111. renameTypeToplevel (Tycon x) = do
  112. var <- useVariable scopeTypes x
  113. pure (Tycon var)
  114. renameTypeToplevel x = error $ "idk how to rename: " ++ show x
  115. extendBy :: Scope -> RenameCtx -> RenameCtx
  116. extendBy s rc = rc{rcScope = s <> rcScope rc}
  117. importModule :: ModuleImport ParsedVar -> Rename (ModuleImport FqVar, Scope)
  118. importModule Import{importMod, importList, importQualified, importAlias, importBegin, importEnd} = do
  119. fp <- asks rcOurFilePath
  120. our_mod_id <- asks rcOurModId
  121. res_fp <- liftAct $ askOracle $
  122. AhcModuleFilepath { ahcfpImportingModule = fp
  123. , ahcfpModName = importMod
  124. }
  125. renamed_import <- liftAct $ askOracle $ AhcRenamedModule res_fp
  126. let
  127. orig = rnmModSignature renamed_import
  128. other_mod = Fe.moduleName $ rnmModModule renamed_import
  129. il <- traverse (renameModVarList orig) importList
  130. orig <- pure $ restrictToModVarList il orig
  131. mod <- pure $
  132. if importQualified
  133. then mempty { _scopeNamespaces = HashMap.singleton (varId importMod) (other_mod, orig) }
  134. else orig
  135. mod <- pure $
  136. case importAlias of
  137. Just x -> mod & scopeNamespaces %~ HashMap.insert (varId x) (other_mod, orig)
  138. Nothing -> mod
  139. our_mod_name <- makeVariable Rename.Types.Module importMod
  140. alias <- traverse (makeVariable Rename.Types.Module) importAlias
  141. let
  142. imp = Import our_mod_name il importQualified alias importBegin importEnd
  143. pure (imp, mod)
  144. makeVariable :: MonadReader RenameCtx m => Namespace -> ParsedVar -> m FqVar
  145. makeVariable nsc x = do
  146. context <- ask
  147. pure $
  148. FqVar { fqVarName = varId x
  149. , fqVarModule = rcOurModId context
  150. , fqVarNamespace = nsc
  151. , fqBegin = rcSpanStart context
  152. , fqEnd = rcSpanEnd context
  153. }
  154. makeVariable_unique :: Namespace -> Lens' Scope (HashMap Text [FqVar]) -> ParsedVar -> Rename (Text, FqVar)
  155. makeVariable_unique this_ns ns x = do
  156. var <- asks rcThisModule
  157. scope <- liftIO . readMVar $ var
  158. let
  159. the_hm = scope ^. ns
  160. case HashMap.lookup (varId x) the_hm of
  161. Just (orig:_) -> redeclaration orig x
  162. _ -> do
  163. new_var <- makeVariable this_ns x
  164. liftIO $ modifyMVar_ var $ \s -> pure $ over ns (insertVariable (varId x) new_var) s
  165. pure (varId x, new_var)
  166. insertVariable :: Text -> FqVar -> HashMap Text [FqVar] -> HashMap Text [FqVar]
  167. insertVariable c v = HashMap.alter go c where
  168. go (Just xs) = Just (v:xs)
  169. go Nothing = Just [v]
  170. insertVariables :: Lens' Scope (HashMap Text [FqVar]) -> [(Text, FqVar)] -> Rename a -> Rename a
  171. insertVariables lens vars = local (over (_rcScope . lens) go) where
  172. go x = foldr (\(x, y) -> insertVariable x y) x vars
  173. useVariable :: Lens' Scope (HashMap Text [FqVar]) -> ParsedVar -> Rename FqVar
  174. useVariable final_ns var =
  175. do scope <- asks rcScope
  176. go scope var
  177. where
  178. go scope (QualVar id prfx begin end) =
  179. case HashMap.lookup prfx (scope ^. scopeNamespaces) of
  180. Nothing -> notInScope var
  181. Just (_, sc) -> local (\s -> s { rcScope = sc }) $ useVariable final_ns (UnqualVar id begin end)
  182. go scope (UnqualVar id begin end) =
  183. case HashMap.lookup id (scope ^. final_ns) of
  184. Just [var] -> pure var
  185. Just vars -> ambiguousVariables vars
  186. Nothing -> notInScope var
  187. go _ x = error $ "idk how to rename yet: " ++ show x
  188. ambiguousVariables :: [FqVar] -> Rename a
  189. ambiguousVariables vs = throwRenamer $ \e -> e { errorMessage = show vs }
  190. notInScope :: HasPosn x => x -> Rename a
  191. notInScope x =
  192. local (renamerSourcePos (startPosn x) (endPosn x)) $
  193. throwRenamer $ \e -> e { errorMessage = "variable not in scope" }
  194. redeclaration :: FqVar -> ParsedVar -> Rename a
  195. redeclaration first v = do
  196. liftIO $ pPrint first
  197. throwRenamer $ \e -> e { errorMessage = "variables can only have one declaration."
  198. , errorInlineDesc = Just "first declaration here"
  199. , errorPointers = pointTo v v "redeclaration here"
  200. , errorBegin = startPosn first
  201. , errorEnd = endPosn first
  202. }
  203. throwRenamer :: (MonadIO m, MonadReader RenameCtx m) => (AhcError -> AhcError) -> m b
  204. throwRenamer cont = do
  205. context <- ask
  206. let
  207. fname = moduleFp (rcOurModId context)
  208. errorBegin = rcSpanStart context
  209. errorEnd = rcSpanEnd context
  210. liftIO . throwIO $ cont (emptyError { errorFilename = fname, errorBegin, errorEnd })