summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/mruby.h2
-rw-r--r--src/array.c3
-rw-r--r--src/class.c6
-rw-r--r--src/kernel.c8
-rw-r--r--src/numeric.c4
-rw-r--r--src/object.c6
-rw-r--r--src/re.c2
-rw-r--r--src/variable.c11
-rw-r--r--src/vm.c17
-rw-r--r--test/t/array.rb10
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 */
diff --git a/src/re.c b/src/re.c
index 3639a41c6..f3cfea484 100644
--- a/src/re.c
+++ b/src/re.c
@@ -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
diff --git a/src/vm.c b/src/vm.c
index bd3d05d81..62ef5069d 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -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