git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
Merge pull request #2129 from purescript/name-map

Use Map rather than list in Exports

commit2da48257f7ed842fc574087f570c54c55587243f authorGary Burgess <gary.burgess@gmail.com> dateSun 15 May 2016, 22:36 (10 years ago) parent11f4898b7a6f2b
6 files changed+160−145
src/Language/PureScript/Docs/Convert/ReExports.hs+13−6 src/Language/PureScript/Linter/Imports.hs+12−13 src/Language/PureScript/Sugar/Names.hs+27−21 src/Language/PureScript/Sugar/Names/Env.hs+41−39 src/Language/PureScript/Sugar/Names/Exports.hs+36−32 src/Language/PureScript/Sugar/Names/Imports.hs+31−34
src/Language/PureScript/Docs/Convert/ReExports.hs+13−6
@@ -4,7 +4,7 @@ module Language.PureScript.Docs.Convert.ReExports
44
55import Prelude.Compat
66
7−import Control.Arrow ((&&&), first, second)
7+import Control.Arrow ((&&&), second)
88import Control.Monad
99import Control.Monad.Reader.Class (MonadReader, ask)
1010import Control.Monad.State.Class (MonadState, gets, modify)
@@ -96,7 +96,7 @@ getReExports env mn =
9696-- * Filters type class declarations to ensure that only re-exported type
9797-- class members are listed.
9898--
99−collectDeclarations ::
99+collectDeclarations :: forall m.
100100 (MonadState (Map P.ModuleName Module) m, MonadReader P.ModuleName m) =>
101101 P.Imports ->
102102 P.Exports ->
@@ -111,13 +111,20 @@ collectDeclarations imports exports = do
111111 (vals, classes) <- handleTypeClassMembers valsAndMembers typeClasses
112112
113113 let filteredTypes = filterDataConstructors expCtors types
114− let filteredClasses = filterTypeClassMembers (map fst expVals) classes
114+ let filteredClasses = filterTypeClassMembers (Map.keys expVals) classes
115115
116116 pure (Map.toList (Map.unionsWith (<>) [filteredTypes, filteredClasses, vals, valOps, typeOps]))
117117
118118 where
119+
120+ collect
121+ :: (Eq a, Show a)
122+ => (P.ModuleName -> a -> m (P.ModuleName, [b]))
123+ -> [P.ImportRecord a]
124+ -> Map a P.ModuleName
125+ -> m (Map P.ModuleName [b])
119126 collect lookup' imps exps = do
120− imps' <- traverse (findImport imps) exps
127+ imps' <- traverse (findImport imps) $ Map.toList exps
121128 Map.fromListWith (<>) <$> traverse (uncurry lookup') imps'
122129
123130 expVals = P.exportedValues exports
@@ -126,13 +133,13 @@ collectDeclarations imports exports = do
126133 expValOps = P.exportedValueOps exports
127134 impValOps = concat (Map.elems (P.importedValueOps imports))
128135
129− expTypes = map (first fst) (P.exportedTypes exports)
136+ expTypes = Map.map snd (P.exportedTypes exports)
130137 impTypes = concat (Map.elems (P.importedTypes imports))
131138
132139 expTypeOps = P.exportedTypeOps exports
133140 impTypeOps = concat (Map.elems (P.importedTypeOps imports))
134141
135− expCtors = concatMap (snd . fst) (P.exportedTypes exports)
142+ expCtors = concatMap fst (Map.elems (P.exportedTypes exports))
136143
137144 expTCs = P.exportedTypeClasses exports
138145 impTCs = concat (Map.elems (P.importedTypeClasses imports))
src/Language/PureScript/Linter/Imports.hs+12−13
@@ -158,17 +158,17 @@ lintImports (Module ss _ mn mdecls (Just mexports)) env usedImps = do
158158 -- that are implicitly exported and then re-exported.
159159 elaborateUsed :: Imports -> ModuleName -> UsedImports -> UsedImports
160160 elaborateUsed scope mne used =
161− let classes = extractByQual mne (importedTypeClasses scope) TyClassName
162− types = extractByQual mne (importedTypes scope) TyName
163− dctors = extractByQual mne (importedDataConstructors scope) DctorName
164− values = extractByQual mne (importedValues scope) IdentName
165− in foldr go used (classes ++ types ++ dctors ++ values)
161+ foldr go used
162+ $ extractByQual mne (importedTypeClasses scope) TyClassName
163+ ++ extractByQual mne (importedTypes scope) TyName
164+ ++ extractByQual mne (importedDataConstructors scope) DctorName
165+ ++ extractByQual mne (importedValues scope) IdentName
166166 where
167167 go :: (ModuleName, Qualified Name) -> UsedImports -> UsedImports
168168 go (q, name) = M.alter (Just . maybe [name] (name :)) q
169169
170170 extractByQual
171− :: (Eq a)
171+ :: Eq a
172172 => ModuleName
173173 -> M.Map (Qualified a) [ImportRecord a]
174174 -> (a -> Name)
@@ -257,21 +257,20 @@ lintImportDecl env mni qualifierName names declType allowImplicit =
257257
258258 dtys
259259 :: ModuleName
260− -> [((ProperName 'TypeName, [ProperName 'ConstructorName]), ModuleName)]
261− dtys mn = maybe [] exportedTypes $ envModuleExports <$> mn `M.lookup` env
260+ -> M.Map (ProperName 'TypeName) ([ProperName 'ConstructorName], ModuleName)
261+ dtys mn = maybe M.empty exportedTypes $ envModuleExports <$> mn `M.lookup` env
262262
263263 dctorsForType
264264 :: ModuleName
265265 -> ProperName 'TypeName
266266 -> [ProperName 'ConstructorName]
267− dctorsForType mn tn =
268− maybe [] (snd . fst) $ find ((== tn) . fst . fst) (dtys mn)
267+ dctorsForType mn tn = maybe [] fst $ tn `M.lookup` dtys mn
269268
270269 typeForDCtor
271270 :: ModuleName
272271 -> ProperName 'ConstructorName
273272 -> Maybe (ProperName 'TypeName)
274− typeForDCtor mn pn = fst . fst <$> find (elem pn . snd . fst) (dtys mn)
273+ typeForDCtor mn pn = fst <$> find (elem pn . fst . snd) (M.toList (dtys mn))
275274
276275findUsedRefs
277276 :: Env
@@ -310,8 +309,8 @@ findUsedRefs env mni qn names =
310309 findTypeForDctor mn dctor =
311310 case mn `M.lookup` env of
312311 Just (_, _, exps) ->
313− case find (elem dctor . snd . fst) (exportedTypes exps) of
314− Just ((ty, _), _) -> ty
312+ case find (elem dctor . fst . snd) (M.toList (exportedTypes exps)) of
313+ Just (ty, _) -> ty
315314 Nothing -> internalError $ "missing type for data constructor " ++ runProperName dctor ++ " in findTypeForDctor"
316315 Nothing -> internalError $ "missing module " ++ runModuleName mn ++ " in findTypeForDctor"
317316
src/Language/PureScript/Sugar/Names.hs+27−21
@@ -10,7 +10,7 @@ module Language.PureScript.Sugar.Names
1010
1111import Prelude.Compat
1212
13−import Control.Arrow (first)
13+import Control.Arrow (first, second)
1414import Control.Monad
1515import Control.Monad.Error.Class (MonadError(..))
1616import Control.Monad.State.Lazy
@@ -72,10 +72,10 @@ desugarImportsWithEnv externs modules = do
7272 return $ M.insert efModuleName (ss, imps, exps) env
7373 where
7474
75− exportedTypes :: [((ProperName 'TypeName, [ProperName 'ConstructorName]), ModuleName)]
76− exportedTypes = mapMaybe toExportedType efExports
75+ exportedTypes :: M.Map (ProperName 'TypeName) ([ProperName 'ConstructorName], ModuleName)
76+ exportedTypes = M.fromList $ mapMaybe toExportedType efExports
7777 where
78− toExportedType (TypeRef tyCon dctors) = Just ((tyCon, fromMaybe (mapMaybe forTyCon efDeclarations) dctors), efModuleName)
78+ toExportedType (TypeRef tyCon dctors) = Just (tyCon, (fromMaybe (mapMaybe forTyCon efDeclarations) dctors, efModuleName))
7979 where
8080 forTyCon :: ExternsDeclaration -> Maybe (ProperName 'ConstructorName)
8181 forTyCon (EDDataConstructor pn _ tNm _ _) | tNm == tyCon = Just pn
@@ -83,17 +83,17 @@ desugarImportsWithEnv externs modules = do
8383 toExportedType (PositionedDeclarationRef _ _ r) = toExportedType r
8484 toExportedType _ = Nothing
8585
86− exportedTypeOps :: [(OpName 'TypeOpName, ModuleName)]
87− exportedTypeOps = (, efModuleName) <$> mapMaybe getTypeOpRef efExports
86+ exportedTypeOps :: M.Map (OpName 'TypeOpName) ModuleName
87+ exportedTypeOps = M.fromList $ (, efModuleName) <$> mapMaybe getTypeOpRef efExports
8888
89− exportedTypeClasses :: [(ProperName 'ClassName, ModuleName)]
90− exportedTypeClasses = (, efModuleName) <$> mapMaybe getTypeClassRef efExports
89+ exportedTypeClasses :: M.Map (ProperName 'ClassName) ModuleName
90+ exportedTypeClasses = M.fromList $ (, efModuleName) <$> mapMaybe getTypeClassRef efExports
9191
92− exportedValues :: [(Ident, ModuleName)]
93− exportedValues = (, efModuleName) <$> mapMaybe getValueRef efExports
92+ exportedValues :: M.Map Ident ModuleName
93+ exportedValues = M.fromList $ (, efModuleName) <$> mapMaybe getValueRef efExports
9494
95− exportedValueOps :: [(OpName 'ValueOpName, ModuleName)]
96− exportedValueOps = (, efModuleName) <$> mapMaybe getValueOpRef efExports
95+ exportedValueOps :: M.Map (OpName 'ValueOpName) ModuleName
96+ exportedValueOps = M.fromList $ (, efModuleName) <$> mapMaybe getValueOpRef efExports
9797
9898 updateEnv :: ([Module], Env) -> Module -> m ([Module], Env)
9999 updateEnv (ms, env) m@(Module ss _ mn _ refs) =
@@ -122,7 +122,7 @@ desugarImportsWithEnv externs modules = do
122122elaborateExports :: Exports -> Module -> Module
123123elaborateExports exps (Module ss coms mn decls refs) =
124124 Module ss coms mn decls $
125− Just $ map (\(ctor, dctors) -> TypeRef ctor (Just dctors)) (my exportedTypes) ++
125+ Just $ map (\(ctor, dctors) -> TypeRef ctor (Just dctors)) myTypes ++
126126 map TypeOpRef (my exportedTypeOps) ++
127127 map TypeClassRef (my exportedTypeClasses) ++
128128 map ValueRef (my exportedValues) ++
@@ -131,8 +131,14 @@ elaborateExports exps (Module ss coms mn decls refs) =
131131 where
132132 -- Extracts a list of values from the exports and filters out any values that
133133 -- are re-exports from other modules.
134− my :: (Exports -> [(a, ModuleName)]) -> [a]
135− my f = fst `map` filter ((== mn) . snd) (f exps)
134+ my :: (Exports -> M.Map a ModuleName) -> [a]
135+ my = map fst <$> filt (== mn)
136+
137+ myTypes :: [(ProperName 'TypeName, [ProperName 'ConstructorName])]
138+ myTypes = second fst <$> filt ((== mn) . snd) exportedTypes
139+
140+ filt :: (b -> Bool) -> (Exports -> M.Map a b) -> [(a, b)]
141+ filt predicate f = M.toList $ predicate `M.filter` f exps
136142
137143-- |
138144-- Replaces all local names with qualified names within a module and checks that all existing
@@ -294,26 +300,26 @@ renameInModule env imports (Module ss coms mn decls exps) =
294300
295301 -- Used when performing an update to qualify values and classes with their
296302 -- module of original definition.
297− resolve :: (Eq a) => [(a, ModuleName)] -> a -> Maybe (Qualified a)
298− resolve as name = mkQualified name <$> name `lookup` as
303+ resolve :: Ord a => M.Map a ModuleName -> a -> Maybe (Qualified a)
304+ resolve as name = mkQualified name <$> name `M.lookup` as
299305
300306 -- Used when performing an update to qualify types with their module of
301307 -- original definition.
302308 resolveType
303− :: [((ProperName 'TypeName, [ProperName 'ConstructorName]), ModuleName)]
309+ :: M.Map (ProperName 'TypeName) ([ProperName 'ConstructorName], ModuleName)
304310 -> ProperName 'TypeName
305311 -> Maybe (Qualified (ProperName 'TypeName))
306312 resolveType tys name =
307− mkQualified name . snd <$> find ((== name) . fst . fst) tys
313+ mkQualified name . snd <$> M.lookup name tys
308314
309315 -- Used when performing an update to qualify data constructors with their
310316 -- module of original definition.
311317 resolveDctor
312− :: [((ProperName 'TypeName, [ProperName 'ConstructorName]), ModuleName)]
318+ :: M.Map (ProperName 'TypeName) ([ProperName 'ConstructorName], ModuleName)
313319 -> ProperName 'ConstructorName
314320 -> Maybe (Qualified (ProperName 'ConstructorName))
315321 resolveDctor tys name =
316− mkQualified name . snd <$> find (elem name . snd . fst) tys
322+ mkQualified name . snd <$> find (elem name . fst) tys
317323
318324 -- Update names so unqualified references become qualified, and locally
319325 -- qualified references are replaced with their canoncial qualified names
src/Language/PureScript/Sugar/Names/Env.hs+41−39
@@ -26,7 +26,7 @@ import Control.Monad.Error.Class (MonadError(..))
2626import Control.Monad.Writer.Class (MonadWriter(..))
2727
2828import Data.Function (on)
29−import Data.List (groupBy, sortBy, nub, delete)
29+import Data.List (groupBy, sortBy, delete)
3030import Data.Maybe (fromJust, mapMaybe)
3131import qualified Data.Map as M
3232import qualified Data.Set as S
@@ -92,7 +92,9 @@ data Imports = Imports
9292 --
9393 , importedValueOps :: ImportMap (OpName 'ValueOpName)
9494 -- |
95− -- The modules that have been imported into the current scope.
95+ -- The name of modules that have been imported into the current scope that
96+ -- can be re-exported. If a module is imported with `as` qualification, the
97+ -- `as` name appears here, otherwise the original name.
9698 --
9799 , importedModules :: S.Set ModuleName
98100 -- |
@@ -114,37 +116,34 @@ nullImports = Imports M.empty M.empty M.empty M.empty M.empty M.empty S.empty S.
114116data Exports = Exports
115117 {
116118 -- |
117− -- The types exported from each module along with the module they originally
118− -- came from.
119+ -- The exported types along with the module they originally came from.
119120 --
120− exportedTypes :: [((ProperName 'TypeName, [ProperName 'ConstructorName]), ModuleName)]
121+ exportedTypes :: M.Map (ProperName 'TypeName) ([ProperName 'ConstructorName], ModuleName)
121122 -- |
122− -- The type operators exported from each module along with the module they
123− -- originally came from.
123+ -- The exported type operators along with the module they originally came
124+ -- from.
124125 --
125− , exportedTypeOps :: [(OpName 'TypeOpName, ModuleName)]
126+ , exportedTypeOps :: M.Map (OpName 'TypeOpName) ModuleName
126127 -- |
127− -- The classes exported from each module along with the module they originally
128− -- came from.
128+ -- The exported classes along with the module they originally came from.
129129 --
130− , exportedTypeClasses :: [(ProperName 'ClassName, ModuleName)]
130+ , exportedTypeClasses :: M.Map (ProperName 'ClassName) ModuleName
131131 -- |
132− -- The values exported from each module along with the module they originally
133− -- came from.
132+ -- The exported values along with the module they originally came from.
134133 --
135− , exportedValues :: [(Ident, ModuleName)]
134+ , exportedValues :: M.Map Ident ModuleName
136135 -- |
137− -- The value operators exported from each module along with the module they
138− -- originally came from.
136+ -- The exported value operators along with the module they originally came
137+ -- from.
139138 --
140− , exportedValueOps :: [(OpName 'ValueOpName, ModuleName)]
139+ , exportedValueOps :: M.Map (OpName 'ValueOpName) ModuleName
141140 } deriving (Show, Read)
142141
143142-- |
144143-- An empty 'Exports' value.
145144--
146145nullExports :: Exports
147−nullExports = Exports [] [] [] [] []
146+nullExports = Exports M.empty M.empty M.empty M.empty M.empty
148147
149148-- |
150149-- The imports and exports for a collection of modules. The 'SourceSpan' is used
@@ -177,11 +176,11 @@ envModuleExports (_, _, exps) = exps
177176primExports :: Exports
178177primExports =
179178 nullExports
180− { exportedTypes = mkTypeEntry `map` M.keys primTypes
181− , exportedTypeClasses = mkClassEntry `map` M.keys primClasses
179+ { exportedTypes = M.fromList $ mkTypeEntry `map` M.keys primTypes
180+ , exportedTypeClasses = M.fromList $ mkClassEntry `map` M.keys primClasses
182181 }
183182 where
184− mkTypeEntry (Qualified mn name) = ((name, []), fromJust mn)
183+ mkTypeEntry (Qualified mn name) = (name, ([], fromJust mn))
185184 mkClassEntry (Qualified mn name) = (name, fromJust mn)
186185
187186-- | Environment which only contains the Prim module.
@@ -202,20 +201,21 @@ exportType
202201 -> ModuleName
203202 -> m Exports
204203exportType exps name dctors mn = do
205− let exTypes' = exportedTypes exps
206− let exTypes = filter ((/= mn) . snd) exTypes'
207− let exDctors = (snd . fst) `concatMap` exTypes
204+ let exTypes = exportedTypes exps
208205 let exClasses = exportedTypeClasses exps
209− when (any ((== name) . fst . fst) exTypes) $
210− throwConflictError ConflictingTypeDecls name
211− when (any ((== coerceProperName name) . fst) exClasses) $
206+ case name `M.lookup` exTypes of
207+ Just (_, mn') | mn /= mn' -> throwConflictError ConflictingTypeDecls name
208+ _ -> return ()
209+ when (coerceProperName name `M.member` exClasses) $
212210 throwConflictError TypeConflictsWithClass name
213211 forM_ dctors $ \dctor -> do
214− when (dctor `elem` exDctors) $
212+ when (dctorExists (coerceProperName dctor) `any` exTypes) $
215213 throwConflictError ConflictingCtorDecls dctor
216− when (any ((== coerceProperName dctor) . fst) exClasses) $
214+ when (coerceProperName dctor `M.member` exClasses) $
217215 throwConflictError CtorConflictsWithClass dctor
218− return $ exps { exportedTypes = nub $ ((name, dctors), mn) : exTypes' }
216+ return $ exps { exportedTypes = M.insert name (dctors, mn) exTypes }
217+ where
218+ dctorExists dctor (dctors', mn') = mn /= mn' && elem dctor dctors'
219219
220220-- |
221221-- Safely adds a type operator to some exports, returning an error if a
@@ -242,10 +242,9 @@ exportTypeClass
242242 -> m Exports
243243exportTypeClass exps name mn = do
244244 let exTypes = exportedTypes exps
245− let exDctors = (snd . fst) `concatMap` exTypes
246− when (any ((== coerceProperName name) . fst . fst) exTypes) $
245+ when (coerceProperName name `M.member` exTypes) $
247246 throwConflictError ClassConflictsWithType name
248− when (coerceProperName name `elem` exDctors) $
247+ when ((elem (coerceProperName name) . fst) `any` exTypes) $
249248 throwConflictError ClassConflictsWithCtor name
250249 classes <- addExport DuplicateClassExport name mn (exportedTypeClasses exps)
251250 return $ exps { exportedTypeClasses = classes }
@@ -282,16 +281,19 @@ exportValueOp exps op mn = do
282281-- case an error is returned.
283282--
284283addExport
285− :: (MonadError MultipleErrors m, Eq a)
284+ :: (MonadError MultipleErrors m, Ord a)
286285 => (a -> SimpleErrorMessage)
287286 -> a
288287 -> ModuleName
289− -> [(a, ModuleName)]
290− -> m [(a, ModuleName)]
288+ -> M.Map a ModuleName
289+ -> m (M.Map a ModuleName)
291290addExport what name mn exports =
292− if any (\(name', mn') -> name == name' && mn /= mn') exports
293− then throwConflictError what name
294− else return $ nub $ (name, mn) : exports
291+ case M.lookup name exports of
292+ Just mn'
293+ | mn == mn' -> return exports
294+ | otherwise -> throwConflictError what name
295+ Nothing ->
296+ return $ M.insert name mn exports
295297
296298-- |
297299-- Raises an error for when there is more than one definition for something.
src/Language/PureScript/Sugar/Names/Exports.hs+36−32
@@ -10,7 +10,7 @@ import Control.Monad.Writer.Class (MonadWriter(..))
1010import Control.Monad.Error.Class (MonadError(..))
1111
1212import Data.Foldable (traverse_)
13−import Data.List (find, intersect)
13+import Data.List (intersect)
1414import Data.Maybe (fromMaybe, mapMaybe)
1515import qualified Data.Map as M
1616
@@ -76,11 +76,11 @@ resolveExports env ss mn imps exps refs =
7676 elaborateModuleExports result (PositionedDeclarationRef pos _ r) =
7777 warnAndRethrowWithPosition pos $ elaborateModuleExports result r
7878 elaborateModuleExports result (ModuleRef name) | name == mn = do
79− let types' = exportedTypes result ++ exportedTypes exps
80− let typeOps' = exportedTypeOps result ++ exportedTypeOps exps
81− let classes' = exportedTypeClasses result ++ exportedTypeClasses exps
82− let values' = exportedValues result ++ exportedValues exps
83− let valueOps' = exportedValueOps result ++ exportedValueOps exps
79+ let types' = exportedTypes result `M.union` exportedTypes exps
80+ let typeOps' = exportedTypeOps result `M.union` exportedTypeOps exps
81+ let classes' = exportedTypeClasses result `M.union` exportedTypeClasses exps
82+ let values' = exportedValues result `M.union` exportedValues exps
83+ let valueOps' = exportedValueOps result `M.union` exportedValueOps exps
8484 return result
8585 { exportedTypes = types'
8686 , exportedTypeOps = typeOps'
@@ -155,11 +155,12 @@ resolveExports env ss mn imps exps refs =
155155 go
156156 :: Qualified (ProperName 'TypeName)
157157 -> ((ProperName 'TypeName, [ProperName 'ConstructorName]), ModuleName)
158− go (Qualified (Just mn'') name) = fromMaybe (internalError "Missing value in resolveTypeExports") $ do
159− exps' <- envModuleExports <$> mn'' `M.lookup` env
160− ((_, dctors'), mnOrig) <- find (\((name', _), _) -> name == name') (exportedTypes exps')
161− let relevantDctors = mapMaybe (\(Qualified mn''' dctor) -> if mn''' == Just mn'' then Just dctor else Nothing) dctors
162− return ((name, relevantDctors `intersect` dctors'), mnOrig)
158+ go (Qualified (Just mn'') name) =
159+ fromMaybe (internalError "Missing value in resolveTypeExports") $ do
160+ exps' <- envModuleExports <$> mn'' `M.lookup` env
161+ (dctors', mnOrig) <- name `M.lookup` exportedTypes exps'
162+ let relevantDctors = mapMaybe (disqualifyFor (Just mn'')) dctors
163+ return ((name, relevantDctors `intersect` dctors'), mnOrig)
163164 go (Qualified Nothing _) = internalError "Unqualified value in resolveTypeExports"
164165
165166 -- Looks up an imported type operator and re-qualifies it with the original
@@ -194,10 +195,14 @@ resolveExports env ss mn imps exps refs =
194195 . fromMaybe (internalError "Missing value in resolveValueOp")
195196 $ resolve exportedValueOps op
196197
197− resolve :: (Eq a) => (Exports -> [(a, ModuleName)]) -> Qualified a -> Maybe (Qualified a)
198+ resolve
199+ :: Ord a
200+ => (Exports -> M.Map a ModuleName)
201+ -> Qualified a
202+ -> Maybe (Qualified a)
198203 resolve f (Qualified (Just mn'') a) = do
199204 exps' <- envModuleExports <$> mn'' `M.lookup` env
200− mn''' <- snd <$> find ((== a) . fst) (f exps')
205+ mn''' <- a `M.lookup` f exps'
201206 return $ Qualified (Just mn''') a
202207 resolve _ _ = internalError "Unqualified value in resolve"
203208
@@ -219,11 +224,11 @@ filterModule
219224 -> [DeclarationRef]
220225 -> m Exports
221226filterModule mn exps refs = do
222− types <- foldM filterTypes [] refs
223− typeOps <- foldM (filterExport TyOpName getTypeOpRef exportedTypeOps) [] refs
224− classes <- foldM (filterExport TyClassName getTypeClassRef exportedTypeClasses) [] refs
225− values <- foldM (filterExport IdentName getValueRef exportedValues) [] refs
226− valueOps <- foldM (filterExport ValOpName getValueOpRef exportedValueOps) [] refs
227+ types <- foldM filterTypes M.empty refs
228+ typeOps <- foldM (filterExport TyOpName getTypeOpRef exportedTypeOps) M.empty refs
229+ classes <- foldM (filterExport TyClassName getTypeClassRef exportedTypeClasses) M.empty refs
230+ values <- foldM (filterExport IdentName getValueRef exportedValues) M.empty refs
231+ valueOps <- foldM (filterExport ValOpName getValueOpRef exportedValueOps) M.empty refs
227232 return Exports
228233 { exportedTypes = types
229234 , exportedTypeOps = typeOps
@@ -235,21 +240,19 @@ filterModule mn exps refs = do
235240 where
236241
237242 filterTypes
238− :: [((ProperName 'TypeName, [ProperName 'ConstructorName]), ModuleName)]
243+ :: M.Map (ProperName 'TypeName) ([ProperName 'ConstructorName], ModuleName)
239244 -> DeclarationRef
240− -> m [((ProperName 'TypeName, [ProperName 'ConstructorName]), ModuleName)]
245+ -> m (M.Map (ProperName 'TypeName) ([ProperName 'ConstructorName], ModuleName))
241246 filterTypes result (PositionedDeclarationRef pos _ r) =
242247 rethrowWithPosition pos $ filterTypes result r
243248 filterTypes result (TypeRef name expDcons) =
244− case matchType `find` exportedTypes exps of
249+ case name `M.lookup` exportedTypes exps of
245250 Nothing -> throwError . errorMessage . UnknownExport $ TyName name
246− Just ((_, dcons), _) -> do
251+ Just (dcons, _) -> do
247252 let expDcons' = fromMaybe dcons expDcons
248253 traverse_ (checkDcon name dcons) expDcons'
249− return $ ((name, expDcons'), mn) : result
254+ return $ M.insert name (expDcons', mn) result
250255 where
251− -- Finds a type declaration by matching its name and defining module
252− matchType ((name', _), mn') = name == name' && mn == mn'
253256 -- Ensures a data constructor is exportable for a given type. Takes a type
254257 -- name, a list of exportable data constructors for the type, and the name of
255258 -- the data constructor to check.
@@ -264,18 +267,19 @@ filterModule mn exps refs = do
264267 filterTypes result _ = return result
265268
266269 filterExport
267− :: Eq a
270+ :: Ord a
268271 => (a -> Name)
269272 -> (DeclarationRef -> Maybe a)
270− -> (Exports -> [(a, ModuleName)])
271− -> [(a, ModuleName)]
273+ -> (Exports -> M.Map a ModuleName)
274+ -> M.Map a ModuleName
272275 -> DeclarationRef
273− -> m [(a, ModuleName)]
276+ -> m (M.Map a ModuleName)
274277 filterExport toName get fromExps result (PositionedDeclarationRef pos _ r) =
275278 rethrowWithPosition pos $ filterExport toName get fromExps result r
276279 filterExport toName get fromExps result ref
277280 | Just name <- get ref =
278− if (name, mn) `elem` fromExps exps
279− then return $ (name, mn) : result
280− else throwError . errorMessage . UnknownExport $ toName name
281+ case name `M.lookup` fromExps exps of
282+ -- TODO: I'm not sure if we actually need to check mn == mn' here -gb
283+ Just mn' | mn == mn' -> return $ M.insert name mn result
284+ _ -> throwError . errorMessage . UnknownExport $ toName name
281285 filterExport _ _ _ result _ = return result
src/Language/PureScript/Sugar/Names/Imports.hs+31−34
@@ -7,12 +7,10 @@ module Language.PureScript.Sugar.Names.Imports
77
88import Prelude.Compat
99
10−import Control.Arrow (first)
1110import Control.Monad
1211import Control.Monad.Error.Class (MonadError(..))
1312
1413import Data.Foldable (for_, traverse_)
15−import Data.List (find)
1614import Data.Maybe (fromMaybe)
1715import qualified Data.Map as M
1816import qualified Data.Set as S
@@ -118,30 +116,30 @@ resolveImport importModule exps imps impQual = resolveByType
118116 check (PositionedDeclarationRef pos _ r) =
119117 rethrowWithPosition pos $ check r
120118 check (ValueRef name) =
121− checkImportExists IdentName (fst `map` exportedValues exps) name
119+ checkImportExists IdentName (exportedValues exps) name
122120 check (ValueOpRef op) =
123− checkImportExists ValOpName (fst `map` exportedValueOps exps) op
121+ checkImportExists ValOpName (exportedValueOps exps) op
124122 check (TypeRef name dctors) = do
125− checkImportExists TyName ((fst . fst) `map` exportedTypes exps) name
126− let allDctors = fst `map` allExportedDataConstructors name
123+ checkImportExists TyName (exportedTypes exps) name
124+ let (allDctors, _) = allExportedDataConstructors name
127125 for_ dctors $ traverse_ (checkDctorExists name allDctors)
128126 check (TypeOpRef name) =
129− checkImportExists TyOpName (fst `map` exportedTypeOps exps) name
127+ checkImportExists TyOpName (exportedTypeOps exps) name
130128 check (TypeClassRef name) =
131− checkImportExists TyClassName (fst `map` exportedTypeClasses exps) name
129+ checkImportExists TyClassName (exportedTypeClasses exps) name
132130 check (ModuleRef name) | isHiding =
133131 throwError . errorMessage $ ImportHidingModule name
134132 check r = internalError $ "Invalid argument to checkRefs: " ++ show r
135133
136134 -- Check that an explicitly imported item exists in the module it is being imported from
137135 checkImportExists
138− :: Eq a
136+ :: Ord a
139137 => (a -> Name)
140− -> [a]
138+ -> M.Map a b
141139 -> a
142140 -> m ()
143141 checkImportExists toName exports item
144− = when (item `notElem` exports)
142+ = when (item `M.notMember` exports)
145143 . throwError . errorMessage
146144 $ UnknownImport importModule (toName item)
147145
@@ -177,35 +175,34 @@ resolveImport importModule exps imps impQual = resolveByType
177175 -- Import all symbols
178176 importAll :: (Imports -> DeclarationRef -> m Imports) -> m Imports
179177 importAll importer =
180− foldM (\m ((name, dctors), _) -> importer m (TypeRef name (Just dctors))) imps (exportedTypes exps)
181− >>= flip (foldM (\m (name, _) -> importer m (TypeOpRef name))) (exportedTypeOps exps)
182− >>= flip (foldM (\m (name, _) -> importer m (ValueRef name))) (exportedValues exps)
183− >>= flip (foldM (\m (name, _) -> importer m (ValueOpRef name))) (exportedValueOps exps)
184− >>= flip (foldM (\m (name, _) -> importer m (TypeClassRef name))) (exportedTypeClasses exps)
178+ foldM (\m (name, (dctors, _)) -> importer m (TypeRef name (Just dctors))) imps (M.toList (exportedTypes exps))
179+ >>= flip (foldM (\m (name, _) -> importer m (TypeOpRef name))) (M.toList (exportedTypeOps exps))
180+ >>= flip (foldM (\m (name, _) -> importer m (ValueRef name))) (M.toList (exportedValues exps))
181+ >>= flip (foldM (\m (name, _) -> importer m (ValueOpRef name))) (M.toList (exportedValueOps exps))
182+ >>= flip (foldM (\m (name, _) -> importer m (TypeClassRef name))) (M.toList (exportedTypeClasses exps))
185183
186184 importRef :: ImportProvenance -> Imports -> DeclarationRef -> m Imports
187185 importRef prov imp (PositionedDeclarationRef pos _ r) =
188186 rethrowWithPosition pos $ importRef prov imp r
189187 importRef prov imp (ValueRef name) = do
190− let values' = updateImports (importedValues imp) (exportedValues exps) name prov
188+ let values' = updateImports (importedValues imp) (exportedValues exps) id name prov
191189 return $ imp { importedValues = values' }
192190 importRef prov imp (ValueOpRef name) = do
193− let valueOps' = updateImports (importedValueOps imp) (exportedValueOps exps) name prov
191+ let valueOps' = updateImports (importedValueOps imp) (exportedValueOps exps) id name prov
194192 return $ imp { importedValueOps = valueOps' }
195193 importRef prov imp (TypeRef name dctors) = do
196− let types' = updateImports (importedTypes imp) (first fst `map` exportedTypes exps) name prov
197− let exportedDctors :: [(ProperName 'ConstructorName, ModuleName)]
198− exportedDctors = allExportedDataConstructors name
199− dctorNames :: [ProperName 'ConstructorName]
200− dctorNames = fst `map` exportedDctors
201− maybe (return ()) (traverse_ $ checkDctorExists name dctorNames) dctors
202− let dctors' = foldl (\m d -> updateImports m exportedDctors d prov) (importedDataConstructors imp) (fromMaybe dctorNames dctors)
194+ let types' = updateImports (importedTypes imp) (exportedTypes exps) snd name prov
195+ let (dctorNames, mn) = allExportedDataConstructors name
196+ dctorLookup :: M.Map (ProperName 'ConstructorName) ModuleName
197+ dctorLookup = M.fromList $ map (, mn) dctorNames
198+ traverse_ (traverse_ $ checkDctorExists name dctorNames) dctors
199+ let dctors' = foldl (\m d -> updateImports m dctorLookup id d prov) (importedDataConstructors imp) (fromMaybe dctorNames dctors)
203200 return $ imp { importedTypes = types', importedDataConstructors = dctors' }
204201 importRef prov imp (TypeOpRef name) = do
205− let ops' = updateImports (importedTypeOps imp) (exportedTypeOps exps) name prov
202+ let ops' = updateImports (importedTypeOps imp) (exportedTypeOps exps) id name prov
206203 return $ imp { importedTypeOps = ops' }
207204 importRef prov imp (TypeClassRef name) = do
208− let typeClasses' = updateImports (importedTypeClasses imp) (exportedTypeClasses exps) name prov
205+ let typeClasses' = updateImports (importedTypeClasses imp) (exportedTypeClasses exps) id name prov
209206 return $ imp { importedTypeClasses = typeClasses' }
210207 importRef _ _ TypeInstanceRef{} = internalError "TypeInstanceRef in importRef"
211208 importRef _ _ ModuleRef{} = internalError "ModuleRef in importRef"
@@ -213,23 +210,23 @@ resolveImport importModule exps imps impQual = resolveByType
213210 -- Find all exported data constructors for a given type
214211 allExportedDataConstructors
215212 :: ProperName 'TypeName
216− -> [(ProperName 'ConstructorName, ModuleName)]
213+ -> ([ProperName 'ConstructorName], ModuleName)
217214 allExportedDataConstructors name =
218− case find ((== name) . fst . fst) (exportedTypes exps) of
219− Nothing -> internalError "Invalid state in allExportedDataConstructors"
220− Just ((_, dctors), mn) -> map (, mn) dctors
215+ fromMaybe (internalError "Invalid state in allExportedDataConstructors")
216+ $ name `M.lookup` exportedTypes exps
221217
222218 -- Add something to an import resolution list
223219 updateImports
224220 :: (Ord a)
225221 => M.Map (Qualified a) [ImportRecord a]
226− -> [(a, ModuleName)]
222+ -> M.Map a b
223+ -> (b -> ModuleName)
227224 -> a
228225 -> ImportProvenance
229226 -> M.Map (Qualified a) [ImportRecord a]
230− updateImports imps' exps' name prov =
227+ updateImports imps' exps' expName name prov =
231228 let
232− mnOrig = fromMaybe (internalError "Invalid state in updateImports") (name `lookup` exps')
229+ mnOrig = maybe (internalError "Invalid state in updateImports") expName (name `M.lookup` exps')
233230 rec = ImportRecord (Qualified (Just importModule) name) mnOrig prov
234231 in
235232 M.alter