diff options
| -rw-r--r-- | include/mruby.h | 2 | ||||
| -rw-r--r-- | src/array.c | 3 | ||||
| -rw-r--r-- | src/class.c | 6 | ||||
| -rw-r--r-- | src/kernel.c | 8 | ||||
| -rw-r--r-- | src/numeric.c | 4 | ||||
| -rw-r--r-- | src/object.c | 6 | ||||
| -rw-r--r-- | src/re.c | 2 | ||||
| -rw-r--r-- | src/variable.c | 11 | ||||
| -rw-r--r-- | src/vm.c | 17 | ||||
| -rw-r--r-- | test/t/array.rb | 10 |
10 files changed, 53 insertions, 16 deletions
diff --git a/include/mruby.h b/include/mruby.h index 7abf66cb9..6fcda4d35 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -296,6 +296,7 @@ void mrb_define_singleton_method(mrb_state*, struct RObject*, const char*, mrb_f void mrb_define_module_function(mrb_state*, struct RClass*, const char*, mrb_func_t,int); void mrb_define_const(mrb_state*, struct RClass*, const char *name, mrb_value); void mrb_undef_method(mrb_state*, struct RClass*, const char*); +void mrb_undef_class_method(mrb_state*, struct RClass*, const char*); mrb_value mrb_instance_new(mrb_state *mrb, mrb_value cv); struct RClass * mrb_class_new(mrb_state *mrb, struct RClass *super); struct RClass * mrb_module_new(mrb_state *mrb); @@ -464,7 +465,6 @@ NUM2CHR(mrb_value x) mrb_value mrb_yield(mrb_state *mrb, mrb_value v, mrb_value blk); mrb_value mrb_yield_argv(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv); -mrb_value mrb_yield_with_self(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv, mrb_value self); mrb_value mrb_class_new_instance(mrb_state *mrb, int, mrb_value*, struct RClass *); mrb_value mrb_class_new_instance_m(mrb_state *mrb, mrb_value klass); diff --git a/src/array.c b/src/array.c index ed1c3f475..0f52c38ef 100644 --- a/src/array.c +++ b/src/array.c @@ -789,6 +789,9 @@ mrb_ary_last(mrb_state *mrb, mrb_value self) /* len == 1 */ size = mrb_fixnum(*vals); + if (size < 0) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "negative array size"); + } if (size > a->len) size = a->len; if ((a->flags & MRB_ARY_SHARED) || size > ARY_DEFAULT_LEN) { return ary_subseq(mrb, a, a->len - size, size); diff --git a/src/class.c b/src/class.c index b8532cdcc..f0393c7ec 100644 --- a/src/class.c +++ b/src/class.c @@ -1307,6 +1307,12 @@ mrb_undef_method(mrb_state *mrb, struct RClass *c, const char *name) undef_method(mrb, c, mrb_intern(mrb, name)); } +void +mrb_undef_class_method(mrb_state *mrb, struct RClass *c, const char *name) +{ + mrb_undef_method(mrb, mrb_class_ptr(mrb_singleton_class(mrb, mrb_obj_value(c))), name); +} + mrb_value mrb_mod_undef(mrb_state *mrb, mrb_value mod) { diff --git a/src/kernel.c b/src/kernel.c index f5a1f3d53..468891b23 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -555,6 +555,8 @@ mrb_obj_init_copy(mrb_state *mrb, mrb_value self) return self; } +mrb_value mrb_yield_internal(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv, mrb_value self, struct RClass *c); + /* 15.3.1.3.18 */ /* * call-seq: @@ -580,11 +582,13 @@ mrb_value mrb_obj_instance_eval(mrb_state *mrb, mrb_value self) { mrb_value a, b; + mrb_value cv; if (mrb_get_args(mrb, "|S&", &a, &b) == 1) { - mrb_raise(mrb, E_RUNTIME_ERROR, "instance_eval with string not implemented"); + mrb_raise(mrb, E_NOTIMP_ERROR, "instance_eval with string not implemented"); } - return mrb_yield_with_self(mrb, b, 0, 0, self); + cv = mrb_singleton_class(mrb, self); + return mrb_yield_internal(mrb, b, 0, 0, self, mrb_class_ptr(cv)); } int diff --git a/src/numeric.c b/src/numeric.c index ec3f97ca6..d294597ee 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -1288,7 +1288,7 @@ mrb_init_numeric(mrb_state *mrb) integer = mrb_define_class(mrb, "Integer", numeric); fixnum = mrb->fixnum_class = mrb_define_class(mrb, "Fixnum", integer); - mrb_undef_method(mrb, fixnum, "new"); + mrb_undef_class_method(mrb, fixnum, "new"); mrb_define_method(mrb, fixnum, "+", fix_plus, ARGS_REQ(1)); /* 15.2.8.3.1 */ mrb_define_method(mrb, fixnum, "-", fix_minus, ARGS_REQ(1)); /* 15.2.8.3.2 */ mrb_define_method(mrb, fixnum, "-@", fix_uminus, ARGS_REQ(1)); /* 15.2.7.4.2 */ @@ -1316,7 +1316,7 @@ mrb_init_numeric(mrb_state *mrb) /* Float Class */ fl = mrb->float_class = mrb_define_class(mrb, "Float", numeric); - mrb_undef_method(mrb, fl, "new"); + mrb_undef_class_method(mrb, fl, "new"); mrb_define_method(mrb, fl, "+", flo_plus, ARGS_REQ(1)); /* 15.2.9.3.1 */ mrb_define_method(mrb, fl, "-", flo_minus, ARGS_REQ(1)); /* 15.2.9.3.2 */ mrb_define_method(mrb, fl, "*", flo_mul, ARGS_REQ(1)); /* 15.2.9.3.3 */ diff --git a/src/object.c b/src/object.c index 29684b118..43e064fb0 100644 --- a/src/object.c +++ b/src/object.c @@ -275,7 +275,7 @@ mrb_init_object(mrb_state *mrb) struct RClass *f; n = mrb->nil_class = mrb_define_class(mrb, "NilClass", mrb->object_class); - mrb_undef_method(mrb, n, "new"); + mrb_undef_class_method(mrb, n, "new"); mrb_define_method(mrb, n, "&", false_and, ARGS_REQ(1)); /* 15.2.4.3.1 */ mrb_define_method(mrb, n, "^", false_xor, ARGS_REQ(1)); /* 15.2.4.3.2 */ mrb_define_method(mrb, n, "|", false_or, ARGS_REQ(1)); /* 15.2.4.3.3 */ @@ -283,14 +283,14 @@ mrb_init_object(mrb_state *mrb) mrb_define_method(mrb, n, "to_s", nil_to_s, ARGS_NONE()); /* 15.2.4.3.5 */ t = mrb->true_class = mrb_define_class(mrb, "TrueClass", mrb->object_class); - mrb_undef_method(mrb, n, "new"); + mrb_undef_class_method(mrb, t, "new"); mrb_define_method(mrb, t, "&", true_and, ARGS_REQ(1)); /* 15.2.5.3.1 */ mrb_define_method(mrb, t, "^", true_xor, ARGS_REQ(1)); /* 15.2.5.3.2 */ mrb_define_method(mrb, t, "to_s", true_to_s, ARGS_NONE()); /* 15.2.5.3.3 */ mrb_define_method(mrb, t, "|", true_or, ARGS_REQ(1)); /* 15.2.5.3.4 */ f = mrb->false_class = mrb_define_class(mrb, "FalseClass", mrb->object_class); - mrb_undef_method(mrb, n, "new"); + mrb_undef_class_method(mrb, f, "new"); mrb_define_method(mrb, f, "&", false_and, ARGS_REQ(1)); /* 15.2.6.3.1 */ mrb_define_method(mrb, f, "^", false_xor, ARGS_REQ(1)); /* 15.2.6.3.2 */ mrb_define_method(mrb, f, "to_s", false_to_s, ARGS_NONE()); /* 15.2.6.3.3 */ @@ -2041,7 +2041,7 @@ mrb_init_regexp(mrb_state *mrb) mrb_define_const(mrb, s, "FIXEDENCODING", mrb_fixnum_value(ARG_ENCODING_FIXED)); s = mrb_define_class(mrb, "MatchData", mrb->object_class); - //mrb_undef_method(CLASS_OF(rb_cMatch), "new"); + //mrb_undef_class_method(CLASS_OF(rb_cMatch), "new"); mrb_define_method(mrb, s, "[]", mrb_match_aref, ARGS_ANY()); /* 15.2.16.3.1 */ mrb_define_method(mrb, s, "begin", mrb_match_begin, ARGS_REQ(1)); /* 15.2.16.3.2 */ diff --git a/src/variable.c b/src/variable.c index 501bed5a6..a1a7f2e82 100644 --- a/src/variable.c +++ b/src/variable.c @@ -10,6 +10,7 @@ #include "mruby/variable.h" #include "error.h" #include "mruby/array.h" +#include "mruby/proc.h" #ifdef ENABLE_REGEXP #include "re.h" @@ -342,7 +343,10 @@ mrb_const_get(mrb_state *mrb, mrb_value mod, mrb_sym sym) mrb_value mrb_vm_const_get(mrb_state *mrb, mrb_sym sym) { - return const_get(mrb, mrb->ci->target_class, sym); + struct RClass *c = mrb->ci->proc->target_class; + + if (!c) c = mrb->ci->target_class; + return const_get(mrb, c, sym); } void @@ -355,7 +359,10 @@ mrb_const_set(mrb_state *mrb, mrb_value mod, mrb_sym sym, mrb_value v) void mrb_vm_const_set(mrb_state *mrb, mrb_sym sym, mrb_value v) { - mrb_obj_iv_set(mrb, (struct RObject*)mrb->ci->target_class, sym, v); + struct RClass *c = mrb->ci->proc->target_class; + + if (!c) c = mrb->ci->target_class; + mrb_obj_iv_set(mrb, (struct RObject*)c, sym, v); } void @@ -237,7 +237,7 @@ mrb_funcall_argv(mrb_state *mrb, mrb_value self, const char *name, int argc, mrb } mrb_value -mrb_yield_with_self(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv, mrb_value self) +mrb_yield_internal(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv, mrb_value self, struct RClass *c) { struct RProc *p; mrb_sym mid = mrb->ci->mid; @@ -251,7 +251,7 @@ mrb_yield_with_self(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv, mrb_ ci->proc = p; ci->stackidx = mrb->stack - mrb->stbase; ci->argc = argc; - ci->target_class = p->target_class; + ci->target_class = c; ci->nregs = argc + 2; ci->acc = -1; mrb->stack = mrb->stack + n; @@ -277,13 +277,17 @@ mrb_yield_with_self(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv, mrb_ mrb_value mrb_yield_argv(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv) { - return mrb_yield_with_self(mrb, b, argc, argv, mrb->stack[0]); + struct RProc *p = mrb_proc_ptr(b); + + return mrb_yield_internal(mrb, b, argc, argv, mrb->stack[0], p->target_class); } mrb_value mrb_yield(mrb_state *mrb, mrb_value b, mrb_value v) { - return mrb_yield_with_self(mrb, b, 1, &v, mrb->stack[0]); + struct RProc *p = mrb_proc_ptr(b); + + return mrb_yield_internal(mrb, b, 1, &v, mrb->stack[0], p->target_class); } static void @@ -1564,6 +1568,11 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) CASE(OP_TCLASS) { /* A B R(A) := target_class */ + if (!mrb->ci->target_class) { + mrb_value exc = mrb_exc_new(mrb, E_TYPE_ERROR, "no target class or module", 25); + mrb->exc = (struct RObject*)mrb_object(exc); + goto L_RAISE; + } regs[GETARG_A(i)] = mrb_obj_value(mrb->ci->target_class); NEXT; } diff --git a/test/t/array.rb b/test/t/array.rb index a113df1f4..7029cd3c6 100644 --- a/test/t/array.rb +++ b/test/t/array.rb @@ -153,7 +153,15 @@ end assert('Array#last', '15.2.12.5.18') do a = [1,2,3] - a.last == 3 and [].last == nil + e2 = nil + begin + # this will cause an exception due to the wrong argument + [1,2,3].last(-1) + rescue => e1 + e2 = e1 + end + + a.last == 3 and [].last == nil and e2.class == ArgumentError end assert('Array#length', '15.2.12.5.19') do |
