@@ -26,8 +26,9 @@ import Language.PureScript.TypeChecker.Types as T
26import Language.PureScript.TypeChecker.Synonyms as T
26import Language.PureScript.TypeChecker.Synonyms as T
28import Data.Maybe
28import Data.Maybe
29−import Data.List (nub, (\\), find, intercalate)
29+import Data.List (nub, (\\))
30import Data.Foldable (for_)
30import Data.Foldable (for_)
31import qualified Data.Map as M
32import qualified Data.Map as M
33import Control.Monad.State
34import Control.Monad.State
@@ -46,7 +47,7 @@ addDataType moduleName dtype name args dctors ctorKind = do
46 env <- getEnv
47 env <- getEnv
47 putEnv $ env { types = M.insert (Qualified (Just moduleName) name) (ctorKind, DataType args dctors) (types env) }
48 putEnv $ env { types = M.insert (Qualified (Just moduleName) name) (ctorKind, DataType args dctors) (types env) }
48 forM_ dctors $ \(dctor, tys) ->
49 forM_ dctors $ \(dctor, tys) ->
49− rethrow (mkCompileError ("Error in data constructor " ++ show dctor) Nothing `combineErrors`) $
50+ rethrow (onErrorMessages (ErrorInDataConstructor dctor)) $
50 addDataConstructor moduleName dtype name (map fst args) dctor tys
51 addDataConstructor moduleName dtype name (map fst args) dctor tys
52addDataConstructor :: ModuleName -> DataDeclType -> ProperName -> [String] -> ProperName -> [Type] -> Check ()
53addDataConstructor :: ModuleName -> DataDeclType -> ProperName -> [String] -> ProperName -> [Type] -> Check ()
@@ -70,7 +71,7 @@ valueIsNotDefined :: ModuleName -> Ident -> Check ()
70valueIsNotDefined moduleName name = do
71valueIsNotDefined moduleName name = do
71 env <- getEnv
72 env <- getEnv
72 case M.lookup (moduleName, name) (names env) of
73 case M.lookup (moduleName, name) (names env) of
73− Just _ -> throwError . strMsg $ show name ++ " is already defined"
74+ Just _ -> throwError . errorMessage $ RedefinedIdent name
74 Nothing -> return ()
75 Nothing -> return ()
76addValue :: ModuleName -> Ident -> Type -> NameKind -> Check ()
77addValue :: ModuleName -> Ident -> Type -> NameKind -> Check ()
@@ -94,7 +95,7 @@ addTypeClassDictionaries entries =
95checkDuplicateTypeArguments :: [String] -> Check ()
96checkDuplicateTypeArguments :: [String] -> Check ()
96checkDuplicateTypeArguments args = for_ firstDup $ \dup ->
97checkDuplicateTypeArguments args = for_ firstDup $ \dup ->
97− throwError . strMsg $ "Duplicate type argument '" ++ dup ++ "'"
98+ throwError . errorMessage $ DuplicateTypeArgument dup
99 firstDup :: Maybe String
100 firstDup :: Maybe String
100 firstDup = listToMaybe $ args \\ nub args
101 firstDup = listToMaybe $ args \\ nub args
@@ -103,10 +104,10 @@ checkTypeClassInstance :: ModuleName -> Type -> Check ()
103checkTypeClassInstance _ (TypeVar _) = return ()
104checkTypeClassInstance _ (TypeVar _) = return ()
104checkTypeClassInstance _ (TypeConstructor ctor) = do
105checkTypeClassInstance _ (TypeConstructor ctor) = do
105 env <- getEnv
106 env <- getEnv
106− when (ctor `M.member` typeSynonyms env) . throwError . strMsg $ "Type synonym instances are disallowed"
107+ when (ctor `M.member` typeSynonyms env) . throwError . errorMessage $ TypeSynonymInstance
107 return ()
108 return ()
108checkTypeClassInstance m (TypeApp t1 t2) = checkTypeClassInstance m t1 >> checkTypeClassInstance m t2
109checkTypeClassInstance m (TypeApp t1 t2) = checkTypeClassInstance m t1 >> checkTypeClassInstance m t2
109−checkTypeClassInstance _ ty = throwError $ mkMultipleErrors "Type class instance head is invalid." (Just (TypeError ty))
110+checkTypeClassInstance _ ty = throwError . errorMessage $ InvalidInstanceHead ty
112-- Check that type synonyms are fully-applied in a type
113-- Check that type synonyms are fully-applied in a type
@@ -133,7 +134,7 @@ typeCheckAll mainModuleName moduleName exps = go
133 go :: [Declaration] -> Check [Declaration]
134 go :: [Declaration] -> Check [Declaration]
134 go [] = return []
135 go [] = return []
135 go (DataDeclaration dtype name args dctors : rest) = do
136 go (DataDeclaration dtype name args dctors : rest) = do
136− rethrow (mkCompileError ("Error in type constructor " ++ show name) Nothing `combineErrors`) $ do
137+ rethrow (onErrorMessages (ErrorInTypeConstructor name)) $ do
137 when (dtype == Newtype) $ checkNewtype dctors
138 when (dtype == Newtype) $ checkNewtype dctors
138 checkDuplicateTypeArguments $ map fst args
139 checkDuplicateTypeArguments $ map fst args
139 ctorKind <- kindsOf True moduleName name args (concatMap snd dctors)
140 ctorKind <- kindsOf True moduleName name args (concatMap snd dctors)
@@ -144,10 +145,10 @@ typeCheckAll mainModuleName moduleName exps = go
145 checkNewtype :: [(ProperName, [Type])] -> Check ()
146 checkNewtype :: [(ProperName, [Type])] -> Check ()
146 checkNewtype [(_, [_])] = return ()
147 checkNewtype [(_, [_])] = return ()
147− checkNewtype [(_, _)] = throwError . strMsg $ "newtypes constructors must have a single argument"
148+ checkNewtype [(_, _)] = throwError . errorMessage $ InvalidNewtype
148− checkNewtype _ = throwError . strMsg $ "newtypes must have a single constructor"
149+ checkNewtype _ = throwError . errorMessage $ InvalidNewtype
149 go (d@(DataBindingGroupDeclaration tys) : rest) = do
150 go (d@(DataBindingGroupDeclaration tys) : rest) = do
150− rethrow (mkCompileError "Error in data binding group" Nothing `combineErrors`) $ do
151+ rethrow (onErrorMessages ErrorInDataBindingGroup) $ do
151 let syns = mapMaybe toTypeSynonym tys
152 let syns = mapMaybe toTypeSynonym tys
152 let dataDecls = mapMaybe toDataDecl tys
153 let dataDecls = mapMaybe toDataDecl tys
153 (syn_ks, data_ks) <- kindsOfAll moduleName syns (map (\(_, name, args, dctors) -> (name, args, concatMap snd dctors)) dataDecls)
154 (syn_ks, data_ks) <- kindsOfAll moduleName syns (map (\(_, name, args, dctors) -> (name, args, concatMap snd dctors)) dataDecls)
@@ -169,7 +170,7 @@ typeCheckAll mainModuleName moduleName exps = go
169 toDataDecl (PositionedDeclaration _ _ d') = toDataDecl d'
170 toDataDecl (PositionedDeclaration _ _ d') = toDataDecl d'
170 toDataDecl _ = Nothing
171 toDataDecl _ = Nothing
171 go (TypeSynonymDeclaration name args ty : rest) = do
172 go (TypeSynonymDeclaration name args ty : rest) = do
172− rethrow (mkCompileError ("Error in type synonym " ++ show name) Nothing `combineErrors`) $ do
173+ rethrow (onErrorMessages (ErrorInTypeSynonym name)) $ do
173 checkDuplicateTypeArguments $ map fst args
174 checkDuplicateTypeArguments $ map fst args
174 kind <- kindsOf False moduleName name args [ty]
175 kind <- kindsOf False moduleName name args [ty]
175 let args' = args `withKinds` kind
176 let args' = args `withKinds` kind
@@ -178,7 +179,7 @@ typeCheckAll mainModuleName moduleName exps = go
178 return $ TypeSynonymDeclaration name args ty : ds
179 return $ TypeSynonymDeclaration name args ty : ds
179 go (TypeDeclaration _ _ : _) = error "Type declarations should have been removed"
180 go (TypeDeclaration _ _ : _) = error "Type declarations should have been removed"
180 go (ValueDeclaration name nameKind [] (Right val) : rest) = do
181 go (ValueDeclaration name nameKind [] (Right val) : rest) = do
181− d <- rethrow (mkCompileError ("Error in declaration " ++ show name) Nothing `combineErrors`) $ do
182+ d <- rethrow (onErrorMessages (ErrorInValueDeclaration name)) $ do
182 valueIsNotDefined moduleName name
183 valueIsNotDefined moduleName name
183 [(_, (val', ty))] <- typesOf mainModuleName moduleName [(name, val)]
184 [(_, (val', ty))] <- typesOf mainModuleName moduleName [(name, val)]
184 addValue moduleName name ty nameKind
185 addValue moduleName name ty nameKind
@@ -187,7 +188,7 @@ typeCheckAll mainModuleName moduleName exps = go
187 return $ d : ds
188 return $ d : ds
188 go (ValueDeclaration{} : _) = error "Binders were not desugared"
189 go (ValueDeclaration{} : _) = error "Binders were not desugared"
189 go (BindingGroupDeclaration vals : rest) = do
190 go (BindingGroupDeclaration vals : rest) = do
190− d <- rethrow (mkCompileError ("Error in binding group " ++ show (map (\(ident, _, _) -> ident) vals)) Nothing `combineErrors`) $ do
191+ d <- rethrow (onErrorMessages (ErrorInBindingGroup (map (\(ident, _, _) -> ident) vals))) $ do
191 forM_ (map (\(ident, _, _) -> ident) vals) $ \name ->
192 forM_ (map (\(ident, _, _) -> ident) vals) $ \name ->
192 valueIsNotDefined moduleName name
193 valueIsNotDefined moduleName name
193 tys <- typesOf mainModuleName moduleName $ map (\(ident, _, ty) -> (ident, ty)) vals
194 tys <- typesOf mainModuleName moduleName $ map (\(ident, _, ty) -> (ident, ty)) vals
@@ -207,19 +208,19 @@ typeCheckAll mainModuleName moduleName exps = go
207 ds <- go rest
208 ds <- go rest
208 return $ d : ds
209 return $ d : ds
209 go (d@(ExternDeclaration importTy name _ ty) : rest) = do
210 go (d@(ExternDeclaration importTy name _ ty) : rest) = do
210− rethrow (mkCompileError ("Error in foreign import declaration " ++ show name) Nothing `combineErrors`) $ do
211+ rethrow (onErrorMessages (ErrorInForeignImport name)) $ do
211 env <- getEnv
212 env <- getEnv
212 kind <- kindOf moduleName ty
213 kind <- kindOf moduleName ty
213− guardWith (strMsg "Expected kind *") $ kind == Star
214+ guardWith (errorMessage (ExpectedType kind)) $ kind == Star
214 case M.lookup (moduleName, name) (names env) of
215 case M.lookup (moduleName, name) (names env) of
215− Just _ -> throwError . strMsg $ show name ++ " is already defined"
216+ Just _ -> throwError . errorMessage $ RedefinedIdent name
216 Nothing -> putEnv (env { names = M.insert (moduleName, name) (ty, Extern importTy, Defined) (names env) })
217 Nothing -> putEnv (env { names = M.insert (moduleName, name) (ty, Extern importTy, Defined) (names env) })
217 ds <- go rest
218 ds <- go rest
218 return $ d : ds
219 return $ d : ds
219 go (d@(FixityDeclaration _ name) : rest) = do
220 go (d@(FixityDeclaration _ name) : rest) = do
220 ds <- go rest
221 ds <- go rest
221 env <- getEnv
222 env <- getEnv
222− guardWith (strMsg ("Fixity declaration with no binding: " ++ name)) $ M.member (moduleName, Op name) $ names env
223+ guardWith (errorMessage (OrphanFixityDeclaration name)) $ M.member (moduleName, Op name) $ names env
223 return $ d : ds
224 return $ d : ds
224 go (d@(ImportDeclaration importedModule _ _) : rest) = do
225 go (d@(ImportDeclaration importedModule _ _) : rest) = do
225 tcds <- getTypeClassDictionaries
226 tcds <- getTypeClassDictionaries
@@ -277,7 +278,7 @@ typeCheckAll mainModuleName moduleName exps = go
278typeCheckModule :: Maybe ModuleName -> Module -> Check Module
279typeCheckModule :: Maybe ModuleName -> Module -> Check Module
279typeCheckModule _ (Module _ _ _ Nothing) = error "exports should have been elaborated"
280typeCheckModule _ (Module _ _ _ Nothing) = error "exports should have been elaborated"
280−typeCheckModule mainModuleName (Module coms mn decls (Just exps)) = do
281+typeCheckModule mainModuleName (Module coms mn decls (Just exps)) = rethrow (onErrorMessages (ErrorInModule mn)) $ do
281 modify (\s -> s { checkCurrentModule = Just mn })
282 modify (\s -> s { checkCurrentModule = Just mn })
282 decls' <- typeCheckAll mainModuleName mn exps decls
283 decls' <- typeCheckAll mainModuleName mn exps decls
283 forM_ exps $ \e -> do
284 forM_ exps $ \e -> do
@@ -287,63 +288,54 @@ typeCheckModule mainModuleName (Module coms mn decls (Just exps)) = do
287 return $ Module coms mn decls' (Just exps)
288 return $ Module coms mn decls' (Just exps)
290− checkMemberExport :: (Show a) => String -> (Type -> [a]) -> (a -> Bool) -> DeclarationRef -> Check ()
291+ checkMemberExport :: (Type -> [DeclarationRef]) -> DeclarationRef -> Check ()
291− checkMemberExport thing extract test (ValueRef name) = do
292+ checkMemberExport extract dr@(ValueRef name) = do
292 ty <- lookupVariable mn (Qualified (Just mn) name)
293 ty <- lookupVariable mn (Qualified (Just mn) name)
293− case find test (extract ty) of
294+ case filter (not . exported) (extract ty) of
294− Just hiddenType -> throwError . strMsg $
295+ [] -> return ()
295− "Error in module '" ++ show mn ++ "':\n\
296+ hidden -> throwError . errorMessage $ TransitiveExportError dr hidden
296− \Exporting declaration '" ++ show name ++ "' requires " ++ thing ++ " '" ++ show hiddenType ++ "' to be exported as well"
297+ where
297− Nothing -> return ()
298+ exported e = any (exports e) exps
299+ exports (TypeRef pn1 _) (TypeRef pn2 _) = pn1 == pn2
300+ exports (ValueRef id1) (ValueRef id2) = id1 == id2
301+ exports (TypeClassRef pn1) (TypeClassRef pn2) = pn1 == pn2
302+ exports (TypeInstanceRef id1) (TypeInstanceRef id2) = id1 == id2
303+ exports (PositionedDeclarationRef _ _ r1) r2 = exports r1 r2
304+ exports r1 (PositionedDeclarationRef _ _ r2) = exports r1 r2
298− checkMemberExport _ _ _ _ = return ()
306+ checkMemberExport _ _ = return ()
300 -- Check that all the type constructors defined in the current module that appear in member types
308 -- Check that all the type constructors defined in the current module that appear in member types
301 -- have also been exported from the module
309 -- have also been exported from the module
302 checkTypesAreExported :: DeclarationRef -> Check ()
310 checkTypesAreExported :: DeclarationRef -> Check ()
303− checkTypesAreExported = checkMemberExport "type" findTcons isTconHidden
311+ checkTypesAreExported = checkMemberExport findTcons
305− findTcons :: Type -> [ProperName]
313+ findTcons :: Type -> [DeclarationRef]
306 findTcons = everythingOnTypes (++) go
314 findTcons = everythingOnTypes (++) go
308− go (TypeConstructor (Qualified (Just mn') name)) | mn' == mn = [name]
316+ go (TypeConstructor (Qualified (Just mn') name)) | mn' == mn = [TypeRef name (error "Data constructors unused in checkTypesAreExported")]
309 go _ = []
317 go _ = []
310− isTconHidden :: ProperName -> Bool
311− isTconHidden tyName = all go exps
313− go (TypeRef tyName' _) = tyName' /= tyName
316 -- Check that all the classes defined in the current module that appear in member types have also
319 -- Check that all the classes defined in the current module that appear in member types have also
317 -- been exported from the module
320 -- been exported from the module
318 checkClassesAreExported :: DeclarationRef -> Check ()
321 checkClassesAreExported :: DeclarationRef -> Check ()
319− checkClassesAreExported = checkMemberExport "class" findClasses isClassHidden
322+ checkClassesAreExported = checkMemberExport findClasses
321− findClasses :: Type -> [ProperName]
324+ findClasses :: Type -> [DeclarationRef]
322 findClasses = everythingOnTypes (++) go
325 findClasses = everythingOnTypes (++) go
324− go (ConstrainedType cs _) = mapMaybe (extractCurrentModuleClass . fst) cs
327+ go (ConstrainedType cs _) = mapMaybe (fmap TypeClassRef . extractCurrentModuleClass . fst) cs
325 go _ = []
328 go _ = []
326 extractCurrentModuleClass :: Qualified ProperName -> Maybe ProperName
329 extractCurrentModuleClass :: Qualified ProperName -> Maybe ProperName
327 extractCurrentModuleClass (Qualified (Just mn') name) | mn == mn' = Just name
330 extractCurrentModuleClass (Qualified (Just mn') name) | mn == mn' = Just name
328 extractCurrentModuleClass _ = Nothing
331 extractCurrentModuleClass _ = Nothing
329− isClassHidden :: ProperName -> Bool
330− isClassHidden clsName = all go exps
332− go (TypeClassRef clsName') = clsName' /= clsName
335 checkClassMembersAreExported :: DeclarationRef -> Check ()
333 checkClassMembersAreExported :: DeclarationRef -> Check ()
336− checkClassMembersAreExported (TypeClassRef name) = do
334+ checkClassMembersAreExported dr@(TypeClassRef name) = do
337 let members = ValueRef `map` head (mapMaybe findClassMembers decls)
335 let members = ValueRef `map` head (mapMaybe findClassMembers decls)
338 let missingMembers = members \\ exps
336 let missingMembers = members \\ exps
339− unless (null missingMembers) $
337+ unless (null missingMembers) $ throwError . errorMessage $ TransitiveExportError dr members
340− throwError . strMsg $
341− "Error in module '" ++ show mn ++ "':\n\
342− \Class '" ++ show name ++ "' is exported but is missing member exports for '" ++ intercalate "', '" (map (show . runValueRef) missingMembers) ++ "'"
344− runValueRef :: DeclarationRef -> Ident
345− runValueRef (ValueRef refName) = refName
346− runValueRef _ = error "non-ValueRef passed to runValueRef"
347 findClassMembers :: Declaration -> Maybe [Ident]
339 findClassMembers :: Declaration -> Maybe [Ident]
348 findClassMembers (TypeClassDeclaration name' _ _ ds) | name == name' = Just $ map extractMemberName ds
340 findClassMembers (TypeClassDeclaration name' _ _ ds) | name == name' = Just $ map extractMemberName ds
349 findClassMembers (PositionedDeclaration _ _ d) = findClassMembers d
341 findClassMembers (PositionedDeclaration _ _ d) = findClassMembers d