1212--
1313-----------------------------------------------------------------------------
1414
15- {-# LANGUAGE GeneralizedNewtypeDeriving, FlexibleContexts #-}
15+ {-# LANGUAGE GeneralizedNewtypeDeriving #-}
16+ {-# LANGUAGE FlexibleContexts #-}
17+ {-# LANGUAGE MultiParamTypeClasses #-}
1618
1719module Language.PureScript.Errors where
1820
1921import Data.Either (lefts , rights )
20- import Data.String (IsString (.. ))
21- import Data.List (intersperse , intercalate )
22+ import Data.List (intersperse )
2223import Data.Monoid
24+ import Data.Foldable (fold , foldMap )
2325
2426import Control.Monad.Except
27+ import Control.Monad.Unify
2528import Control.Applicative ((<$>) )
2629
2730import Language.PureScript.AST
2831import Language.PureScript.Pretty
2932import Language.PureScript.Types
33+ import Language.PureScript.Names
34+ import Language.PureScript.Kinds
3035
3136-- |
32- -- Type for sources of type checking errors
33- --
34- data ErrorSource
35- -- |
36- -- An error which originated at a Expr
37- --
38- = ExprError Expr
39- -- |
40- -- An error which originated at a Type
41- --
42- | TypeError Type deriving (Show )
37+ -- A type of error messages
38+ --
39+ data ErrorMessage
40+ = InfiniteType Type
41+ | InfiniteKind Kind
42+ | CannotReorderOperators
43+ | MultipleFixities Ident
44+ | OrphanTypeDeclaration Ident
45+ | RedefinedModule ModuleName
46+ | OverlappingNamesInLet
47+ | UnknownModule ModuleName
48+ | UnknownType (Qualified ProperName )
49+ | UnknownTypeClass (Qualified ProperName )
50+ | UnknownValue (Qualified Ident )
51+ | UnknownDataConstructor (Qualified ProperName ) (Maybe (Qualified ProperName ))
52+ | ConflictingImport String ModuleName
53+ | ConflictingImports String ModuleName ModuleName
54+ | ConflictingTypeDecls ProperName
55+ | ConflictingCtorDecls ProperName
56+ | TypeConflictsWithClass ProperName
57+ | CtorConflictsWithClass ProperName
58+ | ClassConflictsWithType ProperName
59+ | ClassConflictsWithCtor ProperName
60+ | DuplicateClassExport ProperName
61+ | DuplicateValueExport Ident
62+ | ErrorInModule ModuleName ErrorMessage
63+ | PositionedError SourceSpan ErrorMessage
64+ deriving (Show , Eq )
65+
66+ instance UnificationError Type ErrorMessage where
67+ occursCheckFailed = InfiniteType
68+
69+ instance UnificationError Kind ErrorMessage where
70+ occursCheckFailed = InfiniteKind
4371
4472-- |
45- -- Compilation errors
46- --
47- data CompileError
48- = CompileError
49- { -- |
50- -- Error message
51- --
52- compileErrorMessage :: String
53- -- |
54- -- The value where the error occurred
55- --
56- , compileErrorValue :: Maybe ErrorSource
57- -- |
58- -- Optional source position information
59- --
60- , compileErrorPosition :: Maybe SourceSpan
61- }
62- deriving (Show )
73+ -- Pretty print an ErrorMessage
74+ --
75+ prettyPrintErrorMessage :: ErrorMessage -> String
76+ prettyPrintErrorMessage CannotReorderOperators = " Unable to reorder operators"
77+ prettyPrintErrorMessage OverlappingNamesInLet = " Overlapping names in let binding."
78+ prettyPrintErrorMessage (InfiniteType ty) = " Infinite type detected: " ++ prettyPrintType ty
79+ prettyPrintErrorMessage (InfiniteKind ki) = " Infinite kind detected: " ++ prettyPrintKind ki
80+ prettyPrintErrorMessage (MultipleFixities name) = " Multiple fixity declarations for " ++ show name
81+ prettyPrintErrorMessage (OrphanTypeDeclaration pn) = " Orphan type declaration for: " ++ show pn
82+ prettyPrintErrorMessage (RedefinedModule name) = " Module " ++ show name ++ " has been defined multiple times"
83+ prettyPrintErrorMessage (UnknownModule mn) = " Unknown module: " ++ show mn
84+ prettyPrintErrorMessage (UnknownType name) = " Unknown type: " ++ show name
85+ prettyPrintErrorMessage (UnknownTypeClass name) = " Unknown type class: " ++ show name
86+ prettyPrintErrorMessage (UnknownValue name) = " Unknown value: " ++ show name
87+ prettyPrintErrorMessage (UnknownDataConstructor dc tc) = " Unknown data constructor " ++ show dc ++ foldMap ((" for type constructor " ++ ) . show ) tc
88+ prettyPrintErrorMessage (ConflictingImport nm mn) = " Declaration " ++ nm ++ " conflicts with import " ++ show mn
89+ prettyPrintErrorMessage (ConflictingImports nm m1 m2) = " Conflicting imports for " ++ nm ++ " from modules " ++ show m1 ++ " and " ++ show m2
90+ prettyPrintErrorMessage (ConflictingTypeDecls nm) = " Conflicting type declarations for " ++ show nm
91+ prettyPrintErrorMessage (ConflictingCtorDecls nm) = " Conflicting data constructor declarations for " ++ show nm
92+ prettyPrintErrorMessage (TypeConflictsWithClass nm) = " Type " ++ show nm ++ " conflicts with type class declaration of the same name"
93+ prettyPrintErrorMessage (CtorConflictsWithClass nm) = " Data constructor " ++ show nm ++ " conflicts with type class declaration of the same name"
94+ prettyPrintErrorMessage (ClassConflictsWithType nm) = " Type class " ++ show nm ++ " conflicts with type declaration of the same name"
95+ prettyPrintErrorMessage (ClassConflictsWithCtor nm) = " Type class " ++ show nm ++ " conflicts with data constructor declaration of the same name"
96+ prettyPrintErrorMessage (DuplicateClassExport nm) = " Duplicate export declaration for type class " ++ show nm
97+ prettyPrintErrorMessage (DuplicateValueExport nm) = " Duplicate export declaration for value " ++ show nm
98+ prettyPrintErrorMessage (ErrorInModule mn err) = " Error in module " ++ show mn ++ " : " ++ prettyPrintErrorMessage err
99+ prettyPrintErrorMessage (PositionedError pos err) = " Error at " ++ show pos ++ " : \n " ++ prettyPrintErrorMessage err
63100
64101-- |
65102-- A stack trace for an error
66103--
67- data ErrorStack
68- = ErrorStack { runErrorStack :: [CompileError ] }
69- | MultipleErrors [ErrorStack ] deriving (Show )
104+ newtype MultipleErrors = MultipleErrors
105+ { runMultipleErrors :: [ErrorMessage ] } deriving (Show , Eq , Monoid )
70106
71- -- TODO: Remove strMsg, the IsString instance, and unnecessary
72- -- OverloadedStrings pragmas. See #745
73- -- | Create an ErrorStack from a string
74- strMsg :: String -> ErrorStack
75- strMsg s = ErrorStack [CompileError s Nothing Nothing ]
107+ -- |
108+ -- Simplify an error message
109+ --
110+ simplifyErrorMessage :: ErrorMessage -> ErrorMessage
111+ simplifyErrorMessage = unwrap Nothing
112+ where
113+ unwrap :: Maybe SourceSpan -> ErrorMessage -> ErrorMessage
114+ unwrap pos (ErrorInModule mn err) = ErrorInModule mn (unwrap pos err)
115+ unwrap _ (PositionedError pos err) = unwrap (Just pos) err
116+ unwrap pos other = wrap pos other
117+
118+ wrap :: Maybe SourceSpan -> ErrorMessage -> ErrorMessage
119+ wrap Nothing = id
120+ wrap (Just pos) = PositionedError pos
76121
77- instance IsString ErrorStack where
78- fromString = strMsg
122+ -- |
123+ -- Create an error set from a single error message
124+ --
125+ errorMessage :: ErrorMessage -> MultipleErrors
126+ errorMessage err = MultipleErrors [err]
79127
80- prettyPrintErrorStack :: Bool -> ErrorStack -> String
81- prettyPrintErrorStack printFullStack (ErrorStack es) =
82- case mconcat $ map (Last . compileErrorPosition) es of
83- Last (Just sourcePos) -> " Error at " ++ show sourcePos ++ " : \n " ++ prettyPrintErrorStack'
84- _ -> prettyPrintErrorStack'
85- where
86- prettyPrintErrorStack' :: String
87- prettyPrintErrorStack'
88- | printFullStack = intercalate " \n " (map showError (filter isErrorNonEmpty es))
89- | otherwise =
90- let
91- es' = filter isErrorNonEmpty es
92- in case length es' of
93- 1 -> showError (head es')
94- _ -> showError (head es') ++ " \n " ++ showError (last es')
95- prettyPrintErrorStack printFullStack (MultipleErrors es) =
96- unlines $ intersperse " " $ " Multiple errors:" : map (prettyPrintErrorStack printFullStack) es
97-
98- stringifyErrorStack :: (MonadError String m ) => Bool -> Either ErrorStack a -> m a
99- stringifyErrorStack printFullStack = either (throwError . prettyPrintErrorStack printFullStack) return
100-
101- isErrorNonEmpty :: CompileError -> Bool
102- isErrorNonEmpty = not . null . compileErrorMessage
103-
104- showError :: CompileError -> String
105- showError (CompileError msg Nothing _) = msg
106- showError (CompileError msg (Just (ExprError val)) _) = " Error in expression " ++ prettyPrintValue val ++ " :\n " ++ msg
107- showError (CompileError msg (Just (TypeError ty)) _) = " Error in type " ++ prettyPrintType ty ++ " :\n " ++ msg
108-
109- mkErrorStack :: String -> Maybe ErrorSource -> ErrorStack
110- mkErrorStack msg t = ErrorStack [mkCompileError msg t]
111-
112- mkCompileError :: String -> Maybe ErrorSource -> CompileError
113- mkCompileError msg t = CompileError msg t Nothing
114-
115- positionError :: SourceSpan -> CompileError
116- positionError pos = CompileError " " Nothing (Just pos)
128+ -- |
129+ -- Lift a function on ErrorMessage to a function on MultipleErrors
130+ --
131+ onErrorMessages :: (ErrorMessage -> ErrorMessage ) -> MultipleErrors -> MultipleErrors
132+ onErrorMessages f = MultipleErrors . map f . runMultipleErrors
133+
134+ -- |
135+ -- Pretty print a single error, simplifying if necessary
136+ --
137+ prettyPrintSingleError :: Bool -> ErrorMessage -> String
138+ prettyPrintSingleError full e = prettyPrintErrorMessage (if full then e else simplifyErrorMessage e)
139+
140+ -- |
141+ -- Pretty print multiple errors
142+ --
143+ prettyPrintMultipleErrors :: Bool -> MultipleErrors -> String
144+ prettyPrintMultipleErrors full (MultipleErrors [e]) =
145+ prettyPrintSingleError full e
146+ prettyPrintMultipleErrors full (MultipleErrors es) =
147+ unlines $ intersperse " " $ " Multiple errors:" : map (prettyPrintSingleError full) es
148+
149+ -- |
150+ -- Interpret multiple errors in a monad supporting errors
151+ --
152+ interpretMultipleErrors :: (MonadError String m ) => Bool -> Either MultipleErrors a -> m a
153+ interpretMultipleErrors printFullStack = either (throwError . prettyPrintMultipleErrors printFullStack) return
117154
118155-- |
119156-- Rethrow an error with a more detailed error message in the case of failure
@@ -124,30 +161,19 @@ rethrow f = flip catchError $ \e -> throwError (f e)
124161-- |
125162-- Rethrow an error with source position information
126163--
127- rethrowWithPosition :: (MonadError ErrorStack m ) => SourceSpan -> m a -> m a
128- rethrowWithPosition pos = rethrow (positionError pos `combineErrors` )
164+ rethrowWithPosition :: (MonadError MultipleErrors m ) => SourceSpan -> m a -> m a
165+ rethrowWithPosition pos = rethrow (onErrorMessages ( PositionedError pos) )
129166
130167-- |
131168-- Collect errors in in parallel
132169--
133- parU :: (MonadError ErrorStack m , Functor m ) => [a ] -> (a -> m b ) -> m [b ]
170+ parU :: (MonadError MultipleErrors m , Functor m ) => [a ] -> (a -> m b ) -> m [b ]
134171parU xs f = forM xs (withError . f) >>= collectErrors
135172 where
136- withError :: (MonadError ErrorStack m , Functor m ) => m a -> m (Either ErrorStack a )
173+ withError :: (MonadError MultipleErrors m , Functor m ) => m a -> m (Either MultipleErrors a )
137174 withError u = catchError (Right <$> u) (return . Left )
138175
139- collectErrors :: (MonadError ErrorStack m , Functor m ) => [Either ErrorStack a ] -> m [a ]
176+ collectErrors :: (MonadError MultipleErrors m , Functor m ) => [Either MultipleErrors a ] -> m [a ]
140177 collectErrors es = case lefts es of
141- [err] -> throwError err
142178 [] -> return $ rights es
143- errs -> throwError $ MultipleErrors errs
144-
145- -- |
146- -- Add an extra error string onto the top of each error stack in a list of possibly many errors
147- --
148- combineErrors :: CompileError -> ErrorStack -> ErrorStack
149- combineErrors ce err = go (ErrorStack [ce]) err
150- where
151- go (ErrorStack xs) (ErrorStack ys) = ErrorStack (xs ++ ys)
152- go (MultipleErrors es) x = MultipleErrors [ go e x | e <- es ]
153- go x (MultipleErrors es) = MultipleErrors [ go x e | e <- es ]
179+ errs -> throwError $ fold errs
0 commit comments