Implement the first IO function "print" to work via continuations

This commit is contained in:
Konstantin Nazarov 2024-09-28 04:24:37 +01:00
parent d496a95b51
commit cf9aa08aea
Signed by: knazarov
GPG key ID: 4CFE0A42FA409C22
3 changed files with 58 additions and 5 deletions

View file

@ -23,6 +23,7 @@ enum class ErrorCode {
SyntaxError,
RuntimeError,
Raise,
TaskFailed,
};
class Value;

View file

@ -307,8 +307,18 @@ Result<StackFrame> 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<TaskResult>()) return ERROR(TypeMismatch);
const auto& task_result = *result.to<TaskResult>();
auto error = TRY(task_result.error());
if (!error.is<Nil>()) {
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<Value> stdlib_task_unknown(const Array& params) {
}
Result<Value> 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<String>()) {
auto err = Value(TRY(Error::create("type-mismatch", "Type mismatch")));
return ERROR_OBJ(TypeMismatch, err);
}
print_string(*obj.to<String>());
return Value(TRY(Nil::create()));
}
#define STDLIB_TASK(name, id) \

View file

@ -284,12 +284,39 @@ Result<StackFrame> 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<Error>()) {
auto obj = TRY(cont.copy_value());
return ERROR_OBJ(Raise, obj);
}
Value tr;
if (value.is<Task>()) {
auto task_id = value.to<Task>()->task_id();
auto params = TRY(value.to<Task>()->params());
auto res = call_stdlib_task((StdlibTaskId)task_id, params);
if (res.has_error()) {
const auto& err = geterrobj();
Value errobj;
if (err.is<Nil>()) {
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);
}