mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
refactor mrb_bob_missing to share raising NoMethodError code; fix #2878
Note: arguments of mrb_no_method_error() has changed. You need to replace 3rd and 4th argument (say n, argv) to mrb_ary_new_from_values(mrb, n, argv).
This commit is contained in:
@@ -24,7 +24,7 @@ MRB_API mrb_value mrb_exc_new_str(mrb_state *mrb, struct RClass* c, mrb_value st
|
||||
MRB_API mrb_value mrb_make_exception(mrb_state *mrb, int argc, const mrb_value *argv);
|
||||
MRB_API mrb_value mrb_exc_backtrace(mrb_state *mrb, mrb_value exc);
|
||||
MRB_API mrb_value mrb_get_backtrace(mrb_state *mrb);
|
||||
MRB_API mrb_noreturn void mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_int argc, const mrb_value *argv, const char *fmt, ...);
|
||||
MRB_API mrb_noreturn void mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_value args, const char *fmt, ...);
|
||||
|
||||
/* declaration for fail method */
|
||||
MRB_API mrb_value mrb_f_raise(mrb_state*, mrb_value);
|
||||
|
||||
+26
-19
@@ -1262,6 +1262,31 @@ mrb_bob_not(mrb_state *mrb, mrb_value cv)
|
||||
return mrb_bool_value(!mrb_test(cv));
|
||||
}
|
||||
|
||||
void
|
||||
mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value args)
|
||||
{
|
||||
mrb_sym inspect;
|
||||
mrb_value repr;
|
||||
|
||||
inspect = mrb_intern_lit(mrb, "inspect");
|
||||
if (mrb->c->ci > mrb->c->cibase && mrb->c->ci[-1].mid == inspect) {
|
||||
/* method missing in inspect; avoid recursion */
|
||||
repr = mrb_any_to_s(mrb, self);
|
||||
}
|
||||
else if (mrb_respond_to(mrb, self, inspect) && mrb->c->ci - mrb->c->cibase < 64) {
|
||||
repr = mrb_funcall_argv(mrb, self, inspect, 0, 0);
|
||||
if (mrb_string_p(repr) && RSTRING_LEN(repr) > 64) {
|
||||
repr = mrb_any_to_s(mrb, self);
|
||||
}
|
||||
}
|
||||
else {
|
||||
repr = mrb_any_to_s(mrb, self);
|
||||
}
|
||||
|
||||
mrb_no_method_error(mrb, name, args, "undefined method '%S' for %S",
|
||||
mrb_sym2str(mrb, name), repr);
|
||||
}
|
||||
|
||||
/* 15.3.1.3.30 */
|
||||
/*
|
||||
* call-seq:
|
||||
@@ -1301,27 +1326,9 @@ mrb_bob_missing(mrb_state *mrb, mrb_value mod)
|
||||
mrb_sym name;
|
||||
mrb_value *a;
|
||||
mrb_int alen;
|
||||
mrb_sym inspect;
|
||||
mrb_value repr;
|
||||
|
||||
mrb_get_args(mrb, "n*", &name, &a, &alen);
|
||||
|
||||
inspect = mrb_intern_lit(mrb, "inspect");
|
||||
if (mrb->c->ci > mrb->c->cibase && mrb->c->ci[-1].mid == inspect) {
|
||||
/* method missing in inspect; avoid recursion */
|
||||
repr = mrb_any_to_s(mrb, mod);
|
||||
}
|
||||
else if (mrb_respond_to(mrb, mod, inspect) && mrb->c->ci - mrb->c->cibase < 64) {
|
||||
repr = mrb_funcall_argv(mrb, mod, inspect, 0, 0);
|
||||
if (mrb_string_p(repr) && RSTRING_LEN(repr) > 64) {
|
||||
repr = mrb_any_to_s(mrb, mod);
|
||||
}
|
||||
}
|
||||
else {
|
||||
repr = mrb_any_to_s(mrb, mod);
|
||||
}
|
||||
|
||||
mrb_no_method_error(mrb, name, alen, a, "undefined method '%S' for %S", mrb_sym2str(mrb, name), repr);
|
||||
mrb_method_missing(mrb, name, mod, mrb_ary_new_from_values(mrb, alen, a));
|
||||
/* not reached */
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
+2
-3
@@ -424,15 +424,14 @@ mrb_sys_fail(mrb_state *mrb, const char *mesg)
|
||||
}
|
||||
|
||||
MRB_API mrb_noreturn void
|
||||
mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_int argc, const mrb_value *argv, char const* fmt, ...)
|
||||
mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_value args, char const* fmt, ...)
|
||||
{
|
||||
mrb_value exc;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
exc = mrb_funcall(mrb, mrb_obj_value(E_NOMETHOD_ERROR), "new", 3,
|
||||
mrb_vformat(mrb, fmt, ap), mrb_symbol_value(id),
|
||||
mrb_ary_new_from_values(mrb, argc, argv));
|
||||
mrb_vformat(mrb, fmt, ap), mrb_symbol_value(id), args);
|
||||
va_end(ap);
|
||||
mrb_exc_raise(mrb, exc);
|
||||
}
|
||||
|
||||
@@ -723,6 +723,8 @@ argnum_error(mrb_state *mrb, mrb_int num)
|
||||
|
||||
#define CALL_MAXARGS 127
|
||||
|
||||
void mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value args);
|
||||
|
||||
MRB_API mrb_value
|
||||
mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stack_keep)
|
||||
{
|
||||
@@ -1078,8 +1080,15 @@ RETRY_TRY_BLOCK:
|
||||
|
||||
m = mrb_method_search_vm(mrb, &c, missing);
|
||||
if (!m) {
|
||||
mrb_no_method_error(mrb, mid, n, regs+a+1,
|
||||
"undefined method '%S' for %S", mrb_sym2str(mrb, mid), recv);
|
||||
mrb_value args;
|
||||
|
||||
if (n == CALL_MAXARGS) {
|
||||
args = regs[a+1];
|
||||
}
|
||||
else {
|
||||
args = mrb_ary_new_from_values(mrb, n, regs+a+1);
|
||||
}
|
||||
mrb_method_missing(mrb, mid, recv, args);
|
||||
}
|
||||
mid = missing;
|
||||
if (n == CALL_MAXARGS) {
|
||||
|
||||
Reference in New Issue
Block a user