From da8d07d5d42b5a56fea8d30df816b7ee7c7da382 Mon Sep 17 00:00:00 2001 From: Miura Hideki Date: Thu, 15 May 2014 20:28:26 +0900 Subject: Suport block in Kernel#eval --- mrbgems/mruby-eval/src/eval.c | 18 +++++++++++------- mrbgems/mruby-eval/test/eval.rb | 14 ++++++++++++++ 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/mrbgems/mruby-eval/src/eval.c b/mrbgems/mruby-eval/src/eval.c index 8969722f7..78c47750b 100644 --- a/mrbgems/mruby-eval/src/eval.c +++ b/mrbgems/mruby-eval/src/eval.c @@ -26,7 +26,7 @@ get_closure_irep(mrb_state *mrb, int level) } static inline mrb_code -search_variable(mrb_state *mrb, mrb_sym vsym) +search_variable(mrb_state *mrb, mrb_sym vsym, int bnest) { mrb_irep *virep; int level; @@ -38,7 +38,7 @@ search_variable(mrb_state *mrb, mrb_sym vsym) } for (pos = 0; pos < virep->nlocals - 1; pos++) { if (vsym == virep->lv[pos].name) { - return (MKARG_B(pos + 1) | MKARG_C(level)); + return (MKARG_B(pos + 1) | MKARG_C(level + bnest)); } } } @@ -48,11 +48,15 @@ search_variable(mrb_state *mrb, mrb_sym vsym) static void -patch_irep(mrb_state *mrb, mrb_irep *irep) +patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest) { size_t i; mrb_code c; + for (i = 0; i < irep->rlen; i++) { + patch_irep(mrb, irep->reps[i], bnest + 1); + } + for (i = 0; i < irep->ilen; i++) { c = irep->iseq[i]; switch(GET_OPCODE(c)){ @@ -61,7 +65,7 @@ patch_irep(mrb_state *mrb, mrb_irep *irep) break; } { - mrb_code arg = search_variable(mrb, irep->syms[GETARG_B(c)]); + mrb_code arg = search_variable(mrb, irep->syms[GETARG_B(c)], bnest); if (arg != 0) { /* must replace */ irep->iseq[i] = MKOPCODE(OP_GETUPVAR) | MKARG_A(GETARG_A(c)) | arg; @@ -72,7 +76,7 @@ patch_irep(mrb_state *mrb, mrb_irep *irep) case OP_MOVE: /* src part */ if (GETARG_B(c) < irep->nlocals) { - mrb_code arg = search_variable(mrb, irep->lv[GETARG_B(c) - 1].name); + mrb_code arg = search_variable(mrb, irep->lv[GETARG_B(c) - 1].name, bnest); if (arg != 0) { /* must replace */ irep->iseq[i] = MKOPCODE(OP_GETUPVAR) | MKARG_A(GETARG_A(c)) | arg; @@ -80,7 +84,7 @@ patch_irep(mrb_state *mrb, mrb_irep *irep) } /* dst part */ if (GETARG_A(c) < irep->nlocals) { - mrb_code arg = search_variable(mrb, irep->lv[GETARG_A(c) - 1].name); + mrb_code arg = search_variable(mrb, irep->lv[GETARG_A(c) - 1].name, bnest); if (arg != 0) { /* must replace */ irep->iseq[i] = MKOPCODE(OP_SETUPVAR) | MKARG_A(GETARG_B(c)) | arg; @@ -131,7 +135,7 @@ create_proc_from_string(mrb_state *mrb, char *s, int len, mrb_value binding, cha e->stack = mrb->c->ci->stackent; mrb->c->ci->env = e; proc->env = e; - patch_irep(mrb, proc->body.irep); + patch_irep(mrb, proc->body.irep, 0); mrb_parser_free(p); mrbc_context_free(mrb, cxt); diff --git a/mrbgems/mruby-eval/test/eval.rb b/mrbgems/mruby-eval/test/eval.rb index 29cd3a491..115e6e358 100644 --- a/mrbgems/mruby-eval/test/eval.rb +++ b/mrbgems/mruby-eval/test/eval.rb @@ -18,6 +18,20 @@ assert('Kernel.eval') do }.call c } + assert_equal(5) { + c = 5 + lambda { + Kernel.eval 'lambda { c }.call' + }.call + } + assert_equal(15) { + c = 5 + lambda { + a = 10 + Kernel.eval 'lambda { c = a + c }.call' + }.call + c + } end assert('eval') do -- cgit v1.2.3