diff --git a/include/musique.hh b/include/musique.hh index c422de5..5d926c7 100644 --- a/include/musique.hh +++ b/include/musique.hh @@ -457,7 +457,7 @@ struct Lines 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); + void add_line(std::string const& filename, std::string_view source, unsigned line_number); /// Print selected region 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 /// using Parser structure internally - static Result parse(std::string_view source, std::string_view filename); + static Result parse(std::string_view source, std::string_view filename, unsigned line_number = 0); /// Parse sequence, collection of expressions Result parse_sequence(); diff --git a/src/errors.cc b/src/errors.cc index 31fa5d5..35ae955 100644 --- a/src/errors.cc +++ b/src/errors.cc @@ -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(); }, }, err.details); diff --git a/src/lines.cc b/src/lines.cc index 5da416d..d6d74d4 100644 --- a/src/lines.cc +++ b/src/lines.cc @@ -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 diff --git a/src/main.cc b/src/main.cc index d460335..c7d39c9 100644 --- a/src/main.cc +++ b/src/main.cc @@ -17,6 +17,7 @@ namespace fs = std::filesystem; static bool ast_only_mode = 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) @@ -150,7 +151,7 @@ struct Runner /// Run given source Result 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) { dump(ast); @@ -264,8 +265,9 @@ static Result Main(std::span args) for (auto const& [is_file, argument] : runnables) { if (!is_file) { - Lines::the.add_line("", argument); + Lines::the.add_line("", argument, repl_line_number); Try(runner.run(argument, "")); + repl_line_number++; continue; } auto path = argument; @@ -286,6 +288,7 @@ static Result Main(std::span args) } if (runnables.empty() || enable_repl) { + repl_line_number = 1; enable_repl = true; bestlineSetCompletionCallback(completion); for (;;) { @@ -317,12 +320,13 @@ static Result Main(std::span args) continue; } - Lines::the.add_line("", raw); + Lines::the.add_line("", raw, repl_line_number); auto result = runner.run(raw, "", true); if (not result.has_value()) { std::cout << 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 } } diff --git a/src/parser.cc b/src/parser.cc index 09b7b0a..2f55069 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -44,10 +44,11 @@ static Result> parse_many( std::optional separator, At_Least at_least); -Result Parser::parse(std::string_view source, std::string_view filename) +Result Parser::parse(std::string_view source, std::string_view filename, unsigned line_number) { Lexer lexer{source}; lexer.location.filename = filename; + lexer.location.line = line_number; Parser parser; for (;;) {