diff options
| -rw-r--r-- | mrbgems/mruby-binding-core/src/binding-core.c | 22 | ||||
| -rw-r--r-- | mrbgems/mruby-binding/mrblib/binding.rb | 5 | ||||
| -rw-r--r-- | mrbgems/mruby-binding/src/binding.c | 173 | ||||
| -rw-r--r-- | mrbgems/mruby-binding/test/binding.rb | 7 | ||||
| -rw-r--r-- | mrbgems/mruby-compiler/core/parse.y | 16 | ||||
| -rw-r--r-- | mrbgems/mruby-compiler/core/y.tab.c | 16 | ||||
| -rw-r--r-- | mrbgems/mruby-eval/src/eval.c | 47 | ||||
| -rw-r--r-- | mrbgems/mruby-method/src/method.c | 4 | ||||
| -rw-r--r-- | src/proc.c | 9 | ||||
| -rw-r--r-- | src/vm.c | 81 |
10 files changed, 247 insertions, 133 deletions
diff --git a/mrbgems/mruby-binding-core/src/binding-core.c b/mrbgems/mruby-binding-core/src/binding-core.c index 57b1b5434..7b70cfb78 100644 --- a/mrbgems/mruby-binding-core/src/binding-core.c +++ b/mrbgems/mruby-binding-core/src/binding-core.c @@ -24,16 +24,16 @@ binding_extract_pc(mrb_state *mrb, mrb_value binding) } } -static const struct RProc * -binding_extract_proc(mrb_state *mrb, mrb_value binding) +const struct RProc * +mrb_binding_extract_proc(mrb_state *mrb, mrb_value binding) { mrb_value obj = mrb_iv_get(mrb, binding, MRB_SYM(proc)); mrb_check_type(mrb, obj, MRB_TT_PROC); return mrb_proc_ptr(obj); } -static struct REnv * -binding_extract_env(mrb_state *mrb, mrb_value binding) +struct REnv * +mrb_binding_extract_env(mrb_state *mrb, mrb_value binding) { mrb_value obj = mrb_iv_get(mrb, binding, MRB_SYM(env)); if (mrb_nil_p(obj)) { @@ -108,8 +108,8 @@ binding_local_variable_defined_p(mrb_state *mrb, mrb_value self) mrb_sym varname; mrb_get_args(mrb, "n", &varname); - const struct RProc *proc = binding_extract_proc(mrb, self); - struct REnv *env = binding_extract_env(mrb, self); + const struct RProc *proc = mrb_binding_extract_proc(mrb, self); + struct REnv *env = mrb_binding_extract_env(mrb, self); mrb_value *e = binding_local_variable_search(mrb, proc, env, varname); if (e) { return mrb_true_value(); @@ -129,8 +129,8 @@ binding_local_variable_get(mrb_state *mrb, mrb_value self) mrb_sym varname; mrb_get_args(mrb, "n", &varname); - const struct RProc *proc = binding_extract_proc(mrb, self); - struct REnv *env = binding_extract_env(mrb, self); + const struct RProc *proc = mrb_binding_extract_proc(mrb, self); + struct REnv *env = mrb_binding_extract_env(mrb, self); mrb_value *e = binding_local_variable_search(mrb, proc, env, varname); if (!e) { mrb_raisef(mrb, E_NAME_ERROR, "local variable %!n is not defined", varname); @@ -146,8 +146,8 @@ binding_local_variable_set(mrb_state *mrb, mrb_value self) mrb_value obj; mrb_get_args(mrb, "no", &varname, &obj); - const struct RProc *proc = binding_extract_proc(mrb, self); - struct REnv *env = binding_extract_env(mrb, self); + const struct RProc *proc = mrb_binding_extract_proc(mrb, self); + struct REnv *env = mrb_binding_extract_env(mrb, self); mrb_value *e = binding_local_variable_search(mrb, proc, env, varname); if (e) { *e = obj; @@ -184,7 +184,7 @@ binding_source_location(mrb_state *mrb, mrb_value self) } mrb_value srcloc; - const struct RProc *proc = binding_extract_proc(mrb, self); + const struct RProc *proc = mrb_binding_extract_proc(mrb, self); if (!proc || MRB_PROC_CFUNC_P(proc) || !proc->upper || MRB_PROC_CFUNC_P(proc->upper)) { srcloc = mrb_nil_value(); diff --git a/mrbgems/mruby-binding/mrblib/binding.rb b/mrbgems/mruby-binding/mrblib/binding.rb deleted file mode 100644 index b07480db1..000000000 --- a/mrbgems/mruby-binding/mrblib/binding.rb +++ /dev/null @@ -1,5 +0,0 @@ -class Binding - def eval(expr, *args) - Kernel.eval(expr, self, *args) - end -end diff --git a/mrbgems/mruby-binding/src/binding.c b/mrbgems/mruby-binding/src/binding.c new file mode 100644 index 000000000..67692e2b9 --- /dev/null +++ b/mrbgems/mruby-binding/src/binding.c @@ -0,0 +1,173 @@ +#include <mruby.h> +#include <mruby/array.h> +#include <mruby/class.h> +#include <mruby/compile.h> +#include <mruby/error.h> +#include <mruby/proc.h> +#include <mruby/presym.h> +#include <mruby/string.h> + +mrb_noreturn void mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value args); +void mrb_proc_merge_lvar(mrb_state *mrb, mrb_irep *irep, struct REnv *env, int num, const mrb_sym *lv, const mrb_value *stack); +mrb_value mrb_exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p); +const struct RProc *mrb_binding_extract_proc(mrb_state *mrb, mrb_value binding); +struct REnv *mrb_binding_extract_env(mrb_state *mrb, mrb_value binding); +typedef mrb_bool mrb_parser_foreach_top_variable_func(mrb_state *mrb, mrb_sym sym, void *user); +void mrb_parser_foreach_top_variable(mrb_state *mrb, struct mrb_parser_state *p, mrb_parser_foreach_top_variable_func *func, void *user); + +static void +insert_args(mrb_state *mrb, size_t offset, mrb_value obj) +{ + mrb_callinfo *ci = mrb->c->ci; + mrb_value *argp = ci->stack + 1 /* recv */; + + if (ci->argc < 0) { + mrb_ary_splice(mrb, *argp, offset, 0, obj); + } + else { + argp += offset; + mrb_stack_extend(mrb, ci->argc + offset + 2 /* recv + block */); + memmove(argp + 1 /* obj */, argp, sizeof(mrb_value) * (ci->argc - offset + 1 /* block */)); + *argp = obj; + ci->argc++; + } +} + +static void +binding_eval_error_check(mrb_state *mrb, struct mrb_parser_state *p, const char *file) +{ + if (!p) { + mrb_raise(mrb, E_RUNTIME_ERROR, "Failed to create parser state (out of memory)"); + } + + if (0 < p->nerr) { + mrb_value str; + + if (file) { + str = mrb_format(mrb, "file %s line %d: %s", + file, + p->error_buffer[0].lineno, + p->error_buffer[0].message); + } + else { + str = mrb_format(mrb, "line %d: %s", + p->error_buffer[0].lineno, + p->error_buffer[0].message); + } + mrb_exc_raise(mrb, mrb_exc_new_str(mrb, E_SYNTAX_ERROR, str)); + } +} + +#define LV_BUFFERS 8 + +struct expand_lvspace { + mrb_irep *irep; + struct REnv *env; + size_t numvar; + mrb_sym syms[LV_BUFFERS]; +}; + +static mrb_bool +expand_lvspace(mrb_state *mrb, mrb_sym sym, void *user) +{ + struct expand_lvspace *p = (struct expand_lvspace*)user; + mrb_int symlen; + const char *symname = mrb_sym_name_len(mrb, sym, &symlen); + + if (symname && symlen > 0) { + if (symname[0] != '&' && symname[0] != '*') { + p->syms[p->numvar++] = sym; + if (p->numvar >= LV_BUFFERS) { + mrb_proc_merge_lvar(mrb, p->irep, p->env, p->numvar, p->syms, NULL); + p->numvar = 0; + } + } + } + + return TRUE; +} + +struct binding_eval_prepare_body { + mrb_value binding; + const char *file; + const char *expr; + mrb_int exprlen; + mrbc_context *mrbc; + struct mrb_parser_state *pstate; +}; + +static mrb_value +binding_eval_prepare_body(mrb_state *mrb, void *opaque) +{ + struct binding_eval_prepare_body *p = (struct binding_eval_prepare_body*)opaque; + + const struct RProc *proc = mrb_binding_extract_proc(mrb, p->binding); + mrb_assert(!MRB_PROC_CFUNC_P(proc)); + + p->mrbc = mrbc_context_new(mrb); + mrbc_filename(mrb, p->mrbc, p->file ? p->file : "(eval)"); + p->mrbc->upper = proc; + p->mrbc->capture_errors = TRUE; + p->pstate = mrb_parse_nstring(mrb, p->expr, p->exprlen, p->mrbc); + binding_eval_error_check(mrb, p->pstate, p->file); + + struct expand_lvspace args = { + (mrb_irep*)proc->body.irep, + mrb_binding_extract_env(mrb, p->binding), + 0, + { 0 } + }; + mrb_parser_foreach_top_variable(mrb, p->pstate, expand_lvspace, &args); + if (args.numvar > 0) { + mrb_proc_merge_lvar(mrb, args.irep, args.env, args.numvar, args.syms, NULL); + } + + return mrb_nil_value(); +} + +static void +binding_eval_prepare(mrb_state *mrb, mrb_value binding) +{ + struct binding_eval_prepare_body d = { binding, NULL, NULL, 0, NULL, NULL }; + mrb_int argc; + mrb_value *argv; + mrb_get_args(mrb, "s|z*!", &d.expr, &d.exprlen, &d.file, &argv, &argc); + + mrb_bool error; + mrb_value ret = mrb_protect_error(mrb, binding_eval_prepare_body, &d, &error); + if (d.pstate) mrb_parser_free(d.pstate); + if (d.mrbc) mrbc_context_free(mrb, d.mrbc); + if (error) mrb_exc_raise(mrb, ret); +} + +static mrb_value +mrb_binding_eval(mrb_state *mrb, mrb_value binding) +{ + binding_eval_prepare(mrb, binding); + + struct RClass *c = mrb->kernel_module; + mrb_method_t m = mrb_method_search_vm(mrb, &c, MRB_SYM(eval)); + if (MRB_METHOD_UNDEF_P(m)) { + int argc = mrb->c->ci->argc; + mrb_value *argv = mrb->c->ci->stack + 1; + mrb_value args = (argc < 0) ? argv[0] : mrb_ary_new_from_values(mrb, argc, argv); + mrb_method_missing(mrb, MRB_SYM(eval), binding, args); + } + + insert_args(mrb, 1, binding); + struct RProc *proc = MRB_METHOD_PROC_P(m) ? MRB_METHOD_PROC(m) : mrb_proc_new_cfunc(mrb, MRB_METHOD_FUNC(m)); + mrb->c->ci->u.target_class = c; + return mrb_exec_irep(mrb, binding, proc); +} + +void +mrb_mruby_binding_gem_init(mrb_state *mrb) +{ + struct RClass *binding = mrb_class_get_id(mrb, MRB_SYM(Binding)); + mrb_define_method(mrb, binding, "eval", mrb_binding_eval, MRB_ARGS_ANY()); +} + +void +mrb_mruby_binding_gem_final(mrb_state *mrb) +{ +} diff --git a/mrbgems/mruby-binding/test/binding.rb b/mrbgems/mruby-binding/test/binding.rb index 7dd3fd1dd..296fb48d4 100644 --- a/mrbgems/mruby-binding/test/binding.rb +++ b/mrbgems/mruby-binding/test/binding.rb @@ -68,3 +68,10 @@ assert "Binding#eval with Binding.new via Method" do assert_true true end + +assert "access local variables into procs" do + bx = binding + block = bx.eval("a = 1; proc { a }") + bx.eval("a = 2") + assert_equal 2, block.call +end diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index 96615e3bb..7d9db4a2b 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -7759,3 +7759,19 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset) } #endif } + +typedef mrb_bool mrb_parser_foreach_top_variable_func(mrb_state *mrb, mrb_sym sym, void *user); +void mrb_parser_foreach_top_variable(mrb_state *mrb, struct mrb_parser_state *p, mrb_parser_foreach_top_variable_func *func, void *user); + +void +mrb_parser_foreach_top_variable(mrb_state *mrb, struct mrb_parser_state *p, mrb_parser_foreach_top_variable_func *func, void *user) +{ + const mrb_ast_node *n = p->tree; + if ((intptr_t)n->car == NODE_SCOPE) { + n = n->cdr->car; + for (; n; n = n->cdr) { + mrb_sym sym = (intptr_t)n->car; + if (sym && !func(mrb, sym, user)) break; + } + } +} diff --git a/mrbgems/mruby-compiler/core/y.tab.c b/mrbgems/mruby-compiler/core/y.tab.c index 3b2ce8043..9cd36ec7b 100644 --- a/mrbgems/mruby-compiler/core/y.tab.c +++ b/mrbgems/mruby-compiler/core/y.tab.c @@ -13951,3 +13951,19 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset) } #endif } + +typedef mrb_bool mrb_parser_foreach_top_variable_func(mrb_state *mrb, mrb_sym sym, void *user); +void mrb_parser_foreach_top_variable(mrb_state *mrb, struct mrb_parser_state *p, mrb_parser_foreach_top_variable_func *func, void *user); + +void +mrb_parser_foreach_top_variable(mrb_state *mrb, struct mrb_parser_state *p, mrb_parser_foreach_top_variable_func *func, void *user) +{ + const mrb_ast_node *n = p->tree; + if ((intptr_t)n->car == NODE_SCOPE) { + n = n->cdr->car; + for (; n; n = n->cdr) { + mrb_sym sym = (intptr_t)n->car; + if (sym && !func(mrb, sym, user)) break; + } + } +} diff --git a/mrbgems/mruby-eval/src/eval.c b/mrbgems/mruby-eval/src/eval.c index f1c5c475f..de1bcd02d 100644 --- a/mrbgems/mruby-eval/src/eval.c +++ b/mrbgems/mruby-eval/src/eval.c @@ -9,7 +9,7 @@ #include <mruby/variable.h> struct REnv *mrb_env_new(mrb_state *mrb, struct mrb_context *c, mrb_callinfo *ci, int nstacks, mrb_value *stack, struct RClass *tc); -mrb_value mrb_exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p, mrb_func_t posthook); +mrb_value mrb_exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p); mrb_value mrb_obj_instance_eval(mrb_state *mrb, mrb_value self); mrb_value mrb_mod_module_eval(mrb_state*, mrb_value); void mrb_codedump_all(mrb_state*, struct RProc*); @@ -129,44 +129,13 @@ create_proc_from_string(mrb_state *mrb, const char *s, mrb_int len, mrb_value bi } static mrb_value -exec_irep(mrb_state *mrb, mrb_value self, struct RProc *proc, mrb_func_t posthook) +exec_irep(mrb_state *mrb, mrb_value self, struct RProc *proc) { /* no argument passed from eval() */ mrb->c->ci->argc = 0; /* clear block */ mrb->c->ci->stack[1] = mrb_nil_value(); - return mrb_exec_irep(mrb, self, proc, posthook); -} - -static void -eval_merge_lvar(mrb_state *mrb, mrb_irep *irep, struct REnv *env, int num, const mrb_sym *lv, const mrb_value *stack) -{ - mrb_assert(mrb->c->stend >= stack + num); - mrb_proc_merge_lvar(mrb, irep, env, num, lv, stack); -} - -static mrb_value -eval_merge_lvar_hook(mrb_state *mrb, mrb_value dummy_self) -{ - const mrb_callinfo *orig_ci = &mrb->c->ci[1]; - const struct RProc *orig_proc = orig_ci->proc; - const mrb_irep *orig_irep = orig_proc->body.irep; - int orig_nlocals = orig_irep->nlocals; - - if (orig_nlocals > 1) { - struct RProc *proc = (struct RProc *)orig_proc->upper; - struct REnv *env = MRB_PROC_ENV(orig_proc); - eval_merge_lvar(mrb, (mrb_irep *)proc->body.irep, env, - orig_nlocals - 1, orig_irep->lv, - mrb->c->ci->stack + 3 /* hook proc + exc + ret val */); - } - - mrb_value exc = mrb->c->ci->stack[1]; - if (!mrb_nil_p(exc)) { - mrb_exc_raise(mrb, exc); - } - - return mrb->c->ci->stack[2]; + return mrb_exec_irep(mrb, self, proc); } static mrb_value @@ -178,19 +147,15 @@ f_eval(mrb_state *mrb, mrb_value self) const char *file = NULL; mrb_int line = 1; struct RProc *proc; - mrb_func_t posthook = NULL; mrb_get_args(mrb, "s|ozi", &s, &len, &binding, &file, &line); proc = create_proc_from_string(mrb, s, len, binding, file, line); if (!mrb_nil_p(binding)) { self = mrb_iv_get(mrb, binding, MRB_SYM(recv)); - if (mrb_env_p(mrb_iv_get(mrb, binding, MRB_SYM(env)))) { - posthook = eval_merge_lvar_hook; - } } mrb_assert(!MRB_PROC_CFUNC_P(proc)); - return exec_irep(mrb, self, proc, posthook); + return exec_irep(mrb, self, proc); } static mrb_value @@ -210,7 +175,7 @@ f_instance_eval(mrb_state *mrb, mrb_value self) MRB_PROC_SET_TARGET_CLASS(proc, mrb_class_ptr(cv)); mrb_assert(!MRB_PROC_CFUNC_P(proc)); mrb_vm_ci_target_class_set(mrb->c->ci, mrb_class_ptr(cv)); - return exec_irep(mrb, self, proc, NULL); + return exec_irep(mrb, self, proc); } else { mrb_get_args(mrb, ""); @@ -233,7 +198,7 @@ f_class_eval(mrb_state *mrb, mrb_value self) MRB_PROC_SET_TARGET_CLASS(proc, mrb_class_ptr(self)); mrb_assert(!MRB_PROC_CFUNC_P(proc)); mrb_vm_ci_target_class_set(mrb->c->ci, mrb_class_ptr(self)); - return exec_irep(mrb, self, proc, NULL); + return exec_irep(mrb, self, proc); } else { mrb_get_args(mrb, ""); diff --git a/mrbgems/mruby-method/src/method.c b/mrbgems/mruby-method/src/method.c index 7410f007e..02131050d 100644 --- a/mrbgems/mruby-method/src/method.c +++ b/mrbgems/mruby-method/src/method.c @@ -7,7 +7,7 @@ #include "mruby/presym.h" mrb_noreturn void mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value args); -mrb_value mrb_exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p, mrb_func_t posthook); +mrb_value mrb_exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p); static mrb_value args_shift(mrb_state *mrb) @@ -242,7 +242,7 @@ mcall(mrb_state *mrb, mrb_value self, mrb_value recv) mrb->c->ci->mid = mid; mrb->c->ci->u.target_class = tc; - return mrb_exec_irep(mrb, recv, proc, NULL); + return mrb_exec_irep(mrb, recv, proc); } static mrb_value diff --git a/src/proc.c b/src/proc.c index 2717cd610..1d5a4aa76 100644 --- a/src/proc.c +++ b/src/proc.c @@ -417,7 +417,14 @@ mrb_proc_merge_lvar(mrb_state *mrb, mrb_irep *irep, struct REnv *env, int num, c mrb_sym *destlv = (mrb_sym*)irep->lv + irep->nlocals - 1 /* self */; mrb_value *destst = env->stack + irep->nlocals; memmove(destlv, lv, sizeof(mrb_sym) * num); - memmove(destst, stack, sizeof(mrb_value) * num); + if (stack) { + memmove(destst, stack, sizeof(mrb_value) * num); + } + else { + for (int i = num; i > 0; i--, destst++) { + *destst = mrb_nil_value(); + } + } irep->nlocals += num; irep->nregs = irep->nlocals; MRB_ENV_SET_LEN(env, irep->nlocals); @@ -526,68 +526,8 @@ mrb_funcall_argv(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc, cons return mrb_funcall_with_block(mrb, self, mid, argc, argv, mrb_nil_value()); } -#define DECOMPOSE32(n) (((n) >> 24) & 0xff), (((n) >> 16) & 0xff), (((n) >> 8) & 0xff), (((n) >> 0) & 0xff) -#define CATCH_HANDLER_MAKE_BYTECODE(t, b, e, j) t, DECOMPOSE32(b), DECOMPOSE32(e), DECOMPOSE32(j) -#define CATCH_HANDLER_NUM_TO_BYTE(n) ((n) * sizeof(struct mrb_irep_catch_handler)) - -static void -exec_irep_prepare_posthook(mrb_state *mrb, mrb_callinfo *ci, int nregs, mrb_func_t posthook) -{ - /* - * stack: [proc, errinfo, return value by called proc] - * - * begin - * OP_NOP # A dummy instruction built in to make the catch handler react. - * ensure - * OP_EXCEPT R1 # Save the exception object. - * OP_CALL # Call a C function for the hook. - * # The stack is kept as it is in the called proc. - * # The exception will be rethrown within the hook function. - * end - */ - static const mrb_code hook_iseq[] = { - OP_NOP, - OP_EXCEPT, 1, - OP_CALL, - CATCH_HANDLER_MAKE_BYTECODE(MRB_CATCH_ENSURE, 0, 1, 1), - }; - static const mrb_irep hook_irep = { - 1, 3, 1, MRB_IREP_STATIC, hook_iseq, - NULL, NULL, NULL, NULL, NULL, - sizeof(hook_iseq) / sizeof(hook_iseq[0]) - CATCH_HANDLER_NUM_TO_BYTE(1), - 0, 0, 0, 0 - }; - static const struct RProc hook_caller = { - NULL, NULL, MRB_TT_PROC, MRB_GC_RED, MRB_FL_OBJ_IS_FROZEN, { &hook_irep }, NULL, { NULL } - }; - - struct RProc *hook = mrb_proc_new_cfunc(mrb, posthook); - int acc = 2; - memmove(ci->stack + acc, ci->stack, sizeof(mrb_value) * nregs); - ci->stack[0] = mrb_obj_value(hook); - ci->stack[1] = mrb_nil_value(); - mrb_callinfo hook_ci = { 0, 0, ci->acc, &hook_caller, ci->stack, &hook_iseq[1], { NULL } }; - ci = cipush(mrb, acc, acc, NULL, ci[0].proc, ci[0].mid, ci[0].argc); - ci->u.env = ci[-1].u.env; - ci[-1] = hook_ci; -} - -/* - * If `posthook` is given, `posthook` will be called even if an - * exception or global jump occurs in `p`. Exception or global jump objects - * are stored in `mrb->c->stack[1]` and should be rethrown in `posthook`. - * - * if (!mrb_nil_p(mrb->c->stack[1])) { - * mrb_exc_raise(mrb, mrb->c->stack[1]); - * } - * - * If you want to return the return value by `proc` as it is, please do - * `return mrb->c->stack[2]`. - * - * However, if `proc` is a C function, it will be ignored. - */ static mrb_value -exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p, mrb_func_t posthook) +exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p) { mrb_callinfo *ci = mrb->c->ci; int keep, nregs; @@ -600,17 +540,12 @@ exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p, mrb_func_t posthook) nregs = p->body.irep->nregs; if (ci->argc < 0) keep = 3; else keep = ci->argc + 2; - int extra = posthook ? (2 /* hook proc + errinfo */) : 0; if (nregs < keep) { - mrb_stack_extend(mrb, keep + extra); + mrb_stack_extend(mrb, keep); } else { - mrb_stack_extend(mrb, nregs + extra); - stack_clear(ci->stack+keep, nregs-keep + extra); - } - - if (posthook) { - exec_irep_prepare_posthook(mrb, ci, (nregs < keep ? keep : nregs), posthook); + mrb_stack_extend(mrb, nregs); + stack_clear(ci->stack+keep, nregs-keep); } cipush(mrb, 0, 0, NULL, NULL, 0, 0); @@ -619,11 +554,11 @@ exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p, mrb_func_t posthook) } mrb_value -mrb_exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p, mrb_func_t posthook) +mrb_exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p) { mrb_callinfo *ci = mrb->c->ci; if (ci->acc >= 0) { - return exec_irep(mrb, self, p, posthook); + return exec_irep(mrb, self, p); } else { mrb_value ret; @@ -706,7 +641,7 @@ mrb_f_send(mrb_state *mrb, mrb_value self) } return MRB_METHOD_CFUNC(m)(mrb, self); } - return exec_irep(mrb, self, MRB_METHOD_PROC(m), NULL); + return exec_irep(mrb, self, MRB_METHOD_PROC(m)); } static mrb_value @@ -884,7 +819,7 @@ mrb_yield_cont(mrb_state *mrb, mrb_value b, mrb_value self, mrb_int argc, const mrb->c->ci->stack[1] = mrb_ary_new_from_values(mrb, argc, argv); mrb->c->ci->stack[2] = mrb_nil_value(); ci->argc = -1; - return exec_irep(mrb, self, p, NULL); + return exec_irep(mrb, self, p); } static struct RBreak* |
