diff --git a/include/mruby/internal.h b/include/mruby/internal.h index 0a3f605ee..96efc7697 100644 --- a/include/mruby/internal.h +++ b/include/mruby/internal.h @@ -52,7 +52,7 @@ mrb_value mrb_get_backtrace(mrb_state *mrb); void mrb_exc_mesg_set(mrb_state *mrb, struct RException *exc, mrb_value mesg); mrb_value mrb_exc_mesg_get(mrb_state *mrb, struct RException *exc); mrb_value mrb_f_raise(mrb_state*, mrb_value); -mrb_value mrb_make_exception(mrb_state *mrb, mrb_int argc, const mrb_value *argv); +mrb_value mrb_make_exception(mrb_state *mrb, mrb_value exc, mrb_value mesg); /* gc */ void mrb_gc_mark_mt(mrb_state*, struct RClass*); diff --git a/src/error.c b/src/error.c index c48331f7f..c8907552c 100644 --- a/src/error.c +++ b/src/error.c @@ -459,53 +459,29 @@ mrb_bug(mrb_state *mrb, const char *fmt, ...) } mrb_value -mrb_make_exception(mrb_state *mrb, mrb_int argc, const mrb_value *argv) +mrb_make_exception(mrb_state *mrb, mrb_value exc, mrb_value mesg) { - mrb_value mesg; - int n; + mrb_int n = 1; - mesg = mrb_nil_value(); - switch (argc) { - case 0: - break; - case 1: - if (mrb_nil_p(argv[0])) - break; - if (mrb_string_p(argv[0])) { - mesg = mrb_exc_new_str(mrb, E_RUNTIME_ERROR, argv[0]); - break; - } - n = 0; - goto exception_call; - - case 2: - case 3: - n = 1; -exception_call: - { - mrb_sym exc = MRB_SYM(exception); - if (mrb_respond_to(mrb, argv[0], exc)) { - mesg = mrb_funcall_argv(mrb, argv[0], exc, n, argv+1); - } - else { - /* undef */ - mrb_raise(mrb, E_TYPE_ERROR, "exception class/object expected"); - } - } - - break; - default: - mrb_argnum_error(mrb, argc, 0, 3); - break; + if (mrb_nil_p(mesg)) { + n = 0; } - if (argc > 0) { - if (mrb_type(mesg) != MRB_TT_EXCEPTION) - mrb_raise(mrb, E_EXCEPTION, "exception object expected"); - if (argc > 2) - set_backtrace(mrb, mesg, argv[2]); + if (mrb_class_p(exc)) { + exc = mrb_funcall_argv(mrb, exc, MRB_SYM(new), n, &mesg); } - - return mesg; + else if (mrb_exception_p(exc)) { + if (n > 0) { + exc = mrb_obj_clone(mrb, exc); + mrb_exc_mesg_set(mrb, mrb_exc_ptr(exc), mesg); + } + } + else { + mrb_raise(mrb, E_TYPE_ERROR, "exception class/object expected"); + } + if (mrb_type(exc) != MRB_TT_EXCEPTION) { + mrb_raise(mrb, E_EXCEPTION, "exception object expected"); + } + return exc; } MRB_API mrb_noreturn void diff --git a/src/kernel.c b/src/kernel.c index 250f01d2c..5060521d4 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -380,24 +380,26 @@ mrb_false(mrb_state *mrb, mrb_value self) MRB_API mrb_value mrb_f_raise(mrb_state *mrb, mrb_value self) { - mrb_value a[2], exc; + mrb_value exc, mesg; mrb_int argc; - argc = mrb_get_args(mrb, "|oo", &a[0], &a[1]); + argc = mrb_get_args(mrb, "|oo", &exc, &mesg); mrb->c->ci->mid = 0; switch (argc) { case 0: mrb_raise(mrb, E_RUNTIME_ERROR, ""); break; case 1: - if (mrb_string_p(a[0])) { - a[1] = a[0]; - argc = 2; - a[0] = mrb_obj_value(E_RUNTIME_ERROR); + if (mrb_string_p(exc)) { + mesg = exc; + exc = mrb_obj_value(E_RUNTIME_ERROR); + } + else { + mesg = mrb_nil_value(); } /* fall through */ default: - exc = mrb_make_exception(mrb, argc, a); + exc = mrb_make_exception(mrb, exc, mesg); mrb_exc_raise(mrb, exc); break; }