diff --git a/include/mruby/internal.h b/include/mruby/internal.h index 4365b4f50..f2e8ade6e 100644 --- a/include/mruby/internal.h +++ b/include/mruby/internal.h @@ -182,6 +182,7 @@ mrb_value mrb_mod_class_variables(mrb_state*, mrb_value); mrb_value mrb_mod_cv_get(mrb_state *mrb, struct RClass * c, mrb_sym sym); mrb_bool mrb_mod_cv_defined(mrb_state *mrb, struct RClass * c, mrb_sym sym); mrb_bool mrb_ident_p(const char *s, mrb_int len); +mrb_value mrb_exc_const_get(mrb_state *mrb, mrb_sym sym); /* GC functions */ void mrb_gc_mark_gv(mrb_state*); diff --git a/src/class.c b/src/class.c index 8b5eee766..6c82ad218 100644 --- a/src/class.c +++ b/src/class.c @@ -659,7 +659,7 @@ mrb_class_get_id(mrb_state *mrb, mrb_sym name) MRB_API struct RClass* mrb_exc_get_id(mrb_state *mrb, mrb_sym name) { - mrb_value c = mrb_const_get(mrb, mrb_obj_value(mrb->object_class), name); + mrb_value c = mrb_exc_const_get(mrb, name); if (!mrb_class_p(c)) { mrb_raise(mrb, E_EXCEPTION, "exception corrupted"); @@ -670,7 +670,9 @@ mrb_exc_get_id(mrb_state *mrb, mrb_sym name) if (e == E_EXCEPTION) return exc; } - return E_EXCEPTION; + mrb_raise(mrb, E_EXCEPTION, "non-exception raised"); + /* not reached */ + return NULL; } MRB_API struct RClass* diff --git a/src/variable.c b/src/variable.c index d224a5a34..ee857140b 100644 --- a/src/variable.c +++ b/src/variable.c @@ -764,7 +764,7 @@ mod_const_check(mrb_state *mrb, mrb_value mod) } static mrb_value -const_get(mrb_state *mrb, struct RClass *base, mrb_sym sym, mrb_bool skip) +const_get_nohook(mrb_state *mrb, struct RClass *base, mrb_sym sym, mrb_bool skip) { struct RClass *c = base; mrb_value v; @@ -785,12 +785,30 @@ L_RETRY: retry = TRUE; goto L_RETRY; } - mrb_value mod = mrb_obj_value(base); - if (mrb_func_basic_p(mrb, mod, MRB_SYM(const_missing), mrb_mod_const_missing)) { - return mrb_const_missing(mrb, mod, sym); + return mrb_undef_value(); +} + +static mrb_value +const_get(mrb_state *mrb, struct RClass *base, mrb_sym sym, mrb_bool skip) +{ + mrb_value v = const_get_nohook(mrb, base, sym, skip); + + /* call const_missing hook */ + if (mrb_undef_p(v)) { + mrb_value mod = mrb_obj_value(base); + if (mrb_func_basic_p(mrb, mod, MRB_SYM(const_missing), mrb_mod_const_missing)) { + return mrb_const_missing(mrb, mod, sym); + } + mrb_value name = mrb_symbol_value(sym); + return mrb_funcall_argv(mrb, mod, MRB_SYM(const_missing), 1, &name); } - mrb_value name = mrb_symbol_value(sym); - return mrb_funcall_argv(mrb, mod, MRB_SYM(const_missing), 1, &name); + return v; +} + +mrb_value +mrb_exc_const_get(mrb_state *mrb, mrb_sym sym) +{ + return const_get_nohook(mrb, mrb->object_class, sym, FALSE); } MRB_API mrb_value