summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2021-06-28 09:13:54 +0900
committerGitHub <[email protected]>2021-06-28 09:13:54 +0900
commitd63c0df6bcd5851522c4b982dba4e0a93f44a2d7 (patch)
tree83c1d2a39786d802d3d09da6d5a4be56d9fe12c2
parente462b42ff05254f8142662c24b426b5af3b98173 (diff)
parentc182903ea0ee5c904725f336373f608962059996 (diff)
downloadmruby-d63c0df6bcd5851522c4b982dba4e0a93f44a2d7.tar.gz
mruby-d63c0df6bcd5851522c4b982dba4e0a93f44a2d7.zip
Merge pull request #5493 from dearblue/binding.2
Fixed finding variables from `proc` in `binding.eval` failed
-rw-r--r--mrbgems/mruby-binding-core/src/binding-core.c22
-rw-r--r--mrbgems/mruby-binding/mrblib/binding.rb5
-rw-r--r--mrbgems/mruby-binding/src/binding.c173
-rw-r--r--mrbgems/mruby-binding/test/binding.rb7
-rw-r--r--mrbgems/mruby-compiler/core/parse.y16
-rw-r--r--mrbgems/mruby-compiler/core/y.tab.c16
-rw-r--r--mrbgems/mruby-eval/src/eval.c47
-rw-r--r--mrbgems/mruby-method/src/method.c4
-rw-r--r--src/proc.c9
-rw-r--r--src/vm.c81
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);
diff --git a/src/vm.c b/src/vm.c
index a6211c118..877057bd6 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -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*