static void patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest, mrb_irep *top) { int i; uint32_t a; uint16_t b; uint8_t c; mrb_code insn; int argc = irep_argc(irep); for (i = 0; i < irep->ilen; ) { insn = irep->iseq[i]; switch(insn){ case OP_EPUSH: b = PEEK_S(irep->iseq+i+1); patch_irep(mrb, irep->reps[b], bnest + 1, top); break; case OP_LAMBDA: case OP_BLOCK: a = PEEK_B(irep->iseq+i+1); b = PEEK_B(irep->iseq+i+2); patch_irep(mrb, irep->reps[b], bnest + 1, top); break; case OP_SEND: b = PEEK_B(irep->iseq+i+2); c = PEEK_B(irep->iseq+i+3); if (c != 0) { break; } else { uint16_t arg = search_variable(mrb, irep->syms[b], bnest); if (arg != 0) { /* must replace */ irep->iseq[i] = OP_GETUPVAR; irep->iseq[i+2] = arg >> 8; irep->iseq[i+3] = arg & 0xff; } } break; case OP_MOVE: a = PEEK_B(irep->iseq+i+1); b = PEEK_B(irep->iseq+i+2); /* src part */ if (potential_upvar_p(irep->lv, b, argc, irep->nlocals)) { uint16_t arg = search_variable(mrb, irep->lv[b - 1].name, bnest); if (arg != 0) { /* must replace */ irep->iseq[i] = insn = OP_GETUPVAR; irep->iseq[i+2] = arg >> 8; irep->iseq[i+3] = arg & 0xff; } }
static void patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest, mrb_irep *top) { int i; mrb_code c; int argc = irep_argc(irep); for (i = 0; i < irep->ilen; i++) { c = irep->iseq[i]; switch(GET_OPCODE(c)){ case OP_EPUSH: patch_irep(mrb, irep->reps[GETARG_Bx(c)], bnest + 1, top); break; case OP_LAMBDA: { int arg_c = GETARG_c(c); if (arg_c & OP_L_CAPTURE) { patch_irep(mrb, irep->reps[GETARG_b(c)], bnest + 1, top); } } break; case OP_SEND: if (GETARG_C(c) != 0) { break; } else { 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; } } break; case OP_MOVE: /* src part */ 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); if (arg != 0) { /* must replace */ irep->iseq[i] = MKOPCODE(OP_GETUPVAR) | MKARG_A(GETARG_A(c)) | arg; } } /* dst part */ 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); if (arg != 0) { /* must replace */ irep->iseq[i] = MKOPCODE(OP_SETUPVAR) | MKARG_A(GETARG_B(c)) | arg; } } break; case OP_GETUPVAR: { int lev = GETARG_C(c)+1; mrb_irep *tmp = search_irep(top, bnest, lev, irep); if (potential_upvar_p(tmp->lv, GETARG_B(c), irep_argc(tmp), tmp->nlocals)) { mrb_code arg = search_variable(mrb, tmp->lv[GETARG_B(c)-1].name, bnest); if (arg != 0) { /* must replace */ irep->iseq[i] = MKOPCODE(OP_GETUPVAR) | MKARG_A(GETARG_A(c)) | arg; } } } break; case OP_SETUPVAR: { int lev = GETARG_C(c)+1; mrb_irep *tmp = search_irep(top, bnest, lev, irep); if (potential_upvar_p(tmp->lv, GETARG_B(c), irep_argc(tmp), tmp->nlocals)) { mrb_code arg = search_variable(mrb, tmp->lv[GETARG_B(c)-1].name, bnest); if (arg != 0) { /* must replace */ irep->iseq[i] = MKOPCODE(OP_SETUPVAR) | MKARG_A(GETARG_A(c)) | arg; } } } break; case OP_STOP: if (mrb->c->ci->acc >= 0) { irep->iseq[i] = MKOP_AB(OP_RETURN, irep->nlocals, OP_R_NORMAL); } break; } } }