{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE InstanceSigs #-} {-# LANGUAGE ScopedTypeVariables #-} module Axel.Error where import Axel.Parse.AST (Expression, toAxel) import Control.Monad.Except (ExceptT, MonadError(throwError), runExceptT) import Data.Semigroup ((<>)) data Error = EvalError String | MacroError String | NormalizeError String [Expression] | ParseError String | ProjectError String instance Show Error where show :: Error -> String show (EvalError err) = err show (MacroError err) = err show (NormalizeError err context) = "error:\n" <> err <> "\n\n" <> "context:\n" <> unlines (map toAxel context) show (ParseError err) = err show (ProjectError err) = err fatal :: String -> String -> a fatal context message = error $ "[FATAL] " <> context <> " - " <> message toIO :: (MonadError IOError m) => ExceptT Error m a -> m a toIO f = do result :: Either Error a <- runExceptT f case result of Left err -> throwError $ userError $ show err Right x -> pure x mapError :: (MonadError e' m) => ExceptT e m a -> (e -> e') -> m a x `mapError` f = runExceptT x >>= \case Left err -> throwError (f err) Right res -> pure res