@@ -17,13 +17,10 @@ module Language.PureScript.Sugar.Names (
19import Data.Maybe (fromMaybe)
19import Data.Maybe (fromMaybe)
21import Data.Generics (extM, mkM, everywhereM)
20import Data.Generics (extM, mkM, everywhereM)
22import Data.Generics.Extras (mkS, extS, everywhereWithContextM')
21import Data.Generics.Extras (mkS, extS, everywhereWithContextM')
23−import Data.List (find)
25import Control.Applicative (Applicative(..), (<$>), (<*>))
23import Control.Applicative (Applicative(..), (<$>), (<*>))
26−import Control.Monad (foldM)
27import Control.Monad.Error
24import Control.Monad.Error
29import qualified Data.Map as M
26import qualified Data.Map as M
@@ -163,9 +160,9 @@ renameInModule imports exports (Module mn decls exps) =
163 updateVars (ValueDeclaration name [] Nothing val) =
160 updateVars (ValueDeclaration name [] Nothing val) =
164 ValueDeclaration name [] Nothing <$> everywhereWithContextM' [] (mkS bindFunctionArgs `extS` bindBinders) val
161 ValueDeclaration name [] Nothing <$> everywhereWithContextM' [] (mkS bindFunctionArgs `extS` bindBinders) val
166− bindFunctionArgs bound (Abs (Left arg) val) = return (arg : bound, Abs (Left arg) val)
163+ bindFunctionArgs bound (Abs (Left arg) val') = return (arg : bound, Abs (Left arg) val')
167− bindFunctionArgs bound (Var name@(Qualified Nothing ident)) | ident `notElem` bound = (,) bound <$> (Var <$> updateValueName name)
164+ bindFunctionArgs bound (Var name'@(Qualified Nothing ident)) | ident `notElem` bound = (,) bound <$> (Var <$> updateValueName name')
168− bindFunctionArgs bound (Var name@(Qualified (Just _) _)) = (,) bound <$> (Var <$> updateValueName name)
165+ bindFunctionArgs bound (Var name'@(Qualified (Just _) _)) = (,) bound <$> (Var <$> updateValueName name')
169 bindFunctionArgs bound other = return (bound, other)
166 bindFunctionArgs bound other = return (bound, other)
170 bindBinders :: [Ident] -> CaseAlternative -> Either String ([Ident], CaseAlternative)
167 bindBinders :: [Ident] -> CaseAlternative -> Either String ([Ident], CaseAlternative)
171 bindBinders bound c@(CaseAlternative bs _ _) = return (binderNames bs ++ bound, c)
168 bindBinders bound c@(CaseAlternative bs _ _) = return (binderNames bs ++ bound, c)
@@ -182,25 +179,25 @@ renameInModule imports exports (Module mn decls exps) =
182 updateConstraints = mapM (\(name, ts) -> (,) <$> updateClassName name <*> pure ts)
179 updateConstraints = mapM (\(name, ts) -> (,) <$> updateClassName name <*> pure ts)
184 updateTypeName (Qualified Nothing name) = update "type" importedTypes name
181 updateTypeName (Qualified Nothing name) = update "type" importedTypes name
185− updateTypeName (Qualified (Just mn) name) = do
182+ updateTypeName (Qualified (Just mn') name) = do
186− modExports <- getExports mn
183+ modExports <- getExports mn'
187 case name `lookup` exportedTypes modExports of
184 case name `lookup` exportedTypes modExports of
188− Nothing -> throwError $ "Unknown type '" ++ show (Qualified (Just mn) name) ++ "'"
185+ Nothing -> throwError $ "Unknown type '" ++ show (Qualified (Just mn') name) ++ "'"
189− _ -> return $ Qualified (Just mn) name
186+ _ -> return $ Qualified (Just mn') name
191 updateDataConstructorName (Qualified Nothing name) = update "data constructor" importedDataConstructors name
188 updateDataConstructorName (Qualified Nothing name) = update "data constructor" importedDataConstructors name
192− updateDataConstructorName (Qualified (Just mn) name) = do
189+ updateDataConstructorName (Qualified (Just mn') name) = do
193− modExports <- getExports mn
190+ modExports <- getExports mn'
194 let allDcons = join $ snd `map` exportedTypes modExports
191 let allDcons = join $ snd `map` exportedTypes modExports
195 if name `elem` allDcons
192 if name `elem` allDcons
196− then return $ Qualified (Just mn) name
193+ then return $ Qualified (Just mn') name
197− else throwError $ "Unknown data constructor '" ++ show (Qualified (Just mn) name) ++ "'"
194+ else throwError $ "Unknown data constructor '" ++ show (Qualified (Just mn') name) ++ "'"
199 updateClassName (Qualified Nothing name) = update "type class" importedTypeClasses name
196 updateClassName (Qualified Nothing name) = update "type class" importedTypeClasses name
200− updateClassName (Qualified (Just mn) name) = check "type class" exportedTypeClasses mn name
197+ updateClassName (Qualified (Just mn') name) = check "type class" exportedTypeClasses mn' name
202 updateValueName (Qualified Nothing name) = update "value" importedValues name
199 updateValueName (Qualified Nothing name) = update "value" importedValues name
203− updateValueName (Qualified (Just mn) name) = check "value" exportedValues mn name
200+ updateValueName (Qualified (Just mn') name) = check "value" exportedValues mn' name
205 -- Replace an unqualified name with a qualified
202 -- Replace an unqualified name with a qualified
206 update :: (Ord a, Show a) => String -> (ImportEnvironment -> M.Map a (Qualified a)) -> a -> Either String (Qualified a)
203 update :: (Ord a, Show a) => String -> (ImportEnvironment -> M.Map a (Qualified a)) -> a -> Either String (Qualified a)
@@ -208,15 +205,15 @@ renameInModule imports exports (Module mn decls exps) =
209 -- Check that a qualified name is valid
206 -- Check that a qualified name is valid
210 check :: (Show a, Eq a) => String -> (Exports -> [a]) -> ModuleName -> a -> Either String (Qualified a)
207 check :: (Show a, Eq a) => String -> (Exports -> [a]) -> ModuleName -> a -> Either String (Qualified a)
211− check t get mn name = do
208+ check t get mn' name = do
212− modExports <- getExports mn
209+ modExports <- getExports mn'
213 if name `elem` get modExports
210 if name `elem` get modExports
214− then return $ Qualified (Just mn) name
211+ then return $ Qualified (Just mn') name
215− else throwError $ "Unknown " ++ t ++ " '" ++ show (Qualified (Just mn) name) ++ "'"
212+ else throwError $ "Unknown " ++ t ++ " '" ++ show (Qualified (Just mn') name) ++ "'"
217 -- Gets the exports for a module, or an error message if the module doesn't exist
214 -- Gets the exports for a module, or an error message if the module doesn't exist
218 getExports :: ModuleName -> Either String Exports
215 getExports :: ModuleName -> Either String Exports
219− getExports mn = maybe (throwError $ "Unknown module '" ++ show mn ++ "'") return $ M.lookup mn exports
216+ getExports mn' = maybe (throwError $ "Unknown module '" ++ show mn' ++ "'") return $ M.lookup mn' exports
222-- Finds all exported declarations in a set of modules.
219-- Finds all exported declarations in a set of modules.
@@ -256,13 +253,13 @@ findExports = foldM addModule $ M.singleton (ModuleName [ProperName "Prim"]) pri
256filterExports :: ModuleName -> [DeclarationRef] -> ExportEnvironment -> Either String ExportEnvironment
253filterExports :: ModuleName -> [DeclarationRef] -> ExportEnvironment -> Either String ExportEnvironment
257filterExports mn exps env = do
254filterExports mn exps env = do
258 let moduleExports = fromMaybe (error "Module is missing") (mn `M.lookup` env)
255 let moduleExports = fromMaybe (error "Module is missing") (mn `M.lookup` env)
259− moduleExports' <- filterModule exps moduleExports
256+ moduleExports' <- filterModule moduleExports
260 return $ M.insert mn moduleExports' env
257 return $ M.insert mn moduleExports' env
263 -- Filter the exports for the specific module
260 -- Filter the exports for the specific module
264− filterModule :: [DeclarationRef] -> Exports -> Either String Exports
261+ filterModule :: Exports -> Either String Exports
265− filterModule exps exported = do
262+ filterModule exported = do
266 types <- foldM (filterTypes $ exportedTypes exported) [] exps
263 types <- foldM (filterTypes $ exportedTypes exported) [] exps
267 values <- foldM (filterValues $ exportedValues exported) [] exps
264 values <- foldM (filterValues $ exportedValues exported) [] exps
268 classes <- foldM (filterClasses $ exportedTypeClasses exported) [] exps
265 classes <- foldM (filterClasses $ exportedTypeClasses exported) [] exps
@@ -271,34 +268,34 @@ filterExports mn exps env = do
271 -- Ensure the exported types and data constructors exist in the module and add them to the set of
268 -- Ensure the exported types and data constructors exist in the module and add them to the set of
272 -- exports
269 -- exports
273 filterTypes :: [(ProperName, [ProperName])] -> [(ProperName, [ProperName])] -> DeclarationRef -> Either String [(ProperName, [ProperName])]
270 filterTypes :: [(ProperName, [ProperName])] -> [(ProperName, [ProperName])] -> DeclarationRef -> Either String [(ProperName, [ProperName])]
274− filterTypes exps result (TypeRef name expDcons) = do
271+ filterTypes expTys result (TypeRef name expDcons) = do
275− dcons <- maybe (throwError $ "Cannot export undefined type '" ++ show name ++ "'") return $ name `lookup` exps
272+ dcons <- maybe (throwError $ "Cannot export undefined type '" ++ show name ++ "'") return $ name `lookup` expTys
276 dcons' <- maybe (return dcons) (foldM (filterDcons name dcons) []) expDcons
273 dcons' <- maybe (return dcons) (foldM (filterDcons name dcons) []) expDcons
277 return $ (name, dcons') : result
274 return $ (name, dcons') : result
278− filterTypes exps result _ = return result
275+ filterTypes _ result _ = return result
280 -- Ensure the exported data constructors exists for a type and add them to the list of exports
277 -- Ensure the exported data constructors exists for a type and add them to the list of exports
281 filterDcons :: ProperName -> [ProperName] -> [ProperName] -> ProperName -> Either String [ProperName]
278 filterDcons :: ProperName -> [ProperName] -> [ProperName] -> ProperName -> Either String [ProperName]
282− filterDcons tcon exps result name =
279+ filterDcons tcon exps' result name =
283− if name `elem` exps
280+ if name `elem` exps'
284 then return $ name : result
281 then return $ name : result
285 else throwError $ "Cannot export undefined data constructor '" ++ show name ++ "' for type '" ++ show tcon ++ "'"
282 else throwError $ "Cannot export undefined data constructor '" ++ show name ++ "' for type '" ++ show tcon ++ "'"
287 -- Ensure the exported classes exist in the module and add them to the set of exports
284 -- Ensure the exported classes exist in the module and add them to the set of exports
288 filterClasses :: [ProperName] -> [ProperName] -> DeclarationRef -> Either String [ProperName]
285 filterClasses :: [ProperName] -> [ProperName] -> DeclarationRef -> Either String [ProperName]
289− filterClasses exps result (TypeClassRef name) =
286+ filterClasses exps' result (TypeClassRef name) =
290− if name `elem` exps
287+ if name `elem` exps'
291 then return $ name : result
288 then return $ name : result
292 else throwError $ "Cannot export undefined type class '" ++ show name ++ "'"
289 else throwError $ "Cannot export undefined type class '" ++ show name ++ "'"
293− filterClasses exps result _ = return result
290+ filterClasses _ result _ = return result
295 -- Ensure the exported values exist in the module and add them to the set of exports
292 -- Ensure the exported values exist in the module and add them to the set of exports
296 filterValues :: [Ident] -> [Ident] -> DeclarationRef -> Either String [Ident]
293 filterValues :: [Ident] -> [Ident] -> DeclarationRef -> Either String [Ident]
297− filterValues exps result (ValueRef name) =
294+ filterValues exps' result (ValueRef name) =
298− if name `elem` exps
295+ if name `elem` exps'
299 then return $ name : result
296 then return $ name : result
300 else throwError $ "Cannot export undefined value '" ++ show name ++ "'"
297 else throwError $ "Cannot export undefined value '" ++ show name ++ "'"
301− filterValues exps result _ = return result
298+ filterValues _ result _ = return result
304-- Type representing a set of declarations being explicitly imported from a module
301-- Type representing a set of declarations being explicitly imported from a module
@@ -333,53 +330,54 @@ resolveImports env (Module currentModule decls _) =
333-- Extends the local environment for a module by resolving an import of another module.
330-- Extends the local environment for a module by resolving an import of another module.
335resolveImport :: ModuleName -> ModuleName -> Exports -> ImportEnvironment -> Maybe ExplicitImports -> Either String ImportEnvironment
332resolveImport :: ModuleName -> ModuleName -> Exports -> ImportEnvironment -> Maybe ExplicitImports -> Either String ImportEnvironment
336−resolveImport currentModule importModule exp imp i = case i of
333+resolveImport currentModule importModule exps imps i = case i of
337− Nothing -> importAll imp
334+ Nothing -> importAll
338− (Just expl) -> foldM importExplicit imp expl
335+ Just expl -> foldM importExplicit imps expl
341 -- Import everything from a module
338 -- Import everything from a module
342− importAll :: ImportEnvironment -> Either String ImportEnvironment
339+ importAll :: Either String ImportEnvironment
343− importAll imp = do
340+ importAll = do
344− imp' <- foldM (\m (name, dctors) -> importExplicit m (TypeRef name (Just dctors))) imp (exportedTypes exp)
341+ imp' <- foldM (\m (name, dctors) -> importExplicit m (TypeRef name (Just dctors))) imps (exportedTypes exps)
345− imp'' <- foldM (\m name -> importExplicit m (ValueRef name)) imp' (exportedValues exp)
342+ imp'' <- foldM (\m name -> importExplicit m (ValueRef name)) imp' (exportedValues exps)
346− foldM (\m name -> importExplicit m (TypeClassRef name)) imp'' (exportedTypeClasses exp)
343+ foldM (\m name -> importExplicit m (TypeClassRef name)) imp'' (exportedTypeClasses exps)
348 -- Import something explicitly
345 -- Import something explicitly
349 importExplicit :: ImportEnvironment -> DeclarationRef -> Either String ImportEnvironment
346 importExplicit :: ImportEnvironment -> DeclarationRef -> Either String ImportEnvironment
350 importExplicit imp (ValueRef name) = do
347 importExplicit imp (ValueRef name) = do
351− checkImportExists "value" values name
348+ _ <- checkImportExists "value" values name
352 values' <- updateImports (importedValues imp) name
349 values' <- updateImports (importedValues imp) name
353 return $ imp { importedValues = values' }
350 return $ imp { importedValues = values' }
354 importExplicit imp (TypeRef name dctors) = do
351 importExplicit imp (TypeRef name dctors) = do
355− checkImportExists "type" types name
352+ _ <- checkImportExists "type" types name
356 types' <- updateImports (importedTypes imp) name
353 types' <- updateImports (importedTypes imp) name
357 let allDctors = allExportedDataConstructors name
354 let allDctors = allExportedDataConstructors name
358 dctors' <- maybe (return allDctors) (mapM $ checkDctorExists allDctors) dctors
355 dctors' <- maybe (return allDctors) (mapM $ checkDctorExists allDctors) dctors
359 dctors'' <- foldM updateImports (importedDataConstructors imp) dctors'
356 dctors'' <- foldM updateImports (importedDataConstructors imp) dctors'
360 return $ imp { importedTypes = types', importedDataConstructors = dctors'' }
357 return $ imp { importedTypes = types', importedDataConstructors = dctors'' }
361 importExplicit imp (TypeClassRef name) = do
358 importExplicit imp (TypeClassRef name) = do
362− checkImportExists "type class" classes name
359+ _ <- checkImportExists "type class" classes name
363 typeClasses' <- updateImports (importedTypeClasses imp) name
360 typeClasses' <- updateImports (importedTypeClasses imp) name
364 return $ imp { importedTypeClasses = typeClasses' }
361 return $ imp { importedTypeClasses = typeClasses' }
366 -- Find all exported data constructors for a given type
363 -- Find all exported data constructors for a given type
367 allExportedDataConstructors :: ProperName -> [ProperName]
364 allExportedDataConstructors :: ProperName -> [ProperName]
368− allExportedDataConstructors name = fromMaybe [] $ name `lookup` exportedTypes exp
365+ allExportedDataConstructors name = fromMaybe [] $ name `lookup` exportedTypes exps
370 -- Add something to the ImportEnvironment if it does not already exist there
367 -- Add something to the ImportEnvironment if it does not already exist there
371 updateImports :: (Ord a, Show a) => M.Map a (Qualified a) -> a -> Either String (M.Map a (Qualified a))
368 updateImports :: (Ord a, Show a) => M.Map a (Qualified a) -> a -> Either String (M.Map a (Qualified a))
372 updateImports m name = case M.lookup name m of
369 updateImports m name = case M.lookup name m of
373 Nothing -> return $ M.insert name (Qualified (Just importModule) name) m
370 Nothing -> return $ M.insert name (Qualified (Just importModule) name) m
371+ Just (Qualified Nothing _) -> error "Invalid state in updateImports"
374 Just x@(Qualified (Just mn) _) -> throwError $
372 Just x@(Qualified (Just mn) _) -> throwError $
375 if mn == currentModule || importModule == currentModule
373 if mn == currentModule || importModule == currentModule
376 then "Definition '" ++ show name ++ "' conflicts with import '" ++ show (Qualified (Just importModule) name) ++ "'"
374 then "Definition '" ++ show name ++ "' conflicts with import '" ++ show (Qualified (Just importModule) name) ++ "'"
377 else "Conflicting imports for '" ++ show name ++ "': '" ++ show x ++ "', '" ++ show (Qualified (Just importModule) name) ++ "'"
375 else "Conflicting imports for '" ++ show name ++ "': '" ++ show x ++ "', '" ++ show (Qualified (Just importModule) name) ++ "'"
379 -- The available values, types, and classes in the module being imported
377 -- The available values, types, and classes in the module being imported
380− values = exportedValues exp
378+ values = exportedValues exps
381− types = fst `map` exportedTypes exp
379+ types = fst `map` exportedTypes exps
382− classes = exportedTypeClasses exp
380+ classes = exportedTypeClasses exps
384 -- Ensure that an explicitly imported data constructor exists for the type it is being imported
382 -- Ensure that an explicitly imported data constructor exists for the type it is being imported