@@ -14,13 +14,14 @@
15{-# LANGUAGE FlexibleContexts #-}
15{-# LANGUAGE FlexibleContexts #-}
16{-# LANGUAGE ScopedTypeVariables #-}
16{-# LANGUAGE ScopedTypeVariables #-}
17+{-# LANGUAGE PatternGuards #-}
18module Language.PureScript.Sugar.Names (
19module Language.PureScript.Sugar.Names (
19 desugarImports
20 desugarImports
22−import Data.List (nub)
23+import Data.List (find, nub, (\\))
23−import Data.Maybe (fromMaybe, isJust, mapMaybe)
24+import Data.Maybe (catMaybes, fromMaybe, isJust, mapMaybe)
25import Control.Applicative (Applicative(..), (<$>), (<*>))
26import Control.Applicative (Applicative(..), (<$>), (<*>))
26import Control.Monad
27import Control.Monad
@@ -59,6 +60,10 @@ data Exports = Exports
59 -- The values exported from each module
60 -- The values exported from each module
61 , exportedValues :: [Ident]
62 , exportedValues :: [Ident]
64+ -- The modules exported from each module
66+ , exportedModules :: [ModuleName]
62 } deriving (Show)
67 } deriving (Show)
@@ -101,7 +106,7 @@ addEmptyModule :: (Applicative m, MonadError MultipleErrors m) => ExportEnvironm
101addEmptyModule env name =
106addEmptyModule env name =
102 if name `M.member` env
107 if name `M.member` env
103 then throwError . errorMessage $ RedefinedModule name
108 then throwError . errorMessage $ RedefinedModule name
104− else return $ M.insert name (Exports [] [] []) env
109+ else return $ M.insert name (Exports [] [] [] []) env
107-- Adds a type belonging to a module to the export environment.
112-- Adds a type belonging to a module to the export environment.
@@ -155,13 +160,65 @@ desugarImports :: forall m. (Applicative m, MonadError MultipleErrors m) => [Mod
155desugarImports modules = do
160desugarImports modules = do
156 unfilteredExports <- findExports modules
161 unfilteredExports <- findExports modules
157 exports <- foldM filterModuleExports unfilteredExports modules
162 exports <- foldM filterModuleExports unfilteredExports modules
163+ let modules' = moduleReexports <$> modules
158− mapM (renameInModule' unfilteredExports exports) modules
164+ mapM (renameInModule' unfilteredExports exports) modules'
166+ moduleReexports :: Module -> Module
167+ moduleReexports (Module coms mn decls exps) =
168+ let importedMods = catMaybes findImports'
169+ in (Module coms mn (decls ++ (concatMap reexports importedMods)) exps)
171+ imports :: [Declaration]
172+ imports = filter isImportDecl decls
173+ findImports' :: [Maybe (Declaration, Module)]
174+ findImports' = go <$> modules
176+ go :: Module -> Maybe (Declaration, Module)
177+ go m@(Module _ mn' _ (Just exps'))
178+ | any isModExport exps', Just d <- find ((== mn') . importedModName) imports = Just (d, m)
180+ importedModName :: Declaration -> ModuleName
181+ importedModName (ImportDeclaration imn _ _) = imn
182+ importedModName (PositionedDeclaration _ _ d) = importedModName d
183+ importedModName _ = error "Not an import decl"
185+ reexports :: (Declaration, Module) -> [Declaration]
186+ reexports (ImportDeclaration _ (Hiding refs) _, (Module coms' mn' ds' (Just exps'))) =
187+ case nonHiddenRefs of
189+ _ -> reexports (ImportDeclaration mn' Implicit Nothing, Module coms' mn' ds' (Just nonHiddenRefs))
191+ nonHiddenRefs :: [DeclarationRef]
192+ nonHiddenRefs = filter isModExport exps' \\ filter isModExport refs
193+ reexports (ImportDeclaration _ ty qual, Module _ _ _ (Just exps')) =
194+ let ty' = case ty of
195+ Explicit _ -> Explicit []
197+ in (\m -> ImportDeclaration m ty' qual) <$> (catMaybes $ go <$> exps')
199+ go :: DeclarationRef -> Maybe ModuleName
200+ go (ModuleRef mn') = Just mn'
202+ reexports (PositionedDeclaration _ _ d, m@(Module _ _ _ (Just _))) = reexports (d, m)
205+ isModExport :: DeclarationRef -> Bool
206+ isModExport (ModuleRef _) = True
207+ isModExport _ = False
161 -- Filters the exports for a module in the global exports environment so that only explicitly
209 -- Filters the exports for a module in the global exports environment so that only explicitly
162 -- exported members remain. If the module does not explicitly export anything, everything is
210 -- exported members remain. If the module does not explicitly export anything, everything is
163 -- exported.
211 -- exported.
164 filterModuleExports :: ExportEnvironment -> Module -> m ExportEnvironment
212 filterModuleExports :: ExportEnvironment -> Module -> m ExportEnvironment
213+ filterModuleExports env (Module _ mn _ (Just exps))
214+ | any isSelfModuleExport exps, Just exps' <- M.lookup mn env =
215+ let moduleNames = filter (/= mn) $ (\(ModuleRef mn') -> mn') <$> filter isModExport exps
216+ in return $ M.insert mn (exps' {exportedModules = moduleNames}) env
218+ isSelfModuleExport :: DeclarationRef -> Bool
219+ isSelfModuleExport (ModuleRef mn') | mn' == mn = True
220+ isSelfModuleExport (PositionedDeclarationRef _ _ ref) = isSelfModuleExport ref
221+ isSelfModuleExport _ = False
165 filterModuleExports env (Module _ mn _ (Just exps)) = filterExports mn exps env
222 filterModuleExports env (Module _ mn _ (Just exps)) = filterExports mn exps env
166 filterModuleExports env _ = return env
223 filterModuleExports env _ = return env
@@ -183,7 +240,8 @@ elaborateExports :: Exports -> Module -> Module
183elaborateExports exps (Module coms mn decls _) = Module coms mn decls (Just $
240elaborateExports exps (Module coms mn decls _) = Module coms mn decls (Just $
184 map (\(ctor, dctors) -> TypeRef ctor (Just dctors)) (exportedTypes exps) ++
241 map (\(ctor, dctors) -> TypeRef ctor (Just dctors)) (exportedTypes exps) ++
185 map TypeClassRef (exportedTypeClasses exps) ++
242 map TypeClassRef (exportedTypeClasses exps) ++
186− map ValueRef (exportedValues exps))
243+ map ValueRef (exportedValues exps) ++
244+ map ModuleRef (exportedModules exps))
189-- Add `import X ()` for any modules where there are only fully qualified references to members.
247-- Add `import X ()` for any modules where there are only fully qualified references to members.
@@ -314,7 +372,7 @@ findExports = foldM addModule $ M.singleton (ModuleName [ProperName C.prim]) pri
316 -- The exported types from the Prim module
374 -- The exported types from the Prim module
317− primExports = Exports (mkTypeEntry `map` M.keys primTypes) [] []
375+ primExports = Exports (mkTypeEntry `map` M.keys primTypes) [] [] []
319 mkTypeEntry (Qualified _ name) = (name, [])
377 mkTypeEntry (Qualified _ name) = (name, [])
@@ -358,7 +416,8 @@ filterExports mn exps env = do
358 types' <- foldM (filterTypes $ exportedTypes exported) [] exps
416 types' <- foldM (filterTypes $ exportedTypes exported) [] exps
359 values <- foldM (filterValues $ exportedValues exported) [] exps
417 values <- foldM (filterValues $ exportedValues exported) [] exps
360 classes <- foldM (filterClasses $ exportedTypeClasses exported) [] exps
418 classes <- foldM (filterClasses $ exportedTypeClasses exported) [] exps
419+ modules <- foldM (filterModules $ exportedModules exported) [] exps
361− return exported { exportedTypes = types', exportedTypeClasses = classes, exportedValues = values }
420+ return exported { exportedTypes = types', exportedTypeClasses = classes, exportedValues = values, exportedModules = modules }
363 -- Ensure the exported types and data constructors exist in the module and add them to the set of
422 -- Ensure the exported types and data constructors exist in the module and add them to the set of
364 -- exports
423 -- exports
@@ -395,6 +454,12 @@ filterExports mn exps env = do
395 else throwError . errorMessage . UnknownValue $ Qualified (Just mn) name
454 else throwError . errorMessage . UnknownValue $ Qualified (Just mn) name
396 filterValues _ result _ = return result
455 filterValues _ result _ = return result
457+ -- Add the exported modules to the set of exports
458+ filterModules :: [ModuleName] -> [ModuleName] -> DeclarationRef -> m [ModuleName]
459+ filterModules exps' result (PositionedDeclarationRef pos _ r) = rethrowWithPosition pos $ filterModules exps' result r
460+ filterModules _ result (ModuleRef name) = return $ name : result
461+ filterModules _ result _ = return result
399-- Finds the imports within a module, mapping the imported module name to an optional set of
464-- Finds the imports within a module, mapping the imported module name to an optional set of
400-- explicitly imported declarations.
465-- explicitly imported declarations.
@@ -501,6 +566,8 @@ resolveImport currentModule importModule exps imps impQual =
501 return ref
566 return ref
502 check ref@(TypeClassRef name) =
567 check ref@(TypeClassRef name) =
503 checkImportExists UnknownTypeClass classes name >> return ref
568 checkImportExists UnknownTypeClass classes name >> return ref
569+ check ref@(ModuleRef name) =
570+ checkImportExists (UnknownModule . (\(Qualified _ m) -> m)) (exportedModules exps) name >> return ref
504 check _ = error "Invalid argument to checkRefIsValid"
571 check _ = error "Invalid argument to checkRefIsValid"
506 -- Find all exported data constructors for a given type
573 -- Find all exported data constructors for a given type