@@ -19,10 +19,13 @@
19module Language.PureScript.Errors where
19module Language.PureScript.Errors where
21import Data.Either (lefts, rights)
21import Data.Either (lefts, rights)
22−import Data.List (intercalate, elemIndex)
22+import Data.List (intercalate)
23+import Data.Function (on)
23import Data.Monoid
24import Data.Monoid
24import Data.Foldable (fold, foldMap)
25import Data.Foldable (fold, foldMap)
27+import qualified Data.Map as M
26import Control.Monad
29import Control.Monad
27import Control.Monad.Error.Class (MonadError(..))
30import Control.Monad.Error.Class (MonadError(..))
28import Control.Monad.Unify
31import Control.Monad.Unify
@@ -252,18 +255,24 @@ errorMessage err = MultipleErrors [err]
252onErrorMessages :: (ErrorMessage -> ErrorMessage) -> MultipleErrors -> MultipleErrors
255onErrorMessages :: (ErrorMessage -> ErrorMessage) -> MultipleErrors -> MultipleErrors
253onErrorMessages f = MultipleErrors . map f . runMultipleErrors
256onErrorMessages f = MultipleErrors . map f . runMultipleErrors
255−replaceUnknowns :: Type -> State [Unknown] Type
258+-- | The various types of things which might need to be relabelled in errors messages.
256−replaceUnknowns = everywhereOnTypesM replaceUnknowns'
259+data LabelType = TypeLabel | SkolemLabel String deriving (Show, Eq, Ord)
258− lookupTable :: Unknown -> [Unknown] -> (Unknown, [Unknown])
259− lookupTable x table = case (elemIndex x table) of
260− Nothing -> (length table, table ++ [x])
261− Just i -> (i, table)
261+-- | A map from rigid type variable name/unknown variable pairs to new variables.
262+type UnknownMap = M.Map (LabelType, Unknown) Unknown
263− replaceUnknowns' :: Type -> State [Unknown] Type
264+replaceUnknowns :: Type -> State UnknownMap Type
264− replaceUnknowns' (TUnknown u) = state $ first TUnknown . lookupTable u
265+replaceUnknowns = everywhereOnTypesM replaceTypes
265− replaceUnknowns' other = return other
266+ where
267+ lookupTable :: (LabelType, Unknown) -> UnknownMap -> (Unknown, UnknownMap)
268+ lookupTable x m = case M.lookup x m of
269+ Nothing -> let i = length (filter (on (==) fst x) (M.keys m)) in (i, M.insert x i m)
272+ replaceTypes :: Type -> State UnknownMap Type
273+ replaceTypes (TUnknown u) = state $ first TUnknown . lookupTable (TypeLabel, u)
274+ replaceTypes (Skolem name s sko) = state $ first (flip (Skolem name) sko) . lookupTable (SkolemLabel name, s)
275+ replaceTypes other = return other
268onTypesInErrorMessageM :: (Applicative m) => (Type -> m Type) -> ErrorMessage -> m ErrorMessage
277onTypesInErrorMessageM :: (Applicative m) => (Type -> m Type) -> ErrorMessage -> m ErrorMessage
269onTypesInErrorMessageM f = g
278onTypesInErrorMessageM f = g
@@ -298,7 +307,7 @@ onTypesInErrorMessageM f = g
299-- Pretty print a single error, simplifying if necessary
308-- Pretty print a single error, simplifying if necessary
301−prettyPrintSingleError :: Bool -> ErrorMessage -> State [Unknown] Box.Box
310+prettyPrintSingleError :: Bool -> ErrorMessage -> State UnknownMap Box.Box
302prettyPrintSingleError full e = prettyPrintErrorMessage <$> onTypesInErrorMessageM replaceUnknowns (if full then e else simplifyErrorMessage e)
311prettyPrintSingleError full e = prettyPrintErrorMessage <$> onTypesInErrorMessageM replaceUnknowns (if full then e else simplifyErrorMessage e)
@@ -569,15 +578,15 @@ prettyPrintSingleError full e = prettyPrintErrorMessage <$> onTypesInErrorMessag
569-- Pretty print multiple errors
578-- Pretty print multiple errors
571prettyPrintMultipleErrors :: Bool -> MultipleErrors -> String
580prettyPrintMultipleErrors :: Bool -> MultipleErrors -> String
572−prettyPrintMultipleErrors full = flip evalState [] . prettyPrintMultipleErrorsWith "Error:" "Multiple errors:" full
581+prettyPrintMultipleErrors full = flip evalState M.empty . prettyPrintMultipleErrorsWith "Error:" "Multiple errors:" full
575-- Pretty print multiple warnings
584-- Pretty print multiple warnings
577prettyPrintMultipleWarnings :: Bool -> MultipleErrors -> String
586prettyPrintMultipleWarnings :: Bool -> MultipleErrors -> String
578−prettyPrintMultipleWarnings full = flip evalState [] . prettyPrintMultipleErrorsWith "Warning:" "Multiple warnings:" full
587+prettyPrintMultipleWarnings full = flip evalState M.empty . prettyPrintMultipleErrorsWith "Warning:" "Multiple warnings:" full
580−prettyPrintMultipleErrorsWith :: String -> String -> Bool -> MultipleErrors -> State [Unknown] String
589+prettyPrintMultipleErrorsWith :: String -> String -> Bool -> MultipleErrors -> State UnknownMap String
581prettyPrintMultipleErrorsWith intro _ full (MultipleErrors [e]) = do
590prettyPrintMultipleErrorsWith intro _ full (MultipleErrors [e]) = do
582 result <- prettyPrintSingleError full e
591 result <- prettyPrintSingleError full e
583 return $ renderBox $
592 return $ renderBox $