{-| Module : Language.Qux.Annotated.Exception Description : Exceptions and utility raising functions. Copyright : (c) Henry J. Wylde, 2015 License : BSD3 Maintainer : public@hjwylde.com Exceptions and utility functions. -} module Language.Qux.Annotated.Exception ( -- * Type exception TypeException(..), pos, message, ) where import Data.List (intercalate) import Language.Qux.Annotated.Parser (SourcePos) import Language.Qux.Syntax -- | An exception that occurs during type checking. See "Language.Qux.Annotated.TypeChecker". data TypeException = TypeException SourcePos String -- ^ A generic type exception with a -- position and message. | DuplicateFunctionName SourcePos Id -- ^ Indicates a function of the given -- name already exists. | DuplicateParameterName SourcePos Id -- ^ Indicates a parameter of the given -- name already exists. | InvalidFunctionCall SourcePos Int Int -- ^ Indicates the wrong number of -- arguments was passed to the -- function call. | MismatchedType SourcePos Id [Id] -- ^ Indicates a type mismatch. deriving Eq instance Show TypeException where show e = show (pos e) ++ ":\n" ++ message e -- | Extracts the source position from the exception. pos :: TypeException -> SourcePos pos (TypeException p _) = p pos (DuplicateFunctionName p _) = p pos (DuplicateParameterName p _) = p pos (InvalidFunctionCall p _ _) = p pos (MismatchedType p _ _) = p -- | Creates a human understandable message from the exception. message :: TypeException -> String message (TypeException _ m) = m message (DuplicateFunctionName _ name) = "duplicate function name \"" ++ name ++ "\"" message (DuplicateParameterName _ name) = "duplicate parameter name \"" ++ name ++ "\"" message (InvalidFunctionCall _ received expected) = intercalate " " [ "invalid arguments count", show received, "\nexpecting", show expected ] message (MismatchedType _ received expects) = intercalate " " [ "unexpected type", "\"" ++ received ++ "\"", "\nexpecting", sentence "or" expects ] where sentence _ [x] = x sentence sep xs = intercalate " " [intercalate ", " (map show $ init xs), sep, show $ last xs]