Skip to content
Snippets Groups Projects
Commit 776e0c92 authored by Stéphane Del Pino's avatar Stéphane Del Pino
Browse files

Improve error management

- UnexpectedError and NotImplementedError now display the throwing line
- Simplify error handling during parsing
parent 7c7975df
No related branches found
No related tags found
1 merge request!168Simplify backtrace output
......@@ -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);
}
......
......@@ -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'
......
......@@ -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)
......
......@@ -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,19 +84,8 @@ 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()});
}
}
}
BuiltinFunctionProcessor(ASTNode& argument_node) : m_argument_node{argument_node} {}
};
......
......@@ -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}
{}
......@@ -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
#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;
BacktraceManager bm;
error_msg << bm;
std::cerr << BacktraceManager{} << '\n';
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 UnexpectedError& unexpected_error) {
std::cerr << unexpected_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 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();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment