summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/class.c56
-rw-r--r--src/vm.c7
2 files changed, 54 insertions, 9 deletions
diff --git a/src/class.c b/src/class.c
index 8c790507e..e4fda18fc 100644
--- a/src/class.c
+++ b/src/class.c
@@ -15,6 +15,7 @@
#include <mruby/error.h>
#include <mruby/data.h>
#include <mruby/istruct.h>
+#include <mruby/opcode.h>
KHASH_DEFINE(mt, mrb_sym, mrb_method_t, TRUE, kh_int_hash_func, kh_int_hash_equal)
@@ -1813,24 +1814,28 @@ mrb_mod_alias(mrb_state *mrb, mrb_value mod)
return mod;
}
+static void
+undef_method(mrb_state *mrb, struct RClass *c, mrb_sym a)
+{
+ mrb_method_t m;
+
+ MRB_METHOD_FROM_PROC(m, NULL);
+ mrb_define_method_raw(mrb, c, a, m);
+}
+
void
mrb_undef_method_id(mrb_state *mrb, struct RClass *c, mrb_sym a)
{
if (!mrb_obj_respond_to(mrb, c, a)) {
mrb_name_error(mrb, a, "undefined method '%n' for class '%C'", a, c);
}
- else {
- mrb_method_t m;
-
- MRB_METHOD_FROM_PROC(m, NULL);
- mrb_define_method_raw(mrb, c, a, m);
- }
+ undef_method(mrb, c, a);
}
MRB_API void
mrb_undef_method(mrb_state *mrb, struct RClass *c, const char *name)
{
- mrb_undef_method_id(mrb, c, mrb_intern_cstr(mrb, name));
+ undef_method(mrb, c, mrb_intern_cstr(mrb, name));
}
MRB_API void
@@ -2112,6 +2117,40 @@ inspect_main(mrb_state *mrb, mrb_value mod)
return mrb_str_new_lit(mrb, "main");
}
+static mrb_code new_iseq[] = {
+ OP_ENTER, 0x0, 0x10, 0x1, /* OP_ENTER 0:0:1:0:0:0:1 */
+ OP_LOADSELF, 0x3, /* OP_LOADSELF R3 */
+ OP_SEND, 0x3, 0x0, 0x0, /* OP_SEND R3 :allocate 0 */
+ OP_MOVE, 0x0, 0x3, /* OP_MOVE R0 R3 */
+ OP_MOVE, 0x4, 0x1, /* OP_MOVE R4 R1 */
+ OP_MOVE, 0x5, 0x2, /* OP_MOVE R5 R2 */
+ OP_SENDVB, 0x3, 0x1, /* OP_SENDVB R4 :initialize */
+ OP_RETURN, 0x0 /* OP_RETURN R0 */
+};
+
+static void
+init_class_new(mrb_state *mrb, struct RClass *cls)
+{
+ struct RProc *p;
+ mrb_method_t m;
+ mrb_irep *new_irep = (mrb_irep*)mrb_malloc(mrb, sizeof(mrb_irep));
+ static const mrb_irep mrb_irep_zero = { 0 };
+
+ *new_irep = mrb_irep_zero;
+ new_irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*2);
+ new_irep->syms[0] = mrb_intern_lit(mrb, "allocate");
+ new_irep->syms[1] = mrb_intern_lit(mrb, "initialize");
+ new_irep->slen = 2;
+ new_irep->flags = MRB_ISEQ_NO_FREE;
+ new_irep->iseq = new_iseq;
+ new_irep->ilen = sizeof(new_iseq);
+ new_irep->nregs = 6;
+ new_irep->nlocals = 3;
+ p = mrb_proc_new(mrb, new_irep);
+ MRB_METHOD_FROM_PROC(m, p);
+ mrb_define_method_raw(mrb, cls, mrb_intern_lit(mrb, "new"), m);
+}
+
void
mrb_init_class(mrb_state *mrb)
{
@@ -2161,10 +2200,11 @@ mrb_init_class(mrb_state *mrb)
mrb_define_class_method(mrb, cls, "new", mrb_class_new_class, MRB_ARGS_OPT(1));
mrb_define_method(mrb, cls, "allocate", mrb_instance_alloc, MRB_ARGS_NONE());
mrb_define_method(mrb, cls, "superclass", mrb_class_superclass, MRB_ARGS_NONE()); /* 15.2.3.3.4 */
- mrb_define_method(mrb, cls, "new", mrb_instance_new, MRB_ARGS_ANY()); /* 15.2.3.3.3 */
mrb_define_method(mrb, cls, "initialize", mrb_class_initialize, MRB_ARGS_OPT(1)); /* 15.2.3.3.1 */
mrb_define_method(mrb, cls, "inherited", mrb_bob_init, MRB_ARGS_REQ(1));
+ init_class_new(mrb, cls);
+
MRB_SET_INSTANCE_TT(mod, MRB_TT_MODULE);
mrb_define_method(mrb, mod, "extend_object", mrb_mod_extend_object, MRB_ARGS_REQ(1)); /* 15.2.2.4.25 */
mrb_define_method(mrb, mod, "extended", mrb_bob_init, MRB_ARGS_REQ(1)); /* 15.2.2.4.26 */
diff --git a/src/vm.c b/src/vm.c
index 12805a8e4..458b9249e 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -2441,7 +2441,12 @@ RETRY_TRY_BLOCK:
CASE(OP_ARYCAT, B) {
mrb_value splat = mrb_ary_splat(mrb, regs[a+1]);
- mrb_ary_concat(mrb, regs[a], splat);
+ if (mrb_nil_p(regs[a])) {
+ regs[a] = splat;
+ }
+ else {
+ mrb_ary_concat(mrb, regs[a], splat);
+ }
mrb_gc_arena_restore(mrb, ai);
NEXT;
}