Add basic runtime function operations.
This commit is contained in:
@@ -5,36 +5,93 @@
|
||||
|
||||
namespace bed::internal::scripting {
|
||||
struct Block {
|
||||
mrb_value proc;
|
||||
mrb_state *mrb;
|
||||
mrb_state *mrb = nullptr;
|
||||
mrb_value proc = mrb_nil_value();
|
||||
|
||||
Block(mrb_state *mrb, mrb_value proc)
|
||||
: proc(proc), mrb(mrb) {
|
||||
Block(mrb_state *mrb, mrb_value proc) noexcept
|
||||
: mrb(mrb), proc(proc) {
|
||||
mrb_gc_register(mrb, proc);
|
||||
}
|
||||
|
||||
Block() : proc(mrb_nil_value()) {}
|
||||
Block() noexcept = default;
|
||||
|
||||
~Block() {
|
||||
if (!mrb_nil_p(proc))
|
||||
~Block() noexcept {
|
||||
if (!mrb_nil_p(proc) && mrb)
|
||||
mrb_gc_unregister(mrb, proc);
|
||||
}
|
||||
|
||||
void set_proc(mrb_value new_proc) {
|
||||
if (!mrb_nil_p(proc))
|
||||
Block(const Block &other) noexcept
|
||||
: mrb(other.mrb), proc(other.proc) {
|
||||
if (mrb && !mrb_nil_p(proc))
|
||||
mrb_gc_register(mrb, proc);
|
||||
}
|
||||
|
||||
Block &operator=(const Block &other) noexcept {
|
||||
if (this != &other) {
|
||||
if (mrb && !mrb_nil_p(proc))
|
||||
mrb_gc_unregister(mrb, proc);
|
||||
mrb = other.mrb;
|
||||
proc = other.proc;
|
||||
if (mrb && !mrb_nil_p(proc))
|
||||
mrb_gc_register(mrb, proc);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Block(Block &&other) noexcept
|
||||
: mrb(other.mrb), proc(other.proc) {
|
||||
other.mrb = nullptr;
|
||||
other.proc = mrb_nil_value();
|
||||
}
|
||||
|
||||
Block &operator=(Block &&other) noexcept {
|
||||
if (this != &other) {
|
||||
if (mrb && !mrb_nil_p(proc))
|
||||
mrb_gc_unregister(mrb, proc);
|
||||
mrb = other.mrb;
|
||||
proc = other.proc;
|
||||
other.mrb = nullptr;
|
||||
other.proc = mrb_nil_value();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void set_proc(mrb_state *mrb_, mrb_value new_proc) {
|
||||
if (!mrb_nil_p(proc) && mrb)
|
||||
mrb_gc_unregister(mrb, proc);
|
||||
mrb = mrb_;
|
||||
proc = new_proc;
|
||||
mrb_gc_register(mrb, proc);
|
||||
}
|
||||
|
||||
Block(const Block &) = delete;
|
||||
Block &operator=(const Block &) = delete;
|
||||
|
||||
mrb_value call(int argc = 0, mrb_value *argv = nullptr) const {
|
||||
if (mrb_nil_p(proc))
|
||||
return mrb_nil_value();
|
||||
mrb_value result = mrb_funcall_argv(mrb, proc, mrb_intern_cstr(mrb, "call"), argc, argv);
|
||||
return result;
|
||||
if (!mrb->exc)
|
||||
return result;
|
||||
mrb_value exc = mrb_obj_value(mrb->exc);
|
||||
mrb_value msg = mrb_funcall(mrb, exc, "message", 0);
|
||||
std::string error;
|
||||
if (mrb_string_p(msg))
|
||||
error.assign(RSTRING_PTR(msg), RSTRING_LEN(msg));
|
||||
auto *fatal_class = mrb_class_get(mrb, "FatalError");
|
||||
if (mrb_obj_is_kind_of(mrb, exc, fatal_class)) {
|
||||
mrb_value code =
|
||||
mrb_iv_get(mrb, exc, mrb_intern_lit(mrb, "@code"));
|
||||
mrb->exc = nullptr;
|
||||
int c = 1;
|
||||
if (mrb_fixnum_p(code))
|
||||
c = mrb_fixnum(code);
|
||||
throw fatal_error(error, c);
|
||||
}
|
||||
auto *ed_class = mrb_class_get(mrb, "EdError");
|
||||
if (mrb_obj_is_kind_of(mrb, exc, ed_class)) {
|
||||
mrb->exc = nullptr;
|
||||
throw ed_error(error);
|
||||
}
|
||||
mrb->exc = nullptr;
|
||||
throw ed_error("Ruby Exception: " + error);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user