syfco-1.1.0.0: src/Data/Error.hs
-----------------------------------------------------------------------------
-- |
-- Module : Data.Error
-- License : MIT (see the LICENSE file)
-- Maintainer : Felix Klein (klein@react.uni-saarland.de)
--
-- Data structures to wrap all contents, that are needed to print nice
-- error messages.
--
-----------------------------------------------------------------------------
{-# LANGUAGE
LambdaCase
, RecordWildCards
#-}
-----------------------------------------------------------------------------
module Data.Error
( Error
, syntaxError
, runtimeError
, typeError
, bindingError
, conversionError
, depError
, cfgError
, parseError
, prError
, prErrPos
) where
-----------------------------------------------------------------------------
import Data.Expression
( ExprPos(..)
, SrcPos(..)
)
import Text.Parsec.Error
( ParseError
)
import System.Exit
( exitFailure
)
import System.IO
( hPrint
, stderr
)
-----------------------------------------------------------------------------
-- | Internal representation of an error.
data Error =
ErrType TypeError
| ErrParse ParseError
| ErrBnd BindingError
| ErrDep DependencyError
| ErrSyntax SyntaxError
| ErrRunT RunTimeError
| ErrConv ConvError
| ErrCfg CfgError
-----------------------------------------------------------------------------
data TypeError =
TypeError
{ errTPos :: ExprPos
, errTMsgs :: [String]
} deriving (Eq, Ord)
-----------------------------------------------------------------------------
data BindingError =
BindingError
{ errBPos :: ExprPos
, errBMsgs :: [String]
} deriving (Eq, Ord)
-----------------------------------------------------------------------------
data DependencyError =
DependencyError
{ errDPos :: ExprPos
, errDMsgs :: [String]
} deriving (Eq, Ord)
-----------------------------------------------------------------------------
data SyntaxError =
SyntaxError
{ errSPos :: ExprPos
, errSMsgs :: [String]
} deriving (Eq, Ord)
-----------------------------------------------------------------------------
data RunTimeError =
RunTimeError
{ errRPos :: ExprPos
, errRMsgs :: [String]
} deriving (Eq, Ord)
-----------------------------------------------------------------------------
data ConvError =
ConvError
{ title :: String
, cmsg :: String
} deriving (Eq, Ord)
-----------------------------------------------------------------------------
data CfgError =
ConfigError
{ fmsg :: String
} deriving (Eq, Ord)
-----------------------------------------------------------------------------
instance Show Error where
show = \case
ErrParse x -> show x
ErrType TypeError{..} -> pr "Type Error" errTPos errTMsgs
ErrBnd BindingError{..} -> pr "Binding Error" errBPos errBMsgs
ErrDep DependencyError{..} -> pr "Dependency Error" errDPos errDMsgs
ErrSyntax SyntaxError{..} -> pr "Syntax Error" errSPos errSMsgs
ErrRunT RunTimeError{..} -> pr "Runtime Error" errRPos errRMsgs
ErrCfg ConfigError{..} -> "\"Error\":\n" ++ fmsg
ErrConv ConvError{..} -> "\"Conversion Error\": " ++ title ++
"\n" ++ cmsg
where
pr errname pos msgs =
"\"" ++ errname ++ "\" (" ++ prErrPos pos ++ "):\n" ++ concat msgs
-----------------------------------------------------------------------------
-- | Use this error constructor, if some sytax related misbehavior is
-- detected.
syntaxError
:: ExprPos -> String -> Either Error a
syntaxError pos msg = Left $ ErrSyntax $ SyntaxError pos [msg]
-----------------------------------------------------------------------------
-- | Use this error constructor, if some runtime execution fails.
runtimeError
:: ExprPos -> String -> Either Error a
runtimeError pos msg = Left $ ErrRunT $ RunTimeError pos [msg]
-----------------------------------------------------------------------------
-- | Use this error constructor, if some type related misbehavior is
-- detected.
typeError
:: ExprPos -> String -> Either Error a
typeError pos msg = Left $ ErrType $ TypeError pos [msg]
-----------------------------------------------------------------------------
-- | Use this error constructor, if some identifier binding related
-- misbehavior is detected.
bindingError
:: ExprPos -> String -> Either Error a
bindingError pos msg = Left $ ErrBnd $ BindingError pos [msg]
-----------------------------------------------------------------------------
-- | Use this error constructor, if some misbehavior concerning dependencies
-- between identifiers is detected.
depError
:: ExprPos -> String -> Either Error a
depError pos msg = Left $ ErrDep $ DependencyError pos [msg]
-----------------------------------------------------------------------------
-- | Use this error constructor, if some unresolvable inconsistency in the
-- configuration exists.
cfgError
:: String -> Either Error a
cfgError msg = Left $ ErrCfg $ ConfigError msg
-----------------------------------------------------------------------------
-- | Use this error constructor, if an invalid command line setting is
-- detected.
conversionError
:: String -> String -> Either Error a
conversionError t msg = Left $ ErrConv $ ConvError t msg
-----------------------------------------------------------------------------
-- | Use this error constructor, whenever a parser fails.
parseError
:: ParseError -> Either Error a
parseError err = Left $ ErrParse err
-----------------------------------------------------------------------------
-- | Prints an error to STDERR and then terminates the program.
prError
:: Error -> IO a
prError err = do
hPrint stderr $ show err
exitFailure
-----------------------------------------------------------------------------
-- | Prints the position of an error related token.
prErrPos
:: ExprPos -> String
prErrPos pos =
let
bl = srcLine $ srcBegin pos
bc = srcColumn $ srcBegin pos
el = srcLine $ srcEnd pos
ec = srcColumn $ srcEnd pos
in
"line " ++ show bl ++ "," ++
"column " ++ show bc ++
if bl == el
then " - " ++ show ec
else " - line " ++ show el ++ ", column " ++ show ec
-----------------------------------------------------------------------------