diff options
Diffstat (limited to 'src/vm.c')
| -rw-r--r-- | src/vm.c | 22 |
1 files changed, 16 insertions, 6 deletions
@@ -266,6 +266,7 @@ ecall(mrb_state *mrb, int i) mrb_value *self = mrb->c->stack; struct RObject *exc; + if (i<0) return; p = mrb->c->ensure[i]; if (!p) return; if (mrb->c->ci->eidx > i) @@ -723,6 +724,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) { @@ -1030,7 +1033,7 @@ RETRY_TRY_BLOCK: mrb_callinfo *ci = mrb->c->ci; int n, eidx = ci->eidx; - for (n=0; n<a && eidx > ci[-1].eidx; n++) { + for (n=0; n<a && (ci == mrb->c->cibase || eidx > ci[-1].eidx); n++) { ecall(mrb, --eidx); ARENA_RESTORE(mrb, ai); } @@ -1078,8 +1081,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) { @@ -1476,9 +1486,6 @@ RETRY_TRY_BLOCK: if (ci->ridx == 0) goto L_STOP; goto L_RESCUE; } - while (eidx > ci[-1].eidx) { - ecall(mrb, --eidx); - } while (ci[0].ridx == ci[-1].ridx) { cipop(mrb); ci = mrb->c->ci; @@ -1488,6 +1495,9 @@ RETRY_TRY_BLOCK: MRB_THROW(prev_jmp); } if (ci == mrb->c->cibase) { + while (eidx > 0) { + ecall(mrb, --eidx); + } if (ci->ridx == 0) { if (mrb->c == mrb->root_c) { regs = mrb->c->stack = mrb->c->stbase; |
