Improved interactive mode interaction with errors

This commit is contained in:
Robert Bendun 2022-08-21 20:24:49 +02:00
parent cb5eedb2a5
commit 43555cbc1c
5 changed files with 22 additions and 9 deletions

View File

@ -457,7 +457,7 @@ struct Lines
void add_file(std::string filename, std::string_view source); void add_file(std::string filename, std::string_view source);
/// Add single line into file (REPL usage) /// Add single line into file (REPL usage)
void add_line(std::string const& filename, std::string_view source); void add_line(std::string const& filename, std::string_view source, unsigned line_number);
/// Print selected region /// Print selected region
void print(std::ostream& os, std::string const& file, unsigned first_line, unsigned last_line) const; void print(std::ostream& os, std::string const& file, unsigned first_line, unsigned last_line) const;
@ -604,7 +604,7 @@ struct Parser
/// Parses whole source code producing Ast or Error /// Parses whole source code producing Ast or Error
/// using Parser structure internally /// using Parser structure internally
static Result<Ast> parse(std::string_view source, std::string_view filename); static Result<Ast> parse(std::string_view source, std::string_view filename, unsigned line_number = 0);
/// Parse sequence, collection of expressions /// Parse sequence, collection of expressions
Result<Ast> parse_sequence(); Result<Ast> parse_sequence();

View File

@ -312,7 +312,12 @@ std::ostream& operator<<(std::ostream& os, Error const& err)
} }
} }
}, },
[&](errors::Undefined_Operator const&) { unimplemented(); }, [&](errors::Undefined_Operator const& err) {
os << "I encountered '" << err.op << "' that looks like operator but it isn't one.\n";
os << '\n';
print_error_line(loc);
},
[&](errors::Unexpected_Keyword const&) { unimplemented(); }, [&](errors::Unexpected_Keyword const&) { unimplemented(); },
}, err.details); }, err.details);

View File

@ -21,9 +21,12 @@ void Lines::add_file(std::string filename, std::string_view source)
} }
} }
void Lines::add_line(std::string const& filename, std::string_view source) void Lines::add_line(std::string const& filename, std::string_view source, unsigned line_number)
{ {
lines[filename].push_back(source); assert(line_number != 0, "Line number = 0 is invalid");
if (lines[filename].size() <= line_number)
lines[filename].resize(line_number);
lines[filename][line_number - 1] = source;
} }
void Lines::print(std::ostream &os, std::string const& filename, unsigned first_line, unsigned last_line) const void Lines::print(std::ostream &os, std::string const& filename, unsigned first_line, unsigned last_line) const

View File

@ -17,6 +17,7 @@ namespace fs = std::filesystem;
static bool ast_only_mode = false; static bool ast_only_mode = false;
static bool enable_repl = false; static bool enable_repl = false;
static unsigned repl_line_number = 1;
#define Ignore(Call) do { auto const ignore_ ## __LINE__ = (Call); (void) ignore_ ## __LINE__; } while(0) #define Ignore(Call) do { auto const ignore_ ## __LINE__ = (Call); (void) ignore_ ## __LINE__; } while(0)
@ -150,7 +151,7 @@ struct Runner
/// Run given source /// Run given source
Result<void> run(std::string_view source, std::string_view filename, bool output = false) Result<void> run(std::string_view source, std::string_view filename, bool output = false)
{ {
auto ast = Try(Parser::parse(source, filename)); auto ast = Try(Parser::parse(source, filename, repl_line_number));
if (ast_only_mode) { if (ast_only_mode) {
dump(ast); dump(ast);
@ -264,8 +265,9 @@ 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); Lines::the.add_line("<arguments>", argument, repl_line_number);
Try(runner.run(argument, "<arguments>")); Try(runner.run(argument, "<arguments>"));
repl_line_number++;
continue; continue;
} }
auto path = argument; auto path = argument;
@ -286,6 +288,7 @@ static Result<void> Main(std::span<char const*> args)
} }
if (runnables.empty() || enable_repl) { if (runnables.empty() || enable_repl) {
repl_line_number = 1;
enable_repl = true; enable_repl = true;
bestlineSetCompletionCallback(completion); bestlineSetCompletionCallback(completion);
for (;;) { for (;;) {
@ -317,12 +320,13 @@ static Result<void> Main(std::span<char const*> args)
continue; continue;
} }
Lines::the.add_line("<repl>", raw); Lines::the.add_line("<repl>", raw, repl_line_number);
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;
std::cerr << result.error() << std::flush; std::cerr << result.error() << std::flush;
} }
repl_line_number++;
// 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

@ -44,10 +44,11 @@ static Result<std::vector<Ast>> parse_many(
std::optional<Token::Type> separator, std::optional<Token::Type> separator,
At_Least at_least); At_Least at_least);
Result<Ast> Parser::parse(std::string_view source, std::string_view filename) Result<Ast> Parser::parse(std::string_view source, std::string_view filename, unsigned line_number)
{ {
Lexer lexer{source}; Lexer lexer{source};
lexer.location.filename = filename; lexer.location.filename = filename;
lexer.location.line = line_number;
Parser parser; Parser parser;
for (;;) { for (;;) {