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

Use a data type for errors, and link to wiki in error messages

commit3a7d26e2bcea2d0a36b95e82090e1d786cef2412 authorPhil Freeman <paf31@cantab.net> dateMon 23 Feb 2015, 13:05 (12 years ago) parentf4b3ae810da3a0
26 files changed+608−401
psci/Main.hs+1−1 src/Control/Monad/Unify.hs+10−6 src/Language/PureScript.hs+4−4 src/Language/PureScript/AST/SourcePos.hs+2−2 src/Language/PureScript/Errors.hs+354−91 src/Language/PureScript/Sugar.hs+1−1 src/Language/PureScript/Sugar/BindingGroups.hs+12−13 src/Language/PureScript/Sugar/CaseDeclarations.hs+11−11 src/Language/PureScript/Sugar/DoNotation.hs+4−4 src/Language/PureScript/Sugar/Names.hs+53−63 src/Language/PureScript/Sugar/ObjectWildcards.hs+1−1 src/Language/PureScript/Sugar/Operators.hs+8−8 src/Language/PureScript/Sugar/TypeClasses.hs+9−10 src/Language/PureScript/Sugar/TypeDeclarations.hs+6−6 src/Language/PureScript/TypeChecker.hs+42−50 src/Language/PureScript/TypeChecker/Entailment.hs+2−45 src/Language/PureScript/TypeChecker/Kinds.hs+5−6 src/Language/PureScript/TypeChecker/Monad.hs+13−13 src/Language/PureScript/TypeChecker/Rows.hs+1−1 src/Language/PureScript/TypeChecker/Skolems.hs+2−3 src/Language/PureScript/TypeChecker/Subsumption.hs+2−9 src/Language/PureScript/TypeChecker/Synonyms.hs+12−12 src/Language/PureScript/TypeChecker/Types.hs+22−32 src/Language/PureScript/TypeChecker/Unify.hs+7−8 src/Language/PureScript/TypeClassDictionaries.hs+23 tests/Main.hs+1−1
psci/Main.hs+1−1
@@ -531,7 +531,7 @@ handleKindOf typ = do
531531 let chk = P.CheckState env' 0 0 (Just mName)
532532 k = L.runStateT (P.unCheck (P.kindOf mName typ')) chk
533533 case k of
534− Left errStack -> PSCI . outputStrLn . P.prettyPrintErrorStack False $ errStack
534+ Left errStack -> PSCI . outputStrLn . P.prettyPrintMultipleErrors False $ errStack
535535 Right (kind, _) -> PSCI . outputStrLn . P.prettyPrintKind $ kind
536536 Nothing -> PSCI $ outputStrLn "Could not find kind"
537537
src/Control/Monad/Unify.hs+10−6
@@ -20,11 +20,9 @@
2020{-# LANGUAGE MultiParamTypeClasses #-}
2121{-# LANGUAGE FunctionalDependencies #-}
2222{-# LANGUAGE UndecidableInstances #-}
23−{-# LANGUAGE OverloadedStrings #-}
2423
2524module Control.Monad.Unify where
2625
27−import Data.String (IsString)
2826import Data.Monoid
2927
3028import Control.Applicative
@@ -84,10 +82,16 @@ data UnifyState t = UnifyState {
8482defaultUnifyState :: (Partial t) => UnifyState t
8583defaultUnifyState = UnifyState 0 mempty
8684
85+-- |
86+-- A class for errors which support unification errors
87+--
88+class UnificationError t e where
89+ occursCheckFailed :: t -> e
90+
8791-- |
8892-- The type checking monad, which provides the state of the type checker, and error reporting capabilities
8993--
90−newtype UnifyT t m a = UnifyT { unUnify :: (StateT (UnifyState t) m) a }
94+newtype UnifyT t m a = UnifyT { unUnify :: StateT (UnifyState t) m a }
9195 deriving (Functor, Monad, Applicative, Alternative, MonadPlus)
9296
9397instance (MonadState s m) => MonadState s (UnifyT t m) where
@@ -113,7 +117,7 @@ substituteOne u t = Substitution $ M.singleton u t
113117-- |
114118-- Replace a unification variable with the specified value in the current substitution
115119--
116−(=:=) :: (IsString e, Monad m, MonadError e m, Unifiable m t) => Unknown -> t -> UnifyT t m ()
120+(=:=) :: (UnificationError t e, Monad m, MonadError e m, Unifiable m t) => Unknown -> t -> UnifyT t m ()
117121(=:=) u t' = do
118122 st <- UnifyT get
119123 let sub = unifyCurrentSubstitution st
@@ -128,10 +132,10 @@ substituteOne u t = Substitution $ M.singleton u t
128132-- |
129133-- Perform the occurs check, to make sure a unification variable does not occur inside a value
130134--
131−occursCheck :: (IsString e, Monad m, MonadError e m, Partial t) => Unknown -> t -> UnifyT t m ()
135+occursCheck :: (UnificationError t e, Monad m, MonadError e m, Partial t) => Unknown -> t -> UnifyT t m ()
132136occursCheck u t =
133137 case isUnknown t of
134− Nothing -> when (u `elem` unknowns t) $ UnifyT . lift . throwError $ "Occurs check fails"
138+ Nothing -> when (u `elem` unknowns t) $ UnifyT . lift . throwError $ occursCheckFailed t
135139 _ -> return ()
136140
137141-- |
src/Language/PureScript.hs+4−4
@@ -96,9 +96,9 @@ compile' env ms prefix = do
9696 additional <- asks optionsAdditional
9797 mainModuleIdent <- asks (fmap moduleNameFromString . optionsMain)
9898 (sorted, _) <- sortModules $ map importPrim $ if noPrelude then ms else map importPrelude ms
99− (desugared, nextVar) <- stringifyErrorStack True $ runSupplyT 0 $ desugar sorted
99+ (desugared, nextVar) <- interpretMultipleErrors True $ runSupplyT 0 $ desugar sorted
100100 (elaborated, env') <- runCheck' env $ forM desugared $ typeCheckModule mainModuleIdent
101− regrouped <- stringifyErrorStack True $ createBindingGroupsModule . collapseBindingGroupsModule $ elaborated
101+ regrouped <- interpretMultipleErrors True $ createBindingGroupsModule . collapseBindingGroupsModule $ elaborated
102102 let corefn = map (CoreFn.moduleToCoreFn env') regrouped
103103 let entryPoints = moduleNameFromString `map` entryPointModules additional
104104 let elim = if null entryPoints then corefn else eliminateDeadCode entryPoints corefn
@@ -192,7 +192,7 @@ make outputDir ms prefix = do
192192
193193 marked <- rebuildIfNecessary (reverseDependencies graph) toRebuild sorted
194194
195− (desugared, nextVar) <- stringifyErrorStack True $ runSupplyT 0 $ zip (map fst marked) <$> desugar (map snd marked)
195+ (desugared, nextVar) <- interpretMultipleErrors True $ runSupplyT 0 $ zip (map fst marked) <$> desugar (map snd marked)
196196
197197 evalSupplyT nextVar $ go initEnvironment desugared
198198
@@ -212,7 +212,7 @@ make outputDir ms prefix = do
212212
213213 (Module _ _ elaborated _, env') <- lift . runCheck' env $ typeCheckModule Nothing m
214214
215− regrouped <- stringifyErrorStack True . createBindingGroups moduleName' . collapseBindingGroups $ elaborated
215+ regrouped <- interpretMultipleErrors True . createBindingGroups moduleName' . collapseBindingGroups $ elaborated
216216
217217 let mod' = Module coms moduleName' regrouped exps
218218 let corefn = CoreFn.moduleToCoreFn env' mod'
src/Language/PureScript/AST/SourcePos.hs+2−2
@@ -30,7 +30,7 @@ data SourcePos = SourcePos
3030 -- Column number
3131 --
3232 , sourcePosColumn :: Int
33− } deriving (D.Data, D.Typeable)
33+ } deriving (Eq, D.Data, D.Typeable)
3434
3535instance Show SourcePos where
3636 show sp = "line " ++ show (sourcePosLine sp) ++ ", column " ++ show (sourcePosColumn sp)
@@ -47,7 +47,7 @@ data SourceSpan = SourceSpan
4747 -- End of the span
4848 --
4949 , spanEnd :: SourcePos
50− } deriving (D.Data, D.Typeable)
50+ } deriving (Eq, D.Data, D.Typeable)
5151
5252instance Show SourceSpan where
5353 show sp = spanName sp ++ " " ++ show (spanStart sp) ++ " - " ++ show (spanEnd sp)
src/Language/PureScript/Errors.hs+354−91
@@ -12,108 +12,378 @@
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(..))
2122import Data.List (intersperse, intercalate)
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
35+import Language.PureScript.TypeClassDictionaries
3036
3137-- |
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)
43−
44−-- |
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− }
38+-- A type of error messages
39+--
40+data ErrorMessage
41+ = InfiniteType Type
42+ | InfiniteKind Kind
43+ | CannotReorderOperators
44+ | MultipleFixities Ident
45+ | OrphanTypeDeclaration Ident
46+ | OrphanFixityDeclaration String
47+ | RedefinedModule ModuleName
48+ | RedefinedIdent Ident
49+ | OverlappingNamesInLet
50+ | UnknownModule ModuleName
51+ | UnknownType (Qualified ProperName)
52+ | UnknownTypeClass (Qualified ProperName)
53+ | UnknownValue (Qualified Ident)
54+ | UnknownDataConstructor (Qualified ProperName) (Maybe (Qualified ProperName))
55+ | UnknownTypeConstructor (Qualified ProperName)
56+ | ConflictingImport String ModuleName
57+ | ConflictingImports String ModuleName ModuleName
58+ | ConflictingTypeDecls ProperName
59+ | ConflictingCtorDecls ProperName
60+ | TypeConflictsWithClass ProperName
61+ | CtorConflictsWithClass ProperName
62+ | ClassConflictsWithType ProperName
63+ | ClassConflictsWithCtor ProperName
64+ | DuplicateClassExport ProperName
65+ | DuplicateValueExport Ident
66+ | DuplicateTypeArgument String
67+ | InvalidDoBind
68+ | InvalidDoLet
69+ | CycleInDeclaration Ident
70+ | CycleInTypeSynonym (Maybe ProperName)
71+ | NameIsUndefined Ident
72+ | NameNotInScope Ident
73+ | UndefinedTypeVariable ProperName
74+ | PartiallyAppliedSynonym (Qualified ProperName)
75+ | NotYetDefined [Ident] ErrorMessage
76+ | EscapedSkolem (Maybe Expr)
77+ | UnspecifiedSkolemScope
78+ | TypesDoNotUnify Type Type
79+ | KindsDoNotUnify Kind Kind
80+ | ConstrainedTypeUnified Type Type
81+ | OverlappingInstances (Qualified ProperName) [Type] [DictionaryValue]
82+ | NoInstanceFound (Qualified ProperName) [Type]
83+ | DuplicateLabel String (Maybe Expr)
84+ | DuplicateValueDeclaration Ident
85+ | ArgListLengthsDiffer Ident
86+ | OverlappingArgNames (Maybe Ident)
87+ | MissingClassMember Ident
88+ | ExpectedType Kind
89+ | IncorrectConstructorArity (Qualified ProperName)
90+ | SubsumptionCheckFailed
91+ | ExprDoesNotHaveType Expr Type
92+ | PropertyIsMissing String Type
93+ | ErrorUnifyingTypes Type Type ErrorMessage
94+ | CannotApplyFunction Type Expr
95+ | TypeSynonymInstance
96+ | InvalidNewtype
97+ | InvalidInstanceHead Type
98+ | TransitiveExportError DeclarationRef [DeclarationRef]
99+ | ErrorInExpression Expr ErrorMessage
100+ | ErrorInModule ModuleName ErrorMessage
101+ | ErrorInInstance (Qualified ProperName) [Type] ErrorMessage
102+ | ErrorInSubsumption Type Type ErrorMessage
103+ | ErrorCheckingType Expr Type ErrorMessage
104+ | ErrorCheckingKind Type ErrorMessage
105+ | ErrorInferringType Expr ErrorMessage
106+ | ErrorInApplication Expr Type Expr ErrorMessage
107+ | ErrorInDataConstructor ProperName ErrorMessage
108+ | ErrorInTypeConstructor ProperName ErrorMessage
109+ | ErrorInBindingGroup [Ident] ErrorMessage
110+ | ErrorInDataBindingGroup ErrorMessage
111+ | ErrorInTypeSynonym ProperName ErrorMessage
112+ | ErrorInValueDeclaration Ident ErrorMessage
113+ | ErrorInForeignImport Ident ErrorMessage
114+ | PositionedError SourceSpan ErrorMessage
62115 deriving (Show)
116+
117+instance UnificationError Type ErrorMessage where
118+ occursCheckFailed = InfiniteType
119+
120+instance UnificationError Kind ErrorMessage where
121+ occursCheckFailed = InfiniteKind
63122
64123-- |
65−-- A stack trace for an error
124+-- Get the error code for a particular error type
66125--
67−data ErrorStack
68− = ErrorStack { runErrorStack :: [CompileError] }
69− | MultipleErrors [ErrorStack] deriving (Show)
126+errorCode :: ErrorMessage -> String
127+errorCode (InfiniteType _) = "InfiniteType"
128+errorCode (InfiniteKind _) = "InfiniteKind"
129+errorCode CannotReorderOperators = "CannotReorderOperators"
130+errorCode (MultipleFixities _) = "MultipleFixities"
131+errorCode (OrphanTypeDeclaration _) = "OrphanTypeDeclaration"
132+errorCode (OrphanFixityDeclaration _) = "OrphanFixityDeclaration"
133+errorCode (RedefinedModule _) = "RedefinedModule"
134+errorCode (RedefinedIdent _) = "RedefinedIdent"
135+errorCode OverlappingNamesInLet = "OverlappingNamesInLet"
136+errorCode (UnknownModule _) = "UnknownModule"
137+errorCode (UnknownType _) = "UnknownType"
138+errorCode (UnknownTypeClass _) = "UnknownTypeClass"
139+errorCode (UnknownValue _) = "UnknownValue"
140+errorCode (UnknownDataConstructor _ _) = "UnknownDataConstructor"
141+errorCode (UnknownTypeConstructor _) = "UnknownTypeConstructor"
142+errorCode (ConflictingImport _ _) = "ConflictingImport"
143+errorCode (ConflictingImports _ _ _) = "ConflictingImports"
144+errorCode (ConflictingTypeDecls _) = "ConflictingTypeDecls"
145+errorCode (ConflictingCtorDecls _) = "ConflictingCtorDecls"
146+errorCode (TypeConflictsWithClass _) = "TypeConflictsWithClass"
147+errorCode (CtorConflictsWithClass _) = "CtorConflictsWithClass"
148+errorCode (ClassConflictsWithType _) = "ClassConflictsWithType"
149+errorCode (ClassConflictsWithCtor _) = "ClassConflictsWithCtor"
150+errorCode (DuplicateClassExport _) = "DuplicateClassExport"
151+errorCode (DuplicateValueExport _) = "DuplicateValueExport"
152+errorCode (DuplicateTypeArgument _) = "DuplicateTypeArgument"
153+errorCode InvalidDoBind = "InvalidDoBind"
154+errorCode InvalidDoLet = "InvalidDoLet"
155+errorCode (CycleInDeclaration _) = "CycleInDeclaration"
156+errorCode (CycleInTypeSynonym _) = "CycleInTypeSynonym"
157+errorCode (NameIsUndefined _) = "NameIsUndefined"
158+errorCode (NameNotInScope _) = "NameNotInScope"
159+errorCode (UndefinedTypeVariable _) = "UndefinedTypeVariable"
160+errorCode (PartiallyAppliedSynonym _) = "PartiallyAppliedSynonym"
161+errorCode (EscapedSkolem _) = "EscapedSkolem"
162+errorCode UnspecifiedSkolemScope = "UnspecifiedSkolemScope"
163+errorCode (TypesDoNotUnify _ _) = "TypesDoNotUnify"
164+errorCode (KindsDoNotUnify _ _) = "KindsDoNotUnify"
165+errorCode (ConstrainedTypeUnified _ _) = "ConstrainedTypeUnified"
166+errorCode (OverlappingInstances _ _ _) = "OverlappingInstances"
167+errorCode (NoInstanceFound _ _) = "NoInstanceFound"
168+errorCode (DuplicateLabel _ _) = "DuplicateLabel"
169+errorCode (DuplicateValueDeclaration _) = "DuplicateValueDeclaration"
170+errorCode (ArgListLengthsDiffer _) = "ArgListLengthsDiffer"
171+errorCode (OverlappingArgNames _) = "OverlappingArgNames"
172+errorCode (MissingClassMember _) = "MissingClassMember"
173+errorCode (ExpectedType _) = "ExpectedType"
174+errorCode (IncorrectConstructorArity _) = "IncorrectConstructorArity"
175+errorCode SubsumptionCheckFailed = "SubsumptionCheckFailed"
176+errorCode (ExprDoesNotHaveType _ _) = "ExprDoesNotHaveType"
177+errorCode (PropertyIsMissing _ _) = "PropertyIsMissing"
178+errorCode (ErrorUnifyingTypes _ _ _) = "ErrorUnifyingTypes"
179+errorCode (CannotApplyFunction _ _) = "CannotApplyFunction"
180+errorCode TypeSynonymInstance = "TypeSynonymInstance"
181+errorCode InvalidNewtype = "InvalidNewtype"
182+errorCode (InvalidInstanceHead _) = "InvalidInstanceHead"
183+errorCode (TransitiveExportError _ _) = "TransitiveExportError"
184+errorCode (NotYetDefined _ e) = errorCode e
185+errorCode (ErrorInExpression _ e) = errorCode e
186+errorCode (ErrorInModule _ e) = errorCode e
187+errorCode (ErrorInInstance _ _ e) = errorCode e
188+errorCode (ErrorInSubsumption _ _ e) = errorCode e
189+errorCode (ErrorCheckingType _ _ e) = errorCode e
190+errorCode (ErrorCheckingKind _ e) = errorCode e
191+errorCode (ErrorInferringType _ e) = errorCode e
192+errorCode (ErrorInApplication _ _ _ e) = errorCode e
193+errorCode (ErrorInDataConstructor _ e) = errorCode e
194+errorCode (ErrorInTypeConstructor _ e) = errorCode e
195+errorCode (ErrorInBindingGroup _ e) = errorCode e
196+errorCode (ErrorInDataBindingGroup e) = errorCode e
197+errorCode (ErrorInTypeSynonym _ e) = errorCode e
198+errorCode (ErrorInValueDeclaration _ e) = errorCode e
199+errorCode (ErrorInForeignImport _ e) = errorCode e
200+errorCode (PositionedError _ e) = errorCode e
70201
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]
76−
77−instance IsString ErrorStack where
78− fromString = strMsg
202+-- |
203+-- Pretty print an ErrorMessage
204+--
205+prettyPrintErrorMessage :: ErrorMessage -> String
206+prettyPrintErrorMessage e =
207+ go e ++ "\n\nSee " ++ wikiUri ++ " for more information, or to contribute content related to this error."
208+ where
209+ wikiUri :: String
210+ wikiUri = "https://github.com/purescript/purescript/wiki/Error-Code-" ++ errorCode e
211+
212+ go :: ErrorMessage -> String
213+ go InvalidDoBind = "Bind statement cannot be the last statement in a do block"
214+ go InvalidDoLet = "Let statement cannot be the last statement in a do block"
215+ go CannotReorderOperators = "Unable to reorder operators"
216+ go UnspecifiedSkolemScope = "Skolem variable scope is unspecified"
217+ go OverlappingNamesInLet = "Overlapping names in let binding."
218+ go (InfiniteType ty) = "Infinite type detected: " ++ prettyPrintType ty
219+ go (InfiniteKind ki) = "Infinite kind detected: " ++ prettyPrintKind ki
220+ go (MultipleFixities name) = "Multiple fixity declarations for " ++ show name
221+ go (OrphanTypeDeclaration nm) = "Orphan type declaration for " ++ show nm
222+ go (OrphanFixityDeclaration op) = "Orphan fixity declaration for " ++ show op
223+ go (RedefinedModule name) = "Module " ++ show name ++ " has been defined multiple times"
224+ go (RedefinedIdent name) = "Name " ++ show name ++ " has been defined multiple times"
225+ go (UnknownModule mn) = "Unknown module " ++ show mn
226+ go (UnknownType name) = "Unknown type " ++ show name
227+ go (UnknownTypeClass name) = "Unknown type class " ++ show name
228+ go (UnknownValue name) = "Unknown value " ++ show name
229+ go (UnknownTypeConstructor name) = "Unknown type constructor " ++ show name
230+ go (UnknownDataConstructor dc tc) = "Unknown data constructor " ++ show dc ++ foldMap ((" for type constructor " ++) . show) tc
231+ go (ConflictingImport nm mn) = "Declaration " ++ nm ++ " conflicts with import " ++ show mn
232+ go (ConflictingImports nm m1 m2) = "Conflicting imports for " ++ nm ++ " from modules " ++ show m1 ++ " and " ++ show m2
233+ go (ConflictingTypeDecls nm) = "Conflicting type declarations for " ++ show nm
234+ go (ConflictingCtorDecls nm) = "Conflicting data constructor declarations for " ++ show nm
235+ go (TypeConflictsWithClass nm) = "Type " ++ show nm ++ " conflicts with type class declaration of the same name"
236+ go (CtorConflictsWithClass nm) = "Data constructor " ++ show nm ++ " conflicts with type class declaration of the same name"
237+ go (ClassConflictsWithType nm) = "Type class " ++ show nm ++ " conflicts with type declaration of the same name"
238+ go (ClassConflictsWithCtor nm) = "Type class " ++ show nm ++ " conflicts with data constructor declaration of the same name"
239+ go (DuplicateClassExport nm) = "Duplicate export declaration for type class " ++ show nm
240+ go (DuplicateValueExport nm) = "Duplicate export declaration for value " ++ show nm
241+ go (CycleInDeclaration nm) = "Cycle in declaration of " ++ show nm
242+ go (NotYetDefined names err) = "The following are not yet defined here: " ++ unwords (map show names) ++ "\n" ++ go err
243+ go (CycleInTypeSynonym pn) = "Cycle in type synonym" ++ foldMap ((" " ++) . show) pn
244+ go (NameIsUndefined ident) = show ident ++ " is undefined"
245+ go (NameNotInScope ident) = show ident ++ " may not be defined in the current scope"
246+ go (UndefinedTypeVariable name) = "Type variable " ++ show name ++ " is undefined"
247+ go (PartiallyAppliedSynonym name) = "Partially applied type synonym " ++ show name
248+ go (EscapedSkolem binding) = "Rigid/skolem type variable " ++ foldMap (("bound by " ++) . prettyPrintValue) binding ++ " has escaped."
249+ go (TypesDoNotUnify t1 t2) = "Cannot unify " ++ prettyPrintType t1 ++ " with " ++ prettyPrintType t2
250+ go (KindsDoNotUnify k1 k2) = "Cannot unify " ++ prettyPrintKind k1 ++ " with " ++ prettyPrintKind k2
251+ go (ConstrainedTypeUnified t1 t2) = "Cannot unify constrained type " ++ prettyPrintType t1 ++ " with " ++ prettyPrintType t2
252+ go (OverlappingInstances nm ts ds) = unlines ( ("Overlapping instances found for " ++ show nm ++ " " ++ unwords (map prettyPrintType ts) ++ ":")
253+ : map prettyPrintDictionaryValue ds)
254+ go (NoInstanceFound nm ts) = "No instance found for " ++ show nm ++ " " ++ unwords (map prettyPrintTypeAtom ts)
255+ go (DuplicateLabel l expr) = "Duplicate label " ++ show l ++ " in row." ++ foldMap ((" Relevant expression: " ++) . prettyPrintValue) expr
256+ go (DuplicateTypeArgument name) = "Duplicate type argument " ++ show name
257+ go (DuplicateValueDeclaration nm) = "Duplicate value declaration for " ++ show nm
258+ go (ArgListLengthsDiffer ident) = "Argument list lengths differ in declaration " ++ show ident
259+ go (OverlappingArgNames ident) = "Overlapping names in function/binder" ++ foldMap ((" in declaration" ++) . show) ident
260+ go (MissingClassMember ident) = "Member " ++ show ident ++ " has not been implemented"
261+ go (ExpectedType kind) = "Expected type of kind *, was " ++ prettyPrintKind kind
262+ go (IncorrectConstructorArity nm) = "Wrong number of arguments to constructor " ++ show nm
263+ go SubsumptionCheckFailed = "Unable to check type subsumption"
264+ go (ExprDoesNotHaveType expr ty) = "Expression " ++ prettyPrintValue expr ++ " does not have type " ++ prettyPrintType ty
265+ go (PropertyIsMissing prop row) = "Row " ++ prettyPrintRow row ++ " lacks required property " ++ show prop
266+ go (CannotApplyFunction fn arg) = "Cannot apply function of type " ++ prettyPrintType fn ++ " to argument " ++ prettyPrintValue arg
267+ go TypeSynonymInstance = "Type synonym instances are disallowed"
268+ go InvalidNewtype = "Newtypes must define a single constructor with a single argument"
269+ go (InvalidInstanceHead ty) = "Invalid type " ++ prettyPrintType ty ++ " in class instance head"
270+ go (TransitiveExportError x ys) = "An export for " ++ prettyPrintExport x ++ " requires the following to also be exported: " ++ intercalate ", " (map prettyPrintExport ys)
271+ go (ErrorUnifyingTypes t1 t2 err) = "Error unifying type " ++ prettyPrintType t1 ++ " with type " ++ prettyPrintType t2 ++ ":\n" ++ go err
272+ go (ErrorInExpression expr err) = "Error in expression " ++ prettyPrintValue expr ++ ":\n" ++ go err
273+ go (ErrorInModule mn err) = "Error in module " ++ show mn ++ ":\n" ++ go err
274+ go (ErrorInSubsumption t1 t2 err) = "Error checking that type " ++ prettyPrintType t1 ++ " subsumes type " ++ prettyPrintType t2 ++ ":\n" ++ go err
275+ go (ErrorInInstance name ts err) = "Error in type class instance " ++ show name ++ " " ++ unwords (map prettyPrintTypeAtom ts) ++ ":\n" ++ go err
276+ go (ErrorCheckingKind ty err) = "Error checking kind of type " ++ prettyPrintType ty ++ ":\n" ++ go err
277+ go (ErrorInferringType expr err) = "Error inferring type of value " ++ prettyPrintValue expr ++ ":\n" ++ go err
278+ go (ErrorCheckingType expr ty err) = "Error checking value " ++ prettyPrintValue expr ++ " has type " ++ prettyPrintType ty ++ ":\n" ++ go err
279+ go (ErrorInApplication f t a err) = "Error applying function " ++ prettyPrintValue f ++ " of type " ++ prettyPrintType t ++ " to argument " ++ prettyPrintValue a ++ ":\n" ++ go err
280+ go (ErrorInDataConstructor nm err) = "Error in data constructor " ++ show nm ++ ":\n" ++ go err
281+ go (ErrorInTypeConstructor nm err) = "Error in type constructor " ++ show nm ++ ":\n" ++ go err
282+ go (ErrorInBindingGroup nms err) = "Error in binding group " ++ intercalate ", " (map show nms) ++ ":\n" ++ go err
283+ go (ErrorInDataBindingGroup err) = "Error in data binding group:\n" ++ go err
284+ go (ErrorInTypeSynonym name err) = "Error in type synonym " ++ show name ++ ":\n" ++ go err
285+ go (ErrorInValueDeclaration n err) = "Error in value declaration " ++ show n ++ ":\n" ++ go err
286+ go (ErrorInForeignImport nm err) = "Error in foreign import " ++ show nm ++ ":\n" ++ go err
287+ go (PositionedError pos err) = "Error at " ++ show pos ++ ":\n" ++ go err
79288
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'
289+-- |
290+-- Render a DictionaryValue fit for human consumption in error messages
291+--
292+prettyPrintDictionaryValue :: DictionaryValue -> String
293+prettyPrintDictionaryValue = unlines . indented 0
85294 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
295+ indented n (LocalDictionaryValue _) = [spaces n ++ "Dictionary in scope"]
296+ indented n (GlobalDictionaryValue nm) = [spaces n ++ show nm]
297+ indented n (DependentDictionaryValue nm args) = (spaces n ++ show nm ++ " via") : concatMap (indented (n + 2)) args
298+ indented n (SubclassDictionaryValue sup nm _) = (spaces n ++ show nm ++ " via superclass") : indented (n + 2) sup
97299
98−stringifyErrorStack :: (MonadError String m) => Bool -> Either ErrorStack a -> m a
99−stringifyErrorStack printFullStack = either (throwError . prettyPrintErrorStack printFullStack) return
300+ spaces n = replicate n ' ' ++ "- "
301+
302+-- |
303+-- Pretty print and export declaration
304+--
305+prettyPrintExport :: DeclarationRef -> String
306+prettyPrintExport (TypeRef pn _) = show pn
307+prettyPrintExport (ValueRef ident) = show ident
308+prettyPrintExport (TypeClassRef pn) = show pn
309+prettyPrintExport (TypeInstanceRef ident) = show ident
310+prettyPrintExport (PositionedDeclarationRef _ _ ref) = prettyPrintExport ref
311+
312+-- |
313+-- A stack trace for an error
314+--
315+newtype MultipleErrors = MultipleErrors
316+ { runMultipleErrors :: [ErrorMessage] } deriving (Show, Monoid)
317+
318+instance UnificationError Type MultipleErrors where
319+ occursCheckFailed = errorMessage . occursCheckFailed
320+
321+instance UnificationError Kind MultipleErrors where
322+ occursCheckFailed = errorMessage . occursCheckFailed
100323
101−isErrorNonEmpty :: CompileError -> Bool
102−isErrorNonEmpty = not . null . compileErrorMessage
324+-- |
325+-- Simplify an error message
326+--
327+simplifyErrorMessage :: ErrorMessage -> ErrorMessage
328+simplifyErrorMessage = unwrap Nothing
329+ where
330+ unwrap :: Maybe SourceSpan -> ErrorMessage -> ErrorMessage
331+ unwrap pos (ErrorInExpression _ err) = unwrap pos err
332+ unwrap pos (ErrorInInstance name ts err) = ErrorInInstance name ts (unwrap pos err)
333+ unwrap pos (ErrorInSubsumption t1 t2 err) = ErrorInSubsumption t1 t2 (unwrap pos err)
334+ unwrap pos (ErrorUnifyingTypes _ _ err) = unwrap pos err
335+ unwrap pos (ErrorInferringType _ err) = unwrap pos err
336+ unwrap pos (ErrorCheckingType _ _ err) = unwrap pos err
337+ unwrap pos (ErrorCheckingKind ty err) = ErrorCheckingKind ty (unwrap pos err)
338+ unwrap pos (ErrorInModule mn err) = ErrorInModule mn (unwrap pos err)
339+ unwrap pos (ErrorInApplication _ _ _ err) = unwrap pos err
340+ unwrap pos (ErrorInDataConstructor nm err) = ErrorInDataConstructor nm (unwrap pos err)
341+ unwrap pos (ErrorInTypeConstructor nm err) = ErrorInTypeConstructor nm (unwrap pos err)
342+ unwrap pos (ErrorInBindingGroup nms err) = ErrorInBindingGroup nms (unwrap pos err)
343+ unwrap pos (ErrorInDataBindingGroup err) = ErrorInDataBindingGroup (unwrap pos err)
344+ unwrap pos (ErrorInTypeSynonym nm err) = ErrorInTypeSynonym nm (unwrap pos err)
345+ unwrap pos (ErrorInValueDeclaration nm err) = ErrorInValueDeclaration nm (unwrap pos err)
346+ unwrap pos (ErrorInForeignImport nm err) = ErrorInForeignImport nm (unwrap pos err)
347+ unwrap pos (NotYetDefined ns err) = NotYetDefined ns (unwrap pos err)
348+ unwrap _ (PositionedError pos err) = unwrap (Just pos) err
349+ unwrap pos other = wrap pos other
350+
351+ wrap :: Maybe SourceSpan -> ErrorMessage -> ErrorMessage
352+ wrap Nothing = id
353+ wrap (Just pos) = PositionedError pos
103354
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
355+-- |
356+-- Create an error set from a single error message
357+--
358+errorMessage :: ErrorMessage -> MultipleErrors
359+errorMessage err = MultipleErrors [err]
108360
109−mkErrorStack :: String -> Maybe ErrorSource -> ErrorStack
110−mkErrorStack msg t = ErrorStack [mkCompileError msg t]
361+-- |
362+-- Lift a function on ErrorMessage to a function on MultipleErrors
363+--
364+onErrorMessages :: (ErrorMessage -> ErrorMessage) -> MultipleErrors -> MultipleErrors
365+onErrorMessages f = MultipleErrors . map f . runMultipleErrors
366+
367+-- |
368+-- Pretty print a single error, simplifying if necessary
369+--
370+prettyPrintSingleError :: Bool -> ErrorMessage -> String
371+prettyPrintSingleError full e = prettyPrintErrorMessage (if full then e else simplifyErrorMessage e)
111372
112−mkCompileError :: String -> Maybe ErrorSource -> CompileError
113−mkCompileError msg t = CompileError msg t Nothing
373+-- |
374+-- Pretty print multiple errors
375+--
376+prettyPrintMultipleErrors :: Bool -> MultipleErrors -> String
377+prettyPrintMultipleErrors full (MultipleErrors [e]) =
378+ prettyPrintSingleError full e
379+prettyPrintMultipleErrors full (MultipleErrors es) =
380+ unlines $ intersperse "" $ "Multiple errors:" : map (prettyPrintSingleError full) es
114381
115−positionError :: SourceSpan -> CompileError
116−positionError pos = CompileError "" Nothing (Just pos)
382+-- |
383+-- Interpret multiple errors in a monad supporting errors
384+--
385+interpretMultipleErrors :: (MonadError String m) => Bool -> Either MultipleErrors a -> m a
386+interpretMultipleErrors printFullStack = either (throwError . prettyPrintMultipleErrors printFullStack) return
117387
118388-- |
119389-- Rethrow an error with a more detailed error message in the case of failure
@@ -124,30 +394,23 @@ rethrow f = flip catchError $ \e -> throwError (f e)
124394-- |
125395-- Rethrow an error with source position information
126396--
127−rethrowWithPosition :: (MonadError ErrorStack m) => SourceSpan -> m a -> m a
128−rethrowWithPosition pos = rethrow (positionError pos `combineErrors`)
397+rethrowWithPosition :: (MonadError MultipleErrors m) => SourceSpan -> m a -> m a
398+rethrowWithPosition pos = rethrow (onErrorMessages withPosition)
399+ where
400+ withPosition :: ErrorMessage -> ErrorMessage
401+ withPosition (PositionedError _ err) = withPosition err
402+ withPosition err = PositionedError pos err
129403
130404-- |
131405-- Collect errors in in parallel
132406--
133−parU :: (MonadError ErrorStack m, Functor m) => [a] -> (a -> m b) -> m [b]
407+parU :: (MonadError MultipleErrors m, Functor m) => [a] -> (a -> m b) -> m [b]
134408parU xs f = forM xs (withError . f) >>= collectErrors
135409 where
136− withError :: (MonadError ErrorStack m, Functor m) => m a -> m (Either ErrorStack a)
410+ withError :: (MonadError MultipleErrors m, Functor m) => m a -> m (Either MultipleErrors a)
137411 withError u = catchError (Right <$> u) (return . Left)
138412
139− collectErrors :: (MonadError ErrorStack m, Functor m) => [Either ErrorStack a] -> m [a]
413+ collectErrors :: (MonadError MultipleErrors m, Functor m) => [Either MultipleErrors a] -> m [a]
140414 collectErrors es = case lefts es of
141− [err] -> throwError err
142415 [] -> 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 ]
416+ errs -> throwError $ fold errs
src/Language/PureScript/Sugar.hs+1−1
@@ -58,7 +58,7 @@ import Language.PureScript.Sugar.TypeDeclarations as S
5858--
5959-- * Group mutually recursive value and data declarations into binding groups.
6060--
61−desugar :: (Applicative m, MonadSupply m, MonadError ErrorStack m) => [Module] -> m [Module]
61+desugar :: (Applicative m, MonadSupply m, MonadError MultipleErrors m) => [Module] -> m [Module]
6262desugar = map removeSignedLiterals
6363 >>> mapM desugarObjectConstructors
6464 >=> mapM desugarOperatorSections
src/Language/PureScript/Sugar/BindingGroups.hs+12−13
@@ -41,7 +41,7 @@ import Language.PureScript.Errors
4141-- |
4242-- Replace all sets of mutually-recursive declarations in a module with binding groups
4343--
44−createBindingGroupsModule :: (Functor m, Applicative m, MonadError ErrorStack m) => [Module] -> m [Module]
44+createBindingGroupsModule :: (Functor m, Applicative m, MonadError MultipleErrors m) => [Module] -> m [Module]
4545createBindingGroupsModule = mapM $ \(Module coms name ds exps) -> Module coms name <$> createBindingGroups name ds <*> pure exps
4646
4747-- |
@@ -50,20 +50,20 @@ createBindingGroupsModule = mapM $ \(Module coms name ds exps) -> Module coms na
5050collapseBindingGroupsModule :: [Module] -> [Module]
5151collapseBindingGroupsModule = map $ \(Module coms name ds exps) -> Module coms name (collapseBindingGroups ds) exps
5252
53−createBindingGroups :: (Functor m, Applicative m, MonadError ErrorStack m) => ModuleName -> [Declaration] -> m [Declaration]
53+createBindingGroups :: (Functor m, Applicative m, MonadError MultipleErrors m) => ModuleName -> [Declaration] -> m [Declaration]
5454createBindingGroups moduleName = mapM f <=< handleDecls
5555
5656 where
5757 (f, _, _) = everywhereOnValuesTopDownM return handleExprs return
5858
59− handleExprs :: (Functor m, MonadError ErrorStack m) => Expr -> m Expr
59+ handleExprs :: (Functor m, MonadError MultipleErrors m) => Expr -> m Expr
6060 handleExprs (Let ds val) = flip Let val <$> handleDecls ds
6161 handleExprs other = return other
6262
6363 -- |
6464 -- Replace all sets of mutually-recursive declarations with binding groups
6565 --
66− handleDecls :: (Functor m, MonadError ErrorStack m) => [Declaration] -> m [Declaration]
66+ handleDecls :: (Functor m, MonadError MultipleErrors m) => [Declaration] -> m [Declaration]
6767 handleDecls ds = do
6868 let values = filter isValueDecl ds
6969 dataDecls = filter isDataDecl ds
@@ -155,7 +155,7 @@ getProperName _ = error "Expected DataDeclaration"
155155-- Convert a group of mutually-recursive dependencies into a BindingGroupDeclaration (or simple ValueDeclaration).
156156--
157157--
158−toBindingGroup :: (Functor m, MonadError ErrorStack m) => ModuleName -> SCC Declaration -> m Declaration
158+toBindingGroup :: (Functor m, MonadError MultipleErrors m) => ModuleName -> SCC Declaration -> m Declaration
159159toBindingGroup _ (AcyclicSCC d) = return d
160160toBindingGroup _ (CyclicSCC [d]) = return d
161161toBindingGroup moduleName (CyclicSCC ds') =
@@ -176,24 +176,23 @@ toBindingGroup moduleName (CyclicSCC ds') =
176176 valueVerts :: [(Declaration, Ident, [Ident])]
177177 valueVerts = map (\d -> (d, getIdent d, usedImmediateIdents moduleName d `intersect` idents)) ds'
178178
179− toBinding :: (MonadError ErrorStack m) => SCC Declaration -> m (Ident, NameKind, Expr)
179+ toBinding :: (MonadError MultipleErrors m) => SCC Declaration -> m (Ident, NameKind, Expr)
180180 toBinding (AcyclicSCC d) = return $ fromValueDecl d
181181 toBinding (CyclicSCC ~(d:ds)) = cycleError d ds
182182
183− cycleError :: (MonadError ErrorStack m) => Declaration -> [Declaration] -> m a
183+ cycleError :: (MonadError MultipleErrors m) => Declaration -> [Declaration] -> m a
184184 cycleError (PositionedDeclaration p _ d) ds = rethrowWithPosition p $ cycleError d ds
185− cycleError (ValueDeclaration n _ _ (Right e)) [] = throwError $
186− mkErrorStack ("Cycle in definition of " ++ show n) (Just (ExprError e))
187− cycleError d ds@(_:_) = rethrow (mkCompileError ("The following are not yet defined here: " ++ unwords (map (show . getIdent) ds)) Nothing `combineErrors`) $ cycleError d []
185+ cycleError (ValueDeclaration n _ _ (Right _)) [] = throwError . errorMessage $ CycleInDeclaration n
186+ cycleError d ds@(_:_) = rethrow (onErrorMessages (NotYetDefined (map getIdent ds))) $ cycleError d []
188187 cycleError _ _ = error "Expected ValueDeclaration"
189188
190−toDataBindingGroup :: (MonadError ErrorStack m) => SCC Declaration -> m Declaration
189+toDataBindingGroup :: (MonadError MultipleErrors m) => SCC Declaration -> m Declaration
191190toDataBindingGroup (AcyclicSCC d) = return d
192191toDataBindingGroup (CyclicSCC [d]) = case isTypeSynonym d of
193− Just pn -> throwError $ mkErrorStack ("Cycle in type synonym " ++ show pn) Nothing
192+ Just pn -> throwError . errorMessage $ CycleInTypeSynonym (Just pn)
194193 _ -> return d
195194toDataBindingGroup (CyclicSCC ds')
196− | all (isJust . isTypeSynonym) ds' = throwError $ mkErrorStack "Cycle in type synonyms" Nothing
195+ | all (isJust . isTypeSynonym) ds' = throwError . errorMessage $ CycleInTypeSynonym Nothing
197196 | otherwise = return $ DataBindingGroupDeclaration ds'
198197
199198isTypeSynonym :: Declaration -> Maybe ProperName
src/Language/PureScript/Sugar/CaseDeclarations.hs+11−11
@@ -44,17 +44,17 @@ isLeft (Right _) = False
4444-- |
4545-- Replace all top-level binders in a module with case expressions.
4646--
47−desugarCasesModule :: (Functor m, Applicative m, MonadSupply m, MonadError ErrorStack m) => [Module] -> m [Module]
47+desugarCasesModule :: (Functor m, Applicative m, MonadSupply m, MonadError MultipleErrors m) => [Module] -> m [Module]
4848desugarCasesModule ms = forM ms $ \(Module coms name ds exps) ->
49− rethrow (mkCompileError ("Error in module " ++ show name) Nothing `combineErrors`) $
49+ rethrow (onErrorMessages (ErrorInModule name)) $
5050 Module coms name <$> (desugarCases <=< desugarAbs $ ds) <*> pure exps
5151
52−desugarAbs :: (Functor m, Applicative m, MonadSupply m, MonadError ErrorStack m) => [Declaration] -> m [Declaration]
52+desugarAbs :: (Functor m, Applicative m, MonadSupply m, MonadError MultipleErrors m) => [Declaration] -> m [Declaration]
5353desugarAbs = flip parU f
5454 where
5555 (f, _, _) = everywhereOnValuesM return replace return
5656
57− replace :: (Functor m, Applicative m, MonadSupply m, MonadError ErrorStack m) => Expr -> m Expr
57+ replace :: (Functor m, Applicative m, MonadSupply m, MonadError MultipleErrors m) => Expr -> m Expr
5858 replace (Abs (Right binder) val) = do
5959 ident <- Ident <$> freshName
6060 return $ Abs (Left ident) $ Case [Var (Qualified Nothing ident)] [CaseAlternative [binder] (Right val)]
@@ -63,10 +63,10 @@ desugarAbs = flip parU f
6363-- |
6464-- Replace all top-level binders with case expressions.
6565--
66−desugarCases :: (Functor m, Applicative m, MonadSupply m, MonadError ErrorStack m) => [Declaration] -> m [Declaration]
66+desugarCases :: (Functor m, Applicative m, MonadSupply m, MonadError MultipleErrors m) => [Declaration] -> m [Declaration]
6767desugarCases = desugarRest <=< fmap join . flip parU toDecls . groupBy inSameGroup
6868 where
69− desugarRest :: (Functor m, Applicative m, MonadSupply m, MonadError ErrorStack m) => [Declaration] -> m [Declaration]
69+ desugarRest :: (Functor m, Applicative m, MonadSupply m, MonadError MultipleErrors m) => [Declaration] -> m [Declaration]
7070 desugarRest (TypeInstanceDeclaration name constraints className tys ds : rest) =
7171 (:) <$> (TypeInstanceDeclaration name constraints className tys <$> desugarCases ds) <*> desugarRest rest
7272 desugarRest (ValueDeclaration name nameKind bs result : rest) =
@@ -89,18 +89,18 @@ inSameGroup (PositionedDeclaration _ _ d1) d2 = inSameGroup d1 d2
8989inSameGroup d1 (PositionedDeclaration _ _ d2) = inSameGroup d1 d2
9090inSameGroup _ _ = False
9191
92−toDecls :: (Functor m, Applicative m, MonadSupply m, MonadError ErrorStack m) => [Declaration] -> m [Declaration]
92+toDecls :: (Functor m, Applicative m, MonadSupply m, MonadError MultipleErrors m) => [Declaration] -> m [Declaration]
9393toDecls [ValueDeclaration ident nameKind bs (Right val)] | all isVarBinder bs = do
9494 let args = map (\(VarBinder arg) -> arg) bs
9595 body = foldr (Abs . Left) val args
96− guardWith (strMsg "Overlapping function argument names") $ length (nub args) == length args
96+ guardWith (errorMessage (OverlappingArgNames (Just ident))) $ length (nub args) == length args
9797 return [ValueDeclaration ident nameKind [] (Right body)]
9898toDecls ds@(ValueDeclaration ident _ bs result : _) = do
9999 let tuples = map toTuple ds
100100 unless (all ((== length bs) . length . fst) tuples) $
101− throwError $ mkErrorStack ("Argument list lengths differ in declaration " ++ show ident) Nothing
101+ throwError . errorMessage $ ArgListLengthsDiffer ident
102102 unless (not (null bs) || isLeft result) $
103− throwError $ mkErrorStack ("Duplicate value declaration '" ++ show ident ++ "'") Nothing
103+ throwError . errorMessage $ DuplicateValueDeclaration ident
104104 caseDecl <- makeCaseDeclaration ident tuples
105105 return [caseDecl]
106106toDecls (PositionedDeclaration pos com d : ds) = do
@@ -117,7 +117,7 @@ toTuple (ValueDeclaration _ _ bs result) = (bs, result)
117117toTuple (PositionedDeclaration _ _ d) = toTuple d
118118toTuple _ = error "Not a value declaration"
119119
120−makeCaseDeclaration :: (Functor m, Applicative m, MonadSupply m, MonadError ErrorStack m) => Ident -> [([Binder], Either [(Guard, Expr)] Expr)] -> m Declaration
120+makeCaseDeclaration :: (Functor m, Applicative m, MonadSupply m, MonadError MultipleErrors m) => Ident -> [([Binder], Either [(Guard, Expr)] Expr)] -> m Declaration
121121makeCaseDeclaration ident alternatives = do
122122 let argPattern = length . fst . head $ alternatives
123123 args <- map Ident <$> replicateM argPattern freshName
src/Language/PureScript/Sugar/DoNotation.hs+4−4
@@ -35,10 +35,10 @@ import Control.Monad.Supply.Class
3535-- Replace all @DoNotationBind@ and @DoNotationValue@ constructors with applications of the Prelude.(>>=) function,
3636-- and all @DoNotationLet@ constructors with let expressions.
3737--
38−desugarDoModule :: forall m. (Applicative m, MonadSupply m, MonadError ErrorStack m) => Module -> m Module
38+desugarDoModule :: forall m. (Applicative m, MonadSupply m, MonadError MultipleErrors m) => Module -> m Module
3939desugarDoModule (Module coms mn ds exts) = Module coms mn <$> parU ds desugarDo <*> pure exts
4040
41−desugarDo :: forall m. (Applicative m, MonadSupply m, MonadError ErrorStack m) => Declaration -> m Declaration
41+desugarDo :: forall m. (Applicative m, MonadSupply m, MonadError MultipleErrors m) => Declaration -> m Declaration
4242desugarDo (PositionedDeclaration pos com d) = PositionedDeclaration pos com <$> (rethrowWithPosition pos $ desugarDo d)
4343desugarDo d =
4444 let (f, _, _) = everywhereOnValuesM return replace return
@@ -61,7 +61,7 @@ desugarDo d =
6161 go (DoNotationValue val : rest) = do
6262 rest' <- go rest
6363 return $ App (App bind val) (Abs (Left (Ident C.__unused)) rest')
64− go [DoNotationBind _ _] = throwError $ mkErrorStack "Bind statement cannot be the last statement in a do block" Nothing
64+ go [DoNotationBind _ _] = throwError . errorMessage $ InvalidDoBind
6565 go (DoNotationBind NullBinder val : rest) = go (DoNotationValue val : rest)
6666 go (DoNotationBind (VarBinder ident) val : rest) = do
6767 rest' <- go rest
@@ -70,7 +70,7 @@ desugarDo d =
7070 rest' <- go rest
7171 ident <- Ident <$> freshName
7272 return $ App (App bind val) (Abs (Left ident) (Case [Var (Qualified Nothing ident)] [CaseAlternative [binder] (Right rest')]))
73− go [DoNotationLet _] = throwError $ mkErrorStack "Let statement cannot be the last statement in a do block" Nothing
73+ go [DoNotationLet _] = throwError . errorMessage $ InvalidDoLet
7474 go (DoNotationLet ds : rest) = do
7575 rest' <- go rest
7676 return $ Let ds rest'
src/Language/PureScript/Sugar/Names.hs+53−63
@@ -87,7 +87,7 @@ data ImportEnvironment = ImportEnvironment
8787-- Updates the exports for a module from the global environment. If the module was not previously
8888-- present in the global environment, it is created.
8989--
90−updateExportedModule :: (Applicative m, MonadError ErrorStack m) => ExportEnvironment -> ModuleName -> (Exports -> m Exports) -> m ExportEnvironment
90+updateExportedModule :: (Applicative m, MonadError MultipleErrors m) => ExportEnvironment -> ModuleName -> (Exports -> m Exports) -> m ExportEnvironment
9191updateExportedModule env mn update = do
9292 let exports = fromMaybe (error "Module was undefined in updateExportedModule") $ mn `M.lookup` env
9393 exports' <- update exports
@@ -96,61 +96,61 @@ updateExportedModule env mn update = do
9696-- |
9797-- Adds an empty module to an ExportEnvironment.
9898--
99−addEmptyModule :: (Applicative m, MonadError ErrorStack m) => ExportEnvironment -> ModuleName -> m ExportEnvironment
99+addEmptyModule :: (Applicative m, MonadError MultipleErrors m) => ExportEnvironment -> ModuleName -> m ExportEnvironment
100100addEmptyModule env name =
101101 if name `M.member` env
102− then throwError $ mkErrorStack ("Module '" ++ show name ++ "' has been defined more than once") Nothing
102+ then throwError . errorMessage $ RedefinedModule name
103103 else return $ M.insert name (Exports [] [] []) env
104104
105105-- |
106106-- Adds a type belonging to a module to the export environment.
107107--
108−addType :: (Applicative m, MonadError ErrorStack m) => ExportEnvironment -> ModuleName -> ProperName -> [ProperName] -> m ExportEnvironment
108+addType :: (Applicative m, MonadError MultipleErrors m) => ExportEnvironment -> ModuleName -> ProperName -> [ProperName] -> m ExportEnvironment
109109addType env mn name dctors = updateExportedModule env mn $ \m -> do
110110 let exTypes = exportedTypes m
111111 let exDctors = snd `concatMap` exTypes
112112 let exClasses = exportedTypeClasses m
113− when (any ((== name) . fst) exTypes) $ throwMultipleDefError "type" name
114− when (name `elem` exClasses) $ throwConflictingDefError "Type" "type class" name
113+ when (any ((== name) . fst) exTypes) $ throwConflictError ConflictingTypeDecls name
114+ when (name `elem` exClasses) $ throwConflictError TypeConflictsWithClass name
115115 forM_ dctors $ \dctor -> do
116− when (dctor `elem` exDctors) $ throwMultipleDefError "data constructor" dctor
117− when (dctor `elem` exClasses) $ throwConflictingDefError "Data constructor" "type class" dctor
116+ when (dctor `elem` exDctors) $ throwConflictError ConflictingCtorDecls dctor
117+ when (dctor `elem` exClasses) $ throwConflictError CtorConflictsWithClass dctor
118118 return $ m { exportedTypes = (name, dctors) : exTypes }
119119
120120-- |
121121-- Adds a class to the export environment.
122122--
123−addTypeClass :: (Applicative m, MonadError ErrorStack m) => ExportEnvironment -> ModuleName -> ProperName -> m ExportEnvironment
123+addTypeClass :: (Applicative m, MonadError MultipleErrors m) => ExportEnvironment -> ModuleName -> ProperName -> m ExportEnvironment
124124addTypeClass env mn name = updateExportedModule env mn $ \m -> do
125125 let exTypes = exportedTypes m
126126 let exDctors = snd `concatMap` exTypes
127− when (any ((== name) . fst) exTypes) $ throwConflictingDefError "Type class" "type" name
128− when (name `elem` exDctors) $ throwConflictingDefError "Type class" "data constructor" name
129− classes <- addExport "type class" (exportedTypeClasses m) name
127+ when (any ((== name) . fst) exTypes) $ throwConflictError ClassConflictsWithType name
128+ when (name `elem` exDctors) $ throwConflictError ClassConflictsWithCtor name
129+ classes <- addExport DuplicateClassExport (exportedTypeClasses m) name
130130 return $ m { exportedTypeClasses = classes }
131131
132132-- |
133133-- Adds a class to the export environment.
134134--
135−addValue :: (Applicative m, MonadError ErrorStack m) => ExportEnvironment -> ModuleName -> Ident -> m ExportEnvironment
135+addValue :: (Applicative m, MonadError MultipleErrors m) => ExportEnvironment -> ModuleName -> Ident -> m ExportEnvironment
136136addValue env mn name = updateExportedModule env mn $ \m -> do
137− values <- addExport "value" (exportedValues m) name
137+ values <- addExport DuplicateValueExport (exportedValues m) name
138138 return $ m { exportedValues = values }
139139
140140-- |
141141-- Adds an entry to a list of exports unless it is already present, in which case an error is
142142-- returned.
143143--
144−addExport :: (Applicative m, MonadError ErrorStack m, Eq a, Show a) => String -> [a] -> a -> m [a]
144+addExport :: (Applicative m, MonadError MultipleErrors m, Eq a, Show a) => (a -> ErrorMessage) -> [a] -> a -> m [a]
145145addExport what exports name =
146146 if name `elem` exports
147− then throwMultipleDefError what name
147+ then throwConflictError what name
148148 else return $ name : exports
149149
150150-- |
151151-- Replaces all local names with qualified names within a set of modules.
152152--
153−desugarImports :: forall m. (Applicative m, MonadError ErrorStack m) => [Module] -> m [Module]
153+desugarImports :: forall m. (Applicative m, MonadError MultipleErrors m) => [Module] -> m [Module]
154154desugarImports modules = do
155155 unfilteredExports <- findExports modules
156156 exports <- foldM filterModuleExports unfilteredExports modules
@@ -168,7 +168,7 @@ desugarImports modules = do
168168 -- the module has access to an unfiltered list of its own members.
169169 renameInModule' :: ExportEnvironment -> ExportEnvironment -> Module -> m Module
170170 renameInModule' unfilteredExports exports m@(Module _ mn _ _) =
171− rethrow (mkCompileError ("Error in module " ++ show mn) Nothing `combineErrors`) $ do
171+ rethrow (onErrorMessages (ErrorInModule mn)) $ do
172172 let env = M.update (\_ -> M.lookup mn unfilteredExports) mn exports
173173 let exps = fromMaybe (error "Module is missing in renameInModule'") $ M.lookup mn exports
174174 imports <- resolveImports env m
@@ -205,7 +205,7 @@ elaborateImports (Module coms mn decls exps) = Module coms mn decls' exps
205205-- Replaces all local names with qualified names within a module and checks that all existing
206206-- qualified names are valid.
207207--
208−renameInModule :: forall m. (Applicative m, MonadError ErrorStack m) => ImportEnvironment -> ExportEnvironment -> Module -> m Module
208+renameInModule :: forall m. (Applicative m, MonadError MultipleErrors m) => ImportEnvironment -> ExportEnvironment -> Module -> m Module
209209renameInModule imports exports (Module coms mn decls exps) =
210210 Module coms mn <$> parU decls go <*> pure exps
211211 where
@@ -236,7 +236,7 @@ renameInModule imports exports (Module coms mn decls exps) =
236236 let args = mapMaybe letBoundVariable ds
237237 unless (length (nub args) == length args) $
238238 maybe id rethrowWithPosition pos $
239− throwError $ mkErrorStack ("Overlapping names in let binding.") Nothing
239+ throwError . errorMessage $ OverlappingNamesInLet
240240 return ((pos, args ++ bound), Let ds val')
241241 where
242242 updateValue (pos, bound) (Var name'@(Qualified Nothing ident)) | ident `notElem` bound =
@@ -271,28 +271,28 @@ renameInModule imports exports (Module coms mn decls exps) =
271271
272272 updateConstraints pos = mapM (\(name, ts) -> (,) <$> updateClassName name pos <*> mapM (updateTypesEverywhere pos) ts)
273273
274− updateTypeName = update "type" importedTypes (\mes -> isJust . (`lookup` exportedTypes mes))
275− updateClassName = update "type class" importedTypeClasses (flip elem . exportedTypeClasses)
276− updateValueName = update "value" importedValues (flip elem . exportedValues)
277− updateDataConstructorName = update "data constructor" importedDataConstructors (\mes -> flip elem (join $ snd `map` exportedTypes mes))
274+ updateTypeName = update UnknownType importedTypes (\mes -> isJust . (`lookup` exportedTypes mes))
275+ updateClassName = update UnknownTypeClass importedTypeClasses (flip elem . exportedTypeClasses)
276+ updateValueName = update UnknownValue importedValues (flip elem . exportedValues)
277+ updateDataConstructorName = update (flip UnknownDataConstructor Nothing) importedDataConstructors (\mes -> flip elem (join $ snd `map` exportedTypes mes))
278278
279279 -- Update names so unqualified references become qualified, and locally qualified references
280280 -- are replaced with their canoncial qualified names (e.g. M.Map -> Data.Map.Map)
281− update :: (Ord a, Show a) => String
281+ update :: (Ord a, Show a) => (Qualified a -> ErrorMessage)
282282 -> (ImportEnvironment -> M.Map (Qualified a) (Qualified a))
283283 -> (Exports -> a -> Bool)
284284 -> Qualified a
285285 -> Maybe SourceSpan
286286 -> m (Qualified a)
287− update t getI checkE qname@(Qualified mn' name) pos = positioned $ case (M.lookup qname imports', mn') of
287+ update unknown getI checkE qname@(Qualified mn' name) pos = positioned $ case (M.lookup qname imports', mn') of
288288 (Just qname', _) -> return qname'
289289 (Nothing, Just mn'') -> do
290− when (isExplicitQualModule mn'') $ throwError $ mkErrorStack ("Unknown " ++ t ++ " '" ++ show qname ++ "'") Nothing
290+ when (isExplicitQualModule mn'') . throwError . errorMessage $ unknown qname
291291 modExports <- getExports mn''
292292 if checkE modExports name
293293 then return qname
294− else throwError $ mkErrorStack ("Unknown " ++ t ++ " '" ++ show qname ++ "'") Nothing
295− _ -> throwError $ mkErrorStack ("Unknown " ++ t ++ " '" ++ show name ++ "'") Nothing
294+ else throwError . errorMessage $ unknown qname
295+ _ -> throwError . errorMessage $ unknown qname
296296 where
297297 isExplicitQualModule :: ModuleName -> Bool
298298 isExplicitQualModule = flip elem $ mapMaybe (\(Qualified q _) -> q) (M.keys imports')
@@ -303,12 +303,12 @@ renameInModule imports exports (Module coms mn decls exps) =
303303
304304 -- Gets the exports for a module, or an error message if the module doesn't exist
305305 getExports :: ModuleName -> m Exports
306− getExports mn' = maybe (throwError $ mkErrorStack ("Unknown module '" ++ show mn' ++ "'") Nothing) return $ M.lookup mn' exports
306+ getExports mn' = maybe (throwError . errorMessage $ UnknownModule mn') return $ M.lookup mn' exports
307307
308308-- |
309309-- Finds all exported declarations in a set of modules.
310310--
311−findExports :: forall m. (Applicative m, MonadError ErrorStack m) => [Module] -> m ExportEnvironment
311+findExports :: forall m. (Applicative m, MonadError MultipleErrors m) => [Module] -> m ExportEnvironment
312312findExports = foldM addModule $ M.singleton (ModuleName [ProperName C.prim]) primExports
313313 where
314314
@@ -321,7 +321,7 @@ findExports = foldM addModule $ M.singleton (ModuleName [ProperName C.prim]) pri
321321 addModule :: ExportEnvironment -> Module -> m ExportEnvironment
322322 addModule env (Module _ mn ds _) = do
323323 env' <- addEmptyModule env mn
324− rethrow (mkCompileError ("Error in module " ++ show mn) Nothing `combineErrors`) $ foldM (addDecl mn) env' ds
324+ rethrow (onErrorMessages (ErrorInModule mn)) $ foldM (addDecl mn) env' ds
325325
326326 -- Add a declaration from a module to the global export environment
327327 addDecl :: ModuleName -> ExportEnvironment -> Declaration -> m ExportEnvironment
@@ -344,10 +344,10 @@ findExports = foldM addModule $ M.singleton (ModuleName [ProperName C.prim]) pri
344344-- Filters the exports for a module to ensure only explicit exports are kept in the global exports
345345-- environment.
346346--
347−filterExports :: forall m. (Applicative m, MonadError ErrorStack m) => ModuleName -> [DeclarationRef] -> ExportEnvironment -> m ExportEnvironment
347+filterExports :: forall m. (Applicative m, MonadError MultipleErrors m) => ModuleName -> [DeclarationRef] -> ExportEnvironment -> m ExportEnvironment
348348filterExports mn exps env = do
349349 let moduleExports = fromMaybe (error "Module is missing") (mn `M.lookup` env)
350− moduleExports' <- rethrow (mkCompileError ("Error in module " ++ show mn) Nothing `combineErrors`) $ filterModule moduleExports
350+ moduleExports' <- rethrow (onErrorMessages (ErrorInModule mn)) $ filterModule moduleExports
351351 return $ M.insert mn moduleExports' env
352352 where
353353
@@ -364,7 +364,7 @@ filterExports mn exps env = do
364364 filterTypes :: [(ProperName, [ProperName])] -> [(ProperName, [ProperName])] -> DeclarationRef -> m [(ProperName, [ProperName])]
365365 filterTypes expTys result (PositionedDeclarationRef pos _ r) = rethrowWithPosition pos $ filterTypes expTys result r
366366 filterTypes expTys result (TypeRef name expDcons) = do
367− dcons <- maybe (throwError $ mkErrorStack ("Cannot export undefined type '" ++ show name ++ "'") Nothing) return $ name `lookup` expTys
367+ dcons <- maybe (throwError . errorMessage . UnknownType $ Qualified (Just mn) name) return $ name `lookup` expTys
368368 dcons' <- maybe (return dcons) (foldM (filterDcons name dcons) []) expDcons
369369 return $ (name, dcons') : result
370370 filterTypes _ result _ = return result
@@ -374,7 +374,7 @@ filterExports mn exps env = do
374374 filterDcons tcon exps' result name =
375375 if name `elem` exps'
376376 then return $ name : result
377− else throwError $ mkErrorStack ("Cannot export undefined data constructor '" ++ show name ++ "' for type '" ++ show tcon ++ "'") Nothing
377+ else throwError . errorMessage $ UnknownDataConstructor (Qualified (Just mn) name) (Just (Qualified (Just mn) tcon))
378378
379379 -- Ensure the exported classes exist in the module and add them to the set of exports
380380 filterClasses :: [ProperName] -> [ProperName] -> DeclarationRef -> m [ProperName]
@@ -382,7 +382,7 @@ filterExports mn exps env = do
382382 filterClasses exps' result (TypeClassRef name) =
383383 if name `elem` exps'
384384 then return $ name : result
385− else throwError $ mkErrorStack ("Cannot export undefined type class '" ++ show name ++ "'") Nothing
385+ else throwError . errorMessage . UnknownTypeClass $ Qualified (Just mn) name
386386 filterClasses _ result _ = return result
387387
388388 -- Ensure the exported values exist in the module and add them to the set of exports
@@ -391,7 +391,7 @@ filterExports mn exps env = do
391391 filterValues exps' result (ValueRef name) =
392392 if name `elem` exps'
393393 then return $ name : result
394− else throwError $ mkErrorStack ("Cannot export undefined value '" ++ show name ++ "'") Nothing
394+ else throwError . errorMessage . UnknownValue $ Qualified (Just mn) name
395395 filterValues _ result _ = return result
396396
397397-- |
@@ -408,7 +408,7 @@ findImports = foldl (findImports' Nothing) M.empty
408408-- |
409409-- Constructs a local environment for a module.
410410--
411−resolveImports :: forall m. (Applicative m, MonadError ErrorStack m) => ExportEnvironment -> Module -> m ImportEnvironment
411+resolveImports :: forall m. (Applicative m, MonadError MultipleErrors m) => ExportEnvironment -> Module -> m ImportEnvironment
412412resolveImports env (Module _ currentModule decls _) =
413413 foldM resolveImport' (ImportEnvironment M.empty M.empty M.empty M.empty) (M.toList scope)
414414 where
@@ -421,7 +421,7 @@ resolveImports env (Module _ currentModule decls _) =
421421
422422 resolveImport' :: ImportEnvironment -> (ModuleName, (Maybe SourceSpan, ImportDeclarationType, Maybe ModuleName)) -> m ImportEnvironment
423423 resolveImport' imp (mn, (pos, typ, impQual)) = do
424− modExports <- positioned $ maybe (throwError $ mkErrorStack ("Cannot import unknown module '" ++ show mn ++ "'") Nothing) return $ mn `M.lookup` env
424+ modExports <- positioned $ maybe (throwError . errorMessage $ UnknownModule mn) return $ mn `M.lookup` env
425425 positioned $ resolveImport currentModule mn modExports imp impQual typ
426426 where
427427 positioned err = case pos of
@@ -431,7 +431,7 @@ resolveImports env (Module _ currentModule decls _) =
431431-- |
432432-- Extends the local environment for a module by resolving an import of another module.
433433--
434−resolveImport :: forall m. (Applicative m, MonadError ErrorStack m) => ModuleName -> ModuleName -> Exports -> ImportEnvironment -> Maybe ModuleName -> ImportDeclarationType -> m ImportEnvironment
434+resolveImport :: forall m. (Applicative m, MonadError MultipleErrors m) => ModuleName -> ModuleName -> Exports -> ImportEnvironment -> Maybe ModuleName -> ImportDeclarationType -> m ImportEnvironment
435435resolveImport currentModule importModule exps imps impQual =
436436 resolveByType
437437 where
@@ -492,14 +492,14 @@ resolveImport currentModule importModule exps imps impQual =
492492 check (PositionedDeclarationRef pos _ r) =
493493 rethrowWithPosition pos $ check r
494494 check ref@(ValueRef name) =
495− checkImportExists "value" values name >> return ref
495+ checkImportExists UnknownValue values name >> return ref
496496 check ref@(TypeRef name dctors) = do
497− _ <- checkImportExists "type" availableTypes name
497+ _ <- checkImportExists UnknownType availableTypes name
498498 let allDctors = allExportedDataConstructors name
499499 _ <- maybe (return allDctors) (mapM $ checkDctorExists allDctors) dctors
500500 return ref
501501 check ref@(TypeClassRef name) =
502− checkImportExists "type class" classes name >> return ref
502+ checkImportExists UnknownTypeClass classes name >> return ref
503503 check _ = error "Invalid argument to checkRefIsValid"
504504
505505 -- Find all exported data constructors for a given type
@@ -511,11 +511,11 @@ resolveImport currentModule importModule exps imps impQual =
511511 updateImports m name = case M.lookup (Qualified impQual name) m of
512512 Nothing -> return $ M.insert (Qualified impQual name) (Qualified (Just importModule) name) m
513513 Just (Qualified Nothing _) -> error "Invalid state in updateImports"
514− Just x@(Qualified (Just mn) _) -> throwError $ mkErrorStack err Nothing
514+ Just (Qualified (Just mn) _) -> throwError . errorMessage $ err
515515 where
516516 err = if mn == currentModule || importModule == currentModule
517− then "Definition '" ++ show name ++ "' conflicts with import '" ++ show (Qualified (Just mn) name) ++ "'"
518− else "Conflicting imports for '" ++ show name ++ "': '" ++ show x ++ "', '" ++ show (Qualified (Just importModule) name) ++ "'"
517+ then ConflictingImport (show name) mn
518+ else ConflictingImports (show name) mn importModule
519519
520520 -- The available values, types, and classes in the module being imported
521521 values = exportedValues exps
@@ -525,27 +525,17 @@ resolveImport currentModule importModule exps imps impQual =
525525 -- Ensure that an explicitly imported data constructor exists for the type it is being imported
526526 -- from
527527 checkDctorExists :: [ProperName] -> ProperName -> m ProperName
528− checkDctorExists = checkImportExists "data constructor"
528+ checkDctorExists = checkImportExists (flip UnknownDataConstructor Nothing)
529529
530530 -- Check that an explicitly imported item exists in the module it is being imported from
531− checkImportExists :: (Eq a, Show a) => String -> [a] -> a -> m a
532− checkImportExists t exports item =
531+ checkImportExists :: (Eq a, Show a) => (Qualified a -> ErrorMessage) -> [a] -> a -> m a
532+ checkImportExists unknown exports item =
533533 if item `elem` exports
534534 then return item
535− else throwError $ mkErrorStack ("Cannot import unknown " ++ t ++ " '" ++ show item ++ "' from '" ++ show importModule ++ "'") Nothing
535+ else throwError . errorMessage . unknown $ Qualified (Just importModule) item
536536
537537-- |
538538-- Raises an error for when there is more than one definition for something.
539539--
540−throwMultipleDefError :: (Applicative m, MonadError ErrorStack m, Show a) => String -> a -> m b
541−throwMultipleDefError what name = throwError $
542− mkErrorStack ("Multiple definitions for " ++ what ++ " '" ++ show name ++ "'") Nothing
543−
544−-- |
545−-- Raises an error for when there is a conflicting definition for something, for example, a type
546−-- class and data constructor of the same name.
547−--
548−throwConflictingDefError :: (Applicative m, MonadError ErrorStack m, Show a) => String -> String -> a -> m b
549−throwConflictingDefError what1 what2 name = throwError $
550− mkErrorStack (what1 ++ " '" ++ show name ++ "' cannot be defined in the same module as a " ++ what2 ++ " of the same name") Nothing
551−
540+throwConflictError :: (Applicative m, MonadError MultipleErrors m, Show a) => (a -> ErrorMessage) -> a -> m b
541+throwConflictError conflict = throwError . errorMessage . conflict
src/Language/PureScript/Sugar/ObjectWildcards.hs+1−1
@@ -31,7 +31,7 @@ import Language.PureScript.AST
3131import Language.PureScript.Errors
3232import Language.PureScript.Names
3333
34−desugarObjectConstructors :: forall m. (Applicative m, MonadSupply m, MonadError ErrorStack m) => Module -> m Module
34+desugarObjectConstructors :: forall m. (Applicative m, MonadSupply m, MonadError MultipleErrors m) => Module -> m Module
3535desugarObjectConstructors (Module coms mn ds exts) = Module coms mn <$> mapM desugarDecl ds <*> pure exts
3636 where
3737
src/Language/PureScript/Sugar/Operators.hs+8−8
@@ -49,7 +49,7 @@ import qualified Language.PureScript.Constants as C
4949-- |
5050-- Remove explicit parentheses and reorder binary operator applications
5151--
52−rebracket :: (Applicative m, MonadError ErrorStack m) => [Module] -> m [Module]
52+rebracket :: (Applicative m, MonadError MultipleErrors m) => [Module] -> m [Module]
5353rebracket ms = do
5454 let fixities = concatMap collectFixities ms
5555 ensureNoDuplicates $ map (\(i, pos, _) -> (i, pos)) fixities
@@ -64,7 +64,7 @@ removeSignedLiterals (Module coms mn ds exts) = Module coms mn (map f' ds) exts
6464 go (UnaryMinus val) = App (Var (Qualified (Just (ModuleName [ProperName C.prelude])) (Ident C.negate))) val
6565 go other = other
6666
67−rebracketModule :: (Applicative m, MonadError ErrorStack m) => [[(Qualified Ident, Expr -> Expr -> Expr, Associativity)]] -> Module -> m Module
67+rebracketModule :: (Applicative m, MonadError MultipleErrors m) => [[(Qualified Ident, Expr -> Expr -> Expr, Associativity)]] -> Module -> m Module
6868rebracketModule opTable (Module coms mn ds exts) =
6969 let (f, _, _) = everywhereOnValuesTopDownM return (matchOperators opTable) return
7070 in Module coms mn <$> (map removeParens <$> parU ds f) <*> pure exts
@@ -85,15 +85,15 @@ collectFixities (Module _ moduleName ds _) = concatMap collect ds
8585 collect FixityDeclaration{} = error "Fixity without srcpos info"
8686 collect _ = []
8787
88−ensureNoDuplicates :: (MonadError ErrorStack m) => [(Qualified Ident, SourceSpan)] -> m ()
88+ensureNoDuplicates :: (MonadError MultipleErrors m) => [(Qualified Ident, SourceSpan)] -> m ()
8989ensureNoDuplicates m = go $ sortBy (compare `on` fst) m
9090 where
9191 go [] = return ()
9292 go [_] = return ()
9393 go ((x@(Qualified (Just mn) name), _) : (y, pos) : _) | x == y =
94− rethrow (mkCompileError ("Error in module " ++ show mn) Nothing `combineErrors`) $
94+ rethrow (onErrorMessages (ErrorInModule mn)) $
9595 rethrowWithPosition pos $
96− throwError $ mkErrorStack ("Redefined fixity for " ++ show name) Nothing
96+ throwError . errorMessage $ MultipleFixities name
9797 go (_ : rest) = go rest
9898
9999customOperatorTable :: [(Qualified Ident, Fixity)] -> [[(Qualified Ident, Expr -> Expr -> Expr, Associativity)]]
@@ -108,7 +108,7 @@ customOperatorTable fixities =
108108
109109type Chain = [Either Expr Expr]
110110
111−matchOperators :: forall m. (MonadError ErrorStack m) => [[(Qualified Ident, Expr -> Expr -> Expr, Associativity)]] -> Expr -> m Expr
111+matchOperators :: forall m. (MonadError MultipleErrors m) => [[(Qualified Ident, Expr -> Expr -> Expr, Associativity)]] -> Expr -> m Expr
112112matchOperators ops = parseChains
113113 where
114114 parseChains :: Expr -> m Expr
@@ -118,7 +118,7 @@ matchOperators ops = parseChains
118118 extendChain (BinaryNoParens op l r) = Left l : Right op : extendChain r
119119 extendChain other = [Left other]
120120 bracketChain :: Chain -> m Expr
121− bracketChain = either (throwError . (`mkErrorStack` Nothing) . show) return . P.parse (P.buildExpressionParser opTable parseValue <* P.eof) "operator expression"
121+ bracketChain = either (const . throwError . errorMessage $ CannotReorderOperators) return . P.parse (P.buildExpressionParser opTable parseValue <* P.eof) "operator expression"
122122 opTable = [P.Infix (P.try (parseTicks >>= \op -> return (\t1 t2 -> App (App op t1) t2))) P.AssocLeft]
123123 : map (map (\(name, f, a) -> P.Infix (P.try (matchOp name) >> return f) (toAssoc a))) ops
124124 ++ [[ P.Infix (P.try (parseOp >>= \ident -> return (\t1 t2 -> App (App (Var ident) t1) t2))) P.AssocLeft ]]
@@ -151,7 +151,7 @@ matchOp op = do
151151 ident <- parseOp
152152 guard $ ident == op
153153
154−desugarOperatorSections :: forall m. (Applicative m, MonadSupply m, MonadError ErrorStack m) => Module -> m Module
154+desugarOperatorSections :: forall m. (Applicative m, MonadSupply m, MonadError MultipleErrors m) => Module -> m Module
155155desugarOperatorSections (Module coms mn ds exts) = Module coms mn <$> mapM goDecl ds <*> pure exts
156156 where
157157
src/Language/PureScript/Sugar/TypeClasses.hs+9−10
@@ -27,7 +27,6 @@ import Language.PureScript.Environment
2727import Language.PureScript.Errors
2828import Language.PureScript.Kinds
2929import Language.PureScript.Names
30−import Language.PureScript.Pretty.Types (prettyPrintTypeAtom)
3130import Language.PureScript.Sugar.CaseDeclarations
3231import Control.Monad.Supply.Class
3332import Language.PureScript.Types
@@ -51,10 +50,10 @@ type Desugar = StateT MemberMap
5150-- Add type synonym declarations for type class dictionary types, and value declarations for type class
5251-- instance dictionary expressions.
5352--
54−desugarTypeClasses :: (Functor m, Applicative m, MonadSupply m, MonadError ErrorStack m) => [Module] -> m [Module]
53+desugarTypeClasses :: (Functor m, Applicative m, MonadSupply m, MonadError MultipleErrors m) => [Module] -> m [Module]
5554desugarTypeClasses = flip evalStateT M.empty . mapM desugarModule
5655
57−desugarModule :: (Functor m, Applicative m, MonadSupply m, MonadError ErrorStack m) => Module -> Desugar m Module
56+desugarModule :: (Functor m, Applicative m, MonadSupply m, MonadError MultipleErrors m) => Module -> Desugar m Module
5857desugarModule (Module coms name decls (Just exps)) = do
5958 (newExpss, declss) <- unzip <$> parU (sortBy classesFirst decls) (desugarDecl name exps)
6059 return $ Module coms name (concat declss) $ Just (exps ++ catMaybes newExpss)
@@ -160,7 +159,7 @@ desugarModule _ = error "Exports should have been elaborated in name desugaring"
160159-- return new Sub(fooString, "");
161160-- };
162161-}
163−desugarDecl :: (Functor m, Applicative m, MonadSupply m, MonadError ErrorStack m) => ModuleName -> [DeclarationRef] -> Declaration -> Desugar m (Maybe DeclarationRef, [Declaration])
162+desugarDecl :: (Functor m, Applicative m, MonadSupply m, MonadError MultipleErrors m) => ModuleName -> [DeclarationRef] -> Declaration -> Desugar m (Maybe DeclarationRef, [Declaration])
164163desugarDecl mn exps = go
165164 where
166165 go d@(TypeClassDeclaration name args implies members) = do
@@ -230,18 +229,18 @@ typeClassMemberToDictionaryAccessor _ _ _ _ = error "Invalid declaration in type
230229unit :: Type
231230unit = TypeApp tyObject REmpty
232231
233−typeInstanceDictionaryDeclaration :: (Functor m, Applicative m, MonadSupply m, MonadError ErrorStack m) => Ident -> ModuleName -> [Constraint] -> Qualified ProperName -> [Type] -> [Declaration] -> Desugar m Declaration
232+typeInstanceDictionaryDeclaration :: (Functor m, Applicative m, MonadSupply m, MonadError MultipleErrors m) => Ident -> ModuleName -> [Constraint] -> Qualified ProperName -> [Type] -> [Declaration] -> Desugar m Declaration
234233typeInstanceDictionaryDeclaration name mn deps className tys decls =
235− rethrow (mkCompileError ("Error in type class instance " ++ show className ++ " " ++ unwords (map prettyPrintTypeAtom tys) ++ ":") Nothing `combineErrors`) $ do
234+ rethrow (onErrorMessages (ErrorInInstance className tys)) $ do
236235 m <- get
237236
238237 -- Lookup the type arguments and member types for the type class
239238 (TypeClassDeclaration _ args implies tyDecls) <-
240− maybe (throwError $ mkErrorStack ("Type class " ++ show className ++ " is undefined") Nothing) return $
239+ maybe (throwError . errorMessage $ UnknownTypeClass className) return $
241240 M.lookup (qualify mn className) m
242241
243242 case mapMaybe declName tyDecls \\ mapMaybe declName decls of
244− x : _ -> throwError $ mkErrorStack ("Member '" ++ show x ++ "' has not been implemented") Nothing
243+ member : _ -> throwError . errorMessage $ MissingClassMember member
245244 [] -> do
246245
247246 let instanceTys = map memberToNameAndType tyDecls
@@ -276,9 +275,9 @@ typeInstanceDictionaryDeclaration name mn deps className tys decls =
276275 declName (TypeDeclaration ident _) = Just ident
277276 declName _ = Nothing
278277
279− memberToValue :: (Functor m, Applicative m, MonadSupply m, MonadError ErrorStack m) => [(Ident, Type)] -> Declaration -> Desugar m Expr
278+ memberToValue :: (Functor m, Applicative m, MonadSupply m, MonadError MultipleErrors m) => [(Ident, Type)] -> Declaration -> Desugar m Expr
280279 memberToValue tys' (ValueDeclaration ident _ [] (Right val)) = do
281− _ <- maybe (throwError $ mkErrorStack ("Type class does not define member '" ++ show ident ++ "'") Nothing) return $ lookup ident tys'
280+ _ <- maybe (throwError . errorMessage $ MissingClassMember ident) return $ lookup ident tys'
282281 return val
283282 memberToValue tys' (PositionedDeclaration pos com d) = rethrowWithPosition pos $ do
284283 val <- memberToValue tys' d
src/Language/PureScript/Sugar/TypeDeclarations.hs+6−6
@@ -35,15 +35,15 @@ import Language.PureScript.Traversals
3535-- |
3636-- Replace all top level type declarations in a module with type annotations
3737--
38−desugarTypeDeclarationsModule :: (Functor m, Applicative m, MonadError ErrorStack m) => [Module] -> m [Module]
38+desugarTypeDeclarationsModule :: (Functor m, Applicative m, MonadError MultipleErrors m) => [Module] -> m [Module]
3939desugarTypeDeclarationsModule ms = forM ms $ \(Module coms name ds exps) ->
40− rethrow (mkCompileError ("Error in module " ++ show name) Nothing `combineErrors`) $
40+ rethrow (onErrorMessages (ErrorInModule name)) $
4141 Module coms name <$> desugarTypeDeclarations ds <*> pure exps
4242
4343-- |
4444-- Replace all top level type declarations with type annotations
4545--
46−desugarTypeDeclarations :: (Functor m, Applicative m, MonadError ErrorStack m) => [Declaration] -> m [Declaration]
46+desugarTypeDeclarations :: (Functor m, Applicative m, MonadError MultipleErrors m) => [Declaration] -> m [Declaration]
4747desugarTypeDeclarations (PositionedDeclaration pos com d : ds) = do
4848 (d' : ds') <- rethrowWithPosition pos $ desugarTypeDeclarations (d : ds)
4949 return (PositionedDeclaration pos com d' : ds')
@@ -51,13 +51,13 @@ desugarTypeDeclarations (TypeDeclaration name ty : d : rest) = do
5151 (_, nameKind, val) <- fromValueDeclaration d
5252 desugarTypeDeclarations (ValueDeclaration name nameKind [] (Right (TypedValue True val ty)) : rest)
5353 where
54− fromValueDeclaration :: (Functor m, Applicative m, MonadError ErrorStack m) => Declaration -> m (Ident, NameKind, Expr)
54+ fromValueDeclaration :: (Functor m, Applicative m, MonadError MultipleErrors m) => Declaration -> m (Ident, NameKind, Expr)
5555 fromValueDeclaration (ValueDeclaration name' nameKind [] (Right val)) | name == name' = return (name', nameKind, val)
5656 fromValueDeclaration (PositionedDeclaration pos com d') = do
5757 (ident, nameKind, val) <- rethrowWithPosition pos $ fromValueDeclaration d'
5858 return (ident, nameKind, PositionedValue pos com val)
59− fromValueDeclaration _ = throwError $ mkErrorStack ("Orphan type declaration for " ++ show name) Nothing
60−desugarTypeDeclarations (TypeDeclaration name _ : []) = throwError $ mkErrorStack ("Orphan type declaration for " ++ show name) Nothing
59+ fromValueDeclaration _ = throwError . errorMessage $ OrphanTypeDeclaration name
60+desugarTypeDeclarations (TypeDeclaration name _ : []) = throwError . errorMessage $ OrphanTypeDeclaration name
6161desugarTypeDeclarations (ValueDeclaration name nameKind bs val : rest) = do
6262 let (_, f, _) = everywhereOnValuesTopDownM return go return
6363 f' (Left gs) = Left <$> mapM (pairM return f) gs
src/Language/PureScript/TypeChecker.hs+42−50
@@ -26,8 +26,9 @@ import Language.PureScript.TypeChecker.Types as T
2626import Language.PureScript.TypeChecker.Synonyms as T
2727
2828import Data.Maybe
29−import Data.List (nub, (\\), find, intercalate)
29+import Data.List (nub, (\\))
3030import Data.Foldable (for_)
31+
3132import qualified Data.Map as M
3233
3334import Control.Monad.State
@@ -46,7 +47,7 @@ addDataType moduleName dtype name args dctors ctorKind = do
4647 env <- getEnv
4748 putEnv $ env { types = M.insert (Qualified (Just moduleName) name) (ctorKind, DataType args dctors) (types env) }
4849 forM_ dctors $ \(dctor, tys) ->
49− rethrow (mkCompileError ("Error in data constructor " ++ show dctor) Nothing `combineErrors`) $
50+ rethrow (onErrorMessages (ErrorInDataConstructor dctor)) $
5051 addDataConstructor moduleName dtype name (map fst args) dctor tys
5152
5253addDataConstructor :: ModuleName -> DataDeclType -> ProperName -> [String] -> ProperName -> [Type] -> Check ()
@@ -70,7 +71,7 @@ valueIsNotDefined :: ModuleName -> Ident -> Check ()
7071valueIsNotDefined moduleName name = do
7172 env <- getEnv
7273 case M.lookup (moduleName, name) (names env) of
73− Just _ -> throwError . strMsg $ show name ++ " is already defined"
74+ Just _ -> throwError . errorMessage $ RedefinedIdent name
7475 Nothing -> return ()
7576
7677addValue :: ModuleName -> Ident -> Type -> NameKind -> Check ()
@@ -94,7 +95,7 @@ addTypeClassDictionaries entries =
9495
9596checkDuplicateTypeArguments :: [String] -> Check ()
9697checkDuplicateTypeArguments args = for_ firstDup $ \dup ->
97− throwError . strMsg $ "Duplicate type argument '" ++ dup ++ "'"
98+ throwError . errorMessage $ DuplicateTypeArgument dup
9899 where
99100 firstDup :: Maybe String
100101 firstDup = listToMaybe $ args \\ nub args
@@ -103,10 +104,10 @@ checkTypeClassInstance :: ModuleName -> Type -> Check ()
103104checkTypeClassInstance _ (TypeVar _) = return ()
104105checkTypeClassInstance _ (TypeConstructor ctor) = do
105106 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
107108 return ()
108109checkTypeClassInstance m (TypeApp t1 t2) = checkTypeClassInstance m t1 >> checkTypeClassInstance m t2
109−checkTypeClassInstance _ ty = throwError $ mkErrorStack "Type class instance head is invalid." (Just (TypeError ty))
110+checkTypeClassInstance _ ty = throwError . errorMessage $ InvalidInstanceHead ty
110111
111112-- |
112113-- Check that type synonyms are fully-applied in a type
@@ -133,7 +134,7 @@ typeCheckAll mainModuleName moduleName exps = go
133134 go :: [Declaration] -> Check [Declaration]
134135 go [] = return []
135136 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
137138 when (dtype == Newtype) $ checkNewtype dctors
138139 checkDuplicateTypeArguments $ map fst args
139140 ctorKind <- kindsOf True moduleName name args (concatMap snd dctors)
@@ -144,10 +145,10 @@ typeCheckAll mainModuleName moduleName exps = go
144145 where
145146 checkNewtype :: [(ProperName, [Type])] -> Check ()
146147 checkNewtype [(_, [_])] = return ()
147− checkNewtype [(_, _)] = throwError . strMsg $ "newtypes constructors must have a single argument"
148− checkNewtype _ = throwError . strMsg $ "newtypes must have a single constructor"
148+ checkNewtype [(_, _)] = throwError . errorMessage $ InvalidNewtype
149+ checkNewtype _ = throwError . errorMessage $ InvalidNewtype
149150 go (d@(DataBindingGroupDeclaration tys) : rest) = do
150− rethrow (mkCompileError "Error in data binding group" Nothing `combineErrors`) $ do
151+ rethrow (onErrorMessages ErrorInDataBindingGroup) $ do
151152 let syns = mapMaybe toTypeSynonym tys
152153 let dataDecls = mapMaybe toDataDecl tys
153154 (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
169170 toDataDecl (PositionedDeclaration _ _ d') = toDataDecl d'
170171 toDataDecl _ = Nothing
171172 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
173174 checkDuplicateTypeArguments $ map fst args
174175 kind <- kindsOf False moduleName name args [ty]
175176 let args' = args `withKinds` kind
@@ -178,7 +179,7 @@ typeCheckAll mainModuleName moduleName exps = go
178179 return $ TypeSynonymDeclaration name args ty : ds
179180 go (TypeDeclaration _ _ : _) = error "Type declarations should have been removed"
180181 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
182183 valueIsNotDefined moduleName name
183184 [(_, (val', ty))] <- typesOf mainModuleName moduleName [(name, val)]
184185 addValue moduleName name ty nameKind
@@ -187,7 +188,7 @@ typeCheckAll mainModuleName moduleName exps = go
187188 return $ d : ds
188189 go (ValueDeclaration{} : _) = error "Binders were not desugared"
189190 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
191192 forM_ (map (\(ident, _, _) -> ident) vals) $ \name ->
192193 valueIsNotDefined moduleName name
193194 tys <- typesOf mainModuleName moduleName $ map (\(ident, _, ty) -> (ident, ty)) vals
@@ -207,19 +208,19 @@ typeCheckAll mainModuleName moduleName exps = go
207208 ds <- go rest
208209 return $ d : ds
209210 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
211212 env <- getEnv
212213 kind <- kindOf moduleName ty
213− guardWith (strMsg "Expected kind *") $ kind == Star
214+ guardWith (errorMessage (ExpectedType kind)) $ kind == Star
214215 case M.lookup (moduleName, name) (names env) of
215− Just _ -> throwError . strMsg $ show name ++ " is already defined"
216+ Just _ -> throwError . errorMessage $ RedefinedIdent name
216217 Nothing -> putEnv (env { names = M.insert (moduleName, name) (ty, Extern importTy, Defined) (names env) })
217218 ds <- go rest
218219 return $ d : ds
219220 go (d@(FixityDeclaration _ name) : rest) = do
220221 ds <- go rest
221222 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
223224 return $ d : ds
224225 go (d@(ImportDeclaration importedModule _ _) : rest) = do
225226 tcds <- getTypeClassDictionaries
@@ -277,7 +278,7 @@ typeCheckAll mainModuleName moduleName exps = go
277278--
278279typeCheckModule :: Maybe ModuleName -> Module -> Check Module
279280typeCheckModule _ (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
281282 modify (\s -> s { checkCurrentModule = Just mn })
282283 decls' <- typeCheckAll mainModuleName mn exps decls
283284 forM_ exps $ \e -> do
@@ -287,63 +288,54 @@ typeCheckModule mainModuleName (Module coms mn decls (Just exps)) = do
287288 return $ Module coms mn decls' (Just exps)
288289 where
289290
290− checkMemberExport :: (Show a) => String -> (Type -> [a]) -> (a -> Bool) -> DeclarationRef -> Check ()
291− checkMemberExport thing extract test (ValueRef name) = do
291+ checkMemberExport :: (Type -> [DeclarationRef]) -> DeclarationRef -> Check ()
292+ checkMemberExport extract dr@(ValueRef name) = do
292293 ty <- lookupVariable mn (Qualified (Just mn) name)
293− case find test (extract ty) of
294− Just hiddenType -> throwError . strMsg $
295− "Error in module '" ++ show mn ++ "':\n\
296− \Exporting declaration '" ++ show name ++ "' requires " ++ thing ++ " '" ++ show hiddenType ++ "' to be exported as well"
297− Nothing -> return ()
298− checkMemberExport _ _ _ _ = return ()
294+ case filter (not . exported) (extract ty) of
295+ [] -> return ()
296+ hidden -> throwError . errorMessage $ TransitiveExportError dr hidden
297+ where
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
305+ exports _ _ = False
306+ checkMemberExport _ _ = return ()
299307
300308 -- Check that all the type constructors defined in the current module that appear in member types
301309 -- have also been exported from the module
302310 checkTypesAreExported :: DeclarationRef -> Check ()
303− checkTypesAreExported = checkMemberExport "type" findTcons isTconHidden
311+ checkTypesAreExported = checkMemberExport findTcons
304312 where
305− findTcons :: Type -> [ProperName]
313+ findTcons :: Type -> [DeclarationRef]
306314 findTcons = everythingOnTypes (++) go
307315 where
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")]
309317 go _ = []
310− isTconHidden :: ProperName -> Bool
311− isTconHidden tyName = all go exps
312− where
313− go (TypeRef tyName' _) = tyName' /= tyName
314− go _ = True
315318
316319 -- Check that all the classes defined in the current module that appear in member types have also
317320 -- been exported from the module
318321 checkClassesAreExported :: DeclarationRef -> Check ()
319− checkClassesAreExported = checkMemberExport "class" findClasses isClassHidden
322+ checkClassesAreExported = checkMemberExport findClasses
320323 where
321− findClasses :: Type -> [ProperName]
324+ findClasses :: Type -> [DeclarationRef]
322325 findClasses = everythingOnTypes (++) go
323326 where
324− go (ConstrainedType cs _) = mapMaybe (extractCurrentModuleClass . fst) cs
327+ go (ConstrainedType cs _) = mapMaybe (fmap TypeClassRef . extractCurrentModuleClass . fst) cs
325328 go _ = []
326329 extractCurrentModuleClass :: Qualified ProperName -> Maybe ProperName
327330 extractCurrentModuleClass (Qualified (Just mn') name) | mn == mn' = Just name
328331 extractCurrentModuleClass _ = Nothing
329− isClassHidden :: ProperName -> Bool
330− isClassHidden clsName = all go exps
331− where
332− go (TypeClassRef clsName') = clsName' /= clsName
333− go _ = True
334332
335333 checkClassMembersAreExported :: DeclarationRef -> Check ()
336− checkClassMembersAreExported (TypeClassRef name) = do
334+ checkClassMembersAreExported dr@(TypeClassRef name) = do
337335 let members = ValueRef `map` head (mapMaybe findClassMembers decls)
338336 let missingMembers = members \\ exps
339− unless (null missingMembers) $
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) ++ "'"
337+ unless (null missingMembers) $ throwError . errorMessage $ TransitiveExportError dr members
343338 where
344− runValueRef :: DeclarationRef -> Ident
345− runValueRef (ValueRef refName) = refName
346− runValueRef _ = error "non-ValueRef passed to runValueRef"
347339 findClassMembers :: Declaration -> Maybe [Ident]
348340 findClassMembers (TypeClassDeclaration name' _ _ ds) | name == name' = Just $ map extractMemberName ds
349341 findClassMembers (PositionedDeclaration _ _ d) = findClassMembers d
src/Language/PureScript/TypeChecker/Entailment.hs+2−45
@@ -31,7 +31,6 @@ import Language.PureScript.AST
3131import Language.PureScript.Errors
3232import Language.PureScript.Environment
3333import Language.PureScript.Names
34−import Language.PureScript.Pretty
3534import Language.PureScript.TypeChecker.Monad
3635import Language.PureScript.TypeChecker.Synonyms
3736import Language.PureScript.TypeChecker.Unify
@@ -39,29 +38,6 @@ import Language.PureScript.TypeClassDictionaries
3938import Language.PureScript.Types
4039import qualified Language.PureScript.Constants as C
4140
42−-- |
43−-- A simplified representation of expressions which are used to represent type
44−-- class dictionaries at runtime, which can be compared for equality
45−--
46−data DictionaryValue
47− -- |
48− -- A dictionary which is brought into scope by a local constraint
49− --
50− = LocalDictionaryValue (Qualified Ident)
51− -- |
52− -- A dictionary which is brought into scope by an instance declaration
53− --
54− | GlobalDictionaryValue (Qualified Ident)
55− -- |
56− -- A dictionary which depends on other dictionaries
57− --
58− | DependentDictionaryValue (Qualified Ident) [DictionaryValue]
59− -- |
60− -- A subclass dictionary
61− --
62− | SubclassDictionaryValue DictionaryValue (Qualified ProperName) Integer
63− deriving (Show, Ord, Eq)
64−
6541-- |
6642-- Check that the current set of type class dictionaries entail the specified type class goal, and, if so,
6743-- return a type class dictionary reference.
@@ -140,16 +116,9 @@ entails env moduleName context = solve (sortedNubBy canonicalizeDictionary (filt
140116 checkOverlaps :: [DictionaryValue] -> Check Expr
141117 checkOverlaps dicts =
142118 case [ (d1, d2) | d1 <- dicts, d2 <- dicts, d1 `overlapping` d2 ] of
143− (d1, d2) : _ -> throwError . strMsg $ unlines
144− [ "Overlapping instances found for " ++ show className ++ " " ++ unwords (map prettyPrintType tys) ++ "."
145− , "For example:"
146− , prettyPrintDictionaryValue d1
147− , "and:"
148− , prettyPrintDictionaryValue d2
149− ]
119+ ds@(_ : _) -> throwError . errorMessage $ OverlappingInstances className tys (map fst ds)
150120 _ -> case chooseSimplestDictionaries dicts of
151− [] -> throwError . strMsg $
152− "No instance found for " ++ show className ++ " " ++ unwords (map prettyPrintTypeAtom tys)
121+ [] -> throwError . errorMessage $ NoInstanceFound className tys
153122 d : _ -> return $ dictionaryValueToValue d
154123 -- Choose the simplest DictionaryValues from a list of candidates
155124 -- The reason for this function is as follows:
@@ -180,18 +149,6 @@ entails env moduleName context = solve (sortedNubBy canonicalizeDictionary (filt
180149 overlapping SubclassDictionaryValue{} _ = False
181150 overlapping _ SubclassDictionaryValue{} = False
182151 overlapping _ _ = True
183− -- |
184− -- Render a DictionaryValue fit for human consumption in error messages
185− --
186− prettyPrintDictionaryValue :: DictionaryValue -> String
187− prettyPrintDictionaryValue = unlines . indented 0
188− where
189− indented n (LocalDictionaryValue _) = [spaces n ++ "Dictionary in scope"]
190− indented n (GlobalDictionaryValue nm) = [spaces n ++ show nm]
191− indented n (DependentDictionaryValue nm args) = (spaces n ++ show nm ++ " via") : concatMap (indented (n + 2)) args
192− indented n (SubclassDictionaryValue sup nm _) = (spaces n ++ show nm ++ " via superclass") : indented (n + 2) sup
193−
194− spaces n = replicate n ' ' ++ "- "
195152
196153 valUndefined :: Expr
197154 valUndefined = Var (Qualified (Just (ModuleName [ProperName C.prim])) (Ident C.undefined))
src/Language/PureScript/TypeChecker/Kinds.hs+5−6
@@ -38,7 +38,6 @@ import Language.PureScript.Environment
3838import Language.PureScript.Errors
3939import Language.PureScript.Kinds
4040import Language.PureScript.Names
41−import Language.PureScript.Pretty
4241import Language.PureScript.TypeChecker.Monad
4342import Language.PureScript.Types
4443
@@ -65,7 +64,7 @@ instance Unifiable Check Kind where
6564 FunKind k1 k2 =?= FunKind k3 k4 = do
6665 k1 =?= k3
6766 k2 =?= k4
68− k1 =?= k2 = UnifyT . lift . throwError . strMsg $ "Cannot unify " ++ prettyPrintKind k1 ++ " with " ++ prettyPrintKind k2 ++ "."
67+ k1 =?= k2 = UnifyT . lift . throwError . errorMessage $ KindsDoNotUnify k1 k2
6968
7069-- |
7170-- Infer the kind of a single type
@@ -78,7 +77,7 @@ kindOf _ ty = fst <$> kindOfWithScopedVars ty
7877--
7978kindOfWithScopedVars :: Type -> Check (Kind, [(String, Kind)])
8079kindOfWithScopedVars ty =
81− rethrow (mkCompileError "Error checking kind" (Just (TypeError ty)) `combineErrors`) $
80+ rethrow (onErrorMessages (ErrorCheckingKind ty)) $
8281 fmap tidyUp . liftUnify $ infer ty
8382 where
8483 tidyUp ((k, args), sub) = ( starIfUnknown (sub $? k)
@@ -156,7 +155,7 @@ starIfUnknown k = k
156155-- Infer a kind for a type
157156--
158157infer :: Type -> UnifyT Kind Check (Kind, [(String, Kind)])
159−infer ty = rethrow (mkCompileError "Error inferring type of value" (Just (TypeError ty)) `combineErrors`) $ infer' ty
158+infer ty = rethrow (onErrorMessages (ErrorCheckingKind ty)) $ infer' ty
160159
161160infer' :: Type -> UnifyT Kind Check (Kind, [(String, Kind)])
162161infer' (ForAll ident ty _) = do
@@ -189,10 +188,10 @@ infer' other = (, []) <$> go other
189188 go (Skolem v _ _) = do
190189 Just moduleName <- checkCurrentModule <$> get
191190 UnifyT . lift $ lookupTypeVariable moduleName (Qualified Nothing (ProperName v))
192− go c@(TypeConstructor v) = do
191+ go (TypeConstructor v) = do
193192 env <- liftCheck getEnv
194193 case M.lookup v (types env) of
195− Nothing -> UnifyT . lift . throwError $ mkErrorStack "Unknown type constructor" (Just (TypeError c))
194+ Nothing -> UnifyT . lift . throwError . errorMessage $ UnknownTypeConstructor v
196195 Just (kind, _) -> return kind
197196 go (TypeApp t1 t2) = do
198197 k0 <- fresh
src/Language/PureScript/TypeChecker/Monad.hs+13−13
@@ -109,41 +109,41 @@ makeBindingGroupVisible action = do
109109-- |
110110-- Lookup the type of a value by name in the @Environment@
111111--
112−lookupVariable :: (e ~ ErrorStack, Functor m, MonadState CheckState m, MonadError e m) => ModuleName -> Qualified Ident -> m Type
112+lookupVariable :: (e ~ MultipleErrors, Functor m, MonadState CheckState m, MonadError e m) => ModuleName -> Qualified Ident -> m Type
113113lookupVariable currentModule (Qualified moduleName var) = do
114114 env <- getEnv
115115 case M.lookup (fromMaybe currentModule moduleName, var) (names env) of
116− Nothing -> throwError . strMsg $ show var ++ " is undefined"
116+ Nothing -> throwError . errorMessage $ NameIsUndefined var
117117 Just (ty, _, _) -> return ty
118118
119119-- |
120120-- Lookup the visibility of a value by name in the @Environment@
121121--
122−getVisibility :: (e ~ ErrorStack, Functor m, MonadState CheckState m, MonadError e m) => ModuleName -> Qualified Ident -> m NameVisibility
122+getVisibility :: (e ~ MultipleErrors, Functor m, MonadState CheckState m, MonadError e m) => ModuleName -> Qualified Ident -> m NameVisibility
123123getVisibility currentModule (Qualified moduleName var) = do
124124 env <- getEnv
125125 case M.lookup (fromMaybe currentModule moduleName, var) (names env) of
126− Nothing -> throwError . strMsg $ show var ++ " is undefined"
126+ Nothing -> throwError . errorMessage $ NameIsUndefined var
127127 Just (_, _, vis) -> return vis
128128
129129-- |
130130-- Assert that a name is visible
131131--
132−checkVisibility :: (e ~ ErrorStack, Functor m, MonadState CheckState m, MonadError e m) => ModuleName -> Qualified Ident -> m ()
132+checkVisibility :: (e ~ MultipleErrors, Functor m, MonadState CheckState m, MonadError e m) => ModuleName -> Qualified Ident -> m ()
133133checkVisibility currentModule name@(Qualified _ var) = do
134134 vis <- getVisibility currentModule name
135135 case vis of
136− Undefined -> throwError . strMsg $ show var ++ " may not be defined in the current scope."
136+ Undefined -> throwError . errorMessage $ NameNotInScope var
137137 _ -> return ()
138138
139139-- |
140140-- Lookup the kind of a type by name in the @Environment@
141141--
142−lookupTypeVariable :: (e ~ ErrorStack, Functor m, MonadState CheckState m, MonadError e m) => ModuleName -> Qualified ProperName -> m Kind
142+lookupTypeVariable :: (e ~ MultipleErrors, Functor m, MonadState CheckState m, MonadError e m) => ModuleName -> Qualified ProperName -> m Kind
143143lookupTypeVariable currentModule (Qualified moduleName name) = do
144144 env <- getEnv
145145 case M.lookup (Qualified (Just $ fromMaybe currentModule moduleName) name) (types env) of
146− Nothing -> throwError . strMsg $ "Type variable " ++ show name ++ " is undefined"
146+ Nothing -> throwError . errorMessage $ UndefinedTypeVariable name
147147 Just (k, _) -> return k
148148
149149-- |
@@ -171,8 +171,8 @@ data CheckState = CheckState {
171171-- |
172172-- The type checking monad, which provides the state of the type checker, and error reporting capabilities
173173--
174−newtype Check a = Check { unCheck :: StateT CheckState (Either ErrorStack) a }
175− deriving (Functor, Monad, Applicative, MonadState CheckState, MonadError ErrorStack)
174+newtype Check a = Check { unCheck :: StateT CheckState (Either MultipleErrors) a }
175+ deriving (Functor, Monad, Applicative, MonadState CheckState, MonadError MultipleErrors)
176176
177177-- |
178178-- Get the current @Environment@
@@ -204,9 +204,9 @@ runCheck = runCheck' initEnvironment
204204runCheck' :: (MonadReader (Options mode) m, MonadError String m) => Environment -> Check a -> m (a, Environment)
205205runCheck' env c = do
206206 verbose <- asks optionsVerboseErrors
207− stringifyErrorStack verbose $ do
208− (a, s) <- flip runStateT (CheckState env 0 0 Nothing) $ unCheck c
209− return (a, checkEnv s)
207+ interpretMultipleErrors verbose $ do
208+ (a, s) <- flip runStateT (CheckState env 0 0 Nothing) $ unCheck c
209+ return (a, checkEnv s)
210210
211211-- |
212212-- Make an assertion, failing with an error message
src/Language/PureScript/TypeChecker/Rows.hs+1−1
@@ -53,7 +53,7 @@ checkDuplicateLabels =
5353 checkDups r@RCons{} =
5454 let (ls, _) = rowToList r in
5555 case firstDup . sort . map fst $ ls of
56− Just l -> throwError $ mkErrorStack ("Duplicate label " ++ show l ++ " in row") $ Just (ExprError val)
56+ Just l -> throwError . errorMessage $ DuplicateLabel l (Just val)
5757 Nothing -> return ()
5858 checkDups _ = return ()
5959
src/Language/PureScript/TypeChecker/Skolems.hs+2−3
@@ -31,7 +31,6 @@ import Control.Monad.Unify
3131
3232import Language.PureScript.AST
3333import Language.PureScript.Errors
34−import Language.PureScript.Pretty
3534import Language.PureScript.TypeChecker.Monad
3635import Language.PureScript.Types
3736
@@ -89,7 +88,7 @@ skolemEscapeCheck root@TypedValue{} =
8988 let (_, f, _, _, _) = everythingWithContextOnValues [] [] (++) def go def def def
9089 in case f root of
9190 [] -> return ()
92− ((binding, val) : _) -> throwError $ mkErrorStack ("Rigid/skolem type variable " ++ maybe "" (("bound by " ++) . prettyPrintValue) binding ++ " has escaped.") (Just (ExprError val))
91+ ((binding, val) : _) -> throwError . errorMessage . ErrorInExpression val $ EscapedSkolem binding
9392 where
9493 def s _ = (s, [])
9594
@@ -112,4 +111,4 @@ skolemEscapeCheck root@TypedValue{} =
112111 where
113112 go' val@(TypedValue _ _ (ForAll _ _ (Just sco'))) | sco == sco' = First (Just val)
114113 go' _ = mempty
115−skolemEscapeCheck val = throwError $ mkErrorStack "Untyped value passed to skolemEscapeCheck" (Just (ExprError val))
114+skolemEscapeCheck _ = error "Untyped value passed to skolemEscapeCheck"
src/Language/PureScript/TypeChecker/Subsumption.hs+2−9
@@ -20,14 +20,12 @@ module Language.PureScript.TypeChecker.Subsumption (
2020import Data.List (sortBy)
2121import Data.Ord (comparing)
2222
23−import Control.Applicative
2423import Control.Monad.Except
2524import Control.Monad.Unify
2625
2726import Language.PureScript.AST
2827import Language.PureScript.Environment
2928import Language.PureScript.Errors
30−import Language.PureScript.Pretty
3129import Language.PureScript.TypeChecker.Monad
3230import Language.PureScript.TypeChecker.Skolems
3331import Language.PureScript.TypeChecker.Synonyms
@@ -38,12 +36,7 @@ import Language.PureScript.Types
3836-- Check whether one type subsumes another, rethrowing errors to provide a better error message
3937--
4038subsumes :: Maybe Expr -> Type -> Type -> UnifyT Type Check (Maybe Expr)
41−subsumes val ty1 ty2 = rethrow (mkCompileError errorMessage (ExprError <$> val) `combineErrors`) $ subsumes' val ty1 ty2
42− where
43− errorMessage = "Error checking that type "
44− ++ prettyPrintType ty1
45− ++ " subsumes type "
46− ++ prettyPrintType ty2
39+subsumes val ty1 ty2 = rethrow (onErrorMessages (ErrorInSubsumption ty1 ty2)) $ subsumes' val ty1 ty2
4740
4841-- |
4942-- Check whether one type subsumes another
@@ -58,7 +51,7 @@ subsumes' val ty1 (ForAll ident ty2 sco) =
5851 sko <- newSkolemConstant
5952 let sk = skolemize ident sko sco' ty2
6053 subsumes val ty1 sk
61− Nothing -> throwError . strMsg $ "Skolem variable scope is unspecified"
54+ Nothing -> throwError . errorMessage $ UnspecifiedSkolemScope
6255subsumes' val (TypeApp (TypeApp f1 arg1) ret1) (TypeApp (TypeApp f2 arg2) ret2) | f1 == tyFunction && f2 == tyFunction = do
6356 _ <- subsumes Nothing arg2 arg1
6457 _ <- subsumes Nothing ret1 ret2
src/Language/PureScript/TypeChecker/Synonyms.hs+12−12
@@ -40,19 +40,19 @@ import Language.PureScript.Types
4040-- |
4141-- Build a type substitution for a type synonym
4242--
43−buildTypeSubstitution :: Qualified ProperName -> Int -> Type -> Either String (Maybe Type)
43+buildTypeSubstitution :: Qualified ProperName -> Int -> Type -> Either ErrorMessage (Maybe Type)
4444buildTypeSubstitution name n = go n []
4545 where
46− go :: Int -> [Type] -> Type -> Either String (Maybe Type)
46+ go :: Int -> [Type] -> Type -> Either ErrorMessage (Maybe Type)
4747 go 0 args (TypeConstructor ctor) | name == ctor = return (Just $ SaturatedTypeSynonym ctor args)
48− go m _ (TypeConstructor ctor) | m > 0 && name == ctor = throwError $ "Partially applied type synonym " ++ show name
48+ go m _ (TypeConstructor ctor) | m > 0 && name == ctor = throwError $ PartiallyAppliedSynonym name
4949 go m args (TypeApp f arg) = go (m - 1) (arg:args) f
5050 go _ _ _ = return Nothing
5151
5252-- |
5353-- Replace all instances of a specific type synonym with the @SaturatedTypeSynonym@ data constructor
5454--
55−saturateTypeSynonym :: Qualified ProperName -> Int -> Type -> Either String Type
55+saturateTypeSynonym :: Qualified ProperName -> Int -> Type -> Either ErrorMessage Type
5656saturateTypeSynonym name n = everywhereOnTypesTopDownM replace
5757 where
5858 replace t = fromMaybe t <$> buildTypeSubstitution name n t
@@ -60,7 +60,7 @@ saturateTypeSynonym name n = everywhereOnTypesTopDownM replace
6060-- |
6161-- Replace all type synonyms with the @SaturatedTypeSynonym@ data constructor
6262--
63−saturateAllTypeSynonyms :: [(Qualified ProperName, Int)] -> Type -> Either String Type
63+saturateAllTypeSynonyms :: [(Qualified ProperName, Int)] -> Type -> Either ErrorMessage Type
6464saturateAllTypeSynonyms syns d = foldM (\result (name, n) -> saturateTypeSynonym name n result) d syns
6565
6666-- |
@@ -76,22 +76,22 @@ desaturateAllTypeSynonyms = everywhereOnTypes replaceSaturatedTypeSynonym
7676-- Replace fully applied type synonyms with the @SaturatedTypeSynonym@ data constructor, which helps generate
7777-- better error messages during unification.
7878--
79−replaceAllTypeSynonyms' :: Environment -> Type -> Either String Type
79+replaceAllTypeSynonyms' :: Environment -> Type -> Either ErrorMessage Type
8080replaceAllTypeSynonyms' env d =
8181 let
8282 syns = map (\(name, (args, _)) -> (name, length args)) . M.toList $ typeSynonyms env
8383 in
8484 saturateAllTypeSynonyms syns d
8585
86−replaceAllTypeSynonyms :: (e ~ ErrorStack, Functor m, Monad m, MonadState CheckState m, MonadError e m) => Type -> m Type
86+replaceAllTypeSynonyms :: (e ~ MultipleErrors, Functor m, Monad m, MonadState CheckState m, MonadError e m) => Type -> m Type
8787replaceAllTypeSynonyms d = do
8888 env <- getEnv
89− either (throwError . strMsg) return $ replaceAllTypeSynonyms' env d
89+ either (throwError . errorMessage) return $ replaceAllTypeSynonyms' env d
9090
9191-- |
9292-- Replace a type synonym and its arguments with the aliased type
9393--
94−expandTypeSynonym' :: Environment -> Qualified ProperName -> [Type] -> Either String Type
94+expandTypeSynonym' :: Environment -> Qualified ProperName -> [Type] -> Either ErrorMessage Type
9595expandTypeSynonym' env name args =
9696 case M.lookup name (typeSynonyms env) of
9797 Just (synArgs, body) -> do
@@ -99,12 +99,12 @@ expandTypeSynonym' env name args =
9999 replaceAllTypeSynonyms' env repl
100100 Nothing -> error "Type synonym was not defined"
101101
102−expandTypeSynonym :: (e ~ ErrorStack, Functor m, Monad m, MonadState CheckState m, MonadError e m) => Qualified ProperName -> [Type] -> m Type
102+expandTypeSynonym :: (e ~ MultipleErrors, Functor m, Monad m, MonadState CheckState m, MonadError e m) => Qualified ProperName -> [Type] -> m Type
103103expandTypeSynonym name args = do
104104 env <- getEnv
105− either (throwError . strMsg) return $ expandTypeSynonym' env name args
105+ either (throwError . errorMessage) return $ expandTypeSynonym' env name args
106106
107−expandAllTypeSynonyms :: (e ~ ErrorStack, Functor m, Applicative m, Monad m, MonadState CheckState m, MonadError e m) => Type -> m Type
107+expandAllTypeSynonyms :: (e ~ MultipleErrors, Functor m, Applicative m, Monad m, MonadState CheckState m, MonadError e m) => Type -> m Type
108108expandAllTypeSynonyms = everywhereOnTypesTopDownM go
109109 where
110110 go (SaturatedTypeSynonym name args) = expandTypeSynonym name args
src/Language/PureScript/TypeChecker/Types.hs+22−32
@@ -39,7 +39,6 @@ import Data.Either (lefts, rights)
3939import Data.List
4040import Data.Maybe (fromMaybe)
4141import qualified Data.Map as M
42−import Data.String (IsString)
4342
4443import Control.Applicative
4544import Control.Monad.Except
@@ -51,7 +50,6 @@ import Language.PureScript.Environment
5150import Language.PureScript.Errors
5251import Language.PureScript.Kinds
5352import Language.PureScript.Names
54−import Language.PureScript.Pretty
5553import Language.PureScript.Traversals
5654import Language.PureScript.TypeChecker.Entailment
5755import Language.PureScript.TypeChecker.Kinds
@@ -184,7 +182,7 @@ replaceTypeClassDictionaries mn =
184182-- Check the kind of a type, failing if it is not of kind *.
185183--
186184checkTypeKind :: Kind -> UnifyT t Check ()
187−checkTypeKind kind = guardWith (strMsg $ "Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
185+checkTypeKind kind = guardWith (errorMessage (ExpectedType kind)) $ kind == Star
188186
189187-- |
190188-- Remove any ForAlls and ConstrainedType constructors in a type by introducing new unknowns
@@ -207,7 +205,7 @@ instantiatePolyTypeWithUnknowns val ty = return (val, ty)
207205-- Infer a type for a value, rethrowing any error to provide a more useful error message
208206--
209207infer :: Expr -> UnifyT Type Check Expr
210−infer val = rethrow (mkCompileError "Error inferring type of value" (Just (ExprError val)) `combineErrors`) $ infer' val
208+infer val = rethrow (onErrorMessages (ErrorInferringType val)) $ infer' val
211209
212210-- |
213211-- Infer a type for a value
@@ -269,7 +267,7 @@ infer' (Var var) = do
269267infer' v@(Constructor c) = do
270268 env <- getEnv
271269 case M.lookup c (dataConstructors env) of
272− Nothing -> throwError . strMsg $ "Constructor " ++ show c ++ " is undefined"
270+ Nothing -> throwError . errorMessage $ UnknownDataConstructor c Nothing
273271 Just (_, _, ty, _) -> do (v', ty') <- sndM (introduceSkolemScope <=< replaceAllTypeSynonyms) <=< instantiatePolyTypeWithUnknowns v $ ty
274272 return $ TypedValue True v' ty'
275273infer' (Case vals binders) = do
@@ -365,8 +363,8 @@ inferBinder val (ConstructorBinder ctor binders) = do
365363 return M.empty
366364 go (binder : binders') (TypeApp (TypeApp t obj) ret) | t == tyFunction =
367365 M.union <$> inferBinder obj binder <*> go binders' ret
368− go _ _ = throwError . strMsg $ "Wrong number of arguments to constructor " ++ show ctor
369− _ -> throwError . strMsg $ "Constructor " ++ show ctor ++ " is not defined"
366+ go _ _ = throwError . errorMessage $ IncorrectConstructorArity ctor
367+ _ -> throwError . errorMessage $ UnknownDataConstructor ctor Nothing
370368inferBinder val (ObjectBinder props) = do
371369 row <- fresh
372370 rest <- fresh
@@ -404,7 +402,7 @@ inferBinder val (PositionedBinder pos _ binder) =
404402checkBinders :: [Type] -> Type -> [CaseAlternative] -> UnifyT Type Check [CaseAlternative]
405403checkBinders _ _ [] = return []
406404checkBinders nvals ret (CaseAlternative binders result : bs) = do
407− guardWith (strMsg "Overlapping binders in case statement") $
405+ guardWith (errorMessage $ OverlappingArgNames Nothing) $
408406 let ns = concatMap binderNames binders in length (nub ns) == length ns
409407 Just moduleName <- checkCurrentModule <$> get
410408 m1 <- M.unions <$> zipWithM inferBinder nvals binders
@@ -427,13 +425,7 @@ checkBinders nvals ret (CaseAlternative binders result : bs) = do
427425-- Check the type of a value, rethrowing errors to provide a better error message
428426--
429427check :: Expr -> Type -> UnifyT Type Check Expr
430−check val ty = rethrow (mkCompileError errorMessage (Just (ExprError val)) `combineErrors`) $ check' val ty
431− where
432− errorMessage =
433− "Error checking type of term " ++
434− prettyPrintValue val ++
435− " against type " ++
436− prettyPrintType ty
428+check val ty = rethrow (onErrorMessages (ErrorCheckingType val ty)) $ check' val ty
437429
438430-- |
439431-- Check the type of a value
@@ -490,7 +482,7 @@ check' v@(Var var) ty = do
490482 ty' <- introduceSkolemScope <=< replaceAllTypeSynonyms <=< replaceTypeWildcards $ ty
491483 v' <- subsumes (Just v) repl ty'
492484 case v' of
493− Nothing -> throwError . strMsg $ "Unable to check type subsumption"
485+ Nothing -> throwError . errorMessage $ SubsumptionCheckFailed
494486 Just v'' -> return $ TypedValue True v'' ty'
495487check' (SuperClassDictionary className tys) _ = do
496488 {-
@@ -513,7 +505,7 @@ check' (TypedValue checkType val ty1) ty2 = do
513505 ty2' <- introduceSkolemScope <=< replaceAllTypeSynonyms <=< replaceTypeWildcards $ ty2
514506 val' <- subsumes (Just val) ty1' ty2'
515507 case val' of
516− Nothing -> throwError . strMsg $ "Unable to check type subsumption"
508+ Nothing -> throwError . errorMessage $ SubsumptionCheckFailed
517509 Just val'' -> do
518510 val''' <- if checkType then withScopedTypeVars moduleName args (check val'' ty2') else return val''
519511 return $ TypedValue checkType (TypedValue True val''' ty1') ty2'
@@ -551,7 +543,7 @@ check' (Accessor prop val) ty = do
551543check' (Constructor c) ty = do
552544 env <- getEnv
553545 case M.lookup c (dataConstructors env) of
554− Nothing -> throwError . strMsg $ "Constructor " ++ show c ++ " is undefined"
546+ Nothing -> throwError . errorMessage $ UnknownDataConstructor c Nothing
555547 Just (_, _, ty1, _) -> do
556548 repl <- introduceSkolemScope <=< replaceAllTypeSynonyms $ ty1
557549 _ <- subsumes Nothing repl ty
@@ -568,7 +560,7 @@ check' val kt@(KindedType ty kind) = do
568560 return $ TypedValue True val' kt
569561check' (PositionedValue pos _ val) ty =
570562 rethrowWithPosition pos $ check' val ty
571−check' val ty = throwError $ mkErrorStack ("Expr does not have type " ++ prettyPrintType ty) (Just (ExprError val))
563+check' val ty = throwError . errorMessage $ ExprDoesNotHaveType val ty
572564
573565containsTypeSynonyms :: Type -> Bool
574566containsTypeSynonyms = everythingOnTypes (||) go where
@@ -589,8 +581,8 @@ checkProperties ps row lax = let (ts, r') = rowToList row in go ps ts r' where
589581 return []
590582 go [] [] Skolem{} | lax = return []
591583 go [] ((p, _): _) _ | lax = return []
592− | otherwise = throwError $ mkErrorStack ("Object does not have property " ++ p) (Just (ExprError (ObjectLiteral ps)))
593− go ((p,_):_) [] REmpty = throwError $ mkErrorStack ("Property " ++ p ++ " is not present in closed object type " ++ prettyPrintRow row) (Just (ExprError (ObjectLiteral ps)))
584+ | otherwise = throwError . errorMessage $ PropertyIsMissing p row
585+ go ((p,_):_) [] REmpty = throwError . errorMessage $ PropertyIsMissing p row
594586 go ((p,v):ps') ts r =
595587 case lookup p ts of
596588 Nothing -> do
@@ -603,19 +595,15 @@ checkProperties ps row lax = let (ts, r') = rowToList row in go ps ts r' where
603595 v' <- check v ty
604596 ps'' <- go ps' (delete (p, ty) ts) r
605597 return $ (p, v') : ps''
606− go _ _ _ = throwError $ mkErrorStack ("Object does not have type " ++ prettyPrintType (TypeApp tyObject row)) (Just (ExprError (ObjectLiteral ps)))
598+ go _ _ _ = throwError . errorMessage $ ExprDoesNotHaveType (ObjectLiteral ps) (TypeApp tyObject row)
607599
608600-- |
609601-- Check the type of a function application, rethrowing errors to provide a better error message
610602--
611603checkFunctionApplication :: Expr -> Type -> Expr -> Maybe Type -> UnifyT Type Check (Type, Expr)
612−checkFunctionApplication fn fnTy arg ret = rethrow (mkCompileError errorMessage (Just (ExprError fn)) `combineErrors`) $ do
604+checkFunctionApplication fn fnTy arg ret = rethrow (onErrorMessages (ErrorInApplication fn fnTy arg)) $ do
613605 subst <- unifyCurrentSubstitution <$> UnifyT get
614606 checkFunctionApplication' fn (subst $? fnTy) arg (($?) subst <$> ret)
615− where
616− errorMessage = "Error applying function of type "
617− ++ prettyPrintType fnTy
618− ++ " to argument " ++ prettyPrintValue arg
619607
620608-- |
621609-- Check the type of a function application
@@ -651,9 +639,7 @@ checkFunctionApplication' fn (ConstrainedType constraints fnTy) arg ret = do
651639 checkFunctionApplication' (foldl App fn (map (flip (TypeClassDictionary True) dicts) constraints)) fnTy arg ret
652640checkFunctionApplication' fn fnTy dict@TypeClassDictionary{} _ =
653641 return (fnTy, App fn dict)
654−checkFunctionApplication' _ fnTy arg _ = throwError . strMsg $ "Cannot apply a function of type "
655− ++ prettyPrintType fnTy
656− ++ " to argument " ++ prettyPrintValue arg
642+checkFunctionApplication' _ fnTy arg _ = throwError . errorMessage $ CannotApplyFunction fnTy arg
657643
658644-- |
659645-- Compute the meet of two types, i.e. the most general type which both types subsume.
@@ -673,5 +659,9 @@ meet e1 e2 t1 t2 = do
673659-- |
674660-- Ensure a set of property names and value does not contain duplicate labels
675661--
676−ensureNoDuplicateProperties :: (IsString e, MonadError e m) => [(String, Expr)] -> m ()
677−ensureNoDuplicateProperties ps = guardWith "Duplicate property names" $ length (nub . map fst $ ps) == length ps
662+ensureNoDuplicateProperties :: (MonadError MultipleErrors m) => [(String, Expr)] -> m ()
663+ensureNoDuplicateProperties ps =
664+ let ls = map fst ps in
665+ case ls \\ nub ls of
666+ l : _ -> throwError . errorMessage $ DuplicateLabel l Nothing
667+ _ -> return ()
src/Language/PureScript/TypeChecker/Unify.hs+7−8
@@ -34,7 +34,6 @@ import Control.Monad.Unify
3434
3535import Language.PureScript.Environment
3636import Language.PureScript.Errors
37−import Language.PureScript.Pretty
3837import Language.PureScript.TypeChecker.Monad
3938import Language.PureScript.TypeChecker.Skolems
4039import Language.PureScript.TypeChecker.Synonyms
@@ -60,7 +59,7 @@ instance Unifiable Check Type where
6059-- Unify two types, updating the current substitution
6160--
6261unifyTypes :: Type -> Type -> UnifyT Type Check ()
63−unifyTypes t1 t2 = rethrow (mkCompileError ("Error unifying type " ++ prettyPrintType t1 ++ " with type " ++ prettyPrintType t2) Nothing `combineErrors`) $
62+unifyTypes t1 t2 = rethrow (onErrorMessages (ErrorUnifyingTypes t1 t2)) $
6463 unifyTypes' t1 t2
6564 where
6665 unifyTypes' (TUnknown u1) (TUnknown u2) | u1 == u2 = return ()
@@ -82,11 +81,11 @@ unifyTypes t1 t2 = rethrow (mkCompileError ("Error unifying type " ++ prettyPrin
8281 sko <- newSkolemConstant
8382 let sk = skolemize ident sko sc ty1
8483 sk `unifyTypes` ty2
85− unifyTypes' ForAll{} _ = throwError . strMsg $ "Skolem variable scope is unspecified"
84+ unifyTypes' ForAll{} _ = throwError . errorMessage $ UnspecifiedSkolemScope
8685 unifyTypes' ty f@ForAll{} = f `unifyTypes` ty
8786 unifyTypes' (TypeVar v1) (TypeVar v2) | v1 == v2 = return ()
88− unifyTypes' (TypeConstructor c1) (TypeConstructor c2) =
89− guardWith (strMsg ("Cannot unify " ++ show c1 ++ " with " ++ show c2 ++ ".")) (c1 == c2)
87+ unifyTypes' ty1@(TypeConstructor c1) ty2@(TypeConstructor c2) =
88+ guardWith (errorMessage (TypesDoNotUnify ty1 ty2)) (c1 == c2)
9089 unifyTypes' (TypeApp t3 t4) (TypeApp t5 t6) = do
9190 t3 `unifyTypes` t5
9291 t4 `unifyTypes` t6
@@ -97,9 +96,9 @@ unifyTypes t1 t2 = rethrow (mkCompileError ("Error unifying type " ++ prettyPrin
9796 unifyTypes' r1 r2@RCons{} = unifyRows r1 r2
9897 unifyTypes' r1@REmpty r2 = unifyRows r1 r2
9998 unifyTypes' r1 r2@REmpty = unifyRows r1 r2
100− unifyTypes' t@(ConstrainedType _ _) _ = throwError . strMsg $ "Attempted to unify a constrained type " ++ prettyPrintType t ++ " with another type."
99+ unifyTypes' ty1@(ConstrainedType _ _) ty2 = throwError . errorMessage $ ConstrainedTypeUnified ty1 ty2
101100 unifyTypes' t3 t4@(ConstrainedType _ _) = unifyTypes' t4 t3
102− unifyTypes' t3 t4 = throwError . strMsg $ "Cannot unify " ++ prettyPrintType t3 ++ " with " ++ prettyPrintType t4 ++ "."
101+ unifyTypes' t3 t4 = throwError . errorMessage $ TypesDoNotUnify t3 t4
103102
104103-- |
105104-- Unify two rows, updating the current substitution
@@ -136,7 +135,7 @@ unifyRows r1 r2 =
136135 unifyRows' [] REmpty [] REmpty = return ()
137136 unifyRows' [] (TypeVar v1) [] (TypeVar v2) | v1 == v2 = return ()
138137 unifyRows' [] (Skolem _ s1 _) [] (Skolem _ s2 _) | s1 == s2 = return ()
139− unifyRows' sd3 r3 sd4 r4 = throwError . strMsg $ "Cannot unify (" ++ prettyPrintRow (rowFromList (sd3, r3)) ++ ") with (" ++ prettyPrintRow (rowFromList (sd4, r4)) ++ ")"
138+ unifyRows' sd3 r3 sd4 r4 = throwError . errorMessage $ TypesDoNotUnify (rowFromList (sd3, r3)) (rowFromList (sd4, r4))
140139
141140-- |
142141-- Check that two types unify
src/Language/PureScript/TypeClassDictionaries.hs+23
@@ -65,6 +65,29 @@ data TypeClassDictionaryType
6565 --
6666 | TCDAlias (Qualified Ident) deriving (Show, Eq, Data, Typeable)
6767
68+-- |
69+-- A simplified representation of expressions which are used to represent type
70+-- class dictionaries at runtime, which can be compared for equality
71+--
72+data DictionaryValue
73+ -- |
74+ -- A dictionary which is brought into scope by a local constraint
75+ --
76+ = LocalDictionaryValue (Qualified Ident)
77+ -- |
78+ -- A dictionary which is brought into scope by an instance declaration
79+ --
80+ | GlobalDictionaryValue (Qualified Ident)
81+ -- |
82+ -- A dictionary which depends on other dictionaries
83+ --
84+ | DependentDictionaryValue (Qualified Ident) [DictionaryValue]
85+ -- |
86+ -- A subclass dictionary
87+ --
88+ | SubclassDictionaryValue DictionaryValue (Qualified ProperName) Integer
89+ deriving (Show, Ord, Eq)
90+
6891-- |
6992-- Find the original dictionary which a type class dictionary in scope refers to
7093--
tests/Main.hs+1−1
@@ -77,7 +77,7 @@ assertDoesNotCompile preludeExterns inputFile = do
7777 putStrLn $ "Assert " ++ inputFile ++ " does not compile"
7878 assert preludeExterns (P.defaultCompileOptions { P.optionsAdditional = P.CompileOptions "Tests" [] [] }) inputFile $ \e ->
7979 case e of
80− Left _ -> return Nothing
80+ Left err -> putStrLn err >> return Nothing
8181 Right _ -> return $ Just "Should not have compiled"
8282
8383findNodeProcess :: IO (Maybe String)