Make errors in REPL more human-readable

This commit is contained in:
Konstantin Nazarov 2024-09-11 01:35:38 +01:00
parent 2bad87d0b0
commit d280c34e66
Signed by: knazarov
GPG key ID: 4CFE0A42FA409C22
5 changed files with 43 additions and 31 deletions

View file

@ -898,3 +898,14 @@ Result<String> build_string(uint64_t value) {
auto val = Value(TRY(Int64::create((int64_t)value))); auto val = Value(TRY(Int64::create((int64_t)value)));
return write_one(val); return write_one(val);
} }
Result<void> print_string(const String& s) {
auto ba = TRY(ByteArray::create(s));
auto size = TRY(ba.size());
for (uint64_t i = 0; i < size; i++) {
std::cout << TRY(ba[i]);
}
return Result<void>();
}

View file

@ -1336,3 +1336,5 @@ Result<String> build_string(const T& value, Args&&... args) {
first = TRY(first.concat(rest)); first = TRY(first.concat(rest));
return first; return first;
} }
Result<void> print_string(const String& s);

View file

@ -622,29 +622,25 @@ Result<Expression> Compiler::compile_fn(Context& context, Symbol& op,
Context ctx = TRY(Context::create(context)); Context ctx = TRY(Context::create(context));
ctx.maxreg = 1; // Reserve the slot for function itself ctx.maxreg = 1; // Reserve the slot for function itself
auto first = TRY(expr.rest()); auto rest = TRY(expr.rest());
if (!TRY(syntax_is_list(first))) {
return ERROR(CompilationError);
}
Value name = TRY(Nil::create()); Value name = TRY(Nil::create());
auto maybe_name = TRY(first.first()); auto maybe_name = TRY(expr.second());
auto maybe_name_unwrapped = TRY(syntax_unwrap(maybe_name)); auto maybe_name_unwrapped = TRY(syntax_unwrap(maybe_name));
if (maybe_name_unwrapped.is<Symbol>()) { if (maybe_name_unwrapped.is<Symbol>()) {
name = TRY(maybe_name_unwrapped.copy()); name = TRY(maybe_name_unwrapped.copy());
ctx.fname = TRY(name.copy()); ctx.fname = TRY(name.copy());
first = TRY(first.rest()); rest = TRY(rest.rest());
if (!TRY(syntax_is_list(first))) { if (!TRY(syntax_is_list(rest))) {
return ERROR(CompilationError); return ERROR(CompilationError);
} }
} }
auto param = TRY(first.first()); auto param = TRY(rest.first());
uint64_t arity = 0; uint64_t arity = 0;
while (!TRY(syntax_is_nil(param))) { while (!TRY(syntax_is_nil(param))) {
@ -655,7 +651,7 @@ Result<Expression> Compiler::compile_fn(Context& context, Symbol& op,
auto param_name_unwrapped = TRY(syntax_unwrap(param_name)); auto param_name_unwrapped = TRY(syntax_unwrap(param_name));
if (!param_name_unwrapped.is<Symbol>()) { if (!param_name_unwrapped.is<Symbol>()) {
return ERROR(CompilationError); return syntax_error(param_name, "Parameter name must be a symbol");
} }
int64_t reg = TRY(ctx.add_var(param_name_unwrapped)); int64_t reg = TRY(ctx.add_var(param_name_unwrapped));
@ -664,13 +660,13 @@ Result<Expression> Compiler::compile_fn(Context& context, Symbol& op,
arity++; arity++;
} }
Value second = TRY(first.rest()); Value body = TRY(rest.rest());
if (!TRY(syntax_is_list(second))) { if (!TRY(syntax_is_list(body))) {
return ERROR(CompilationError); return ERROR(CompilationError);
} }
auto ex = TRY(compile_body(ctx, second)); auto ex = TRY(compile_body(ctx, body));
TRY(ex.add_opcode(Oc::Mov, {0, (int64_t)0}, {0, (int64_t)ex.reg})); TRY(ex.add_opcode(Oc::Mov, {0, (int64_t)0}, {0, (int64_t)ex.reg}));
TRY(ex.add_opcode(Oc::Ret, {0, (int64_t)0})); TRY(ex.add_opcode(Oc::Ret, {0, (int64_t)0}));
@ -821,9 +817,6 @@ Result<Expression> Compiler::compile_body(Context& context, const Value& expr) {
int64_t maxreg = context.maxreg; int64_t maxreg = context.maxreg;
while (!cur.is<Nil>()) { while (!cur.is<Nil>()) {
if (!TRY(syntax_is_list(cur))) {
return ERROR(CompilationError);
}
auto expr_val = TRY(cur.first()); auto expr_val = TRY(cur.first());
// debug_print(expr_val); // debug_print(expr_val);

View file

@ -17,17 +17,6 @@ Result<Value> stdlib_unknown(const Array& params) {
return ERROR(NotImplemented); return ERROR(NotImplemented);
} }
Result<void> print_string(const String& s) {
auto ba = TRY(ByteArray::create(s));
auto size = TRY(ba.size());
for (uint64_t i = 0; i < size; i++) {
std::cout << TRY(ba[i]);
}
return Result<void>();
}
Result<Value> stdlib_print(const Array& params) { Result<Value> stdlib_print(const Array& params) {
auto size = TRY(params.size()); auto size = TRY(params.size());
for (uint64_t i = 0; i < size; i++) { for (uint64_t i = 0; i < size; i++) {

View file

@ -34,7 +34,9 @@ Result<void> print_error(const Result<Value>& res) {
if (errobj.is<Nil>()) { if (errobj.is<Nil>()) {
debug_print(geterr()); debug_print(geterr());
} else { } else {
debug_print(errobj); auto message = TRY(errobj.to<Error>()->message());
print_string(*message.to<String>());
std::cout << "\n";
} }
} }
@ -54,7 +56,13 @@ Result<void> run_repl() {
} }
auto parsed = maybe_parsed.release_value(); auto parsed = maybe_parsed.release_value();
auto compiled = TRY(compile(fname, parsed)); auto maybe_compiled = compile(fname, parsed);
if (maybe_compiled.has_error()) {
print_error(maybe_compiled);
continue;
}
auto compiled = maybe_compiled.release_value();
Module& mod = *compiled.to<Module>(); Module& mod = *compiled.to<Module>();
auto vm = TRY(VM::create()); auto vm = TRY(VM::create());
auto maybe_res = vm.run(mod, globals); auto maybe_res = vm.run(mod, globals);
@ -85,11 +93,20 @@ Result<void> run(int argc, const char* argv[]) {
} }
src = TRY(read_stdin()); src = TRY(read_stdin());
auto fname = TRY(String::create("<stdin>")); auto fname = TRY(String::create("<stdin>"));
TRY(run_string(fname, src)); auto res = run_string(fname, src);
if (res.has_error()) {
print_error(res);
exit(1);
}
} else { } else {
src = TRY(read_file(argv[1])); src = TRY(read_file(argv[1]));
auto fname = TRY(String::create(argv[1])); auto fname = TRY(String::create(argv[1]));
TRY(run_string(fname, src)); auto res = run_string(fname, src);
if (res.has_error()) {
print_error(res);
exit(1);
}
} }
return Result<void>(); return Result<void>();