mbed I/F binding for mruby
Dependents: mruby_mbed_web mirb_mbed
codegen.c
00001 /* 00002 ** codegen.c - mruby code generator 00003 ** 00004 ** See Copyright Notice in mruby.h 00005 */ 00006 00007 #include <ctype.h> 00008 #include <limits.h> 00009 #include <stdlib.h> 00010 #include <string.h> 00011 #include "mruby.h" 00012 #include "mruby/compile.h" 00013 #include "mruby/proc.h" 00014 #include "mruby/numeric.h" 00015 #include "mruby/string.h" 00016 #include "mruby/debug.h" 00017 #include "node.h" 00018 #include "mruby/opcode.h" 00019 #include "mruby/re.h" 00020 #include "mrb_throw.h" 00021 00022 typedef mrb_ast_node node; 00023 typedef struct mrb_parser_state parser_state; 00024 00025 enum looptype { 00026 LOOP_NORMAL, 00027 LOOP_BLOCK, 00028 LOOP_FOR, 00029 LOOP_BEGIN, 00030 LOOP_RESCUE, 00031 }; 00032 00033 struct loopinfo { 00034 enum looptype type; 00035 int pc1, pc2, pc3, acc; 00036 int ensure_level; 00037 struct loopinfo *prev; 00038 }; 00039 00040 typedef struct scope { 00041 mrb_state *mrb; 00042 mrb_pool *mpool; 00043 struct mrb_jmpbuf jmp; 00044 00045 struct scope *prev; 00046 00047 node *lv; 00048 00049 int sp; 00050 int pc; 00051 int lastlabel; 00052 int ainfo:15; 00053 mrb_bool mscope:1; 00054 00055 struct loopinfo *loop; 00056 int ensure_level; 00057 char const *filename; 00058 uint16_t lineno; 00059 00060 mrb_code *iseq; 00061 uint16_t *lines; 00062 int icapa; 00063 00064 mrb_irep *irep; 00065 size_t pcapa; 00066 size_t scapa; 00067 size_t rcapa; 00068 00069 uint16_t nlocals; 00070 uint16_t nregs; 00071 int ai; 00072 00073 int debug_start_pos; 00074 uint16_t filename_index; 00075 parser_state* parser; 00076 } codegen_scope; 00077 00078 static codegen_scope* scope_new(mrb_state *mrb, codegen_scope *prev, node *lv); 00079 static void scope_finish(codegen_scope *s); 00080 static struct loopinfo *loop_push(codegen_scope *s, enum looptype t); 00081 static void loop_break(codegen_scope *s, node *tree); 00082 static void loop_pop(codegen_scope *s, int val); 00083 00084 static void gen_assignment(codegen_scope *s, node *tree, int sp, int val); 00085 static void gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val); 00086 00087 static void codegen(codegen_scope *s, node *tree, int val); 00088 static void raise_error(codegen_scope *s, const char *msg); 00089 00090 static void 00091 codegen_error(codegen_scope *s, const char *message) 00092 { 00093 if (!s) return; 00094 while (s->prev) { 00095 codegen_scope *tmp = s->prev; 00096 mrb_pool_close(s->mpool); 00097 s = tmp; 00098 } 00099 #ifdef ENABLE_STDIO 00100 if (s->filename && s->lineno) { 00101 fprintf(stderr, "codegen error:%s:%d: %s\n", s->filename, s->lineno, message); 00102 } 00103 else { 00104 fprintf(stderr, "codegen error: %s\n", message); 00105 } 00106 #endif 00107 MRB_THROW(&s->jmp); 00108 } 00109 00110 static void* 00111 codegen_palloc(codegen_scope *s, size_t len) 00112 { 00113 void *p = mrb_pool_alloc(s->mpool, len); 00114 00115 if (!p) codegen_error(s, "pool memory allocation"); 00116 return p; 00117 } 00118 00119 static void* 00120 codegen_malloc(codegen_scope *s, size_t len) 00121 { 00122 void *p = mrb_malloc_simple(s->mrb, len); 00123 00124 if (!p) codegen_error(s, "mrb_malloc"); 00125 return p; 00126 } 00127 00128 static void* 00129 codegen_realloc(codegen_scope *s, void *p, size_t len) 00130 { 00131 p = mrb_realloc_simple(s->mrb, p, len); 00132 00133 if (!p && len > 0) codegen_error(s, "mrb_realloc"); 00134 return p; 00135 } 00136 00137 static int 00138 new_label(codegen_scope *s) 00139 { 00140 s->lastlabel = s->pc; 00141 return s->pc; 00142 } 00143 00144 static inline int 00145 genop(codegen_scope *s, mrb_code i) 00146 { 00147 if (s->pc == s->icapa) { 00148 s->icapa *= 2; 00149 s->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->icapa); 00150 if (s->lines) { 00151 s->lines = (uint16_t*)codegen_realloc(s, s->lines, sizeof(short)*s->icapa); 00152 s->irep->lines = s->lines; 00153 } 00154 } 00155 s->iseq[s->pc] = i; 00156 if (s->lines) { 00157 s->lines[s->pc] = s->lineno; 00158 } 00159 return s->pc++; 00160 } 00161 00162 #define NOVAL 0 00163 #define VAL 1 00164 00165 static mrb_bool 00166 no_optimize(codegen_scope *s) 00167 { 00168 if (s && s->parser && s->parser->no_optimize) 00169 return TRUE; 00170 return FALSE; 00171 } 00172 00173 static int 00174 genop_peep(codegen_scope *s, mrb_code i, int val) 00175 { 00176 /* peephole optimization */ 00177 if (!no_optimize(s) && s->lastlabel != s->pc && s->pc > 0) { 00178 mrb_code i0 = s->iseq[s->pc-1]; 00179 int c1 = GET_OPCODE(i); 00180 int c0 = GET_OPCODE(i0); 00181 00182 switch (c1) { 00183 case OP_MOVE: 00184 if (GETARG_A(i) == GETARG_B(i)) { 00185 /* skip useless OP_MOVE */ 00186 return 0; 00187 } 00188 if (val) break; 00189 switch (c0) { 00190 case OP_MOVE: 00191 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i) == GETARG_B(i0)) { 00192 /* skip swapping OP_MOVE */ 00193 return 0; 00194 } 00195 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) { 00196 s->pc--; 00197 return genop_peep(s, MKOP_AB(OP_MOVE, GETARG_A(i), GETARG_B(i0)), val); 00198 } 00199 break; 00200 case OP_LOADI: 00201 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) { 00202 s->iseq[s->pc-1] = MKOP_AsBx(OP_LOADI, GETARG_A(i), GETARG_sBx(i0)); 00203 return 0; 00204 } 00205 break; 00206 case OP_ARRAY: 00207 case OP_HASH: 00208 case OP_RANGE: 00209 case OP_AREF: 00210 case OP_GETUPVAR: 00211 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) { 00212 s->iseq[s->pc-1] = MKOP_ABC(c0, GETARG_A(i), GETARG_B(i0), GETARG_C(i0)); 00213 return 0; 00214 } 00215 break; 00216 case OP_LOADSYM: 00217 case OP_GETGLOBAL: 00218 case OP_GETIV: 00219 case OP_GETCV: 00220 case OP_GETCONST: 00221 case OP_GETSPECIAL: 00222 case OP_LOADL: 00223 case OP_STRING: 00224 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) { 00225 s->iseq[s->pc-1] = MKOP_ABx(c0, GETARG_A(i), GETARG_Bx(i0)); 00226 return 0; 00227 } 00228 break; 00229 case OP_SCLASS: 00230 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) { 00231 s->iseq[s->pc-1] = MKOP_AB(c0, GETARG_A(i), GETARG_B(i0)); 00232 return 0; 00233 } 00234 break; 00235 case OP_LOADNIL: 00236 case OP_LOADSELF: 00237 case OP_LOADT: 00238 case OP_LOADF: 00239 case OP_OCLASS: 00240 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) { 00241 s->iseq[s->pc-1] = MKOP_A(c0, GETARG_A(i)); 00242 return 0; 00243 } 00244 break; 00245 default: 00246 break; 00247 } 00248 break; 00249 case OP_SETIV: 00250 case OP_SETCV: 00251 case OP_SETCONST: 00252 case OP_SETMCNST: 00253 case OP_SETGLOBAL: 00254 if (val) break; 00255 if (c0 == OP_MOVE) { 00256 if (GETARG_A(i) == GETARG_A(i0)) { 00257 s->iseq[s->pc-1] = MKOP_ABx(c1, GETARG_B(i0), GETARG_Bx(i)); 00258 return 0; 00259 } 00260 } 00261 break; 00262 case OP_SETUPVAR: 00263 if (val) break; 00264 if (c0 == OP_MOVE) { 00265 if (GETARG_A(i) == GETARG_A(i0)) { 00266 s->iseq[s->pc-1] = MKOP_ABC(c1, GETARG_B(i0), GETARG_B(i), GETARG_C(i)); 00267 return 0; 00268 } 00269 } 00270 break; 00271 case OP_EPOP: 00272 if (c0 == OP_EPOP) { 00273 s->iseq[s->pc-1] = MKOP_A(OP_EPOP, GETARG_A(i0)+GETARG_A(i)); 00274 return 0; 00275 } 00276 break; 00277 case OP_POPERR: 00278 if (c0 == OP_POPERR) { 00279 s->iseq[s->pc-1] = MKOP_A(OP_POPERR, GETARG_A(i0)+GETARG_A(i)); 00280 return 0; 00281 } 00282 break; 00283 case OP_RETURN: 00284 switch (c0) { 00285 case OP_RETURN: 00286 return 0; 00287 case OP_MOVE: 00288 if (GETARG_A(i0) >= s->nlocals) { 00289 s->iseq[s->pc-1] = MKOP_AB(OP_RETURN, GETARG_B(i0), OP_R_NORMAL); 00290 return 0; 00291 } 00292 break; 00293 case OP_SETIV: 00294 case OP_SETCV: 00295 case OP_SETCONST: 00296 case OP_SETMCNST: 00297 case OP_SETUPVAR: 00298 case OP_SETGLOBAL: 00299 s->pc--; 00300 genop_peep(s, i0, NOVAL); 00301 i0 = s->iseq[s->pc-1]; 00302 return genop(s, MKOP_AB(OP_RETURN, GETARG_A(i0), OP_R_NORMAL)); 00303 #if 0 00304 case OP_SEND: 00305 if (GETARG_B(i) == OP_R_NORMAL && GETARG_A(i) == GETARG_A(i0)) { 00306 s->iseq[s->pc-1] = MKOP_ABC(OP_TAILCALL, GETARG_A(i0), GETARG_B(i0), GETARG_C(i0)); 00307 return; 00308 } 00309 break; 00310 #endif 00311 default: 00312 break; 00313 } 00314 break; 00315 case OP_ADD: 00316 case OP_SUB: 00317 if (c0 == OP_LOADI) { 00318 int c = GETARG_sBx(i0); 00319 00320 if (c1 == OP_SUB) c = -c; 00321 if (c > 127 || c < -127) break; 00322 if (0 <= c) 00323 s->iseq[s->pc-1] = MKOP_ABC(OP_ADDI, GETARG_A(i), GETARG_B(i), c); 00324 else 00325 s->iseq[s->pc-1] = MKOP_ABC(OP_SUBI, GETARG_A(i), GETARG_B(i), -c); 00326 return 0; 00327 } 00328 case OP_STRCAT: 00329 if (c0 == OP_STRING) { 00330 mrb_value v = s->irep->pool[GETARG_Bx(i0)]; 00331 00332 if (mrb_string_p(v) && RSTRING_LEN(v) == 0) { 00333 s->pc--; 00334 return 0; 00335 } 00336 } 00337 break; 00338 case OP_JMPIF: 00339 case OP_JMPNOT: 00340 if (c0 == OP_MOVE && GETARG_A(i) == GETARG_A(i0)) { 00341 s->iseq[s->pc-1] = MKOP_AsBx(c1, GETARG_B(i0), GETARG_sBx(i)); 00342 return s->pc-1; 00343 } 00344 break; 00345 default: 00346 break; 00347 } 00348 } 00349 return genop(s, i); 00350 } 00351 00352 static void 00353 scope_error(codegen_scope *s) 00354 { 00355 exit(EXIT_FAILURE); 00356 } 00357 00358 static inline void 00359 dispatch(codegen_scope *s, int pc) 00360 { 00361 int diff = s->pc - pc; 00362 mrb_code i = s->iseq[pc]; 00363 int c = GET_OPCODE(i); 00364 00365 s->lastlabel = s->pc; 00366 switch (c) { 00367 case OP_JMP: 00368 case OP_JMPIF: 00369 case OP_JMPNOT: 00370 case OP_ONERR: 00371 break; 00372 default: 00373 #ifdef ENABLE_STDIO 00374 fprintf(stderr, "bug: dispatch on non JMP op\n"); 00375 #endif 00376 scope_error(s); 00377 break; 00378 } 00379 s->iseq[pc] = MKOP_AsBx(c, GETARG_A(i), diff); 00380 } 00381 00382 static void 00383 dispatch_linked(codegen_scope *s, int pc) 00384 { 00385 mrb_code i; 00386 int pos; 00387 00388 if (!pc) return; 00389 for (;;) { 00390 i = s->iseq[pc]; 00391 pos = GETARG_sBx(i); 00392 dispatch(s, pc); 00393 if (!pos) break; 00394 pc = pos; 00395 } 00396 } 00397 00398 #define nregs_update do {if (s->sp > s->nregs) s->nregs = s->sp;} while (0) 00399 static void 00400 push_(codegen_scope *s) 00401 { 00402 if (s->sp > 511) { 00403 codegen_error(s, "too complex expression"); 00404 } 00405 s->sp++; 00406 nregs_update; 00407 } 00408 00409 #define push() push_(s) 00410 #define pop_(s) ((s)->sp--) 00411 #define pop() pop_(s) 00412 #define pop_n(n) (s->sp-=(n)) 00413 #define cursp() (s->sp) 00414 00415 static inline int 00416 new_lit(codegen_scope *s, mrb_value val) 00417 { 00418 size_t i; 00419 mrb_value *pv; 00420 00421 switch (mrb_type(val)) { 00422 case MRB_TT_STRING: 00423 for (i=0; i<s->irep->plen; i++) { 00424 mrb_int len; 00425 pv = &s->irep->pool[i]; 00426 00427 if (mrb_type(*pv) != MRB_TT_STRING) continue; 00428 if ((len = RSTRING_LEN(*pv)) != RSTRING_LEN(val)) continue; 00429 if (memcmp(RSTRING_PTR(*pv), RSTRING_PTR(val), len) == 0) 00430 return i; 00431 } 00432 break; 00433 case MRB_TT_FLOAT: 00434 for (i=0; i<s->irep->plen; i++) { 00435 pv = &s->irep->pool[i]; 00436 if (mrb_type(*pv) != MRB_TT_FLOAT) continue; 00437 if (mrb_float(*pv) == mrb_float(val)) return i; 00438 } 00439 break; 00440 case MRB_TT_FIXNUM: 00441 for (i=0; i<s->irep->plen; i++) { 00442 pv = &s->irep->pool[i]; 00443 if (!mrb_fixnum_p(*pv)) continue; 00444 if (mrb_fixnum(*pv) == mrb_fixnum(val)) return i; 00445 } 00446 break; 00447 default: 00448 /* should not happen */ 00449 return 0; 00450 } 00451 00452 if (s->irep->plen == s->pcapa) { 00453 s->pcapa *= 2; 00454 s->irep->pool = (mrb_value *)codegen_realloc(s, s->irep->pool, sizeof(mrb_value)*s->pcapa); 00455 } 00456 00457 pv = &s->irep->pool[s->irep->plen]; 00458 i = s->irep->plen++; 00459 00460 switch (mrb_type(val)) { 00461 case MRB_TT_STRING: 00462 *pv = mrb_str_pool(s->mrb, val); 00463 break; 00464 00465 case MRB_TT_FLOAT: 00466 #ifdef MRB_WORD_BOXING 00467 *pv = mrb_float_pool(s->mrb, mrb_float(val)); 00468 break; 00469 #endif 00470 case MRB_TT_FIXNUM: 00471 *pv = val; 00472 break; 00473 00474 default: 00475 /* should not happen */ 00476 break; 00477 } 00478 return i; 00479 } 00480 00481 static inline int 00482 new_msym(codegen_scope *s, mrb_sym sym) 00483 { 00484 size_t i, len; 00485 00486 mrb_assert(s->irep); 00487 00488 len = s->irep->slen; 00489 if (len > 256) len = 256; 00490 for (i=0; i<len; i++) { 00491 if (s->irep->syms[i] == sym) return i; 00492 if (s->irep->syms[i] == 0) break; 00493 } 00494 if (i == 256) { 00495 codegen_error(s, "too many symbols (max 256)"); 00496 } 00497 s->irep->syms[i] = sym; 00498 if (i == s->irep->slen) s->irep->slen++; 00499 return i; 00500 } 00501 00502 static inline int 00503 new_sym(codegen_scope *s, mrb_sym sym) 00504 { 00505 size_t i; 00506 00507 for (i=0; i<s->irep->slen; i++) { 00508 if (s->irep->syms[i] == sym) return i; 00509 } 00510 if (s->irep->slen > 125 && s->irep->slen < 256) { 00511 s->irep->syms = (mrb_sym *)codegen_realloc(s, s->irep->syms, sizeof(mrb_sym)*65536); 00512 for (i = 0; i < 256 - s->irep->slen; i++) { 00513 static const mrb_sym mrb_sym_zero = { 0 }; 00514 s->irep->syms[i + s->irep->slen] = mrb_sym_zero; 00515 } 00516 s->irep->slen = 256; 00517 } 00518 s->irep->syms[s->irep->slen] = sym; 00519 return s->irep->slen++; 00520 } 00521 00522 static int 00523 node_len(node *tree) 00524 { 00525 int n = 0; 00526 00527 while (tree) { 00528 n++; 00529 tree = tree->cdr; 00530 } 00531 return n; 00532 } 00533 00534 #define sym(x) ((mrb_sym)(intptr_t)(x)) 00535 #define lv_name(lv) sym((lv)->car) 00536 static int 00537 lv_idx(codegen_scope *s, mrb_sym id) 00538 { 00539 node *lv = s->lv; 00540 int n = 1; 00541 00542 while (lv) { 00543 if (lv_name(lv) == id) return n; 00544 n++; 00545 lv = lv->cdr; 00546 } 00547 return 0; 00548 } 00549 00550 static void 00551 for_body(codegen_scope *s, node *tree) 00552 { 00553 codegen_scope *prev = s; 00554 int idx; 00555 struct loopinfo *lp; 00556 node *n2; 00557 mrb_code c; 00558 00559 /* generate receiver */ 00560 codegen(s, tree->cdr->car, VAL); 00561 /* generate loop-block */ 00562 s = scope_new(s->mrb, s, NULL); 00563 if (s == NULL) { 00564 raise_error(prev, "unexpected scope"); 00565 } 00566 00567 push(); /* push for a block parameter */ 00568 00569 lp = loop_push(s, LOOP_FOR); 00570 lp->pc1 = new_label(s); 00571 00572 /* generate loop variable */ 00573 n2 = tree->car; 00574 genop(s, MKOP_Ax(OP_ENTER, 0x40000)); 00575 if (n2->car && !n2->car->cdr && !n2->cdr) { 00576 gen_assignment(s, n2->car->car, 1, NOVAL); 00577 } 00578 else { 00579 gen_vmassignment(s, n2, 1, VAL); 00580 } 00581 codegen(s, tree->cdr->cdr->car, VAL); 00582 pop(); 00583 if (s->pc > 0) { 00584 c = s->iseq[s->pc-1]; 00585 if (GET_OPCODE(c) != OP_RETURN || GETARG_B(c) != OP_R_NORMAL || s->pc == s->lastlabel) 00586 genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL); 00587 } 00588 loop_pop(s, NOVAL); 00589 scope_finish(s); 00590 s = prev; 00591 genop(s, MKOP_Abc(OP_LAMBDA, cursp(), s->irep->rlen-1, OP_L_BLOCK)); 00592 pop(); 00593 idx = new_msym(s, mrb_intern_lit(s->mrb, "each")); 00594 genop(s, MKOP_ABC(OP_SENDB, cursp(), idx, 0)); 00595 } 00596 00597 static int 00598 lambda_body(codegen_scope *s, node *tree, int blk) 00599 { 00600 mrb_code c; 00601 codegen_scope *parent = s; 00602 s = scope_new(s->mrb, s, tree->car); 00603 if (s == NULL) { 00604 raise_error(parent, "unexpected scope"); 00605 } 00606 00607 s->mscope = !blk; 00608 00609 if (blk) { 00610 struct loopinfo *lp = loop_push(s, LOOP_BLOCK); 00611 lp->pc1 = new_label(s); 00612 } 00613 tree = tree->cdr; 00614 if (tree->car) { 00615 mrb_aspec a; 00616 int ma, oa, ra, pa, ka, kd, ba; 00617 int pos, i; 00618 node *n, *opt; 00619 00620 ma = node_len(tree->car->car); 00621 n = tree->car->car; 00622 while (n) { 00623 n = n->cdr; 00624 } 00625 oa = node_len(tree->car->cdr->car); 00626 ra = tree->car->cdr->cdr->car ? 1 : 0; 00627 pa = node_len(tree->car->cdr->cdr->cdr->car); 00628 ka = kd = 0; 00629 ba = tree->car->cdr->cdr->cdr->cdr ? 1 : 0; 00630 00631 a = ((mrb_aspec)(ma & 0x1f) << 18) 00632 | ((mrb_aspec)(oa & 0x1f) << 13) 00633 | ((ra & 1) << 12) 00634 | ((pa & 0x1f) << 7) 00635 | ((ka & 0x1f) << 2) 00636 | ((kd & 1)<< 1) 00637 | (ba & 1); 00638 s->ainfo = (((ma+oa) & 0x3f) << 6) /* (12bits = 6:1:5) */ 00639 | ((ra & 1) << 5) 00640 | (pa & 0x1f); 00641 genop(s, MKOP_Ax(OP_ENTER, a)); 00642 pos = new_label(s); 00643 for (i=0; i<oa; i++) { 00644 new_label(s); 00645 genop(s, MKOP_sBx(OP_JMP, 0)); 00646 } 00647 if (oa > 0) { 00648 genop(s, MKOP_sBx(OP_JMP, 0)); 00649 } 00650 opt = tree->car->cdr->car; 00651 i = 0; 00652 while (opt) { 00653 int idx; 00654 00655 dispatch(s, pos+i); 00656 codegen(s, opt->car->cdr, VAL); 00657 idx = lv_idx(s, (mrb_sym)(intptr_t)opt->car->car); 00658 pop(); 00659 genop_peep(s, MKOP_AB(OP_MOVE, idx, cursp()), NOVAL); 00660 i++; 00661 opt = opt->cdr; 00662 } 00663 if (oa > 0) { 00664 dispatch(s, pos+i); 00665 } 00666 } 00667 codegen(s, tree->cdr->car, VAL); 00668 pop(); 00669 if (s->pc > 0) { 00670 c = s->iseq[s->pc-1]; 00671 if (GET_OPCODE(c) != OP_RETURN || GETARG_B(c) != OP_R_NORMAL || s->pc == s->lastlabel) { 00672 if (s->nregs == 0) { 00673 genop(s, MKOP_A(OP_LOADNIL, 0)); 00674 genop(s, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL)); 00675 } 00676 else { 00677 genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL); 00678 } 00679 } 00680 } 00681 if (blk) { 00682 loop_pop(s, NOVAL); 00683 } 00684 scope_finish(s); 00685 return parent->irep->rlen - 1; 00686 } 00687 00688 static int 00689 scope_body(codegen_scope *s, node *tree, int val) 00690 { 00691 codegen_scope *scope = scope_new(s->mrb, s, tree->car); 00692 if (scope == NULL) { 00693 raise_error(s, "unexpected scope"); 00694 } 00695 00696 codegen(scope, tree->cdr, VAL); 00697 if (!s->iseq) { 00698 genop(scope, MKOP_A(OP_STOP, 0)); 00699 } 00700 else if (!val) { 00701 genop(scope, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL)); 00702 } 00703 else { 00704 if (scope->nregs == 0) { 00705 genop(scope, MKOP_A(OP_LOADNIL, 0)); 00706 genop(scope, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL)); 00707 } 00708 else { 00709 genop_peep(scope, MKOP_AB(OP_RETURN, scope->sp-1, OP_R_NORMAL), NOVAL); 00710 } 00711 } 00712 scope_finish(scope); 00713 if (!s->irep) { 00714 /* should not happen */ 00715 return 0; 00716 } 00717 return s->irep->rlen - 1; 00718 } 00719 00720 static mrb_bool 00721 nosplat(node *t) 00722 { 00723 while (t) { 00724 if ((intptr_t)t->car->car == NODE_SPLAT) return FALSE; 00725 t = t->cdr; 00726 } 00727 return TRUE; 00728 } 00729 00730 static mrb_sym 00731 attrsym(codegen_scope *s, mrb_sym a) 00732 { 00733 const char *name; 00734 mrb_int len; 00735 char *name2; 00736 00737 name = mrb_sym2name_len(s->mrb, a, &len); 00738 name2 = (char *)codegen_palloc(s, 00739 (size_t)len 00740 + 1 /* '=' */ 00741 + 1 /* '\0' */ 00742 ); 00743 mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX); 00744 memcpy(name2, name, (size_t)len); 00745 name2[len] = '='; 00746 name2[len+1] = '\0'; 00747 00748 return mrb_intern(s->mrb, name2, len+1); 00749 } 00750 00751 static int 00752 gen_values(codegen_scope *s, node *t, int val) 00753 { 00754 int n = 0; 00755 int is_splat; 00756 00757 while (t) { 00758 is_splat = (intptr_t)t->car->car == NODE_SPLAT; /* splat mode */ 00759 if (n >= 127 || is_splat) { 00760 if (val) { 00761 pop_n(n); 00762 genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), n)); 00763 push(); 00764 codegen(s, t->car, VAL); 00765 pop(); pop(); 00766 if (is_splat) { 00767 genop(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1)); 00768 } 00769 else { 00770 genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1)); 00771 } 00772 t = t->cdr; 00773 while (t) { 00774 push(); 00775 codegen(s, t->car, VAL); 00776 pop(); pop(); 00777 if ((intptr_t)t->car->car == NODE_SPLAT) { 00778 genop(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1)); 00779 } 00780 else { 00781 genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1)); 00782 } 00783 t = t->cdr; 00784 } 00785 } 00786 else { 00787 codegen(s, t->car->cdr, NOVAL); 00788 t = t->cdr; 00789 while (t) { 00790 codegen(s, t->car, NOVAL); 00791 t = t->cdr; 00792 } 00793 } 00794 return -1; 00795 } 00796 /* normal (no splat) mode */ 00797 codegen(s, t->car, val); 00798 n++; 00799 t = t->cdr; 00800 } 00801 return n; 00802 } 00803 00804 #define CALL_MAXARGS 127 00805 00806 static void 00807 gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val) 00808 { 00809 mrb_sym sym = name ? name : sym(tree->cdr->car); 00810 int idx; 00811 int n = 0, noop = 0, sendv = 0, blk = 0; 00812 00813 codegen(s, tree->car, VAL); /* receiver */ 00814 idx = new_msym(s, sym); 00815 tree = tree->cdr->cdr->car; 00816 if (tree) { 00817 n = gen_values(s, tree->car, VAL); 00818 if (n < 0) { 00819 n = noop = sendv = 1; 00820 push(); 00821 } 00822 } 00823 if (sp) { 00824 if (sendv) { 00825 pop(); 00826 genop(s, MKOP_AB(OP_ARYPUSH, cursp(), sp)); 00827 push(); 00828 } 00829 else { 00830 genop(s, MKOP_AB(OP_MOVE, cursp(), sp)); 00831 push(); 00832 n++; 00833 } 00834 } 00835 if (tree && tree->cdr) { 00836 noop = 1; 00837 codegen(s, tree->cdr, VAL); 00838 pop(); 00839 } 00840 else { 00841 blk = cursp(); 00842 } 00843 push();pop(); 00844 pop_n(n+1); 00845 { 00846 mrb_int symlen; 00847 const char *symname = mrb_sym2name_len(s->mrb, sym, &symlen); 00848 00849 if (!noop && symlen == 1 && symname[0] == '+') { 00850 genop_peep(s, MKOP_ABC(OP_ADD, cursp(), idx, n), val); 00851 } 00852 else if (!noop && symlen == 1 && symname[0] == '-') { 00853 genop_peep(s, MKOP_ABC(OP_SUB, cursp(), idx, n), val); 00854 } 00855 else if (!noop && symlen == 1 && symname[0] == '*') { 00856 genop(s, MKOP_ABC(OP_MUL, cursp(), idx, n)); 00857 } 00858 else if (!noop && symlen == 1 && symname[0] == '/') { 00859 genop(s, MKOP_ABC(OP_DIV, cursp(), idx, n)); 00860 } 00861 else if (!noop && symlen == 1 && symname[0] == '<') { 00862 genop(s, MKOP_ABC(OP_LT, cursp(), idx, n)); 00863 } 00864 else if (!noop && symlen == 2 && symname[0] == '<' && symname[1] == '=') { 00865 genop(s, MKOP_ABC(OP_LE, cursp(), idx, n)); 00866 } 00867 else if (!noop && symlen == 1 && symname[0] == '>') { 00868 genop(s, MKOP_ABC(OP_GT, cursp(), idx, n)); 00869 } 00870 else if (!noop && symlen == 2 && symname[0] == '>' && symname[1] == '=') { 00871 genop(s, MKOP_ABC(OP_GE, cursp(), idx, n)); 00872 } 00873 else if (!noop && symlen == 2 && symname[0] == '=' && symname[1] == '=') { 00874 genop(s, MKOP_ABC(OP_EQ, cursp(), idx, n)); 00875 } 00876 else { 00877 if (sendv) n = CALL_MAXARGS; 00878 if (blk > 0) { /* no block */ 00879 genop(s, MKOP_ABC(OP_SEND, cursp(), idx, n)); 00880 } 00881 else { 00882 genop(s, MKOP_ABC(OP_SENDB, cursp(), idx, n)); 00883 } 00884 } 00885 } 00886 if (val) { 00887 push(); 00888 } 00889 } 00890 00891 static void 00892 gen_assignment(codegen_scope *s, node *tree, int sp, int val) 00893 { 00894 int idx; 00895 int type = (intptr_t)tree->car; 00896 00897 tree = tree->cdr; 00898 switch ((intptr_t)type) { 00899 case NODE_GVAR: 00900 idx = new_sym(s, sym(tree)); 00901 genop_peep(s, MKOP_ABx(OP_SETGLOBAL, sp, idx), val); 00902 break; 00903 case NODE_LVAR: 00904 idx = lv_idx(s, sym(tree)); 00905 if (idx > 0) { 00906 if (idx != sp) { 00907 genop_peep(s, MKOP_AB(OP_MOVE, idx, sp), val); 00908 } 00909 break; 00910 } 00911 else { /* upvar */ 00912 int lv = 0; 00913 codegen_scope *up = s->prev; 00914 00915 while (up) { 00916 idx = lv_idx(up, sym(tree)); 00917 if (idx > 0) { 00918 genop_peep(s, MKOP_ABC(OP_SETUPVAR, sp, idx, lv), val); 00919 break; 00920 } 00921 lv++; 00922 up = up->prev; 00923 } 00924 } 00925 break; 00926 case NODE_IVAR: 00927 idx = new_sym(s, sym(tree)); 00928 genop_peep(s, MKOP_ABx(OP_SETIV, sp, idx), val); 00929 break; 00930 case NODE_CVAR: 00931 idx = new_sym(s, sym(tree)); 00932 genop_peep(s, MKOP_ABx(OP_SETCV, sp, idx), val); 00933 break; 00934 case NODE_CONST: 00935 idx = new_sym(s, sym(tree)); 00936 genop_peep(s, MKOP_ABx(OP_SETCONST, sp, idx), val); 00937 break; 00938 case NODE_COLON2: 00939 idx = new_sym(s, sym(tree->cdr)); 00940 genop_peep(s, MKOP_AB(OP_MOVE, cursp(), sp), NOVAL); 00941 push(); 00942 codegen(s, tree->car, VAL); 00943 pop_n(2); 00944 genop_peep(s, MKOP_ABx(OP_SETMCNST, cursp(), idx), val); 00945 break; 00946 00947 case NODE_CALL: 00948 push(); 00949 gen_call(s, tree, attrsym(s, sym(tree->cdr->car)), sp, NOVAL); 00950 pop(); 00951 if (val) { 00952 genop_peep(s, MKOP_AB(OP_MOVE, cursp(), sp), val); 00953 } 00954 break; 00955 00956 default: 00957 #ifdef ENABLE_STDIO 00958 printf("unknown lhs %d\n", type); 00959 #endif 00960 break; 00961 } 00962 if (val) push(); 00963 } 00964 00965 static void 00966 gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val) 00967 { 00968 int n = 0, post = 0; 00969 node *t, *p; 00970 00971 if (tree->car) { /* pre */ 00972 t = tree->car; 00973 n = 0; 00974 while (t) { 00975 genop(s, MKOP_ABC(OP_AREF, cursp(), rhs, n)); 00976 gen_assignment(s, t->car, cursp(), NOVAL); 00977 n++; 00978 t = t->cdr; 00979 } 00980 } 00981 t = tree->cdr; 00982 if (t) { 00983 if (t->cdr) { /* post count */ 00984 p = t->cdr->car; 00985 while (p) { 00986 post++; 00987 p = p->cdr; 00988 } 00989 } 00990 if (val) { 00991 genop(s, MKOP_AB(OP_MOVE, cursp(), rhs)); 00992 push(); 00993 } 00994 pop(); 00995 genop(s, MKOP_ABC(OP_APOST, cursp(), n, post)); 00996 n = 1; 00997 if (t->car) { /* rest */ 00998 gen_assignment(s, t->car, cursp(), NOVAL); 00999 } 01000 if (t->cdr && t->cdr->car) { 01001 t = t->cdr->car; 01002 while (t) { 01003 gen_assignment(s, t->car, cursp()+n, NOVAL); 01004 t = t->cdr; 01005 n++; 01006 } 01007 } 01008 } 01009 else { 01010 pop(); 01011 } 01012 } 01013 01014 static void 01015 gen_send_intern(codegen_scope *s) 01016 { 01017 pop(); 01018 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "intern")), 0)); 01019 push(); 01020 } 01021 static void 01022 gen_literal_array(codegen_scope *s, node *tree, mrb_bool sym, int val) 01023 { 01024 if (val) { 01025 int i = 0, j = 0; 01026 01027 while (tree) { 01028 switch ((intptr_t)tree->car->car) { 01029 case NODE_STR: 01030 if ((tree->cdr == NULL) && ((intptr_t)tree->car->cdr->cdr == 0)) 01031 break; 01032 /* fall through */ 01033 case NODE_BEGIN: 01034 codegen(s, tree->car, VAL); 01035 ++j; 01036 break; 01037 01038 case NODE_LITERAL_DELIM: 01039 if (j > 0) { 01040 j = 0; 01041 ++i; 01042 if (sym) 01043 gen_send_intern(s); 01044 } 01045 break; 01046 } 01047 if (j >= 2) { 01048 pop(); pop(); 01049 genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL); 01050 push(); 01051 j = 1; 01052 } 01053 tree = tree->cdr; 01054 } 01055 if (j > 0) { 01056 ++i; 01057 if (sym) 01058 gen_send_intern(s); 01059 } 01060 pop_n(i); 01061 genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), i)); 01062 push(); 01063 } 01064 else { 01065 while (tree) { 01066 switch ((intptr_t)tree->car->car) { 01067 case NODE_BEGIN: case NODE_BLOCK: 01068 codegen(s, tree->car, NOVAL); 01069 } 01070 tree = tree->cdr; 01071 } 01072 } 01073 } 01074 01075 static void 01076 raise_error(codegen_scope *s, const char *msg) 01077 { 01078 int idx = new_lit(s, mrb_str_new_cstr(s->mrb, msg)); 01079 01080 genop(s, MKOP_ABx(OP_ERR, 1, idx)); 01081 } 01082 01083 static double 01084 readint_float(codegen_scope *s, const char *p, int base) 01085 { 01086 const char *e = p + strlen(p); 01087 double f = 0; 01088 int n; 01089 01090 if (*p == '+') p++; 01091 while (p < e) { 01092 char c = *p; 01093 c = tolower((unsigned char)c); 01094 for (n=0; n<base; n++) { 01095 if (mrb_digitmap[n] == c) { 01096 f *= base; 01097 f += n; 01098 break; 01099 } 01100 } 01101 if (n == base) { 01102 codegen_error(s, "malformed readint input"); 01103 } 01104 p++; 01105 } 01106 return f; 01107 } 01108 01109 static mrb_int 01110 readint_mrb_int(codegen_scope *s, const char *p, int base, mrb_bool neg, mrb_bool *overflow) 01111 { 01112 const char *e = p + strlen(p); 01113 mrb_int result = 0; 01114 int n; 01115 01116 mrb_assert(base >= 2 && base <= 36); 01117 if (*p == '+') p++; 01118 while (p < e) { 01119 char c = *p; 01120 c = tolower((unsigned char)c); 01121 for (n=0; n<base; n++) { 01122 if (mrb_digitmap[n] == c) { 01123 break; 01124 } 01125 } 01126 if (n == base) { 01127 codegen_error(s, "malformed readint input"); 01128 } 01129 01130 if (neg) { 01131 if ((MRB_INT_MIN + n)/base > result) { 01132 *overflow = TRUE; 01133 return 0; 01134 } 01135 result *= base; 01136 result -= n; 01137 } 01138 else { 01139 if ((MRB_INT_MAX - n)/base < result) { 01140 *overflow = TRUE; 01141 return 0; 01142 } 01143 result *= base; 01144 result += n; 01145 } 01146 p++; 01147 } 01148 *overflow = FALSE; 01149 return result; 01150 } 01151 01152 static void 01153 codegen(codegen_scope *s, node *tree, int val) 01154 { 01155 int nt; 01156 01157 if (!tree) return; 01158 01159 if (s->irep && s->filename_index != tree->filename_index) { 01160 s->irep->filename = mrb_parser_get_filename(s->parser, s->filename_index); 01161 mrb_debug_info_append_file(s->mrb, s->irep, s->debug_start_pos, s->pc); 01162 s->debug_start_pos = s->pc; 01163 s->filename_index = tree->filename_index; 01164 s->filename = mrb_parser_get_filename(s->parser, tree->filename_index); 01165 } 01166 01167 nt = (intptr_t)tree->car; 01168 s->lineno = tree->lineno; 01169 tree = tree->cdr; 01170 switch (nt) { 01171 case NODE_BEGIN: 01172 if (val && !tree) { 01173 genop(s, MKOP_A(OP_LOADNIL, cursp())); 01174 push(); 01175 } 01176 while (tree) { 01177 codegen(s, tree->car, tree->cdr ? NOVAL : val); 01178 tree = tree->cdr; 01179 } 01180 break; 01181 01182 case NODE_RESCUE: 01183 { 01184 int onerr, noexc, exend, pos1, pos2, tmp; 01185 struct loopinfo *lp; 01186 01187 onerr = genop(s, MKOP_Bx(OP_ONERR, 0)); 01188 lp = loop_push(s, LOOP_BEGIN); 01189 lp->pc1 = onerr; 01190 if (tree->car) { 01191 codegen(s, tree->car, val); 01192 if (val) pop(); 01193 } 01194 lp->type = LOOP_RESCUE; 01195 noexc = genop(s, MKOP_Bx(OP_JMP, 0)); 01196 dispatch(s, onerr); 01197 tree = tree->cdr; 01198 exend = 0; 01199 pos1 = 0; 01200 if (tree->car) { 01201 node *n2 = tree->car; 01202 int exc = cursp(); 01203 01204 genop(s, MKOP_A(OP_RESCUE, exc)); 01205 push(); 01206 while (n2) { 01207 node *n3 = n2->car; 01208 node *n4 = n3->car; 01209 01210 if (pos1) dispatch(s, pos1); 01211 pos2 = 0; 01212 do { 01213 if (n4) { 01214 codegen(s, n4->car, VAL); 01215 } 01216 else { 01217 genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "StandardError")))); 01218 push(); 01219 } 01220 genop(s, MKOP_AB(OP_MOVE, cursp(), exc)); 01221 pop(); 01222 if (n4 && n4->car && (intptr_t)n4->car->car == NODE_SPLAT) { 01223 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1)); 01224 } 01225 else { 01226 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "===")), 1)); 01227 } 01228 tmp = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2)); 01229 pos2 = tmp; 01230 if (n4) { 01231 n4 = n4->cdr; 01232 } 01233 } while (n4); 01234 pos1 = genop(s, MKOP_sBx(OP_JMP, 0)); 01235 dispatch_linked(s, pos2); 01236 01237 pop(); 01238 if (n3->cdr->car) { 01239 gen_assignment(s, n3->cdr->car, exc, NOVAL); 01240 } 01241 if (n3->cdr->cdr->car) { 01242 codegen(s, n3->cdr->cdr->car, val); 01243 if (val) pop(); 01244 } 01245 tmp = genop(s, MKOP_sBx(OP_JMP, exend)); 01246 exend = tmp; 01247 n2 = n2->cdr; 01248 push(); 01249 } 01250 if (pos1) { 01251 dispatch(s, pos1); 01252 genop(s, MKOP_A(OP_RAISE, exc)); 01253 } 01254 } 01255 pop(); 01256 tree = tree->cdr; 01257 dispatch(s, noexc); 01258 genop(s, MKOP_A(OP_POPERR, 1)); 01259 if (tree->car) { 01260 codegen(s, tree->car, val); 01261 } 01262 else if (val) { 01263 push(); 01264 } 01265 dispatch_linked(s, exend); 01266 loop_pop(s, NOVAL); 01267 } 01268 break; 01269 01270 case NODE_ENSURE: 01271 { 01272 int idx; 01273 int epush = s->pc; 01274 01275 genop(s, MKOP_Bx(OP_EPUSH, 0)); 01276 s->ensure_level++; 01277 codegen(s, tree->car, val); 01278 idx = scope_body(s, tree->cdr, NOVAL); 01279 s->iseq[epush] = MKOP_Bx(OP_EPUSH, idx); 01280 s->ensure_level--; 01281 genop_peep(s, MKOP_A(OP_EPOP, 1), NOVAL); 01282 } 01283 break; 01284 01285 case NODE_LAMBDA: 01286 { 01287 int idx = lambda_body(s, tree, 1); 01288 01289 genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_LAMBDA)); 01290 push(); 01291 } 01292 break; 01293 01294 case NODE_BLOCK: 01295 { 01296 int idx = lambda_body(s, tree, 1); 01297 01298 genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_BLOCK)); 01299 push(); 01300 } 01301 break; 01302 01303 case NODE_IF: 01304 { 01305 int pos1, pos2; 01306 node *e = tree->cdr->cdr->car; 01307 01308 codegen(s, tree->car, VAL); 01309 pop(); 01310 pos1 = genop_peep(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0), NOVAL); 01311 01312 codegen(s, tree->cdr->car, val); 01313 if (val && !(tree->cdr->car)) { 01314 genop(s, MKOP_A(OP_LOADNIL, cursp())); 01315 push(); 01316 } 01317 if (e) { 01318 if (val) pop(); 01319 pos2 = genop(s, MKOP_sBx(OP_JMP, 0)); 01320 dispatch(s, pos1); 01321 codegen(s, e, val); 01322 dispatch(s, pos2); 01323 } 01324 else { 01325 if (val) { 01326 pop(); 01327 pos2 = genop(s, MKOP_sBx(OP_JMP, 0)); 01328 dispatch(s, pos1); 01329 genop(s, MKOP_A(OP_LOADNIL, cursp())); 01330 dispatch(s, pos2); 01331 push(); 01332 } 01333 else { 01334 dispatch(s, pos1); 01335 } 01336 } 01337 } 01338 break; 01339 01340 case NODE_AND: 01341 { 01342 int pos; 01343 01344 codegen(s, tree->car, VAL); 01345 pop(); 01346 pos = genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0)); 01347 codegen(s, tree->cdr, val); 01348 dispatch(s, pos); 01349 } 01350 break; 01351 01352 case NODE_OR: 01353 { 01354 int pos; 01355 01356 codegen(s, tree->car, VAL); 01357 pop(); 01358 pos = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), 0)); 01359 codegen(s, tree->cdr, val); 01360 dispatch(s, pos); 01361 } 01362 break; 01363 01364 case NODE_WHILE: 01365 { 01366 struct loopinfo *lp = loop_push(s, LOOP_NORMAL); 01367 01368 lp->pc1 = genop(s, MKOP_sBx(OP_JMP, 0)); 01369 lp->pc2 = new_label(s); 01370 codegen(s, tree->cdr, NOVAL); 01371 dispatch(s, lp->pc1); 01372 codegen(s, tree->car, VAL); 01373 pop(); 01374 genop(s, MKOP_AsBx(OP_JMPIF, cursp(), lp->pc2 - s->pc)); 01375 01376 loop_pop(s, val); 01377 } 01378 break; 01379 01380 case NODE_UNTIL: 01381 { 01382 struct loopinfo *lp = loop_push(s, LOOP_NORMAL); 01383 01384 lp->pc1 = genop(s, MKOP_sBx(OP_JMP, 0)); 01385 lp->pc2 = new_label(s); 01386 codegen(s, tree->cdr, NOVAL); 01387 dispatch(s, lp->pc1); 01388 codegen(s, tree->car, VAL); 01389 pop(); 01390 genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), lp->pc2 - s->pc)); 01391 01392 loop_pop(s, val); 01393 } 01394 break; 01395 01396 case NODE_FOR: 01397 for_body(s, tree); 01398 if (val) push(); 01399 break; 01400 01401 case NODE_CASE: 01402 { 01403 int head = 0; 01404 int pos1, pos2, pos3, tmp; 01405 node *n; 01406 01407 pos3 = 0; 01408 if (tree->car) { 01409 head = cursp(); 01410 codegen(s, tree->car, VAL); 01411 } 01412 tree = tree->cdr; 01413 while (tree) { 01414 n = tree->car->car; 01415 pos1 = pos2 = 0; 01416 while (n) { 01417 codegen(s, n->car, VAL); 01418 if (head) { 01419 genop(s, MKOP_AB(OP_MOVE, cursp(), head)); 01420 pop(); 01421 if ((intptr_t)n->car->car == NODE_SPLAT) { 01422 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1)); 01423 } 01424 else { 01425 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "===")), 1)); 01426 } 01427 } 01428 else { 01429 pop(); 01430 } 01431 tmp = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2)); 01432 pos2 = tmp; 01433 n = n->cdr; 01434 } 01435 if (tree->car->car) { 01436 pos1 = genop(s, MKOP_sBx(OP_JMP, 0)); 01437 dispatch_linked(s, pos2); 01438 } 01439 codegen(s, tree->car->cdr, val); 01440 if (val) pop(); 01441 tmp = genop(s, MKOP_sBx(OP_JMP, pos3)); 01442 pos3 = tmp; 01443 if (pos1) dispatch(s, pos1); 01444 tree = tree->cdr; 01445 } 01446 if (val) { 01447 int pos = cursp(); 01448 genop(s, MKOP_A(OP_LOADNIL, cursp())); 01449 if (pos3) dispatch_linked(s, pos3); 01450 pop(); 01451 genop(s, MKOP_AB(OP_MOVE, cursp(), pos)); 01452 push(); 01453 } 01454 else if (pos3) { 01455 dispatch_linked(s, pos3); 01456 } 01457 } 01458 break; 01459 01460 case NODE_SCOPE: 01461 scope_body(s, tree, NOVAL); 01462 break; 01463 01464 case NODE_FCALL: 01465 case NODE_CALL: 01466 gen_call(s, tree, 0, 0, val); 01467 break; 01468 01469 case NODE_DOT2: 01470 codegen(s, tree->car, val); 01471 codegen(s, tree->cdr, val); 01472 if (val) { 01473 pop(); pop(); 01474 genop(s, MKOP_ABC(OP_RANGE, cursp(), cursp(), FALSE)); 01475 push(); 01476 } 01477 break; 01478 01479 case NODE_DOT3: 01480 codegen(s, tree->car, val); 01481 codegen(s, tree->cdr, val); 01482 if (val) { 01483 pop(); pop(); 01484 genop(s, MKOP_ABC(OP_RANGE, cursp(), cursp(), TRUE)); 01485 push(); 01486 } 01487 break; 01488 01489 case NODE_COLON2: 01490 { 01491 int sym = new_sym(s, sym(tree->cdr)); 01492 01493 codegen(s, tree->car, VAL); 01494 pop(); 01495 genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym)); 01496 if (val) push(); 01497 } 01498 break; 01499 01500 case NODE_COLON3: 01501 { 01502 int sym = new_sym(s, sym(tree)); 01503 01504 genop(s, MKOP_A(OP_OCLASS, cursp())); 01505 genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym)); 01506 if (val) push(); 01507 } 01508 break; 01509 01510 case NODE_ARRAY: 01511 { 01512 int n; 01513 01514 n = gen_values(s, tree, val); 01515 if (n >= 0) { 01516 if (val) { 01517 pop_n(n); 01518 genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), n)); 01519 push(); 01520 } 01521 } 01522 else if (val) { 01523 push(); 01524 } 01525 } 01526 break; 01527 01528 case NODE_HASH: 01529 { 01530 int len = 0; 01531 mrb_bool update = FALSE; 01532 01533 while (tree) { 01534 codegen(s, tree->car->car, val); 01535 codegen(s, tree->car->cdr, val); 01536 len++; 01537 tree = tree->cdr; 01538 if (val && len == 126) { 01539 pop_n(len*2); 01540 genop(s, MKOP_ABC(OP_HASH, cursp(), cursp(), len)); 01541 if (update) { 01542 pop(); 01543 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__update")), 1)); 01544 } 01545 push(); 01546 update = TRUE; 01547 len = 0; 01548 } 01549 } 01550 if (val) { 01551 pop_n(len*2); 01552 genop(s, MKOP_ABC(OP_HASH, cursp(), cursp(), len)); 01553 if (update) { 01554 pop(); 01555 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__update")), 1)); 01556 } 01557 push(); 01558 } 01559 } 01560 break; 01561 01562 case NODE_SPLAT: 01563 codegen(s, tree, VAL); 01564 break; 01565 01566 case NODE_ASGN: 01567 codegen(s, tree->cdr, VAL); 01568 pop(); 01569 gen_assignment(s, tree->car, cursp(), val); 01570 break; 01571 01572 case NODE_MASGN: 01573 { 01574 int len = 0, n = 0, post = 0; 01575 node *t = tree->cdr, *p; 01576 int rhs = cursp(); 01577 01578 if ((intptr_t)t->car == NODE_ARRAY && nosplat(t->cdr)) { 01579 /* fixed rhs */ 01580 t = t->cdr; 01581 while (t) { 01582 codegen(s, t->car, VAL); 01583 len++; 01584 t = t->cdr; 01585 } 01586 tree = tree->car; 01587 if (tree->car) { /* pre */ 01588 t = tree->car; 01589 n = 0; 01590 while (t) { 01591 gen_assignment(s, t->car, rhs+n, NOVAL); 01592 n++; 01593 t = t->cdr; 01594 } 01595 } 01596 t = tree->cdr; 01597 if (t) { 01598 if (t->cdr) { /* post count */ 01599 p = t->cdr->car; 01600 while (p) { 01601 post++; 01602 p = p->cdr; 01603 } 01604 } 01605 if (t->car) { /* rest (len - pre - post) */ 01606 int rn = len - post - n; 01607 01608 genop(s, MKOP_ABC(OP_ARRAY, cursp(), rhs+n, rn)); 01609 gen_assignment(s, t->car, cursp(), NOVAL); 01610 n += rn; 01611 } 01612 if (t->cdr && t->cdr->car) { 01613 t = t->cdr->car; 01614 while (n<len) { 01615 gen_assignment(s, t->car, rhs+n, NOVAL); 01616 t = t->cdr; 01617 n++; 01618 } 01619 } 01620 } 01621 pop_n(len); 01622 if (val) { 01623 genop(s, MKOP_ABC(OP_ARRAY, rhs, rhs, len)); 01624 push(); 01625 } 01626 } 01627 else { 01628 /* variable rhs */ 01629 codegen(s, t, VAL); 01630 gen_vmassignment(s, tree->car, rhs, val); 01631 } 01632 } 01633 break; 01634 01635 case NODE_OP_ASGN: 01636 { 01637 mrb_sym sym = sym(tree->cdr->car); 01638 mrb_int len; 01639 const char *name = mrb_sym2name_len(s->mrb, sym, &len); 01640 int idx; 01641 01642 codegen(s, tree->car, VAL); 01643 if (len == 2 && 01644 ((name[0] == '|' && name[1] == '|') || 01645 (name[0] == '&' && name[1] == '&'))) { 01646 int pos; 01647 01648 pop(); 01649 pos = genop_peep(s, MKOP_AsBx(name[0] == '|' ? OP_JMPIF : OP_JMPNOT, cursp(), 0), NOVAL); 01650 codegen(s, tree->cdr->cdr->car, VAL); 01651 pop(); 01652 gen_assignment(s, tree->car, cursp(), val); 01653 dispatch(s, pos); 01654 break; 01655 } 01656 codegen(s, tree->cdr->cdr->car, VAL); 01657 push(); pop(); 01658 pop(); pop(); 01659 01660 idx = new_msym(s, sym); 01661 if (len == 1 && name[0] == '+') { 01662 genop_peep(s, MKOP_ABC(OP_ADD, cursp(), idx, 1), val); 01663 } 01664 else if (len == 1 && name[0] == '-') { 01665 genop_peep(s, MKOP_ABC(OP_SUB, cursp(), idx, 1), val); 01666 } 01667 else if (len == 1 && name[0] == '*') { 01668 genop(s, MKOP_ABC(OP_MUL, cursp(), idx, 1)); 01669 } 01670 else if (len == 1 && name[0] == '/') { 01671 genop(s, MKOP_ABC(OP_DIV, cursp(), idx, 1)); 01672 } 01673 else if (len == 1 && name[0] == '<') { 01674 genop(s, MKOP_ABC(OP_LT, cursp(), idx, 1)); 01675 } 01676 else if (len == 2 && name[0] == '<' && name[1] == '=') { 01677 genop(s, MKOP_ABC(OP_LE, cursp(), idx, 1)); 01678 } 01679 else if (len == 1 && name[0] == '>') { 01680 genop(s, MKOP_ABC(OP_GT, cursp(), idx, 1)); 01681 } 01682 else if (len == 2 && name[0] == '>' && name[1] == '=') { 01683 genop(s, MKOP_ABC(OP_GE, cursp(), idx, 1)); 01684 } 01685 else { 01686 genop(s, MKOP_ABC(OP_SEND, cursp(), idx, 1)); 01687 } 01688 } 01689 gen_assignment(s, tree->car, cursp(), val); 01690 break; 01691 01692 case NODE_SUPER: 01693 { 01694 int n = 0, noop = 0, sendv = 0; 01695 01696 push(); /* room for receiver */ 01697 if (tree) { 01698 node *args = tree->car; 01699 if (args) { 01700 n = gen_values(s, args, VAL); 01701 if (n < 0) { 01702 n = noop = sendv = 1; 01703 push(); 01704 } 01705 } 01706 } 01707 if (tree && tree->cdr) { 01708 codegen(s, tree->cdr, VAL); 01709 pop(); 01710 } 01711 else { 01712 genop(s, MKOP_A(OP_LOADNIL, cursp())); 01713 push(); pop(); 01714 } 01715 pop_n(n+1); 01716 if (sendv) n = CALL_MAXARGS; 01717 genop(s, MKOP_ABC(OP_SUPER, cursp(), 0, n)); 01718 if (val) push(); 01719 } 01720 break; 01721 01722 case NODE_ZSUPER: 01723 { 01724 codegen_scope *s2 = s; 01725 int lv = 0, ainfo = 0; 01726 01727 push(); /* room for receiver */ 01728 while (!s2->mscope) { 01729 lv++; 01730 s2 = s2->prev; 01731 if (!s2) break; 01732 } 01733 if (s2) ainfo = s2->ainfo; 01734 genop(s, MKOP_ABx(OP_ARGARY, cursp(), (ainfo<<4)|(lv & 0xf))); 01735 push(); push(); pop(); /* ARGARY pushes two values */ 01736 if (tree && tree->cdr) { 01737 codegen(s, tree->cdr, VAL); 01738 pop(); 01739 } 01740 pop(); pop(); 01741 genop(s, MKOP_ABC(OP_SUPER, cursp(), 0, CALL_MAXARGS)); 01742 if (val) push(); 01743 } 01744 break; 01745 01746 case NODE_RETURN: 01747 if (tree) { 01748 codegen(s, tree, VAL); 01749 pop(); 01750 } 01751 else { 01752 genop(s, MKOP_A(OP_LOADNIL, cursp())); 01753 } 01754 if (s->loop) { 01755 genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_RETURN)); 01756 } 01757 else { 01758 genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL); 01759 } 01760 if (val) push(); 01761 break; 01762 01763 case NODE_YIELD: 01764 { 01765 codegen_scope *s2 = s; 01766 int lv = 0, ainfo = 0; 01767 int n = 0, sendv = 0; 01768 01769 while (!s2->mscope) { 01770 lv++; 01771 s2 = s2->prev; 01772 if (!s2) break; 01773 } 01774 if (s2) ainfo = s2->ainfo; 01775 genop(s, MKOP_ABx(OP_BLKPUSH, cursp(), (ainfo<<4)|(lv & 0xf))); 01776 push(); 01777 if (tree) { 01778 n = gen_values(s, tree, VAL); 01779 if (n < 0) { 01780 n = sendv = 1; 01781 push(); 01782 } 01783 } 01784 pop_n(n+1); 01785 if (sendv) n = CALL_MAXARGS; 01786 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "call")), n)); 01787 if (val) push(); 01788 } 01789 break; 01790 01791 case NODE_BREAK: 01792 loop_break(s, tree); 01793 if (val) push(); 01794 break; 01795 01796 case NODE_NEXT: 01797 if (!s->loop) { 01798 raise_error(s, "unexpected next"); 01799 } 01800 else if (s->loop->type == LOOP_NORMAL) { 01801 if (s->ensure_level > s->loop->ensure_level) { 01802 genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL); 01803 } 01804 codegen(s, tree, NOVAL); 01805 genop(s, MKOP_sBx(OP_JMP, s->loop->pc1 - s->pc)); 01806 } 01807 else { 01808 if (tree) { 01809 codegen(s, tree, VAL); 01810 pop(); 01811 } 01812 else { 01813 genop(s, MKOP_A(OP_LOADNIL, cursp())); 01814 } 01815 genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL); 01816 } 01817 if (val) push(); 01818 break; 01819 01820 case NODE_REDO: 01821 if (!s->loop) { 01822 raise_error(s, "unexpected redo"); 01823 } 01824 else { 01825 if (s->ensure_level > s->loop->ensure_level) { 01826 genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL); 01827 } 01828 genop(s, MKOP_sBx(OP_JMP, s->loop->pc2 - s->pc)); 01829 } 01830 break; 01831 01832 case NODE_RETRY: 01833 { 01834 const char *msg = "unexpected retry"; 01835 01836 if (!s->loop) { 01837 raise_error(s, msg); 01838 } 01839 else { 01840 struct loopinfo *lp = s->loop; 01841 int n = 0; 01842 01843 while (lp && lp->type != LOOP_RESCUE) { 01844 if (lp->type == LOOP_BEGIN) { 01845 n++; 01846 } 01847 lp = lp->prev; 01848 } 01849 if (!lp) { 01850 raise_error(s, msg); 01851 } 01852 else { 01853 if (n > 0) { 01854 while (n--) { 01855 genop_peep(s, MKOP_A(OP_POPERR, 1), NOVAL); 01856 } 01857 } 01858 if (s->ensure_level > lp->ensure_level) { 01859 genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - lp->ensure_level), NOVAL); 01860 } 01861 genop(s, MKOP_sBx(OP_JMP, lp->pc1 - s->pc)); 01862 } 01863 } 01864 } 01865 break; 01866 01867 case NODE_LVAR: 01868 if (val) { 01869 int idx = lv_idx(s, sym(tree)); 01870 01871 if (idx > 0) { 01872 genop_peep(s, MKOP_AB(OP_MOVE, cursp(), idx), NOVAL); 01873 } 01874 else { 01875 int lv = 0; 01876 codegen_scope *up = s->prev; 01877 01878 while (up) { 01879 idx = lv_idx(up, sym(tree)); 01880 if (idx > 0) { 01881 genop(s, MKOP_ABC(OP_GETUPVAR, cursp(), idx, lv)); 01882 break; 01883 } 01884 lv++; 01885 up = up->prev; 01886 } 01887 } 01888 push(); 01889 } 01890 break; 01891 01892 case NODE_GVAR: 01893 { 01894 int sym = new_sym(s, sym(tree)); 01895 01896 genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym)); 01897 push(); 01898 } 01899 break; 01900 01901 case NODE_IVAR: 01902 { 01903 int sym = new_sym(s, sym(tree)); 01904 01905 genop(s, MKOP_ABx(OP_GETIV, cursp(), sym)); 01906 push(); 01907 } 01908 break; 01909 01910 case NODE_CVAR: 01911 { 01912 int sym = new_sym(s, sym(tree)); 01913 01914 genop(s, MKOP_ABx(OP_GETCV, cursp(), sym)); 01915 push(); 01916 } 01917 break; 01918 01919 case NODE_CONST: 01920 { 01921 int sym = new_sym(s, sym(tree)); 01922 01923 genop(s, MKOP_ABx(OP_GETCONST, cursp(), sym)); 01924 push(); 01925 } 01926 break; 01927 01928 case NODE_DEFINED: 01929 codegen(s, tree, VAL); 01930 break; 01931 01932 case NODE_BACK_REF: 01933 { 01934 char buf[2] = { '$' }; 01935 mrb_value str; 01936 int sym; 01937 01938 buf[1] = (char)(intptr_t)tree; 01939 str = mrb_str_new(s->mrb, buf, 2); 01940 sym = new_sym(s, mrb_intern_str(s->mrb, str)); 01941 genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym)); 01942 push(); 01943 } 01944 break; 01945 01946 case NODE_NTH_REF: 01947 { 01948 int sym; 01949 mrb_state *mrb = s->mrb; 01950 mrb_value fix = mrb_fixnum_value((intptr_t)tree); 01951 mrb_value str = mrb_str_buf_new(mrb, 4); 01952 01953 mrb_str_cat_lit(mrb, str, "$"); 01954 mrb_str_cat_str(mrb, str, mrb_fixnum_to_str(mrb, fix, 10)); 01955 sym = new_sym(s, mrb_intern_str(mrb, str)); 01956 genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym)); 01957 push(); 01958 } 01959 break; 01960 01961 case NODE_ARG: 01962 /* should not happen */ 01963 break; 01964 01965 case NODE_BLOCK_ARG: 01966 codegen(s, tree, VAL); 01967 break; 01968 01969 case NODE_INT: 01970 if (val) { 01971 char *p = (char*)tree->car; 01972 int base = (intptr_t)tree->cdr->car; 01973 mrb_int i; 01974 mrb_code co; 01975 mrb_bool overflow; 01976 01977 i = readint_mrb_int(s, p, base, FALSE, &overflow); 01978 if (overflow) { 01979 double f = readint_float(s, p, base); 01980 int off = new_lit(s, mrb_float_value(s->mrb, f)); 01981 01982 genop(s, MKOP_ABx(OP_LOADL, cursp(), off)); 01983 } 01984 else { 01985 if (i < MAXARG_sBx && i > -MAXARG_sBx) { 01986 co = MKOP_AsBx(OP_LOADI, cursp(), i); 01987 } 01988 else { 01989 int off = new_lit(s, mrb_fixnum_value(i)); 01990 co = MKOP_ABx(OP_LOADL, cursp(), off); 01991 } 01992 genop(s, co); 01993 } 01994 push(); 01995 } 01996 break; 01997 01998 case NODE_FLOAT: 01999 if (val) { 02000 char *p = (char*)tree; 02001 mrb_float f = str_to_mrb_float(p); 02002 int off = new_lit(s, mrb_float_value(s->mrb, f)); 02003 02004 genop(s, MKOP_ABx(OP_LOADL, cursp(), off)); 02005 push(); 02006 } 02007 break; 02008 02009 case NODE_NEGATE: 02010 { 02011 nt = (intptr_t)tree->car; 02012 tree = tree->cdr; 02013 switch (nt) { 02014 case NODE_FLOAT: 02015 { 02016 char *p = (char*)tree; 02017 mrb_float f = str_to_mrb_float(p); 02018 int off = new_lit(s, mrb_float_value(s->mrb, -f)); 02019 02020 genop(s, MKOP_ABx(OP_LOADL, cursp(), off)); 02021 push(); 02022 } 02023 break; 02024 02025 case NODE_INT: 02026 { 02027 char *p = (char*)tree->car; 02028 int base = (intptr_t)tree->cdr->car; 02029 mrb_int i; 02030 mrb_code co; 02031 mrb_bool overflow; 02032 02033 i = readint_mrb_int(s, p, base, TRUE, &overflow); 02034 if (overflow) { 02035 double f = readint_float(s, p, base); 02036 int off = new_lit(s, mrb_float_value(s->mrb, -f)); 02037 02038 genop(s, MKOP_ABx(OP_LOADL, cursp(), off)); 02039 } 02040 else { 02041 if (i < MAXARG_sBx && i > -MAXARG_sBx) { 02042 co = MKOP_AsBx(OP_LOADI, cursp(), i); 02043 } 02044 else { 02045 int off = new_lit(s, mrb_fixnum_value(i)); 02046 co = MKOP_ABx(OP_LOADL, cursp(), off); 02047 } 02048 genop(s, co); 02049 } 02050 push(); 02051 } 02052 break; 02053 02054 default: 02055 { 02056 int sym = new_msym(s, mrb_intern_lit(s->mrb, "-")); 02057 02058 genop(s, MKOP_ABx(OP_LOADI, cursp(), 0)); 02059 push(); 02060 codegen(s, tree, VAL); 02061 pop(); pop(); 02062 genop(s, MKOP_ABC(OP_SUB, cursp(), sym, 2)); 02063 } 02064 break; 02065 } 02066 } 02067 break; 02068 02069 case NODE_STR: 02070 if (val) { 02071 char *p = (char*)tree->car; 02072 size_t len = (intptr_t)tree->cdr; 02073 int ai = mrb_gc_arena_save(s->mrb); 02074 int off = new_lit(s, mrb_str_new(s->mrb, p, len)); 02075 02076 mrb_gc_arena_restore(s->mrb, ai); 02077 genop(s, MKOP_ABx(OP_STRING, cursp(), off)); 02078 push(); 02079 } 02080 break; 02081 02082 case NODE_HEREDOC: 02083 tree = ((struct mrb_parser_heredoc_info *)tree)->doc; 02084 /* fall through */ 02085 case NODE_DSTR: 02086 if (val) { 02087 node *n = tree; 02088 02089 codegen(s, n->car, VAL); 02090 n = n->cdr; 02091 while (n) { 02092 codegen(s, n->car, VAL); 02093 pop(); pop(); 02094 genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL); 02095 push(); 02096 n = n->cdr; 02097 } 02098 } 02099 else { 02100 node *n = tree; 02101 02102 while (n) { 02103 if ((intptr_t)n->car->car != NODE_STR) { 02104 codegen(s, n->car, NOVAL); 02105 } 02106 n = n->cdr; 02107 } 02108 } 02109 break; 02110 02111 case NODE_WORDS: 02112 gen_literal_array(s, tree, FALSE, val); 02113 break; 02114 02115 case NODE_SYMBOLS: 02116 gen_literal_array(s, tree, TRUE, val); 02117 break; 02118 02119 case NODE_DXSTR: 02120 { 02121 node *n; 02122 int ai = mrb_gc_arena_save(s->mrb); 02123 int sym = new_sym(s, mrb_intern_lit(s->mrb, "Kernel")); 02124 02125 if (val == NOVAL) { push(); } 02126 genop(s, MKOP_A(OP_OCLASS, cursp())); 02127 genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym)); 02128 push(); 02129 codegen(s, tree->car, VAL); 02130 n = tree->cdr; 02131 while (n) { 02132 if ((intptr_t)n->car->car == NODE_XSTR) { 02133 n->car->car = (struct mrb_ast_node*)(intptr_t)NODE_STR; 02134 mrb_assert(!n->cdr); /* must be the end */ 02135 } 02136 codegen(s, n->car, VAL); 02137 pop(); pop(); 02138 genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL); 02139 push(); 02140 n = n->cdr; 02141 } 02142 pop(); 02143 pop(); 02144 sym = new_sym(s, mrb_intern_lit(s->mrb, "`")); 02145 genop(s, MKOP_ABC(OP_SEND, cursp(), sym, 1)); 02146 if (val == NOVAL) { pop(); } 02147 else { push(); } 02148 mrb_gc_arena_restore(s->mrb, ai); 02149 } 02150 break; 02151 02152 case NODE_XSTR: 02153 { 02154 char *p = (char*)tree->car; 02155 size_t len = (intptr_t)tree->cdr; 02156 int ai = mrb_gc_arena_save(s->mrb); 02157 int sym = new_sym(s, mrb_intern_lit(s->mrb, "Kernel")); 02158 int off = new_lit(s, mrb_str_new(s->mrb, p, len)); 02159 02160 if (val == NOVAL) { push(); } 02161 genop(s, MKOP_A(OP_OCLASS, cursp())); 02162 genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym)); 02163 push(); 02164 genop(s, MKOP_ABx(OP_STRING, cursp(), off)); 02165 pop(); 02166 sym = new_sym(s, mrb_intern_lit(s->mrb, "`")); 02167 genop(s, MKOP_ABC(OP_SEND, cursp(), sym, 1)); 02168 if (val == NOVAL) { pop(); } 02169 else { push(); } 02170 mrb_gc_arena_restore(s->mrb, ai); 02171 } 02172 break; 02173 02174 case NODE_REGX: 02175 if (val) { 02176 char *p1 = (char*)tree->car; 02177 char *p2 = (char*)tree->cdr; 02178 int ai = mrb_gc_arena_save(s->mrb); 02179 int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS)); 02180 int off = new_lit(s, mrb_str_new_cstr(s->mrb, p1)); 02181 int argc = 1; 02182 02183 genop(s, MKOP_A(OP_OCLASS, cursp())); 02184 genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym)); 02185 push(); 02186 genop(s, MKOP_ABx(OP_STRING, cursp(), off)); 02187 if (p2) { 02188 push(); 02189 off = new_lit(s, mrb_str_new_cstr(s->mrb, p2)); 02190 genop(s, MKOP_ABx(OP_STRING, cursp(), off)); 02191 argc++; 02192 pop(); 02193 } 02194 pop(); 02195 sym = new_sym(s, mrb_intern_lit(s->mrb, "compile")); 02196 genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc)); 02197 mrb_gc_arena_restore(s->mrb, ai); 02198 push(); 02199 } 02200 break; 02201 02202 case NODE_DREGX: 02203 if (val) { 02204 node *n = tree->car; 02205 int ai = mrb_gc_arena_save(s->mrb); 02206 int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS)); 02207 int argc = 1; 02208 int off; 02209 char *p; 02210 02211 genop(s, MKOP_A(OP_OCLASS, cursp())); 02212 genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym)); 02213 push(); 02214 codegen(s, n->car, VAL); 02215 n = n->cdr; 02216 while (n) { 02217 codegen(s, n->car, VAL); 02218 pop(); pop(); 02219 genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL); 02220 push(); 02221 n = n->cdr; 02222 } 02223 n = tree->cdr->cdr; 02224 if (n->car) { 02225 p = (char*)n->car; 02226 off = new_lit(s, mrb_str_new_cstr(s->mrb, p)); 02227 codegen(s, tree->car, VAL); 02228 genop(s, MKOP_ABx(OP_STRING, cursp(), off)); 02229 pop(); 02230 genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL); 02231 } 02232 if (n->cdr) { 02233 char *p2 = (char*)n->cdr; 02234 02235 push(); 02236 off = new_lit(s, mrb_str_new_cstr(s->mrb, p2)); 02237 genop(s, MKOP_ABx(OP_STRING, cursp(), off)); 02238 argc++; 02239 pop(); 02240 } 02241 pop(); 02242 sym = new_sym(s, mrb_intern_lit(s->mrb, "compile")); 02243 genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc)); 02244 mrb_gc_arena_restore(s->mrb, ai); 02245 push(); 02246 } 02247 else { 02248 node *n = tree->car; 02249 02250 while (n) { 02251 if ((intptr_t)n->car->car != NODE_STR) { 02252 codegen(s, n->car, NOVAL); 02253 } 02254 n = n->cdr; 02255 } 02256 } 02257 break; 02258 02259 case NODE_SYM: 02260 if (val) { 02261 int sym = new_sym(s, sym(tree)); 02262 02263 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym)); 02264 push(); 02265 } 02266 break; 02267 02268 case NODE_DSYM: 02269 codegen(s, tree, val); 02270 if (val) { 02271 gen_send_intern(s); 02272 } 02273 break; 02274 02275 case NODE_SELF: 02276 if (val) { 02277 genop(s, MKOP_A(OP_LOADSELF, cursp())); 02278 push(); 02279 } 02280 break; 02281 02282 case NODE_NIL: 02283 if (val) { 02284 genop(s, MKOP_A(OP_LOADNIL, cursp())); 02285 push(); 02286 } 02287 break; 02288 02289 case NODE_TRUE: 02290 if (val) { 02291 genop(s, MKOP_A(OP_LOADT, cursp())); 02292 push(); 02293 } 02294 break; 02295 02296 case NODE_FALSE: 02297 if (val) { 02298 genop(s, MKOP_A(OP_LOADF, cursp())); 02299 push(); 02300 } 02301 break; 02302 02303 case NODE_ALIAS: 02304 { 02305 int a = new_msym(s, sym(tree->car)); 02306 int b = new_msym(s, sym(tree->cdr)); 02307 int c = new_msym(s, mrb_intern_lit(s->mrb, "alias_method")); 02308 02309 genop(s, MKOP_A(OP_TCLASS, cursp())); 02310 push(); 02311 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), a)); 02312 push(); 02313 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), b)); 02314 push(); 02315 genop(s, MKOP_A(OP_LOADNIL, cursp())); 02316 pop_n(3); 02317 genop(s, MKOP_ABC(OP_SEND, cursp(), c, 2)); 02318 if (val) { 02319 push(); 02320 } 02321 } 02322 break; 02323 02324 case NODE_UNDEF: 02325 { 02326 int undef = new_msym(s, mrb_intern_lit(s->mrb, "undef_method")); 02327 int num = 0; 02328 node *t = tree; 02329 02330 genop(s, MKOP_A(OP_TCLASS, cursp())); 02331 push(); 02332 while (t) { 02333 int symbol = new_msym(s, sym(t->car)); 02334 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), symbol)); 02335 push(); 02336 t = t->cdr; 02337 num++; 02338 } 02339 pop_n(num + 1); 02340 genop(s, MKOP_ABC(OP_SEND, cursp(), undef, num)); 02341 if (val) { 02342 push(); 02343 } 02344 } 02345 break; 02346 02347 case NODE_CLASS: 02348 { 02349 int idx; 02350 02351 if (tree->car->car == (node*)0) { 02352 genop(s, MKOP_A(OP_LOADNIL, cursp())); 02353 push(); 02354 } 02355 else if (tree->car->car == (node*)1) { 02356 genop(s, MKOP_A(OP_OCLASS, cursp())); 02357 push(); 02358 } 02359 else { 02360 codegen(s, tree->car->car, VAL); 02361 } 02362 if (tree->cdr->car) { 02363 codegen(s, tree->cdr->car, VAL); 02364 } 02365 else { 02366 genop(s, MKOP_A(OP_LOADNIL, cursp())); 02367 push(); 02368 } 02369 pop(); pop(); 02370 idx = new_msym(s, sym(tree->car->cdr)); 02371 genop(s, MKOP_AB(OP_CLASS, cursp(), idx)); 02372 idx = scope_body(s, tree->cdr->cdr->car, val); 02373 genop(s, MKOP_ABx(OP_EXEC, cursp(), idx)); 02374 if (val) { 02375 push(); 02376 } 02377 } 02378 break; 02379 02380 case NODE_MODULE: 02381 { 02382 int idx; 02383 02384 if (tree->car->car == (node*)0) { 02385 genop(s, MKOP_A(OP_LOADNIL, cursp())); 02386 push(); 02387 } 02388 else if (tree->car->car == (node*)1) { 02389 genop(s, MKOP_A(OP_OCLASS, cursp())); 02390 push(); 02391 } 02392 else { 02393 codegen(s, tree->car->car, VAL); 02394 } 02395 pop(); 02396 idx = new_msym(s, sym(tree->car->cdr)); 02397 genop(s, MKOP_AB(OP_MODULE, cursp(), idx)); 02398 idx = scope_body(s, tree->cdr->car, val); 02399 genop(s, MKOP_ABx(OP_EXEC, cursp(), idx)); 02400 if (val) { 02401 push(); 02402 } 02403 } 02404 break; 02405 02406 case NODE_SCLASS: 02407 { 02408 int idx; 02409 02410 codegen(s, tree->car, VAL); 02411 pop(); 02412 genop(s, MKOP_AB(OP_SCLASS, cursp(), cursp())); 02413 idx = scope_body(s, tree->cdr->car, val); 02414 genop(s, MKOP_ABx(OP_EXEC, cursp(), idx)); 02415 if (val) { 02416 push(); 02417 } 02418 } 02419 break; 02420 02421 case NODE_DEF: 02422 { 02423 int sym = new_msym(s, sym(tree->car)); 02424 int idx = lambda_body(s, tree->cdr, 0); 02425 02426 genop(s, MKOP_A(OP_TCLASS, cursp())); 02427 push(); 02428 genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_METHOD)); 02429 push(); pop(); 02430 pop(); 02431 genop(s, MKOP_AB(OP_METHOD, cursp(), sym)); 02432 if (val) { 02433 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym)); 02434 push(); 02435 } 02436 } 02437 break; 02438 02439 case NODE_SDEF: 02440 { 02441 node *recv = tree->car; 02442 int sym = new_msym(s, sym(tree->cdr->car)); 02443 int idx = lambda_body(s, tree->cdr->cdr, 0); 02444 02445 codegen(s, recv, VAL); 02446 pop(); 02447 genop(s, MKOP_AB(OP_SCLASS, cursp(), cursp())); 02448 push(); 02449 genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_METHOD)); 02450 pop(); 02451 genop(s, MKOP_AB(OP_METHOD, cursp(), sym)); 02452 if (val) { 02453 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym)); 02454 push(); 02455 } 02456 } 02457 break; 02458 02459 case NODE_POSTEXE: 02460 codegen(s, tree, NOVAL); 02461 break; 02462 02463 default: 02464 break; 02465 } 02466 } 02467 02468 static void 02469 scope_add_irep(codegen_scope *s, mrb_irep *irep) 02470 { 02471 if (s->irep == NULL) { 02472 s->irep = irep; 02473 return; 02474 } 02475 if (s->irep->rlen == s->rcapa) { 02476 s->rcapa *= 2; 02477 s->irep->reps = (mrb_irep**)codegen_realloc(s, s->irep->reps, sizeof(mrb_irep*)*s->rcapa); 02478 } 02479 s->irep->reps[s->irep->rlen] = irep; 02480 s->irep->rlen++; 02481 } 02482 02483 static codegen_scope* 02484 scope_new(mrb_state *mrb, codegen_scope *prev, node *lv) 02485 { 02486 static const codegen_scope codegen_scope_zero = { 0 }; 02487 mrb_pool *pool = mrb_pool_open(mrb); 02488 codegen_scope *p = (codegen_scope *)mrb_pool_alloc(pool, sizeof(codegen_scope)); 02489 02490 if (!p) return NULL; 02491 *p = codegen_scope_zero; 02492 p->mrb = mrb; 02493 p->mpool = pool; 02494 if (!prev) return p; 02495 p->prev = prev; 02496 p->ainfo = -1; 02497 p->mscope = 0; 02498 02499 p->irep = mrb_add_irep(mrb); 02500 scope_add_irep(prev, p->irep); 02501 02502 p->rcapa = 8; 02503 p->irep->reps = (mrb_irep**)mrb_malloc(mrb, sizeof(mrb_irep*)*p->rcapa); 02504 02505 p->icapa = 1024; 02506 p->iseq = (mrb_code*)mrb_malloc(mrb, sizeof(mrb_code)*p->icapa); 02507 p->irep->iseq = p->iseq; 02508 02509 p->pcapa = 32; 02510 p->irep->pool = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value)*p->pcapa); 02511 p->irep->plen = 0; 02512 02513 p->scapa = 256; 02514 p->irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*p->scapa); 02515 p->irep->slen = 0; 02516 02517 p->lv = lv; 02518 p->sp += node_len(lv)+1; /* add self */ 02519 p->nlocals = p->sp; 02520 if (lv) { 02521 node *n = lv; 02522 size_t i = 0; 02523 02524 p->irep->lv = (struct mrb_locals*)mrb_malloc(mrb, sizeof(struct mrb_locals) * (p->nlocals - 1)); 02525 for (i=0, n=lv; n; i++,n=n->cdr) { 02526 p->irep->lv[i].name = lv_name(n); 02527 if (lv_name(n)) { 02528 p->irep->lv[i].r = lv_idx(p, lv_name(n)); 02529 } 02530 else { 02531 p->irep->lv[i].r = 0; 02532 } 02533 } 02534 mrb_assert(i + 1 == p->nlocals); 02535 } 02536 p->ai = mrb_gc_arena_save(mrb); 02537 02538 p->filename = prev->filename; 02539 if (p->filename) { 02540 p->lines = (uint16_t*)mrb_malloc(mrb, sizeof(short)*p->icapa); 02541 } 02542 p->lineno = prev->lineno; 02543 02544 /* debug setting */ 02545 p->debug_start_pos = 0; 02546 if (p->filename) { 02547 mrb_debug_info_alloc(mrb, p->irep); 02548 p->irep->filename = p->filename; 02549 p->irep->lines = p->lines; 02550 } 02551 else { 02552 p->irep->debug_info = NULL; 02553 } 02554 p->parser = prev->parser; 02555 p->filename_index = prev->filename_index; 02556 02557 return p; 02558 } 02559 02560 static void 02561 scope_finish(codegen_scope *s) 02562 { 02563 mrb_state *mrb = s->mrb; 02564 mrb_irep *irep = s->irep; 02565 size_t fname_len; 02566 char *fname; 02567 02568 irep->flags = 0; 02569 if (s->iseq) { 02570 irep->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc); 02571 irep->ilen = s->pc; 02572 if (s->lines) { 02573 irep->lines = (uint16_t *)codegen_realloc(s, s->lines, sizeof(uint16_t)*s->pc); 02574 } 02575 else { 02576 irep->lines = 0; 02577 } 02578 } 02579 irep->pool = (mrb_value*)codegen_realloc(s, irep->pool, sizeof(mrb_value)*irep->plen); 02580 irep->syms = (mrb_sym*)codegen_realloc(s, irep->syms, sizeof(mrb_sym)*irep->slen); 02581 irep->reps = (mrb_irep**)codegen_realloc(s, irep->reps, sizeof(mrb_irep*)*irep->rlen); 02582 if (s->filename) { 02583 s->irep->filename = mrb_parser_get_filename(s->parser, s->filename_index); 02584 mrb_debug_info_append_file(mrb, s->irep, s->debug_start_pos, s->pc); 02585 02586 fname_len = strlen(s->filename); 02587 fname = (char*)codegen_malloc(s, fname_len + 1); 02588 memcpy(fname, s->filename, fname_len); 02589 fname[fname_len] = '\0'; 02590 irep->filename = fname; 02591 } 02592 02593 irep->nlocals = s->nlocals; 02594 irep->nregs = s->nregs; 02595 02596 mrb_gc_arena_restore(mrb, s->ai); 02597 mrb_pool_close(s->mpool); 02598 } 02599 02600 static struct loopinfo* 02601 loop_push(codegen_scope *s, enum looptype t) 02602 { 02603 struct loopinfo *p = (struct loopinfo *)codegen_palloc(s, sizeof(struct loopinfo)); 02604 02605 p->type = t; 02606 p->pc1 = p->pc2 = p->pc3 = 0; 02607 p->prev = s->loop; 02608 p->ensure_level = s->ensure_level; 02609 p->acc = cursp(); 02610 s->loop = p; 02611 02612 return p; 02613 } 02614 02615 static void 02616 loop_break(codegen_scope *s, node *tree) 02617 { 02618 if (!s->loop) { 02619 codegen(s, tree, NOVAL); 02620 raise_error(s, "unexpected break"); 02621 } 02622 else { 02623 struct loopinfo *loop; 02624 02625 if (tree) { 02626 codegen(s, tree, VAL); 02627 pop(); 02628 } 02629 02630 loop = s->loop; 02631 while (loop->type == LOOP_BEGIN) { 02632 genop_peep(s, MKOP_A(OP_POPERR, 1), NOVAL); 02633 loop = loop->prev; 02634 } 02635 while (loop->type == LOOP_RESCUE) { 02636 loop = loop->prev; 02637 } 02638 if (loop->type == LOOP_NORMAL) { 02639 int tmp; 02640 02641 if (s->ensure_level > s->loop->ensure_level) { 02642 genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL); 02643 } 02644 if (tree) { 02645 genop_peep(s, MKOP_AB(OP_MOVE, loop->acc, cursp()), NOVAL); 02646 } 02647 tmp = genop(s, MKOP_sBx(OP_JMP, loop->pc3)); 02648 loop->pc3 = tmp; 02649 } 02650 else { 02651 genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_BREAK)); 02652 } 02653 } 02654 } 02655 02656 static void 02657 loop_pop(codegen_scope *s, int val) 02658 { 02659 if (val) { 02660 genop(s, MKOP_A(OP_LOADNIL, cursp())); 02661 } 02662 dispatch_linked(s, s->loop->pc3); 02663 s->loop = s->loop->prev; 02664 if (val) push(); 02665 } 02666 02667 #ifdef ENABLE_STDIO 02668 static int 02669 print_r(mrb_state *mrb, mrb_irep *irep, size_t n, int pre) 02670 { 02671 size_t i; 02672 02673 if (n == 0) return 0; 02674 02675 for (i=0; i+1<irep->nlocals; i++) { 02676 if (irep->lv[i].r == n) { 02677 mrb_sym sym = irep->lv[i].name; 02678 if (pre) printf(" "); 02679 printf("R%d:%s", (int)n, mrb_sym2name(mrb, sym)); 02680 return 1; 02681 } 02682 } 02683 return 0; 02684 } 02685 02686 #define RA 1 02687 #define RB 2 02688 #define RAB 3 02689 02690 static void 02691 print_lv(mrb_state *mrb, mrb_irep *irep, mrb_code c, int r) 02692 { 02693 int pre = 0; 02694 02695 if (!irep->lv 02696 || ((!(r & RA) || GETARG_A(c) >= irep->nlocals) 02697 && (!(r & RB) || GETARG_B(c) >= irep->nlocals))) { 02698 printf("\n"); 02699 return; 02700 } 02701 printf("\t; "); 02702 if (r & RA) { 02703 pre = print_r(mrb, irep, GETARG_A(c), 0); 02704 } 02705 if (r & RB) { 02706 print_r(mrb, irep, GETARG_B(c), pre); 02707 } 02708 printf("\n"); 02709 } 02710 #endif 02711 02712 static void 02713 codedump(mrb_state *mrb, mrb_irep *irep) 02714 { 02715 #ifdef ENABLE_STDIO 02716 int i; 02717 int ai; 02718 mrb_code c; 02719 const char *file = NULL, *next_file; 02720 int32_t line; 02721 02722 if (!irep) return; 02723 printf("irep %p nregs=%d nlocals=%d pools=%d syms=%d reps=%d\n", (void*)irep, 02724 irep->nregs, irep->nlocals, (int)irep->plen, (int)irep->slen, (int)irep->rlen); 02725 02726 for (i = 0; i < (int)irep->ilen; i++) { 02727 ai = mrb_gc_arena_save(mrb); 02728 02729 next_file = mrb_debug_get_filename(irep, i); 02730 if (next_file && file != next_file) { 02731 printf("file: %s\n", next_file); 02732 file = next_file; 02733 } 02734 line = mrb_debug_get_line(irep, i); 02735 if (line < 0) { 02736 printf(" "); 02737 } 02738 else { 02739 printf("%5d ", line); 02740 } 02741 02742 printf("%03d ", i); 02743 c = irep->iseq[i]; 02744 switch (GET_OPCODE(c)) { 02745 case OP_NOP: 02746 printf("OP_NOP\n"); 02747 break; 02748 case OP_MOVE: 02749 printf("OP_MOVE\tR%d\tR%d", GETARG_A(c), GETARG_B(c)); 02750 print_lv(mrb, irep, c, RAB); 02751 break; 02752 case OP_LOADL: 02753 { 02754 mrb_value v = irep->pool[GETARG_Bx(c)]; 02755 mrb_value s = mrb_inspect(mrb, v); 02756 printf("OP_LOADL\tR%d\tL(%d)\t; %s", GETARG_A(c), GETARG_Bx(c), RSTRING_PTR(s)); 02757 } 02758 print_lv(mrb, irep, c, RA); 02759 break; 02760 case OP_LOADI: 02761 printf("OP_LOADI\tR%d\t%d", GETARG_A(c), GETARG_sBx(c)); 02762 print_lv(mrb, irep, c, RA); 02763 break; 02764 case OP_LOADSYM: 02765 printf("OP_LOADSYM\tR%d\t:%s", GETARG_A(c), 02766 mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)])); 02767 print_lv(mrb, irep, c, RA); 02768 break; 02769 case OP_LOADNIL: 02770 printf("OP_LOADNIL\tR%d\t", GETARG_A(c)); 02771 print_lv(mrb, irep, c, RA); 02772 break; 02773 case OP_LOADSELF: 02774 printf("OP_LOADSELF\tR%d\t", GETARG_A(c)); 02775 print_lv(mrb, irep, c, RA); 02776 break; 02777 case OP_LOADT: 02778 printf("OP_LOADT\tR%d\t", GETARG_A(c)); 02779 print_lv(mrb, irep, c, RA); 02780 break; 02781 case OP_LOADF: 02782 printf("OP_LOADF\tR%d\t", GETARG_A(c)); 02783 print_lv(mrb, irep, c, RA); 02784 break; 02785 case OP_GETGLOBAL: 02786 printf("OP_GETGLOBAL\tR%d\t:%s", GETARG_A(c), 02787 mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)])); 02788 print_lv(mrb, irep, c, RA); 02789 break; 02790 case OP_SETGLOBAL: 02791 printf("OP_SETGLOBAL\t:%s\tR%d", 02792 mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]), 02793 GETARG_A(c)); 02794 print_lv(mrb, irep, c, RA); 02795 break; 02796 case OP_GETCONST: 02797 printf("OP_GETCONST\tR%d\t:%s", GETARG_A(c), 02798 mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)])); 02799 print_lv(mrb, irep, c, RA); 02800 break; 02801 case OP_SETCONST: 02802 printf("OP_SETCONST\t:%s\tR%d", 02803 mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]), 02804 GETARG_A(c)); 02805 print_lv(mrb, irep, c, RA); 02806 break; 02807 case OP_GETMCNST: 02808 printf("OP_GETMCNST\tR%d\tR%d::%s", GETARG_A(c), GETARG_A(c), 02809 mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)])); 02810 print_lv(mrb, irep, c, RAB); 02811 break; 02812 case OP_SETMCNST: 02813 printf("OP_SETMCNST\tR%d::%s\tR%d", GETARG_A(c)+1, 02814 mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]), 02815 GETARG_A(c)); 02816 print_lv(mrb, irep, c, RA); 02817 break; 02818 case OP_GETIV: 02819 printf("OP_GETIV\tR%d\t%s", GETARG_A(c), 02820 mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)])); 02821 print_lv(mrb, irep, c, RA); 02822 break; 02823 case OP_SETIV: 02824 printf("OP_SETIV\t%s\tR%d", 02825 mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]), 02826 GETARG_A(c)); 02827 print_lv(mrb, irep, c, RA); 02828 break; 02829 case OP_GETUPVAR: 02830 printf("OP_GETUPVAR\tR%d\t%d\t%d", 02831 GETARG_A(c), GETARG_B(c), GETARG_C(c)); 02832 print_lv(mrb, irep, c, RA); 02833 break; 02834 case OP_SETUPVAR: 02835 printf("OP_SETUPVAR\tR%d\t%d\t%d", 02836 GETARG_A(c), GETARG_B(c), GETARG_C(c)); 02837 print_lv(mrb, irep, c, RA); 02838 break; 02839 case OP_GETCV: 02840 printf("OP_GETCV\tR%d\t%s", GETARG_A(c), 02841 mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)])); 02842 print_lv(mrb, irep, c, RA); 02843 break; 02844 case OP_SETCV: 02845 printf("OP_SETCV\t%s\tR%d", 02846 mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]), 02847 GETARG_A(c)); 02848 print_lv(mrb, irep, c, RA); 02849 break; 02850 case OP_JMP: 02851 printf("OP_JMP\t\t%03d\n", i+GETARG_sBx(c)); 02852 break; 02853 case OP_JMPIF: 02854 printf("OP_JMPIF\tR%d\t%03d\n", GETARG_A(c), i+GETARG_sBx(c)); 02855 break; 02856 case OP_JMPNOT: 02857 printf("OP_JMPNOT\tR%d\t%03d\n", GETARG_A(c), i+GETARG_sBx(c)); 02858 break; 02859 case OP_SEND: 02860 printf("OP_SEND\tR%d\t:%s\t%d\n", GETARG_A(c), 02861 mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), 02862 GETARG_C(c)); 02863 break; 02864 case OP_SENDB: 02865 printf("OP_SENDB\tR%d\t:%s\t%d\n", GETARG_A(c), 02866 mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), 02867 GETARG_C(c)); 02868 break; 02869 case OP_TAILCALL: 02870 printf("OP_TAILCALL\tR%d\t:%s\t%d\n", GETARG_A(c), 02871 mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), 02872 GETARG_C(c)); 02873 break; 02874 case OP_SUPER: 02875 printf("OP_SUPER\tR%d\t%d\n", GETARG_A(c), 02876 GETARG_C(c)); 02877 break; 02878 case OP_ARGARY: 02879 printf("OP_ARGARY\tR%d\t%d:%d:%d:%d", GETARG_A(c), 02880 (GETARG_Bx(c)>>10)&0x3f, 02881 (GETARG_Bx(c)>>9)&0x1, 02882 (GETARG_Bx(c)>>4)&0x1f, 02883 (GETARG_Bx(c)>>0)&0xf); 02884 print_lv(mrb, irep, c, RA); 02885 break; 02886 02887 case OP_ENTER: 02888 printf("OP_ENTER\t%d:%d:%d:%d:%d:%d:%d\n", 02889 (GETARG_Ax(c)>>18)&0x1f, 02890 (GETARG_Ax(c)>>13)&0x1f, 02891 (GETARG_Ax(c)>>12)&0x1, 02892 (GETARG_Ax(c)>>7)&0x1f, 02893 (GETARG_Ax(c)>>2)&0x1f, 02894 (GETARG_Ax(c)>>1)&0x1, 02895 GETARG_Ax(c) & 0x1); 02896 break; 02897 case OP_RETURN: 02898 printf("OP_RETURN\tR%d", GETARG_A(c)); 02899 switch (GETARG_B(c)) { 02900 case OP_R_NORMAL: 02901 case OP_R_RETURN: 02902 printf("\treturn"); break; 02903 case OP_R_BREAK: 02904 printf("\tbreak"); break; 02905 default: 02906 printf("\tbroken"); break; 02907 break; 02908 } 02909 print_lv(mrb, irep, c, RA); 02910 break; 02911 case OP_BLKPUSH: 02912 printf("OP_BLKPUSH\tR%d\t%d:%d:%d:%d", GETARG_A(c), 02913 (GETARG_Bx(c)>>10)&0x3f, 02914 (GETARG_Bx(c)>>9)&0x1, 02915 (GETARG_Bx(c)>>4)&0x1f, 02916 (GETARG_Bx(c)>>0)&0xf); 02917 print_lv(mrb, irep, c, RA); 02918 break; 02919 02920 case OP_LAMBDA: 02921 printf("OP_LAMBDA\tR%d\tI(%+d)\t%d", GETARG_A(c), GETARG_b(c)+1, GETARG_c(c)); 02922 print_lv(mrb, irep, c, RA); 02923 break; 02924 case OP_RANGE: 02925 printf("OP_RANGE\tR%d\tR%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c)); 02926 print_lv(mrb, irep, c, RAB); 02927 break; 02928 case OP_METHOD: 02929 printf("OP_METHOD\tR%d\t:%s", GETARG_A(c), 02930 mrb_sym2name(mrb, irep->syms[GETARG_B(c)])); 02931 print_lv(mrb, irep, c, RA); 02932 break; 02933 02934 case OP_ADD: 02935 printf("OP_ADD\tR%d\t:%s\t%d\n", GETARG_A(c), 02936 mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), 02937 GETARG_C(c)); 02938 break; 02939 case OP_ADDI: 02940 printf("OP_ADDI\tR%d\t:%s\t%d\n", GETARG_A(c), 02941 mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), 02942 GETARG_C(c)); 02943 break; 02944 case OP_SUB: 02945 printf("OP_SUB\tR%d\t:%s\t%d\n", GETARG_A(c), 02946 mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), 02947 GETARG_C(c)); 02948 break; 02949 case OP_SUBI: 02950 printf("OP_SUBI\tR%d\t:%s\t%d\n", GETARG_A(c), 02951 mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), 02952 GETARG_C(c)); 02953 break; 02954 case OP_MUL: 02955 printf("OP_MUL\tR%d\t:%s\t%d\n", GETARG_A(c), 02956 mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), 02957 GETARG_C(c)); 02958 break; 02959 case OP_DIV: 02960 printf("OP_DIV\tR%d\t:%s\t%d\n", GETARG_A(c), 02961 mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), 02962 GETARG_C(c)); 02963 break; 02964 case OP_LT: 02965 printf("OP_LT\tR%d\t:%s\t%d\n", GETARG_A(c), 02966 mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), 02967 GETARG_C(c)); 02968 break; 02969 case OP_LE: 02970 printf("OP_LE\tR%d\t:%s\t%d\n", GETARG_A(c), 02971 mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), 02972 GETARG_C(c)); 02973 break; 02974 case OP_GT: 02975 printf("OP_GT\tR%d\t:%s\t%d\n", GETARG_A(c), 02976 mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), 02977 GETARG_C(c)); 02978 break; 02979 case OP_GE: 02980 printf("OP_GE\tR%d\t:%s\t%d\n", GETARG_A(c), 02981 mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), 02982 GETARG_C(c)); 02983 break; 02984 case OP_EQ: 02985 printf("OP_EQ\tR%d\t:%s\t%d\n", GETARG_A(c), 02986 mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), 02987 GETARG_C(c)); 02988 break; 02989 02990 case OP_STOP: 02991 printf("OP_STOP\n"); 02992 break; 02993 02994 case OP_ARRAY: 02995 printf("OP_ARRAY\tR%d\tR%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c)); 02996 print_lv(mrb, irep, c, RAB); 02997 break; 02998 case OP_ARYCAT: 02999 printf("OP_ARYCAT\tR%d\tR%d", GETARG_A(c), GETARG_B(c)); 03000 print_lv(mrb, irep, c, RAB); 03001 break; 03002 case OP_ARYPUSH: 03003 printf("OP_ARYPUSH\tR%d\tR%d", GETARG_A(c), GETARG_B(c)); 03004 print_lv(mrb, irep, c, RAB); 03005 break; 03006 case OP_AREF: 03007 printf("OP_AREF\tR%d\tR%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c)); 03008 print_lv(mrb, irep, c, RAB); 03009 break; 03010 case OP_APOST: 03011 printf("OP_APOST\tR%d\t%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c)); 03012 print_lv(mrb, irep, c, RAB); 03013 break; 03014 case OP_STRING: 03015 { 03016 mrb_value v = irep->pool[GETARG_Bx(c)]; 03017 mrb_value s = mrb_str_dump(mrb, mrb_str_new(mrb, RSTRING_PTR(v), RSTRING_LEN(v))); 03018 printf("OP_STRING\tR%d\tL(%d)\t; %s", GETARG_A(c), GETARG_Bx(c), RSTRING_PTR(s)); 03019 } 03020 print_lv(mrb, irep, c, RA); 03021 break; 03022 case OP_STRCAT: 03023 printf("OP_STRCAT\tR%d\tR%d", GETARG_A(c), GETARG_B(c)); 03024 print_lv(mrb, irep, c, RAB); 03025 break; 03026 case OP_HASH: 03027 printf("OP_HASH\tR%d\tR%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c)); 03028 print_lv(mrb, irep, c, RAB); 03029 break; 03030 03031 case OP_OCLASS: 03032 printf("OP_OCLASS\tR%d", GETARG_A(c)); 03033 print_lv(mrb, irep, c, RA); 03034 break; 03035 case OP_CLASS: 03036 printf("OP_CLASS\tR%d\t:%s", GETARG_A(c), 03037 mrb_sym2name(mrb, irep->syms[GETARG_B(c)])); 03038 print_lv(mrb, irep, c, RA); 03039 break; 03040 case OP_MODULE: 03041 printf("OP_MODULE\tR%d\t:%s", GETARG_A(c), 03042 mrb_sym2name(mrb, irep->syms[GETARG_B(c)])); 03043 print_lv(mrb, irep, c, RA); 03044 break; 03045 case OP_EXEC: 03046 printf("OP_EXEC\tR%d\tI(%+d)", GETARG_A(c), GETARG_Bx(c)+1); 03047 print_lv(mrb, irep, c, RA); 03048 break; 03049 case OP_SCLASS: 03050 printf("OP_SCLASS\tR%d\tR%d", GETARG_A(c), GETARG_B(c)); 03051 print_lv(mrb, irep, c, RAB); 03052 break; 03053 case OP_TCLASS: 03054 printf("OP_TCLASS\tR%d", GETARG_A(c)); 03055 print_lv(mrb, irep, c, RA); 03056 break; 03057 case OP_ERR: 03058 { 03059 mrb_value v = irep->pool[GETARG_Bx(c)]; 03060 mrb_value s = mrb_str_dump(mrb, mrb_str_new(mrb, RSTRING_PTR(v), RSTRING_LEN(v))); 03061 printf("OP_ERR\t%s\n", RSTRING_PTR(s)); 03062 } 03063 break; 03064 case OP_EPUSH: 03065 printf("OP_EPUSH\t:I(%+d)\n", GETARG_Bx(c)+1); 03066 break; 03067 case OP_ONERR: 03068 printf("OP_ONERR\t%03d\n", i+GETARG_sBx(c)); 03069 break; 03070 case OP_RESCUE: 03071 printf("OP_RESCUE\tR%d", GETARG_A(c)); 03072 print_lv(mrb, irep, c, RA); 03073 break; 03074 case OP_RAISE: 03075 printf("OP_RAISE\tR%d", GETARG_A(c)); 03076 print_lv(mrb, irep, c, RA); 03077 break; 03078 case OP_POPERR: 03079 printf("OP_POPERR\t%d", GETARG_A(c)); 03080 print_lv(mrb, irep, c, RA); 03081 break; 03082 case OP_EPOP: 03083 printf("OP_EPOP\t%d\n", GETARG_A(c)); 03084 break; 03085 03086 default: 03087 printf("OP_unknown %d\t%d\t%d\t%d\n", GET_OPCODE(c), 03088 GETARG_A(c), GETARG_B(c), GETARG_C(c)); 03089 break; 03090 } 03091 mrb_gc_arena_restore(mrb, ai); 03092 } 03093 printf("\n"); 03094 #endif 03095 } 03096 03097 static void 03098 codedump_recur(mrb_state *mrb, mrb_irep *irep) 03099 { 03100 size_t i; 03101 03102 codedump(mrb, irep); 03103 for (i=0; i<irep->rlen; i++) { 03104 codedump_recur(mrb, irep->reps[i]); 03105 } 03106 } 03107 03108 void 03109 mrb_codedump_all(mrb_state *mrb, struct RProc *proc) 03110 { 03111 codedump_recur(mrb, proc->body.irep); 03112 } 03113 03114 MRB_API struct RProc* 03115 mrb_generate_code(mrb_state *mrb, parser_state *p) 03116 { 03117 codegen_scope *scope = scope_new(mrb, 0, 0); 03118 struct RProc *proc; 03119 03120 if (!scope) { 03121 return NULL; 03122 } 03123 scope->mrb = mrb; 03124 scope->parser = p; 03125 scope->filename = p->filename; 03126 scope->filename_index = p->current_filename_index; 03127 03128 MRB_TRY(&scope->jmp) { 03129 /* prepare irep */ 03130 codegen(scope, p->tree, NOVAL); 03131 proc = mrb_proc_new(mrb, scope->irep); 03132 mrb_irep_decref(mrb, scope->irep); 03133 mrb_pool_close(scope->mpool); 03134 return proc; 03135 } 03136 MRB_CATCH(&scope->jmp) { 03137 if (scope->filename == scope->irep->filename) { 03138 scope->irep->filename = NULL; 03139 } 03140 mrb_irep_decref(mrb, scope->irep); 03141 mrb_pool_close(scope->mpool); 03142 return NULL; 03143 } 03144 MRB_END_EXC(&scope->jmp); 03145 } 03146
Generated on Tue Jul 12 2022 18:00:34 by 1.7.2