Implement "task" and "task-result" objects for stdlib IO
This commit is contained in:
parent
efef0c57ae
commit
d496a95b51
14 changed files with 388 additions and 7 deletions
|
@ -98,6 +98,10 @@ Result<PodObject*> Arena::gc_pod(PodObject* obj) {
|
|||
return gc_error((PodError*)obj);
|
||||
case Tag::Continuation:
|
||||
return gc_continuation((PodContinuation*)obj);
|
||||
case Tag::Task:
|
||||
return gc_task((PodTask*)obj);
|
||||
case Tag::TaskResult:
|
||||
return gc_task_result((PodTaskResult*)obj);
|
||||
}
|
||||
|
||||
return ERROR(TypeMismatch);
|
||||
|
@ -282,7 +286,7 @@ Result<PodObject*> Arena::gc_error(PodError* obj) {
|
|||
|
||||
Result<PodObject*> Arena::gc_continuation(PodContinuation* obj) {
|
||||
auto nobj = TRY(alloc<PodContinuation>());
|
||||
nobj->header.tag = Tag::Error;
|
||||
nobj->header.tag = Tag::Continuation;
|
||||
|
||||
nobj->value = TRY(gc_pod(obj->value.get()));
|
||||
nobj->frame = TRY(gc_pod(obj->frame.get()));
|
||||
|
@ -290,6 +294,26 @@ Result<PodObject*> Arena::gc_continuation(PodContinuation* obj) {
|
|||
return nobj;
|
||||
}
|
||||
|
||||
Result<PodObject*> Arena::gc_task(PodTask* obj) {
|
||||
auto nobj = TRY(alloc<PodTask>());
|
||||
nobj->header.tag = Tag::Task;
|
||||
|
||||
nobj->task_id = obj->task_id;
|
||||
nobj->params = TRY(gc_pod(obj->params.get()));
|
||||
|
||||
return nobj;
|
||||
}
|
||||
|
||||
Result<PodObject*> Arena::gc_task_result(PodTaskResult* obj) {
|
||||
auto nobj = TRY(alloc<PodTaskResult>());
|
||||
nobj->header.tag = Tag::TaskResult;
|
||||
|
||||
nobj->result = TRY(gc_pod(obj->result.get()));
|
||||
nobj->error = TRY(gc_pod(obj->error.get()));
|
||||
|
||||
return nobj;
|
||||
}
|
||||
|
||||
Arena& get_arena() {
|
||||
if (current_arena == 0) die("Arena not set\n");
|
||||
return *current_arena;
|
||||
|
|
|
@ -162,6 +162,8 @@ class Arena {
|
|||
Result<PodObject*> gc_stack(PodStackFrame* obj);
|
||||
Result<PodObject*> gc_error(PodError* obj);
|
||||
Result<PodObject*> gc_continuation(PodContinuation* obj);
|
||||
Result<PodObject*> gc_task(PodTask* obj);
|
||||
Result<PodObject*> gc_task_result(PodTaskResult* obj);
|
||||
|
||||
void add_root(GcRootList* node) { _gcroot.insert(node); }
|
||||
|
||||
|
|
|
@ -48,6 +48,10 @@ Result<Value> Value::create(PodObject* obj) {
|
|||
return Value(TRY(Error::create((PodError*)obj)));
|
||||
case Tag::Continuation:
|
||||
return Value(TRY(Continuation::create((PodContinuation*)obj)));
|
||||
case Tag::Task:
|
||||
return Value(TRY(Task::create((PodTask*)obj)));
|
||||
case Tag::TaskResult:
|
||||
return Value(TRY(TaskResult::create((PodTaskResult*)obj)));
|
||||
};
|
||||
return Value();
|
||||
}
|
||||
|
@ -521,8 +525,8 @@ Result<Continuation> Continuation::copy() const {
|
|||
Result<Value> Continuation::value() const {
|
||||
return Value::create(_value->value.get());
|
||||
}
|
||||
Result<Value> Continuation::frame() const {
|
||||
return Value::create(_value->frame.get());
|
||||
Result<StackFrame> Continuation::frame() const {
|
||||
return StackFrame::create((PodStackFrame*)_value->frame.get());
|
||||
}
|
||||
|
||||
Result<short> Continuation::cmp(const Continuation& rhs) const {
|
||||
|
@ -537,6 +541,79 @@ Result<short> Continuation::cmp(const Continuation& rhs) const {
|
|||
return res;
|
||||
}
|
||||
|
||||
Result<Task> Task::create(uint64_t task_id, const Array& params) {
|
||||
auto pod = TRY(arena_alloc<PodTask>());
|
||||
pod->header.tag = Tag::Task;
|
||||
|
||||
pod->task_id = task_id;
|
||||
pod->params = params.pod();
|
||||
|
||||
return Task(TRY(MkGcRoot(pod)));
|
||||
}
|
||||
|
||||
Result<Value> Task::copy_value() const {
|
||||
return Value(Task(TRY(_value.copy())));
|
||||
}
|
||||
Result<Task> Task::copy() const { return Task(TRY(_value.copy())); }
|
||||
|
||||
Result<Symbol> Task::name() const {
|
||||
const char* task_name =
|
||||
TRY(get_stdlib_task_name(StdlibTaskId(_value->task_id)));
|
||||
return Symbol::create(task_name);
|
||||
}
|
||||
|
||||
uint64_t Task::task_id() const { return _value->task_id; }
|
||||
|
||||
Result<Array> Task::params() const {
|
||||
return Array::create((PodArray*)_value->params.get());
|
||||
}
|
||||
|
||||
Result<short> Task::cmp(const Task& rhs) const {
|
||||
short res = (task_id() > rhs.task_id()) - (task_id() < rhs.task_id());
|
||||
if (res != 0) return res;
|
||||
|
||||
auto lhs_params = TRY(params());
|
||||
auto rhs_params = TRY(rhs.params());
|
||||
res = TRY(lhs_params.cmp(rhs_params));
|
||||
return res;
|
||||
}
|
||||
|
||||
Result<TaskResult> TaskResult::create(const Value& result, const Value& error) {
|
||||
auto pod = TRY(arena_alloc<PodTaskResult>());
|
||||
pod->header.tag = Tag::TaskResult;
|
||||
|
||||
pod->result = result.pod();
|
||||
pod->error = error.pod();
|
||||
|
||||
return TaskResult(TRY(MkGcRoot(pod)));
|
||||
}
|
||||
|
||||
Result<Value> TaskResult::copy_value() const {
|
||||
return Value(TaskResult(TRY(_value.copy())));
|
||||
}
|
||||
Result<TaskResult> TaskResult::copy() const {
|
||||
return TaskResult(TRY(_value.copy()));
|
||||
}
|
||||
|
||||
Result<Value> TaskResult::result() const {
|
||||
return Value::create(_value->result.get());
|
||||
}
|
||||
Result<Value> TaskResult::error() const {
|
||||
return Value::create(_value->error.get());
|
||||
}
|
||||
|
||||
Result<short> TaskResult::cmp(const TaskResult& rhs) const {
|
||||
auto lhs_result = TRY(result());
|
||||
auto rhs_result = TRY(rhs.result());
|
||||
short res = TRY(lhs_result.cmp(rhs_result));
|
||||
if (res != 0) return res;
|
||||
|
||||
auto lhs_error = TRY(error());
|
||||
auto rhs_error = TRY(rhs.error());
|
||||
res = TRY(lhs_error.cmp(rhs_error));
|
||||
return res;
|
||||
}
|
||||
|
||||
Result<Pair> Pair::create(const Value& first, const Value& rest) {
|
||||
auto pod = TRY(arena_alloc<PodPair>());
|
||||
pod->header.tag = Tag::Pair;
|
||||
|
|
|
@ -38,6 +38,8 @@ class Function;
|
|||
class StdlibFunction;
|
||||
class Module;
|
||||
class Continuation;
|
||||
class Task;
|
||||
class TaskResult;
|
||||
|
||||
short cmp_tag(Tag lhs, Tag rhs);
|
||||
|
||||
|
@ -110,6 +112,12 @@ class Object {
|
|||
virtual Result<short> cmp(const Continuation& rhs) const {
|
||||
return cmp_tag(tag(), Tag::Continuation);
|
||||
}
|
||||
virtual Result<short> cmp(const Task& rhs) const {
|
||||
return cmp_tag(tag(), Tag::Task);
|
||||
}
|
||||
virtual Result<short> cmp(const TaskResult& rhs) const {
|
||||
return cmp_tag(tag(), Tag::TaskResult);
|
||||
}
|
||||
|
||||
virtual Result<Value> add(const Object&) const;
|
||||
virtual Result<Value> add(const Int64&) const;
|
||||
|
@ -1239,7 +1247,7 @@ class Continuation : public Object {
|
|||
const StackFrame& frame);
|
||||
|
||||
Result<Value> value() const;
|
||||
Result<Value> frame() const;
|
||||
Result<StackFrame> frame() const;
|
||||
|
||||
virtual Result<Value> copy_value() const final;
|
||||
Result<Continuation> copy() const;
|
||||
|
@ -1248,6 +1256,69 @@ class Continuation : public Object {
|
|||
GcRoot<PodContinuation> _value;
|
||||
};
|
||||
|
||||
class Task : public Object {
|
||||
public:
|
||||
Task() {}
|
||||
Task(Task&& rhs) : _value(std::move(rhs._value)) {}
|
||||
Task(GcRoot<PodTask>&& val) : _value(std::move(val)) {}
|
||||
|
||||
virtual Tag tag() const final { return Tag::Task; }
|
||||
virtual PodObject* pod() const final { return _value.get(); }
|
||||
virtual Result<short> cmp(const Object& rhs) const final {
|
||||
return -TRY(rhs.cmp(*this));
|
||||
}
|
||||
virtual Result<short> cmp(const Task& rhs) const final;
|
||||
|
||||
virtual void move(Object* obj) final { new (obj) Task(std::move(_value)); }
|
||||
|
||||
static Result<Task> create(PodTask* obj) { return Task(TRY(MkGcRoot(obj))); }
|
||||
|
||||
static Result<Task> create(uint64_t task_id, const Array& params);
|
||||
|
||||
Result<Symbol> name() const;
|
||||
uint64_t task_id() const;
|
||||
Result<Array> params() const;
|
||||
|
||||
virtual Result<Value> copy_value() const final;
|
||||
Result<Task> copy() const;
|
||||
|
||||
private:
|
||||
GcRoot<PodTask> _value;
|
||||
};
|
||||
|
||||
class TaskResult : public Object {
|
||||
public:
|
||||
TaskResult() {}
|
||||
TaskResult(TaskResult&& rhs) : _value(std::move(rhs._value)) {}
|
||||
TaskResult(GcRoot<PodTaskResult>&& val) : _value(std::move(val)) {}
|
||||
|
||||
virtual Tag tag() const final { return Tag::TaskResult; }
|
||||
virtual PodObject* pod() const final { return _value.get(); }
|
||||
virtual Result<short> cmp(const Object& rhs) const final {
|
||||
return -TRY(rhs.cmp(*this));
|
||||
}
|
||||
virtual Result<short> cmp(const TaskResult& rhs) const final;
|
||||
|
||||
virtual void move(Object* obj) final {
|
||||
new (obj) TaskResult(std::move(_value));
|
||||
}
|
||||
|
||||
static Result<TaskResult> create(PodTaskResult* obj) {
|
||||
return TaskResult(TRY(MkGcRoot(obj)));
|
||||
}
|
||||
|
||||
static Result<TaskResult> create(const Value& result, const Value& error);
|
||||
|
||||
Result<Value> result() const;
|
||||
Result<Value> error() const;
|
||||
|
||||
virtual Result<Value> copy_value() const final;
|
||||
Result<TaskResult> copy() const;
|
||||
|
||||
private:
|
||||
GcRoot<PodTaskResult> _value;
|
||||
};
|
||||
|
||||
// note: this class doesn't perform proper destruction of objects in some cases
|
||||
class Value {
|
||||
public:
|
||||
|
|
|
@ -240,6 +240,8 @@ Result<Expression> Compiler::compile_expr(Context& context, const Value& expr) {
|
|||
case Tag::StackFrame:
|
||||
case Tag::Error:
|
||||
case Tag::Continuation:
|
||||
case Tag::Task:
|
||||
case Tag::TaskResult:
|
||||
return ERROR(TypeMismatch);
|
||||
}
|
||||
return ERROR(TypeMismatch);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
enum class ErrorCode {
|
||||
Success,
|
||||
Unknown,
|
||||
OutOfMemory,
|
||||
IndexOutOfRange,
|
||||
TypeMismatch,
|
||||
|
|
18
src/pod.hpp
18
src/pod.hpp
|
@ -26,6 +26,8 @@ enum class Tag : uint8_t {
|
|||
StackFrame,
|
||||
Error,
|
||||
Continuation,
|
||||
Task,
|
||||
TaskResult,
|
||||
};
|
||||
|
||||
template <class T>
|
||||
|
@ -220,6 +222,22 @@ class PodContinuation final : public PodObject {
|
|||
OffPtr<PodObject> frame;
|
||||
};
|
||||
|
||||
class PodTask final : public PodObject {
|
||||
public:
|
||||
PodTask() : PodObject(Tag::Task) {};
|
||||
|
||||
uint64_t task_id;
|
||||
OffPtr<PodObject> params;
|
||||
};
|
||||
|
||||
class PodTaskResult final : public PodObject {
|
||||
public:
|
||||
PodTaskResult() : PodObject(Tag::TaskResult) {};
|
||||
|
||||
OffPtr<PodObject> result;
|
||||
OffPtr<PodObject> error;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class Ptr {
|
||||
public:
|
||||
|
|
|
@ -10,6 +10,7 @@ class Result {
|
|||
Result(const T& res) : _value(res), _error(ErrorCode::Success) {}
|
||||
Result(T&& res) : _value(std::move(res)), _error(ErrorCode::Success) {}
|
||||
Result(ErrorCode err) : _error(err) {}
|
||||
Result() : _error(ErrorCode::Unknown) {}
|
||||
|
||||
bool has_error() const { return _error != ErrorCode::Success; }
|
||||
bool has_value() const { return !has_error(); }
|
||||
|
|
101
src/stdlib.cpp
101
src/stdlib.cpp
|
@ -14,6 +14,14 @@ struct StdlibFunctionEntry {
|
|||
StdlibFunctionIdPtr fun_ptr;
|
||||
};
|
||||
|
||||
typedef Result<Value> (*StdlibTaskIdPtr)(const Array& params);
|
||||
|
||||
struct StdlibTaskEntry {
|
||||
const char* name;
|
||||
StdlibTaskId task_id;
|
||||
StdlibTaskIdPtr task_ptr;
|
||||
};
|
||||
|
||||
Result<StackFrame> stdlib_unknown(const StackFrame& stack) {
|
||||
return ERROR(NotImplemented);
|
||||
}
|
||||
|
@ -290,7 +298,9 @@ Result<StackFrame> stdlib_error(const StackFrame& stack) {
|
|||
auto val = Value(TRY(
|
||||
Error::create(*error_name.to<Symbol>(), *error_message.to<String>())));
|
||||
|
||||
return ERROR_OBJ(RuntimeError, val);
|
||||
auto cont = Value(TRY(Continuation::create(val, stack)));
|
||||
|
||||
return ERROR_OBJ(Raise, cont);
|
||||
}
|
||||
|
||||
Result<StackFrame> stdlib_raise(const StackFrame& stack) {
|
||||
|
@ -315,6 +325,27 @@ Result<StackFrame> stdlib_raise(const StackFrame& stack) {
|
|||
return ERROR_OBJ(Raise, cont);
|
||||
}
|
||||
|
||||
Result<StackFrame> stdlib_task(const StackFrame& stack) {
|
||||
auto params = TRY(stack.get(0));
|
||||
Array& params_array = *params.to<Array>();
|
||||
|
||||
auto size = TRY(params.size());
|
||||
if (size == 0) return ERROR(ArgumentCountMismatch);
|
||||
|
||||
Value task_id = TRY(params_array.get(0));
|
||||
if (!task_id.is<Int64>()) return ERROR(TypeMismatch);
|
||||
|
||||
Value task_params = TRY(params_array.slice(1, size));
|
||||
|
||||
auto val = Value(TRY(Task::create((uint64_t)task_id.to<Int64>()->value(), *task_params.to<Array>())));
|
||||
|
||||
auto res = TRY(stack.set(0, val));
|
||||
|
||||
res = TRY(res.ret(0));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#define STDLIB_FUNCTION(name, id) \
|
||||
[(uint64_t)StdlibFunctionId::id] = {#name, StdlibFunctionId::id, \
|
||||
stdlib_##name}
|
||||
|
@ -335,10 +366,30 @@ static StdlibFunctionEntry function_entries[] = {
|
|||
STDLIB_FUNCTION(map, Map),
|
||||
STDLIB_FUNCTION(error, Error),
|
||||
STDLIB_FUNCTION(raise, Raise),
|
||||
STDLIB_FUNCTION(task, Task),
|
||||
[(uint64_t)StdlibFunctionId::Max] = {0, StdlibFunctionId::Max,
|
||||
stdlib_unknown},
|
||||
};
|
||||
|
||||
Result<Value> stdlib_task_unknown(const Array& params) {
|
||||
return ERROR(NotImplemented);
|
||||
}
|
||||
|
||||
Result<Value> stdlib_task_print(const Array& params) {
|
||||
return ERROR(NotImplemented);
|
||||
}
|
||||
|
||||
#define STDLIB_TASK(name, id) \
|
||||
[(uint64_t)StdlibTaskId::id] = {#name, StdlibTaskId::id, \
|
||||
stdlib_task_##name}
|
||||
|
||||
static StdlibTaskEntry task_entries[] = {
|
||||
STDLIB_TASK(unknown, Unknown),
|
||||
STDLIB_TASK(print, Print),
|
||||
[(uint64_t)StdlibTaskId::Max] = {0, StdlibTaskId::Max,
|
||||
stdlib_task_unknown},
|
||||
};
|
||||
|
||||
// TODO: this just scans through the array of functions linearly every time.
|
||||
// It doesn't have much effect at runtime, because such lookup is likely to
|
||||
// happen on compile-time only. But anyway, this is worth speeding up
|
||||
|
@ -389,3 +440,51 @@ Result<const char*> get_stdlib_function_name(StdlibFunctionId fun_id) {
|
|||
|
||||
return function_entries[(uint64_t)fun_id].name;
|
||||
}
|
||||
|
||||
|
||||
StdlibTaskEntry get_task_entry(const char* name) {
|
||||
for (uint64_t i = 1; i < (uint64_t)StdlibTaskId::Max; i++) {
|
||||
if (strcmp(task_entries[i].name, name) == 0) {
|
||||
return task_entries[i];
|
||||
}
|
||||
}
|
||||
return task_entries[(uint64_t)StdlibTaskId::Unknown];
|
||||
}
|
||||
|
||||
Result<StdlibTaskId> get_stdlib_task(const Symbol& name) {
|
||||
const uint64_t bufsize = 256;
|
||||
char buf[bufsize];
|
||||
auto size = TRY(name.size());
|
||||
if (size + 1 > bufsize) {
|
||||
return ERROR(KeyError);
|
||||
}
|
||||
|
||||
for (uint64_t i = 0; i < size; i++) {
|
||||
buf[i] = (char)TRY(name[i]);
|
||||
}
|
||||
buf[size] = 0;
|
||||
|
||||
StdlibTaskId task_id = get_task_entry(buf).task_id;
|
||||
if (task_id == StdlibTaskId::Unknown) {
|
||||
return ERROR(KeyError);
|
||||
}
|
||||
|
||||
return task_id;
|
||||
}
|
||||
|
||||
Result<Value> call_stdlib_task(StdlibTaskId fun_id,
|
||||
const Array& params) {
|
||||
if (fun_id == StdlibTaskId(0) || fun_id >= StdlibTaskId::Max) {
|
||||
return ERROR(KeyError);
|
||||
}
|
||||
|
||||
return task_entries[(uint64_t)fun_id].task_ptr(params);
|
||||
}
|
||||
|
||||
Result<const char*> get_stdlib_task_name(StdlibTaskId fun_id) {
|
||||
if (fun_id == StdlibTaskId(0) || fun_id >= StdlibTaskId::Max) {
|
||||
return ERROR(KeyError);
|
||||
}
|
||||
|
||||
return task_entries[(uint64_t)fun_id].name;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,13 @@ enum class StdlibFunctionId : uint64_t {
|
|||
Map,
|
||||
Error,
|
||||
Raise,
|
||||
Task,
|
||||
Max,
|
||||
};
|
||||
|
||||
enum class StdlibTaskId : uint64_t {
|
||||
Unknown,
|
||||
Print,
|
||||
Max,
|
||||
};
|
||||
|
||||
|
@ -27,8 +34,13 @@ class Value;
|
|||
class Symbol;
|
||||
class Array;
|
||||
class StackFrame;
|
||||
class Continuation;
|
||||
|
||||
Result<const char*> get_stdlib_function_name(StdlibFunctionId fun_id);
|
||||
Result<StdlibFunctionId> get_stdlib_function(const Symbol& name);
|
||||
Result<StackFrame> call_stdlib_function(StdlibFunctionId fun_id,
|
||||
const StackFrame& stack);
|
||||
|
||||
Result<const char*> get_stdlib_task_name(StdlibTaskId task_id);
|
||||
Result<StdlibTaskId> get_stdlib_task(const Symbol& name);
|
||||
Result<Value> call_stdlib_task(StdlibTaskId task_id, const Array& params);
|
||||
|
|
37
src/vm.cpp
37
src/vm.cpp
|
@ -1,6 +1,7 @@
|
|||
#include "vm.hpp"
|
||||
|
||||
#include "common.hpp"
|
||||
#include "error.hpp"
|
||||
#include "stdlib.hpp"
|
||||
|
||||
Result<Value> VM::getreg(uint64_t idx) { return _stack.get(idx); }
|
||||
|
@ -279,6 +280,19 @@ Result<void> VM::step_bytecode() {
|
|||
return Result<void>();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
return ERROR(TypeMismatch);
|
||||
}
|
||||
|
||||
Result<void> VM::step_native() {
|
||||
auto fun = TRY(_stack.fun());
|
||||
if (!fun.is<StdlibFunction>()) return ERROR(TypeMismatch);
|
||||
|
@ -290,13 +304,32 @@ Result<void> VM::step_native() {
|
|||
|
||||
Result<void> VM::step() {
|
||||
auto fun = TRY(_stack.fun());
|
||||
Result<void> res;
|
||||
if (fun.is<Function>()) {
|
||||
return step_bytecode();
|
||||
res = std::move(step_bytecode());
|
||||
} else if (fun.is<StdlibFunction>()) {
|
||||
return step_native();
|
||||
res = std::move(step_native());
|
||||
} else {
|
||||
return ERROR(NotImplemented);
|
||||
}
|
||||
|
||||
if (res.has_error()) {
|
||||
auto obj = TRY(geterrobj().copy());
|
||||
if (obj.is<Nil>()) return res;
|
||||
|
||||
if (res.error() == ErrorCode::Raise) {
|
||||
if (obj.is<Continuation>()) {
|
||||
_stack = TRY(handle_raise(*obj.to<Continuation>()));
|
||||
return Result<void>();
|
||||
}
|
||||
}
|
||||
|
||||
auto cont = Value(TRY(Continuation::create(obj, _stack)));
|
||||
_stack = TRY(handle_raise(*obj.to<Continuation>()));
|
||||
return Result<void>();
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
Result<Value> VM::run() {
|
||||
|
|
|
@ -62,6 +62,8 @@ class VM {
|
|||
Result<void> vm_global_load(Opcode& oc);
|
||||
Result<void> vm_global_store(Opcode& oc);
|
||||
|
||||
Result<StackFrame> handle_raise(const Continuation& cont);
|
||||
|
||||
Result<Value> get(bool is_const, uint64_t idx);
|
||||
Result<Value> getconst(uint64_t idx);
|
||||
Result<Value> getreg(uint64_t idx);
|
||||
|
|
|
@ -45,6 +45,10 @@ Result<String> Writer::write_one(const Value& obj) {
|
|||
return write_error(*obj.to<Error>());
|
||||
case Tag::Continuation:
|
||||
return write_continuation(*obj.to<Continuation>());
|
||||
case Tag::Task:
|
||||
return write_task(*obj.to<Task>());
|
||||
case Tag::TaskResult:
|
||||
return write_task_result(*obj.to<TaskResult>());
|
||||
};
|
||||
return String();
|
||||
}
|
||||
|
@ -403,6 +407,39 @@ Result<String> Writer::write_continuation(const Continuation& val) {
|
|||
return TRY(String::create("#<continuation>"));
|
||||
}
|
||||
|
||||
Result<String> Writer::write_task(const Task& val) {
|
||||
auto name = TRY(val.name());
|
||||
String name_str = TRY(write_symbol(name));
|
||||
String params_str = TRY(write_one(TRY(val.params())));
|
||||
|
||||
String res = TRY(String::create("#<task "));
|
||||
res = TRY(res.concat(name_str));
|
||||
res = TRY(res.concat(" "));
|
||||
res = TRY(res.concat(params_str));
|
||||
res = TRY(res.concat(">"));
|
||||
return res;
|
||||
}
|
||||
|
||||
Result<String> Writer::write_task_result(const TaskResult& val) {
|
||||
auto error = TRY(val.error());
|
||||
auto result = TRY(val.result());
|
||||
|
||||
String res = TRY(String::create("#<task-result "));
|
||||
|
||||
if (error.is<Nil>()) {
|
||||
res = TRY(res.concat(" :result "));
|
||||
String s = TRY(write_one(result));
|
||||
res = TRY(res.concat(s));
|
||||
} else {
|
||||
res = TRY(res.concat(" :error "));
|
||||
String s = TRY(write_one(error));
|
||||
res = TRY(res.concat(s));
|
||||
}
|
||||
|
||||
res = TRY(res.concat(">"));
|
||||
return res;
|
||||
}
|
||||
|
||||
Result<String> write_one(const Value& value) {
|
||||
auto w = Writer();
|
||||
return w.write_one(value);
|
||||
|
|
|
@ -30,6 +30,8 @@ class Writer {
|
|||
Result<String> write_stack(const StackFrame& val);
|
||||
Result<String> write_error(const Error& val);
|
||||
Result<String> write_continuation(const Continuation& val);
|
||||
Result<String> write_task(const Task& val);
|
||||
Result<String> write_task_result(const TaskResult& val);
|
||||
};
|
||||
|
||||
Result<String> write_one(const Value& value);
|
||||
|
|
Loading…
Reference in a new issue