Relevant code printing when error reporting
This commit is contained in:
parent
d16f6de53c
commit
b7d879bf70
1
Makefile
1
Makefile
@ -14,6 +14,7 @@ Obj= \
|
|||||||
errors.o \
|
errors.o \
|
||||||
interpreter.o \
|
interpreter.o \
|
||||||
lexer.o \
|
lexer.o \
|
||||||
|
lines.o \
|
||||||
location.o \
|
location.o \
|
||||||
number.o \
|
number.o \
|
||||||
parser.o \
|
parser.o \
|
||||||
|
@ -125,36 +125,47 @@ std::ostream& operator<<(std::ostream& os, Error const& err)
|
|||||||
|
|
||||||
error_heading(os, err.location, Error_Level::Error, short_description);
|
error_heading(os, err.location, Error_Level::Error, short_description);
|
||||||
|
|
||||||
|
auto const loc = err.location;
|
||||||
visit(Overloaded {
|
visit(Overloaded {
|
||||||
[&os](errors::Unrecognized_Character const& err) {
|
[&](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: U+" << 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";
|
||||||
|
|
||||||
|
Lines::the.print(os, std::string(loc->filename), loc->line, loc->line);
|
||||||
|
|
||||||
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";
|
||||||
},
|
},
|
||||||
|
|
||||||
[&os](errors::Failed_Numeric_Parsing const& err) {
|
[&](errors::Failed_Numeric_Parsing const& err) {
|
||||||
constexpr auto Max = std::numeric_limits<decltype(Number::num)>::max();
|
constexpr auto Max = std::numeric_limits<decltype(Number::num)>::max();
|
||||||
constexpr auto Min = std::numeric_limits<decltype(Number::num)>::min();
|
constexpr auto Min = std::numeric_limits<decltype(Number::num)>::min();
|
||||||
os << "I tried to parse numeric literal, but I failed.";
|
os << "I tried to parse numeric literal, but I failed.\n\n";
|
||||||
|
|
||||||
|
Lines::the.print(os, std::string(loc->filename), loc->line, loc->line);
|
||||||
|
|
||||||
if (err.reason == std::errc::result_out_of_range) {
|
if (err.reason == std::errc::result_out_of_range) {
|
||||||
os << " Declared number is outside of valid range of numbers that can be represented.\n";
|
os << "\nDeclared number is outside of valid range of numbers that can be represented.\n";
|
||||||
os << " Only numbers in range [" << Min << ", " << Max << "] are supported\n";
|
os << "Only numbers in range [" << Min << ", " << Max << "] are supported\n";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
[&os](errors::internal::Unexpected_Token const& ut) {
|
[&](errors::internal::Unexpected_Token const& ut) {
|
||||||
os << "I encountered unexpected token during " << ut.when << '\n';
|
os << "I encountered unexpected token during " << ut.when << '\n';
|
||||||
os << " Token type: " << ut.type << '\n';
|
os << " Token type: " << ut.type << '\n';
|
||||||
os << " Token source: " << ut.source << '\n';
|
os << " Token source: " << ut.source << "\n\n";
|
||||||
|
|
||||||
|
Lines::the.print(os, std::string(loc->filename), loc->line, loc->line);
|
||||||
|
|
||||||
os << pretty::begin_comment << "\nThis error is considered an internal one. It should not be displayed to the end user.\n" << pretty::end;
|
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);
|
||||||
},
|
},
|
||||||
|
|
||||||
[&os](errors::Expected_Expression_Separator_Before const& err) {
|
[&](errors::Expected_Expression_Separator_Before const& err) {
|
||||||
os << "I failed to parse following code, due to missing semicolon before it!\n";
|
os << "I failed to parse following code, due to missing semicolon before it!\n\n";
|
||||||
|
|
||||||
|
Lines::the.print(os, std::string(loc->filename), loc->line, loc->line);
|
||||||
|
|
||||||
if (err.what == "var") {
|
if (err.what == "var") {
|
||||||
os << "\nIf you want to create variable inside expression try wrapping them inside parentheses like this:\n";
|
os << "\nIf you want to create variable inside expression try wrapping them inside parentheses like this:\n";
|
||||||
@ -162,9 +173,10 @@ std::ostream& operator<<(std::ostream& os, Error const& err)
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
[&os](errors::Literal_As_Identifier const& err) {
|
[&](errors::Literal_As_Identifier const& err) {
|
||||||
os << "I expected an identifier in " << err.context << ", but found" << (err.type_name.empty() ? "" : " ") << err.type_name << " value = '" << err.source << "'\n";
|
os << "I expected an identifier in " << err.context << ", but found" << (err.type_name.empty() ? "" : " ") << err.type_name << " value = '" << err.source << "'\n\n";
|
||||||
|
|
||||||
|
Lines::the.print(os, std::string(loc->filename), loc->line, loc->line);
|
||||||
|
|
||||||
if (err.type_name == "chord") {
|
if (err.type_name == "chord") {
|
||||||
os << "\nTry renaming to different name or appending with something that is not part of chord literal like 'x'\n";
|
os << "\nTry renaming to different name or appending with something that is not part of chord literal like 'x'\n";
|
||||||
@ -176,10 +188,10 @@ std::ostream& operator<<(std::ostream& os, Error const& err)
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
[&os](errors::Not_Callable const&) { unimplemented(); },
|
[&](errors::Not_Callable const&) { unimplemented(); },
|
||||||
[&os](errors::Undefined_Operator const&) { unimplemented(); },
|
[&](errors::Undefined_Operator const&) { unimplemented(); },
|
||||||
[&os](errors::Unexpected_Keyword const&) { unimplemented(); },
|
[&](errors::Unexpected_Keyword const&) { unimplemented(); },
|
||||||
[&os](errors::Unexpected_Empty_Source const&) { unimplemented(); }
|
[&](errors::Unexpected_Empty_Source const&) { unimplemented(); }
|
||||||
}, err.details);
|
}, err.details);
|
||||||
|
|
||||||
return os;
|
return os;
|
||||||
|
36
src/lines.cc
Normal file
36
src/lines.cc
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#include <musique.hh>
|
||||||
|
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
|
Lines Lines::the;
|
||||||
|
|
||||||
|
void Lines::add_file(std::string filename, std::string_view source)
|
||||||
|
{
|
||||||
|
auto file = lines.insert({ filename, {} });
|
||||||
|
auto &lines_in_file = file.first->second;
|
||||||
|
|
||||||
|
while (not source.empty()) {
|
||||||
|
auto end = source.find('\n');
|
||||||
|
if (end == std::string_view::npos) {
|
||||||
|
lines_in_file.push_back({ source.data(), end });
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
lines_in_file.push_back({ source.data(), end });
|
||||||
|
source.remove_prefix(end+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lines::add_line(std::string const& filename, std::string_view source)
|
||||||
|
{
|
||||||
|
lines[filename].push_back(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lines::print(std::ostream &os, std::string const& filename, unsigned first_line, unsigned last_line) const
|
||||||
|
{
|
||||||
|
auto const& file = lines.at(filename);
|
||||||
|
for (auto i = first_line; i <= last_line; ++i) {
|
||||||
|
os << std::setw(3) << std::right << i << " | " << file[i-1] << '\n';
|
||||||
|
}
|
||||||
|
os << std::flush;
|
||||||
|
}
|
@ -166,11 +166,13 @@ static Result<void> Main(std::span<char const*> args)
|
|||||||
|
|
||||||
for (auto const& [is_file, argument] : runnables) {
|
for (auto const& [is_file, argument] : runnables) {
|
||||||
if (!is_file) {
|
if (!is_file) {
|
||||||
|
Lines::the.add_line("<arguments>", argument);
|
||||||
Try(runner.run(argument, "<arguments>"));
|
Try(runner.run(argument, "<arguments>"));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto const path = argument;
|
auto path = argument;
|
||||||
if (path == "-") {
|
if (path == "-") {
|
||||||
|
path = "<stdin>";
|
||||||
eternal_sources.emplace_back(std::istreambuf_iterator<char>(std::cin), std::istreambuf_iterator<char>());
|
eternal_sources.emplace_back(std::istreambuf_iterator<char>(std::cin), std::istreambuf_iterator<char>());
|
||||||
} else {
|
} else {
|
||||||
if (not fs::exists(path)) {
|
if (not fs::exists(path)) {
|
||||||
@ -181,6 +183,7 @@ static Result<void> Main(std::span<char const*> args)
|
|||||||
eternal_sources.emplace_back(std::istreambuf_iterator<char>(source_file), std::istreambuf_iterator<char>());
|
eternal_sources.emplace_back(std::istreambuf_iterator<char>(source_file), std::istreambuf_iterator<char>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Lines::the.add_file(std::string(path), eternal_sources.back());
|
||||||
Try(runner.run(eternal_sources.back(), path));
|
Try(runner.run(eternal_sources.back(), path));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,6 +219,7 @@ static Result<void> Main(std::span<char const*> args)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Lines::the.add_line("<repl>", raw);
|
||||||
auto result = runner.run(raw, "<repl>", true);
|
auto result = runner.run(raw, "<repl>", true);
|
||||||
if (not result.has_value()) {
|
if (not result.has_value()) {
|
||||||
std::cout << std::flush;
|
std::cout << std::flush;
|
||||||
|
@ -392,6 +392,23 @@ std::ostream& operator<<(std::ostream& os, Token const& tok);
|
|||||||
/// Token type debug printing
|
/// Token type debug printing
|
||||||
std::ostream& operator<<(std::ostream& os, Token::Type type);
|
std::ostream& operator<<(std::ostream& os, Token::Type type);
|
||||||
|
|
||||||
|
struct Lines
|
||||||
|
{
|
||||||
|
static Lines the;
|
||||||
|
|
||||||
|
/// Region of lines in files
|
||||||
|
std::unordered_map<std::string, std::vector<std::string_view>> lines;
|
||||||
|
|
||||||
|
/// Add lines from file
|
||||||
|
void add_file(std::string filename, std::string_view source);
|
||||||
|
|
||||||
|
/// Add single line into file (REPL usage)
|
||||||
|
void add_line(std::string const& filename, std::string_view source);
|
||||||
|
|
||||||
|
/// Print selected region
|
||||||
|
void print(std::ostream& os, std::string const& file, unsigned first_line, unsigned last_line) const;
|
||||||
|
};
|
||||||
|
|
||||||
/// Explicit marker of the end of file
|
/// Explicit marker of the end of file
|
||||||
struct End_Of_File {};
|
struct End_Of_File {};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user