@@ -18,6 +18,7 @@ module Language.PureScript.Sugar.Names (
19import Data.Data
19import Data.Data
20import Data.Maybe (fromMaybe, isJust, mapMaybe)
20import Data.Maybe (fromMaybe, isJust, mapMaybe)
21+import Data.Monoid ((<>))
21import Data.Generics (extM, mkM, everywhereM)
22import Data.Generics (extM, mkM, everywhereM)
22import Data.Generics.Extras (mkS, extS, everywhereWithContextM')
23import Data.Generics.Extras (mkS, extS, everywhereWithContextM')
@@ -30,6 +31,7 @@ import Language.PureScript.Declarations
30import Language.PureScript.Names
31import Language.PureScript.Names
31import Language.PureScript.Types
32import Language.PureScript.Types
32import Language.PureScript.Environment
33import Language.PureScript.Environment
34+import Language.PureScript.Errors
35-- The global export environment - every declaration exported from every module.
37-- The global export environment - every declaration exported from every module.
@@ -80,7 +82,7 @@ data ImportEnvironment = ImportEnvironment
80-- Updates the exports for a module from the global environment. If the module was not previously
82-- Updates the exports for a module from the global environment. If the module was not previously
81-- present in the global environment, it is created.
83-- present in the global environment, it is created.
83−updateExportedModule :: ExportEnvironment -> ModuleName -> (Exports -> Either String Exports) -> Either String ExportEnvironment
85+updateExportedModule :: ExportEnvironment -> ModuleName -> (Exports -> Either ErrorStack Exports) -> Either ErrorStack ExportEnvironment
84updateExportedModule env mn update = do
86updateExportedModule env mn update = do
85 let exports = fromMaybe (error "Module was undefined in updateExportedModule") $ mn `M.lookup` env
87 let exports = fromMaybe (error "Module was undefined in updateExportedModule") $ mn `M.lookup` env
86 exports' <- update exports
88 exports' <- update exports
@@ -89,16 +91,16 @@ updateExportedModule env mn update = do
90-- Adds an empty module to an ExportEnvironment.
92-- Adds an empty module to an ExportEnvironment.
92−addEmptyModule :: ExportEnvironment -> ModuleName -> Either String ExportEnvironment
94+addEmptyModule :: ExportEnvironment -> ModuleName -> Either ErrorStack ExportEnvironment
93addEmptyModule env name =
95addEmptyModule env name =
94 if name `M.member` env
96 if name `M.member` env
95− then throwError $ "Module '" ++ show name ++ "' has been defined more than once"
97+ then throwError $ mkErrorStack ("Module '" ++ show name ++ "' has been defined more than once") Nothing
96 else return $ M.insert name (Exports [] [] []) env
98 else return $ M.insert name (Exports [] [] []) env
99-- Adds a type belonging to a module to the export environment.
101-- Adds a type belonging to a module to the export environment.
101−addType :: ExportEnvironment -> ModuleName -> ProperName -> [ProperName] -> Either String ExportEnvironment
103+addType :: ExportEnvironment -> ModuleName -> ProperName -> [ProperName] -> Either ErrorStack ExportEnvironment
102addType env mn name dctors = updateExportedModule env mn $ \m -> do
104addType env mn name dctors = updateExportedModule env mn $ \m -> do
103 types' <- addExport (exportedTypes m) (name, dctors)
105 types' <- addExport (exportedTypes m) (name, dctors)
104 return $ m { exportedTypes = types' }
106 return $ m { exportedTypes = types' }
@@ -106,7 +108,7 @@ addType env mn name dctors = updateExportedModule env mn $ \m -> do
107-- Adds a class to the export environment.
109-- Adds a class to the export environment.
109−addTypeClass :: ExportEnvironment -> ModuleName -> ProperName -> Either String ExportEnvironment
111+addTypeClass :: ExportEnvironment -> ModuleName -> ProperName -> Either ErrorStack ExportEnvironment
110addTypeClass env mn name = updateExportedModule env mn $ \m -> do
112addTypeClass env mn name = updateExportedModule env mn $ \m -> do
111 classes <- addExport (exportedTypeClasses m) name
113 classes <- addExport (exportedTypeClasses m) name
112 return $ m { exportedTypeClasses = classes }
114 return $ m { exportedTypeClasses = classes }
@@ -114,7 +116,7 @@ addTypeClass env mn name = updateExportedModule env mn $ \m -> do
115-- Adds a class to the export environment.
117-- Adds a class to the export environment.
117−addValue :: ExportEnvironment -> ModuleName -> Ident -> Either String ExportEnvironment
119+addValue :: ExportEnvironment -> ModuleName -> Ident -> Either ErrorStack ExportEnvironment
118addValue env mn name = updateExportedModule env mn $ \m -> do
120addValue env mn name = updateExportedModule env mn $ \m -> do
119 values <- addExport (exportedValues m) name
121 values <- addExport (exportedValues m) name
120 return $ m { exportedValues = values }
122 return $ m { exportedValues = values }
@@ -123,16 +125,16 @@ addValue env mn name = updateExportedModule env mn $ \m -> do
123-- Adds an entry to a list of exports unless it is already present, in which case an error is
125-- Adds an entry to a list of exports unless it is already present, in which case an error is
124-- returned.
126-- returned.
126−addExport :: (Eq a, Show a) => [a] -> a -> Either String [a]
128+addExport :: (Eq a, Show a) => [a] -> a -> Either ErrorStack [a]
127addExport exports name =
129addExport exports name =
128 if name `elem` exports
130 if name `elem` exports
129− then throwError $ "Multiple definitions for '" ++ show name ++ "'"
131+ then throwError $ mkErrorStack ("Multiple definitions for '" ++ show name ++ "'") Nothing
130 else return $ name : exports
132 else return $ name : exports
133-- Replaces all local names with qualified names within a set of modules.
135-- Replaces all local names with qualified names within a set of modules.
135−desugarImports :: [Module] -> Either String [Module]
137+desugarImports :: [Module] -> Either ErrorStack [Module]
136desugarImports modules = do
138desugarImports modules = do
137 unfilteredExports <- findExports modules
139 unfilteredExports <- findExports modules
138 exports <- foldM filterModuleExports unfilteredExports modules
140 exports <- foldM filterModuleExports unfilteredExports modules
@@ -142,30 +144,19 @@ desugarImports modules = do
142 -- Filters the exports for a module in the global exports environment so that only explicitly
144 -- Filters the exports for a module in the global exports environment so that only explicitly
143 -- exported members remain. If the module does not explicitly export anything, everything is
145 -- exported members remain. If the module does not explicitly export anything, everything is
144 -- exported.
146 -- exported.
145− filterModuleExports :: ExportEnvironment -> Module -> Either String ExportEnvironment
147+ filterModuleExports :: ExportEnvironment -> Module -> Either ErrorStack ExportEnvironment
146 filterModuleExports env (Module mn _ (Just exps)) = filterExports mn exps env
148 filterModuleExports env (Module mn _ (Just exps)) = filterExports mn exps env
147 filterModuleExports env _ = return env
149 filterModuleExports env _ = return env
149 -- Rename and check all the names within a module. We tweak the global exports environment so
151 -- Rename and check all the names within a module. We tweak the global exports environment so
150 -- the module has access to an unfiltered list of its own members.
152 -- the module has access to an unfiltered list of its own members.
151− renameInModule' :: ExportEnvironment -> ExportEnvironment -> Module -> Either String Module
153+ renameInModule' :: ExportEnvironment -> ExportEnvironment -> Module -> Either ErrorStack Module
152− renameInModule' unfilteredExports exports m@(Module mn _ _) = rethrowForModule m $ do
154+ renameInModule' unfilteredExports exports m@(Module mn _ _) =
155+ rethrow (strMsg ("Error in module " ++ show mn) <>) $ do
153− let env = M.update (\_ -> M.lookup mn unfilteredExports) mn exports
156+ let env = M.update (\_ -> M.lookup mn unfilteredExports) mn exports
154− let exps = fromMaybe (error "Module is missing in renameInModule'") $ M.lookup mn exports
157+ let exps = fromMaybe (error "Module is missing in renameInModule'") $ M.lookup mn exports
155− imports <- resolveImports env m
158+ imports <- resolveImports env m
156− renameInModule imports env (elaborateExports exps m)
159+ renameInModule imports env (elaborateExports exps m)
159−-- Rethrow an error with an extra message line prepended
161−rethrow :: String -> Either String a -> Either String a
162−rethrow msg = flip catchError $ \e -> throwError (msg ++ ":\n" ++ e)
165−-- Rethrow an error with details of the current module prepended to the message
167−rethrowForModule :: Module -> Either String a -> Either String a
168−rethrowForModule (Module mn _ _) = rethrow $ "Error in module '" ++ show mn ++ "'"
171-- Make all exports for a module explicit. This may still effect modules that have an exports list,
162-- Make all exports for a module explicit. This may still effect modules that have an exports list,
@@ -181,23 +172,27 @@ elaborateExports exps (Module mn decls _) = Module mn decls (Just $
181-- Replaces all local names with qualified names within a module and checks that all existing
172-- Replaces all local names with qualified names within a module and checks that all existing
182-- qualified names are valid.
173-- qualified names are valid.
184−renameInModule :: ImportEnvironment -> ExportEnvironment -> Module -> Either String Module
175+renameInModule :: ImportEnvironment -> ExportEnvironment -> Module -> Either ErrorStack Module
185renameInModule imports exports (Module mn decls exps) =
176renameInModule imports exports (Module mn decls exps) =
186 Module mn <$> mapM go decls <*> pure exps
177 Module mn <$> mapM go decls <*> pure exps
179+ go :: Declaration -> Either ErrorStack Declaration
188 go (DataDeclaration name args dctors) =
180 go (DataDeclaration name args dctors) =
181+ rethrow (strMsg ("Error in data declaration " ++ show name) <>) $
189− rethrowFor "data declaration" name $ DataDeclaration <$> pure name <*> pure args <*> updateAll dctors
182+ DataDeclaration <$> pure name <*> pure args <*> updateAll dctors
190 go (DataBindingGroupDeclaration decls') =
183 go (DataBindingGroupDeclaration decls') =
191 DataBindingGroupDeclaration <$> mapM go decls'
184 DataBindingGroupDeclaration <$> mapM go decls'
192 go (TypeSynonymDeclaration name ps ty) =
185 go (TypeSynonymDeclaration name ps ty) =
186+ rethrow (strMsg ("Error in type synonym " ++ show name) <>) $
193− rethrowFor "type synonym" name $ TypeSynonymDeclaration <$> pure name <*> pure ps <*> updateType' ty
187+ TypeSynonymDeclaration <$> pure name <*> pure ps <*> updateType' ty
194 go (TypeInstanceDeclaration name cs cn ts ds) =
188 go (TypeInstanceDeclaration name cs cn ts ds) =
195 TypeInstanceDeclaration name <$> updateConstraints cs <*> updateClassName cn <*> updateType' ts <*> mapM go ds
189 TypeInstanceDeclaration name <$> updateConstraints cs <*> updateClassName cn <*> updateType' ts <*> mapM go ds
196 go (ExternInstanceDeclaration name cs cn ts) =
190 go (ExternInstanceDeclaration name cs cn ts) =
197 ExternInstanceDeclaration name <$> updateConstraints cs <*> updateClassName cn <*> updateType' ts
191 ExternInstanceDeclaration name <$> updateConstraints cs <*> updateClassName cn <*> updateType' ts
198 go (ValueDeclaration name nameKind [] Nothing val) = do
192 go (ValueDeclaration name nameKind [] Nothing val) = do
199 val' <- everywhereWithContextM' [] (mkS bindFunctionArgs `extS` bindBinders) val
193 val' <- everywhereWithContextM' [] (mkS bindFunctionArgs `extS` bindBinders) val
194+ rethrow (strMsg ("Error in declaration " ++ show name) <>) $
200− rethrowFor "declaration" name $ ValueDeclaration name nameKind [] Nothing <$> updateAll val'
195+ ValueDeclaration name nameKind [] Nothing <$> updateAll val'
202 bindFunctionArgs bound (Abs (Left arg) val') = return (arg : bound, Abs (Left arg) val')
197 bindFunctionArgs bound (Abs (Left arg) val') = return (arg : bound, Abs (Left arg) val')
203 bindFunctionArgs bound (Let ds val') = let args = mapMaybe letBoundVariable ds in
198 bindFunctionArgs bound (Let ds val') = let args = mapMaybe letBoundVariable ds in
@@ -211,7 +206,7 @@ renameInModule imports exports (Module mn decls exps) =
211 bindFunctionArgs bound (BinaryNoParens name'@(Qualified (Just _) _) v1 v2) =
206 bindFunctionArgs bound (BinaryNoParens name'@(Qualified (Just _) _) v1 v2) =
212 (,) bound <$> (BinaryNoParens <$> updateValueName name' <*> pure v1 <*> pure v2)
207 (,) bound <$> (BinaryNoParens <$> updateValueName name' <*> pure v1 <*> pure v2)
213 bindFunctionArgs bound other = return (bound, other)
208 bindFunctionArgs bound other = return (bound, other)
214− bindBinders :: [Ident] -> CaseAlternative -> Either String ([Ident], CaseAlternative)
209+ bindBinders :: [Ident] -> CaseAlternative -> Either ErrorStack ([Ident], CaseAlternative)
215 bindBinders bound c@(CaseAlternative bs _ _) = return (binderNames bs ++ bound, c)
210 bindBinders bound c@(CaseAlternative bs _ _) = return (binderNames bs ++ bound, c)
217 letBoundVariable :: Declaration -> Maybe Ident
212 letBoundVariable :: Declaration -> Maybe Ident
@@ -220,17 +215,18 @@ renameInModule imports exports (Module mn decls exps) =
220 letBoundVariable _ = Nothing
215 letBoundVariable _ = Nothing
221 go (ValueDeclaration name _ _ _ _) = error $ "Binders should have been desugared in " ++ show name
216 go (ValueDeclaration name _ _ _ _) = error $ "Binders should have been desugared in " ++ show name
222 go (ExternDeclaration fit name js ty) =
217 go (ExternDeclaration fit name js ty) =
218+ rethrow (strMsg ("Error in declaration " ++ show name) <>) $
223− rethrowFor "declaration" name $ ExternDeclaration <$> pure fit <*> pure name <*> pure js <*> updateType' ty
219+ ExternDeclaration <$> pure fit <*> pure name <*> pure js <*> updateType' ty
224 go (BindingGroupDeclaration decls') = do
220 go (BindingGroupDeclaration decls') = do
225 BindingGroupDeclaration <$> mapM go' decls'
221 BindingGroupDeclaration <$> mapM go' decls'
223+ go' = \(name, nk, value) ->
224+ rethrow (strMsg ("Error in declaration " ++ show name) <>) $
226− where go' = \(name, nk, value) -> rethrowFor "declaration" name $ (,,) <$> pure name <*> pure nk <*> updateAll value
225+ (,,) <$> pure name <*> pure nk <*> updateAll value
227 go (PositionedDeclaration pos d) = PositionedDeclaration pos <$> go d
226 go (PositionedDeclaration pos d) = PositionedDeclaration pos <$> go d
228 go d = updateAll d
227 go d = updateAll d
230− rethrowFor :: (Show a) => String -> a -> Either String b -> Either String b
231− rethrowFor what name = rethrow $ "Error in " ++ what ++ " '" ++ show name ++ "'"
233− updateAll :: Data d => d -> Either String d
229+ updateAll :: Data d => d -> Either ErrorStack d
234 updateAll = everywhereM (mkM updateType `extM` updateValue `extM` updateBinder)
230 updateAll = everywhereM (mkM updateType `extM` updateValue `extM` updateBinder)
236 updateValue (Constructor name) = Constructor <$> updateDataConstructorName name
232 updateValue (Constructor name) = Constructor <$> updateDataConstructorName name
@@ -243,7 +239,7 @@ renameInModule imports exports (Module mn decls exps) =
243 updateType (SaturatedTypeSynonym name tys) = SaturatedTypeSynonym <$> updateTypeName name <*> mapM updateType tys
239 updateType (SaturatedTypeSynonym name tys) = SaturatedTypeSynonym <$> updateTypeName name <*> mapM updateType tys
244 updateType (ConstrainedType cs t) = ConstrainedType <$> updateConstraints cs <*> pure t
240 updateType (ConstrainedType cs t) = ConstrainedType <$> updateConstraints cs <*> pure t
245 updateType t = return t
241 updateType t = return t
246− updateType' :: Data d => d -> Either String d
242+ updateType' :: Data d => d -> Either ErrorStack d
247 updateType' = everywhereM (mkM updateType)
243 updateType' = everywhereM (mkM updateType)
249 updateConstraints = mapM (\(name, ts) -> (,) <$> updateClassName name <*> pure ts)
245 updateConstraints = mapM (\(name, ts) -> (,) <$> updateClassName name <*> pure ts)
@@ -259,24 +255,24 @@ renameInModule imports exports (Module mn decls exps) =
259 -> (ImportEnvironment -> M.Map (Qualified a) (Qualified a))
255 -> (ImportEnvironment -> M.Map (Qualified a) (Qualified a))
260 -> (Exports -> a -> Bool)
256 -> (Exports -> a -> Bool)
261 -> (Qualified a)
257 -> (Qualified a)
262− -> Either String (Qualified a)
258+ -> Either ErrorStack (Qualified a)
263 update t getI checkE qname@(Qualified mn' name) = case (M.lookup qname (getI imports), mn') of
259 update t getI checkE qname@(Qualified mn' name) = case (M.lookup qname (getI imports), mn') of
264 (Just qname', _) -> return qname'
260 (Just qname', _) -> return qname'
265 (Nothing, Just mn'') -> do
261 (Nothing, Just mn'') -> do
266 modExports <- getExports mn''
262 modExports <- getExports mn''
267 if checkE modExports name
263 if checkE modExports name
268 then return qname
264 then return qname
269− else throwError $ "Unknown " ++ t ++ " '" ++ show (qname) ++ "'"
265+ else throwError $ mkErrorStack ("Unknown " ++ t ++ " '" ++ show (qname) ++ "'") Nothing
270− _ -> throwError $ "Unknown " ++ t ++ " '" ++ show name ++ "'"
266+ _ -> throwError $ mkErrorStack ("Unknown " ++ t ++ " '" ++ show name ++ "'") Nothing
272 -- Gets the exports for a module, or an error message if the module doesn't exist
268 -- Gets the exports for a module, or an error message if the module doesn't exist
273− getExports :: ModuleName -> Either String Exports
269+ getExports :: ModuleName -> Either ErrorStack Exports
274− getExports mn' = maybe (throwError $ "Unknown module '" ++ show mn' ++ "'") return $ M.lookup mn' exports
270+ getExports mn' = maybe (throwError $ mkErrorStack ("Unknown module '" ++ show mn' ++ "'") Nothing) return $ M.lookup mn' exports
277-- Finds all exported declarations in a set of modules.
273-- Finds all exported declarations in a set of modules.
279−findExports :: [Module] -> Either String ExportEnvironment
275+findExports :: [Module] -> Either ErrorStack ExportEnvironment
280findExports = foldM addModule $ M.singleton (ModuleName [ProperName "Prim"]) primExports
276findExports = foldM addModule $ M.singleton (ModuleName [ProperName "Prim"]) primExports
@@ -286,13 +282,13 @@ findExports = foldM addModule $ M.singleton (ModuleName [ProperName "Prim"]) pri
286 mkTypeEntry (Qualified _ name) = (name, [])
282 mkTypeEntry (Qualified _ name) = (name, [])
288 -- Add all of the exported declarations from a module to the global export environment
284 -- Add all of the exported declarations from a module to the global export environment
289− addModule :: ExportEnvironment -> Module -> Either String ExportEnvironment
285+ addModule :: ExportEnvironment -> Module -> Either ErrorStack ExportEnvironment
290 addModule env m@(Module mn ds _) = do
286 addModule env m@(Module mn ds _) = do
291 env' <- addEmptyModule env mn
287 env' <- addEmptyModule env mn
292− rethrowForModule m $ foldM (addDecl mn) env' ds
288+ rethrow (strMsg ("Error in module " ++ show mn) <>) $ foldM (addDecl mn) env' ds
294 -- Add a declaration from a module to the global export environment
290 -- Add a declaration from a module to the global export environment
295− addDecl :: ModuleName -> ExportEnvironment -> Declaration -> Either String ExportEnvironment
291+ addDecl :: ModuleName -> ExportEnvironment -> Declaration -> Either ErrorStack ExportEnvironment
296 addDecl mn env (TypeClassDeclaration tcn _ ds) = do
292 addDecl mn env (TypeClassDeclaration tcn _ ds) = do
297 env' <- addTypeClass env mn tcn
293 env' <- addTypeClass env mn tcn
298 foldM (\env'' (TypeDeclaration name _) -> addValue env'' mn name) env' ds
294 foldM (\env'' (TypeDeclaration name _) -> addValue env'' mn name) env' ds
@@ -308,7 +304,7 @@ findExports = foldM addModule $ M.singleton (ModuleName [ProperName "Prim"]) pri
308-- Filters the exports for a module to ensure only explicit exports are kept in the global exports
304-- Filters the exports for a module to ensure only explicit exports are kept in the global exports
309-- environment.
305-- environment.
311−filterExports :: ModuleName -> [DeclarationRef] -> ExportEnvironment -> Either String ExportEnvironment
307+filterExports :: ModuleName -> [DeclarationRef] -> ExportEnvironment -> Either ErrorStack ExportEnvironment
312filterExports mn exps env = do
308filterExports mn exps env = do
313 let moduleExports = fromMaybe (error "Module is missing") (mn `M.lookup` env)
309 let moduleExports = fromMaybe (error "Module is missing") (mn `M.lookup` env)
314 moduleExports' <- filterModule moduleExports
310 moduleExports' <- filterModule moduleExports
@@ -316,7 +312,7 @@ filterExports mn exps env = do
318 -- Filter the exports for the specific module
314 -- Filter the exports for the specific module
319− filterModule :: Exports -> Either String Exports
315+ filterModule :: Exports -> Either ErrorStack Exports
320 filterModule exported = do
316 filterModule exported = do
321 types' <- foldM (filterTypes $ exportedTypes exported) [] exps
317 types' <- foldM (filterTypes $ exportedTypes exported) [] exps
322 values <- foldM (filterValues $ exportedValues exported) [] exps
318 values <- foldM (filterValues $ exportedValues exported) [] exps
@@ -325,34 +321,34 @@ filterExports mn exps env = do
326 -- Ensure the exported types and data constructors exist in the module and add them to the set of
322 -- Ensure the exported types and data constructors exist in the module and add them to the set of
327 -- exports
323 -- exports
328− filterTypes :: [(ProperName, [ProperName])] -> [(ProperName, [ProperName])] -> DeclarationRef -> Either String [(ProperName, [ProperName])]
324+ filterTypes :: [(ProperName, [ProperName])] -> [(ProperName, [ProperName])] -> DeclarationRef -> Either ErrorStack [(ProperName, [ProperName])]
329 filterTypes expTys result (TypeRef name expDcons) = do
325 filterTypes expTys result (TypeRef name expDcons) = do
330− dcons <- maybe (throwError $ "Cannot export undefined type '" ++ show name ++ "'") return $ name `lookup` expTys
326+ dcons <- maybe (throwError $ mkErrorStack ("Cannot export undefined type '" ++ show name ++ "'") Nothing) return $ name `lookup` expTys
331 dcons' <- maybe (return dcons) (foldM (filterDcons name dcons) []) expDcons
327 dcons' <- maybe (return dcons) (foldM (filterDcons name dcons) []) expDcons
332 return $ (name, dcons') : result
328 return $ (name, dcons') : result
333 filterTypes _ result _ = return result
329 filterTypes _ result _ = return result
335 -- Ensure the exported data constructors exists for a type and add them to the list of exports
331 -- Ensure the exported data constructors exists for a type and add them to the list of exports
336− filterDcons :: ProperName -> [ProperName] -> [ProperName] -> ProperName -> Either String [ProperName]
332+ filterDcons :: ProperName -> [ProperName] -> [ProperName] -> ProperName -> Either ErrorStack [ProperName]
337 filterDcons tcon exps' result name =
333 filterDcons tcon exps' result name =
338 if name `elem` exps'
334 if name `elem` exps'
339 then return $ name : result
335 then return $ name : result
340− else throwError $ "Cannot export undefined data constructor '" ++ show name ++ "' for type '" ++ show tcon ++ "'"
336+ else throwError $ mkErrorStack ("Cannot export undefined data constructor '" ++ show name ++ "' for type '" ++ show tcon ++ "'") Nothing
342 -- Ensure the exported classes exist in the module and add them to the set of exports
338 -- Ensure the exported classes exist in the module and add them to the set of exports
343− filterClasses :: [ProperName] -> [ProperName] -> DeclarationRef -> Either String [ProperName]
339+ filterClasses :: [ProperName] -> [ProperName] -> DeclarationRef -> Either ErrorStack [ProperName]
344 filterClasses exps' result (TypeClassRef name) =
340 filterClasses exps' result (TypeClassRef name) =
345 if name `elem` exps'
341 if name `elem` exps'
346 then return $ name : result
342 then return $ name : result
347− else throwError $ "Cannot export undefined type class '" ++ show name ++ "'"
343+ else throwError $ mkErrorStack ("Cannot export undefined type class '" ++ show name ++ "'") Nothing
348 filterClasses _ result _ = return result
344 filterClasses _ result _ = return result
350 -- Ensure the exported values exist in the module and add them to the set of exports
346 -- Ensure the exported values exist in the module and add them to the set of exports
351− filterValues :: [Ident] -> [Ident] -> DeclarationRef -> Either String [Ident]
347+ filterValues :: [Ident] -> [Ident] -> DeclarationRef -> Either ErrorStack [Ident]
352 filterValues exps' result (ValueRef name) =
348 filterValues exps' result (ValueRef name) =
353 if name `elem` exps'
349 if name `elem` exps'
354 then return $ name : result
350 then return $ name : result
355− else throwError $ "Cannot export undefined value '" ++ show name ++ "'"
351+ else throwError $ mkErrorStack ("Cannot export undefined value '" ++ show name ++ "'") Nothing
356 filterValues _ result _ = return result
352 filterValues _ result _ = return result
@@ -374,7 +370,7 @@ findImports = foldl findImports' M.empty
375-- Constructs a local environment for a module.
371-- Constructs a local environment for a module.
377−resolveImports :: ExportEnvironment -> Module -> Either String ImportEnvironment
373+resolveImports :: ExportEnvironment -> Module -> Either ErrorStack ImportEnvironment
378resolveImports env (Module currentModule decls _) =
374resolveImports env (Module currentModule decls _) =
379 foldM resolveImport' (ImportEnvironment M.empty M.empty M.empty M.empty) (M.toList scope)
375 foldM resolveImport' (ImportEnvironment M.empty M.empty M.empty M.empty) (M.toList scope)
@@ -382,25 +378,25 @@ resolveImports env (Module currentModule decls _) =
382 scope :: M.Map ModuleName (Maybe ExplicitImports, Maybe ModuleName)
378 scope :: M.Map ModuleName (Maybe ExplicitImports, Maybe ModuleName)
383 scope = M.insert currentModule (Nothing, Nothing) (findImports decls)
379 scope = M.insert currentModule (Nothing, Nothing) (findImports decls)
384 resolveImport' imp (mn, (explImports, impQual)) = do
380 resolveImport' imp (mn, (explImports, impQual)) = do
385− modExports <- maybe (throwError $ "Cannot import unknown module '" ++ show mn ++ "'") return $ mn `M.lookup` env
381+ modExports <- maybe (throwError $ mkErrorStack ("Cannot import unknown module '" ++ show mn ++ "'") Nothing) return $ mn `M.lookup` env
386 resolveImport currentModule mn modExports imp impQual explImports
382 resolveImport currentModule mn modExports imp impQual explImports
389-- Extends the local environment for a module by resolving an import of another module.
385-- Extends the local environment for a module by resolving an import of another module.
391−resolveImport :: ModuleName -> ModuleName -> Exports -> ImportEnvironment -> Maybe ModuleName -> Maybe ExplicitImports-> Either String ImportEnvironment
387+resolveImport :: ModuleName -> ModuleName -> Exports -> ImportEnvironment -> Maybe ModuleName -> Maybe ExplicitImports-> Either ErrorStack ImportEnvironment
392resolveImport currentModule importModule exps imps impQual = maybe importAll (foldM importExplicit imps)
388resolveImport currentModule importModule exps imps impQual = maybe importAll (foldM importExplicit imps)
395 -- Import everything from a module
391 -- Import everything from a module
396− importAll :: Either String ImportEnvironment
392+ importAll :: Either ErrorStack ImportEnvironment
397 importAll = do
393 importAll = do
398 imp' <- foldM (\m (name, dctors) -> importExplicit m (TypeRef name (Just dctors))) imps (exportedTypes exps)
394 imp' <- foldM (\m (name, dctors) -> importExplicit m (TypeRef name (Just dctors))) imps (exportedTypes exps)
399 imp'' <- foldM (\m name -> importExplicit m (ValueRef name)) imp' (exportedValues exps)
395 imp'' <- foldM (\m name -> importExplicit m (ValueRef name)) imp' (exportedValues exps)
400 foldM (\m name -> importExplicit m (TypeClassRef name)) imp'' (exportedTypeClasses exps)
396 foldM (\m name -> importExplicit m (TypeClassRef name)) imp'' (exportedTypeClasses exps)
402 -- Import something explicitly
398 -- Import something explicitly
403− importExplicit :: ImportEnvironment -> DeclarationRef -> Either String ImportEnvironment
399+ importExplicit :: ImportEnvironment -> DeclarationRef -> Either ErrorStack ImportEnvironment
404 importExplicit imp (ValueRef name) = do
400 importExplicit imp (ValueRef name) = do
405 _ <- checkImportExists "value" values name
401 _ <- checkImportExists "value" values name
406 values' <- updateImports (importedValues imp) name
402 values' <- updateImports (importedValues imp) name
@@ -423,14 +419,15 @@ resolveImport currentModule importModule exps imps impQual = maybe importAll (fo
423 allExportedDataConstructors name = fromMaybe [] $ name `lookup` exportedTypes exps
419 allExportedDataConstructors name = fromMaybe [] $ name `lookup` exportedTypes exps
425 -- Add something to the ImportEnvironment if it does not already exist there
421 -- Add something to the ImportEnvironment if it does not already exist there
426− updateImports :: (Ord a, Show a) => M.Map (Qualified a) (Qualified a) -> a -> Either String (M.Map (Qualified a) (Qualified a))
422+ updateImports :: (Ord a, Show a) => M.Map (Qualified a) (Qualified a) -> a -> Either ErrorStack (M.Map (Qualified a) (Qualified a))
427 updateImports m name = case M.lookup (Qualified impQual name) m of
423 updateImports m name = case M.lookup (Qualified impQual name) m of
428 Nothing -> return $ M.insert (Qualified impQual name) (Qualified (Just importModule) name) m
424 Nothing -> return $ M.insert (Qualified impQual name) (Qualified (Just importModule) name) m
429 Just (Qualified Nothing _) -> error "Invalid state in updateImports"
425 Just (Qualified Nothing _) -> error "Invalid state in updateImports"
430− Just x@(Qualified (Just mn) _) -> throwError $
426+ Just x@(Qualified (Just mn) _) -> throwError $ mkErrorStack err Nothing
431− if mn == currentModule || importModule == currentModule
428+ err = if mn == currentModule || importModule == currentModule
432− then "Definition '" ++ show name ++ "' conflicts with import '" ++ show (Qualified (Just importModule) name) ++ "'"
429+ then "Definition '" ++ show name ++ "' conflicts with import '" ++ show (Qualified (Just importModule) name) ++ "'"
433− else "Conflicting imports for '" ++ show name ++ "': '" ++ show x ++ "', '" ++ show (Qualified (Just importModule) name) ++ "'"
430+ else "Conflicting imports for '" ++ show name ++ "': '" ++ show x ++ "', '" ++ show (Qualified (Just importModule) name) ++ "'"
435 -- The available values, types, and classes in the module being imported
432 -- The available values, types, and classes in the module being imported
436 values = exportedValues exps
433 values = exportedValues exps
@@ -439,14 +436,14 @@ resolveImport currentModule importModule exps imps impQual = maybe importAll (fo
440 -- Ensure that an explicitly imported data constructor exists for the type it is being imported
437 -- Ensure that an explicitly imported data constructor exists for the type it is being imported
442− checkDctorExists :: [ProperName] -> ProperName -> Either String ProperName
439+ checkDctorExists :: [ProperName] -> ProperName -> Either ErrorStack ProperName
443 checkDctorExists = checkImportExists "data constructor"
440 checkDctorExists = checkImportExists "data constructor"
445 -- Check that an explicitly imported item exists in the module it is being imported from
442 -- Check that an explicitly imported item exists in the module it is being imported from
446− checkImportExists :: (Eq a, Show a) => String -> [a] -> a -> Either String a
443+ checkImportExists :: (Eq a, Show a) => String -> [a] -> a -> Either ErrorStack a
447 checkImportExists t exports item =
444 checkImportExists t exports item =
448 if item `elem` exports
445 if item `elem` exports
449 then return item
446 then return item
450− else throwError $ "Unable to find " ++ t ++ " '" ++ show (Qualified (Just importModule) item) ++ "'"
447+ else throwError $ mkErrorStack ("Unable to find " ++ t ++ " '" ++ show (Qualified (Just importModule) item) ++ "'") Nothing