Skip to content

Commit 9c311dd

Browse files
committed
refactor mrb_bob_missing to share raising NoMethodError code; fix mruby#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).
1 parent 4dac03c commit 9c311dd

4 files changed

Lines changed: 40 additions & 25 deletions

File tree

include/mruby/error.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ MRB_API mrb_value mrb_exc_new_str(mrb_state *mrb, struct RClass* c, mrb_value st
2424
MRB_API mrb_value mrb_make_exception(mrb_state *mrb, int argc, const mrb_value *argv);
2525
MRB_API mrb_value mrb_exc_backtrace(mrb_state *mrb, mrb_value exc);
2626
MRB_API mrb_value mrb_get_backtrace(mrb_state *mrb);
27-
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, ...);
27+
MRB_API mrb_noreturn void mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_value args, const char *fmt, ...);
2828

2929
/* declaration for fail method */
3030
MRB_API mrb_value mrb_f_raise(mrb_state*, mrb_value);

src/class.c

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1262,6 +1262,31 @@ mrb_bob_not(mrb_state *mrb, mrb_value cv)
12621262
return mrb_bool_value(!mrb_test(cv));
12631263
}
12641264

1265+
void
1266+
mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value args)
1267+
{
1268+
mrb_sym inspect;
1269+
mrb_value repr;
1270+
1271+
inspect = mrb_intern_lit(mrb, "inspect");
1272+
if (mrb->c->ci > mrb->c->cibase && mrb->c->ci[-1].mid == inspect) {
1273+
/* method missing in inspect; avoid recursion */
1274+
repr = mrb_any_to_s(mrb, self);
1275+
}
1276+
else if (mrb_respond_to(mrb, self, inspect) && mrb->c->ci - mrb->c->cibase < 64) {
1277+
repr = mrb_funcall_argv(mrb, self, inspect, 0, 0);
1278+
if (mrb_string_p(repr) && RSTRING_LEN(repr) > 64) {
1279+
repr = mrb_any_to_s(mrb, self);
1280+
}
1281+
}
1282+
else {
1283+
repr = mrb_any_to_s(mrb, self);
1284+
}
1285+
1286+
mrb_no_method_error(mrb, name, args, "undefined method '%S' for %S",
1287+
mrb_sym2str(mrb, name), repr);
1288+
}
1289+
12651290
/* 15.3.1.3.30 */
12661291
/*
12671292
* call-seq:
@@ -1301,27 +1326,9 @@ mrb_bob_missing(mrb_state *mrb, mrb_value mod)
13011326
mrb_sym name;
13021327
mrb_value *a;
13031328
mrb_int alen;
1304-
mrb_sym inspect;
1305-
mrb_value repr;
13061329

13071330
mrb_get_args(mrb, "n*", &name, &a, &alen);
1308-
1309-
inspect = mrb_intern_lit(mrb, "inspect");
1310-
if (mrb->c->ci > mrb->c->cibase && mrb->c->ci[-1].mid == inspect) {
1311-
/* method missing in inspect; avoid recursion */
1312-
repr = mrb_any_to_s(mrb, mod);
1313-
}
1314-
else if (mrb_respond_to(mrb, mod, inspect) && mrb->c->ci - mrb->c->cibase < 64) {
1315-
repr = mrb_funcall_argv(mrb, mod, inspect, 0, 0);
1316-
if (mrb_string_p(repr) && RSTRING_LEN(repr) > 64) {
1317-
repr = mrb_any_to_s(mrb, mod);
1318-
}
1319-
}
1320-
else {
1321-
repr = mrb_any_to_s(mrb, mod);
1322-
}
1323-
1324-
mrb_no_method_error(mrb, name, alen, a, "undefined method '%S' for %S", mrb_sym2str(mrb, name), repr);
1331+
mrb_method_missing(mrb, name, mod, mrb_ary_new_from_values(mrb, alen, a));
13251332
/* not reached */
13261333
return mrb_nil_value();
13271334
}

src/error.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -424,15 +424,14 @@ mrb_sys_fail(mrb_state *mrb, const char *mesg)
424424
}
425425

426426
MRB_API mrb_noreturn void
427-
mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_int argc, const mrb_value *argv, char const* fmt, ...)
427+
mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_value args, char const* fmt, ...)
428428
{
429429
mrb_value exc;
430430
va_list ap;
431431

432432
va_start(ap, fmt);
433433
exc = mrb_funcall(mrb, mrb_obj_value(E_NOMETHOD_ERROR), "new", 3,
434-
mrb_vformat(mrb, fmt, ap), mrb_symbol_value(id),
435-
mrb_ary_new_from_values(mrb, argc, argv));
434+
mrb_vformat(mrb, fmt, ap), mrb_symbol_value(id), args);
436435
va_end(ap);
437436
mrb_exc_raise(mrb, exc);
438437
}

src/vm.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,8 @@ argnum_error(mrb_state *mrb, mrb_int num)
723723

724724
#define CALL_MAXARGS 127
725725

726+
void mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value args);
727+
726728
MRB_API mrb_value
727729
mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stack_keep)
728730
{
@@ -1078,8 +1080,15 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int
10781080

10791081
m = mrb_method_search_vm(mrb, &c, missing);
10801082
if (!m) {
1081-
mrb_no_method_error(mrb, mid, n, regs+a+1,
1082-
"undefined method '%S' for %S", mrb_sym2str(mrb, mid), recv);
1083+
mrb_value args;
1084+
1085+
if (n == CALL_MAXARGS) {
1086+
args = regs[a+1];
1087+
}
1088+
else {
1089+
args = mrb_ary_new_from_values(mrb, n, regs+a+1);
1090+
}
1091+
mrb_method_missing(mrb, mid, recv, args);
10831092
}
10841093
mid = missing;
10851094
if (n == CALL_MAXARGS) {

0 commit comments

Comments
 (0)