Optionally colorful errors part 2; repl dont exit on errors

This commit is contained in:
Robert Bendun 2022-05-29 23:34:20 +02:00
parent 3c4da4a226
commit 016e48570e
4 changed files with 37 additions and 10 deletions

View File

@ -17,6 +17,7 @@ Obj= \
location.o \ location.o \
number.o \ number.o \
parser.o \ parser.o \
pretty.o \
unicode.o \ unicode.o \
unicode_tables.o \ unicode_tables.o \
value.o value.o

View File

@ -37,30 +37,37 @@ static std::ostream& error_heading(
Error_Level lvl, Error_Level lvl,
std::string_view short_description) std::string_view short_description)
{ {
std::stringstream ss;
switch (lvl) { switch (lvl) {
case Error_Level::Error: case Error_Level::Error:
os << "ERROR " << short_description << ' '; ss << pretty::begin_error << "ERROR " << pretty::end << short_description;
break; break;
// This branch should be reached if we have Error_Level::Bug // This branch should be reached if we have Error_Level::Bug
// or definetely where error level is outside of enum Error_Level // or definetely where error level is outside of enum Error_Level
default: default:
os << "IMPLEMENTATION BUG " << short_description << ' '; ss << pretty::begin_error << "IMPLEMENTATION BUG " << pretty::end << short_description;
} }
if (location) { if (location) {
os << " at " << *location; ss << " at " << pretty::begin_path << *location << pretty::end;
} }
auto heading = std::move(ss).str();
os << heading << '\n';
auto const line_length = heading.size();
std::fill_n(std::ostreambuf_iterator<char>(os), line_length, '-');
return os << '\n'; return os << '\n';
} }
static void encourage_contact(std::ostream &os) static void encourage_contact(std::ostream &os)
{ {
os << os << pretty::begin_comment << "\n"
"Interpreter got in state that was not expected by it's developers.\n" "Interpreter got in state that was not expected by it's developers.\n"
"Contact them providing code that coused it and error message above to resolve this trouble\n" "Contact them providing code that coused it and error message above to resolve this trouble\n"
<< std::flush; << pretty::end << std::flush;
} }
void assert(bool condition, std::string message, Location loc) void assert(bool condition, std::string message, Location loc)
@ -69,7 +76,7 @@ void assert(bool condition, std::string message, Location loc)
error_heading(std::cerr, loc, Error_Level::Bug, "Assertion in interpreter"); error_heading(std::cerr, loc, Error_Level::Bug, "Assertion in interpreter");
if (not message.empty()) if (not message.empty())
std::cerr << "with message: " << message << std::endl; std::cerr << message << std::endl;
encourage_contact(std::cerr); encourage_contact(std::cerr);
@ -91,7 +98,6 @@ void assert(bool condition, std::string message, Location loc)
[[noreturn]] void unreachable(Location loc) [[noreturn]] void unreachable(Location loc)
{ {
error_heading(std::cerr, loc, Error_Level::Bug, "Reached unreachable state"); error_heading(std::cerr, loc, Error_Level::Bug, "Reached unreachable state");
encourage_contact(std::cerr); encourage_contact(std::cerr);
std::exit(1); std::exit(1);
@ -117,7 +123,7 @@ std::ostream& operator<<(std::ostream& os, Error const& err)
visit(Overloaded { visit(Overloaded {
[&os](errors::Unrecognized_Character const& err) { [&os](errors::Unrecognized_Character const& err) {
os << "I encountered character in the source code that was not supposed to be here.\n"; os << "I encountered character in the source code that was not supposed to be here.\n";
os << " Character Unicode code: " << std::hex << err.invalid_character << '\n'; os << " Character Unicode code: U+" << std::hex << err.invalid_character << '\n';
os << " Character printed: '" << utf8::Print{err.invalid_character} << "'\n"; os << " Character printed: '" << utf8::Print{err.invalid_character} << "'\n";
os << "\n"; os << "\n";
os << "Musique only accepts characters that are unicode letters or ascii numbers and punctuation\n"; os << "Musique only accepts characters that are unicode letters or ascii numbers and punctuation\n";
@ -138,7 +144,7 @@ std::ostream& operator<<(std::ostream& os, Error const& err)
os << " Token type: " << ut.type << '\n'; os << " Token type: " << ut.type << '\n';
os << " Token source: " << ut.source << '\n'; os << " Token source: " << ut.source << '\n';
os << "\nThis error is considered an internal one. It should not be displayed to the end user.\n"; os << pretty::begin_comment << "\nThis error is considered an internal one. It should not be displayed to the end user.\n" << pretty::end;
encourage_contact(os); encourage_contact(os);
}, },

View File

@ -111,6 +111,10 @@ std::vector<std::string> eternal_sources;
/// Fancy main that supports Result forwarding on error (Try macro) /// Fancy main that supports Result forwarding on error (Try macro)
static Result<void> Main(std::span<char const*> args) static Result<void> Main(std::span<char const*> args)
{ {
if (isatty(STDOUT_FILENO) && getenv("NO_COLOR") == nullptr) {
pretty::terminal_mode();
}
/// Describes all arguments that will be run /// Describes all arguments that will be run
struct Run struct Run
{ {
@ -211,7 +215,11 @@ static Result<void> Main(std::span<char const*> args)
continue; continue;
} }
Try(runner.run(raw, "<repl>")); auto result = runner.run(raw, "<repl>");
if (not result.has_value()) {
std::cout << std::flush;
std::cerr << result.error() << std::flush;
}
// We don't free input line since there could be values that still relay on it // We don't free input line since there could be values that still relay on it
} }
} }

View File

@ -122,6 +122,18 @@ namespace errors
>; >;
} }
/// All code related to pretty printing
namespace pretty
{
std::ostream& begin_error(std::ostream&);
std::ostream& begin_path(std::ostream&);
std::ostream& begin_comment(std::ostream&);
std::ostream& end(std::ostream&);
void terminal_mode();
void no_color_mode();
}
template<typename ...Lambdas> template<typename ...Lambdas>
struct Overloaded : Lambdas... { using Lambdas::operator()...; }; struct Overloaded : Lambdas... { using Lambdas::operator()...; };