From 3c30440d65b9522aed317e535aa59a80f12bde56 Mon Sep 17 00:00:00 2001 From: Konstantin Nazarov Date: Tue, 10 Sep 2024 01:42:47 +0100 Subject: [PATCH] Add location-aware error reporting function to the compiler --- src/compiler.cpp | 24 +++++++++++++++++++++--- src/compiler.hpp | 12 ++++++++++-- src/valeri.cpp | 13 ++++++++----- 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index fe3b367..076cbea 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -170,7 +170,7 @@ Result is_comparison_op(Symbol& sym) { return false; } -Result Compiler::compile(Value& expr) { +Result Compiler::compile(const Value& expr) { auto context = TRY(Context::create()); // If expression is empty - just return nil @@ -1020,7 +1020,25 @@ Result Compiler::compile_symbol(Context& context, return std::move(ex); } -Result compile(Value& expr) { - Compiler c = Compiler(); +Result Compiler::syntax_error(const Value& expr, const char* msg) { + if (expr.is()) { + Syntax& stx = *expr.to(); + auto srcloc = TRY(stx.srcloc()); + SrcLoc& loc = *srcloc.to(); + auto range = loc.sourcerange(); + auto pos = range.start; + + return ERROR_FMT(SyntaxError, _fname, ":", pos.line, ":", pos.column, + " Syntax error: ", msg); + } + return ERROR_FMT(SyntaxError, _fname, " Syntax error: ", msg); +} + +Result Compiler::create(const String& fname) { + return Compiler(TRY(fname.copy())); +} + +Result compile(const String& fname, const Value& expr) { + Compiler c = TRY(Compiler::create(fname)); return c.compile(expr); } diff --git a/src/compiler.hpp b/src/compiler.hpp index 87af4ac..2c8ff74 100644 --- a/src/compiler.hpp +++ b/src/compiler.hpp @@ -27,8 +27,11 @@ struct Expression { class Compiler { public: Compiler() {} + Compiler(String&& fname) : _fname(std::move(fname)) {} - Result compile(Value& expr); + static Result create(const String& fname); + + Result compile(const Value& expr); Result compile_expr(Context& context, const Value& expr); Result compile_list(Context& context, const Value& expr); Result compile_primop(Context& context, Symbol& op, @@ -57,6 +60,11 @@ class Compiler { const Value& expr); Result compile_body(Context& context, const Value& expr); Result compile_function_call(Context& context, const Value& expr); + + Result syntax_error(const Value& expr, const char* message); + + private: + String _fname; }; -Result compile(Value& expr); +Result compile(const String& fname, const Value& expr); diff --git a/src/valeri.cpp b/src/valeri.cpp index 20c7ce6..1124612 100644 --- a/src/valeri.cpp +++ b/src/valeri.cpp @@ -13,12 +13,12 @@ StaticArena<64 * 1024 * 1024> arena; -Result run_string(const String& src) { +Result run_string(const String& fname, const String& src) { auto parsed = TRY(read_multiple(src)); TRY(arena_gc()); - auto compiled = TRY(compile(parsed)); + auto compiled = TRY(compile(fname, parsed)); Module& mod = *compiled.to(); auto vm = TRY(VM::create()); @@ -44,6 +44,7 @@ Result print_error(const Result& res) { Result run_repl() { Dict globals = TRY(Dict::create()); + auto fname = TRY(String::create("")); while (true) { auto src = TRY(read_line("valeri> ")); auto maybe_parsed = read_multiple(src); @@ -53,7 +54,7 @@ Result run_repl() { } auto parsed = maybe_parsed.release_value(); - auto compiled = TRY(compile(parsed)); + auto compiled = TRY(compile(fname, parsed)); Module& mod = *compiled.to(); auto vm = TRY(VM::create()); auto maybe_res = vm.run(mod, globals); @@ -83,10 +84,12 @@ Result run(int argc, const char* argv[]) { return run_repl(); } src = TRY(read_stdin()); - TRY(run_string(src)); + auto fname = TRY(String::create("")); + TRY(run_string(fname, src)); } else { src = TRY(read_file(argv[1])); - TRY(run_string(src)); + auto fname = TRY(String::create(argv[1])); + TRY(run_string(fname, src)); } return Result();