From cf9aa08aea859924b0e588ee7733c0f560fef311 Mon Sep 17 00:00:00 2001 From: Konstantin Nazarov Date: Sat, 28 Sep 2024 04:24:37 +0100 Subject: [PATCH] Implement the first IO function "print" to work via continuations --- src/error.hpp | 1 + src/stdlib.cpp | 31 ++++++++++++++++++++++++++++--- src/vm.cpp | 31 +++++++++++++++++++++++++++++-- 3 files changed, 58 insertions(+), 5 deletions(-) diff --git a/src/error.hpp b/src/error.hpp index bdd49d3..1d6d8c0 100644 --- a/src/error.hpp +++ b/src/error.hpp @@ -23,6 +23,7 @@ enum class ErrorCode { SyntaxError, RuntimeError, Raise, + TaskFailed, }; class Value; diff --git a/src/stdlib.cpp b/src/stdlib.cpp index 311cac6..22632f7 100644 --- a/src/stdlib.cpp +++ b/src/stdlib.cpp @@ -307,8 +307,18 @@ Result stdlib_raise(const StackFrame& stack) { auto stack_size = TRY(stack.size()); if (stack_size > 1) { - auto accumulator = TRY(stack.get(0)); - auto res = TRY(stack.set(0, accumulator)); + auto result = TRY(stack.get(1)); + if (!result.is()) return ERROR(TypeMismatch); + + const auto& task_result = *result.to(); + + auto error = TRY(task_result.error()); + + if (!error.is()) { + return ERROR_OBJ(TaskFailed, error); + } + + auto res = TRY(stack.set(0, TRY(task_result.result()))); res = TRY(res.ret(0)); return res; @@ -376,7 +386,22 @@ Result stdlib_task_unknown(const Array& params) { } Result stdlib_task_print(const Array& params) { - return ERROR(NotImplemented); + auto size = TRY(params.size()); + + if (size != 1) { + auto err = Value(TRY(Error::create("argument-count-mismatch", "Argument count mismatch"))); + return ERROR_OBJ(ArgumentCountMismatch, err); + } + + auto obj = TRY(params.get(0)); + + if (!obj.is()) { + auto err = Value(TRY(Error::create("type-mismatch", "Type mismatch"))); + return ERROR_OBJ(TypeMismatch, err); + } + + print_string(*obj.to()); + return Value(TRY(Nil::create())); } #define STDLIB_TASK(name, id) \ diff --git a/src/vm.cpp b/src/vm.cpp index d1dd962..9d9cb7f 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -284,12 +284,39 @@ Result VM::handle_raise(const Continuation& cont) { // TODO: this should do proper stack unwinding auto value = TRY(cont.value()); - std::cout << "Handle raise\n"; - if (value.is()) { auto obj = TRY(cont.copy_value()); return ERROR_OBJ(Raise, obj); } + + Value tr; + + if (value.is()) { + auto task_id = value.to()->task_id(); + auto params = TRY(value.to()->params()); + + auto res = call_stdlib_task((StdlibTaskId)task_id, params); + + if (res.has_error()) { + const auto& err = geterrobj(); + Value errobj; + if (err.is()) { + errobj = Value(TRY(Error::create("unknown-error", "Unknown error"))); + } else { + errobj = TRY(err.copy()); + } + + tr = Value(TRY(TaskResult::create(TRY(Nil::create()), errobj))); + } else { + tr = Value( + TRY(TaskResult::create(res.release_value(), TRY(Nil::create())))); + } + + auto frame = TRY(cont.frame()); + + auto new_frame = frame.set(TRY(frame.size()), tr); + return new_frame; + } return ERROR(TypeMismatch); }