diff --git a/src/language/PugsParser.cpp b/src/language/PugsParser.cpp index bf573ac54378d1cfd08d619eb80bfbe69950a6ed..fbf7b60a21d0ea6aed9e9609d2b4c733a56fbcbc 100644 --- a/src/language/PugsParser.cpp +++ b/src/language/PugsParser.cpp @@ -126,6 +126,12 @@ parser(const std::string& filename) finalize(); std::exit(1); } + catch (const IExitError& e) { + std::cerr << ASTBacktrace::getInstance().errorMessageAt(e.what()) << '\n'; + + finalize(); + std::exit(1); + } } else { parse_and_execute(input); } diff --git a/src/language/ast/ASTBacktrace.cpp b/src/language/ast/ASTBacktrace.cpp index 90f84bf13fe46299797f11f478fd33f09e0571e9..f34eb0273b1b8d47b25a77a29eefd956e8602160 100644 --- a/src/language/ast/ASTBacktrace.cpp +++ b/src/language/ast/ASTBacktrace.cpp @@ -9,15 +9,14 @@ ASTBacktrace::ASTBacktrace(const std::shared_ptr<TAO_PEGTL_NAMESPACE::file_input {} std::string -ASTBacktrace::stackInfo() const +ASTBacktrace::errorMessageAt(const std::string& message) const { auto& stack = ASTBacktrace::getInstance().m_stack; std::ostringstream error_msg; auto p = stack[stack.size() - 1]->begin(); error_msg << rang::style::bold << p.source << ':' << p.line << ':' << p.column << ": " << rang::style::reset - << rang::fgB::red << "error: " << rang::fg::reset << rang::style::bold << "emitted while executing" - << rang::style::reset << '\n'; + << message << rang::fg::reset << '\n'; if (m_file_input.use_count() > 0) { error_msg << m_file_input->line_at(p) << '\n' diff --git a/src/language/ast/ASTBacktrace.hpp b/src/language/ast/ASTBacktrace.hpp index 4dfc3c2ba5f8a8f3feca01a2a9edd41bf57d3f63..add4bc8b09f2c09c157a6d980104791a9cd89b08 100644 --- a/src/language/ast/ASTBacktrace.hpp +++ b/src/language/ast/ASTBacktrace.hpp @@ -22,7 +22,7 @@ class ASTBacktrace ~ASTBacktrace() = default; public: - std::string stackInfo() const; + std::string errorMessageAt(const std::string& error_msg) const; void push(const ASTNode* node) diff --git a/src/language/node_processor/BuiltinFunctionProcessor.hpp b/src/language/node_processor/BuiltinFunctionProcessor.hpp index 708141d17726102e944200f7c496e522885dfd61..e427160a44cbbb78be3067e6526e44e2f65c8b53 100644 --- a/src/language/node_processor/BuiltinFunctionProcessor.hpp +++ b/src/language/node_processor/BuiltinFunctionProcessor.hpp @@ -7,8 +7,6 @@ #include <language/utils/BuiltinFunctionEmbedder.hpp> #include <language/utils/ParseError.hpp> -#include <utils/SignalManager.hpp> - class BuiltinFunctionExpressionProcessor final : public INodeProcessor { private: @@ -86,18 +84,7 @@ class BuiltinFunctionProcessor : public INodeProcessor } } - if (SignalManager::pauseOnError()) { - // LCOV_EXCL_START - return m_function_expression_processor->execute(context_exec_policy); - // LCOV_EXCL_STOP - } else { - try { - return m_function_expression_processor->execute(context_exec_policy); - } - catch (std::runtime_error& e) { - throw ParseError(e.what(), {m_argument_node.begin()}); - } - } + return m_function_expression_processor->execute(context_exec_policy); } BuiltinFunctionProcessor(ASTNode& argument_node) : m_argument_node{argument_node} {} diff --git a/src/utils/Exceptions.cpp b/src/utils/Exceptions.cpp index 1bf598b7ceac54e0cff3d8b2662b35bdc0654e07..5ffc6f943edc2afa489d0e50a4568cef7effb9da 100644 --- a/src/utils/Exceptions.cpp +++ b/src/utils/Exceptions.cpp @@ -10,23 +10,26 @@ RawError::RawError(std::string_view error_msg) : IExitError(std::string{error_ms NormalError::NormalError(std::string_view error_msg) : IExitError([&] { std::ostringstream os; - os << rang::style::bold << "error:" << rang::style::reset << ' ' << error_msg; + os << rang::fgB::red << "error:" << rang::style::reset << ' ' << error_msg; return os.str(); }()) {} -UnexpectedError::UnexpectedError(std::string_view error_msg) +UnexpectedError::UnexpectedError(std::string_view error_msg, const std::experimental::source_location& source_location) : IBacktraceError([&] { std::ostringstream os; os << rang::fgB::red << "unexpected error:" << rang::style::reset << ' ' << error_msg; return os.str(); - }()) + }()), + m_source_location{source_location} {} -NotImplementedError::NotImplementedError(std::string_view error_msg) +NotImplementedError::NotImplementedError(std::string_view error_msg, + const std::experimental::source_location& source_location) : IBacktraceError([&] { std::ostringstream os; os << rang::fgB::yellow << "not implemented yet:" << rang::style::reset << ' ' << error_msg; return os.str(); - }()) + }()), + m_source_location{source_location} {} diff --git a/src/utils/Exceptions.hpp b/src/utils/Exceptions.hpp index eb229198bc7fcc16d3d4216e859b66c6cf496376..46bfd60bd4b3f5b3cf5ca19c527595fcf92d34db 100644 --- a/src/utils/Exceptions.hpp +++ b/src/utils/Exceptions.hpp @@ -3,6 +3,9 @@ #include <stdexcept> #include <string> +#include <string_view> + +#include <experimental/source_location> struct IExitError : public std::runtime_error { @@ -32,6 +35,8 @@ struct NormalError : public IExitError struct IBacktraceError : public std::runtime_error { + virtual const std::experimental::source_location& sourceLocation() const = 0; + IBacktraceError(const IBacktraceError&) = delete; IBacktraceError(IBacktraceError&&) = delete; @@ -39,20 +44,42 @@ struct IBacktraceError : public std::runtime_error virtual ~IBacktraceError() = default; }; -struct UnexpectedError : IBacktraceError +class UnexpectedError final : public IBacktraceError { + private: + const std::experimental::source_location m_source_location; + + public: + const std::experimental::source_location& + sourceLocation() const + { + return m_source_location; + } + UnexpectedError(const UnexpectedError&) = delete; UnexpectedError(UnexpectedError&&) = delete; - UnexpectedError(std::string_view error_msg); + UnexpectedError(std::string_view error_msg, + const std::experimental::source_location& = std::experimental::source_location::current()); }; -struct NotImplementedError : IBacktraceError +class NotImplementedError final : public IBacktraceError { + private: + const std::experimental::source_location m_source_location; + + public: + const std::experimental::source_location& + sourceLocation() const + { + return m_source_location; + } + NotImplementedError(const NotImplementedError&) = delete; NotImplementedError(NotImplementedError&&) = delete; - NotImplementedError(std::string_view error_msg); + NotImplementedError(std::string_view error_msg, + const std::experimental::source_location& = std::experimental::source_location::current()); }; #endif // EXCEPTIONS_HPP diff --git a/src/utils/SignalManager.cpp b/src/utils/SignalManager.cpp index 1fb5c9949264c9bd6b6b8800d5ea344cf1c73566..f2721177285d3ed5c8edb7ca484a685679c94e5d 100644 --- a/src/utils/SignalManager.cpp +++ b/src/utils/SignalManager.cpp @@ -1,6 +1,7 @@ #include <utils/SignalManager.hpp> #include <language/ast/ASTBacktrace.hpp> +#include <language/utils/ParseError.hpp> #include <utils/BacktraceManager.hpp> #include <utils/ConsoleManager.hpp> #include <utils/Messenger.hpp> @@ -78,24 +79,36 @@ SignalManager::handler(int signal) // Each failing process must write std::cerr.setstate(std::ios::goodbit); - std::ostringstream error_msg; + std::cerr << BacktraceManager{} << '\n'; - BacktraceManager bm; - error_msg << bm; - - std::cerr << error_msg.str() << '\n'; + std::cerr << "\n *** " << rang::style::reset << rang::fg::reset << rang::style::bold << "Signal " << rang::fgB::red + << signalName(signal) << rang::fg::reset << " caught" << rang::style::reset << " ***\n\n"; std::exception_ptr eptr = std::current_exception(); try { if (eptr) { std::rethrow_exception(eptr); + } else { + std::ostringstream error_msg; + error_msg << "received " << signalName(signal); + std::cerr << ASTBacktrace::getInstance().errorMessageAt(error_msg.str()) << '\n'; } } - catch (const NotImplementedError& not_implemented_error) { - std::cerr << not_implemented_error.what() << '\n'; + catch (const IBacktraceError& backtrace_error) { + auto source_location = backtrace_error.sourceLocation(); + std::cerr << rang::fgB::cyan << source_location.file_name() << ':' << source_location.line() << ':' + << source_location.column() << ':' << rang::fg::reset << rang::fgB::yellow + << " threw the following exception" << rang::fg::reset << "\n\n"; + std::cerr << ASTBacktrace::getInstance().errorMessageAt(backtrace_error.what()) << '\n'; + } + catch (const ParseError& parse_error) { + auto p = parse_error.positions().front(); + std::cerr << rang::style::bold << p.source << ':' << p.line << ':' << p.column << ':' << rang::style::reset + << rang::fgB::red << " error: " << rang::fg::reset << rang::style::bold << parse_error.what() + << rang::style::reset << '\n'; } - catch (const UnexpectedError& unexpected_error) { - std::cerr << unexpected_error.what() << '\n'; + catch (const IExitError& exit_error) { + std::cerr << ASTBacktrace::getInstance().errorMessageAt(exit_error.what()) << '\n'; } catch (const AssertError& assert_error) { std::cerr << assert_error << '\n'; @@ -104,11 +117,6 @@ SignalManager::handler(int signal) std::cerr << "Unknown exception!\n"; } - std::cerr << "\n *** " << rang::style::reset << rang::fg::reset << rang::style::bold << "Signal " << rang::fgB::red - << signalName(signal) << rang::fg::reset << " caught" << rang::style::reset << " ***\n"; - - std::cerr << '\n' << ASTBacktrace::getInstance().stackInfo() << '\n'; - SignalManager::pauseForDebug(signal); mutex.unlock();