static void replace_stop_with_return(mrb_state *mrb, mrb_irep *irep) { if (irep->iseq[irep->ilen - 1] == MKOP_A(OP_STOP, 0)) { irep->iseq = mrb_realloc(mrb, irep->iseq, (irep->ilen + 1) * sizeof(mrb_code)); irep->iseq[irep->ilen - 1] = MKOP_A(OP_LOADNIL, 0); irep->iseq[irep->ilen] = MKOP_AB(OP_RETURN, 0, OP_R_NORMAL); irep->ilen++; } }
static mrb_value eval_context_compile(mrb_state *mrb, mrb_value self) { char *script; mrb_int script_length; mrbc_context* compile_ctx; struct mrb_parser_state *parser; struct RProc *proc; mrb_get_args(mrb, "s", &script, &script_length); compile_ctx = mrbc_context_new(mrb); if (!compile_ctx) { mrb_raise(mrb, E_RUNTIME_ERROR, "[mruby][eval][compile] failed to allocate context"); } compile_ctx->capture_errors = TRUE; parser = mrb_parse_nstring(mrb, script, script_length, compile_ctx); if (!parser) { mrbc_context_free(mrb, compile_ctx); mrb_raise(mrb, E_RUNTIME_ERROR, "[mruby][eval][compile] failed to allocate parser"); } if (parser->nerr > 0) { struct mrb_parser_message *error = &(parser->error_buffer[0]); mrb_value new_args[1]; mrb_value exception; new_args[0] = mrb_format(mrb, "line %S:%S: %S", mrb_fixnum_value(error->lineno), mrb_fixnum_value(error->column), mrb_str_new_cstr(mrb, error->message)); exception = mrb_obj_new(mrb, E_SYNTAX_ERROR, 1, new_args); mrb_parser_free(parser); mrbc_context_free(mrb, compile_ctx); mrb_exc_raise(mrb, exception); } proc = mrb_generate_code(mrb, parser); { mrb_code *iseq = proc->body.irep->iseq; while (GET_OPCODE(*iseq) != OP_STOP) { iseq++; } *iseq = MKOP_AB(OP_RETURN, 1, OP_R_NORMAL); } mrb_parser_free(parser); mrbc_context_free(mrb, compile_ctx); return mrb_obj_value(proc); }
static void replace_stop_with_return(mrb_state *mrb, mrb_irep *irep) { if (irep->iseq[irep->ilen - 1] == MKOP_A(OP_STOP, 0)) { if (irep->flags == MRB_ISEQ_NO_FREE) { mrb_code* iseq = (mrb_code *)mrb_malloc(mrb, (irep->ilen + 1) * sizeof(mrb_code)); memcpy(iseq, irep->iseq, irep->ilen * sizeof(mrb_code)); irep->iseq = iseq; irep->flags &= ~MRB_ISEQ_NO_FREE; } else { irep->iseq = (mrb_code *)mrb_realloc(mrb, irep->iseq, (irep->ilen + 1) * sizeof(mrb_code)); } irep->iseq[irep->ilen - 1] = MKOP_A(OP_LOADNIL, 0); irep->iseq[irep->ilen] = MKOP_AB(OP_RETURN, 0, OP_R_NORMAL); irep->ilen++; } }
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; } } }