summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/mruby-eval/src
diff options
context:
space:
mode:
authordearblue <[email protected]>2021-06-26 10:52:56 +0900
committerdearblue <[email protected]>2021-06-26 13:43:36 +0900
commitc182903ea0ee5c904725f336373f608962059996 (patch)
tree9ec19890875f891f287d002664699ccdfb12318b /mrbgems/mruby-eval/src
parent5fc301f07d0ce26ab93ff237d15fa81894c9f1d6 (diff)
downloadmruby-c182903ea0ee5c904725f336373f608962059996.tar.gz
mruby-c182903ea0ee5c904725f336373f608962059996.zip
Fixed finding variables from `proc` in `binding.eval` failed
Previously the following code did not produce the expected results: ```ruby bx = binding block = bx.eval("a = 1; proc { a }") bx.eval("a = 2") p block.call # Expect 2 but return 1 due to a bug ``` The previous implementation of `Binding#eval` evaluated the code and then merged the top layer variables. This patch will parse and expand the variable space before making a call to `eval`. This means that the call to `Binding#eval` will do the parsing twice. In addition, the following changes will be made: - Make `mrb_parser_foreach_top_variable()`, `mrb_binding_extract_proc()` and `mrb_binding_extract_env()` functions private global functions. - Remove the `posthook` argument from `mrb_exec_irep()`. The `posthook` argument was introduced to implement the `binding` method. This patch is unnecessary because it uses a different implementation method. ref #5362 fixed #5491
Diffstat (limited to 'mrbgems/mruby-eval/src')
-rw-r--r--mrbgems/mruby-eval/src/eval.c47
1 files changed, 6 insertions, 41 deletions
diff --git a/mrbgems/mruby-eval/src/eval.c b/mrbgems/mruby-eval/src/eval.c
index 66f4d5283..19e4fe2ed 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*);
@@ -128,44 +128,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
@@ -177,19 +146,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
@@ -209,7 +174,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, "");
@@ -232,7 +197,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, "");