diff options
| -rw-r--r-- | include/mruby.h | 44 | ||||
| -rw-r--r-- | include/mruby/string.h | 2 | ||||
| -rw-r--r-- | src/class.c | 18 | ||||
| -rw-r--r-- | src/error.c | 9 | ||||
| -rw-r--r-- | src/string.c | 1 | ||||
| -rw-r--r-- | src/vm.c | 39 | ||||
| -rw-r--r-- | test/t/nomethoderror.rb | 18 |
7 files changed, 100 insertions, 31 deletions
diff --git a/include/mruby.h b/include/mruby.h index 76a028ad4..99d06146f 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -608,6 +608,14 @@ MRB_API mrb_bool mrb_class_defined(mrb_state *mrb, const char *name); MRB_API struct RClass * mrb_class_get(mrb_state *mrb, const char *name); /** + * Gets a exception class. + * @param [mrb_state*] mrb The current mruby state. + * @param [const char *] name The name of the class. + * @return [struct RClass *] A reference to the class. +*/ +MRB_API struct RClass * mrb_exc_get(mrb_state *mrb, const char *name); + +/** * Returns an mrb_bool. True if inner class was defined, and false if the inner class was not defined. * * Example: @@ -1091,23 +1099,23 @@ MRB_API void mrb_print_error(mrb_state *mrb); + those E_* macros requires mrb_state* variable named mrb. + exception objects obtained from those macros are local to mrb */ -#define E_RUNTIME_ERROR (mrb_class_get(mrb, "RuntimeError")) -#define E_TYPE_ERROR (mrb_class_get(mrb, "TypeError")) -#define E_ARGUMENT_ERROR (mrb_class_get(mrb, "ArgumentError")) -#define E_INDEX_ERROR (mrb_class_get(mrb, "IndexError")) -#define E_RANGE_ERROR (mrb_class_get(mrb, "RangeError")) -#define E_NAME_ERROR (mrb_class_get(mrb, "NameError")) -#define E_NOMETHOD_ERROR (mrb_class_get(mrb, "NoMethodError")) -#define E_SCRIPT_ERROR (mrb_class_get(mrb, "ScriptError")) -#define E_SYNTAX_ERROR (mrb_class_get(mrb, "SyntaxError")) -#define E_LOCALJUMP_ERROR (mrb_class_get(mrb, "LocalJumpError")) -#define E_REGEXP_ERROR (mrb_class_get(mrb, "RegexpError")) -#define E_SYSSTACK_ERROR (mrb_class_get(mrb, "SystemStackError")) - -#define E_NOTIMP_ERROR (mrb_class_get(mrb, "NotImplementedError")) -#define E_FLOATDOMAIN_ERROR (mrb_class_get(mrb, "FloatDomainError")) - -#define E_KEY_ERROR (mrb_class_get(mrb, "KeyError")) +#define E_RUNTIME_ERROR (mrb_exc_get(mrb, "RuntimeError")) +#define E_TYPE_ERROR (mrb_exc_get(mrb, "TypeError")) +#define E_ARGUMENT_ERROR (mrb_exc_get(mrb, "ArgumentError")) +#define E_INDEX_ERROR (mrb_exc_get(mrb, "IndexError")) +#define E_RANGE_ERROR (mrb_exc_get(mrb, "RangeError")) +#define E_NAME_ERROR (mrb_exc_get(mrb, "NameError")) +#define E_NOMETHOD_ERROR (mrb_exc_get(mrb, "NoMethodError")) +#define E_SCRIPT_ERROR (mrb_exc_get(mrb, "ScriptError")) +#define E_SYNTAX_ERROR (mrb_exc_get(mrb, "SyntaxError")) +#define E_LOCALJUMP_ERROR (mrb_exc_get(mrb, "LocalJumpError")) +#define E_REGEXP_ERROR (mrb_exc_get(mrb, "RegexpError")) +#define E_SYSSTACK_ERROR (mrb_exc_get(mrb, "SystemStackError")) + +#define E_NOTIMP_ERROR (mrb_exc_get(mrb, "NotImplementedError")) +#define E_FLOATDOMAIN_ERROR (mrb_exc_get(mrb, "FloatDomainError")) + +#define E_KEY_ERROR (mrb_exc_get(mrb, "KeyError")) MRB_API mrb_value mrb_yield(mrb_state *mrb, mrb_value b, mrb_value arg); MRB_API mrb_value mrb_yield_argv(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv); @@ -1160,7 +1168,7 @@ MRB_API mrb_value mrb_fiber_yield(mrb_state *mrb, mrb_int argc, const mrb_value * * @mrbgem mruby-fiber */ -#define E_FIBER_ERROR (mrb_class_get(mrb, "FiberError")) +#define E_FIBER_ERROR (mrb_exc_get(mrb, "FiberError")) /* memory pool implementation */ typedef struct mrb_pool mrb_pool; diff --git a/include/mruby/string.h b/include/mruby/string.h index 9ccf8f187..5a5a6ffd2 100644 --- a/include/mruby/string.h +++ b/include/mruby/string.h @@ -68,7 +68,7 @@ struct RString { #define mrb_str_ptr(s) ((struct RString*)(mrb_ptr(s))) #define RSTRING(s) mrb_str_ptr(s) #define RSTRING_PTR(s) RSTR_PTR(RSTRING(s)) -#define RSTRING_EMBED_LEN(s) RSTR_ENBED_LEN(RSTRING(s)) +#define RSTRING_EMBED_LEN(s) RSTR_EMBED_LEN(RSTRING(s)) #define RSTRING_LEN(s) RSTR_LEN(RSTRING(s)) #define RSTRING_CAPA(s) RSTR_CAPA(RSTRING(s)) #define RSTRING_END(s) (RSTRING_PTR(s) + RSTRING_LEN(s)) diff --git a/src/class.c b/src/class.c index fed259b5b..45827f5ba 100644 --- a/src/class.c +++ b/src/class.c @@ -318,6 +318,20 @@ mrb_class_get(mrb_state *mrb, const char *name) } MRB_API struct RClass * +mrb_exc_get(mrb_state *mrb, const char *name) +{ + struct RClass *exc = mrb_class_get_under(mrb, mrb->object_class, name); + struct RClass *e = exc; + + while (e) { + if (e == mrb->eException_class) + return exc; + e = e->super; + } + return mrb->eException_class; +} + +MRB_API struct RClass * mrb_module_get_under(mrb_state *mrb, struct RClass *outer, const char *name) { return module_from_sym(mrb, outer, mrb_intern_cstr(mrb, name)); @@ -901,7 +915,9 @@ boot_defclass(mrb_state *mrb, struct RClass *super) static void boot_initmod(mrb_state *mrb, struct RClass *mod) { - mod->mt = kh_init(mt, mrb); + if (!mod->mt) { + mod->mt = kh_init(mt, mrb); + } } static struct RClass* diff --git a/src/error.c b/src/error.c index b24aed798..8e456ff1a 100644 --- a/src/error.c +++ b/src/error.c @@ -44,8 +44,10 @@ static mrb_value exc_initialize(mrb_state *mrb, mrb_value exc) { mrb_value mesg; + mrb_int argc; + mrb_value *argv; - if (mrb_get_args(mrb, "|o", &mesg) == 1) { + if (mrb_get_args(mrb, "|o*", &mesg, &argv, &argc) >= 1) { mrb_iv_set(mrb, exc, mrb_intern_lit(mrb, "mesg"), mesg); } return exc; @@ -278,8 +280,6 @@ mrb_exc_set(mrb_state *mrb, mrb_value exc) mrb->exc = 0; } else { - if (!mrb_obj_is_kind_of(mrb, exc, mrb->eException_class)) - mrb_raise(mrb, E_TYPE_ERROR, "exception object expected"); mrb->exc = mrb_obj_ptr(exc); } } @@ -287,6 +287,9 @@ mrb_exc_set(mrb_state *mrb, mrb_value exc) MRB_API mrb_noreturn void mrb_exc_raise(mrb_state *mrb, mrb_value exc) { + if (!mrb_obj_is_kind_of(mrb, exc, mrb->eException_class)) { + mrb_raise(mrb, E_TYPE_ERROR, "exception object expected"); + } mrb_exc_set(mrb, exc); if (!mrb->gc.out_of_memory) { exc_debug_info(mrb, mrb->exc); diff --git a/src/string.c b/src/string.c index b4746545a..d6bdd6975 100644 --- a/src/string.c +++ b/src/string.c @@ -519,6 +519,7 @@ str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2) long len; check_frozen(mrb, s1); + if (s1 == s2) return mrb_obj_value(s1); len = RSTR_LEN(s2); if (RSTR_SHARED_P(s1)) { str_decref(mrb, s1->as.heap.aux.shared); @@ -373,7 +373,7 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc mrb_method_missing(mrb, mid, self, args); } undef = mid; - n++; argc++; + argc++; } ci = cipush(mrb); ci->mid = mid; @@ -389,8 +389,18 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc ci->nregs = argc + 2; stack_extend(mrb, ci->nregs, 0); } + else if (argc >= CALL_MAXARGS) { + mrb_value args = mrb_ary_new_from_values(mrb, argc, argv); + stack_extend(mrb, ci->nregs, 0); + mrb->c->stack[1] = args; + if (undef) { + mrb_ary_unshift(mrb, mrb->c->stack[1], mrb_symbol_value(undef)); + } + ci->argc = -1; + argc = 1; + } else { - ci->nregs = p->body.irep->nregs + n; + ci->nregs = p->body.irep->nregs + argc; stack_extend(mrb, ci->nregs, argc+2); } if (voff >= 0) { @@ -403,7 +413,7 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc stack_copy(mrb->c->stack+2, argv, argc-1); } } - else if (argc > 0) { + else if (ci->argc > 0) { stack_copy(mrb->c->stack+1, argv, argc); } mrb->c->stack[argc+1] = blk; @@ -707,15 +717,22 @@ argnum_error(mrb_state *mrb, mrb_int num) { mrb_value exc; mrb_value str; + mrb_int argc = mrb->c->ci->argc; + if (argc < 0) { + mrb_value args = mrb->c->stack[1]; + if (mrb_array_p(args)) { + argc = RARRAY_LEN(args); + } + } if (mrb->c->ci->mid) { str = mrb_format(mrb, "'%S': wrong number of arguments (%S for %S)", mrb_sym2str(mrb, mrb->c->ci->mid), - mrb_fixnum_value(mrb->c->ci->argc), mrb_fixnum_value(num)); + mrb_fixnum_value(argc), mrb_fixnum_value(num)); } else { str = mrb_format(mrb, "wrong number of arguments (%S for %S)", - mrb_fixnum_value(mrb->c->ci->argc), mrb_fixnum_value(num)); + mrb_fixnum_value(argc), mrb_fixnum_value(num)); } exc = mrb_exc_new_str(mrb, E_ARGUMENT_ERROR, str); mrb_exc_set(mrb, exc); @@ -1288,7 +1305,7 @@ RETRY_TRY_BLOCK: int a = GETARG_A(i); int n = GETARG_C(i); - if (mid == 0) { + if (mid == 0 || !mrb->c->ci->target_class) { mrb_value exc; exc = mrb_exc_new_str_lit(mrb, E_NOMETHOD_ERROR, "super called outside of method"); @@ -2411,7 +2428,8 @@ RETRY_TRY_BLOCK: CASE(OP_RANGE) { /* A B C R(A) := range_new(R(B),R(B+1),C) */ int b = GETARG_B(i); - regs[GETARG_A(i)] = mrb_range_new(mrb, regs[b], regs[b+1], GETARG_C(i)); + mrb_value val = mrb_range_new(mrb, regs[b], regs[b+1], GETARG_C(i)); + regs[GETARG_A(i)] = val; ARENA_RESTORE(mrb, ai); NEXT; } @@ -2477,7 +2495,12 @@ RETRY_TRY_BLOCK: MRB_API mrb_value mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) { - return mrb_vm_run(mrb, proc, self, mrb->c->ci->argc + 2); /* argc + 2 (receiver and block) */ + if (mrb->c->ci->argc < 0) { + return mrb_vm_run(mrb, proc, self, 3); /* receiver, args and block) */ + } + else { + return mrb_vm_run(mrb, proc, self, mrb->c->ci->argc + 2); /* argc + 2 (receiver and block) */ + } } MRB_API mrb_value diff --git a/test/t/nomethoderror.rb b/test/t/nomethoderror.rb index 1c09bc20e..41a3ba14f 100644 --- a/test/t/nomethoderror.rb +++ b/test/t/nomethoderror.rb @@ -51,3 +51,21 @@ assert('Can still call super when BasicObject#method_missing is removed') do end end end + +assert("NoMethodError#new does not return an exception") do + begin + class << NoMethodError + def new(*) + nil + end + end + + assert_raise(TypeError) do + Object.q + end + ensure + class << NoMethodError + remove_method :new + end + end +end |
