now retrieves number of arguments of blocks from OP_ENTER op code; close #2671

parent 358dd611
...@@ -56,16 +56,11 @@ search_variable(mrb_state *mrb, mrb_sym vsym, int bnest) ...@@ -56,16 +56,11 @@ search_variable(mrb_state *mrb, mrb_sym vsym, int bnest)
} }
static mrb_bool static mrb_bool
potential_upvar_p(struct mrb_locals *lv, uint16_t v, uint16_t nlocals) potential_upvar_p(struct mrb_locals *lv, uint16_t v, int argc, uint16_t nlocals)
{ {
int i;
if (v >= nlocals) return FALSE; if (v >= nlocals) return FALSE;
/* skip arguments */ /* skip arguments */
for (i=0; i<nlocals-1; i++) { if (v < argc+1) return FALSE;
if (lv[i].name == 0)
return i < v;
}
return TRUE; return TRUE;
} }
...@@ -74,10 +69,19 @@ patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest) ...@@ -74,10 +69,19 @@ patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest)
{ {
size_t i; size_t i;
mrb_code c; mrb_code c;
int argc = 0;
for (i = 0; i < irep->ilen; i++) { for (i = 0; i < irep->ilen; i++) {
c = irep->iseq[i]; c = irep->iseq[i];
switch(GET_OPCODE(c)){ switch(GET_OPCODE(c)){
case OP_ENTER:
{
mrb_aspec ax = GETARG_Ax(i);
/* extra 1 means a slot for block */
argc = MRB_ASPEC_REQ(ax)+MRB_ASPEC_OPT(ax)+MRB_ASPEC_REST(ax)+MRB_ASPEC_POST(ax)+1;
}
break;
case OP_EPUSH: case OP_EPUSH:
patch_irep(mrb, irep->reps[GETARG_Bx(c)], bnest + 1); patch_irep(mrb, irep->reps[GETARG_Bx(c)], bnest + 1);
break; break;
...@@ -106,7 +110,7 @@ patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest) ...@@ -106,7 +110,7 @@ patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest)
case OP_MOVE: case OP_MOVE:
/* src part */ /* src part */
if (potential_upvar_p(irep->lv, GETARG_B(c), irep->nlocals)) { if (potential_upvar_p(irep->lv, GETARG_B(c), argc, irep->nlocals)) {
mrb_code arg = search_variable(mrb, irep->lv[GETARG_B(c) - 1].name, bnest); mrb_code arg = search_variable(mrb, irep->lv[GETARG_B(c) - 1].name, bnest);
if (arg != 0) { if (arg != 0) {
/* must replace */ /* must replace */
...@@ -114,7 +118,7 @@ patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest) ...@@ -114,7 +118,7 @@ patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest)
} }
} }
/* dst part */ /* dst part */
if (potential_upvar_p(irep->lv, GETARG_A(c), irep->nlocals)) { if (potential_upvar_p(irep->lv, GETARG_A(c), argc, irep->nlocals)) {
mrb_code arg = search_variable(mrb, irep->lv[GETARG_A(c) - 1].name, bnest); mrb_code arg = search_variable(mrb, irep->lv[GETARG_A(c) - 1].name, bnest);
if (arg != 0) { if (arg != 0) {
/* must replace */ /* must replace */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment