mbed I/F binding for mruby

Dependents:   mruby_mbed_web mirb_mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers codegen.c Source File

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