@@ -1,16 +1,3 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Sugar.Names.Imports
4−-- License : MIT (http://opensource.org/licenses/MIT)
5−--
6−-- Maintainer : Phil Freeman <paf31@cantab.net>, Gary Burgess <gary.burgess@gmail.com>
7−-- Stability : experimental
8−-- Portability :
9−--
10−-- |
11−--
12−-----------------------------------------------------------------------------
13−
141{-# LANGUAGE FlexibleContexts #-}
152{-# LANGUAGE ScopedTypeVariables #-}
163{-# LANGUAGE TupleSections #-}
@@ -47,34 +34,36 @@ import Language.PureScript.Sugar.Names.Env
4734-- Finds the imports within a module, mapping the imported module name to an optional set of
4835-- explicitly imported declarations.
4936--
50−findImports :: forall m. (Applicative m, MonadError MultipleErrors m, MonadWriter MultipleErrors m) => [Declaration] -> m (M.Map ModuleName [(Maybe SourceSpan, ImportDeclarationType, Maybe ModuleName)])
37+findImports
38+ :: forall m
39+ . (Applicative m, MonadError MultipleErrors m, MonadWriter MultipleErrors m)
40+ => [Declaration]
41+ -> m (M.Map ModuleName [(Maybe SourceSpan, ImportDeclarationType, Maybe ModuleName)])
5142findImports = foldM (go Nothing) M.empty
5243 where
5344 go pos result (ImportDeclaration mn typ qual isOldSyntax) = do
5445 when isOldSyntax . tell . errorMessage $ DeprecatedQualifiedSyntax mn (fromJust qual)
55− checkImportRefType typ
5646 let imp = (pos, typ, qual)
5747 return $ M.insert mn (maybe [imp] (imp :) (mn `M.lookup` result)) result
5848 go _ result (PositionedDeclaration pos _ d) = warnAndRethrowWithPosition pos $ go (Just pos) result d
5949 go _ result _ = return result
6050
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 ()
68−
6951type ImportDef = (Maybe SourceSpan, ImportDeclarationType, Maybe ModuleName)
7052
7153-- |
7254-- Constructs a set of imports for a module.
7355--
74−resolveImports :: forall m. (Applicative m, MonadError MultipleErrors m, MonadWriter MultipleErrors m) => Env -> Module -> m Imports
75−resolveImports env (Module _ _ currentModule decls _) =
56+resolveImports
57+ :: forall m
58+ . (Applicative m, MonadError MultipleErrors m, MonadWriter MultipleErrors m)
59+ => Env
60+ -> Module
61+ -> m (Module, Imports)
62+resolveImports env (Module ss coms currentModule decls exps) =
7663 warnAndRethrow (addHint (ErrorInModule currentModule)) $ do
77− imports <- findImports decls
64+
65+ decls' <- traverse updateImportRef decls
66+ imports <- findImports decls'
7867
7968 for_ (M.toList imports) $ \(mn, imps) -> do
8069
@@ -110,7 +99,8 @@ resolveImports env (Module _ _ currentModule decls _) =
11099 return ()
111100
112101 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)
114104
115105 where
116106 selfCartesianSubset :: [a] -> [(a, a)]
@@ -142,12 +132,38 @@ resolveImports env (Module _ _ currentModule decls _) =
142132 warn :: Maybe SourceSpan -> SimpleErrorMessage -> m ()
143133 warn pos msg = maybe id warnWithPosition pos $ tell . errorMessage $ msg
144134
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
140+ typ' <- case typ of
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
146+
147+ updateProperRef :: ModuleName -> Exports -> DeclarationRef -> m DeclarationRef
148+ updateProperRef importModule modExports (ProperRef name) =
149+ if name `elem` (fst `map` exportedTypeClasses modExports)
150+ then do
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
157+
145158-- | Constructs a set of imports for a single module import.
146−resolveModuleImport ::
147− forall m. (Applicative m, MonadError MultipleErrors m, MonadWriter MultipleErrors m) =>
148− ModuleName -> Env -> Imports ->
149− (ModuleName, [(Maybe SourceSpan, ImportDeclarationType, Maybe ModuleName)]) ->
150− m Imports
159+resolveModuleImport
160+ :: forall m
161+ . (Applicative m, MonadError MultipleErrors m, MonadWriter MultipleErrors m)
162+ => ModuleName
163+ -> Env
164+ -> Imports
165+ -> (ModuleName, [(Maybe SourceSpan, ImportDeclarationType, Maybe ModuleName)])
166+ -> m Imports
151167resolveModuleImport currentModule env ie (mn, imps) = foldM go ie imps
152168 where
153169 go :: Imports -> (Maybe SourceSpan, ImportDeclarationType, Maybe ModuleName) -> m Imports
@@ -163,17 +179,24 @@ resolveModuleImport currentModule env ie (mn, imps) = foldM go ie imps
163179-- |
164180-- Extends the local environment for a module by resolving an import of another module.
165181--
166−resolveImport :: forall m. (Applicative m, MonadError MultipleErrors m, MonadWriter MultipleErrors m) => ModuleName -> ModuleName -> Exports -> Imports -> Maybe ModuleName -> ImportDeclarationType -> m Imports
167−resolveImport currentModule importModule exps imps impQual =
168− resolveByType
182+resolveImport
183+ :: forall m
184+ . (Applicative m, MonadError MultipleErrors m, MonadWriter MultipleErrors m)
185+ => ModuleName
186+ -> ModuleName
187+ -> Exports
188+ -> Imports
189+ -> Maybe ModuleName
190+ -> ImportDeclarationType
191+ -> m Imports
192+resolveImport currentModule importModule exps imps impQual = resolveByType
169193 where
170194
171195 resolveByType :: ImportDeclarationType -> m Imports
172196 resolveByType Implicit = importAll importExplicit
173− resolveByType (Explicit explImports) = checkRefs explImports >> foldM importExplicit imps explImports
174− resolveByType (Hiding hiddenImports) = do
175− checkRefs hiddenImports
176− imps' <- importAll (importNonHidden hiddenImports)
197+ resolveByType (Explicit refs) = checkRefs False refs >> foldM importExplicit imps refs
198+ resolveByType (Hiding refs) = do
199+ imps' <- checkRefs True refs >> importAll (importNonHidden refs)
177200 let isEmptyImport
178201 = M.null (importedTypes imps')
179202 && M.null (importedDataConstructors imps')
@@ -183,8 +206,8 @@ resolveImport currentModule importModule exps imps impQual =
183206 return imps'
184207
185208 -- Check that a 'DeclarationRef' refers to an importable symbol
186− checkRefs :: [DeclarationRef] -> m ()
187− checkRefs = traverse_ check
209+ checkRefs :: Bool -> [DeclarationRef] -> m ()
210+ checkRefs isHiding = traverse_ check
188211 where
189212 check (PositionedDeclarationRef pos _ r) =
190213 rethrowWithPosition pos $ check r
@@ -196,9 +219,9 @@ resolveImport currentModule importModule exps imps impQual =
196219 maybe (return ()) (traverse_ $ checkDctorExists name allDctors) dctors
197220 check (TypeClassRef name) =
198221 checkImportExists UnknownImportTypeClass (fst `map` exportedTypeClasses exps) name
199− --check (ModuleRef name) =
200− -- checkImportExists (const UnknownModule) (exportedModules exps) name
201− check _ = internalError "Invalid argument to checkRefs"
222+ check (ModuleRef name) | isHiding =
223+ throwError . errorMessage $ ImportHidingModule name
224+ check r = internalError $ "Invalid argument to checkRefs: " ++ show r
202225
203226 -- Check that an explicitly imported item exists in the module it is being imported from
204227 checkImportExists :: (Eq a) => (ModuleName -> a -> SimpleErrorMessage) -> [a] -> a -> m ()
@@ -264,11 +287,13 @@ resolveImport currentModule importModule exps imps impQual =
264287 Just ((_, dctors), mn) -> map (, mn) dctors
265288
266289 -- Add something to the Imports if it does not already exist there
267− updateImports :: (Ord a) => M.Map (Qualified a) (Qualified a, ModuleName)
268− -> (a -> String)
269− -> [(a, ModuleName)]
270− -> a
271− -> m (M.Map (Qualified a) (Qualified a, ModuleName))
290+ updateImports
291+ :: (Ord a)
292+ => M.Map (Qualified a) (Qualified a, ModuleName)
293+ -> (a -> String)
294+ -> [(a, ModuleName)]
295+ -> a
296+ -> m (M.Map (Qualified a) (Qualified a, ModuleName))
272297 updateImports imps' render exps' name = case M.lookup (Qualified impQual name) imps' of
273298
274299 -- If the name is not already present add it to the list, after looking up