source: EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-compiler/core/codegen.c@ 439

Last change on this file since 439 was 439, checked in by coas-nagasima, 4 years ago

mrubyを2.1.1に更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 71.4 KB
Line 
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
29typedef mrb_ast_node node;
30typedef struct mrb_parser_state parser_state;
31
32enum looptype {
33 LOOP_NORMAL,
34 LOOP_BLOCK,
35 LOOP_FOR,
36 LOOP_BEGIN,
37 LOOP_RESCUE,
38};
39
40struct loopinfo {
41 enum looptype type;
42 int pc0, pc1, pc2, pc3, acc;
43 int ensure_level;
44 struct loopinfo *prev;
45};
46
47typedef 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
86static codegen_scope* scope_new(mrb_state *mrb, codegen_scope *prev, node *lv);
87static void scope_finish(codegen_scope *s);
88static struct loopinfo *loop_push(codegen_scope *s, enum looptype t);
89static void loop_break(codegen_scope *s, node *tree);
90static void loop_pop(codegen_scope *s, int val);
91
92static void gen_assignment(codegen_scope *s, node *tree, int sp, int val);
93static void gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val);
94
95static void codegen(codegen_scope *s, node *tree, int val);
96static void raise_error(codegen_scope *s, const char *msg);
97
98static void
99codegen_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_free(s->mrb, s->lines);
106 mrb_pool_close(s->mpool);
107 s = tmp;
108 }
109#ifndef MRB_DISABLE_STDIO
110 if (s->filename_sym && s->lineno) {
111 const char *filename = mrb_sym_name_len(s->mrb, s->filename_sym, NULL);
112 fprintf(stderr, "codegen error:%s:%d: %s\n", filename, s->lineno, message);
113 }
114 else {
115 fprintf(stderr, "codegen error: %s\n", message);
116 }
117#endif
118 MRB_THROW(&s->jmp);
119}
120
121static void*
122codegen_palloc(codegen_scope *s, size_t len)
123{
124 void *p = mrb_pool_alloc(s->mpool, len);
125
126 if (!p) codegen_error(s, "pool memory allocation");
127 return p;
128}
129
130static void*
131codegen_realloc(codegen_scope *s, void *p, size_t len)
132{
133 p = mrb_realloc_simple(s->mrb, p, len);
134
135 if (!p && len > 0) codegen_error(s, "mrb_realloc");
136 return p;
137}
138
139static int
140new_label(codegen_scope *s)
141{
142 return s->lastlabel = s->pc;
143}
144
145static void
146emit_B(codegen_scope *s, uint32_t pc, uint8_t i)
147{
148 if (pc >= MAXARG_S || s->icapa >= MAXARG_S) {
149 codegen_error(s, "too big code block");
150 }
151 if (pc >= s->icapa) {
152 s->icapa *= 2;
153 if (s->icapa > MAXARG_S) {
154 s->icapa = MAXARG_S;
155 }
156 s->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->icapa);
157 if (s->lines) {
158 s->lines = (uint16_t*)codegen_realloc(s, s->lines, sizeof(uint16_t)*s->icapa);
159 }
160 }
161 if (s->lines) {
162 if (s->lineno > 0 || pc == 0)
163 s->lines[pc] = s->lineno;
164 else
165 s->lines[pc] = s->lines[pc-1];
166 }
167 s->iseq[pc] = i;
168}
169
170static void
171emit_S(codegen_scope *s, int pc, uint16_t i)
172{
173 uint8_t hi = i>>8;
174 uint8_t lo = i&0xff;
175
176 emit_B(s, pc, hi);
177 emit_B(s, pc+1, lo);
178}
179
180static void
181gen_B(codegen_scope *s, uint8_t i)
182{
183 emit_B(s, s->pc, i);
184 s->pc++;
185}
186
187static void
188gen_S(codegen_scope *s, uint16_t i)
189{
190 emit_S(s, s->pc, i);
191 s->pc += 2;
192}
193
194static void
195genop_0(codegen_scope *s, mrb_code i)
196{
197 s->lastpc = s->pc;
198 gen_B(s, i);
199}
200
201static void
202genop_1(codegen_scope *s, mrb_code i, uint16_t a)
203{
204 s->lastpc = s->pc;
205 if (a > 0xff) {
206 gen_B(s, OP_EXT1);
207 gen_B(s, i);
208 gen_S(s, a);
209 }
210 else {
211 gen_B(s, i);
212 gen_B(s, (uint8_t)a);
213 }
214}
215
216static void
217genop_2(codegen_scope *s, mrb_code i, uint16_t a, uint16_t b)
218{
219 s->lastpc = s->pc;
220 if (a > 0xff && b > 0xff) {
221 gen_B(s, OP_EXT3);
222 gen_B(s, i);
223 gen_S(s, a);
224 gen_S(s, b);
225 }
226 else if (b > 0xff) {
227 gen_B(s, OP_EXT2);
228 gen_B(s, i);
229 gen_B(s, (uint8_t)a);
230 gen_S(s, b);
231 }
232 else if (a > 0xff) {
233 gen_B(s, OP_EXT1);
234 gen_B(s, i);
235 gen_S(s, a);
236 gen_B(s, (uint8_t)b);
237 }
238 else {
239 gen_B(s, i);
240 gen_B(s, (uint8_t)a);
241 gen_B(s, (uint8_t)b);
242 }
243}
244
245static void
246genop_3(codegen_scope *s, mrb_code i, uint16_t a, uint16_t b, uint8_t c)
247{
248 genop_2(s, i, a, b);
249 gen_B(s, c);
250}
251
252static void
253genop_2S(codegen_scope *s, mrb_code i, uint16_t a, uint16_t b)
254{
255 genop_1(s, i, a);
256 gen_S(s, b);
257}
258
259static void
260genop_W(codegen_scope *s, mrb_code i, uint32_t a)
261{
262 uint8_t a1 = (a>>16) & 0xff;
263 uint8_t a2 = (a>>8) & 0xff;
264 uint8_t a3 = a & 0xff;
265
266 s->lastpc = s->pc;
267 gen_B(s, i);
268 gen_B(s, a1);
269 gen_B(s, a2);
270 gen_B(s, a3);
271}
272
273#define NOVAL 0
274#define VAL 1
275
276static mrb_bool
277no_optimize(codegen_scope *s)
278{
279 if (s && s->parser && s->parser->no_optimize)
280 return TRUE;
281 return FALSE;
282}
283
284static
285mrb_bool
286on_eval(codegen_scope *s)
287{
288 if (s && s->parser && s->parser->on_eval)
289 return TRUE;
290 return FALSE;
291}
292
293struct mrb_insn_data
294mrb_decode_insn(const 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
343static struct mrb_insn_data
344mrb_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
355static mrb_bool
356no_peephole(codegen_scope *s)
357{
358 return no_optimize(s) || s->lastlabel == s->pc || s->pc == 0 || s->pc == s->lastpc;
359}
360
361static uint16_t
362genjmp(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
373static uint16_t
374genjmp2(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
404static void
405gen_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
446static void
447gen_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
465static void
466gen_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
503static int
504dispatch(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
514static void
515dispatch_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)
525static void
526push_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
535static void
536pop_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
550static inline int
551new_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_string_p(*pv)) 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_float_p(*pv)) 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, RSTRING_PTR(val), RSTRING_LEN(val), RSTR_NOFREE_P(RSTRING(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
626static int
627new_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
645static int
646node_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
663static int
664lv_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
677static void
678for_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
690 push(); /* push for a block parameter */
691
692 /* generate loop variable */
693 n2 = tree->car;
694 genop_W(s, OP_ENTER, 0x40000);
695 if (n2->car && !n2->car->cdr && !n2->cdr) {
696 gen_assignment(s, n2->car->car, 1, NOVAL);
697 }
698 else {
699 gen_vmassignment(s, n2, 1, VAL);
700 }
701 /* construct loop */
702 lp = loop_push(s, LOOP_FOR);
703 lp->pc2 = new_label(s);
704
705 /* loop body */
706 codegen(s, tree->cdr->cdr->car, VAL);
707 pop();
708 gen_return(s, OP_RETURN, cursp());
709 loop_pop(s, NOVAL);
710 scope_finish(s);
711 s = prev;
712 genop_2(s, OP_BLOCK, cursp(), s->irep->rlen-1);
713 push();pop(); /* space for a block */
714 pop();
715 idx = new_sym(s, mrb_intern_lit(s->mrb, "each"));
716 genop_3(s, OP_SENDB, cursp(), idx, 0);
717}
718
719static int
720lambda_body(codegen_scope *s, node *tree, int blk)
721{
722 codegen_scope *parent = s;
723 s = scope_new(s->mrb, s, tree->car);
724
725 s->mscope = !blk;
726
727 if (blk) {
728 struct loopinfo *lp = loop_push(s, LOOP_BLOCK);
729 lp->pc0 = new_label(s);
730 }
731 tree = tree->cdr;
732 if (tree->car == NULL) {
733 genop_W(s, OP_ENTER, 0);
734 }
735 else {
736 mrb_aspec a;
737 int ma, oa, ra, pa, ka, kd, ba;
738 int pos, i;
739 node *opt;
740 node *margs, *pargs;
741 node *tail;
742
743 /* mandatory arguments */
744 ma = node_len(tree->car->car);
745 margs = tree->car->car;
746 tail = tree->car->cdr->cdr->cdr->cdr;
747
748 /* optional arguments */
749 oa = node_len(tree->car->cdr->car);
750 /* rest argument? */
751 ra = tree->car->cdr->cdr->car ? 1 : 0;
752 /* mandatory arugments after rest argument */
753 pa = node_len(tree->car->cdr->cdr->cdr->car);
754 pargs = tree->car->cdr->cdr->cdr->car;
755 /* keyword arguments */
756 ka = tail? node_len(tail->cdr->car) : 0;
757 /* keyword dictionary? */
758 kd = tail && tail->cdr->cdr->car? 1 : 0;
759 /* block argument? */
760 ba = tail && tail->cdr->cdr->cdr->car ? 1 : 0;
761
762 if (ma > 0x1f || oa > 0x1f || pa > 0x1f || ka > 0x1f) {
763 codegen_error(s, "too many formal arguments");
764 }
765 a = MRB_ARGS_REQ(ma)
766 | MRB_ARGS_OPT(oa)
767 | (ra? MRB_ARGS_REST() : 0)
768 | MRB_ARGS_POST(pa)
769 | MRB_ARGS_KEY(ka, kd)
770 | (ba? MRB_ARGS_BLOCK() : 0);
771 s->ainfo = (((ma+oa) & 0x3f) << 7) /* (12bits = 5:1:5:1) */
772 | ((ra & 0x1) << 6)
773 | ((pa & 0x1f) << 1)
774 | ((ka | kd) != 0 ? 0x01 : 0x00);
775 genop_W(s, OP_ENTER, a);
776 /* generate jump table for optional arguments initializer */
777 pos = new_label(s);
778 for (i=0; i<oa; i++) {
779 new_label(s);
780 genjmp(s, OP_JMP, 0);
781 }
782 if (oa > 0) {
783 genjmp(s, OP_JMP, 0);
784 }
785 opt = tree->car->cdr->car;
786 i = 0;
787 while (opt) {
788 int idx;
789
790 dispatch(s, pos+i*3+1);
791 codegen(s, opt->car->cdr, VAL);
792 pop();
793 idx = lv_idx(s, nsym(opt->car->car));
794 gen_move(s, idx, cursp(), 0);
795 i++;
796 opt = opt->cdr;
797 }
798 if (oa > 0) {
799 dispatch(s, pos+i*3+1);
800 }
801
802 /* keyword arguments */
803 if (tail) {
804 node *kwds = tail->cdr->car;
805 int kwrest = 0;
806
807 if (tail->cdr->cdr->car) {
808 kwrest = 1;
809 }
810 mrb_assert(nint(tail->car) == NODE_ARGS_TAIL);
811 mrb_assert(node_len(tail) == 4);
812
813 while (kwds) {
814 int jmpif_key_p, jmp_def_set = -1;
815 node *kwd = kwds->car, *def_arg = kwd->cdr->cdr->car;
816 mrb_sym kwd_sym = nsym(kwd->cdr->car);
817
818 mrb_assert(nint(kwd->car) == NODE_KW_ARG);
819
820 if (def_arg) {
821 genop_2(s, OP_KEY_P, lv_idx(s, kwd_sym), new_sym(s, kwd_sym));
822 jmpif_key_p = genjmp2(s, OP_JMPIF, lv_idx(s, kwd_sym), 0, 0);
823 codegen(s, def_arg, VAL);
824 pop();
825 gen_move(s, lv_idx(s, kwd_sym), cursp(), 0);
826 jmp_def_set = genjmp(s, OP_JMP, 0);
827 dispatch(s, jmpif_key_p);
828 }
829 genop_2(s, OP_KARG, lv_idx(s, kwd_sym), new_sym(s, kwd_sym));
830 if (jmp_def_set != -1) {
831 dispatch(s, jmp_def_set);
832 }
833 i++;
834
835 kwds = kwds->cdr;
836 }
837 if (tail->cdr->car && !kwrest) {
838 genop_0(s, OP_KEYEND);
839 }
840 }
841
842 /* argument destructuring */
843 if (margs) {
844 node *n = margs;
845
846 pos = 1;
847 while (n) {
848 if (nint(n->car->car) == NODE_MASGN) {
849 gen_vmassignment(s, n->car->cdr->car, pos, NOVAL);
850 }
851 pos++;
852 n = n->cdr;
853 }
854 }
855 if (pargs) {
856 node *n = margs;
857
858 pos = ma+oa+ra+1;
859 while (n) {
860 if (nint(n->car->car) == NODE_MASGN) {
861 gen_vmassignment(s, n->car->cdr->car, pos, NOVAL);
862 }
863 pos++;
864 n = n->cdr;
865 }
866 }
867 }
868
869 codegen(s, tree->cdr->car, VAL);
870 pop();
871 if (s->pc > 0) {
872 gen_return(s, OP_RETURN, cursp());
873 }
874 if (blk) {
875 loop_pop(s, NOVAL);
876 }
877 scope_finish(s);
878 return parent->irep->rlen - 1;
879}
880
881static int
882scope_body(codegen_scope *s, node *tree, int val)
883{
884 codegen_scope *scope = scope_new(s->mrb, s, tree->car);
885
886 codegen(scope, tree->cdr, VAL);
887 gen_return(scope, OP_RETURN, scope->sp-1);
888 if (!s->iseq) {
889 genop_0(scope, OP_STOP);
890 }
891 scope_finish(scope);
892 if (!s->irep) {
893 /* should not happen */
894 return 0;
895 }
896 return s->irep->rlen - 1;
897}
898
899static mrb_bool
900nosplat(node *t)
901{
902 while (t) {
903 if (nint(t->car->car) == NODE_SPLAT) return FALSE;
904 t = t->cdr;
905 }
906 return TRUE;
907}
908
909static mrb_sym
910attrsym(codegen_scope *s, mrb_sym a)
911{
912 const char *name;
913 mrb_int len;
914 char *name2;
915
916 name = mrb_sym_name_len(s->mrb, a, &len);
917 name2 = (char *)codegen_palloc(s,
918 (size_t)len
919 + 1 /* '=' */
920 + 1 /* '\0' */
921 );
922 mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX);
923 memcpy(name2, name, (size_t)len);
924 name2[len] = '=';
925 name2[len+1] = '\0';
926
927 return mrb_intern(s->mrb, name2, len+1);
928}
929
930#define CALL_MAXARGS 127
931
932static int
933gen_values(codegen_scope *s, node *t, int val, int extra)
934{
935 int n = 0;
936 int is_splat;
937
938 while (t) {
939 is_splat = nint(t->car->car) == NODE_SPLAT; /* splat mode */
940 if (
941 n+extra >= CALL_MAXARGS - 1 /* need to subtract one because vm.c expects an array if n == CALL_MAXARGS */
942 || is_splat) {
943 if (val) {
944 if (is_splat && n == 0 && nint(t->car->cdr->car) == NODE_ARRAY) {
945 codegen(s, t->car->cdr, VAL);
946 pop();
947 }
948 else {
949 pop_n(n);
950 if (n == 0 && is_splat) {
951 genop_1(s, OP_LOADNIL, cursp());
952 }
953 else {
954 genop_2(s, OP_ARRAY, cursp(), n);
955 }
956 push();
957 codegen(s, t->car, VAL);
958 pop(); pop();
959 if (is_splat) {
960 genop_1(s, OP_ARYCAT, cursp());
961 }
962 else {
963 genop_1(s, OP_ARYPUSH, cursp());
964 }
965 }
966 t = t->cdr;
967 while (t) {
968 push();
969 codegen(s, t->car, VAL);
970 pop(); pop();
971 if (nint(t->car->car) == NODE_SPLAT) {
972 genop_1(s, OP_ARYCAT, cursp());
973 }
974 else {
975 genop_1(s, OP_ARYPUSH, cursp());
976 }
977 t = t->cdr;
978 }
979 }
980 else {
981 while (t) {
982 codegen(s, t->car, NOVAL);
983 t = t->cdr;
984 }
985 }
986 return -1;
987 }
988 /* normal (no splat) mode */
989 codegen(s, t->car, val);
990 n++;
991 t = t->cdr;
992 }
993 return n;
994}
995
996static void
997gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe)
998{
999 mrb_sym sym = name ? name : nsym(tree->cdr->car);
1000 int skip = 0;
1001 int n = 0, noop = 0, sendv = 0, blk = 0;
1002
1003 codegen(s, tree->car, VAL); /* receiver */
1004 if (safe) {
1005 int recv = cursp()-1;
1006 gen_move(s, cursp(), recv, 1);
1007 skip = genjmp2(s, OP_JMPNIL, cursp(), 0, val);
1008 }
1009 tree = tree->cdr->cdr->car;
1010 if (tree) {
1011 n = gen_values(s, tree->car, VAL, sp?1:0);
1012 if (n < 0) {
1013 n = noop = sendv = 1;
1014 push();
1015 }
1016 }
1017 if (sp) { /* last argument pushed (attr=) */
1018 if (sendv) {
1019 gen_move(s, cursp(), sp, 0);
1020 pop();
1021 genop_1(s, OP_ARYPUSH, cursp());
1022 push();
1023 }
1024 else {
1025 gen_move(s, cursp(), sp, 0);
1026 push();
1027 n++;
1028 }
1029 }
1030 if (tree && tree->cdr) {
1031 noop = 1;
1032 codegen(s, tree->cdr, VAL);
1033 pop();
1034 blk = 1;
1035 }
1036 push();pop();
1037 pop_n(n+1);
1038 {
1039 mrb_int symlen;
1040 const char *symname = mrb_sym_name_len(s->mrb, sym, &symlen);
1041
1042 if (!noop && symlen == 1 && symname[0] == '+' && n == 1) {
1043 gen_addsub(s, OP_ADD, cursp());
1044 }
1045 else if (!noop && symlen == 1 && symname[0] == '-' && n == 1) {
1046 gen_addsub(s, OP_SUB, cursp());
1047 }
1048 else if (!noop && symlen == 1 && symname[0] == '*' && n == 1) {
1049 genop_1(s, OP_MUL, cursp());
1050 }
1051 else if (!noop && symlen == 1 && symname[0] == '/' && n == 1) {
1052 genop_1(s, OP_DIV, cursp());
1053 }
1054 else if (!noop && symlen == 1 && symname[0] == '<' && n == 1) {
1055 genop_1(s, OP_LT, cursp());
1056 }
1057 else if (!noop && symlen == 2 && symname[0] == '<' && symname[1] == '=' && n == 1) {
1058 genop_1(s, OP_LE, cursp());
1059 }
1060 else if (!noop && symlen == 1 && symname[0] == '>' && n == 1) {
1061 genop_1(s, OP_GT, cursp());
1062 }
1063 else if (!noop && symlen == 2 && symname[0] == '>' && symname[1] == '=' && n == 1) {
1064 genop_1(s, OP_GE, cursp());
1065 }
1066 else if (!noop && symlen == 2 && symname[0] == '=' && symname[1] == '=' && n == 1) {
1067 genop_1(s, OP_EQ, cursp());
1068 }
1069 else {
1070 int idx = new_sym(s, sym);
1071
1072 if (sendv) {
1073 genop_2(s, blk ? OP_SENDVB : OP_SENDV, cursp(), idx);
1074 }
1075 else {
1076 genop_3(s, blk ? OP_SENDB : OP_SEND, cursp(), idx, n);
1077 }
1078 }
1079 }
1080 if (safe) {
1081 dispatch(s, skip);
1082 }
1083 if (val) {
1084 push();
1085 }
1086}
1087
1088static void
1089gen_assignment(codegen_scope *s, node *tree, int sp, int val)
1090{
1091 int idx;
1092 int type = nint(tree->car);
1093
1094 tree = tree->cdr;
1095 switch (type) {
1096 case NODE_GVAR:
1097 idx = new_sym(s, nsym(tree));
1098 genop_2(s, OP_SETGV, sp, idx);
1099 break;
1100 case NODE_ARG:
1101 case NODE_LVAR:
1102 idx = lv_idx(s, nsym(tree));
1103 if (idx > 0) {
1104 if (idx != sp) {
1105 gen_move(s, idx, sp, val);
1106 if (val && on_eval(s)) genop_0(s, OP_NOP);
1107 }
1108 break;
1109 }
1110 else { /* upvar */
1111 int lv = 0;
1112 codegen_scope *up = s->prev;
1113
1114 while (up) {
1115 idx = lv_idx(up, nsym(tree));
1116 if (idx > 0) {
1117 genop_3(s, OP_SETUPVAR, sp, idx, lv);
1118 break;
1119 }
1120 lv++;
1121 up = up->prev;
1122 }
1123 }
1124 break;
1125 case NODE_NVAR:
1126 idx = nint(tree);
1127 codegen_error(s, "Can't assign to numbered parameter");
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
1178static void
1179gen_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
1229static void
1230gen_intern(codegen_scope *s)
1231{
1232 pop();
1233 genop_1(s, OP_INTERN, cursp());
1234 push();
1235}
1236
1237static void
1238gen_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
1291static void
1292raise_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
1300static double
1301readint_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
1327static mrb_int
1328readint_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
1370static void
1371gen_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
1384static void
1385codegen(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_sym_name_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, nil_p = FALSE;
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 case NODE_CALL:
1574 {
1575 node *n = tree->car->cdr;
1576 mrb_sym mid = nsym(n->cdr->car);
1577 mrb_sym mnil = mrb_intern_lit(s->mrb, "nil?");
1578 if (mid == mnil && n->cdr->cdr->car == NULL) {
1579 nil_p = TRUE;
1580 codegen(s, n->car, VAL);
1581 }
1582 }
1583 break;
1584 }
1585 if (!nil_p) {
1586 codegen(s, tree->car, VAL);
1587 }
1588 pop();
1589 if (val || tree->cdr->car) {
1590 if (nil_p) {
1591 pos2 = genjmp2(s, OP_JMPNIL, cursp(), 0, val);
1592 pos1 = genjmp(s, OP_JMP, 0);
1593 dispatch(s, pos2);
1594 }
1595 else {
1596 pos1 = genjmp2(s, OP_JMPNOT, cursp(), 0, val);
1597 }
1598 codegen(s, tree->cdr->car, val);
1599 if (val) pop();
1600 if (elsepart || val) {
1601 pos2 = genjmp(s, OP_JMP, 0);
1602 dispatch(s, pos1);
1603 codegen(s, elsepart, val);
1604 dispatch(s, pos2);
1605 }
1606 else {
1607 dispatch(s, pos1);
1608 }
1609 }
1610 else { /* empty then-part */
1611 if (elsepart) {
1612 if (nil_p) {
1613 pos1 = genjmp2(s, OP_JMPNIL, cursp(), 0, val);
1614 }
1615 else {
1616 pos1 = genjmp2(s, OP_JMPIF, cursp(), 0, val);
1617 }
1618 codegen(s, elsepart, val);
1619 dispatch(s, pos1);
1620 }
1621 else if (val && !nil_p) {
1622 genop_1(s, OP_LOADNIL, cursp());
1623 push();
1624 }
1625 }
1626 }
1627 break;
1628
1629 case NODE_AND:
1630 {
1631 int pos;
1632
1633 codegen(s, tree->car, VAL);
1634 pop();
1635 pos = genjmp2(s, OP_JMPNOT, cursp(), 0, val);
1636 codegen(s, tree->cdr, val);
1637 dispatch(s, pos);
1638 }
1639 break;
1640
1641 case NODE_OR:
1642 {
1643 int pos;
1644
1645 codegen(s, tree->car, VAL);
1646 pop();
1647 pos = genjmp2(s, OP_JMPIF, cursp(), 0, val);
1648 codegen(s, tree->cdr, val);
1649 dispatch(s, pos);
1650 }
1651 break;
1652
1653 case NODE_WHILE:
1654 {
1655 struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
1656
1657 lp->pc0 = new_label(s);
1658 lp->pc1 = genjmp(s, OP_JMP, 0);
1659 lp->pc2 = new_label(s);
1660 codegen(s, tree->cdr, NOVAL);
1661 dispatch(s, lp->pc1);
1662 codegen(s, tree->car, VAL);
1663 pop();
1664 genjmp2(s, OP_JMPIF, cursp(), lp->pc2, NOVAL);
1665
1666 loop_pop(s, val);
1667 }
1668 break;
1669
1670 case NODE_UNTIL:
1671 {
1672 struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
1673
1674 lp->pc0 = new_label(s);
1675 lp->pc1 = genjmp(s, OP_JMP, 0);
1676 lp->pc2 = new_label(s);
1677 codegen(s, tree->cdr, NOVAL);
1678 dispatch(s, lp->pc1);
1679 codegen(s, tree->car, VAL);
1680 pop();
1681 genjmp2(s, OP_JMPNOT, cursp(), lp->pc2, NOVAL);
1682
1683 loop_pop(s, val);
1684 }
1685 break;
1686
1687 case NODE_FOR:
1688 for_body(s, tree);
1689 if (val) push();
1690 break;
1691
1692 case NODE_CASE:
1693 {
1694 int head = 0;
1695 int pos1, pos2, pos3, tmp;
1696 node *n;
1697
1698 pos3 = 0;
1699 if (tree->car) {
1700 head = cursp();
1701 codegen(s, tree->car, VAL);
1702 }
1703 tree = tree->cdr;
1704 while (tree) {
1705 n = tree->car->car;
1706 pos1 = pos2 = 0;
1707 while (n) {
1708 codegen(s, n->car, VAL);
1709 if (head) {
1710 gen_move(s, cursp(), head, 0);
1711 push(); push(); pop(); pop(); pop();
1712 if (nint(n->car->car) == NODE_SPLAT) {
1713 genop_3(s, OP_SEND, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1);
1714 }
1715 else {
1716 genop_3(s, OP_SEND, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "===")), 1);
1717 }
1718 }
1719 else {
1720 pop();
1721 }
1722 tmp = genjmp2(s, OP_JMPIF, cursp(), pos2, NOVAL);
1723 pos2 = tmp;
1724 n = n->cdr;
1725 }
1726 if (tree->car->car) {
1727 pos1 = genjmp(s, OP_JMP, 0);
1728 dispatch_linked(s, pos2);
1729 }
1730 codegen(s, tree->car->cdr, val);
1731 if (val) pop();
1732 tmp = genjmp(s, OP_JMP, pos3);
1733 pos3 = tmp;
1734 if (pos1) dispatch(s, pos1);
1735 tree = tree->cdr;
1736 }
1737 if (val) {
1738 int pos = cursp();
1739 genop_1(s, OP_LOADNIL, cursp());
1740 if (pos3) dispatch_linked(s, pos3);
1741 if (head) pop();
1742 if (cursp() != pos) {
1743 gen_move(s, cursp(), pos, 0);
1744 }
1745 push();
1746 }
1747 else {
1748 if (pos3) {
1749 dispatch_linked(s, pos3);
1750 }
1751 if (head) {
1752 pop();
1753 }
1754 }
1755 }
1756 break;
1757
1758 case NODE_SCOPE:
1759 scope_body(s, tree, NOVAL);
1760 break;
1761
1762 case NODE_FCALL:
1763 case NODE_CALL:
1764 gen_call(s, tree, 0, 0, val, 0);
1765 break;
1766 case NODE_SCALL:
1767 gen_call(s, tree, 0, 0, val, 1);
1768 break;
1769
1770 case NODE_DOT2:
1771 codegen(s, tree->car, val);
1772 codegen(s, tree->cdr, val);
1773 if (val) {
1774 pop(); pop();
1775 genop_1(s, OP_RANGE_INC, cursp());
1776 push();
1777 }
1778 break;
1779
1780 case NODE_DOT3:
1781 codegen(s, tree->car, val);
1782 codegen(s, tree->cdr, val);
1783 if (val) {
1784 pop(); pop();
1785 genop_1(s, OP_RANGE_EXC, cursp());
1786 push();
1787 }
1788 break;
1789
1790 case NODE_COLON2:
1791 {
1792 int sym = new_sym(s, nsym(tree->cdr));
1793
1794 codegen(s, tree->car, VAL);
1795 pop();
1796 genop_2(s, OP_GETMCNST, cursp(), sym);
1797 if (val) push();
1798 }
1799 break;
1800
1801 case NODE_COLON3:
1802 {
1803 int sym = new_sym(s, nsym(tree));
1804
1805 genop_1(s, OP_OCLASS, cursp());
1806 genop_2(s, OP_GETMCNST, cursp(), sym);
1807 if (val) push();
1808 }
1809 break;
1810
1811 case NODE_ARRAY:
1812 {
1813 int n;
1814
1815 n = gen_values(s, tree, val, 0);
1816 if (n >= 0) {
1817 if (val) {
1818 pop_n(n);
1819 genop_2(s, OP_ARRAY, cursp(), n);
1820 push();
1821 }
1822 }
1823 else if (val) {
1824 push();
1825 }
1826 }
1827 break;
1828
1829 case NODE_HASH:
1830 case NODE_KW_HASH:
1831 {
1832 int len = 0;
1833 mrb_bool update = FALSE;
1834
1835 while (tree) {
1836 if (nint(tree->car->car->car) == NODE_KW_REST_ARGS) {
1837 if (len > 0) {
1838 pop_n(len*2);
1839 if (!update) {
1840 genop_2(s, OP_HASH, cursp(), len);
1841 }
1842 else {
1843 pop();
1844 genop_2(s, OP_HASHADD, cursp(), len);
1845 }
1846 push();
1847 }
1848 codegen(s, tree->car->cdr, VAL);
1849 if (len > 0 || update) {
1850 pop(); pop();
1851 genop_1(s, OP_HASHCAT, cursp());
1852 push();
1853 }
1854 update = TRUE;
1855 len = 0;
1856 }
1857 else {
1858 codegen(s, tree->car->car, val);
1859 codegen(s, tree->car->cdr, val);
1860 len++;
1861 }
1862 tree = tree->cdr;
1863 if (val && len == 255) {
1864 pop_n(len*2);
1865 if (!update) {
1866 genop_2(s, OP_HASH, cursp(), len);
1867 }
1868 else {
1869 pop();
1870 genop_2(s, OP_HASHADD, cursp(), len);
1871 }
1872 push();
1873 update = TRUE;
1874 len = 0;
1875 }
1876 }
1877 if (val) {
1878 pop_n(len*2);
1879 if (!update) {
1880 genop_2(s, OP_HASH, cursp(), len);
1881 }
1882 else {
1883 pop();
1884 if (len > 0) {
1885 genop_2(s, OP_HASHADD, cursp(), len);
1886 }
1887 }
1888 push();
1889 }
1890 }
1891 break;
1892
1893 case NODE_SPLAT:
1894 codegen(s, tree, val);
1895 break;
1896
1897 case NODE_ASGN:
1898 codegen(s, tree->cdr, VAL);
1899 pop();
1900 gen_assignment(s, tree->car, cursp(), val);
1901 break;
1902
1903 case NODE_MASGN:
1904 {
1905 int len = 0, n = 0, post = 0;
1906 node *t = tree->cdr, *p;
1907 int rhs = cursp();
1908
1909 if (nint(t->car) == NODE_ARRAY && t->cdr && nosplat(t->cdr)) {
1910 /* fixed rhs */
1911 t = t->cdr;
1912 while (t) {
1913 codegen(s, t->car, VAL);
1914 len++;
1915 t = t->cdr;
1916 }
1917 tree = tree->car;
1918 if (tree->car) { /* pre */
1919 t = tree->car;
1920 n = 0;
1921 while (t) {
1922 if (n < len) {
1923 gen_assignment(s, t->car, rhs+n, NOVAL);
1924 n++;
1925 }
1926 else {
1927 genop_1(s, OP_LOADNIL, rhs+n);
1928 gen_assignment(s, t->car, rhs+n, NOVAL);
1929 }
1930 t = t->cdr;
1931 }
1932 }
1933 t = tree->cdr;
1934 if (t) {
1935 if (t->cdr) { /* post count */
1936 p = t->cdr->car;
1937 while (p) {
1938 post++;
1939 p = p->cdr;
1940 }
1941 }
1942 if (t->car) { /* rest (len - pre - post) */
1943 int rn;
1944
1945 if (len < post + n) {
1946 rn = 0;
1947 }
1948 else {
1949 rn = len - post - n;
1950 }
1951 genop_3(s, OP_ARRAY2, cursp(), rhs+n, rn);
1952 gen_assignment(s, t->car, cursp(), NOVAL);
1953 n += rn;
1954 }
1955 if (t->cdr && t->cdr->car) {
1956 t = t->cdr->car;
1957 while (n<len) {
1958 gen_assignment(s, t->car, rhs+n, NOVAL);
1959 t = t->cdr;
1960 n++;
1961 }
1962 }
1963 }
1964 pop_n(len);
1965 if (val) {
1966 genop_2(s, OP_ARRAY, rhs, len);
1967 push();
1968 }
1969 }
1970 else {
1971 /* variable rhs */
1972 codegen(s, t, VAL);
1973 gen_vmassignment(s, tree->car, rhs, val);
1974 if (!val) {
1975 pop();
1976 }
1977 }
1978 }
1979 break;
1980
1981 case NODE_OP_ASGN:
1982 {
1983 mrb_sym sym = nsym(tree->cdr->car);
1984 mrb_int len;
1985 const char *name = mrb_sym_name_len(s->mrb, sym, &len);
1986 int idx, callargs = -1, vsp = -1;
1987
1988 if ((len == 2 && name[0] == '|' && name[1] == '|') &&
1989 (nint(tree->car->car) == NODE_CONST ||
1990 nint(tree->car->car) == NODE_CVAR)) {
1991 int onerr, noexc, exc;
1992 struct loopinfo *lp;
1993
1994 onerr = genjmp(s, OP_ONERR, 0);
1995 lp = loop_push(s, LOOP_BEGIN);
1996 lp->pc1 = onerr;
1997 exc = cursp();
1998 codegen(s, tree->car, VAL);
1999 lp->type = LOOP_RESCUE;
2000 genop_1(s, OP_POPERR, 1);
2001 noexc = genjmp(s, OP_JMP, 0);
2002 dispatch(s, onerr);
2003 genop_1(s, OP_EXCEPT, exc);
2004 genop_1(s, OP_LOADF, exc);
2005 dispatch(s, noexc);
2006 loop_pop(s, NOVAL);
2007 }
2008 else if (nint(tree->car->car) == NODE_CALL) {
2009 node *n = tree->car->cdr;
2010 int base, i, nargs = 0;
2011 callargs = 0;
2012
2013 if (val) {
2014 vsp = cursp();
2015 push();
2016 }
2017 codegen(s, n->car, VAL); /* receiver */
2018 idx = new_sym(s, nsym(n->cdr->car));
2019 base = cursp()-1;
2020 if (n->cdr->cdr->car) {
2021 nargs = gen_values(s, n->cdr->cdr->car->car, VAL, 1);
2022 if (nargs >= 0) {
2023 callargs = nargs;
2024 }
2025 else { /* varargs */
2026 push();
2027 nargs = 1;
2028 callargs = CALL_MAXARGS;
2029 }
2030 }
2031 /* copy receiver and arguments */
2032 gen_move(s, cursp(), base, 1);
2033 for (i=0; i<nargs; i++) {
2034 gen_move(s, cursp()+i+1, base+i+1, 1);
2035 }
2036 push_n(nargs+2);pop_n(nargs+2); /* space for receiver, arguments and a block */
2037 genop_3(s, OP_SEND, cursp(), idx, callargs);
2038 push();
2039 }
2040 else {
2041 codegen(s, tree->car, VAL);
2042 }
2043 if (len == 2 &&
2044 ((name[0] == '|' && name[1] == '|') ||
2045 (name[0] == '&' && name[1] == '&'))) {
2046 int pos;
2047
2048 pop();
2049 if (val) {
2050 if (vsp >= 0) {
2051 gen_move(s, vsp, cursp(), 1);
2052 }
2053 pos = genjmp2(s, name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0, val);
2054 }
2055 else {
2056 pos = genjmp2(s, name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0, val);
2057 }
2058 codegen(s, tree->cdr->cdr->car, VAL);
2059 pop();
2060 if (val && vsp >= 0) {
2061 gen_move(s, vsp, cursp(), 1);
2062 }
2063 if (nint(tree->car->car) == NODE_CALL) {
2064 if (callargs == CALL_MAXARGS) {
2065 pop();
2066 genop_1(s, OP_ARYPUSH, cursp());
2067 }
2068 else {
2069 pop_n(callargs);
2070 callargs++;
2071 }
2072 pop();
2073 idx = new_sym(s, attrsym(s, nsym(tree->car->cdr->cdr->car)));
2074 genop_3(s, OP_SEND, cursp(), idx, callargs);
2075 }
2076 else {
2077 gen_assignment(s, tree->car, cursp(), val);
2078 }
2079 dispatch(s, pos);
2080 goto exit;
2081 }
2082 codegen(s, tree->cdr->cdr->car, VAL);
2083 push(); pop();
2084 pop(); pop();
2085
2086 if (len == 1 && name[0] == '+') {
2087 gen_addsub(s, OP_ADD, cursp());
2088 }
2089 else if (len == 1 && name[0] == '-') {
2090 gen_addsub(s, OP_SUB, cursp());
2091 }
2092 else if (len == 1 && name[0] == '*') {
2093 genop_1(s, OP_MUL, cursp());
2094 }
2095 else if (len == 1 && name[0] == '/') {
2096 genop_1(s, OP_DIV, cursp());
2097 }
2098 else if (len == 1 && name[0] == '<') {
2099 genop_1(s, OP_LT, cursp());
2100 }
2101 else if (len == 2 && name[0] == '<' && name[1] == '=') {
2102 genop_1(s, OP_LE, cursp());
2103 }
2104 else if (len == 1 && name[0] == '>') {
2105 genop_1(s, OP_GT, cursp());
2106 }
2107 else if (len == 2 && name[0] == '>' && name[1] == '=') {
2108 genop_1(s, OP_GE, cursp());
2109 }
2110 else {
2111 idx = new_sym(s, sym);
2112 genop_3(s, OP_SEND, cursp(), idx, 1);
2113 }
2114 if (callargs < 0) {
2115 gen_assignment(s, tree->car, cursp(), val);
2116 }
2117 else {
2118 if (val && vsp >= 0) {
2119 gen_move(s, vsp, cursp(), 0);
2120 }
2121 if (callargs == CALL_MAXARGS) {
2122 pop();
2123 genop_1(s, OP_ARYPUSH, cursp());
2124 }
2125 else {
2126 pop_n(callargs);
2127 callargs++;
2128 }
2129 pop();
2130 idx = new_sym(s, attrsym(s,nsym(tree->car->cdr->cdr->car)));
2131 genop_3(s, OP_SEND, cursp(), idx, callargs);
2132 }
2133 }
2134 break;
2135
2136 case NODE_SUPER:
2137 {
2138 codegen_scope *s2 = s;
2139 int lv = 0;
2140 int n = 0, noop = 0, sendv = 0;
2141
2142 push(); /* room for receiver */
2143 while (!s2->mscope) {
2144 lv++;
2145 s2 = s2->prev;
2146 if (!s2) break;
2147 }
2148 genop_2S(s, OP_ARGARY, cursp(), (lv & 0xf));
2149 push(); push(); /* ARGARY pushes two values */
2150 pop(); pop();
2151 if (tree) {
2152 node *args = tree->car;
2153 if (args) {
2154 n = gen_values(s, args, VAL, 0);
2155 if (n < 0) {
2156 n = noop = sendv = 1;
2157 push();
2158 }
2159 }
2160 }
2161 if (tree && tree->cdr) {
2162 codegen(s, tree->cdr, VAL);
2163 pop();
2164 }
2165 else {
2166 genop_1(s, OP_LOADNIL, cursp());
2167 push(); pop();
2168 }
2169 pop_n(n+1);
2170 if (sendv) n = CALL_MAXARGS;
2171 genop_2(s, OP_SUPER, cursp(), n);
2172 if (val) push();
2173 }
2174 break;
2175
2176 case NODE_ZSUPER:
2177 {
2178 codegen_scope *s2 = s;
2179 int lv = 0, ainfo = 0;
2180
2181 push(); /* room for receiver */
2182 while (!s2->mscope) {
2183 lv++;
2184 s2 = s2->prev;
2185 if (!s2) break;
2186 }
2187 if (s2) ainfo = s2->ainfo;
2188 genop_2S(s, OP_ARGARY, cursp(), (ainfo<<4)|(lv & 0xf));
2189 push(); push(); pop(); /* ARGARY pushes two values */
2190 if (tree && tree->cdr) {
2191 codegen(s, tree->cdr, VAL);
2192 pop();
2193 }
2194 pop(); pop();
2195 genop_2(s, OP_SUPER, cursp(), CALL_MAXARGS);
2196 if (val) push();
2197 }
2198 break;
2199
2200 case NODE_RETURN:
2201 if (tree) {
2202 gen_retval(s, tree);
2203 }
2204 else {
2205 genop_1(s, OP_LOADNIL, cursp());
2206 }
2207 if (s->loop) {
2208 gen_return(s, OP_RETURN_BLK, cursp());
2209 }
2210 else {
2211 gen_return(s, OP_RETURN, cursp());
2212 }
2213 if (val) push();
2214 break;
2215
2216 case NODE_YIELD:
2217 {
2218 codegen_scope *s2 = s;
2219 int lv = 0, ainfo = 0;
2220 int n = 0, sendv = 0;
2221
2222 while (!s2->mscope) {
2223 lv++;
2224 s2 = s2->prev;
2225 if (!s2) break;
2226 }
2227 if (s2) ainfo = s2->ainfo;
2228 push();
2229 if (tree) {
2230 n = gen_values(s, tree, VAL, 0);
2231 if (n < 0) {
2232 n = sendv = 1;
2233 push();
2234 }
2235 }
2236 push();pop(); /* space for a block */
2237 pop_n(n+1);
2238 genop_2S(s, OP_BLKPUSH, cursp(), (ainfo<<4)|(lv & 0xf));
2239 if (sendv) n = CALL_MAXARGS;
2240 genop_3(s, OP_SEND, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "call")), n);
2241 if (val) push();
2242 }
2243 break;
2244
2245 case NODE_BREAK:
2246 loop_break(s, tree);
2247 if (val) push();
2248 break;
2249
2250 case NODE_NEXT:
2251 if (!s->loop) {
2252 raise_error(s, "unexpected next");
2253 }
2254 else if (s->loop->type == LOOP_NORMAL) {
2255 if (s->ensure_level > s->loop->ensure_level) {
2256 genop_1(s, OP_EPOP, s->ensure_level - s->loop->ensure_level);
2257 }
2258 codegen(s, tree, NOVAL);
2259 genjmp(s, OP_JMP, s->loop->pc0);
2260 }
2261 else {
2262 if (tree) {
2263 codegen(s, tree, VAL);
2264 pop();
2265 }
2266 else {
2267 genop_1(s, OP_LOADNIL, cursp());
2268 }
2269 gen_return(s, OP_RETURN, cursp());
2270 }
2271 if (val) push();
2272 break;
2273
2274 case NODE_REDO:
2275 if (!s->loop || s->loop->type == LOOP_BEGIN || s->loop->type == LOOP_RESCUE) {
2276 raise_error(s, "unexpected redo");
2277 }
2278 else {
2279 if (s->ensure_level > s->loop->ensure_level) {
2280 genop_1(s, OP_EPOP, s->ensure_level - s->loop->ensure_level);
2281 }
2282 genjmp(s, OP_JMP, s->loop->pc2);
2283 }
2284 if (val) push();
2285 break;
2286
2287 case NODE_RETRY:
2288 {
2289 const char *msg = "unexpected retry";
2290
2291 if (!s->loop) {
2292 raise_error(s, msg);
2293 }
2294 else {
2295 struct loopinfo *lp = s->loop;
2296 int n = 0;
2297
2298 while (lp && lp->type != LOOP_RESCUE) {
2299 if (lp->type == LOOP_BEGIN) {
2300 n++;
2301 }
2302 lp = lp->prev;
2303 }
2304 if (!lp) {
2305 raise_error(s, msg);
2306 }
2307 else {
2308 if (n > 0) {
2309 genop_1(s, OP_POPERR, n);
2310 }
2311 if (s->ensure_level > lp->ensure_level) {
2312 genop_1(s, OP_EPOP, s->ensure_level - lp->ensure_level);
2313 }
2314 genjmp(s, OP_JMP, lp->pc0);
2315 }
2316 }
2317 if (val) push();
2318 }
2319 break;
2320
2321 case NODE_LVAR:
2322 if (val) {
2323 int idx = lv_idx(s, nsym(tree));
2324
2325 if (idx > 0) {
2326 gen_move(s, cursp(), idx, val);
2327 if (val && on_eval(s)) genop_0(s, OP_NOP);
2328 }
2329 else {
2330 int lv = 0;
2331 codegen_scope *up = s->prev;
2332
2333 while (up) {
2334 idx = lv_idx(up, nsym(tree));
2335 if (idx > 0) {
2336 genop_3(s, OP_GETUPVAR, cursp(), idx, lv);
2337 break;
2338 }
2339 lv++;
2340 up = up->prev;
2341 }
2342 }
2343 push();
2344 }
2345 break;
2346
2347 case NODE_NVAR:
2348 if (val) {
2349 int idx = nint(tree);
2350
2351 gen_move(s, cursp(), idx, val);
2352 if (val && on_eval(s)) genop_0(s, OP_NOP);
2353
2354 push();
2355 }
2356 break;
2357
2358 case NODE_GVAR:
2359 {
2360 int sym = new_sym(s, nsym(tree));
2361
2362 genop_2(s, OP_GETGV, cursp(), sym);
2363 if (val) push();
2364 }
2365 break;
2366
2367 case NODE_IVAR:
2368 {
2369 int sym = new_sym(s, nsym(tree));
2370
2371 genop_2(s, OP_GETIV, cursp(), sym);
2372 if (val) push();
2373 }
2374 break;
2375
2376 case NODE_CVAR:
2377 {
2378 int sym = new_sym(s, nsym(tree));
2379
2380 genop_2(s, OP_GETCV, cursp(), sym);
2381 if (val) push();
2382 }
2383 break;
2384
2385 case NODE_CONST:
2386 {
2387 int sym = new_sym(s, nsym(tree));
2388
2389 genop_2(s, OP_GETCONST, cursp(), sym);
2390 if (val) push();
2391 }
2392 break;
2393
2394 case NODE_BACK_REF:
2395 if (val) {
2396 char buf[] = {'$', nchar(tree)};
2397 int sym = new_sym(s, mrb_intern(s->mrb, buf, sizeof(buf)));
2398
2399 genop_2(s, OP_GETGV, cursp(), sym);
2400 push();
2401 }
2402 break;
2403
2404 case NODE_NTH_REF:
2405 if (val) {
2406 mrb_state *mrb = s->mrb;
2407 mrb_value str;
2408 int sym;
2409
2410 str = mrb_format(mrb, "$%d", nint(tree));
2411 sym = new_sym(s, mrb_intern_str(mrb, str));
2412 genop_2(s, OP_GETGV, cursp(), sym);
2413 push();
2414 }
2415 break;
2416
2417 case NODE_ARG:
2418 /* should not happen */
2419 break;
2420
2421 case NODE_BLOCK_ARG:
2422 codegen(s, tree, val);
2423 break;
2424
2425 case NODE_INT:
2426 if (val) {
2427 char *p = (char*)tree->car;
2428 int base = nint(tree->cdr->car);
2429 mrb_int i;
2430 mrb_bool overflow;
2431
2432 i = readint_mrb_int(s, p, base, FALSE, &overflow);
2433#ifndef MRB_WITHOUT_FLOAT
2434 if (overflow) {
2435 double f = readint_float(s, p, base);
2436 int off = new_lit(s, mrb_float_value(s->mrb, f));
2437
2438 genop_2(s, OP_LOADL, cursp(), off);
2439 }
2440 else
2441#endif
2442 {
2443 if (i == -1) genop_1(s, OP_LOADI__1, cursp());
2444 else if (i < 0) genop_2(s, OP_LOADINEG, cursp(), (uint16_t)-i);
2445 else if (i < 8) genop_1(s, OP_LOADI_0 + (uint8_t)i, cursp());
2446 else if (i <= 0xffff) genop_2(s, OP_LOADI, cursp(), (uint16_t)i);
2447 else {
2448 int off = new_lit(s, mrb_fixnum_value(i));
2449 genop_2(s, OP_LOADL, cursp(), off);
2450 }
2451 }
2452 push();
2453 }
2454 break;
2455
2456#ifndef MRB_WITHOUT_FLOAT
2457 case NODE_FLOAT:
2458 if (val) {
2459 char *p = (char*)tree;
2460 mrb_float f = mrb_float_read(p, NULL);
2461 int off = new_lit(s, mrb_float_value(s->mrb, f));
2462
2463 genop_2(s, OP_LOADL, cursp(), off);
2464 push();
2465 }
2466 break;
2467#endif
2468
2469 case NODE_NEGATE:
2470 {
2471 nt = nint(tree->car);
2472 switch (nt) {
2473#ifndef MRB_WITHOUT_FLOAT
2474 case NODE_FLOAT:
2475 if (val) {
2476 char *p = (char*)tree->cdr;
2477 mrb_float f = mrb_float_read(p, NULL);
2478 int off = new_lit(s, mrb_float_value(s->mrb, -f));
2479
2480 genop_2(s, OP_LOADL, cursp(), off);
2481 push();
2482 }
2483 break;
2484#endif
2485
2486 case NODE_INT:
2487 if (val) {
2488 char *p = (char*)tree->cdr->car;
2489 int base = nint(tree->cdr->cdr->car);
2490 mrb_int i;
2491 mrb_bool overflow;
2492
2493 i = readint_mrb_int(s, p, base, TRUE, &overflow);
2494#ifndef MRB_WITHOUT_FLOAT
2495 if (overflow) {
2496 double f = readint_float(s, p, base);
2497 int off = new_lit(s, mrb_float_value(s->mrb, -f));
2498
2499 genop_2(s, OP_LOADL, cursp(), off);
2500 }
2501 else {
2502#endif
2503 if (i == -1) genop_1(s, OP_LOADI__1, cursp());
2504 else if (i >= -0xffff) {
2505 genop_2(s, OP_LOADINEG, cursp(), (uint16_t)-i);
2506 }
2507 else {
2508 int off = new_lit(s, mrb_fixnum_value(i));
2509 genop_2(s, OP_LOADL, cursp(), off);
2510 }
2511#ifndef MRB_WITHOUT_FLOAT
2512 }
2513#endif
2514 push();
2515 }
2516 break;
2517
2518 default:
2519 if (val) {
2520 int sym = new_sym(s, mrb_intern_lit(s->mrb, "-@"));
2521 codegen(s, tree, VAL);
2522 pop();
2523 genop_3(s, OP_SEND, cursp(), sym, 0);
2524 push();
2525 }
2526 else {
2527 codegen(s, tree, NOVAL);
2528 }
2529 break;
2530 }
2531 }
2532 break;
2533
2534 case NODE_STR:
2535 if (val) {
2536 char *p = (char*)tree->car;
2537 size_t len = (intptr_t)tree->cdr;
2538 int ai = mrb_gc_arena_save(s->mrb);
2539 int off = new_lit(s, mrb_str_new(s->mrb, p, len));
2540
2541 mrb_gc_arena_restore(s->mrb, ai);
2542 genop_2(s, OP_STRING, cursp(), off);
2543 push();
2544 }
2545 break;
2546
2547 case NODE_HEREDOC:
2548 tree = ((struct mrb_parser_heredoc_info *)tree)->doc;
2549 /* fall through */
2550 case NODE_DSTR:
2551 if (val) {
2552 node *n = tree;
2553
2554 if (!n) {
2555 genop_1(s, OP_LOADNIL, cursp());
2556 push();
2557 break;
2558 }
2559 codegen(s, n->car, VAL);
2560 n = n->cdr;
2561 while (n) {
2562 codegen(s, n->car, VAL);
2563 pop(); pop();
2564 genop_1(s, OP_STRCAT, cursp());
2565 push();
2566 n = n->cdr;
2567 }
2568 }
2569 else {
2570 node *n = tree;
2571
2572 while (n) {
2573 if (nint(n->car->car) != NODE_STR) {
2574 codegen(s, n->car, NOVAL);
2575 }
2576 n = n->cdr;
2577 }
2578 }
2579 break;
2580
2581 case NODE_WORDS:
2582 gen_literal_array(s, tree, FALSE, val);
2583 break;
2584
2585 case NODE_SYMBOLS:
2586 gen_literal_array(s, tree, TRUE, val);
2587 break;
2588
2589 case NODE_DXSTR:
2590 {
2591 node *n;
2592 int ai = mrb_gc_arena_save(s->mrb);
2593 int sym = new_sym(s, mrb_intern_lit(s->mrb, "Kernel"));
2594
2595 genop_1(s, OP_LOADSELF, cursp());
2596 push();
2597 codegen(s, tree->car, VAL);
2598 n = tree->cdr;
2599 while (n) {
2600 if (nint(n->car->car) == NODE_XSTR) {
2601 n->car->car = (struct mrb_ast_node*)(intptr_t)NODE_STR;
2602 mrb_assert(!n->cdr); /* must be the end */
2603 }
2604 codegen(s, n->car, VAL);
2605 pop(); pop();
2606 genop_1(s, OP_STRCAT, cursp());
2607 push();
2608 n = n->cdr;
2609 }
2610 push(); /* for block */
2611 pop_n(3);
2612 sym = new_sym(s, mrb_intern_lit(s->mrb, "`"));
2613 genop_3(s, OP_SEND, cursp(), sym, 1);
2614 if (val) push();
2615 mrb_gc_arena_restore(s->mrb, ai);
2616 }
2617 break;
2618
2619 case NODE_XSTR:
2620 {
2621 char *p = (char*)tree->car;
2622 size_t len = (intptr_t)tree->cdr;
2623 int ai = mrb_gc_arena_save(s->mrb);
2624 int off = new_lit(s, mrb_str_new(s->mrb, p, len));
2625 int sym;
2626
2627 genop_1(s, OP_LOADSELF, cursp());
2628 push();
2629 genop_2(s, OP_STRING, cursp(), off);
2630 push(); push();
2631 pop_n(3);
2632 sym = new_sym(s, mrb_intern_lit(s->mrb, "`"));
2633 genop_3(s, OP_SEND, cursp(), sym, 1);
2634 if (val) push();
2635 mrb_gc_arena_restore(s->mrb, ai);
2636 }
2637 break;
2638
2639 case NODE_REGX:
2640 if (val) {
2641 char *p1 = (char*)tree->car;
2642 char *p2 = (char*)tree->cdr->car;
2643 char *p3 = (char*)tree->cdr->cdr;
2644 int ai = mrb_gc_arena_save(s->mrb);
2645 int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS));
2646 int off = new_lit(s, mrb_str_new_cstr(s->mrb, p1));
2647 int argc = 1;
2648
2649 genop_1(s, OP_OCLASS, cursp());
2650 genop_2(s, OP_GETMCNST, cursp(), sym);
2651 push();
2652 genop_2(s, OP_STRING, cursp(), off);
2653 push();
2654 if (p2 || p3) {
2655 if (p2) { /* opt */
2656 off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
2657 genop_2(s, OP_STRING, cursp(), off);
2658 }
2659 else {
2660 genop_1(s, OP_LOADNIL, cursp());
2661 }
2662 push();
2663 argc++;
2664 if (p3) { /* enc */
2665 off = new_lit(s, mrb_str_new(s->mrb, p3, 1));
2666 genop_2(s, OP_STRING, cursp(), off);
2667 push();
2668 argc++;
2669 }
2670 }
2671 push(); /* space for a block */
2672 pop_n(argc+2);
2673 sym = new_sym(s, mrb_intern_lit(s->mrb, "compile"));
2674 genop_3(s, OP_SEND, cursp(), sym, argc);
2675 mrb_gc_arena_restore(s->mrb, ai);
2676 push();
2677 }
2678 break;
2679
2680 case NODE_DREGX:
2681 if (val) {
2682 node *n = tree->car;
2683 int ai = mrb_gc_arena_save(s->mrb);
2684 int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS));
2685 int argc = 1;
2686 int off;
2687 char *p;
2688
2689 genop_1(s, OP_OCLASS, cursp());
2690 genop_2(s, OP_GETMCNST, cursp(), sym);
2691 push();
2692 codegen(s, n->car, VAL);
2693 n = n->cdr;
2694 while (n) {
2695 codegen(s, n->car, VAL);
2696 pop(); pop();
2697 genop_1(s, OP_STRCAT, cursp());
2698 push();
2699 n = n->cdr;
2700 }
2701 n = tree->cdr->cdr;
2702 if (n->car) { /* tail */
2703 p = (char*)n->car;
2704 off = new_lit(s, mrb_str_new_cstr(s->mrb, p));
2705 codegen(s, tree->car, VAL);
2706 genop_2(s, OP_STRING, cursp(), off);
2707 pop();
2708 genop_1(s, OP_STRCAT, cursp());
2709 push();
2710 }
2711 if (n->cdr->car) { /* opt */
2712 char *p2 = (char*)n->cdr->car;
2713 off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
2714 genop_2(s, OP_STRING, cursp(), off);
2715 push();
2716 argc++;
2717 }
2718 if (n->cdr->cdr) { /* enc */
2719 char *p2 = (char*)n->cdr->cdr;
2720 off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
2721 genop_2(s, OP_STRING, cursp(), off);
2722 push();
2723 argc++;
2724 }
2725 push(); /* space for a block */
2726 pop_n(argc+2);
2727 sym = new_sym(s, mrb_intern_lit(s->mrb, "compile"));
2728 genop_3(s, OP_SEND, cursp(), sym, argc);
2729 mrb_gc_arena_restore(s->mrb, ai);
2730 push();
2731 }
2732 else {
2733 node *n = tree->car;
2734
2735 while (n) {
2736 if (nint(n->car->car) != NODE_STR) {
2737 codegen(s, n->car, NOVAL);
2738 }
2739 n = n->cdr;
2740 }
2741 }
2742 break;
2743
2744 case NODE_SYM:
2745 if (val) {
2746 int sym = new_sym(s, nsym(tree));
2747
2748 genop_2(s, OP_LOADSYM, cursp(), sym);
2749 push();
2750 }
2751 break;
2752
2753 case NODE_DSYM:
2754 codegen(s, tree, val);
2755 if (val) {
2756 gen_intern(s);
2757 }
2758 break;
2759
2760 case NODE_SELF:
2761 if (val) {
2762 genop_1(s, OP_LOADSELF, cursp());
2763 push();
2764 }
2765 break;
2766
2767 case NODE_NIL:
2768 if (val) {
2769 genop_1(s, OP_LOADNIL, cursp());
2770 push();
2771 }
2772 break;
2773
2774 case NODE_TRUE:
2775 if (val) {
2776 genop_1(s, OP_LOADT, cursp());
2777 push();
2778 }
2779 break;
2780
2781 case NODE_FALSE:
2782 if (val) {
2783 genop_1(s, OP_LOADF, cursp());
2784 push();
2785 }
2786 break;
2787
2788 case NODE_ALIAS:
2789 {
2790 int a = new_sym(s, nsym(tree->car));
2791 int b = new_sym(s, nsym(tree->cdr));
2792
2793 genop_2(s, OP_ALIAS, a, b);
2794 if (val) {
2795 genop_1(s, OP_LOADNIL, cursp());
2796 push();
2797 }
2798 }
2799 break;
2800
2801 case NODE_UNDEF:
2802 {
2803 node *t = tree;
2804
2805 while (t) {
2806 int symbol = new_sym(s, nsym(t->car));
2807 genop_1(s, OP_UNDEF, symbol);
2808 t = t->cdr;
2809 }
2810 if (val) {
2811 genop_1(s, OP_LOADNIL, cursp());
2812 push();
2813 }
2814 }
2815 break;
2816
2817 case NODE_CLASS:
2818 {
2819 int idx;
2820 node *body;
2821
2822 if (tree->car->car == (node*)0) {
2823 genop_1(s, OP_LOADNIL, cursp());
2824 push();
2825 }
2826 else if (tree->car->car == (node*)1) {
2827 genop_1(s, OP_OCLASS, cursp());
2828 push();
2829 }
2830 else {
2831 codegen(s, tree->car->car, VAL);
2832 }
2833 if (tree->cdr->car) {
2834 codegen(s, tree->cdr->car, VAL);
2835 }
2836 else {
2837 genop_1(s, OP_LOADNIL, cursp());
2838 push();
2839 }
2840 pop(); pop();
2841 idx = new_sym(s, nsym(tree->car->cdr));
2842 genop_2(s, OP_CLASS, cursp(), idx);
2843 body = tree->cdr->cdr->car;
2844 if (nint(body->cdr->car) == NODE_BEGIN && body->cdr->cdr == NULL) {
2845 genop_1(s, OP_LOADNIL, cursp());
2846 }
2847 else {
2848 idx = scope_body(s, body, val);
2849 genop_2(s, OP_EXEC, cursp(), idx);
2850 }
2851 if (val) {
2852 push();
2853 }
2854 }
2855 break;
2856
2857 case NODE_MODULE:
2858 {
2859 int idx;
2860
2861 if (tree->car->car == (node*)0) {
2862 genop_1(s, OP_LOADNIL, cursp());
2863 push();
2864 }
2865 else if (tree->car->car == (node*)1) {
2866 genop_1(s, OP_OCLASS, cursp());
2867 push();
2868 }
2869 else {
2870 codegen(s, tree->car->car, VAL);
2871 }
2872 pop();
2873 idx = new_sym(s, nsym(tree->car->cdr));
2874 genop_2(s, OP_MODULE, cursp(), idx);
2875 if (nint(tree->cdr->car->cdr->car) == NODE_BEGIN &&
2876 tree->cdr->car->cdr->cdr == NULL) {
2877 genop_1(s, OP_LOADNIL, cursp());
2878 }
2879 else {
2880 idx = scope_body(s, tree->cdr->car, val);
2881 genop_2(s, OP_EXEC, cursp(), idx);
2882 }
2883 if (val) {
2884 push();
2885 }
2886 }
2887 break;
2888
2889 case NODE_SCLASS:
2890 {
2891 int idx;
2892
2893 codegen(s, tree->car, VAL);
2894 pop();
2895 genop_1(s, OP_SCLASS, cursp());
2896 if (nint(tree->cdr->car->cdr->car) == NODE_BEGIN &&
2897 tree->cdr->car->cdr->cdr == NULL) {
2898 genop_1(s, OP_LOADNIL, cursp());
2899 }
2900 else {
2901 idx = scope_body(s, tree->cdr->car, val);
2902 genop_2(s, OP_EXEC, cursp(), idx);
2903 }
2904 if (val) {
2905 push();
2906 }
2907 }
2908 break;
2909
2910 case NODE_DEF:
2911 {
2912 int sym = new_sym(s, nsym(tree->car));
2913 int idx = lambda_body(s, tree->cdr, 0);
2914
2915 genop_1(s, OP_TCLASS, cursp());
2916 push();
2917 genop_2(s, OP_METHOD, cursp(), idx);
2918 push(); pop();
2919 pop();
2920 genop_2(s, OP_DEF, cursp(), sym);
2921 if (val) {
2922 genop_2(s, OP_LOADSYM, cursp(), sym);
2923 push();
2924 }
2925 }
2926 break;
2927
2928 case NODE_SDEF:
2929 {
2930 node *recv = tree->car;
2931 int sym = new_sym(s, nsym(tree->cdr->car));
2932 int idx = lambda_body(s, tree->cdr->cdr, 0);
2933
2934 codegen(s, recv, VAL);
2935 pop();
2936 genop_1(s, OP_SCLASS, cursp());
2937 push();
2938 genop_2(s, OP_METHOD, cursp(), idx);
2939 pop();
2940 genop_2(s, OP_DEF, cursp(), sym);
2941 if (val) {
2942 genop_2(s, OP_LOADSYM, cursp(), sym);
2943 push();
2944 }
2945 }
2946 break;
2947
2948 case NODE_POSTEXE:
2949 codegen(s, tree, NOVAL);
2950 break;
2951
2952 default:
2953 break;
2954 }
2955 exit:
2956 s->rlev = rlev;
2957}
2958
2959static void
2960scope_add_irep(codegen_scope *s, mrb_irep *irep)
2961{
2962 if (s->irep == NULL) {
2963 s->irep = irep;
2964 return;
2965 }
2966 if (s->irep->rlen == s->rcapa) {
2967 s->rcapa *= 2;
2968 s->irep->reps = (mrb_irep**)codegen_realloc(s, s->irep->reps, sizeof(mrb_irep*)*s->rcapa);
2969 }
2970 s->irep->reps[s->irep->rlen] = irep;
2971 s->irep->rlen++;
2972}
2973
2974static codegen_scope*
2975scope_new(mrb_state *mrb, codegen_scope *prev, node *lv)
2976{
2977 static const codegen_scope codegen_scope_zero = { 0 };
2978 mrb_pool *pool = mrb_pool_open(mrb);
2979 codegen_scope *p = (codegen_scope *)mrb_pool_alloc(pool, sizeof(codegen_scope));
2980
2981 if (!p) {
2982 if (prev)
2983 codegen_error(prev, "unexpected scope");
2984 return NULL;
2985 }
2986 *p = codegen_scope_zero;
2987 p->mrb = mrb;
2988 p->mpool = pool;
2989 if (!prev) return p;
2990 p->prev = prev;
2991 p->ainfo = -1;
2992 p->mscope = 0;
2993
2994 p->irep = mrb_add_irep(mrb);
2995 scope_add_irep(prev, p->irep);
2996
2997 p->rcapa = 8;
2998 p->irep->reps = (mrb_irep**)mrb_malloc(mrb, sizeof(mrb_irep*)*p->rcapa);
2999
3000 p->icapa = 1024;
3001 p->iseq = (mrb_code*)mrb_malloc(mrb, sizeof(mrb_code)*p->icapa);
3002 p->irep->iseq = NULL;
3003
3004 p->pcapa = 32;
3005 p->irep->pool = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value)*p->pcapa);
3006 p->irep->plen = 0;
3007
3008 p->scapa = 256;
3009 p->irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*p->scapa);
3010 p->irep->slen = 0;
3011
3012 p->lv = lv;
3013 p->sp += node_len(lv)+1; /* add self */
3014 p->nlocals = p->sp;
3015 if (lv) {
3016 node *n = lv;
3017 size_t i = 0;
3018
3019 p->irep->lv = (struct mrb_locals*)mrb_malloc(mrb, sizeof(struct mrb_locals) * (p->nlocals - 1));
3020 for (i=0, n=lv; n; i++,n=n->cdr) {
3021 p->irep->lv[i].name = lv_name(n);
3022 if (lv_name(n)) {
3023 p->irep->lv[i].r = lv_idx(p, lv_name(n));
3024 }
3025 else {
3026 p->irep->lv[i].r = 0;
3027 }
3028 }
3029 mrb_assert(i + 1 == p->nlocals);
3030 }
3031 p->ai = mrb_gc_arena_save(mrb);
3032
3033 p->filename_sym = prev->filename_sym;
3034 if (p->filename_sym) {
3035 p->lines = (uint16_t*)mrb_malloc(mrb, sizeof(short)*p->icapa);
3036 }
3037 p->lineno = prev->lineno;
3038
3039 /* debug setting */
3040 p->debug_start_pos = 0;
3041 if (p->filename_sym) {
3042 mrb_debug_info_alloc(mrb, p->irep);
3043 }
3044 else {
3045 p->irep->debug_info = NULL;
3046 }
3047 p->parser = prev->parser;
3048 p->filename_index = prev->filename_index;
3049
3050 p->rlev = prev->rlev+1;
3051
3052 return p;
3053}
3054
3055static void
3056scope_finish(codegen_scope *s)
3057{
3058 mrb_state *mrb = s->mrb;
3059 mrb_irep *irep = s->irep;
3060
3061 if (s->nlocals >= 0x3ff) {
3062 codegen_error(s, "too many local variables");
3063 }
3064 irep->flags = 0;
3065 if (s->iseq) {
3066 irep->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc);
3067 irep->ilen = s->pc;
3068 }
3069 irep->pool = (mrb_value*)codegen_realloc(s, irep->pool, sizeof(mrb_value)*irep->plen);
3070 irep->syms = (mrb_sym*)codegen_realloc(s, irep->syms, sizeof(mrb_sym)*irep->slen);
3071 irep->reps = (mrb_irep**)codegen_realloc(s, irep->reps, sizeof(mrb_irep*)*irep->rlen);
3072 if (s->filename_sym) {
3073 mrb_sym fname = mrb_parser_get_filename(s->parser, s->filename_index);
3074 const char *filename = mrb_sym_name_len(s->mrb, fname, NULL);
3075
3076 mrb_debug_info_append_file(s->mrb, s->irep->debug_info,
3077 filename, s->lines, s->debug_start_pos, s->pc);
3078 }
3079 mrb_free(s->mrb, s->lines);
3080
3081 irep->nlocals = s->nlocals;
3082 irep->nregs = s->nregs;
3083
3084 mrb_gc_arena_restore(mrb, s->ai);
3085 mrb_pool_close(s->mpool);
3086}
3087
3088static struct loopinfo*
3089loop_push(codegen_scope *s, enum looptype t)
3090{
3091 struct loopinfo *p = (struct loopinfo *)codegen_palloc(s, sizeof(struct loopinfo));
3092
3093 p->type = t;
3094 p->pc0 = p->pc1 = p->pc2 = p->pc3 = 0;
3095 p->prev = s->loop;
3096 p->ensure_level = s->ensure_level;
3097 p->acc = cursp();
3098 s->loop = p;
3099
3100 return p;
3101}
3102
3103static void
3104loop_break(codegen_scope *s, node *tree)
3105{
3106 if (!s->loop) {
3107 codegen(s, tree, NOVAL);
3108 raise_error(s, "unexpected break");
3109 }
3110 else {
3111 struct loopinfo *loop;
3112 int n = 0;
3113
3114 if (tree) {
3115 gen_retval(s, tree);
3116 }
3117
3118 loop = s->loop;
3119 while (loop) {
3120 if (loop->type == LOOP_BEGIN) {
3121 n++;
3122 loop = loop->prev;
3123 }
3124 else if (loop->type == LOOP_RESCUE) {
3125 loop = loop->prev;
3126 }
3127 else{
3128 break;
3129 }
3130 }
3131 if (!loop) {
3132 raise_error(s, "unexpected break");
3133 return;
3134 }
3135 if (n > 0) {
3136 genop_1(s, OP_POPERR, n);
3137 }
3138
3139 if (loop->type == LOOP_NORMAL) {
3140 int tmp;
3141
3142 if (s->ensure_level > s->loop->ensure_level) {
3143 genop_1(s, OP_EPOP, s->ensure_level - s->loop->ensure_level);
3144 }
3145 if (tree) {
3146 gen_move(s, loop->acc, cursp(), 0);
3147 }
3148 tmp = genjmp(s, OP_JMP, loop->pc3);
3149 loop->pc3 = tmp;
3150 }
3151 else {
3152 if (!tree) {
3153 genop_1(s, OP_LOADNIL, cursp());
3154 }
3155 gen_return(s, OP_BREAK, cursp());
3156 }
3157 }
3158}
3159
3160static void
3161loop_pop(codegen_scope *s, int val)
3162{
3163 if (val) {
3164 genop_1(s, OP_LOADNIL, cursp());
3165 }
3166 dispatch_linked(s, s->loop->pc3);
3167 s->loop = s->loop->prev;
3168 if (val) push();
3169}
3170
3171static struct RProc*
3172generate_code(mrb_state *mrb, parser_state *p, int val)
3173{
3174 codegen_scope *scope = scope_new(mrb, 0, 0);
3175 struct RProc *proc;
3176 struct mrb_jmpbuf *prev_jmp = mrb->jmp;
3177
3178 scope->mrb = mrb;
3179 scope->parser = p;
3180 scope->filename_sym = p->filename_sym;
3181 scope->filename_index = p->current_filename_index;
3182
3183 MRB_TRY(&scope->jmp) {
3184 mrb->jmp = &scope->jmp;
3185 /* prepare irep */
3186 codegen(scope, p->tree, val);
3187 proc = mrb_proc_new(mrb, scope->irep);
3188 mrb_irep_decref(mrb, scope->irep);
3189 mrb_pool_close(scope->mpool);
3190 proc->c = NULL;
3191 if (mrb->c->cibase && mrb->c->cibase->proc == proc->upper) {
3192 proc->upper = NULL;
3193 }
3194 mrb->jmp = prev_jmp;
3195 return proc;
3196 }
3197 MRB_CATCH(&scope->jmp) {
3198 mrb_irep_decref(mrb, scope->irep);
3199 mrb_pool_close(scope->mpool);
3200 mrb->jmp = prev_jmp;
3201 return NULL;
3202 }
3203 MRB_END_EXC(&scope->jmp);
3204}
3205
3206MRB_API struct RProc*
3207mrb_generate_code(mrb_state *mrb, parser_state *p)
3208{
3209 return generate_code(mrb, p, VAL);
3210}
3211
3212void
3213mrb_irep_remove_lv(mrb_state *mrb, mrb_irep *irep)
3214{
3215 int i;
3216
3217 if (irep->lv) {
3218 mrb_free(mrb, irep->lv);
3219 irep->lv = NULL;
3220 }
3221
3222 for (i = 0; i < irep->rlen; ++i) {
3223 mrb_irep_remove_lv(mrb, irep->reps[i]);
3224 }
3225}
3226
3227#undef OPCODE
3228#define Z 1
3229#define S 3
3230#define W 4
3231/* instruction sizes */
3232uint8_t mrb_insn_size[] = {
3233#define B 2
3234#define BB 3
3235#define BBB 4
3236#define BS 4
3237#define SB 4
3238#define OPCODE(_,x) x,
3239#include "mruby/ops.h"
3240#undef OPCODE
3241#undef B
3242#undef BB
3243#undef BS
3244#undef SB
3245#undef BBB
3246};
3247/* EXT1 instruction sizes */
3248uint8_t mrb_insn_size1[] = {
3249#define B 3
3250#define BB 4
3251#define BBB 5
3252#define BS 5
3253#define SB 5
3254#define OPCODE(_,x) x,
3255#include "mruby/ops.h"
3256#undef OPCODE
3257#undef B
3258};
3259/* EXT2 instruction sizes */
3260uint8_t mrb_insn_size2[] = {
3261#define B 2
3262#define OPCODE(_,x) x,
3263#include "mruby/ops.h"
3264#undef OPCODE
3265#undef BB
3266#undef BBB
3267#undef BS
3268#undef SB
3269};
3270/* EXT3 instruction sizes */
3271#define BB 5
3272#define BBB 6
3273#define BS 4
3274#define SB 5
3275uint8_t mrb_insn_size3[] = {
3276#define OPCODE(_,x) x,
3277#include "mruby/ops.h"
3278};
Note: See TracBrowser for help on using the repository browser.