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, SyntaxError,
RuntimeError, RuntimeError,
Raise, Raise,
TaskFailed,
}; };
class Value; class Value;

View file

@ -307,8 +307,18 @@ Result<StackFrame> stdlib_raise(const StackFrame& stack) {
auto stack_size = TRY(stack.size()); auto stack_size = TRY(stack.size());
if (stack_size > 1) { if (stack_size > 1) {
auto accumulator = TRY(stack.get(0)); auto result = TRY(stack.get(1));
auto res = TRY(stack.set(0, accumulator)); 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)); res = TRY(res.ret(0));
return res; return res;
@ -376,7 +386,22 @@ Result<Value> stdlib_task_unknown(const Array& params) {
} }
Result<Value> stdlib_task_print(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) \ #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 // TODO: this should do proper stack unwinding
auto value = TRY(cont.value()); auto value = TRY(cont.value());
std::cout << "Handle raise\n";
if (value.is<Error>()) { if (value.is<Error>()) {
auto obj = TRY(cont.copy_value()); auto obj = TRY(cont.copy_value());
return ERROR_OBJ(Raise, obj); 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); return ERROR(TypeMismatch);
} }