diff --git a/src/arena.cpp b/src/arena.cpp index 3b4fd81..49ab0ca 100644 --- a/src/arena.cpp +++ b/src/arena.cpp @@ -2,6 +2,7 @@ #include "die.hpp" #include "error.hpp" +#include "pod.hpp" static Arena* current_arena = 0; @@ -95,6 +96,8 @@ Result Arena::gc_pod(PodObject* obj) { return gc_stack((PodStackFrame*)obj); case Tag::Error: return gc_error((PodError*)obj); + case Tag::Continuation: + return gc_continuation((PodContinuation*)obj); } return ERROR(TypeMismatch); @@ -277,6 +280,16 @@ Result Arena::gc_error(PodError* obj) { return nobj; } +Result Arena::gc_continuation(PodContinuation* obj) { + auto nobj = TRY(alloc()); + nobj->header.tag = Tag::Error; + + nobj->props = TRY(gc_pod(obj->props.get())); + nobj->frame = TRY(gc_pod(obj->frame.get())); + + return nobj; +} + Arena& get_arena() { if (current_arena == 0) die("Arena not set\n"); return *current_arena; diff --git a/src/arena.hpp b/src/arena.hpp index 40e67d6..1a303fd 100644 --- a/src/arena.hpp +++ b/src/arena.hpp @@ -161,6 +161,7 @@ class Arena { Result gc_module(PodModule* obj); Result gc_stack(PodStackFrame* obj); Result gc_error(PodError* obj); + Result gc_continuation(PodContinuation* obj); void add_root(GcRootList* node) { _gcroot.insert(node); } diff --git a/src/common.cpp b/src/common.cpp index 8e90cb6..e91190b 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -46,6 +46,8 @@ Result Value::create(PodObject* obj) { return Value(TRY(StackFrame::create((PodStackFrame*)obj))); case Tag::Error: return Value(TRY(Error::create((PodError*)obj))); + case Tag::Continuation: + return Value(TRY(Continuation::create((PodContinuation*)obj))); }; return Value(); } @@ -498,6 +500,32 @@ Result Error::cmp(const Error& rhs) const { return res; } +Result Continuation::copy_value() const { + return Value(Continuation(TRY(_value.copy()))); +} +Result Continuation::copy() const { + return Continuation(TRY(_value.copy())); +} + +Result Continuation::props() const { + return Value::create(_value->props.get()); +} +Result Continuation::frame() const { + return Value::create(_value->frame.get()); +} + +Result Continuation::cmp(const Continuation& rhs) const { + auto lhs_props = TRY(props()); + auto rhs_props = TRY(rhs.props()); + short res = TRY(lhs_props.cmp(rhs_props)); + if (res != 0) return res; + + auto lhs_frame = TRY(frame()); + auto rhs_frame = TRY(rhs.frame()); + res = TRY(lhs_frame.cmp(rhs_frame)); + return res; +} + Result Pair::create(const Value& first, const Value& rest) { auto pod = TRY(arena_alloc()); pod->header.tag = Tag::Pair; diff --git a/src/common.hpp b/src/common.hpp index 0fc5d17..ea3c594 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -37,6 +37,7 @@ class Error; class Function; class StdlibFunction; class Module; +class Continuation; short cmp_tag(Tag lhs, Tag rhs); @@ -106,6 +107,9 @@ class Object { virtual Result cmp(const Error& rhs) const { return cmp_tag(tag(), Tag::Error); } + virtual Result cmp(const Continuation& rhs) const { + return cmp_tag(tag(), Tag::Continuation); + } virtual Result add(const Object&) const; virtual Result add(const Int64&) const; @@ -1210,6 +1214,48 @@ class Error : public Object { GcRoot _value; }; +class Continuation : public Object { + public: + Continuation() {} + Continuation(Continuation&& rhs) : _value(std::move(rhs._value)) {} + Continuation(GcRoot&& val) : _value(std::move(val)) {} + + virtual Tag tag() const final { return Tag::Continuation; } + virtual PodObject* pod() const final { return _value.get(); } + virtual Result cmp(const Object& rhs) const final { + return -TRY(rhs.cmp(*this)); + } + virtual Result cmp(const Continuation& rhs) const final; + + virtual void move(Object* obj) final { + new (obj) Continuation(std::move(_value)); + } + + static Result create(PodContinuation* obj) { + return Continuation(TRY(MkGcRoot(obj))); + } + + static Result create(const Dict& props, + const StackFrame& frame) { + auto pod = TRY(arena_alloc()); + pod->header.tag = Tag::Continuation; + + pod->props = props.pod(); + pod->frame = frame.pod(); + + return Continuation(TRY(MkGcRoot(pod))); + } + + Result props() const; + Result frame() const; + + virtual Result copy_value() const final; + Result copy() const; + + private: + GcRoot _value; +}; + // note: this class doesn't perform proper destruction of objects in some cases class Value { public: diff --git a/src/compiler.cpp b/src/compiler.cpp index e94a065..ecc1c04 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -239,6 +239,7 @@ Result Compiler::compile_expr(Context& context, const Value& expr) { case Tag::Module: case Tag::StackFrame: case Tag::Error: + case Tag::Continuation: return ERROR(TypeMismatch); } return ERROR(TypeMismatch); diff --git a/src/pod.hpp b/src/pod.hpp index 6456489..3e8d531 100644 --- a/src/pod.hpp +++ b/src/pod.hpp @@ -25,6 +25,7 @@ enum class Tag : uint8_t { Module, StackFrame, Error, + Continuation, }; template @@ -211,6 +212,14 @@ class PodError final : public PodObject { OffPtr message; }; +class PodContinuation final : public PodObject { +public: + PodContinuation() : PodObject(Tag::Continuation) {}; + + OffPtr props; + OffPtr frame; +}; + template class Ptr { public: diff --git a/src/writer.cpp b/src/writer.cpp index 713a468..5a3a5bf 100644 --- a/src/writer.cpp +++ b/src/writer.cpp @@ -43,6 +43,8 @@ Result Writer::write_one(const Value& obj) { return write_stack(*obj.to()); case Tag::Error: return write_error(*obj.to()); + case Tag::Continuation: + return write_continuation(*obj.to()); }; return String(); } @@ -397,6 +399,10 @@ Result Writer::write_error(const Error& val) { return res; } +Result Writer::write_continuation(const Continuation& val) { + return TRY(String::create("#")); +} + Result write_one(const Value& value) { auto w = Writer(); return w.write_one(value); diff --git a/src/writer.hpp b/src/writer.hpp index 2f3df43..e5d44b7 100644 --- a/src/writer.hpp +++ b/src/writer.hpp @@ -29,6 +29,7 @@ class Writer { Result write_module(const Module& val); Result write_stack(const StackFrame& val); Result write_error(const Error& val); + Result write_continuation(const Continuation& val); }; Result write_one(const Value& value);