mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
vm.c: use prepare_missing in mrb_funcall_with_block
Remove code duplication.
This commit is contained in:
@@ -430,6 +430,52 @@ mrb_ci_nregs(mrb_callinfo *ci)
|
||||
return nregs;
|
||||
}
|
||||
|
||||
mrb_value mrb_obj_missing(mrb_state *mrb, mrb_value mod);
|
||||
|
||||
static mrb_method_t
|
||||
prepare_missing(mrb_state *mrb, mrb_value recv, mrb_sym mid, struct RClass **clsp, uint32_t a, uint16_t *c, mrb_value blk, int super)
|
||||
{
|
||||
mrb_sym missing = MRB_SYM(method_missing);
|
||||
mrb_callinfo *ci = mrb->c->ci;
|
||||
uint16_t b = *c;
|
||||
mrb_int n = b & 0xf;
|
||||
mrb_int nk = (b>>4) & 0xf;
|
||||
mrb_value *argv = &ci->stack[a+1];
|
||||
mrb_value args;
|
||||
mrb_method_t m;
|
||||
|
||||
/* pack positional arguments */
|
||||
if (n == 15) args = argv[0];
|
||||
else args = mrb_ary_new_from_values(mrb, n, argv);
|
||||
|
||||
if (mrb_func_basic_p(mrb, recv, missing, mrb_obj_missing)) {
|
||||
method_missing:
|
||||
if (super) mrb_no_method_error(mrb, mid, args, "no superclass method '%n'", mid);
|
||||
else mrb_method_missing(mrb, mid, recv, args);
|
||||
/* not reached */
|
||||
}
|
||||
if (mid != missing) {
|
||||
*clsp = mrb_class(mrb, recv);
|
||||
}
|
||||
m = mrb_method_search_vm(mrb, clsp, missing);
|
||||
if (MRB_METHOD_UNDEF_P(m)) goto method_missing; /* just in case */
|
||||
mrb_stack_extend(mrb, a+4);
|
||||
|
||||
argv = &ci->stack[a+1]; /* maybe reallocated */
|
||||
argv[0] = args;
|
||||
if (nk == 0) {
|
||||
argv[1] = blk;
|
||||
}
|
||||
else {
|
||||
mrb_assert(nk == 15);
|
||||
argv[1] = argv[n];
|
||||
argv[2] = blk;
|
||||
}
|
||||
*c = 15 | (nk<<4);
|
||||
mrb_ary_unshift(mrb, args, mrb_symbol_value(mid));
|
||||
return m;
|
||||
}
|
||||
|
||||
MRB_API mrb_value
|
||||
mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc, const mrb_value *argv, mrb_value blk)
|
||||
{
|
||||
@@ -478,24 +524,15 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc
|
||||
c = mrb_class(mrb, self);
|
||||
m = mrb_method_search_vm(mrb, &c, mid);
|
||||
mrb_stack_extend(mrb, n + argc + 3);
|
||||
if (MRB_METHOD_UNDEF_P(m) || argc >= 15) {
|
||||
mrb_value args = mrb_ary_new_from_values(mrb, argc, argv);
|
||||
|
||||
ci->stack[n+1] = args;
|
||||
if (argc >= 15) {
|
||||
ci->stack[n+1] = mrb_ary_new_from_values(mrb, argc, argv);
|
||||
argc = 15;
|
||||
}
|
||||
if (MRB_METHOD_UNDEF_P(m)) {
|
||||
mrb_sym missing = MRB_SYM(method_missing);
|
||||
mrb_value args = ci->stack[n+1];
|
||||
|
||||
m = mrb_method_search_vm(mrb, &c, missing);
|
||||
if (MRB_METHOD_UNDEF_P(m)) {
|
||||
mrb_method_missing(mrb, mid, self, args);
|
||||
}
|
||||
mrb_ary_unshift(mrb, args, mrb_symbol_value(mid));
|
||||
mrb_stack_extend(mrb, n+2);
|
||||
ci->stack[n+1] = args;
|
||||
argc = 15;
|
||||
uint16_t ac = (uint16_t)argc;
|
||||
m = prepare_missing(mrb, self, mid, &c, n, &ac, mrb_nil_value(), 0);
|
||||
argc = (mrb_int)ac;
|
||||
mid = MRB_SYM(method_missing);
|
||||
}
|
||||
ci = cipush(mrb, n, 0, c, NULL, mid, argc);
|
||||
if (MRB_METHOD_PROC_P(m)) {
|
||||
@@ -1123,52 +1160,6 @@ hash_new_from_values(mrb_state *mrb, mrb_int argc, mrb_value *regs)
|
||||
return hash;
|
||||
}
|
||||
|
||||
mrb_value mrb_obj_missing(mrb_state *mrb, mrb_value mod);
|
||||
|
||||
static mrb_method_t
|
||||
prepare_missing(mrb_state *mrb, mrb_value recv, mrb_sym mid, struct RClass **clsp, uint32_t a, uint16_t *c, mrb_value blk, int super)
|
||||
{
|
||||
mrb_sym missing = MRB_SYM(method_missing);
|
||||
mrb_callinfo *ci = mrb->c->ci;
|
||||
uint16_t b = *c;
|
||||
mrb_int n = b & 0xf;
|
||||
mrb_int nk = (b>>4) & 0xf;
|
||||
mrb_value *argv = &ci->stack[a+1];
|
||||
mrb_value args;
|
||||
mrb_method_t m;
|
||||
|
||||
/* pack positional arguments */
|
||||
if (n == 15) args = argv[0];
|
||||
else args = mrb_ary_new_from_values(mrb, n, argv);
|
||||
|
||||
if (mrb_func_basic_p(mrb, recv, missing, mrb_obj_missing)) {
|
||||
method_missing:
|
||||
if (super) mrb_no_method_error(mrb, mid, args, "no superclass method '%n'", mid);
|
||||
else mrb_method_missing(mrb, mid, recv, args);
|
||||
/* not reached */
|
||||
}
|
||||
if (mid != missing) {
|
||||
*clsp = mrb_class(mrb, recv);
|
||||
}
|
||||
m = mrb_method_search_vm(mrb, clsp, missing);
|
||||
if (MRB_METHOD_UNDEF_P(m)) goto method_missing; /* just in case */
|
||||
mrb_stack_extend(mrb, a+4);
|
||||
|
||||
argv = &ci->stack[a+1]; /* maybe reallocated */
|
||||
argv[0] = args;
|
||||
if (nk == 0) {
|
||||
argv[1] = blk;
|
||||
}
|
||||
else {
|
||||
mrb_assert(nk == 15);
|
||||
argv[1] = argv[n];
|
||||
argv[2] = blk;
|
||||
}
|
||||
*c = 15 | (nk<<4);
|
||||
mrb_ary_unshift(mrb, args, mrb_symbol_value(mid));
|
||||
return m;
|
||||
}
|
||||
|
||||
void mrb_method_added(mrb_state *mrb, struct RClass *c, mrb_sym mid);
|
||||
mrb_value mrb_str_aref(mrb_state *mrb, mrb_value str, mrb_value idx, mrb_value len);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user