@@ -1,16 +1,3 @@
1−-----------------------------------------------------------------------------
3−-- Module : Language.PureScript.Sugar.Names.Imports
4−-- License : MIT (http://opensource.org/licenses/MIT)
6−-- Maintainer : Phil Freeman <paf31@cantab.net>, Gary Burgess <gary.burgess@gmail.com>
7−-- Stability : experimental
12−-----------------------------------------------------------------------------
14{-# LANGUAGE FlexibleContexts #-}
1{-# LANGUAGE FlexibleContexts #-}
15{-# LANGUAGE ScopedTypeVariables #-}
2{-# LANGUAGE ScopedTypeVariables #-}
16{-# LANGUAGE TupleSections #-}
3{-# LANGUAGE TupleSections #-}
@@ -47,34 +34,36 @@ import Language.PureScript.Sugar.Names.Env
47-- Finds the imports within a module, mapping the imported module name to an optional set of
34-- Finds the imports within a module, mapping the imported module name to an optional set of
48-- explicitly imported declarations.
35-- explicitly imported declarations.
39+ . (Applicative m, MonadError MultipleErrors m, MonadWriter MultipleErrors m)
50−findImports :: forall m. (Applicative m, MonadError MultipleErrors m, MonadWriter MultipleErrors m) => [Declaration] -> m (M.Map ModuleName [(Maybe SourceSpan, ImportDeclarationType, Maybe ModuleName)])
41+ -> m (M.Map ModuleName [(Maybe SourceSpan, ImportDeclarationType, Maybe ModuleName)])
51findImports = foldM (go Nothing) M.empty
42findImports = foldM (go Nothing) M.empty
53 go pos result (ImportDeclaration mn typ qual isOldSyntax) = do
44 go pos result (ImportDeclaration mn typ qual isOldSyntax) = do
54 when isOldSyntax . tell . errorMessage $ DeprecatedQualifiedSyntax mn (fromJust qual)
45 when isOldSyntax . tell . errorMessage $ DeprecatedQualifiedSyntax mn (fromJust qual)
55− checkImportRefType typ
56 let imp = (pos, typ, qual)
46 let imp = (pos, typ, qual)
57 return $ M.insert mn (maybe [imp] (imp :) (mn `M.lookup` result)) result
47 return $ M.insert mn (maybe [imp] (imp :) (mn `M.lookup` result)) result
58 go _ result (PositionedDeclaration pos _ d) = warnAndRethrowWithPosition pos $ go (Just pos) result d
48 go _ result (PositionedDeclaration pos _ d) = warnAndRethrowWithPosition pos $ go (Just pos) result d
59 go _ result _ = return result
49 go _ result _ = return result
61− -- Ensure that modules don't appear in an `import X hiding (...)`
62− checkImportRefType :: ImportDeclarationType -> m ()
63− checkImportRefType (Hiding refs) = traverse_ checkImportRef refs
64− checkImportRefType _ = return ()
65− checkImportRef :: DeclarationRef -> m ()
66− checkImportRef (ModuleRef name) = throwError . errorMessage $ ImportHidingModule name
67− checkImportRef _ = return ()
69type ImportDef = (Maybe SourceSpan, ImportDeclarationType, Maybe ModuleName)
51type ImportDef = (Maybe SourceSpan, ImportDeclarationType, Maybe ModuleName)
72-- Constructs a set of imports for a module.
54-- Constructs a set of imports for a module.
74−resolveImports :: forall m. (Applicative m, MonadError MultipleErrors m, MonadWriter MultipleErrors m) => Env -> Module -> m Imports
58+ . (Applicative m, MonadError MultipleErrors m, MonadWriter MultipleErrors m)
61+ -> m (Module, Imports)
75−resolveImports env (Module _ _ currentModule decls _) =
62+resolveImports env (Module ss coms currentModule decls exps) =
76 warnAndRethrow (addHint (ErrorInModule currentModule)) $ do
63 warnAndRethrow (addHint (ErrorInModule currentModule)) $ do
65+ decls' <- traverse updateImportRef decls
77− imports <- findImports decls
66+ imports <- findImports decls'
79 for_ (M.toList imports) $ \(mn, imps) -> do
68 for_ (M.toList imports) $ \(mn, imps) -> do
@@ -110,7 +99,8 @@ resolveImports env (Module _ _ currentModule decls _) =
110 return ()
99 return ()
112 let scope = M.insert currentModule [(Nothing, Implicit, Nothing)] imports
101 let scope = M.insert currentModule [(Nothing, Implicit, Nothing)] imports
113− foldM (resolveModuleImport currentModule env) nullImports (M.toList scope)
102+ resolved <- foldM (resolveModuleImport currentModule env) nullImports (M.toList scope)
103+ return (Module ss coms currentModule decls' exps, resolved)
116 selfCartesianSubset :: [a] -> [(a, a)]
106 selfCartesianSubset :: [a] -> [(a, a)]
@@ -142,12 +132,38 @@ resolveImports env (Module _ _ currentModule decls _) =
142 warn :: Maybe SourceSpan -> SimpleErrorMessage -> m ()
132 warn :: Maybe SourceSpan -> SimpleErrorMessage -> m ()
143 warn pos msg = maybe id warnWithPosition pos $ tell . errorMessage $ msg
133 warn pos msg = maybe id warnWithPosition pos $ tell . errorMessage $ msg
135+ updateImportRef :: Declaration -> m Declaration
136+ updateImportRef (PositionedDeclaration pos com d) =
137+ warnWithPosition pos $ PositionedDeclaration pos com <$> updateImportRef d
138+ updateImportRef (ImportDeclaration mn typ qual isOldSyntax) = do
139+ modExports <- getExports env mn
141+ Implicit -> return Implicit
142+ Explicit refs -> Explicit <$> updateProperRef mn modExports `traverse` refs
143+ Hiding refs -> Hiding <$> updateProperRef mn modExports `traverse` refs
144+ return $ ImportDeclaration mn typ' qual isOldSyntax
145+ updateImportRef other = return other
147+ updateProperRef :: ModuleName -> Exports -> DeclarationRef -> m DeclarationRef
148+ updateProperRef importModule modExports (ProperRef name) =
149+ if name `elem` (fst `map` exportedTypeClasses modExports)
151+ tell . errorMessage $ DeprecatedClassImport importModule name
152+ return $ TypeClassRef name
153+ else return $ TypeRef name (Just [])
154+ updateProperRef importModule modExports (PositionedDeclarationRef pos com ref) =
155+ PositionedDeclarationRef pos com <$> updateProperRef importModule modExports ref
156+ updateProperRef _ _ other = return other
145-- | Constructs a set of imports for a single module import.
158-- | Constructs a set of imports for a single module import.
146−resolveModuleImport ::
159+resolveModuleImport
147− forall m. (Applicative m, MonadError MultipleErrors m, MonadWriter MultipleErrors m) =>
161+ . (Applicative m, MonadError MultipleErrors m, MonadWriter MultipleErrors m)
148− ModuleName -> Env -> Imports ->
164+ -> Imports
149− (ModuleName, [(Maybe SourceSpan, ImportDeclarationType, Maybe ModuleName)]) ->
165+ -> (ModuleName, [(Maybe SourceSpan, ImportDeclarationType, Maybe ModuleName)])
150− m Imports
166+ -> m Imports
151resolveModuleImport currentModule env ie (mn, imps) = foldM go ie imps
167resolveModuleImport currentModule env ie (mn, imps) = foldM go ie imps
153 go :: Imports -> (Maybe SourceSpan, ImportDeclarationType, Maybe ModuleName) -> m Imports
169 go :: Imports -> (Maybe SourceSpan, ImportDeclarationType, Maybe ModuleName) -> m Imports
@@ -163,17 +179,24 @@ resolveModuleImport currentModule env ie (mn, imps) = foldM go ie imps
164-- Extends the local environment for a module by resolving an import of another module.
180-- Extends the local environment for a module by resolving an import of another module.
166−resolveImport :: forall m. (Applicative m, MonadError MultipleErrors m, MonadWriter MultipleErrors m) => ModuleName -> ModuleName -> Exports -> Imports -> Maybe ModuleName -> ImportDeclarationType -> m Imports
184+ . (Applicative m, MonadError MultipleErrors m, MonadWriter MultipleErrors m)
190+ -> ImportDeclarationType
167−resolveImport currentModule importModule exps imps impQual =
192+resolveImport currentModule importModule exps imps impQual = resolveByType
171 resolveByType :: ImportDeclarationType -> m Imports
195 resolveByType :: ImportDeclarationType -> m Imports
172 resolveByType Implicit = importAll importExplicit
196 resolveByType Implicit = importAll importExplicit
173− resolveByType (Explicit explImports) = checkRefs explImports >> foldM importExplicit imps explImports
197+ resolveByType (Explicit refs) = checkRefs False refs >> foldM importExplicit imps refs
174− resolveByType (Hiding hiddenImports) = do
198+ resolveByType (Hiding refs) = do
175− checkRefs hiddenImports
176− imps' <- importAll (importNonHidden hiddenImports)
199+ imps' <- checkRefs True refs >> importAll (importNonHidden refs)
177 let isEmptyImport
200 let isEmptyImport
178 = M.null (importedTypes imps')
201 = M.null (importedTypes imps')
179 && M.null (importedDataConstructors imps')
202 && M.null (importedDataConstructors imps')
@@ -183,8 +206,8 @@ resolveImport currentModule importModule exps imps impQual =
183 return imps'
206 return imps'
185 -- Check that a 'DeclarationRef' refers to an importable symbol
208 -- Check that a 'DeclarationRef' refers to an importable symbol
186− checkRefs :: [DeclarationRef] -> m ()
209+ checkRefs :: Bool -> [DeclarationRef] -> m ()
187− checkRefs = traverse_ check
210+ checkRefs isHiding = traverse_ check
189 check (PositionedDeclarationRef pos _ r) =
212 check (PositionedDeclarationRef pos _ r) =
190 rethrowWithPosition pos $ check r
213 rethrowWithPosition pos $ check r
@@ -196,9 +219,9 @@ resolveImport currentModule importModule exps imps impQual =
196 maybe (return ()) (traverse_ $ checkDctorExists name allDctors) dctors
219 maybe (return ()) (traverse_ $ checkDctorExists name allDctors) dctors
197 check (TypeClassRef name) =
220 check (TypeClassRef name) =
198 checkImportExists UnknownImportTypeClass (fst `map` exportedTypeClasses exps) name
221 checkImportExists UnknownImportTypeClass (fst `map` exportedTypeClasses exps) name
199− --check (ModuleRef name) =
222+ check (ModuleRef name) | isHiding =
200− -- checkImportExists (const UnknownModule) (exportedModules exps) name
223+ throwError . errorMessage $ ImportHidingModule name
201− check _ = internalError "Invalid argument to checkRefs"
224+ check r = internalError $ "Invalid argument to checkRefs: " ++ show r
203 -- Check that an explicitly imported item exists in the module it is being imported from
226 -- Check that an explicitly imported item exists in the module it is being imported from
204 checkImportExists :: (Eq a) => (ModuleName -> a -> SimpleErrorMessage) -> [a] -> a -> m ()
227 checkImportExists :: (Eq a) => (ModuleName -> a -> SimpleErrorMessage) -> [a] -> a -> m ()
@@ -264,11 +287,13 @@ resolveImport currentModule importModule exps imps impQual =
264 Just ((_, dctors), mn) -> map (, mn) dctors
287 Just ((_, dctors), mn) -> map (, mn) dctors
266 -- Add something to the Imports if it does not already exist there
289 -- Add something to the Imports if it does not already exist there
267− updateImports :: (Ord a) => M.Map (Qualified a) (Qualified a, ModuleName)
292+ => M.Map (Qualified a) (Qualified a, ModuleName)
268− -> (a -> String)
293+ -> (a -> String)
269− -> [(a, ModuleName)]
294+ -> [(a, ModuleName)]
271− -> m (M.Map (Qualified a) (Qualified a, ModuleName))
296+ -> m (M.Map (Qualified a) (Qualified a, ModuleName))
272 updateImports imps' render exps' name = case M.lookup (Qualified impQual name) imps' of
297 updateImports imps' render exps' name = case M.lookup (Qualified impQual name) imps' of
274 -- If the name is not already present add it to the list, after looking up
299 -- If the name is not already present add it to the list, after looking up