Apply PIE to nghttpx
[platform/upstream/nghttp2.git] / third-party / mruby / mrbgems / mruby-compiler / core / codegen.c
1 /*
2 ** codegen.c - mruby code generator
3 **
4 ** See Copyright Notice in mruby.h
5 */
6
7 #include <ctype.h>
8 #include <limits.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <math.h>
12 #include <mruby.h>
13 #include <mruby/compile.h>
14 #include <mruby/proc.h>
15 #include <mruby/numeric.h>
16 #include <mruby/string.h>
17 #include <mruby/debug.h>
18 #include "node.h"
19 #include <mruby/opcode.h>
20 #include <mruby/re.h>
21 #include <mruby/throw.h>
22
23 #ifndef MRB_CODEGEN_LEVEL_MAX
24 #define MRB_CODEGEN_LEVEL_MAX 1024
25 #endif
26
27 #define MAXARG_S (1<<16)
28
29 typedef mrb_ast_node node;
30 typedef struct mrb_parser_state parser_state;
31
32 enum looptype {
33   LOOP_NORMAL,
34   LOOP_BLOCK,
35   LOOP_FOR,
36   LOOP_BEGIN,
37   LOOP_RESCUE,
38 };
39
40 struct loopinfo {
41   enum looptype type;
42   int pc0, pc1, pc2, pc3, acc;
43   int ensure_level;
44   struct loopinfo *prev;
45 };
46
47 typedef struct scope {
48   mrb_state *mrb;
49   mrb_pool *mpool;
50   struct mrb_jmpbuf jmp;
51
52   struct scope *prev;
53
54   node *lv;
55
56   uint16_t sp;
57   uint16_t pc;
58   uint16_t lastpc;
59   uint16_t lastlabel;
60   int ainfo:15;
61   mrb_bool mscope:1;
62
63   struct loopinfo *loop;
64   int ensure_level;
65   mrb_sym filename_sym;
66   uint16_t lineno;
67
68   mrb_code *iseq;
69   uint16_t *lines;
70   uint32_t icapa;
71
72   mrb_irep *irep;
73   uint32_t pcapa, scapa, rcapa;
74
75   uint16_t nlocals;
76   uint16_t nregs;
77   int ai;
78
79   int debug_start_pos;
80   uint16_t filename_index;
81   parser_state* parser;
82
83   int rlev;                     /* recursion levels */
84 } codegen_scope;
85
86 static codegen_scope* scope_new(mrb_state *mrb, codegen_scope *prev, node *lv);
87 static void scope_finish(codegen_scope *s);
88 static struct loopinfo *loop_push(codegen_scope *s, enum looptype t);
89 static void loop_break(codegen_scope *s, node *tree);
90 static void loop_pop(codegen_scope *s, int val);
91
92 static void gen_assignment(codegen_scope *s, node *tree, int sp, int val);
93 static void gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val);
94
95 static void codegen(codegen_scope *s, node *tree, int val);
96 static void raise_error(codegen_scope *s, const char *msg);
97
98 static void
99 codegen_error(codegen_scope *s, const char *message)
100 {
101   if (!s) return;
102   while (s->prev) {
103     codegen_scope *tmp = s->prev;
104     mrb_free(s->mrb, s->iseq);
105     mrb_pool_close(s->mpool);
106     s = tmp;
107   }
108 #ifndef MRB_DISABLE_STDIO
109   if (s->filename_sym && s->lineno) {
110     const char *filename = mrb_sym2name_len(s->mrb, s->filename_sym, NULL);
111     fprintf(stderr, "codegen error:%s:%d: %s\n", filename, s->lineno, message);
112   }
113   else {
114     fprintf(stderr, "codegen error: %s\n", message);
115   }
116 #endif
117   MRB_THROW(&s->jmp);
118 }
119
120 static void*
121 codegen_palloc(codegen_scope *s, size_t len)
122 {
123   void *p = mrb_pool_alloc(s->mpool, len);
124
125   if (!p) codegen_error(s, "pool memory allocation");
126   return p;
127 }
128
129 static void*
130 codegen_realloc(codegen_scope *s, void *p, size_t len)
131 {
132   p = mrb_realloc_simple(s->mrb, p, len);
133
134   if (!p && len > 0) codegen_error(s, "mrb_realloc");
135   return p;
136 }
137
138 static int
139 new_label(codegen_scope *s)
140 {
141   return s->lastlabel = s->pc;
142 }
143
144 static void
145 emit_B(codegen_scope *s, uint32_t pc, uint8_t i)
146 {
147   if (pc >= MAXARG_S || s->icapa >= MAXARG_S) {
148     codegen_error(s, "too big code block");
149   }
150   if (pc >= s->icapa) {
151     s->icapa *= 2;
152     if (s->icapa > MAXARG_S) {
153       s->icapa = MAXARG_S;
154     }
155     s->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->icapa);
156     if (s->lines) {
157       s->lines = (uint16_t*)codegen_realloc(s, s->lines, sizeof(uint16_t)*s->icapa);
158     }
159   }
160   if (s->lines) {
161     if (s->lineno > 0 || pc == 0)
162       s->lines[pc] = s->lineno;
163     else
164       s->lines[pc] = s->lines[pc-1];
165   }
166   s->iseq[pc] = i;
167 }
168
169 static void
170 emit_S(codegen_scope *s, int pc, uint16_t i)
171 {
172   uint8_t hi = i>>8;
173   uint8_t lo = i&0xff;
174
175   emit_B(s, pc,   hi);
176   emit_B(s, pc+1, lo);
177 }
178
179 static void
180 gen_B(codegen_scope *s, uint8_t i)
181 {
182   emit_B(s, s->pc, i);
183   s->pc++;
184 }
185
186 static void
187 gen_S(codegen_scope *s, uint16_t i)
188 {
189   emit_S(s, s->pc, i);
190   s->pc += 2;
191 }
192
193 static void
194 genop_0(codegen_scope *s, mrb_code i)
195 {
196   s->lastpc = s->pc;
197   gen_B(s, i);
198 }
199
200 static void
201 genop_1(codegen_scope *s, mrb_code i, uint16_t a)
202 {
203   s->lastpc = s->pc;
204   if (a > 0xff) {
205     gen_B(s, OP_EXT1);
206     gen_B(s, i);
207     gen_S(s, a);
208   }
209   else {
210     gen_B(s, i);
211     gen_B(s, (uint8_t)a);
212   }
213 }
214
215 static void
216 genop_2(codegen_scope *s, mrb_code i, uint16_t a, uint16_t b)
217 {
218   s->lastpc = s->pc;
219   if (a > 0xff && b > 0xff) {
220     gen_B(s, OP_EXT3);
221     gen_B(s, i);
222     gen_S(s, a);
223     gen_S(s, b);
224   }
225   else if (b > 0xff) {
226     gen_B(s, OP_EXT2);
227     gen_B(s, i);
228     gen_B(s, (uint8_t)a);
229     gen_S(s, b);
230   }
231   else if (a > 0xff) {
232     gen_B(s, OP_EXT1);
233     gen_B(s, i);
234     gen_S(s, a);
235     gen_B(s, (uint8_t)b);
236   }
237   else {
238     gen_B(s, i);
239     gen_B(s, (uint8_t)a);
240     gen_B(s, (uint8_t)b);
241   }
242 }
243
244 static void
245 genop_3(codegen_scope *s, mrb_code i, uint16_t a, uint16_t b, uint8_t c)
246 {
247   genop_2(s, i, a, b);
248   gen_B(s, c);
249 }
250
251 static void
252 genop_2S(codegen_scope *s, mrb_code i, uint16_t a, uint16_t b)
253 {
254   genop_1(s, i, a);
255   gen_S(s, b);
256 }
257
258 static void
259 genop_W(codegen_scope *s, mrb_code i, uint32_t a)
260 {
261   uint8_t a1 = (a>>16) & 0xff;
262   uint8_t a2 = (a>>8) & 0xff;
263   uint8_t a3 = a & 0xff;
264
265   s->lastpc = s->pc;
266   gen_B(s, i);
267   gen_B(s, a1);
268   gen_B(s, a2);
269   gen_B(s, a3);
270 }
271
272 #define NOVAL  0
273 #define VAL    1
274
275 //static
276 mrb_bool
277 no_optimize(codegen_scope *s)
278 {
279   if (s && s->parser && s->parser->no_optimize)
280     return TRUE;
281   return FALSE;
282 }
283
284 static
285 mrb_bool
286 on_eval(codegen_scope *s)
287 {
288   if (s && s->parser && s->parser->on_eval)
289     return TRUE;
290   return FALSE;
291 }
292
293 struct mrb_insn_data
294 mrb_decode_insn(mrb_code *pc)
295 {
296   struct mrb_insn_data data = { 0 };
297   mrb_code insn = READ_B();
298   uint16_t a = 0;
299   uint16_t b = 0;
300   uint8_t  c = 0;
301
302   switch (insn) {
303 #define FETCH_Z() /* empty */
304 #define OPCODE(i,x) case OP_ ## i: FETCH_ ## x (); break;
305 #include "mruby/ops.h"
306 #undef OPCODE
307   }
308   switch (insn) {
309   case OP_EXT1:
310     insn = READ_B();
311     switch (insn) {
312 #define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _1 (); break;
313 #include "mruby/ops.h"
314 #undef OPCODE
315     }
316     break;
317   case OP_EXT2:
318     insn = READ_B();
319     switch (insn) {
320 #define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _2 (); break;
321 #include "mruby/ops.h"
322 #undef OPCODE
323     }
324     break;
325   case OP_EXT3:
326     insn = READ_B();
327     switch (insn) {
328 #define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _3 (); break;
329 #include "mruby/ops.h"
330 #undef OPCODE
331     }
332     break;
333   default:
334     break;
335   }
336   data.insn = insn;
337   data.a = a;
338   data.b = b;
339   data.c = c;
340   return data;
341 }
342
343 static struct mrb_insn_data
344 mrb_last_insn(codegen_scope *s)
345 {
346   if (s->pc == s->lastpc) {
347     struct mrb_insn_data data;
348
349     data.insn = OP_NOP;
350     return data;
351   }
352   return mrb_decode_insn(&s->iseq[s->lastpc]);
353 }
354
355 static mrb_bool
356 no_peephole(codegen_scope *s)
357 {
358   return no_optimize(s) || s->lastlabel == s->pc || s->pc == 0 || s->pc == s->lastpc;
359 }
360
361 static uint16_t
362 genjmp(codegen_scope *s, mrb_code i, uint16_t pc)
363 {
364   uint16_t pos;
365
366   s->lastpc = s->pc;
367   gen_B(s, i);
368   pos = s->pc;
369   gen_S(s, pc);
370   return pos;
371 }
372
373 static uint16_t
374 genjmp2(codegen_scope *s, mrb_code i, uint16_t a, int pc, int val)
375 {
376   uint16_t pos;
377
378   if (!no_peephole(s) && !val) {
379     struct mrb_insn_data data = mrb_last_insn(s);
380
381     if (data.insn == OP_MOVE && data.a == a) {
382       s->pc = s->lastpc;
383       a = data.b;
384     }
385   }
386
387   s->lastpc = s->pc;
388   if (a > 0xff) {
389     gen_B(s, OP_EXT1);
390     gen_B(s, i);
391     gen_S(s, a);
392     pos = s->pc;
393     gen_S(s, pc);
394   }
395   else {
396     gen_B(s, i);
397     gen_B(s, (uint8_t)a);
398     pos = s->pc;
399     gen_S(s, pc);
400   }
401   return pos;
402 }
403
404 static void
405 gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep)
406 {
407   if (no_peephole(s)) {
408   normal:
409     genop_2(s, OP_MOVE, dst, src);
410     if (on_eval(s)) {
411       genop_0(s, OP_NOP);
412     }
413     return;
414   }
415   else {
416     struct mrb_insn_data data = mrb_last_insn(s);
417
418     switch (data.insn) {
419     case OP_MOVE:
420       if (dst == src) return;             /* remove useless MOVE */
421       if (data.b == dst && data.a == src) /* skip swapping MOVE */
422         return;
423       goto normal;
424     case OP_LOADNIL: case OP_LOADSELF: case OP_LOADT: case OP_LOADF:
425     case OP_LOADI__1:
426     case OP_LOADI_0: case OP_LOADI_1: case OP_LOADI_2: case OP_LOADI_3:
427     case OP_LOADI_4: case OP_LOADI_5: case OP_LOADI_6: case OP_LOADI_7:
428       if (nopeep || data.a != src || data.a < s->nlocals) goto normal;
429       s->pc = s->lastpc;
430       genop_1(s, data.insn, dst);
431       break;
432     case OP_LOADI: case OP_LOADINEG: case OP_LOADL: case OP_LOADSYM:
433     case OP_GETGV: case OP_GETSV: case OP_GETIV: case OP_GETCV:
434     case OP_GETCONST: case OP_STRING:
435     case OP_LAMBDA: case OP_BLOCK: case OP_METHOD: case OP_BLKPUSH:
436       if (nopeep || data.a != src || data.a < s->nlocals) goto normal;
437       s->pc = s->lastpc;
438       genop_2(s, data.insn, dst, data.b);
439       break;
440     default:
441       goto normal;
442     }
443   }
444 }
445
446 static void
447 gen_return(codegen_scope *s, uint8_t op, uint16_t src)
448 {
449   if (no_peephole(s)) {
450     genop_1(s, op, src);
451   }
452   else {
453     struct mrb_insn_data data = mrb_last_insn(s);
454
455     if (data.insn == OP_MOVE && src == data.a) {
456       s->pc = s->lastpc;
457       genop_1(s, op, data.b);
458     }
459     else if (data.insn != OP_RETURN) {
460       genop_1(s, op, src);
461     }
462   }
463 }
464
465 static void
466 gen_addsub(codegen_scope *s, uint8_t op, uint16_t dst)
467 {
468   if (no_peephole(s)) {
469   normal:
470     genop_1(s, op, dst);
471     return;
472   }
473   else {
474     struct mrb_insn_data data = mrb_last_insn(s);
475
476     switch (data.insn) {
477     case OP_LOADI__1:
478       if (op == OP_ADD) op = OP_SUB;
479       else op = OP_ADD;
480       data.b = 1;
481       goto replace;
482     case OP_LOADI_0: case OP_LOADI_1: case OP_LOADI_2: case OP_LOADI_3:
483     case OP_LOADI_4: case OP_LOADI_5: case OP_LOADI_6: case OP_LOADI_7:
484       data.b = data.insn - OP_LOADI_0;
485       /* fall through */
486     case OP_LOADI:
487     replace:
488       if (data.b >= 128) goto normal;
489       s->pc = s->lastpc;
490       if (op == OP_ADD) {
491         genop_2(s, OP_ADDI, dst, (uint8_t)data.b);
492       }
493       else {
494         genop_2(s, OP_SUBI, dst, (uint8_t)data.b);
495       }
496       break;
497     default:
498       goto normal;
499     }
500   }
501 }
502
503 static int
504 dispatch(codegen_scope *s, uint16_t pos0)
505 {
506   uint16_t newpos;
507
508   s->lastlabel = s->pc;
509   newpos = PEEK_S(s->iseq+pos0);
510   emit_S(s, pos0, s->pc);
511   return newpos;
512 }
513
514 static void
515 dispatch_linked(codegen_scope *s, uint16_t pos)
516 {
517   if (pos==0) return;
518   for (;;) {
519     pos = dispatch(s, pos);
520     if (pos==0) break;
521   }
522 }
523
524 #define nregs_update do {if (s->sp > s->nregs) s->nregs = s->sp;} while (0)
525 static void
526 push_n_(codegen_scope *s, int n)
527 {
528   if (s->sp+n >= 0xffff) {
529     codegen_error(s, "too complex expression");
530   }
531   s->sp+=n;
532   nregs_update;
533 }
534
535 static void
536 pop_n_(codegen_scope *s, int n)
537 {
538   if ((int)s->sp-n < 0) {
539     codegen_error(s, "stack pointer underflow");
540   }
541   s->sp-=n;
542 }
543
544 #define push() push_n_(s,1)
545 #define push_n(n) push_n_(s,n)
546 #define pop() pop_n_(s,1)
547 #define pop_n(n) pop_n_(s,n)
548 #define cursp() (s->sp)
549
550 static inline int
551 new_lit(codegen_scope *s, mrb_value val)
552 {
553   int i;
554   mrb_value *pv;
555
556   switch (mrb_type(val)) {
557   case MRB_TT_STRING:
558     for (i=0; i<s->irep->plen; i++) {
559       mrb_int len;
560       pv = &s->irep->pool[i];
561
562       if (mrb_type(*pv) != MRB_TT_STRING) continue;
563       if ((len = RSTRING_LEN(*pv)) != RSTRING_LEN(val)) continue;
564       if (memcmp(RSTRING_PTR(*pv), RSTRING_PTR(val), len) == 0)
565         return i;
566     }
567     break;
568 #ifndef MRB_WITHOUT_FLOAT
569   case MRB_TT_FLOAT:
570     for (i=0; i<s->irep->plen; i++) {
571       mrb_float f1, f2;
572       pv = &s->irep->pool[i];
573       if (mrb_type(*pv) != MRB_TT_FLOAT) continue;
574       f1 = mrb_float(*pv);
575       f2 = mrb_float(val);
576       if (f1 == f2 && !signbit(f1) == !signbit(f2)) return i;
577     }
578     break;
579 #endif
580   case MRB_TT_FIXNUM:
581     for (i=0; i<s->irep->plen; i++) {
582       pv = &s->irep->pool[i];
583       if (!mrb_fixnum_p(*pv)) continue;
584       if (mrb_fixnum(*pv) == mrb_fixnum(val)) return i;
585     }
586     break;
587   default:
588     /* should not happen */
589     return 0;
590   }
591
592   if (s->irep->plen == s->pcapa) {
593     s->pcapa *= 2;
594     s->irep->pool = (mrb_value *)codegen_realloc(s, s->irep->pool, sizeof(mrb_value)*s->pcapa);
595   }
596
597   pv = &s->irep->pool[s->irep->plen];
598   i = s->irep->plen++;
599
600   switch (mrb_type(val)) {
601   case MRB_TT_STRING:
602     *pv = mrb_str_pool(s->mrb, val);
603     break;
604
605 #ifndef MRB_WITHOUT_FLOAT
606   case MRB_TT_FLOAT:
607 #ifdef MRB_WORD_BOXING
608     *pv = mrb_float_pool(s->mrb, mrb_float(val));
609     break;
610 #endif
611 #endif
612   case MRB_TT_FIXNUM:
613     *pv = val;
614     break;
615
616   default:
617     /* should not happen */
618     break;
619   }
620   return i;
621 }
622
623 /* maximum symbol numbers */
624 #define MAXSYMLEN 0x10000
625
626 static int
627 new_sym(codegen_scope *s, mrb_sym sym)
628 {
629   int i, len;
630
631   mrb_assert(s->irep);
632
633   len = s->irep->slen;
634   for (i=0; i<len; i++) {
635     if (s->irep->syms[i] == sym) return i;
636   }
637   if (s->irep->slen >= s->scapa) {
638     s->scapa *= 2;
639     s->irep->syms = (mrb_sym*)codegen_realloc(s, s->irep->syms, sizeof(mrb_sym)*s->scapa);
640   }
641   s->irep->syms[s->irep->slen] = sym;
642   return s->irep->slen++;
643 }
644
645 static int
646 node_len(node *tree)
647 {
648   int n = 0;
649
650   while (tree) {
651     n++;
652     tree = tree->cdr;
653   }
654   return n;
655 }
656
657 #define nint(x) ((int)(intptr_t)(x))
658 #define nchar(x) ((char)(intptr_t)(x))
659 #define nsym(x) ((mrb_sym)(intptr_t)(x))
660
661 #define lv_name(lv) nsym((lv)->car)
662
663 static int
664 lv_idx(codegen_scope *s, mrb_sym id)
665 {
666   node *lv = s->lv;
667   int n = 1;
668
669   while (lv) {
670     if (lv_name(lv) == id) return n;
671     n++;
672     lv = lv->cdr;
673   }
674   return 0;
675 }
676
677 static void
678 for_body(codegen_scope *s, node *tree)
679 {
680   codegen_scope *prev = s;
681   int idx;
682   struct loopinfo *lp;
683   node *n2;
684
685   /* generate receiver */
686   codegen(s, tree->cdr->car, VAL);
687   /* generate loop-block */
688   s = scope_new(s->mrb, s, NULL);
689   if (s == NULL) {
690     raise_error(prev, "unexpected scope");
691   }
692
693   push();                       /* push for a block parameter */
694
695   /* generate loop variable */
696   n2 = tree->car;
697   genop_W(s, OP_ENTER, 0x40000);
698   if (n2->car && !n2->car->cdr && !n2->cdr) {
699     gen_assignment(s, n2->car->car, 1, NOVAL);
700   }
701   else {
702     gen_vmassignment(s, n2, 1, VAL);
703   }
704   /* construct loop */
705   lp = loop_push(s, LOOP_FOR);
706   lp->pc2 = new_label(s);
707
708   /* loop body */
709   codegen(s, tree->cdr->cdr->car, VAL);
710   pop();
711   gen_return(s, OP_RETURN, cursp());
712   loop_pop(s, NOVAL);
713   scope_finish(s);
714   s = prev;
715   genop_2(s, OP_BLOCK, cursp(), s->irep->rlen-1);
716   push();pop(); /* space for a block */
717   pop();
718   idx = new_sym(s, mrb_intern_lit(s->mrb, "each"));
719   genop_3(s, OP_SENDB, cursp(), idx, 0);
720 }
721
722 static int
723 lambda_body(codegen_scope *s, node *tree, int blk)
724 {
725   codegen_scope *parent = s;
726   s = scope_new(s->mrb, s, tree->car);
727   if (s == NULL) {
728     raise_error(parent, "unexpected scope");
729   }
730
731   s->mscope = !blk;
732
733   if (blk) {
734     struct loopinfo *lp = loop_push(s, LOOP_BLOCK);
735     lp->pc0 = new_label(s);
736   }
737   tree = tree->cdr;
738   if (tree->car == NULL) {
739     genop_W(s, OP_ENTER, 0);
740   }
741   else {
742     mrb_aspec a;
743     int ma, oa, ra, pa, ka, kd, ba;
744     int pos, i;
745     node *opt;
746     node *margs, *pargs;
747     node *tail;
748
749     /* mandatory arguments */
750     ma = node_len(tree->car->car);
751     margs = tree->car->car;
752     tail = tree->car->cdr->cdr->cdr->cdr;
753
754     /* optional arguments */
755     oa = node_len(tree->car->cdr->car);
756     /* rest argument? */
757     ra = tree->car->cdr->cdr->car ? 1 : 0;
758     /* mandatory arugments after rest argument */
759     pa = node_len(tree->car->cdr->cdr->cdr->car);
760     pargs = tree->car->cdr->cdr->cdr->car;
761     /* keyword arguments */
762     ka = tail? node_len(tail->cdr->car) : 0;
763     /* keyword dictionary? */
764     kd = tail && tail->cdr->cdr->car? 1 : 0;
765     /* block argument? */
766     ba = tail && tail->cdr->cdr->cdr->car ? 1 : 0;
767
768     if (ma > 0x1f || oa > 0x1f || pa > 0x1f || ka > 0x1f) {
769       codegen_error(s, "too many formal arguments");
770     }
771     a = MRB_ARGS_REQ(ma)
772       | MRB_ARGS_OPT(oa)
773       | (ra? MRB_ARGS_REST() : 0)
774       | MRB_ARGS_POST(pa)
775       | MRB_ARGS_KEY(ka, kd)
776       | (ba? MRB_ARGS_BLOCK() : 0);
777     s->ainfo = (((ma+oa) & 0x3f) << 7) /* (12bits = 5:1:5:1) */
778       | ((ra & 0x1) << 6)
779       | ((pa & 0x1f) << 1)
780       | (kd & 0x1);
781     genop_W(s, OP_ENTER, a);
782     /* generate jump table for optional arguments initializer */
783     pos = new_label(s);
784     for (i=0; i<oa; i++) {
785       new_label(s);
786       genjmp(s, OP_JMP, 0);
787     }
788     if (oa > 0) {
789       genjmp(s, OP_JMP, 0);
790     }
791     opt = tree->car->cdr->car;
792     i = 0;
793     while (opt) {
794       int idx;
795
796       dispatch(s, pos+i*3+1);
797       codegen(s, opt->car->cdr, VAL);
798       pop();
799       idx = lv_idx(s, nsym(opt->car->car));
800       gen_move(s, idx, cursp(), 0);
801       i++;
802       opt = opt->cdr;
803     }
804     if (oa > 0) {
805       dispatch(s, pos+i*3+1);
806     }
807
808     /* keyword arguments */
809     if (tail) {
810       node *kwds = tail->cdr->car;
811       int kwrest = 0;
812
813       if (tail->cdr->cdr->car) {
814         kwrest = 1;
815       }
816       mrb_assert(nint(tail->car) == NODE_ARGS_TAIL);
817       mrb_assert(node_len(tail) == 4);
818
819       while (kwds) {
820         int jmpif_key_p, jmp_def_set = -1;
821         node *kwd = kwds->car, *def_arg = kwd->cdr->cdr->car;
822         mrb_sym kwd_sym = nsym(kwd->cdr->car);
823
824         mrb_assert(nint(kwd->car) == NODE_KW_ARG);
825
826         if (def_arg) {
827           genop_2(s, OP_KEY_P, lv_idx(s, kwd_sym), new_sym(s, kwd_sym));
828           jmpif_key_p = genjmp2(s, OP_JMPIF, lv_idx(s, kwd_sym), 0, 0);
829           codegen(s, def_arg, VAL);
830           pop();
831           gen_move(s, lv_idx(s, kwd_sym), cursp(), 0);
832           jmp_def_set = genjmp(s, OP_JMP, 0);
833           dispatch(s, jmpif_key_p);
834         }
835         genop_2(s, OP_KARG, lv_idx(s, kwd_sym), new_sym(s, kwd_sym));
836         if (jmp_def_set != -1) {
837           dispatch(s, jmp_def_set);
838         }
839         i++;
840
841         kwds = kwds->cdr;
842       }
843       if (tail->cdr->car && !kwrest) {
844         genop_0(s, OP_KEYEND);
845       }
846     }
847
848     /* argument destructuring */
849     if (margs) {
850       node *n = margs;
851
852       pos = 1;
853       while (n) {
854         if (nint(n->car->car) == NODE_MASGN) {
855           gen_vmassignment(s, n->car->cdr->car, pos, NOVAL);
856         }
857         pos++;
858         n = n->cdr;
859       }
860     }
861     if (pargs) {
862       node *n = margs;
863
864       pos = ma+oa+ra+1;
865       while (n) {
866         if (nint(n->car->car) == NODE_MASGN) {
867           gen_vmassignment(s, n->car->cdr->car, pos, NOVAL);
868         }
869         pos++;
870         n = n->cdr;
871       }
872     }
873   }
874
875   codegen(s, tree->cdr->car, VAL);
876   pop();
877   if (s->pc > 0) {
878     gen_return(s, OP_RETURN, cursp());
879   }
880   if (blk) {
881     loop_pop(s, NOVAL);
882   }
883   scope_finish(s);
884   return parent->irep->rlen - 1;
885 }
886
887 static int
888 scope_body(codegen_scope *s, node *tree, int val)
889 {
890   codegen_scope *scope = scope_new(s->mrb, s, tree->car);
891   if (scope == NULL) {
892     codegen_error(s, "unexpected scope");
893   }
894
895   codegen(scope, tree->cdr, VAL);
896   gen_return(scope, OP_RETURN, scope->sp-1);
897   if (!s->iseq) {
898     genop_0(scope, OP_STOP);
899   }
900   scope_finish(scope);
901   if (!s->irep) {
902     /* should not happen */
903     return 0;
904   }
905   return s->irep->rlen - 1;
906 }
907
908 static mrb_bool
909 nosplat(node *t)
910 {
911   while (t) {
912     if (nint(t->car->car) == NODE_SPLAT) return FALSE;
913     t = t->cdr;
914   }
915   return TRUE;
916 }
917
918 static mrb_sym
919 attrsym(codegen_scope *s, mrb_sym a)
920 {
921   const char *name;
922   mrb_int len;
923   char *name2;
924
925   name = mrb_sym2name_len(s->mrb, a, &len);
926   name2 = (char *)codegen_palloc(s,
927                                  (size_t)len
928                                  + 1 /* '=' */
929                                  + 1 /* '\0' */
930                                  );
931   mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX);
932   memcpy(name2, name, (size_t)len);
933   name2[len] = '=';
934   name2[len+1] = '\0';
935
936   return mrb_intern(s->mrb, name2, len+1);
937 }
938
939 #define CALL_MAXARGS 127
940
941 static int
942 gen_values(codegen_scope *s, node *t, int val, int extra)
943 {
944   int n = 0;
945   int is_splat;
946
947   while (t) {
948     is_splat = nint(t->car->car) == NODE_SPLAT; /* splat mode */
949     if (
950       n+extra >= CALL_MAXARGS - 1 /* need to subtract one because vm.c expects an array if n == CALL_MAXARGS */
951       || is_splat) {
952       if (val) {
953         if (is_splat && n == 0 && nint(t->car->cdr->car) == NODE_ARRAY) {
954           codegen(s, t->car->cdr, VAL);
955           pop();
956         }
957         else {
958           pop_n(n);
959           genop_2(s, OP_ARRAY, cursp(), n);
960           push();
961           codegen(s, t->car, VAL);
962           pop(); pop();
963           if (is_splat) {
964             genop_1(s, OP_ARYCAT, cursp());
965           }
966           else {
967             genop_1(s, OP_ARYPUSH, cursp());
968           }
969         }
970         t = t->cdr;
971         while (t) {
972           push();
973           codegen(s, t->car, VAL);
974           pop(); pop();
975           if (nint(t->car->car) == NODE_SPLAT) {
976             genop_1(s, OP_ARYCAT, cursp());
977           }
978           else {
979             genop_1(s, OP_ARYPUSH, cursp());
980           }
981           t = t->cdr;
982         }
983       }
984       else {
985         while (t) {
986           codegen(s, t->car, NOVAL);
987           t = t->cdr;
988         }
989       }
990       return -1;
991     }
992     /* normal (no splat) mode */
993     codegen(s, t->car, val);
994     n++;
995     t = t->cdr;
996   }
997   return n;
998 }
999
1000 static void
1001 gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe)
1002 {
1003   mrb_sym sym = name ? name : nsym(tree->cdr->car);
1004   int skip = 0;
1005   int n = 0, noop = 0, sendv = 0, blk = 0;
1006
1007   codegen(s, tree->car, VAL); /* receiver */
1008   if (safe) {
1009     int recv = cursp()-1;
1010     gen_move(s, cursp(), recv, 1);
1011     skip = genjmp2(s, OP_JMPNIL, cursp(), 0, val);
1012   }
1013   tree = tree->cdr->cdr->car;
1014   if (tree) {
1015     n = gen_values(s, tree->car, VAL, sp?1:0);
1016     if (n < 0) {
1017       n = noop = sendv = 1;
1018       push();
1019     }
1020   }
1021   if (sp) {                     /* last argument pushed (attr=) */
1022     if (sendv) {
1023       gen_move(s, cursp(), sp, 0);
1024       pop();
1025       genop_1(s, OP_ARYPUSH, cursp());
1026       push();
1027     }
1028     else {
1029       gen_move(s, cursp(), sp, 0);
1030       push();
1031       n++;
1032     }
1033   }
1034   if (tree && tree->cdr) {
1035     noop = 1;
1036     codegen(s, tree->cdr, VAL);
1037     pop();
1038     blk = 1;
1039   }
1040   push();pop();
1041   pop_n(n+1);
1042   {
1043     mrb_int symlen;
1044     const char *symname = mrb_sym2name_len(s->mrb, sym, &symlen);
1045
1046     if (!noop && symlen == 1 && symname[0] == '+' && n == 1)  {
1047       gen_addsub(s, OP_ADD, cursp());
1048     }
1049     else if (!noop && symlen == 1 && symname[0] == '-' && n == 1)  {
1050       gen_addsub(s, OP_SUB, cursp());
1051     }
1052     else if (!noop && symlen == 1 && symname[0] == '*' && n == 1)  {
1053       genop_1(s, OP_MUL, cursp());
1054     }
1055     else if (!noop && symlen == 1 && symname[0] == '/' && n == 1)  {
1056       genop_1(s, OP_DIV, cursp());
1057     }
1058     else if (!noop && symlen == 1 && symname[0] == '<' && n == 1)  {
1059       genop_1(s, OP_LT, cursp());
1060     }
1061     else if (!noop && symlen == 2 && symname[0] == '<' && symname[1] == '=' && n == 1)  {
1062       genop_1(s, OP_LE, cursp());
1063     }
1064     else if (!noop && symlen == 1 && symname[0] == '>' && n == 1)  {
1065       genop_1(s, OP_GT, cursp());
1066     }
1067     else if (!noop && symlen == 2 && symname[0] == '>' && symname[1] == '=' && n == 1)  {
1068       genop_1(s, OP_GE, cursp());
1069     }
1070     else if (!noop && symlen == 2 && symname[0] == '=' && symname[1] == '=' && n == 1)  {
1071       genop_1(s, OP_EQ, cursp());
1072     }
1073     else {
1074       int idx = new_sym(s, sym);
1075
1076       if (sendv) {
1077         genop_2(s, blk ? OP_SENDVB : OP_SENDV, cursp(), idx);
1078       }
1079       else {
1080         genop_3(s, blk ? OP_SENDB : OP_SEND, cursp(), idx, n);
1081       }
1082     }
1083   }
1084   if (safe) {
1085     dispatch(s, skip);
1086   }
1087   if (val) {
1088     push();
1089   }
1090 }
1091
1092 static void
1093 gen_assignment(codegen_scope *s, node *tree, int sp, int val)
1094 {
1095   int idx;
1096   int type = nint(tree->car);
1097
1098   tree = tree->cdr;
1099   switch (type) {
1100   case NODE_GVAR:
1101     idx = new_sym(s, nsym(tree));
1102     genop_2(s, OP_SETGV, sp, idx);
1103     break;
1104   case NODE_ARG:
1105   case NODE_LVAR:
1106     idx = lv_idx(s, nsym(tree));
1107     if (idx > 0) {
1108       if (idx != sp) {
1109         gen_move(s, idx, sp, val);
1110         if (val && on_eval(s)) genop_0(s, OP_NOP);
1111       }
1112       break;
1113     }
1114     else {                      /* upvar */
1115       int lv = 0;
1116       codegen_scope *up = s->prev;
1117
1118       while (up) {
1119         idx = lv_idx(up, nsym(tree));
1120         if (idx > 0) {
1121           genop_3(s, OP_SETUPVAR, sp, idx, lv);
1122           break;
1123         }
1124         lv++;
1125         up = up->prev;
1126       }
1127     }
1128     break;
1129   case NODE_IVAR:
1130     idx = new_sym(s, nsym(tree));
1131     genop_2(s, OP_SETIV, sp, idx);
1132     break;
1133   case NODE_CVAR:
1134     idx = new_sym(s, nsym(tree));
1135     genop_2(s, OP_SETCV, sp, idx);
1136     break;
1137   case NODE_CONST:
1138     idx = new_sym(s, nsym(tree));
1139     genop_2(s, OP_SETCONST, sp, idx);
1140     break;
1141   case NODE_COLON2:
1142     gen_move(s, cursp(), sp, 0);
1143     push();
1144     codegen(s, tree->car, VAL);
1145     pop_n(2);
1146     idx = new_sym(s, nsym(tree->cdr));
1147     genop_2(s, OP_SETMCNST, sp, idx);
1148     break;
1149
1150   case NODE_CALL:
1151   case NODE_SCALL:
1152     push();
1153     gen_call(s, tree, attrsym(s, nsym(tree->cdr->car)), sp, NOVAL,
1154              type == NODE_SCALL);
1155     pop();
1156     if (val) {
1157       gen_move(s, cursp(), sp, 0);
1158     }
1159     break;
1160
1161   case NODE_MASGN:
1162     gen_vmassignment(s, tree->car, sp, val);
1163     break;
1164
1165   /* splat without assignment */
1166   case NODE_NIL:
1167     break;
1168
1169   default:
1170 #ifndef MRB_DISABLE_STDIO
1171     fprintf(stderr, "unknown lhs %d\n", type);
1172 #endif
1173     break;
1174   }
1175   if (val) push();
1176 }
1177
1178 static void
1179 gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val)
1180 {
1181   int n = 0, post = 0;
1182   node *t, *p;
1183
1184   if (tree->car) {              /* pre */
1185     t = tree->car;
1186     n = 0;
1187     while (t) {
1188       int sp = cursp();
1189
1190       genop_3(s, OP_AREF, sp, rhs, n);
1191       push();
1192       gen_assignment(s, t->car, sp, NOVAL);
1193       pop();
1194       n++;
1195       t = t->cdr;
1196     }
1197   }
1198   t = tree->cdr;
1199   if (t) {
1200     if (t->cdr) {               /* post count */
1201       p = t->cdr->car;
1202       while (p) {
1203         post++;
1204         p = p->cdr;
1205       }
1206     }
1207     gen_move(s, cursp(), rhs, val);
1208     push_n(post+1);
1209     pop_n(post+1);
1210     genop_3(s, OP_APOST, cursp(), n, post);
1211     n = 1;
1212     if (t->car && t->car != (node*)-1) { /* rest */
1213       gen_assignment(s, t->car, cursp(), NOVAL);
1214     }
1215     if (t->cdr && t->cdr->car) {
1216       t = t->cdr->car;
1217       while (t) {
1218         gen_assignment(s, t->car, cursp()+n, NOVAL);
1219         t = t->cdr;
1220         n++;
1221       }
1222     }
1223     if (val) {
1224       gen_move(s, cursp(), rhs, 0);
1225     }
1226   }
1227 }
1228
1229 static void
1230 gen_intern(codegen_scope *s)
1231 {
1232   pop();
1233   genop_1(s, OP_INTERN, cursp());
1234   push();
1235 }
1236
1237 static void
1238 gen_literal_array(codegen_scope *s, node *tree, mrb_bool sym, int val)
1239 {
1240   if (val) {
1241     int i = 0, j = 0;
1242
1243     while (tree) {
1244       switch (nint(tree->car->car)) {
1245       case NODE_STR:
1246         if ((tree->cdr == NULL) && (nint(tree->car->cdr->cdr) == 0))
1247           break;
1248         /* fall through */
1249       case NODE_BEGIN:
1250         codegen(s, tree->car, VAL);
1251         ++j;
1252         break;
1253
1254       case NODE_LITERAL_DELIM:
1255         if (j > 0) {
1256           j = 0;
1257           ++i;
1258           if (sym)
1259             gen_intern(s);
1260         }
1261         break;
1262       }
1263       while (j >= 2) {
1264         pop(); pop();
1265         genop_1(s, OP_STRCAT, cursp());
1266         push();
1267         j--;
1268       }
1269       tree = tree->cdr;
1270     }
1271     if (j > 0) {
1272       ++i;
1273       if (sym)
1274         gen_intern(s);
1275     }
1276     pop_n(i);
1277     genop_2(s, OP_ARRAY, cursp(), i);
1278     push();
1279   }
1280   else {
1281     while (tree) {
1282       switch (nint(tree->car->car)) {
1283       case NODE_BEGIN: case NODE_BLOCK:
1284         codegen(s, tree->car, NOVAL);
1285       }
1286       tree = tree->cdr;
1287     }
1288   }
1289 }
1290
1291 static void
1292 raise_error(codegen_scope *s, const char *msg)
1293 {
1294   int idx = new_lit(s, mrb_str_new_cstr(s->mrb, msg));
1295
1296   genop_1(s, OP_ERR, idx);
1297 }
1298
1299 #ifndef MRB_WITHOUT_FLOAT
1300 static double
1301 readint_float(codegen_scope *s, const char *p, int base)
1302 {
1303   const char *e = p + strlen(p);
1304   double f = 0;
1305   int n;
1306
1307   if (*p == '+') p++;
1308   while (p < e) {
1309     char c = *p;
1310     c = tolower((unsigned char)c);
1311     for (n=0; n<base; n++) {
1312       if (mrb_digitmap[n] == c) {
1313         f *= base;
1314         f += n;
1315         break;
1316       }
1317     }
1318     if (n == base) {
1319       codegen_error(s, "malformed readint input");
1320     }
1321     p++;
1322   }
1323   return f;
1324 }
1325 #endif
1326
1327 static mrb_int
1328 readint_mrb_int(codegen_scope *s, const char *p, int base, mrb_bool neg, mrb_bool *overflow)
1329 {
1330   const char *e = p + strlen(p);
1331   mrb_int result = 0;
1332   int n;
1333
1334   mrb_assert(base >= 2 && base <= 36);
1335   if (*p == '+') p++;
1336   while (p < e) {
1337     char c = *p;
1338     c = tolower((unsigned char)c);
1339     for (n=0; n<base; n++) {
1340       if (mrb_digitmap[n] == c) {
1341         break;
1342       }
1343     }
1344     if (n == base) {
1345       codegen_error(s, "malformed readint input");
1346     }
1347
1348     if (neg) {
1349       if ((MRB_INT_MIN + n)/base > result) {
1350         *overflow = TRUE;
1351         return 0;
1352       }
1353       result *= base;
1354       result -= n;
1355     }
1356     else {
1357       if ((MRB_INT_MAX - n)/base < result) {
1358         *overflow = TRUE;
1359         return 0;
1360       }
1361       result *= base;
1362       result += n;
1363     }
1364     p++;
1365   }
1366   *overflow = FALSE;
1367   return result;
1368 }
1369
1370 static void
1371 gen_retval(codegen_scope *s, node *tree)
1372 {
1373   if (nint(tree->car) == NODE_SPLAT) {
1374     codegen(s, tree, VAL);
1375     pop();
1376     genop_1(s, OP_ARYDUP, cursp());
1377   }
1378   else {
1379     codegen(s, tree, VAL);
1380     pop();
1381   }
1382 }
1383
1384 static void
1385 codegen(codegen_scope *s, node *tree, int val)
1386 {
1387   int nt;
1388   int rlev = s->rlev;
1389
1390   if (!tree) {
1391     if (val) {
1392       genop_1(s, OP_LOADNIL, cursp());
1393       push();
1394     }
1395     return;
1396   }
1397
1398   s->rlev++;
1399   if (s->rlev > MRB_CODEGEN_LEVEL_MAX) {
1400     codegen_error(s, "too complex expression");
1401   }
1402   if (s->irep && s->filename_index != tree->filename_index) {
1403     mrb_sym fname = mrb_parser_get_filename(s->parser, s->filename_index);
1404     const char *filename = mrb_sym2name_len(s->mrb, fname, NULL);
1405
1406     mrb_debug_info_append_file(s->mrb, s->irep->debug_info,
1407                                filename, s->lines, s->debug_start_pos, s->pc);
1408     s->debug_start_pos = s->pc;
1409     s->filename_index = tree->filename_index;
1410     s->filename_sym = mrb_parser_get_filename(s->parser, tree->filename_index);
1411   }
1412
1413   nt = nint(tree->car);
1414   s->lineno = tree->lineno;
1415   tree = tree->cdr;
1416   switch (nt) {
1417   case NODE_BEGIN:
1418     if (val && !tree) {
1419       genop_1(s, OP_LOADNIL, cursp());
1420       push();
1421     }
1422     while (tree) {
1423       codegen(s, tree->car, tree->cdr ? NOVAL : val);
1424       tree = tree->cdr;
1425     }
1426     break;
1427
1428   case NODE_RESCUE:
1429     {
1430       int noexc, exend, pos1, pos2, tmp;
1431       struct loopinfo *lp;
1432
1433       if (tree->car == NULL) goto exit;
1434       lp = loop_push(s, LOOP_BEGIN);
1435       lp->pc0 = new_label(s);
1436       lp->pc1 = genjmp(s, OP_ONERR, 0);
1437       codegen(s, tree->car, VAL);
1438       pop();
1439       lp->type = LOOP_RESCUE;
1440       noexc = genjmp(s, OP_JMP, 0);
1441       dispatch(s, lp->pc1);
1442       tree = tree->cdr;
1443       exend = 0;
1444       pos1 = 0;
1445       if (tree->car) {
1446         node *n2 = tree->car;
1447         int exc = cursp();
1448
1449         genop_1(s, OP_EXCEPT, exc);
1450         push();
1451         while (n2) {
1452           node *n3 = n2->car;
1453           node *n4 = n3->car;
1454
1455           if (pos1) dispatch(s, pos1);
1456           pos2 = 0;
1457           do {
1458             if (n4 && n4->car && nint(n4->car->car) == NODE_SPLAT) {
1459               codegen(s, n4->car, VAL);
1460               gen_move(s, cursp(), exc, 0);
1461               push_n(2); pop_n(2); /* space for one arg and a block */
1462               pop();
1463               genop_3(s, OP_SEND, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1);
1464             }
1465             else {
1466               if (n4) {
1467                 codegen(s, n4->car, VAL);
1468               }
1469               else {
1470                 genop_2(s, OP_GETCONST, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "StandardError")));
1471                 push();
1472               }
1473               pop();
1474               genop_2(s, OP_RESCUE, exc, cursp());
1475             }
1476             tmp = genjmp2(s, OP_JMPIF, cursp(), pos2, val);
1477             pos2 = tmp;
1478             if (n4) {
1479               n4 = n4->cdr;
1480             }
1481           } while (n4);
1482           pos1 = genjmp(s, OP_JMP, 0);
1483           dispatch_linked(s, pos2);
1484
1485           pop();
1486           if (n3->cdr->car) {
1487             gen_assignment(s, n3->cdr->car, exc, NOVAL);
1488           }
1489           if (n3->cdr->cdr->car) {
1490             codegen(s, n3->cdr->cdr->car, val);
1491             if (val) pop();
1492           }
1493           tmp = genjmp(s, OP_JMP, exend);
1494           exend = tmp;
1495           n2 = n2->cdr;
1496           push();
1497         }
1498         if (pos1) {
1499           dispatch(s, pos1);
1500           genop_1(s, OP_RAISE, exc);
1501         }
1502       }
1503       pop();
1504       tree = tree->cdr;
1505       dispatch(s, noexc);
1506       genop_1(s, OP_POPERR, 1);
1507       if (tree->car) {
1508         codegen(s, tree->car, val);
1509       }
1510       else if (val) {
1511         push();
1512       }
1513       dispatch_linked(s, exend);
1514       loop_pop(s, NOVAL);
1515     }
1516     break;
1517
1518   case NODE_ENSURE:
1519     if (!tree->cdr || !tree->cdr->cdr ||
1520         (nint(tree->cdr->cdr->car) == NODE_BEGIN &&
1521          tree->cdr->cdr->cdr)) {
1522       int idx;
1523
1524       s->ensure_level++;
1525       idx = scope_body(s, tree->cdr, NOVAL);
1526       genop_1(s, OP_EPUSH, idx);
1527       codegen(s, tree->car, val);
1528       s->ensure_level--;
1529       genop_1(s, OP_EPOP, 1);
1530     }
1531     else {                      /* empty ensure ignored */
1532       codegen(s, tree->car, val);
1533     }
1534     break;
1535
1536   case NODE_LAMBDA:
1537     if (val) {
1538       int idx = lambda_body(s, tree, 1);
1539
1540       genop_2(s, OP_LAMBDA, cursp(), idx);
1541       push();
1542     }
1543     break;
1544
1545   case NODE_BLOCK:
1546     if (val) {
1547       int idx = lambda_body(s, tree, 1);
1548
1549       genop_2(s, OP_BLOCK, cursp(), idx);
1550       push();
1551     }
1552     break;
1553
1554   case NODE_IF:
1555     {
1556       int pos1, pos2;
1557       node *elsepart = tree->cdr->cdr->car;
1558
1559       if (!tree->car) {
1560         codegen(s, elsepart, val);
1561         goto exit;
1562       }
1563       switch (nint(tree->car->car)) {
1564       case NODE_TRUE:
1565       case NODE_INT:
1566       case NODE_STR:
1567         codegen(s, tree->cdr->car, val);
1568         goto exit;
1569       case NODE_FALSE:
1570       case NODE_NIL:
1571         codegen(s, elsepart, val);
1572         goto exit;
1573       }
1574       codegen(s, tree->car, VAL);
1575       pop();
1576       pos1 = genjmp2(s, OP_JMPNOT, cursp(), 0, val);
1577
1578       codegen(s, tree->cdr->car, val);
1579       if (elsepart) {
1580         if (val) pop();
1581         pos2 = genjmp(s, OP_JMP, 0);
1582         dispatch(s, pos1);
1583         codegen(s, elsepart, val);
1584         dispatch(s, pos2);
1585       }
1586       else {
1587         if (val) {
1588           pop();
1589           pos2 = genjmp(s, OP_JMP, 0);
1590           dispatch(s, pos1);
1591           genop_1(s, OP_LOADNIL, cursp());
1592           dispatch(s, pos2);
1593           push();
1594         }
1595         else {
1596           dispatch(s, pos1);
1597         }
1598       }
1599     }
1600     break;
1601
1602   case NODE_AND:
1603     {
1604       int pos;
1605
1606       codegen(s, tree->car, VAL);
1607       pop();
1608       pos = genjmp2(s, OP_JMPNOT, cursp(), 0, val);
1609       codegen(s, tree->cdr, val);
1610       dispatch(s, pos);
1611     }
1612     break;
1613
1614   case NODE_OR:
1615     {
1616       int pos;
1617
1618       codegen(s, tree->car, VAL);
1619       pop();
1620       pos = genjmp2(s, OP_JMPIF, cursp(), 0, val);
1621       codegen(s, tree->cdr, val);
1622       dispatch(s, pos);
1623     }
1624     break;
1625
1626   case NODE_WHILE:
1627     {
1628       struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
1629
1630       lp->pc0 = new_label(s);
1631       lp->pc1 = genjmp(s, OP_JMP, 0);
1632       lp->pc2 = new_label(s);
1633       codegen(s, tree->cdr, NOVAL);
1634       dispatch(s, lp->pc1);
1635       codegen(s, tree->car, VAL);
1636       pop();
1637       genjmp2(s, OP_JMPIF, cursp(), lp->pc2, NOVAL);
1638
1639       loop_pop(s, val);
1640     }
1641     break;
1642
1643   case NODE_UNTIL:
1644     {
1645       struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
1646
1647       lp->pc0 = new_label(s);
1648       lp->pc1 = genjmp(s, OP_JMP, 0);
1649       lp->pc2 = new_label(s);
1650       codegen(s, tree->cdr, NOVAL);
1651       dispatch(s, lp->pc1);
1652       codegen(s, tree->car, VAL);
1653       pop();
1654       genjmp2(s, OP_JMPNOT, cursp(), lp->pc2, NOVAL);
1655
1656       loop_pop(s, val);
1657     }
1658     break;
1659
1660   case NODE_FOR:
1661     for_body(s, tree);
1662     if (val) push();
1663     break;
1664
1665   case NODE_CASE:
1666     {
1667       int head = 0;
1668       int pos1, pos2, pos3, tmp;
1669       node *n;
1670
1671       pos3 = 0;
1672       if (tree->car) {
1673         head = cursp();
1674         codegen(s, tree->car, VAL);
1675       }
1676       tree = tree->cdr;
1677       while (tree) {
1678         n = tree->car->car;
1679         pos1 = pos2 = 0;
1680         while (n) {
1681           codegen(s, n->car, VAL);
1682           if (head) {
1683             gen_move(s, cursp(), head, 0);
1684             push(); push(); pop(); pop(); pop();
1685             if (nint(n->car->car) == NODE_SPLAT) {
1686               genop_3(s, OP_SEND, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1);
1687             }
1688             else {
1689               genop_3(s, OP_SEND, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "===")), 1);
1690             }
1691           }
1692           else {
1693             pop();
1694           }
1695           tmp = genjmp2(s, OP_JMPIF, cursp(), pos2, NOVAL);
1696           pos2 = tmp;
1697           n = n->cdr;
1698         }
1699         if (tree->car->car) {
1700           pos1 = genjmp(s, OP_JMP, 0);
1701           dispatch_linked(s, pos2);
1702         }
1703         codegen(s, tree->car->cdr, val);
1704         if (val) pop();
1705         tmp = genjmp(s, OP_JMP, pos3);
1706         pos3 = tmp;
1707         if (pos1) dispatch(s, pos1);
1708         tree = tree->cdr;
1709       }
1710       if (val) {
1711         int pos = cursp();
1712         genop_1(s, OP_LOADNIL, cursp());
1713         if (pos3) dispatch_linked(s, pos3);
1714         if (head) pop();
1715         if (cursp() != pos) {
1716           gen_move(s, cursp(), pos, 0);
1717         }
1718         push();
1719       }
1720       else {
1721         if (pos3) {
1722           dispatch_linked(s, pos3);
1723         }
1724         if (head) {
1725           pop();
1726         }
1727       }
1728     }
1729     break;
1730
1731   case NODE_SCOPE:
1732     scope_body(s, tree, NOVAL);
1733     break;
1734
1735   case NODE_FCALL:
1736   case NODE_CALL:
1737     gen_call(s, tree, 0, 0, val, 0);
1738     break;
1739   case NODE_SCALL:
1740     gen_call(s, tree, 0, 0, val, 1);
1741     break;
1742
1743   case NODE_DOT2:
1744     codegen(s, tree->car, val);
1745     codegen(s, tree->cdr, val);
1746     if (val) {
1747       pop(); pop();
1748       genop_1(s, OP_RANGE_INC, cursp());
1749       push();
1750     }
1751     break;
1752
1753   case NODE_DOT3:
1754     codegen(s, tree->car, val);
1755     codegen(s, tree->cdr, val);
1756     if (val) {
1757       pop(); pop();
1758       genop_1(s, OP_RANGE_EXC, cursp());
1759       push();
1760     }
1761     break;
1762
1763   case NODE_COLON2:
1764     {
1765       int sym = new_sym(s, nsym(tree->cdr));
1766
1767       codegen(s, tree->car, VAL);
1768       pop();
1769       genop_2(s, OP_GETMCNST, cursp(), sym);
1770       if (val) push();
1771     }
1772     break;
1773
1774   case NODE_COLON3:
1775     {
1776       int sym = new_sym(s, nsym(tree));
1777
1778       genop_1(s, OP_OCLASS, cursp());
1779       genop_2(s, OP_GETMCNST, cursp(), sym);
1780       if (val) push();
1781     }
1782     break;
1783
1784   case NODE_ARRAY:
1785     {
1786       int n;
1787
1788       n = gen_values(s, tree, val, 0);
1789       if (n >= 0) {
1790         if (val) {
1791           pop_n(n);
1792           genop_2(s, OP_ARRAY, cursp(), n);
1793           push();
1794         }
1795       }
1796       else if (val) {
1797         push();
1798       }
1799     }
1800     break;
1801
1802   case NODE_HASH:
1803   case NODE_KW_HASH:
1804     {
1805       int len = 0;
1806       mrb_bool update = FALSE;
1807
1808       while (tree) {
1809         if (nint(tree->car->car->car) == NODE_KW_REST_ARGS) {
1810           if (len > 0) {
1811             pop_n(len*2);
1812             if (!update) {
1813               genop_2(s, OP_HASH, cursp(), len);
1814             }
1815             else {
1816               pop();
1817               genop_2(s, OP_HASHADD, cursp(), len);
1818             }
1819             push();
1820           }
1821           codegen(s, tree->car->cdr, VAL);
1822           if (len > 0 || update) {
1823             pop(); pop();
1824             genop_1(s, OP_HASHCAT, cursp());
1825             push();
1826           }
1827           update = TRUE;
1828           len = 0;
1829         }
1830         else {
1831           codegen(s, tree->car->car, val);
1832           codegen(s, tree->car->cdr, val);
1833           len++;
1834         }
1835         tree = tree->cdr;
1836         if (val && len == 255) {
1837           pop_n(len*2);
1838           if (!update) {
1839             genop_2(s, OP_HASH, cursp(), len);
1840           }
1841           else {
1842             pop();
1843             genop_2(s, OP_HASHADD, cursp(), len);
1844           }
1845           push();
1846           update = TRUE;
1847           len = 0;
1848         }
1849       }
1850       if (val) {
1851         pop_n(len*2);
1852         if (!update) {
1853           genop_2(s, OP_HASH, cursp(), len);
1854         }
1855         else {
1856           pop();
1857           if (len > 0) {
1858             genop_2(s, OP_HASHADD, cursp(), len);
1859           }
1860         }
1861         push();
1862       }
1863     }
1864     break;
1865
1866   case NODE_SPLAT:
1867     codegen(s, tree, val);
1868     break;
1869
1870   case NODE_ASGN:
1871     codegen(s, tree->cdr, VAL);
1872     pop();
1873     gen_assignment(s, tree->car, cursp(), val);
1874     break;
1875
1876   case NODE_MASGN:
1877     {
1878       int len = 0, n = 0, post = 0;
1879       node *t = tree->cdr, *p;
1880       int rhs = cursp();
1881
1882       if (nint(t->car) == NODE_ARRAY && t->cdr && nosplat(t->cdr)) {
1883         /* fixed rhs */
1884         t = t->cdr;
1885         while (t) {
1886           codegen(s, t->car, VAL);
1887           len++;
1888           t = t->cdr;
1889         }
1890         tree = tree->car;
1891         if (tree->car) {                /* pre */
1892           t = tree->car;
1893           n = 0;
1894           while (t) {
1895             if (n < len) {
1896               gen_assignment(s, t->car, rhs+n, NOVAL);
1897               n++;
1898             }
1899             else {
1900               genop_1(s, OP_LOADNIL, rhs+n);
1901               gen_assignment(s, t->car, rhs+n, NOVAL);
1902             }
1903             t = t->cdr;
1904           }
1905         }
1906         t = tree->cdr;
1907         if (t) {
1908           if (t->cdr) {         /* post count */
1909             p = t->cdr->car;
1910             while (p) {
1911               post++;
1912               p = p->cdr;
1913             }
1914           }
1915           if (t->car) {         /* rest (len - pre - post) */
1916             int rn;
1917
1918             if (len < post + n) {
1919               rn = 0;
1920             }
1921             else {
1922               rn = len - post - n;
1923             }
1924             genop_3(s, OP_ARRAY2, cursp(), rhs+n, rn);
1925             gen_assignment(s, t->car, cursp(), NOVAL);
1926             n += rn;
1927           }
1928           if (t->cdr && t->cdr->car) {
1929             t = t->cdr->car;
1930             while (n<len) {
1931               gen_assignment(s, t->car, rhs+n, NOVAL);
1932               t = t->cdr;
1933               n++;
1934             }
1935           }
1936         }
1937         pop_n(len);
1938         if (val) {
1939           genop_2(s, OP_ARRAY, rhs, len);
1940           push();
1941         }
1942       }
1943       else {
1944         /* variable rhs */
1945         codegen(s, t, VAL);
1946         gen_vmassignment(s, tree->car, rhs, val);
1947         if (!val) {
1948           pop();
1949         }
1950       }
1951     }
1952     break;
1953
1954   case NODE_OP_ASGN:
1955     {
1956       mrb_sym sym = nsym(tree->cdr->car);
1957       mrb_int len;
1958       const char *name = mrb_sym2name_len(s->mrb, sym, &len);
1959       int idx, callargs = -1, vsp = -1;
1960
1961       if ((len == 2 && name[0] == '|' && name[1] == '|') &&
1962           (nint(tree->car->car) == NODE_CONST ||
1963            nint(tree->car->car) == NODE_CVAR)) {
1964         int onerr, noexc, exc;
1965         struct loopinfo *lp;
1966
1967         onerr = genjmp(s, OP_ONERR, 0);
1968         lp = loop_push(s, LOOP_BEGIN);
1969         lp->pc1 = onerr;
1970         exc = cursp();
1971         codegen(s, tree->car, VAL);
1972         lp->type = LOOP_RESCUE;
1973         genop_1(s, OP_POPERR, 1);
1974         noexc = genjmp(s, OP_JMP, 0);
1975         dispatch(s, onerr);
1976         genop_1(s, OP_EXCEPT, exc);
1977         genop_1(s, OP_LOADF, exc);
1978         dispatch(s, noexc);
1979         loop_pop(s, NOVAL);
1980       }
1981       else if (nint(tree->car->car) == NODE_CALL) {
1982         node *n = tree->car->cdr;
1983         int base, i, nargs = 0;
1984         callargs = 0;
1985
1986         if (val) {
1987           vsp = cursp();
1988           push();
1989         }
1990         codegen(s, n->car, VAL);   /* receiver */
1991         idx = new_sym(s, nsym(n->cdr->car));
1992         base = cursp()-1;
1993         if (n->cdr->cdr->car) {
1994           nargs = gen_values(s, n->cdr->cdr->car->car, VAL, 1);
1995           if (nargs >= 0) {
1996             callargs = nargs;
1997           }
1998           else { /* varargs */
1999             push();
2000             nargs = 1;
2001             callargs = CALL_MAXARGS;
2002           }
2003         }
2004         /* copy receiver and arguments */
2005         gen_move(s, cursp(), base, 1);
2006         for (i=0; i<nargs; i++) {
2007           gen_move(s, cursp()+i+1, base+i+1, 1);
2008         }
2009         push_n(nargs+2);pop_n(nargs+2); /* space for receiver, arguments and a block */
2010         genop_3(s, OP_SEND, cursp(), idx, callargs);
2011         push();
2012       }
2013       else {
2014         codegen(s, tree->car, VAL);
2015       }
2016       if (len == 2 &&
2017           ((name[0] == '|' && name[1] == '|') ||
2018            (name[0] == '&' && name[1] == '&'))) {
2019         int pos;
2020
2021         pop();
2022         if (val) {
2023           if (vsp >= 0) {
2024             gen_move(s, vsp, cursp(), 1);
2025           }
2026           pos = genjmp2(s, name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0, val);
2027         }
2028         else {
2029           pos = genjmp2(s, name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0, val);
2030         }
2031         codegen(s, tree->cdr->cdr->car, VAL);
2032         pop();
2033         if (val && vsp >= 0) {
2034           gen_move(s, vsp, cursp(), 1);
2035         }
2036         if (nint(tree->car->car) == NODE_CALL) {
2037           if (callargs == CALL_MAXARGS) {
2038             pop();
2039             genop_1(s, OP_ARYPUSH, cursp());
2040           }
2041           else {
2042             pop_n(callargs);
2043             callargs++;
2044           }
2045           pop();
2046           idx = new_sym(s, attrsym(s, nsym(tree->car->cdr->cdr->car)));
2047           genop_3(s, OP_SEND, cursp(), idx, callargs);
2048         }
2049         else {
2050           gen_assignment(s, tree->car, cursp(), val);
2051         }
2052         dispatch(s, pos);
2053         goto exit;
2054       }
2055       codegen(s, tree->cdr->cdr->car, VAL);
2056       push(); pop();
2057       pop(); pop();
2058
2059       if (len == 1 && name[0] == '+')  {
2060         gen_addsub(s, OP_ADD, cursp());
2061       }
2062       else if (len == 1 && name[0] == '-')  {
2063         gen_addsub(s, OP_SUB, cursp());
2064       }
2065       else if (len == 1 && name[0] == '*')  {
2066         genop_1(s, OP_MUL, cursp());
2067       }
2068       else if (len == 1 && name[0] == '/')  {
2069         genop_1(s, OP_DIV, cursp());
2070       }
2071       else if (len == 1 && name[0] == '<')  {
2072         genop_1(s, OP_LT, cursp());
2073       }
2074       else if (len == 2 && name[0] == '<' && name[1] == '=')  {
2075         genop_1(s, OP_LE, cursp());
2076       }
2077       else if (len == 1 && name[0] == '>')  {
2078         genop_1(s, OP_GT, cursp());
2079       }
2080       else if (len == 2 && name[0] == '>' && name[1] == '=')  {
2081         genop_1(s, OP_GE, cursp());
2082       }
2083       else {
2084         idx = new_sym(s, sym);
2085         genop_3(s, OP_SEND, cursp(), idx, 1);
2086       }
2087       if (callargs < 0) {
2088         gen_assignment(s, tree->car, cursp(), val);
2089       }
2090       else {
2091         if (val && vsp >= 0) {
2092           gen_move(s, vsp, cursp(), 0);
2093         }
2094         if (callargs == CALL_MAXARGS) {
2095           pop();
2096           genop_1(s, OP_ARYPUSH, cursp());
2097         }
2098         else {
2099           pop_n(callargs);
2100           callargs++;
2101         }
2102         pop();
2103         idx = new_sym(s, attrsym(s,nsym(tree->car->cdr->cdr->car)));
2104         genop_3(s, OP_SEND, cursp(), idx, callargs);
2105       }
2106     }
2107     break;
2108
2109   case NODE_SUPER:
2110     {
2111       codegen_scope *s2 = s;
2112       int lv = 0;
2113       int n = 0, noop = 0, sendv = 0;
2114
2115       push();        /* room for receiver */
2116       while (!s2->mscope) {
2117         lv++;
2118         s2 = s2->prev;
2119         if (!s2) break;
2120       }
2121       genop_2S(s, OP_ARGARY, cursp(), (lv & 0xf));
2122       push(); push();         /* ARGARY pushes two values */
2123       pop(); pop();
2124       if (tree) {
2125         node *args = tree->car;
2126         if (args) {
2127           n = gen_values(s, args, VAL, 0);
2128           if (n < 0) {
2129             n = noop = sendv = 1;
2130             push();
2131           }
2132         }
2133       }
2134       if (tree && tree->cdr) {
2135         codegen(s, tree->cdr, VAL);
2136         pop();
2137       }
2138       else {
2139         genop_1(s, OP_LOADNIL, cursp());
2140         push(); pop();
2141       }
2142       pop_n(n+1);
2143       if (sendv) n = CALL_MAXARGS;
2144       genop_2(s, OP_SUPER, cursp(), n);
2145       if (val) push();
2146     }
2147     break;
2148
2149   case NODE_ZSUPER:
2150     {
2151       codegen_scope *s2 = s;
2152       int lv = 0, ainfo = 0;
2153
2154       push();        /* room for receiver */
2155       while (!s2->mscope) {
2156         lv++;
2157         s2 = s2->prev;
2158         if (!s2) break;
2159       }
2160       if (s2) ainfo = s2->ainfo;
2161       genop_2S(s, OP_ARGARY, cursp(), (ainfo<<4)|(lv & 0xf));
2162       push(); push(); pop();    /* ARGARY pushes two values */
2163       if (tree && tree->cdr) {
2164         codegen(s, tree->cdr, VAL);
2165         pop();
2166       }
2167       pop(); pop();
2168       genop_2(s, OP_SUPER, cursp(), CALL_MAXARGS);
2169       if (val) push();
2170     }
2171     break;
2172
2173   case NODE_RETURN:
2174     if (tree) {
2175       gen_retval(s, tree);
2176     }
2177     else {
2178       genop_1(s, OP_LOADNIL, cursp());
2179     }
2180     if (s->loop) {
2181       gen_return(s, OP_RETURN_BLK, cursp());
2182     }
2183     else {
2184       gen_return(s, OP_RETURN, cursp());
2185     }
2186     if (val) push();
2187     break;
2188
2189   case NODE_YIELD:
2190     {
2191       codegen_scope *s2 = s;
2192       int lv = 0, ainfo = 0;
2193       int n = 0, sendv = 0;
2194
2195       while (!s2->mscope) {
2196         lv++;
2197         s2 = s2->prev;
2198         if (!s2) break;
2199       }
2200       if (s2) ainfo = s2->ainfo;
2201       push();
2202       if (tree) {
2203         n = gen_values(s, tree, VAL, 0);
2204         if (n < 0) {
2205           n = sendv = 1;
2206           push();
2207         }
2208       }
2209       push();pop(); /* space for a block */
2210       pop_n(n+1);
2211       genop_2S(s, OP_BLKPUSH, cursp(), (ainfo<<4)|(lv & 0xf));
2212       if (sendv) n = CALL_MAXARGS;
2213       genop_3(s, OP_SEND, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "call")), n);
2214       if (val) push();
2215     }
2216     break;
2217
2218   case NODE_BREAK:
2219     loop_break(s, tree);
2220     if (val) push();
2221     break;
2222
2223   case NODE_NEXT:
2224     if (!s->loop) {
2225       raise_error(s, "unexpected next");
2226     }
2227     else if (s->loop->type == LOOP_NORMAL) {
2228       if (s->ensure_level > s->loop->ensure_level) {
2229         genop_1(s, OP_EPOP, s->ensure_level - s->loop->ensure_level);
2230       }
2231       codegen(s, tree, NOVAL);
2232       genjmp(s, OP_JMP, s->loop->pc0);
2233     }
2234     else {
2235       if (tree) {
2236         codegen(s, tree, VAL);
2237         pop();
2238       }
2239       else {
2240         genop_1(s, OP_LOADNIL, cursp());
2241       }
2242       gen_return(s, OP_RETURN, cursp());
2243     }
2244     if (val) push();
2245     break;
2246
2247   case NODE_REDO:
2248     if (!s->loop || s->loop->type == LOOP_BEGIN || s->loop->type == LOOP_RESCUE) {
2249       raise_error(s, "unexpected redo");
2250     }
2251     else {
2252       if (s->ensure_level > s->loop->ensure_level) {
2253         genop_1(s, OP_EPOP, s->ensure_level - s->loop->ensure_level);
2254       }
2255       genjmp(s, OP_JMP, s->loop->pc2);
2256     }
2257     if (val) push();
2258     break;
2259
2260   case NODE_RETRY:
2261     {
2262       const char *msg = "unexpected retry";
2263
2264       if (!s->loop) {
2265         raise_error(s, msg);
2266       }
2267       else {
2268         struct loopinfo *lp = s->loop;
2269         int n = 0;
2270
2271         while (lp && lp->type != LOOP_RESCUE) {
2272           if (lp->type == LOOP_BEGIN) {
2273             n++;
2274           }
2275           lp = lp->prev;
2276         }
2277         if (!lp) {
2278           raise_error(s, msg);
2279         }
2280         else {
2281           if (n > 0) {
2282             genop_1(s, OP_POPERR, n);
2283           }
2284           if (s->ensure_level > lp->ensure_level) {
2285             genop_1(s, OP_EPOP, s->ensure_level - lp->ensure_level);
2286           }
2287           genjmp(s, OP_JMP, lp->pc0);
2288         }
2289       }
2290       if (val) push();
2291     }
2292     break;
2293
2294   case NODE_LVAR:
2295     if (val) {
2296       int idx = lv_idx(s, nsym(tree));
2297
2298       if (idx > 0) {
2299         gen_move(s, cursp(), idx, val);
2300         if (val && on_eval(s)) genop_0(s, OP_NOP);
2301       }
2302       else {
2303         int lv = 0;
2304         codegen_scope *up = s->prev;
2305
2306         while (up) {
2307           idx = lv_idx(up, nsym(tree));
2308           if (idx > 0) {
2309             genop_3(s, OP_GETUPVAR, cursp(), idx, lv);
2310             break;
2311           }
2312           lv++;
2313           up = up->prev;
2314         }
2315       }
2316       push();
2317     }
2318     break;
2319
2320   case NODE_GVAR:
2321     {
2322       int sym = new_sym(s, nsym(tree));
2323
2324       genop_2(s, OP_GETGV, cursp(), sym);
2325       if (val) push();
2326     }
2327     break;
2328
2329   case NODE_IVAR:
2330     {
2331       int sym = new_sym(s, nsym(tree));
2332
2333       genop_2(s, OP_GETIV, cursp(), sym);
2334       if (val) push();
2335     }
2336     break;
2337
2338   case NODE_CVAR:
2339     {
2340       int sym = new_sym(s, nsym(tree));
2341
2342       genop_2(s, OP_GETCV, cursp(), sym);
2343       if (val) push();
2344     }
2345     break;
2346
2347   case NODE_CONST:
2348     {
2349       int sym = new_sym(s, nsym(tree));
2350
2351       genop_2(s, OP_GETCONST, cursp(), sym);
2352       if (val) push();
2353     }
2354     break;
2355
2356   case NODE_DEFINED:
2357     codegen(s, tree, val);
2358     break;
2359
2360   case NODE_BACK_REF:
2361     if (val) {
2362       char buf[] = {'$', nchar(tree)};
2363       int sym = new_sym(s, mrb_intern(s->mrb, buf, sizeof(buf)));
2364
2365       genop_2(s, OP_GETGV, cursp(), sym);
2366       push();
2367     }
2368     break;
2369
2370   case NODE_NTH_REF:
2371     if (val) {
2372       mrb_state *mrb = s->mrb;
2373       mrb_value str;
2374       int sym;
2375
2376       str = mrb_format(mrb, "$%S", mrb_fixnum_value(nint(tree)));
2377       sym = new_sym(s, mrb_intern_str(mrb, str));
2378       genop_2(s, OP_GETGV, cursp(), sym);
2379       push();
2380     }
2381     break;
2382
2383   case NODE_ARG:
2384     /* should not happen */
2385     break;
2386
2387   case NODE_BLOCK_ARG:
2388     codegen(s, tree, val);
2389     break;
2390
2391   case NODE_INT:
2392     if (val) {
2393       char *p = (char*)tree->car;
2394       int base = nint(tree->cdr->car);
2395       mrb_int i;
2396       mrb_bool overflow;
2397
2398       i = readint_mrb_int(s, p, base, FALSE, &overflow);
2399 #ifndef MRB_WITHOUT_FLOAT
2400       if (overflow) {
2401         double f = readint_float(s, p, base);
2402         int off = new_lit(s, mrb_float_value(s->mrb, f));
2403
2404         genop_2(s, OP_LOADL, cursp(), off);
2405       }
2406       else
2407 #endif
2408       {
2409         if (i == -1) genop_1(s, OP_LOADI__1, cursp());
2410         else if (i < 0) genop_2(s, OP_LOADINEG, cursp(), (uint16_t)-i);
2411         else if (i < 8) genop_1(s, OP_LOADI_0 + (uint8_t)i, cursp());
2412         else if (i <= 0xffff) genop_2(s, OP_LOADI, cursp(), (uint16_t)i);
2413         else {
2414           int off = new_lit(s, mrb_fixnum_value(i));
2415           genop_2(s, OP_LOADL, cursp(), off);
2416         }
2417       }
2418       push();
2419     }
2420     break;
2421
2422 #ifndef MRB_WITHOUT_FLOAT
2423   case NODE_FLOAT:
2424     if (val) {
2425       char *p = (char*)tree;
2426       mrb_float f = mrb_float_read(p, NULL);
2427       int off = new_lit(s, mrb_float_value(s->mrb, f));
2428
2429       genop_2(s, OP_LOADL, cursp(), off);
2430       push();
2431     }
2432     break;
2433 #endif
2434
2435   case NODE_NEGATE:
2436     {
2437       nt = nint(tree->car);
2438       switch (nt) {
2439 #ifndef MRB_WITHOUT_FLOAT
2440       case NODE_FLOAT:
2441         if (val) {
2442           char *p = (char*)tree->cdr;
2443           mrb_float f = mrb_float_read(p, NULL);
2444           int off = new_lit(s, mrb_float_value(s->mrb, -f));
2445
2446           genop_2(s, OP_LOADL, cursp(), off);
2447           push();
2448         }
2449         break;
2450 #endif
2451
2452       case NODE_INT:
2453         if (val) {
2454           char *p = (char*)tree->cdr->car;
2455           int base = nint(tree->cdr->cdr->car);
2456           mrb_int i;
2457           mrb_bool overflow;
2458
2459           i = readint_mrb_int(s, p, base, TRUE, &overflow);
2460 #ifndef MRB_WITHOUT_FLOAT
2461           if (overflow) {
2462             double f = readint_float(s, p, base);
2463             int off = new_lit(s, mrb_float_value(s->mrb, -f));
2464
2465             genop_2(s, OP_LOADL, cursp(), off);
2466           }
2467           else {
2468 #endif
2469             if (i == -1) genop_1(s, OP_LOADI__1, cursp());
2470             else if (i >= -0xffff) {
2471               genop_2(s, OP_LOADINEG, cursp(), (uint16_t)-i);
2472             }
2473             else {
2474               int off = new_lit(s, mrb_fixnum_value(i));
2475               genop_2(s, OP_LOADL, cursp(), off);
2476             }
2477 #ifndef MRB_WITHOUT_FLOAT
2478           }
2479 #endif
2480           push();
2481         }
2482         break;
2483
2484       default:
2485         if (val) {
2486           int sym = new_sym(s, mrb_intern_lit(s->mrb, "-@"));
2487           codegen(s, tree, VAL);
2488           pop();
2489           genop_3(s, OP_SEND, cursp(), sym, 0);
2490           push();
2491         }
2492         else {
2493           codegen(s, tree, NOVAL);
2494         }
2495         break;
2496       }
2497     }
2498     break;
2499
2500   case NODE_STR:
2501     if (val) {
2502       char *p = (char*)tree->car;
2503       size_t len = (intptr_t)tree->cdr;
2504       int ai = mrb_gc_arena_save(s->mrb);
2505       int off = new_lit(s, mrb_str_new(s->mrb, p, len));
2506
2507       mrb_gc_arena_restore(s->mrb, ai);
2508       genop_2(s, OP_STRING, cursp(), off);
2509       push();
2510     }
2511     break;
2512
2513   case NODE_HEREDOC:
2514     tree = ((struct mrb_parser_heredoc_info *)tree)->doc;
2515     /* fall through */
2516   case NODE_DSTR:
2517     if (val) {
2518       node *n = tree;
2519
2520       if (!n) {
2521         genop_1(s, OP_LOADNIL, cursp());
2522         push();
2523         break;
2524       }
2525       codegen(s, n->car, VAL);
2526       n = n->cdr;
2527       while (n) {
2528         codegen(s, n->car, VAL);
2529         pop(); pop();
2530         genop_1(s, OP_STRCAT, cursp());
2531         push();
2532         n = n->cdr;
2533       }
2534     }
2535     else {
2536       node *n = tree;
2537
2538       while (n) {
2539         if (nint(n->car->car) != NODE_STR) {
2540           codegen(s, n->car, NOVAL);
2541         }
2542         n = n->cdr;
2543       }
2544     }
2545     break;
2546
2547   case NODE_WORDS:
2548     gen_literal_array(s, tree, FALSE, val);
2549     break;
2550
2551   case NODE_SYMBOLS:
2552     gen_literal_array(s, tree, TRUE, val);
2553     break;
2554
2555   case NODE_DXSTR:
2556     {
2557       node *n;
2558       int ai = mrb_gc_arena_save(s->mrb);
2559       int sym = new_sym(s, mrb_intern_lit(s->mrb, "Kernel"));
2560
2561       genop_1(s, OP_LOADSELF, cursp());
2562       push();
2563       codegen(s, tree->car, VAL);
2564       n = tree->cdr;
2565       while (n) {
2566         if (nint(n->car->car) == NODE_XSTR) {
2567           n->car->car = (struct mrb_ast_node*)(intptr_t)NODE_STR;
2568           mrb_assert(!n->cdr); /* must be the end */
2569         }
2570         codegen(s, n->car, VAL);
2571         pop(); pop();
2572         genop_1(s, OP_STRCAT, cursp());
2573         push();
2574         n = n->cdr;
2575       }
2576       push();                   /* for block */
2577       pop_n(3);
2578       sym = new_sym(s, mrb_intern_lit(s->mrb, "`"));
2579       genop_3(s, OP_SEND, cursp(), sym, 1);
2580       if (val) push();
2581       mrb_gc_arena_restore(s->mrb, ai);
2582     }
2583     break;
2584
2585   case NODE_XSTR:
2586     {
2587       char *p = (char*)tree->car;
2588       size_t len = (intptr_t)tree->cdr;
2589       int ai = mrb_gc_arena_save(s->mrb);
2590       int off = new_lit(s, mrb_str_new(s->mrb, p, len));
2591       int sym;
2592
2593       genop_1(s, OP_LOADSELF, cursp());
2594       push();
2595       genop_2(s, OP_STRING, cursp(), off);
2596       push(); push();
2597       pop_n(3);
2598       sym = new_sym(s, mrb_intern_lit(s->mrb, "`"));
2599       genop_3(s, OP_SEND, cursp(), sym, 1);
2600       if (val) push();
2601       mrb_gc_arena_restore(s->mrb, ai);
2602     }
2603     break;
2604
2605   case NODE_REGX:
2606     if (val) {
2607       char *p1 = (char*)tree->car;
2608       char *p2 = (char*)tree->cdr->car;
2609       char *p3 = (char*)tree->cdr->cdr;
2610       int ai = mrb_gc_arena_save(s->mrb);
2611       int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS));
2612       int off = new_lit(s, mrb_str_new_cstr(s->mrb, p1));
2613       int argc = 1;
2614
2615       genop_1(s, OP_OCLASS, cursp());
2616       genop_2(s, OP_GETMCNST, cursp(), sym);
2617       push();
2618       genop_2(s, OP_STRING, cursp(), off);
2619       push();
2620       if (p2 || p3) {
2621         if (p2) { /* opt */
2622           off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
2623           genop_2(s, OP_STRING, cursp(), off);
2624         }
2625         else {
2626           genop_1(s, OP_LOADNIL, cursp());
2627         }
2628         push();
2629         argc++;
2630         if (p3) { /* enc */
2631           off = new_lit(s, mrb_str_new(s->mrb, p3, 1));
2632           genop_2(s, OP_STRING, cursp(), off);
2633           push();
2634           argc++;
2635         }
2636       }
2637       push(); /* space for a block */
2638       pop_n(argc+2);
2639       sym = new_sym(s, mrb_intern_lit(s->mrb, "compile"));
2640       genop_3(s, OP_SEND, cursp(), sym, argc);
2641       mrb_gc_arena_restore(s->mrb, ai);
2642       push();
2643     }
2644     break;
2645
2646   case NODE_DREGX:
2647     if (val) {
2648       node *n = tree->car;
2649       int ai = mrb_gc_arena_save(s->mrb);
2650       int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS));
2651       int argc = 1;
2652       int off;
2653       char *p;
2654
2655       genop_1(s, OP_OCLASS, cursp());
2656       genop_2(s, OP_GETMCNST, cursp(), sym);
2657       push();
2658       codegen(s, n->car, VAL);
2659       n = n->cdr;
2660       while (n) {
2661         codegen(s, n->car, VAL);
2662         pop(); pop();
2663         genop_1(s, OP_STRCAT, cursp());
2664         push();
2665         n = n->cdr;
2666       }
2667       n = tree->cdr->cdr;
2668       if (n->car) { /* tail */
2669         p = (char*)n->car;
2670         off = new_lit(s, mrb_str_new_cstr(s->mrb, p));
2671         codegen(s, tree->car, VAL);
2672         genop_2(s, OP_STRING, cursp(), off);
2673         pop();
2674         genop_1(s, OP_STRCAT, cursp());
2675         push();
2676       }
2677       if (n->cdr->car) { /* opt */
2678         char *p2 = (char*)n->cdr->car;
2679         off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
2680         genop_2(s, OP_STRING, cursp(), off);
2681         push();
2682         argc++;
2683       }
2684       if (n->cdr->cdr) { /* enc */
2685         char *p2 = (char*)n->cdr->cdr;
2686         off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
2687         genop_2(s, OP_STRING, cursp(), off);
2688         push();
2689         argc++;
2690       }
2691       push(); /* space for a block */
2692       pop_n(argc+2);
2693       sym = new_sym(s, mrb_intern_lit(s->mrb, "compile"));
2694       genop_3(s, OP_SEND, cursp(), sym, argc);
2695       mrb_gc_arena_restore(s->mrb, ai);
2696       push();
2697     }
2698     else {
2699       node *n = tree->car;
2700
2701       while (n) {
2702         if (nint(n->car->car) != NODE_STR) {
2703           codegen(s, n->car, NOVAL);
2704         }
2705         n = n->cdr;
2706       }
2707     }
2708     break;
2709
2710   case NODE_SYM:
2711     if (val) {
2712       int sym = new_sym(s, nsym(tree));
2713
2714       genop_2(s, OP_LOADSYM, cursp(), sym);
2715       push();
2716     }
2717     break;
2718
2719   case NODE_DSYM:
2720     codegen(s, tree, val);
2721     if (val) {
2722       gen_intern(s);
2723     }
2724     break;
2725
2726   case NODE_SELF:
2727     if (val) {
2728       genop_1(s, OP_LOADSELF, cursp());
2729       push();
2730     }
2731     break;
2732
2733   case NODE_NIL:
2734     if (val) {
2735       genop_1(s, OP_LOADNIL, cursp());
2736       push();
2737     }
2738     break;
2739
2740   case NODE_TRUE:
2741     if (val) {
2742       genop_1(s, OP_LOADT, cursp());
2743       push();
2744     }
2745     break;
2746
2747   case NODE_FALSE:
2748     if (val) {
2749       genop_1(s, OP_LOADF, cursp());
2750       push();
2751     }
2752     break;
2753
2754   case NODE_ALIAS:
2755     {
2756       int a = new_sym(s, nsym(tree->car));
2757       int b = new_sym(s, nsym(tree->cdr));
2758
2759       genop_2(s, OP_ALIAS, a, b);
2760       if (val) {
2761         genop_1(s, OP_LOADNIL, cursp());
2762         push();
2763       }
2764     }
2765    break;
2766
2767   case NODE_UNDEF:
2768     {
2769       node *t = tree;
2770
2771       while (t) {
2772         int symbol = new_sym(s, nsym(t->car));
2773         genop_1(s, OP_UNDEF, symbol);
2774         t = t->cdr;
2775       }
2776       if (val) {
2777         genop_1(s, OP_LOADNIL, cursp());
2778         push();
2779       }
2780     }
2781     break;
2782
2783   case NODE_CLASS:
2784     {
2785       int idx;
2786       node *body;
2787
2788       if (tree->car->car == (node*)0) {
2789         genop_1(s, OP_LOADNIL, cursp());
2790         push();
2791       }
2792       else if (tree->car->car == (node*)1) {
2793         genop_1(s, OP_OCLASS, cursp());
2794         push();
2795       }
2796       else {
2797         codegen(s, tree->car->car, VAL);
2798       }
2799       if (tree->cdr->car) {
2800         codegen(s, tree->cdr->car, VAL);
2801       }
2802       else {
2803         genop_1(s, OP_LOADNIL, cursp());
2804         push();
2805       }
2806       pop(); pop();
2807       idx = new_sym(s, nsym(tree->car->cdr));
2808       genop_2(s, OP_CLASS, cursp(), idx);
2809       body = tree->cdr->cdr->car;
2810       if (nint(body->cdr->car) == NODE_BEGIN && body->cdr->cdr == NULL) {
2811         genop_1(s, OP_LOADNIL, cursp());
2812       }
2813       else {
2814         idx = scope_body(s, body, val);
2815         genop_2(s, OP_EXEC, cursp(), idx);
2816       }
2817       if (val) {
2818         push();
2819       }
2820     }
2821     break;
2822
2823   case NODE_MODULE:
2824     {
2825       int idx;
2826
2827       if (tree->car->car == (node*)0) {
2828         genop_1(s, OP_LOADNIL, cursp());
2829         push();
2830       }
2831       else if (tree->car->car == (node*)1) {
2832         genop_1(s, OP_OCLASS, cursp());
2833         push();
2834       }
2835       else {
2836         codegen(s, tree->car->car, VAL);
2837       }
2838       pop();
2839       idx = new_sym(s, nsym(tree->car->cdr));
2840       genop_2(s, OP_MODULE, cursp(), idx);
2841       if (nint(tree->cdr->car->cdr->car) == NODE_BEGIN &&
2842           tree->cdr->car->cdr->cdr == NULL) {
2843         genop_1(s, OP_LOADNIL, cursp());
2844       }
2845       else {
2846         idx = scope_body(s, tree->cdr->car, val);
2847         genop_2(s, OP_EXEC, cursp(), idx);
2848       }
2849       if (val) {
2850         push();
2851       }
2852     }
2853     break;
2854
2855   case NODE_SCLASS:
2856     {
2857       int idx;
2858
2859       codegen(s, tree->car, VAL);
2860       pop();
2861       genop_1(s, OP_SCLASS, cursp());
2862       if (nint(tree->cdr->car->cdr->car) == NODE_BEGIN &&
2863           tree->cdr->car->cdr->cdr == NULL) {
2864         genop_1(s, OP_LOADNIL, cursp());
2865       }
2866       else {
2867         idx = scope_body(s, tree->cdr->car, val);
2868         genop_2(s, OP_EXEC, cursp(), idx);
2869       }
2870       if (val) {
2871         push();
2872       }
2873     }
2874     break;
2875
2876   case NODE_DEF:
2877     {
2878       int sym = new_sym(s, nsym(tree->car));
2879       int idx = lambda_body(s, tree->cdr, 0);
2880
2881       genop_1(s, OP_TCLASS, cursp());
2882       push();
2883       genop_2(s, OP_METHOD, cursp(), idx);
2884       push(); pop();
2885       pop();
2886       genop_2(s, OP_DEF, cursp(), sym);
2887       if (val) {
2888         genop_2(s, OP_LOADSYM, cursp(), sym);
2889         push();
2890       }
2891     }
2892     break;
2893
2894   case NODE_SDEF:
2895     {
2896       node *recv = tree->car;
2897       int sym = new_sym(s, nsym(tree->cdr->car));
2898       int idx = lambda_body(s, tree->cdr->cdr, 0);
2899
2900       codegen(s, recv, VAL);
2901       pop();
2902       genop_1(s, OP_SCLASS, cursp());
2903       push();
2904       genop_2(s, OP_METHOD, cursp(), idx);
2905       pop();
2906       genop_2(s, OP_DEF, cursp(), sym);
2907       if (val) {
2908         genop_2(s, OP_LOADSYM, cursp(), sym);
2909         push();
2910       }
2911     }
2912     break;
2913
2914   case NODE_POSTEXE:
2915     codegen(s, tree, NOVAL);
2916     break;
2917
2918   default:
2919     break;
2920   }
2921  exit:
2922   s->rlev = rlev;
2923 }
2924
2925 static void
2926 scope_add_irep(codegen_scope *s, mrb_irep *irep)
2927 {
2928   if (s->irep == NULL) {
2929     s->irep = irep;
2930     return;
2931   }
2932   if (s->irep->rlen == s->rcapa) {
2933     s->rcapa *= 2;
2934     s->irep->reps = (mrb_irep**)codegen_realloc(s, s->irep->reps, sizeof(mrb_irep*)*s->rcapa);
2935   }
2936   s->irep->reps[s->irep->rlen] = irep;
2937   s->irep->rlen++;
2938 }
2939
2940 static codegen_scope*
2941 scope_new(mrb_state *mrb, codegen_scope *prev, node *lv)
2942 {
2943   static const codegen_scope codegen_scope_zero = { 0 };
2944   mrb_pool *pool = mrb_pool_open(mrb);
2945   codegen_scope *p = (codegen_scope *)mrb_pool_alloc(pool, sizeof(codegen_scope));
2946
2947   if (!p) return NULL;
2948   *p = codegen_scope_zero;
2949   p->mrb = mrb;
2950   p->mpool = pool;
2951   if (!prev) return p;
2952   p->prev = prev;
2953   p->ainfo = -1;
2954   p->mscope = 0;
2955
2956   p->irep = mrb_add_irep(mrb);
2957   scope_add_irep(prev, p->irep);
2958
2959   p->rcapa = 8;
2960   p->irep->reps = (mrb_irep**)mrb_malloc(mrb, sizeof(mrb_irep*)*p->rcapa);
2961
2962   p->icapa = 1024;
2963   p->iseq = (mrb_code*)mrb_malloc(mrb, sizeof(mrb_code)*p->icapa);
2964   p->irep->iseq = NULL;
2965
2966   p->pcapa = 32;
2967   p->irep->pool = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value)*p->pcapa);
2968   p->irep->plen = 0;
2969
2970   p->scapa = 256;
2971   p->irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*p->scapa);
2972   p->irep->slen = 0;
2973
2974   p->lv = lv;
2975   p->sp += node_len(lv)+1;        /* add self */
2976   p->nlocals = p->sp;
2977   if (lv) {
2978     node *n = lv;
2979     size_t i = 0;
2980
2981     p->irep->lv = (struct mrb_locals*)mrb_malloc(mrb, sizeof(struct mrb_locals) * (p->nlocals - 1));
2982     for (i=0, n=lv; n; i++,n=n->cdr) {
2983       p->irep->lv[i].name = lv_name(n);
2984       if (lv_name(n)) {
2985         p->irep->lv[i].r = lv_idx(p, lv_name(n));
2986       }
2987       else {
2988         p->irep->lv[i].r = 0;
2989       }
2990     }
2991     mrb_assert(i + 1 == p->nlocals);
2992   }
2993   p->ai = mrb_gc_arena_save(mrb);
2994
2995   p->filename_sym = prev->filename_sym;
2996   if (p->filename_sym) {
2997     p->lines = (uint16_t*)mrb_malloc(mrb, sizeof(short)*p->icapa);
2998   }
2999   p->lineno = prev->lineno;
3000
3001   /* debug setting */
3002   p->debug_start_pos = 0;
3003   if (p->filename_sym) {
3004     mrb_debug_info_alloc(mrb, p->irep);
3005   }
3006   else {
3007     p->irep->debug_info = NULL;
3008   }
3009   p->parser = prev->parser;
3010   p->filename_index = prev->filename_index;
3011
3012   p->rlev = prev->rlev+1;
3013
3014   return p;
3015 }
3016
3017 static void
3018 scope_finish(codegen_scope *s)
3019 {
3020   mrb_state *mrb = s->mrb;
3021   mrb_irep *irep = s->irep;
3022
3023   irep->flags = 0;
3024   if (s->iseq) {
3025     irep->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc);
3026     irep->ilen = s->pc;
3027   }
3028   irep->pool = (mrb_value*)codegen_realloc(s, irep->pool, sizeof(mrb_value)*irep->plen);
3029   irep->syms = (mrb_sym*)codegen_realloc(s, irep->syms, sizeof(mrb_sym)*irep->slen);
3030   irep->reps = (mrb_irep**)codegen_realloc(s, irep->reps, sizeof(mrb_irep*)*irep->rlen);
3031   if (s->filename_sym) {
3032     mrb_sym fname = mrb_parser_get_filename(s->parser, s->filename_index);
3033     const char *filename = mrb_sym2name_len(s->mrb, fname, NULL);
3034
3035     mrb_debug_info_append_file(s->mrb, s->irep->debug_info,
3036                                filename, s->lines, s->debug_start_pos, s->pc);
3037   }
3038   mrb_free(s->mrb, s->lines);
3039
3040   irep->nlocals = s->nlocals;
3041   irep->nregs = s->nregs;
3042
3043   mrb_gc_arena_restore(mrb, s->ai);
3044   mrb_pool_close(s->mpool);
3045 }
3046
3047 static struct loopinfo*
3048 loop_push(codegen_scope *s, enum looptype t)
3049 {
3050   struct loopinfo *p = (struct loopinfo *)codegen_palloc(s, sizeof(struct loopinfo));
3051
3052   p->type = t;
3053   p->pc0 = p->pc1 = p->pc2 = p->pc3 = 0;
3054   p->prev = s->loop;
3055   p->ensure_level = s->ensure_level;
3056   p->acc = cursp();
3057   s->loop = p;
3058
3059   return p;
3060 }
3061
3062 static void
3063 loop_break(codegen_scope *s, node *tree)
3064 {
3065   if (!s->loop) {
3066     codegen(s, tree, NOVAL);
3067     raise_error(s, "unexpected break");
3068   }
3069   else {
3070     struct loopinfo *loop;
3071     int n = 0;
3072
3073     if (tree) {
3074       gen_retval(s, tree);
3075     }
3076
3077     loop = s->loop;
3078     while (loop) {
3079       if (loop->type == LOOP_BEGIN) {
3080         n++;
3081         loop = loop->prev;
3082       }
3083       else if (loop->type == LOOP_RESCUE) {
3084         loop = loop->prev;
3085       }
3086       else{
3087         break;
3088       }
3089     }
3090     if (!loop) {
3091       raise_error(s, "unexpected break");
3092       return;
3093     }
3094     if (n > 0) {
3095       genop_1(s, OP_POPERR, n);
3096     }
3097
3098     if (loop->type == LOOP_NORMAL) {
3099       int tmp;
3100
3101       if (s->ensure_level > s->loop->ensure_level) {
3102         genop_1(s, OP_EPOP, s->ensure_level - s->loop->ensure_level);
3103       }
3104       if (tree) {
3105         gen_move(s, loop->acc, cursp(), 0);
3106       }
3107       tmp = genjmp(s, OP_JMP, loop->pc3);
3108       loop->pc3 = tmp;
3109     }
3110     else {
3111       if (!tree) {
3112         genop_1(s, OP_LOADNIL, cursp());
3113       }
3114       gen_return(s, OP_BREAK, cursp());
3115     }
3116   }
3117 }
3118
3119 static void
3120 loop_pop(codegen_scope *s, int val)
3121 {
3122   if (val) {
3123     genop_1(s, OP_LOADNIL, cursp());
3124   }
3125   dispatch_linked(s, s->loop->pc3);
3126   s->loop = s->loop->prev;
3127   if (val) push();
3128 }
3129
3130 static struct RProc*
3131 generate_code(mrb_state *mrb, parser_state *p, int val)
3132 {
3133   codegen_scope *scope = scope_new(mrb, 0, 0);
3134   struct RProc *proc;
3135   struct mrb_jmpbuf *prev_jmp = mrb->jmp;
3136
3137   if (!scope) {
3138     return NULL;
3139   }
3140   scope->mrb = mrb;
3141   scope->parser = p;
3142   scope->filename_sym = p->filename_sym;
3143   scope->filename_index = p->current_filename_index;
3144
3145   MRB_TRY(&scope->jmp) {
3146     mrb->jmp = &scope->jmp;
3147     /* prepare irep */
3148     codegen(scope, p->tree, val);
3149     proc = mrb_proc_new(mrb, scope->irep);
3150     mrb_irep_decref(mrb, scope->irep);
3151     mrb_pool_close(scope->mpool);
3152     proc->c = NULL;
3153     if (mrb->c->cibase && mrb->c->cibase->proc == proc->upper) {
3154       proc->upper = NULL;
3155     }
3156     mrb->jmp = prev_jmp;
3157     return proc;
3158   }
3159   MRB_CATCH(&scope->jmp) {
3160     mrb_irep_decref(mrb, scope->irep);
3161     mrb_pool_close(scope->mpool);
3162     mrb->jmp = prev_jmp;
3163     return NULL;
3164   }
3165   MRB_END_EXC(&scope->jmp);
3166 }
3167
3168 MRB_API struct RProc*
3169 mrb_generate_code(mrb_state *mrb, parser_state *p)
3170 {
3171   return generate_code(mrb, p, VAL);
3172 }
3173
3174 void
3175 mrb_irep_remove_lv(mrb_state *mrb, mrb_irep *irep)
3176 {
3177   int i;
3178
3179   if (irep->lv) {
3180     mrb_free(mrb, irep->lv);
3181     irep->lv = NULL;
3182   }
3183
3184   for (i = 0; i < irep->rlen; ++i) {
3185     mrb_irep_remove_lv(mrb, irep->reps[i]);
3186   }
3187 }
3188
3189 #undef OPCODE
3190 #define Z 1
3191 #define S 3
3192 #define W 4
3193 /* instruction sizes */
3194 uint8_t mrb_insn_size[] = {
3195 #define B 2
3196 #define BB 3
3197 #define BBB 4
3198 #define BS 4
3199 #define SB 4
3200 #define OPCODE(_,x) x,
3201 #include "mruby/ops.h"
3202 #undef OPCODE
3203 #undef B
3204 #undef BB
3205 #undef BS
3206 #undef SB
3207 #undef BBB
3208 };
3209 /* EXT1 instruction sizes */
3210 uint8_t mrb_insn_size1[] = {
3211 #define B 3
3212 #define BB 4
3213 #define BBB 5
3214 #define BS 5
3215 #define SB 5
3216 #define OPCODE(_,x) x,
3217 #include "mruby/ops.h"
3218 #undef OPCODE
3219 #undef B
3220 };
3221 /* EXT2 instruction sizes */
3222 uint8_t mrb_insn_size2[] = {
3223 #define B 2
3224 #define OPCODE(_,x) x,
3225 #include "mruby/ops.h"
3226 #undef OPCODE
3227 #undef BB
3228 #undef BBB
3229 #undef BS
3230 #undef SB
3231 };
3232 /* EXT3 instruction sizes */
3233 #define BB 5
3234 #define BBB 6
3235 #define BS 4
3236 #define SB 5
3237 uint8_t mrb_insn_size3[] = {
3238 #define OPCODE(_,x) x,
3239 #include "mruby/ops.h"
3240 };