Add an error class to represent runtime errors
This commit is contained in:
parent
fa4b912b88
commit
02dce3e11c
8 changed files with 100 additions and 0 deletions
|
@ -91,6 +91,8 @@ Result<PodObject*> Arena::gc_pod(PodObject* obj) {
|
||||||
return gc_module((PodModule*)obj);
|
return gc_module((PodModule*)obj);
|
||||||
case Tag::Stack:
|
case Tag::Stack:
|
||||||
return gc_stack((PodStack*)obj);
|
return gc_stack((PodStack*)obj);
|
||||||
|
case Tag::Error:
|
||||||
|
return gc_error((PodError*)obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ERROR(TypeMismatch);
|
return ERROR(TypeMismatch);
|
||||||
|
@ -264,6 +266,16 @@ Result<PodObject*> Arena::gc_stack(PodStack* obj) {
|
||||||
return nobj;
|
return nobj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result<PodObject*> Arena::gc_error(PodError* obj) {
|
||||||
|
auto nobj = TRY(alloc<PodError>());
|
||||||
|
nobj->header.tag = Tag::Error;
|
||||||
|
|
||||||
|
nobj->name = TRY(gc_pod(obj->name.get()));
|
||||||
|
nobj->message = TRY(gc_pod(obj->message.get()));
|
||||||
|
|
||||||
|
return nobj;
|
||||||
|
}
|
||||||
|
|
||||||
Arena& get_arena() {
|
Arena& get_arena() {
|
||||||
if (current_arena == 0) die("Arena not set\n");
|
if (current_arena == 0) die("Arena not set\n");
|
||||||
return *current_arena;
|
return *current_arena;
|
||||||
|
|
|
@ -160,6 +160,7 @@ class Arena {
|
||||||
Result<PodObject*> gc_stdlib_function(PodStdlibFunction* obj);
|
Result<PodObject*> gc_stdlib_function(PodStdlibFunction* obj);
|
||||||
Result<PodObject*> gc_module(PodModule* obj);
|
Result<PodObject*> gc_module(PodModule* obj);
|
||||||
Result<PodObject*> gc_stack(PodStack* obj);
|
Result<PodObject*> gc_stack(PodStack* obj);
|
||||||
|
Result<PodObject*> gc_error(PodError* obj);
|
||||||
|
|
||||||
void add_root(GcRootList* node) { _gcroot.insert(node); }
|
void add_root(GcRootList* node) { _gcroot.insert(node); }
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,8 @@ Result<Value> Value::create(PodObject* obj) {
|
||||||
return Value(TRY(Module::create((PodModule*)obj)));
|
return Value(TRY(Module::create((PodModule*)obj)));
|
||||||
case Tag::Stack:
|
case Tag::Stack:
|
||||||
return Value(TRY(Stack::create((PodStack*)obj)));
|
return Value(TRY(Stack::create((PodStack*)obj)));
|
||||||
|
case Tag::Error:
|
||||||
|
return Value(TRY(Error::create((PodError*)obj)));
|
||||||
};
|
};
|
||||||
return Value();
|
return Value();
|
||||||
}
|
}
|
||||||
|
@ -314,6 +316,28 @@ Result<void> Stack::settop(uint64_t idx) {
|
||||||
return Result<void>();
|
return Result<void>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result<Value> Error::copy_value() const {
|
||||||
|
return Value(Error(TRY(_value.copy())));
|
||||||
|
}
|
||||||
|
Result<Error> Error::copy() const { return Error(TRY(_value.copy())); }
|
||||||
|
|
||||||
|
Result<Value> Error::name() const { return Value::create(_value->name.get()); }
|
||||||
|
Result<Value> Error::message() const {
|
||||||
|
return Value::create(_value->message.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<short> Error::cmp(const Error& rhs) const {
|
||||||
|
auto lhs_name = TRY(name());
|
||||||
|
auto rhs_name = TRY(rhs.name());
|
||||||
|
short res = TRY(lhs_name.cmp(rhs_name));
|
||||||
|
if (res != 0) return res;
|
||||||
|
|
||||||
|
auto lhs_message = TRY(message());
|
||||||
|
auto rhs_message = TRY(rhs.message());
|
||||||
|
res = TRY(lhs_message.cmp(rhs_message));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
Result<Pair> Pair::create(const Value& first, const Value& rest) {
|
Result<Pair> Pair::create(const Value& first, const Value& rest) {
|
||||||
auto pod = TRY(arena_alloc<PodPair>());
|
auto pod = TRY(arena_alloc<PodPair>());
|
||||||
pod->header.tag = Tag::Pair;
|
pod->header.tag = Tag::Pair;
|
||||||
|
|
|
@ -33,6 +33,7 @@ class ByteArray;
|
||||||
class Writer;
|
class Writer;
|
||||||
class Opcode;
|
class Opcode;
|
||||||
class Stack;
|
class Stack;
|
||||||
|
class Error;
|
||||||
class Function;
|
class Function;
|
||||||
class StdlibFunction;
|
class StdlibFunction;
|
||||||
class Module;
|
class Module;
|
||||||
|
@ -102,6 +103,9 @@ class Object {
|
||||||
virtual Result<short> cmp(const Stack& rhs) const {
|
virtual Result<short> cmp(const Stack& rhs) const {
|
||||||
return ERROR(NotImplemented);
|
return ERROR(NotImplemented);
|
||||||
}
|
}
|
||||||
|
virtual Result<short> cmp(const Error& rhs) const {
|
||||||
|
return cmp_tag(tag(), Tag::Error);
|
||||||
|
}
|
||||||
|
|
||||||
virtual Result<Value> add(const Object&) const;
|
virtual Result<Value> add(const Object&) const;
|
||||||
virtual Result<Value> add(const Int64&) const;
|
virtual Result<Value> add(const Int64&) const;
|
||||||
|
@ -1130,6 +1134,48 @@ class Stack : public Object {
|
||||||
GcRoot<PodStack> _value;
|
GcRoot<PodStack> _value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Error : public Object {
|
||||||
|
public:
|
||||||
|
Error() {}
|
||||||
|
Error(Error&& rhs) : _value(std::move(rhs._value)) {}
|
||||||
|
Error(GcRoot<PodError>&& val) : _value(std::move(val)) {}
|
||||||
|
|
||||||
|
virtual Tag tag() const final { return Tag::Error; }
|
||||||
|
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 Error& rhs) const final;
|
||||||
|
|
||||||
|
virtual void move(Object* obj) final { new (obj) Error(std::move(_value)); }
|
||||||
|
|
||||||
|
static Result<Error> create(PodError* obj) {
|
||||||
|
return Error(TRY(MkGcRoot(obj)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result<Error> create(const char* name, const char* message) {
|
||||||
|
auto name_str = TRY(Symbol::create(name));
|
||||||
|
auto message_str = TRY(String::create(message));
|
||||||
|
|
||||||
|
auto pod = TRY(arena_alloc<PodError>());
|
||||||
|
pod->header.tag = Tag::Error;
|
||||||
|
|
||||||
|
pod->name = name_str.pod();
|
||||||
|
pod->message = message_str.pod();
|
||||||
|
|
||||||
|
return Error(TRY(MkGcRoot(pod)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<Value> name() const;
|
||||||
|
Result<Value> message() const;
|
||||||
|
|
||||||
|
virtual Result<Value> copy_value() const final;
|
||||||
|
Result<Error> copy() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
GcRoot<PodError> _value;
|
||||||
|
};
|
||||||
|
|
||||||
// note: this class doesn't perform proper destruction of objects in some cases
|
// note: this class doesn't perform proper destruction of objects in some cases
|
||||||
class Value {
|
class Value {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -238,6 +238,7 @@ Result<Expression> Compiler::compile_expr(Context& context, const Value& expr) {
|
||||||
case Tag::StdlibFunction:
|
case Tag::StdlibFunction:
|
||||||
case Tag::Module:
|
case Tag::Module:
|
||||||
case Tag::Stack:
|
case Tag::Stack:
|
||||||
|
case Tag::Error:
|
||||||
return ERROR(TypeMismatch);
|
return ERROR(TypeMismatch);
|
||||||
}
|
}
|
||||||
return ERROR(TypeMismatch);
|
return ERROR(TypeMismatch);
|
||||||
|
|
|
@ -24,6 +24,7 @@ enum class Tag : uint8_t {
|
||||||
StdlibFunction,
|
StdlibFunction,
|
||||||
Module,
|
Module,
|
||||||
Stack,
|
Stack,
|
||||||
|
Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
|
@ -200,6 +201,14 @@ class PodStack final : public PodObject {
|
||||||
OffPtr<PodObject> data[];
|
OffPtr<PodObject> data[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PodError final : public PodObject {
|
||||||
|
public:
|
||||||
|
PodError() : PodObject(Tag::Error) {};
|
||||||
|
|
||||||
|
OffPtr<PodObject> name;
|
||||||
|
OffPtr<PodObject> message;
|
||||||
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
class Ptr {
|
class Ptr {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -41,6 +41,8 @@ Result<String> Writer::write_one(const Value& obj) {
|
||||||
return write_module(*obj.to<Module>());
|
return write_module(*obj.to<Module>());
|
||||||
case Tag::Stack:
|
case Tag::Stack:
|
||||||
return write_stack(*obj.to<Stack>());
|
return write_stack(*obj.to<Stack>());
|
||||||
|
case Tag::Error:
|
||||||
|
return write_error(*obj.to<Error>());
|
||||||
};
|
};
|
||||||
return String();
|
return String();
|
||||||
}
|
}
|
||||||
|
@ -376,6 +378,10 @@ Result<String> Writer::write_stack(const Stack& val) {
|
||||||
return TRY(String::create("#<stack>"));
|
return TRY(String::create("#<stack>"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result<String> Writer::write_error(const Error& val) {
|
||||||
|
return TRY(String::create("#<error>"));
|
||||||
|
}
|
||||||
|
|
||||||
Result<String> write_one(const Value& value) {
|
Result<String> write_one(const Value& value) {
|
||||||
auto w = Writer();
|
auto w = Writer();
|
||||||
return w.write_one(value);
|
return w.write_one(value);
|
||||||
|
|
|
@ -28,6 +28,7 @@ class Writer {
|
||||||
Result<String> write_stdlib_function(const StdlibFunction& val);
|
Result<String> write_stdlib_function(const StdlibFunction& val);
|
||||||
Result<String> write_module(const Module& val);
|
Result<String> write_module(const Module& val);
|
||||||
Result<String> write_stack(const Stack& val);
|
Result<String> write_stack(const Stack& val);
|
||||||
|
Result<String> write_error(const Error& val);
|
||||||
};
|
};
|
||||||
|
|
||||||
Result<String> write_one(const Value& value);
|
Result<String> write_one(const Value& value);
|
||||||
|
|
Loading…
Reference in a new issue