Implement the first IO function "print" to work via continuations
This commit is contained in:
parent
d496a95b51
commit
cf9aa08aea
3 changed files with 58 additions and 5 deletions
|
@ -23,6 +23,7 @@ enum class ErrorCode {
|
|||
SyntaxError,
|
||||
RuntimeError,
|
||||
Raise,
|
||||
TaskFailed,
|
||||
};
|
||||
|
||||
class Value;
|
||||
|
|
|
@ -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) \
|
||||
|
|
31
src/vm.cpp
31
src/vm.cpp
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue