Merge pull request #1875 from akuroda/pr_nil_test
[mruby.git] / src / codegen.c
blob60da17f2b5c5d05b8f480810bd3f5f02168a1079
1 /*
2 ** codegen.c - mruby code generator
3 **
4 ** See Copyright Notice in mruby.h
5 */
7 #include <ctype.h>
8 #include <limits.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include "mruby.h"
12 #include "mruby/compile.h"
13 #include "mruby/proc.h"
14 #include "mruby/numeric.h"
15 #include "mruby/string.h"
16 #include "mruby/debug.h"
17 #include "node.h"
18 #include "opcode.h"
19 #include "re.h"
20 #include "mrb_throw.h"
22 typedef mrb_ast_node node;
23 typedef struct mrb_parser_state parser_state;
25 enum looptype {
26 LOOP_NORMAL,
27 LOOP_BLOCK,
28 LOOP_FOR,
29 LOOP_BEGIN,
30 LOOP_RESCUE,
33 struct loopinfo {
34 enum looptype type;
35 int pc1, pc2, pc3, acc;
36 int ensure_level;
37 struct loopinfo *prev;
40 typedef struct scope {
41 mrb_state *mrb;
42 mrb_pool *mpool;
43 struct mrb_jmpbuf jmp;
45 struct scope *prev;
47 node *lv;
49 int sp;
50 int pc;
51 int lastlabel;
52 int ainfo:15;
53 mrb_bool mscope:1;
55 struct loopinfo *loop;
56 int ensure_level;
57 char const *filename;
58 uint16_t lineno;
60 mrb_code *iseq;
61 uint16_t *lines;
62 int icapa;
64 mrb_irep *irep;
65 size_t pcapa;
66 size_t scapa;
67 size_t rcapa;
69 int nlocals;
70 int nregs;
71 int ai;
73 int debug_start_pos;
74 uint16_t filename_index;
75 parser_state* parser;
76 } codegen_scope;
78 static codegen_scope* scope_new(mrb_state *mrb, codegen_scope *prev, node *lv);
79 static void scope_finish(codegen_scope *s);
80 static struct loopinfo *loop_push(codegen_scope *s, enum looptype t);
81 static void loop_break(codegen_scope *s, node *tree);
82 static void loop_pop(codegen_scope *s, int val);
84 static void gen_assignment(codegen_scope *s, node *node, int sp, int val);
85 static void gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val);
87 static void codegen(codegen_scope *s, node *tree, int val);
89 static void
90 codegen_error(codegen_scope *s, const char *message)
92 if (!s) return;
93 while (s->prev) {
94 codegen_scope *tmp = s->prev;
95 mrb_pool_close(s->mpool);
96 s = tmp;
98 #ifdef ENABLE_STDIO
99 if (s->filename && s->lineno) {
100 fprintf(stderr, "codegen error:%s:%d: %s\n", s->filename, s->lineno, message);
102 else {
103 fprintf(stderr, "codegen error: %s\n", message);
105 #endif
106 MRB_THROW(&s->jmp);
109 static void*
110 codegen_palloc(codegen_scope *s, size_t len)
112 void *p = mrb_pool_alloc(s->mpool, len);
114 if (!p) codegen_error(s, "pool memory allocation");
115 return p;
118 static void*
119 codegen_malloc(codegen_scope *s, size_t len)
121 void *p = mrb_malloc_simple(s->mrb, len);
123 if (!p) codegen_error(s, "mrb_malloc");
124 return p;
127 static void*
128 codegen_realloc(codegen_scope *s, void *p, size_t len)
130 p = mrb_realloc_simple(s->mrb, p, len);
132 if (!p && len > 0) codegen_error(s, "mrb_realloc");
133 return p;
136 static int
137 new_label(codegen_scope *s)
139 s->lastlabel = s->pc;
140 return s->pc;
143 static inline int
144 genop(codegen_scope *s, mrb_code i)
146 if (s->pc == s->icapa) {
147 s->icapa *= 2;
148 s->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->icapa);
149 if (s->lines) {
150 s->lines = (uint16_t*)codegen_realloc(s, s->lines, sizeof(short)*s->icapa);
151 s->irep->lines = s->lines;
154 s->iseq[s->pc] = i;
155 if (s->lines) {
156 s->lines[s->pc] = s->lineno;
158 return s->pc++;
161 #define NOVAL 0
162 #define VAL 1
164 static int
165 genop_peep(codegen_scope *s, mrb_code i, int val)
167 /* peephole optimization */
168 if (s->lastlabel != s->pc && s->pc > 0) {
169 mrb_code i0 = s->iseq[s->pc-1];
170 int c1 = GET_OPCODE(i);
171 int c0 = GET_OPCODE(i0);
173 switch (c1) {
174 case OP_MOVE:
175 if (GETARG_A(i) == GETARG_B(i)) {
176 /* skip useless OP_MOVE */
177 return 0;
179 if (val) break;
180 switch (c0) {
181 case OP_MOVE:
182 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i) == GETARG_B(i0) && GETARG_A(i) >= s->nlocals) {
183 /* skip swapping OP_MOVE */
184 return 0;
186 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
187 s->iseq[s->pc-1] = MKOP_AB(OP_MOVE, GETARG_A(i), GETARG_B(i0));
188 return 0;
190 break;
191 case OP_LOADI:
192 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
193 s->iseq[s->pc-1] = MKOP_AsBx(OP_LOADI, GETARG_A(i), GETARG_sBx(i0));
194 return 0;
196 break;
197 case OP_ARRAY:
198 case OP_HASH:
199 case OP_RANGE:
200 case OP_AREF:
201 case OP_GETUPVAR:
202 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
203 s->iseq[s->pc-1] = MKOP_ABC(c0, GETARG_A(i), GETARG_B(i0), GETARG_C(i0));
204 return 0;
206 break;
207 case OP_LOADSYM:
208 case OP_GETGLOBAL:
209 case OP_GETIV:
210 case OP_GETCV:
211 case OP_GETCONST:
212 case OP_GETSPECIAL:
213 case OP_LOADL:
214 case OP_STRING:
215 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
216 s->iseq[s->pc-1] = MKOP_ABx(c0, GETARG_A(i), GETARG_Bx(i0));
217 return 0;
219 break;
220 case OP_SCLASS:
221 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
222 s->iseq[s->pc-1] = MKOP_AB(c0, GETARG_A(i), GETARG_B(i0));
223 return 0;
225 break;
226 case OP_LOADNIL:
227 case OP_LOADSELF:
228 case OP_LOADT:
229 case OP_LOADF:
230 case OP_OCLASS:
231 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
232 s->iseq[s->pc-1] = MKOP_A(c0, GETARG_A(i));
233 return 0;
235 break;
236 default:
237 break;
239 break;
240 case OP_SETIV:
241 case OP_SETCV:
242 case OP_SETCONST:
243 case OP_SETMCNST:
244 case OP_SETGLOBAL:
245 if (val) break;
246 if (c0 == OP_MOVE) {
247 if (GETARG_A(i) == GETARG_A(i0)) {
248 s->iseq[s->pc-1] = MKOP_ABx(c1, GETARG_B(i0), GETARG_Bx(i));
249 return 0;
252 break;
253 case OP_SETUPVAR:
254 if (val) break;
255 if (c0 == OP_MOVE) {
256 if (GETARG_A(i) == GETARG_A(i0)) {
257 s->iseq[s->pc-1] = MKOP_ABC(c1, GETARG_B(i0), GETARG_B(i), GETARG_C(i));
258 return 0;
261 break;
262 case OP_EPOP:
263 if (c0 == OP_EPOP) {
264 s->iseq[s->pc-1] = MKOP_A(OP_EPOP, GETARG_A(i0)+GETARG_A(i));
265 return 0;
267 break;
268 case OP_POPERR:
269 if (c0 == OP_POPERR) {
270 s->iseq[s->pc-1] = MKOP_A(OP_POPERR, GETARG_A(i0)+GETARG_A(i));
271 return 0;
273 break;
274 case OP_RETURN:
275 switch (c0) {
276 case OP_RETURN:
277 return 0;
278 case OP_MOVE:
279 s->iseq[s->pc-1] = MKOP_AB(OP_RETURN, GETARG_B(i0), OP_R_NORMAL);
280 return 0;
281 case OP_SETIV:
282 case OP_SETCV:
283 case OP_SETCONST:
284 case OP_SETMCNST:
285 case OP_SETUPVAR:
286 case OP_SETGLOBAL:
287 s->pc--;
288 genop_peep(s, i0, NOVAL);
289 i0 = s->iseq[s->pc-1];
290 return genop(s, MKOP_AB(OP_RETURN, GETARG_A(i0), OP_R_NORMAL));
291 #if 0
292 case OP_SEND:
293 if (GETARG_B(i) == OP_R_NORMAL && GETARG_A(i) == GETARG_A(i0)) {
294 s->iseq[s->pc-1] = MKOP_ABC(OP_TAILCALL, GETARG_A(i0), GETARG_B(i0), GETARG_C(i0));
295 return;
297 break;
298 #endif
299 default:
300 break;
302 break;
303 case OP_ADD:
304 case OP_SUB:
305 if (c0 == OP_LOADI) {
306 int c = GETARG_sBx(i0);
308 if (c1 == OP_SUB) c = -c;
309 if (c > 127 || c < -127) break;
310 if (0 <= c)
311 s->iseq[s->pc-1] = MKOP_ABC(OP_ADDI, GETARG_A(i), GETARG_B(i), c);
312 else
313 s->iseq[s->pc-1] = MKOP_ABC(OP_SUBI, GETARG_A(i), GETARG_B(i), -c);
314 return 0;
316 case OP_STRCAT:
317 if (c0 == OP_STRING) {
318 int i = GETARG_Bx(i0);
320 if (mrb_type(s->irep->pool[i]) == MRB_TT_STRING &&
321 RSTRING_LEN(s->irep->pool[i]) == 0) {
322 s->pc--;
323 return 0;
326 break;
327 case OP_JMPIF:
328 case OP_JMPNOT:
329 if (c0 == OP_MOVE && GETARG_A(i) == GETARG_A(i0)) {
330 s->iseq[s->pc-1] = MKOP_AsBx(c1, GETARG_B(i0), GETARG_sBx(i));
331 return s->pc-1;
333 break;
334 default:
335 break;
338 return genop(s, i);
341 static void
342 scope_error(codegen_scope *s)
344 exit(EXIT_FAILURE);
347 static inline void
348 dispatch(codegen_scope *s, int pc)
350 int diff = s->pc - pc;
351 mrb_code i = s->iseq[pc];
352 int c = GET_OPCODE(i);
354 s->lastlabel = s->pc;
355 switch (c) {
356 case OP_JMP:
357 case OP_JMPIF:
358 case OP_JMPNOT:
359 case OP_ONERR:
360 break;
361 default:
362 #ifdef ENABLE_STDIO
363 fprintf(stderr, "bug: dispatch on non JMP op\n");
364 #endif
365 scope_error(s);
366 break;
368 s->iseq[pc] = MKOP_AsBx(c, GETARG_A(i), diff);
371 static void
372 dispatch_linked(codegen_scope *s, int pc)
374 mrb_code i;
375 int pos;
377 if (!pc) return;
378 for (;;) {
379 i = s->iseq[pc];
380 pos = GETARG_sBx(i);
381 dispatch(s, pc);
382 if (!pos) break;
383 pc = pos;
387 #define nregs_update do {if (s->sp > s->nregs) s->nregs = s->sp;} while (0)
388 static void
389 push_(codegen_scope *s)
391 if (s->sp > 511) {
392 codegen_error(s, "too complex expression");
394 s->sp++;
395 nregs_update;
398 #define push() push_(s)
399 #define pop_(s) ((s)->sp--)
400 #define pop() pop_(s)
401 #define pop_n(n) (s->sp-=(n))
402 #define cursp() (s->sp)
404 static inline int
405 new_lit(codegen_scope *s, mrb_value val)
407 size_t i;
408 mrb_value *pv;
410 switch (mrb_type(val)) {
411 case MRB_TT_STRING:
412 for (i=0; i<s->irep->plen; i++) {
413 mrb_int len;
414 pv = &s->irep->pool[i];
416 if (mrb_type(*pv) != MRB_TT_STRING) continue;
417 if ((len = RSTRING_LEN(*pv)) != RSTRING_LEN(val)) continue;
418 if (memcmp(RSTRING_PTR(*pv), RSTRING_PTR(val), len) == 0)
419 return i;
421 break;
422 case MRB_TT_FLOAT:
423 for (i=0; i<s->irep->plen; i++) {
424 pv = &s->irep->pool[i];
425 if (mrb_type(*pv) != MRB_TT_FLOAT) continue;
426 if (mrb_float(*pv) == mrb_float(val)) return i;
428 break;
429 case MRB_TT_FIXNUM:
430 for (i=0; i<s->irep->plen; i++) {
431 pv = &s->irep->pool[i];
432 if (!mrb_fixnum_p(*pv)) continue;
433 if (mrb_fixnum(*pv) == mrb_fixnum(val)) return i;
435 break;
436 default:
437 /* should not happen */
438 return 0;
441 if (s->irep->plen == s->pcapa) {
442 s->pcapa *= 2;
443 s->irep->pool = (mrb_value *)codegen_realloc(s, s->irep->pool, sizeof(mrb_value)*s->pcapa);
446 pv = &s->irep->pool[s->irep->plen];
447 i = s->irep->plen++;
449 switch (mrb_type(val)) {
450 case MRB_TT_STRING:
451 *pv = mrb_str_pool(s->mrb, val);
452 break;
454 case MRB_TT_FLOAT:
455 #ifdef MRB_WORD_BOXING
456 *pv = mrb_float_pool(s->mrb, mrb_float(val));
457 break;
458 #endif
459 case MRB_TT_FIXNUM:
460 *pv = val;
461 break;
463 default:
464 /* should not happen */
465 break;
467 return i;
470 static inline int
471 new_msym(codegen_scope *s, mrb_sym sym)
473 size_t i, len;
475 len = s->irep->slen;
476 if (len > 256) len = 256;
477 for (i=0; i<len; i++) {
478 if (s->irep->syms[i] == sym) return i;
479 if (s->irep->syms[i] == 0) break;
481 if (i == 256) {
482 codegen_error(s, "too many symbols (max 256)");
484 s->irep->syms[i] = sym;
485 if (i == s->irep->slen) s->irep->slen++;
486 return i;
489 static inline int
490 new_sym(codegen_scope *s, mrb_sym sym)
492 size_t i;
494 for (i=0; i<s->irep->slen; i++) {
495 if (s->irep->syms[i] == sym) return i;
497 if (s->irep->slen > 125 && s->irep->slen < 256) {
498 s->irep->syms = (mrb_sym *)codegen_realloc(s, s->irep->syms, sizeof(mrb_sym)*65536);
499 for (i = 0; i < 256 - s->irep->slen; i++) {
500 static const mrb_sym mrb_sym_zero = { 0 };
501 s->irep->syms[i + s->irep->slen] = mrb_sym_zero;
503 s->irep->slen = 256;
505 s->irep->syms[s->irep->slen] = sym;
506 return s->irep->slen++;
509 static int
510 node_len(node *tree)
512 int n = 0;
514 while (tree) {
515 n++;
516 tree = tree->cdr;
518 return n;
521 #define sym(x) ((mrb_sym)(intptr_t)(x))
522 #define lv_name(lv) sym((lv)->car)
523 static int
524 lv_idx(codegen_scope *s, mrb_sym id)
526 node *lv = s->lv;
527 int n = 1;
529 while (lv) {
530 if (lv_name(lv) == id) return n;
531 n++;
532 lv = lv->cdr;
534 return 0;
537 static void
538 for_body(codegen_scope *s, node *tree)
540 codegen_scope *prev = s;
541 int idx;
542 struct loopinfo *lp;
543 node *n2;
544 mrb_code c;
546 /* generate receiver */
547 codegen(s, tree->cdr->car, VAL);
548 /* generate loop-block */
549 s = scope_new(s->mrb, s, tree->car);
551 lp = loop_push(s, LOOP_FOR);
552 lp->pc1 = new_label(s);
554 /* generate loop variable */
555 n2 = tree->car;
556 if (n2->car && !n2->car->cdr && !n2->cdr) {
557 genop(s, MKOP_Ax(OP_ENTER, 0x40000));
558 gen_assignment(s, n2->car->car, 1, NOVAL);
560 else {
561 genop(s, MKOP_Ax(OP_ENTER, 0x40000));
562 gen_vmassignment(s, n2, 1, VAL);
564 codegen(s, tree->cdr->cdr->car, VAL);
565 pop();
566 if (s->pc > 0) {
567 c = s->iseq[s->pc-1];
568 if (GET_OPCODE(c) != OP_RETURN || GETARG_B(c) != OP_R_NORMAL || s->pc == s->lastlabel)
569 genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
571 loop_pop(s, NOVAL);
572 scope_finish(s);
573 s = prev;
574 genop(s, MKOP_Abc(OP_LAMBDA, cursp(), s->irep->rlen-1, OP_L_BLOCK));
575 pop();
576 idx = new_msym(s, mrb_intern_lit(s->mrb, "each"));
577 genop(s, MKOP_ABC(OP_SENDB, cursp(), idx, 0));
580 static int
581 lambda_body(codegen_scope *s, node *tree, int blk)
583 mrb_code c;
584 codegen_scope *parent = s;
585 s = scope_new(s->mrb, s, tree->car);
586 s->mscope = !blk;
588 if (blk) {
589 struct loopinfo *lp = loop_push(s, LOOP_BLOCK);
590 lp->pc1 = new_label(s);
592 tree = tree->cdr;
593 if (tree->car) {
594 mrb_aspec a;
595 int ma, oa, ra, pa, ka, kd, ba;
596 int pos, i;
597 node *n, *opt;
599 ma = node_len(tree->car->car);
600 n = tree->car->car;
601 while (n) {
602 n = n->cdr;
604 oa = node_len(tree->car->cdr->car);
605 ra = tree->car->cdr->cdr->car ? 1 : 0;
606 pa = node_len(tree->car->cdr->cdr->cdr->car);
607 ka = kd = 0;
608 ba = tree->car->cdr->cdr->cdr->cdr ? 1 : 0;
610 a = ((mrb_aspec)(ma & 0x1f) << 18)
611 | ((mrb_aspec)(oa & 0x1f) << 13)
612 | ((ra & 1) << 12)
613 | ((pa & 0x1f) << 7)
614 | ((ka & 0x1f) << 2)
615 | ((kd & 1)<< 1)
616 | (ba & 1);
617 s->ainfo = (((ma+oa) & 0x3f) << 6) /* (12bits = 6:1:5) */
618 | ((ra & 1) << 5)
619 | (pa & 0x1f);
620 genop(s, MKOP_Ax(OP_ENTER, a));
621 pos = new_label(s);
622 for (i=0; i<oa; i++) {
623 new_label(s);
624 genop(s, MKOP_sBx(OP_JMP, 0));
626 if (oa > 0) {
627 genop(s, MKOP_sBx(OP_JMP, 0));
629 opt = tree->car->cdr->car;
630 i = 0;
631 while (opt) {
632 int idx;
634 dispatch(s, pos+i);
635 codegen(s, opt->car->cdr, VAL);
636 idx = lv_idx(s, (mrb_sym)(intptr_t)opt->car->car);
637 pop();
638 genop_peep(s, MKOP_AB(OP_MOVE, idx, cursp()), NOVAL);
639 i++;
640 opt = opt->cdr;
642 if (oa > 0) {
643 dispatch(s, pos+i);
646 codegen(s, tree->cdr->car, VAL);
647 pop();
648 if (s->pc > 0) {
649 c = s->iseq[s->pc-1];
650 if (GET_OPCODE(c) != OP_RETURN || GETARG_B(c) != OP_R_NORMAL || s->pc == s->lastlabel) {
651 if (s->nregs == 0) {
652 genop(s, MKOP_A(OP_LOADNIL, 0));
653 genop(s, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
655 else {
656 genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
660 if (blk) {
661 loop_pop(s, NOVAL);
663 scope_finish(s);
664 return parent->irep->rlen - 1;
667 static int
668 scope_body(codegen_scope *s, node *tree, int val)
670 codegen_scope *scope = scope_new(s->mrb, s, tree->car);
672 codegen(scope, tree->cdr, VAL);
673 if (!s->iseq) {
674 genop(scope, MKOP_A(OP_STOP, 0));
676 else if (!val) {
677 genop(scope, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
679 else {
680 if (scope->nregs == 0) {
681 genop(scope, MKOP_A(OP_LOADNIL, 0));
682 genop(scope, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
684 else {
685 genop_peep(scope, MKOP_AB(OP_RETURN, scope->sp-1, OP_R_NORMAL), NOVAL);
688 scope_finish(scope);
689 if (!s->irep) {
690 /* should not happen */
691 return 0;
693 return s->irep->rlen - 1;
696 static mrb_bool
697 nosplat(node *t)
699 while (t) {
700 if ((intptr_t)t->car->car == NODE_SPLAT) return FALSE;
701 t = t->cdr;
703 return TRUE;
706 static mrb_sym
707 attrsym(codegen_scope *s, mrb_sym a)
709 const char *name;
710 mrb_int len;
711 char *name2;
713 name = mrb_sym2name_len(s->mrb, a, &len);
714 name2 = (char *)codegen_palloc(s,
715 (size_t)len
716 + 1 /* '=' */
717 + 1 /* '\0' */
719 memcpy(name2, name, (size_t)len);
720 name2[len] = '=';
721 name2[len+1] = '\0';
723 return mrb_intern(s->mrb, name2, len+1);
726 static int
727 gen_values(codegen_scope *s, node *t, int val)
729 int n = 0;
730 int is_splat;
732 while (t) {
733 is_splat = (intptr_t)t->car->car == NODE_SPLAT; /* splat mode */
734 if (n >= 127 || is_splat) {
735 if (val) {
736 pop_n(n);
737 genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), n));
738 push();
739 codegen(s, t->car, VAL);
740 pop(); pop();
741 if (is_splat) {
742 genop(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1));
744 else {
745 genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
747 t = t->cdr;
748 while (t) {
749 push();
750 codegen(s, t->car, VAL);
751 pop(); pop();
752 if ((intptr_t)t->car->car == NODE_SPLAT) {
753 genop(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1));
755 else {
756 genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
758 t = t->cdr;
761 else {
762 codegen(s, t->car->cdr, NOVAL);
763 t = t->cdr;
764 while (t) {
765 codegen(s, t->car, NOVAL);
766 t = t->cdr;
769 return -1;
771 /* normal (no splat) mode */
772 codegen(s, t->car, val);
773 n++;
774 t = t->cdr;
776 return n;
779 #define CALL_MAXARGS 127
781 static void
782 gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val)
784 mrb_sym sym = name ? name : sym(tree->cdr->car);
785 int idx;
786 int n = 0, noop = 0, sendv = 0, blk = 0;
788 codegen(s, tree->car, VAL); /* receiver */
789 idx = new_msym(s, sym);
790 tree = tree->cdr->cdr->car;
791 if (tree) {
792 n = gen_values(s, tree->car, VAL);
793 if (n < 0) {
794 n = noop = sendv = 1;
795 push();
798 if (sp) {
799 if (sendv) {
800 pop();
801 genop(s, MKOP_AB(OP_ARYPUSH, cursp(), sp));
802 push();
804 else {
805 genop(s, MKOP_AB(OP_MOVE, cursp(), sp));
806 push();
807 n++;
810 if (tree && tree->cdr) {
811 noop = 1;
812 codegen(s, tree->cdr, VAL);
813 pop();
815 else {
816 blk = cursp();
818 pop_n(n+1);
820 mrb_int len;
821 const char *name = mrb_sym2name_len(s->mrb, sym, &len);
823 if (!noop && len == 1 && name[0] == '+') {
824 genop_peep(s, MKOP_ABC(OP_ADD, cursp(), idx, n), val);
826 else if (!noop && len == 1 && name[0] == '-') {
827 genop_peep(s, MKOP_ABC(OP_SUB, cursp(), idx, n), val);
829 else if (!noop && len == 1 && name[0] == '*') {
830 genop(s, MKOP_ABC(OP_MUL, cursp(), idx, n));
832 else if (!noop && len == 1 && name[0] == '/') {
833 genop(s, MKOP_ABC(OP_DIV, cursp(), idx, n));
835 else if (!noop && len == 1 && name[0] == '<') {
836 genop(s, MKOP_ABC(OP_LT, cursp(), idx, n));
838 else if (!noop && len == 2 && name[0] == '<' && name[1] == '=') {
839 genop(s, MKOP_ABC(OP_LE, cursp(), idx, n));
841 else if (!noop && len == 1 && name[0] == '>') {
842 genop(s, MKOP_ABC(OP_GT, cursp(), idx, n));
844 else if (!noop && len == 2 && name[0] == '>' && name[1] == '=') {
845 genop(s, MKOP_ABC(OP_GE, cursp(), idx, n));
847 else if (!noop && len == 2 && name[0] == '=' && name[1] == '=') {
848 genop(s, MKOP_ABC(OP_EQ, cursp(), idx, n));
850 else {
851 if (sendv) n = CALL_MAXARGS;
852 if (blk > 0) { /* no block */
853 genop(s, MKOP_ABC(OP_SEND, cursp(), idx, n));
855 else {
856 genop(s, MKOP_ABC(OP_SENDB, cursp(), idx, n));
860 if (val) {
861 push();
865 static void
866 gen_assignment(codegen_scope *s, node *node, int sp, int val)
868 int idx;
869 int type = (intptr_t)node->car;
871 node = node->cdr;
872 switch ((intptr_t)type) {
873 case NODE_GVAR:
874 idx = new_sym(s, sym(node));
875 genop_peep(s, MKOP_ABx(OP_SETGLOBAL, sp, idx), val);
876 break;
877 case NODE_LVAR:
878 idx = lv_idx(s, sym(node));
879 if (idx > 0) {
880 if (idx != sp) {
881 genop_peep(s, MKOP_AB(OP_MOVE, idx, sp), val);
883 break;
885 else { /* upvar */
886 int lv = 0;
887 codegen_scope *up = s->prev;
889 while (up) {
890 idx = lv_idx(up, sym(node));
891 if (idx > 0) {
892 genop_peep(s, MKOP_ABC(OP_SETUPVAR, sp, idx, lv), val);
893 break;
895 lv++;
896 up = up->prev;
899 break;
900 case NODE_IVAR:
901 idx = new_sym(s, sym(node));
902 genop_peep(s, MKOP_ABx(OP_SETIV, sp, idx), val);
903 break;
904 case NODE_CVAR:
905 idx = new_sym(s, sym(node));
906 genop_peep(s, MKOP_ABx(OP_SETCV, sp, idx), val);
907 break;
908 case NODE_CONST:
909 idx = new_sym(s, sym(node));
910 genop_peep(s, MKOP_ABx(OP_SETCONST, sp, idx), val);
911 break;
912 case NODE_COLON2:
913 idx = new_sym(s, sym(node->cdr));
914 genop_peep(s, MKOP_AB(OP_MOVE, cursp(), sp), NOVAL);
915 push();
916 codegen(s, node->car, VAL);
917 pop_n(2);
918 genop_peep(s, MKOP_ABx(OP_SETMCNST, cursp(), idx), val);
919 break;
921 case NODE_CALL:
922 push();
923 gen_call(s, node, attrsym(s, sym(node->cdr->car)), sp, NOVAL);
924 pop();
925 if (val) {
926 genop_peep(s, MKOP_AB(OP_MOVE, cursp(), sp), val);
928 break;
930 default:
931 #ifdef ENABLE_STDIO
932 printf("unknown lhs %d\n", type);
933 #endif
934 break;
936 if (val) push();
939 static void
940 gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val)
942 int n = 0, post = 0;
943 node *t, *p;
945 if (tree->car) { /* pre */
946 t = tree->car;
947 n = 0;
948 while (t) {
949 genop(s, MKOP_ABC(OP_AREF, cursp(), rhs, n));
950 gen_assignment(s, t->car, cursp(), NOVAL);
951 n++;
952 t = t->cdr;
955 t = tree->cdr;
956 if (t) {
957 if (t->cdr) { /* post count */
958 p = t->cdr->car;
959 while (p) {
960 post++;
961 p = p->cdr;
964 if (val) {
965 genop(s, MKOP_AB(OP_MOVE, cursp(), rhs));
966 push();
968 pop();
969 genop(s, MKOP_ABC(OP_APOST, cursp(), n, post));
970 n = 1;
971 if (t->car) { /* rest */
972 gen_assignment(s, t->car, cursp(), NOVAL);
974 if (t->cdr && t->cdr->car) {
975 t = t->cdr->car;
976 while (t) {
977 gen_assignment(s, t->car, cursp()+n, NOVAL);
978 t = t->cdr;
979 n++;
983 else {
984 pop();
988 static void
989 gen_send_intern(codegen_scope *s)
991 pop();
992 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "intern")), 0));
993 push();
995 static void
996 gen_literal_array(codegen_scope *s, node *tree, mrb_bool sym, int val)
998 if (val) {
999 int i = 0, j = 0;
1001 while (tree) {
1002 switch ((intptr_t)tree->car->car) {
1003 case NODE_STR:
1004 if ((tree->cdr == NULL) && ((intptr_t)tree->car->cdr->cdr == 0))
1005 break;
1006 /* fall through */
1007 case NODE_BEGIN:
1008 codegen(s, tree->car, VAL);
1009 ++j;
1010 break;
1012 case NODE_LITERAL_DELIM:
1013 if (j > 0) {
1014 j = 0;
1015 ++i;
1016 if (sym)
1017 gen_send_intern(s);
1019 break;
1021 if (j >= 2) {
1022 pop(); pop();
1023 genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
1024 push();
1025 j = 1;
1027 tree = tree->cdr;
1029 if (j > 0) {
1030 ++i;
1031 if (sym)
1032 gen_send_intern(s);
1034 pop_n(i);
1035 genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), i));
1036 push();
1038 else {
1039 while (tree) {
1040 switch ((intptr_t)tree->car->car) {
1041 case NODE_BEGIN: case NODE_BLOCK:
1042 codegen(s, tree->car, NOVAL);
1044 tree = tree->cdr;
1049 static void
1050 raise_error(codegen_scope *s, const char *msg)
1052 int idx = new_lit(s, mrb_str_new_cstr(s->mrb, msg));
1054 genop(s, MKOP_ABx(OP_ERR, 1, idx));
1057 static double
1058 readint_float(codegen_scope *s, const char *p, int base)
1060 const char *e = p + strlen(p);
1061 double f = 0;
1062 int n;
1064 if (*p == '+') p++;
1065 while (p < e) {
1066 char c = *p;
1067 c = tolower((unsigned char)c);
1068 for (n=0; n<base; n++) {
1069 if (mrb_digitmap[n] == c) {
1070 f *= base;
1071 f += n;
1072 break;
1075 if (n == base) {
1076 codegen_error(s, "malformed readint input");
1078 p++;
1080 return f;
1083 static mrb_int
1084 readint_mrb_int(codegen_scope *s, const char *p, int base, mrb_bool neg, mrb_bool *overflow)
1086 const char *e = p + strlen(p);
1087 mrb_int result = 0;
1088 int n;
1090 if (*p == '+') p++;
1091 while (p < e) {
1092 char c = *p;
1093 c = tolower((unsigned char)c);
1094 for (n=0; n<base; n++) {
1095 if (mrb_digitmap[n] == c) {
1096 break;
1099 if (n == base) {
1100 codegen_error(s, "malformed readint input");
1103 if (neg) {
1104 if ((MRB_INT_MIN + n)/base > result) {
1105 *overflow = TRUE;
1106 return 0;
1108 result *= base;
1109 result -= n;
1111 else {
1112 if ((MRB_INT_MAX - n)/base < result) {
1113 *overflow = TRUE;
1114 return 0;
1116 result *= base;
1117 result += n;
1119 p++;
1121 *overflow = FALSE;
1122 return result;
1125 static void
1126 codegen(codegen_scope *s, node *tree, int val)
1128 int nt;
1130 if (!tree) return;
1132 if (s->irep && s->pc > 0 && s->filename_index != tree->filename_index) {
1133 s->irep->filename = mrb_parser_get_filename(s->parser, s->filename_index);
1134 mrb_debug_info_append_file(s->mrb, s->irep, s->debug_start_pos, s->pc);
1135 s->debug_start_pos = s->pc;
1136 s->filename_index = tree->filename_index;
1137 s->filename = mrb_parser_get_filename(s->parser, tree->filename_index);
1140 nt = (intptr_t)tree->car;
1141 s->lineno = tree->lineno;
1142 tree = tree->cdr;
1143 switch (nt) {
1144 case NODE_BEGIN:
1145 if (val && !tree) {
1146 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1147 push();
1149 while (tree) {
1150 codegen(s, tree->car, tree->cdr ? NOVAL : val);
1151 tree = tree->cdr;
1153 break;
1155 case NODE_RESCUE:
1157 int onerr, noexc, exend, pos1, pos2, tmp;
1158 struct loopinfo *lp;
1160 onerr = genop(s, MKOP_Bx(OP_ONERR, 0));
1161 lp = loop_push(s, LOOP_BEGIN);
1162 lp->pc1 = onerr;
1163 if (tree->car) {
1164 codegen(s, tree->car, val);
1165 if (val) pop();
1167 lp->type = LOOP_RESCUE;
1168 noexc = genop(s, MKOP_Bx(OP_JMP, 0));
1169 dispatch(s, onerr);
1170 tree = tree->cdr;
1171 exend = 0;
1172 pos1 = 0;
1173 if (tree->car) {
1174 node *n2 = tree->car;
1175 int exc = cursp();
1177 genop(s, MKOP_A(OP_RESCUE, exc));
1178 push();
1179 while (n2) {
1180 node *n3 = n2->car;
1181 node *n4 = n3->car;
1183 if (pos1) dispatch(s, pos1);
1184 pos2 = 0;
1185 do {
1186 if (n4) {
1187 codegen(s, n4->car, VAL);
1189 else {
1190 genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "StandardError"))));
1191 push();
1193 genop(s, MKOP_AB(OP_MOVE, cursp(), exc));
1194 pop();
1195 if (n4 && n4->car && (intptr_t)n4->car->car == NODE_SPLAT) {
1196 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1));
1198 else {
1199 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "===")), 1));
1201 tmp = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2));
1202 pos2 = tmp;
1203 if (n4) {
1204 n4 = n4->cdr;
1206 } while (n4);
1207 pos1 = genop(s, MKOP_sBx(OP_JMP, 0));
1208 dispatch_linked(s, pos2);
1210 pop();
1211 if (n3->cdr->car) {
1212 gen_assignment(s, n3->cdr->car, exc, NOVAL);
1214 if (n3->cdr->cdr->car) {
1215 codegen(s, n3->cdr->cdr->car, val);
1216 if (val) pop();
1218 tmp = genop(s, MKOP_sBx(OP_JMP, exend));
1219 exend = tmp;
1220 n2 = n2->cdr;
1221 push();
1223 if (pos1) {
1224 dispatch(s, pos1);
1225 genop(s, MKOP_A(OP_RAISE, exc));
1228 pop();
1229 tree = tree->cdr;
1230 dispatch(s, noexc);
1231 genop(s, MKOP_A(OP_POPERR, 1));
1232 if (tree->car) {
1233 codegen(s, tree->car, val);
1235 else if (val) {
1236 push();
1238 dispatch_linked(s, exend);
1239 loop_pop(s, NOVAL);
1241 break;
1243 case NODE_ENSURE:
1245 int idx;
1246 int epush = s->pc;
1248 genop(s, MKOP_Bx(OP_EPUSH, 0));
1249 s->ensure_level++;
1250 codegen(s, tree->car, val);
1251 idx = scope_body(s, tree->cdr, NOVAL);
1252 s->iseq[epush] = MKOP_Bx(OP_EPUSH, idx);
1253 s->ensure_level--;
1254 genop_peep(s, MKOP_A(OP_EPOP, 1), NOVAL);
1256 break;
1258 case NODE_LAMBDA:
1260 int idx = lambda_body(s, tree, 1);
1262 genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_LAMBDA));
1263 push();
1265 break;
1267 case NODE_BLOCK:
1269 int idx = lambda_body(s, tree, 1);
1271 genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_BLOCK));
1272 push();
1274 break;
1276 case NODE_IF:
1278 int pos1, pos2;
1279 node *e = tree->cdr->cdr->car;
1281 codegen(s, tree->car, VAL);
1282 pop();
1283 pos1 = genop_peep(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0), NOVAL);
1285 codegen(s, tree->cdr->car, val);
1286 if (val && !(tree->cdr->car)) {
1287 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1288 push();
1290 if (e) {
1291 if (val) pop();
1292 pos2 = genop(s, MKOP_sBx(OP_JMP, 0));
1293 dispatch(s, pos1);
1294 codegen(s, e, val);
1295 dispatch(s, pos2);
1297 else {
1298 if (val) {
1299 pop();
1300 pos2 = genop(s, MKOP_sBx(OP_JMP, 0));
1301 dispatch(s, pos1);
1302 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1303 dispatch(s, pos2);
1304 push();
1306 else {
1307 dispatch(s, pos1);
1311 break;
1313 case NODE_AND:
1315 int pos;
1317 codegen(s, tree->car, VAL);
1318 pop();
1319 pos = genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0));
1320 codegen(s, tree->cdr, val);
1321 dispatch(s, pos);
1323 break;
1325 case NODE_OR:
1327 int pos;
1329 codegen(s, tree->car, VAL);
1330 pop();
1331 pos = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), 0));
1332 codegen(s, tree->cdr, val);
1333 dispatch(s, pos);
1335 break;
1337 case NODE_WHILE:
1339 struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
1341 lp->pc1 = genop(s, MKOP_sBx(OP_JMP, 0));
1342 lp->pc2 = new_label(s);
1343 codegen(s, tree->cdr, NOVAL);
1344 dispatch(s, lp->pc1);
1345 codegen(s, tree->car, VAL);
1346 pop();
1347 genop(s, MKOP_AsBx(OP_JMPIF, cursp(), lp->pc2 - s->pc));
1349 loop_pop(s, val);
1351 break;
1353 case NODE_UNTIL:
1355 struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
1357 lp->pc1 = genop(s, MKOP_sBx(OP_JMP, 0));
1358 lp->pc2 = new_label(s);
1359 codegen(s, tree->cdr, NOVAL);
1360 dispatch(s, lp->pc1);
1361 codegen(s, tree->car, VAL);
1362 pop();
1363 genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), lp->pc2 - s->pc));
1365 loop_pop(s, val);
1367 break;
1369 case NODE_FOR:
1370 for_body(s, tree);
1371 if (val) push();
1372 break;
1374 case NODE_CASE:
1376 int head = 0;
1377 int pos1, pos2, pos3, tmp;
1378 node *n;
1380 pos3 = 0;
1381 if (tree->car) {
1382 head = cursp();
1383 codegen(s, tree->car, VAL);
1385 tree = tree->cdr;
1386 while (tree) {
1387 n = tree->car->car;
1388 pos1 = pos2 = 0;
1389 while (n) {
1390 codegen(s, n->car, VAL);
1391 if (head) {
1392 genop(s, MKOP_AB(OP_MOVE, cursp(), head));
1393 pop();
1394 if ((intptr_t)n->car->car == NODE_SPLAT) {
1395 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1));
1397 else {
1398 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "===")), 1));
1401 else {
1402 pop();
1404 tmp = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2));
1405 pos2 = tmp;
1406 n = n->cdr;
1408 if (tree->car->car) {
1409 pos1 = genop(s, MKOP_sBx(OP_JMP, 0));
1410 dispatch_linked(s, pos2);
1412 codegen(s, tree->car->cdr, val);
1413 if (val) pop();
1414 tmp = genop(s, MKOP_sBx(OP_JMP, pos3));
1415 pos3 = tmp;
1416 if (pos1) dispatch(s, pos1);
1417 tree = tree->cdr;
1419 if (val) {
1420 int pos = cursp();
1421 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1422 if (pos3) dispatch_linked(s, pos3);
1423 pop();
1424 genop(s, MKOP_AB(OP_MOVE, cursp(), pos));
1425 push();
1427 else if (pos3) {
1428 dispatch_linked(s, pos3);
1431 break;
1433 case NODE_SCOPE:
1434 scope_body(s, tree, NOVAL);
1435 break;
1437 case NODE_FCALL:
1438 case NODE_CALL:
1439 gen_call(s, tree, 0, 0, val);
1440 break;
1442 case NODE_DOT2:
1443 codegen(s, tree->car, val);
1444 codegen(s, tree->cdr, val);
1445 if (val) {
1446 pop(); pop();
1447 genop(s, MKOP_ABC(OP_RANGE, cursp(), cursp(), 0));
1448 push();
1450 break;
1452 case NODE_DOT3:
1453 codegen(s, tree->car, val);
1454 codegen(s, tree->cdr, val);
1455 if (val) {
1456 pop(); pop();
1457 genop(s, MKOP_ABC(OP_RANGE, cursp(), cursp(), 1));
1458 push();
1460 break;
1462 case NODE_COLON2:
1464 int sym = new_sym(s, sym(tree->cdr));
1466 codegen(s, tree->car, VAL);
1467 pop();
1468 genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
1469 if (val) push();
1471 break;
1473 case NODE_COLON3:
1475 int sym = new_sym(s, sym(tree));
1477 genop(s, MKOP_A(OP_OCLASS, cursp()));
1478 genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
1479 if (val) push();
1481 break;
1483 case NODE_ARRAY:
1485 int n;
1487 n = gen_values(s, tree, val);
1488 if (n >= 0) {
1489 if (val) {
1490 pop_n(n);
1491 genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), n));
1492 push();
1495 else if (val) {
1496 push();
1499 break;
1501 case NODE_HASH:
1503 int len = 0;
1505 while (tree) {
1506 codegen(s, tree->car->car, val);
1507 codegen(s, tree->car->cdr, val);
1508 len++;
1509 tree = tree->cdr;
1511 if (val) {
1512 pop_n(len*2);
1513 genop(s, MKOP_ABC(OP_HASH, cursp(), cursp(), len));
1514 push();
1517 break;
1519 case NODE_SPLAT:
1520 codegen(s, tree, VAL);
1521 break;
1523 case NODE_ASGN:
1524 codegen(s, tree->cdr, VAL);
1525 pop();
1526 gen_assignment(s, tree->car, cursp(), val);
1527 break;
1529 case NODE_MASGN:
1531 int len = 0, n = 0, post = 0;
1532 node *t = tree->cdr, *p;
1533 int rhs = cursp();
1535 if ((intptr_t)t->car == NODE_ARRAY && nosplat(t->cdr)) {
1536 /* fixed rhs */
1537 t = t->cdr;
1538 while (t) {
1539 codegen(s, t->car, VAL);
1540 len++;
1541 t = t->cdr;
1543 tree = tree->car;
1544 if (tree->car) { /* pre */
1545 t = tree->car;
1546 n = 0;
1547 while (t) {
1548 gen_assignment(s, t->car, rhs+n, NOVAL);
1549 n++;
1550 t = t->cdr;
1553 t = tree->cdr;
1554 if (t) {
1555 if (t->cdr) { /* post count */
1556 p = t->cdr->car;
1557 while (p) {
1558 post++;
1559 p = p->cdr;
1562 if (t->car) { /* rest (len - pre - post) */
1563 int rn = len - post - n;
1565 genop(s, MKOP_ABC(OP_ARRAY, cursp(), rhs+n, rn));
1566 gen_assignment(s, t->car, cursp(), NOVAL);
1567 n += rn;
1569 if (t->cdr && t->cdr->car) {
1570 t = t->cdr->car;
1571 while (n<len) {
1572 gen_assignment(s, t->car, rhs+n, NOVAL);
1573 t = t->cdr;
1574 n++;
1578 pop_n(len);
1579 if (val) {
1580 genop(s, MKOP_ABC(OP_ARRAY, rhs, rhs, len));
1581 push();
1584 else {
1585 /* variable rhs */
1586 codegen(s, t, VAL);
1587 gen_vmassignment(s, tree->car, rhs, val);
1590 break;
1592 case NODE_OP_ASGN:
1594 mrb_sym sym = sym(tree->cdr->car);
1595 mrb_int len;
1596 const char *name = mrb_sym2name_len(s->mrb, sym, &len);
1597 int idx;
1599 codegen(s, tree->car, VAL);
1600 if (len == 2 &&
1601 ((name[0] == '|' && name[1] == '|') ||
1602 (name[0] == '&' && name[1] == '&'))) {
1603 int pos;
1605 pop();
1606 pos = genop_peep(s, MKOP_AsBx(name[0] == '|' ? OP_JMPIF : OP_JMPNOT, cursp(), 0), NOVAL);
1607 codegen(s, tree->cdr->cdr->car, VAL);
1608 pop();
1609 gen_assignment(s, tree->car, cursp(), val);
1610 dispatch(s, pos);
1611 break;
1613 codegen(s, tree->cdr->cdr->car, VAL);
1614 pop(); pop();
1616 idx = new_msym(s, sym);
1617 if (len == 1 && name[0] == '+') {
1618 genop_peep(s, MKOP_ABC(OP_ADD, cursp(), idx, 1), val);
1620 else if (len == 1 && name[0] == '-') {
1621 genop_peep(s, MKOP_ABC(OP_SUB, cursp(), idx, 1), val);
1623 else if (len == 1 && name[0] == '*') {
1624 genop(s, MKOP_ABC(OP_MUL, cursp(), idx, 1));
1626 else if (len == 1 && name[0] == '/') {
1627 genop(s, MKOP_ABC(OP_DIV, cursp(), idx, 1));
1629 else if (len == 1 && name[0] == '<') {
1630 genop(s, MKOP_ABC(OP_LT, cursp(), idx, 1));
1632 else if (len == 2 && name[0] == '<' && name[1] == '=') {
1633 genop(s, MKOP_ABC(OP_LE, cursp(), idx, 1));
1635 else if (len == 1 && name[0] == '>') {
1636 genop(s, MKOP_ABC(OP_GT, cursp(), idx, 1));
1638 else if (len == 2 && name[0] == '>' && name[1] == '=') {
1639 genop(s, MKOP_ABC(OP_GE, cursp(), idx, 1));
1641 else {
1642 genop(s, MKOP_ABC(OP_SEND, cursp(), idx, 1));
1645 gen_assignment(s, tree->car, cursp(), val);
1646 break;
1648 case NODE_SUPER:
1650 int n = 0, noop = 0, sendv = 0;
1652 push(); /* room for receiver */
1653 if (tree) {
1654 node *args = tree->car;
1655 if (args) {
1656 n = gen_values(s, args, VAL);
1657 if (n < 0) {
1658 n = noop = sendv = 1;
1659 push();
1663 if (tree && tree->cdr) {
1664 codegen(s, tree->cdr, VAL);
1665 pop();
1667 else {
1668 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1670 pop_n(n+1);
1671 if (sendv) n = CALL_MAXARGS;
1672 genop(s, MKOP_ABC(OP_SUPER, cursp(), 0, n));
1673 if (val) push();
1675 break;
1677 case NODE_ZSUPER:
1679 codegen_scope *s2 = s;
1680 int lv = 0, ainfo = 0;
1682 push(); /* room for receiver */
1683 while (!s2->mscope) {
1684 lv++;
1685 s2 = s2->prev;
1686 if (!s2) break;
1688 if (s2) ainfo = s2->ainfo;
1689 genop(s, MKOP_ABx(OP_ARGARY, cursp(), (ainfo<<4)|(lv & 0xf)));
1690 if (tree && tree->cdr) {
1691 push();
1692 codegen(s, tree->cdr, VAL);
1693 pop_n(2);
1695 pop();
1696 genop(s, MKOP_ABC(OP_SUPER, cursp(), 0, CALL_MAXARGS));
1697 if (val) push();
1699 break;
1701 case NODE_RETURN:
1702 if (tree) {
1703 codegen(s, tree, VAL);
1704 pop();
1706 else {
1707 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1709 if (s->loop) {
1710 genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_RETURN));
1712 else {
1713 genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
1715 if (val) push();
1716 break;
1718 case NODE_YIELD:
1720 codegen_scope *s2 = s;
1721 int lv = 0, ainfo = 0;
1722 int n = 0, sendv = 0;
1724 while (!s2->mscope) {
1725 lv++;
1726 s2 = s2->prev;
1727 if (!s2) break;
1729 if (s2) ainfo = s2->ainfo;
1730 genop(s, MKOP_ABx(OP_BLKPUSH, cursp(), (ainfo<<4)|(lv & 0xf)));
1731 push();
1732 if (tree) {
1733 n = gen_values(s, tree, VAL);
1734 if (n < 0) {
1735 n = sendv = 1;
1736 push();
1739 pop_n(n+1);
1740 if (sendv) n = CALL_MAXARGS;
1741 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "call")), n));
1742 if (val) push();
1744 break;
1746 case NODE_BREAK:
1747 loop_break(s, tree);
1748 if (val) push();
1749 break;
1751 case NODE_NEXT:
1752 if (!s->loop) {
1753 raise_error(s, "unexpected next");
1755 else if (s->loop->type == LOOP_NORMAL) {
1756 if (s->ensure_level > s->loop->ensure_level) {
1757 genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL);
1759 codegen(s, tree, NOVAL);
1760 genop(s, MKOP_sBx(OP_JMP, s->loop->pc1 - s->pc));
1762 else {
1763 if (tree) {
1764 codegen(s, tree, VAL);
1765 pop();
1767 else {
1768 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1770 genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
1772 if (val) push();
1773 break;
1775 case NODE_REDO:
1776 if (!s->loop) {
1777 raise_error(s, "unexpected redo");
1779 else {
1780 if (s->ensure_level > s->loop->ensure_level) {
1781 genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL);
1783 genop(s, MKOP_sBx(OP_JMP, s->loop->pc2 - s->pc));
1785 break;
1787 case NODE_RETRY:
1789 const char *msg = "unexpected retry";
1791 if (!s->loop) {
1792 raise_error(s, msg);
1794 else {
1795 struct loopinfo *lp = s->loop;
1796 int n = 0;
1798 while (lp && lp->type != LOOP_RESCUE) {
1799 if (lp->type == LOOP_BEGIN) {
1800 n++;
1802 lp = lp->prev;
1804 if (!lp) {
1805 raise_error(s, msg);
1807 else {
1808 if (n > 0) {
1809 while (n--) {
1810 genop_peep(s, MKOP_A(OP_POPERR, 1), NOVAL);
1813 if (s->ensure_level > lp->ensure_level) {
1814 genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - lp->ensure_level), NOVAL);
1816 genop(s, MKOP_sBx(OP_JMP, lp->pc1 - s->pc));
1820 break;
1822 case NODE_LVAR:
1823 if (val) {
1824 int idx = lv_idx(s, sym(tree));
1826 if (idx > 0) {
1827 genop(s, MKOP_AB(OP_MOVE, cursp(), idx));
1829 else {
1830 int lv = 0;
1831 codegen_scope *up = s->prev;
1833 while (up) {
1834 idx = lv_idx(up, sym(tree));
1835 if (idx > 0) {
1836 genop(s, MKOP_ABC(OP_GETUPVAR, cursp(), idx, lv));
1837 break;
1839 lv++;
1840 up = up->prev;
1843 push();
1845 break;
1847 case NODE_GVAR:
1849 int sym = new_sym(s, sym(tree));
1851 genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
1852 push();
1854 break;
1856 case NODE_IVAR:
1858 int sym = new_sym(s, sym(tree));
1860 genop(s, MKOP_ABx(OP_GETIV, cursp(), sym));
1861 push();
1863 break;
1865 case NODE_CVAR:
1867 int sym = new_sym(s, sym(tree));
1869 genop(s, MKOP_ABx(OP_GETCV, cursp(), sym));
1870 push();
1872 break;
1874 case NODE_CONST:
1876 int sym = new_sym(s, sym(tree));
1878 genop(s, MKOP_ABx(OP_GETCONST, cursp(), sym));
1879 push();
1881 break;
1883 case NODE_DEFINED:
1884 codegen(s, tree, VAL);
1885 break;
1887 case NODE_BACK_REF:
1889 char buf[2] = { '$' };
1890 mrb_value str;
1891 int sym;
1893 buf[1] = (char)(intptr_t)tree;
1894 str = mrb_str_new(s->mrb, buf, 2);
1895 sym = new_sym(s, mrb_intern_str(s->mrb, str));
1896 genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
1897 push();
1899 break;
1901 case NODE_NTH_REF:
1903 int sym;
1904 mrb_state *mrb = s->mrb;
1905 mrb_value fix = mrb_fixnum_value((intptr_t)tree);
1906 mrb_value str = mrb_str_buf_new(mrb, 4);
1908 mrb_str_cat_lit(mrb, str, "$");
1909 mrb_str_buf_append(mrb, str, mrb_fixnum_to_str(mrb, fix, 10));
1910 sym = new_sym(s, mrb_intern_str(mrb, str));
1911 genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
1912 push();
1914 break;
1916 case NODE_ARG:
1917 /* should not happen */
1918 break;
1920 case NODE_BLOCK_ARG:
1921 codegen(s, tree, VAL);
1922 break;
1924 case NODE_INT:
1925 if (val) {
1926 char *p = (char*)tree->car;
1927 int base = (intptr_t)tree->cdr->car;
1928 mrb_int i;
1929 mrb_code co;
1930 mrb_bool overflow;
1932 i = readint_mrb_int(s, p, base, FALSE, &overflow);
1933 if (overflow) {
1934 double f = readint_float(s, p, base);
1935 int off = new_lit(s, mrb_float_value(s->mrb, f));
1937 genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
1939 else {
1940 if (i < MAXARG_sBx && i > -MAXARG_sBx) {
1941 co = MKOP_AsBx(OP_LOADI, cursp(), i);
1943 else {
1944 int off = new_lit(s, mrb_fixnum_value(i));
1945 co = MKOP_ABx(OP_LOADL, cursp(), off);
1947 genop(s, co);
1949 push();
1951 break;
1953 case NODE_FLOAT:
1954 if (val) {
1955 char *p = (char*)tree;
1956 mrb_float f = str_to_mrb_float(p);
1957 int off = new_lit(s, mrb_float_value(s->mrb, f));
1959 genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
1960 push();
1962 break;
1964 case NODE_NEGATE:
1966 nt = (intptr_t)tree->car;
1967 tree = tree->cdr;
1968 switch (nt) {
1969 case NODE_FLOAT:
1971 char *p = (char*)tree;
1972 mrb_float f = str_to_mrb_float(p);
1973 int off = new_lit(s, mrb_float_value(s->mrb, -f));
1975 genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
1976 push();
1978 break;
1980 case NODE_INT:
1982 char *p = (char*)tree->car;
1983 int base = (intptr_t)tree->cdr->car;
1984 mrb_int i;
1985 mrb_code co;
1986 mrb_bool overflow;
1988 i = readint_mrb_int(s, p, base, TRUE, &overflow);
1989 if (overflow) {
1990 double f = readint_float(s, p, base);
1991 int off = new_lit(s, mrb_float_value(s->mrb, -f));
1993 genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
1995 else {
1996 if (i < MAXARG_sBx && i > -MAXARG_sBx) {
1997 co = MKOP_AsBx(OP_LOADI, cursp(), i);
1999 else {
2000 int off = new_lit(s, mrb_fixnum_value(i));
2001 co = MKOP_ABx(OP_LOADL, cursp(), off);
2003 genop(s, co);
2005 push();
2007 break;
2009 default:
2011 int sym = new_msym(s, mrb_intern_lit(s->mrb, "-"));
2013 genop(s, MKOP_ABx(OP_LOADI, cursp(), 0));
2014 push();
2015 codegen(s, tree, VAL);
2016 pop(); pop();
2017 genop(s, MKOP_ABC(OP_SUB, cursp(), sym, 2));
2019 break;
2022 break;
2024 case NODE_STR:
2025 if (val) {
2026 char *p = (char*)tree->car;
2027 size_t len = (intptr_t)tree->cdr;
2028 int ai = mrb_gc_arena_save(s->mrb);
2029 int off = new_lit(s, mrb_str_new(s->mrb, p, len));
2031 mrb_gc_arena_restore(s->mrb, ai);
2032 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2033 push();
2035 break;
2037 case NODE_HEREDOC:
2038 tree = ((struct mrb_parser_heredoc_info *)tree)->doc;
2039 /* fall through */
2040 case NODE_DSTR:
2041 if (val) {
2042 node *n = tree;
2044 codegen(s, n->car, VAL);
2045 n = n->cdr;
2046 while (n) {
2047 codegen(s, n->car, VAL);
2048 pop(); pop();
2049 genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
2050 push();
2051 n = n->cdr;
2054 else {
2055 node *n = tree;
2057 while (n) {
2058 if ((intptr_t)n->car->car != NODE_STR) {
2059 codegen(s, n->car, NOVAL);
2061 n = n->cdr;
2064 break;
2066 case NODE_WORDS:
2067 gen_literal_array(s, tree, FALSE, val);
2068 break;
2070 case NODE_SYMBOLS:
2071 gen_literal_array(s, tree, TRUE, val);
2072 break;
2074 case NODE_XSTR:
2075 if (val) {
2076 char *p = (char*)tree->car;
2077 size_t len = (intptr_t)tree->cdr;
2078 int ai = mrb_gc_arena_save(s->mrb);
2079 int sym = new_sym(s, mrb_intern_lit(s->mrb, "Kernel"));
2080 int off = new_lit(s, mrb_str_new(s->mrb, p, len));
2082 genop(s, MKOP_A(OP_OCLASS, cursp()));
2083 genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
2084 push();
2085 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2086 pop();
2087 sym = new_sym(s, mrb_intern_lit(s->mrb, "`"));
2088 genop(s, MKOP_ABC(OP_SEND, cursp(), sym, 1));
2089 mrb_gc_arena_restore(s->mrb, ai);
2090 push();
2092 break;
2094 case NODE_REGX:
2095 if (val) {
2096 char *p1 = (char*)tree->car;
2097 char *p2 = (char*)tree->cdr;
2098 int ai = mrb_gc_arena_save(s->mrb);
2099 int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS));
2100 int off = new_lit(s, mrb_str_new_cstr(s->mrb, p1));
2101 int argc = 1;
2103 genop(s, MKOP_A(OP_OCLASS, cursp()));
2104 genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
2105 push();
2106 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2107 if (p2) {
2108 push();
2109 off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
2110 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2111 argc++;
2112 pop();
2114 pop();
2115 sym = new_sym(s, mrb_intern_lit(s->mrb, "compile"));
2116 genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc));
2117 mrb_gc_arena_restore(s->mrb, ai);
2118 push();
2120 break;
2122 case NODE_DREGX:
2123 if (val) {
2124 node *n = tree->car;
2125 int ai = mrb_gc_arena_save(s->mrb);
2126 int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS));
2127 int argc = 1;
2128 int off;
2129 char *p;
2131 genop(s, MKOP_A(OP_OCLASS, cursp()));
2132 genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
2133 push();
2134 codegen(s, n->car, VAL);
2135 n = n->cdr;
2136 while (n) {
2137 codegen(s, n->car, VAL);
2138 pop(); pop();
2139 genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
2140 push();
2141 n = n->cdr;
2143 n = tree->cdr->cdr;
2144 if (n->car) {
2145 p = (char*)n->car;
2146 off = new_lit(s, mrb_str_new_cstr(s->mrb, p));
2147 codegen(s, tree->car, VAL);
2148 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2149 pop();
2150 genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
2152 if (n->cdr) {
2153 char *p2 = (char*)n->cdr;
2154 int off;
2156 push();
2157 off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
2158 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2159 argc++;
2160 pop();
2162 pop();
2163 sym = new_sym(s, mrb_intern_lit(s->mrb, "compile"));
2164 genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc));
2165 mrb_gc_arena_restore(s->mrb, ai);
2166 push();
2168 else {
2169 node *n = tree->car;
2171 while (n) {
2172 if ((intptr_t)n->car->car != NODE_STR) {
2173 codegen(s, n->car, NOVAL);
2175 n = n->cdr;
2178 break;
2180 case NODE_SYM:
2181 if (val) {
2182 int sym = new_sym(s, sym(tree));
2184 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym));
2185 push();
2187 break;
2189 case NODE_DSYM:
2190 codegen(s, tree, val);
2191 if (val) {
2192 gen_send_intern(s);
2194 break;
2196 case NODE_SELF:
2197 if (val) {
2198 genop(s, MKOP_A(OP_LOADSELF, cursp()));
2199 push();
2201 break;
2203 case NODE_NIL:
2204 if (val) {
2205 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2206 push();
2208 break;
2210 case NODE_TRUE:
2211 if (val) {
2212 genop(s, MKOP_A(OP_LOADT, cursp()));
2213 push();
2215 break;
2217 case NODE_FALSE:
2218 if (val) {
2219 genop(s, MKOP_A(OP_LOADF, cursp()));
2220 push();
2222 break;
2224 case NODE_ALIAS:
2226 int a = new_msym(s, sym(tree->car));
2227 int b = new_msym(s, sym(tree->cdr));
2228 int c = new_msym(s, mrb_intern_lit(s->mrb,"alias_method"));
2230 genop(s, MKOP_A(OP_TCLASS, cursp()));
2231 push();
2232 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), a));
2233 push();
2234 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), b));
2235 push();
2236 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2237 pop_n(3);
2238 genop(s, MKOP_ABC(OP_SEND, cursp(), c, 2));
2239 if (val) {
2240 push();
2243 break;
2245 case NODE_UNDEF:
2247 int undef = new_msym(s, mrb_intern_lit(s->mrb, "undef_method"));
2248 int num = 0;
2249 node *t = tree;
2251 genop(s, MKOP_A(OP_TCLASS, cursp()));
2252 push();
2253 while (t) {
2254 int symbol = new_msym(s, sym(t->car));
2255 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), symbol));
2256 push();
2257 t = t->cdr;
2258 num++;
2260 pop_n(num + 1);
2261 genop(s, MKOP_ABC(OP_SEND, cursp(), undef, num));
2262 if (val) {
2263 push();
2266 break;
2268 case NODE_CLASS:
2270 int idx;
2272 if (tree->car->car == (node*)0) {
2273 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2274 push();
2276 else if (tree->car->car == (node*)1) {
2277 genop(s, MKOP_A(OP_OCLASS, cursp()));
2278 push();
2280 else {
2281 codegen(s, tree->car->car, VAL);
2283 if (tree->cdr->car) {
2284 codegen(s, tree->cdr->car, VAL);
2286 else {
2287 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2288 push();
2290 pop(); pop();
2291 idx = new_msym(s, sym(tree->car->cdr));
2292 genop(s, MKOP_AB(OP_CLASS, cursp(), idx));
2293 idx = scope_body(s, tree->cdr->cdr->car, val);
2294 genop(s, MKOP_ABx(OP_EXEC, cursp(), idx));
2295 if (val) {
2296 push();
2299 break;
2301 case NODE_MODULE:
2303 int idx;
2305 if (tree->car->car == (node*)0) {
2306 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2307 push();
2309 else if (tree->car->car == (node*)1) {
2310 genop(s, MKOP_A(OP_OCLASS, cursp()));
2311 push();
2313 else {
2314 codegen(s, tree->car->car, VAL);
2316 pop();
2317 idx = new_msym(s, sym(tree->car->cdr));
2318 genop(s, MKOP_AB(OP_MODULE, cursp(), idx));
2319 idx = scope_body(s, tree->cdr->car, val);
2320 genop(s, MKOP_ABx(OP_EXEC, cursp(), idx));
2321 if (val) {
2322 push();
2325 break;
2327 case NODE_SCLASS:
2329 int idx;
2331 codegen(s, tree->car, VAL);
2332 pop();
2333 genop(s, MKOP_AB(OP_SCLASS, cursp(), cursp()));
2334 idx = scope_body(s, tree->cdr->car, val);
2335 genop(s, MKOP_ABx(OP_EXEC, cursp(), idx));
2336 if (val) {
2337 push();
2340 break;
2342 case NODE_DEF:
2344 int sym = new_msym(s, sym(tree->car));
2345 int idx = lambda_body(s, tree->cdr, 0);
2347 genop(s, MKOP_A(OP_TCLASS, cursp()));
2348 push();
2349 genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_METHOD));
2350 pop();
2351 genop(s, MKOP_AB(OP_METHOD, cursp(), sym));
2352 if (val) {
2353 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym));
2354 push();
2357 break;
2359 case NODE_SDEF:
2361 node *recv = tree->car;
2362 int sym = new_msym(s, sym(tree->cdr->car));
2363 int idx = lambda_body(s, tree->cdr->cdr, 0);
2365 codegen(s, recv, VAL);
2366 pop();
2367 genop(s, MKOP_AB(OP_SCLASS, cursp(), cursp()));
2368 push();
2369 genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_METHOD));
2370 pop();
2371 genop(s, MKOP_AB(OP_METHOD, cursp(), sym));
2372 if (val) {
2373 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym));
2374 push();
2377 break;
2379 case NODE_POSTEXE:
2380 codegen(s, tree, NOVAL);
2381 break;
2383 default:
2384 break;
2388 static void
2389 scope_add_irep(codegen_scope *s, mrb_irep *irep)
2391 if (s->irep == NULL) {
2392 s->irep = irep;
2393 return;
2395 if (s->irep->rlen == s->rcapa) {
2396 s->rcapa *= 2;
2397 s->irep->reps = (mrb_irep**)codegen_realloc(s, s->irep->reps, sizeof(mrb_irep*)*s->rcapa);
2399 s->irep->reps[s->irep->rlen] = irep;
2400 s->irep->rlen++;
2403 static codegen_scope*
2404 scope_new(mrb_state *mrb, codegen_scope *prev, node *lv)
2406 static const codegen_scope codegen_scope_zero = { 0 };
2407 mrb_pool *pool = mrb_pool_open(mrb);
2408 codegen_scope *p = (codegen_scope *)mrb_pool_alloc(pool, sizeof(codegen_scope));
2410 if (!p) return 0;
2411 *p = codegen_scope_zero;
2412 p->mrb = mrb;
2413 p->mpool = pool;
2414 if (!prev) return p;
2415 p->prev = prev;
2416 p->ainfo = -1;
2417 p->mscope = 0;
2419 p->irep = mrb_add_irep(mrb);
2420 scope_add_irep(prev, p->irep);
2422 p->rcapa = 8;
2423 p->irep->reps = (mrb_irep**)mrb_malloc(mrb, sizeof(mrb_irep*)*p->rcapa);
2425 p->icapa = 1024;
2426 p->iseq = (mrb_code*)mrb_malloc(mrb, sizeof(mrb_code)*p->icapa);
2427 p->irep->iseq = p->iseq;
2429 p->pcapa = 32;
2430 p->irep->pool = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value)*p->pcapa);
2431 p->irep->plen = 0;
2433 p->scapa = 256;
2434 p->irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*p->scapa);
2435 p->irep->slen = 0;
2437 p->lv = lv;
2438 p->sp += node_len(lv)+1; /* add self */
2439 p->nlocals = p->sp;
2440 p->ai = mrb_gc_arena_save(mrb);
2442 p->filename = prev->filename;
2443 if (p->filename) {
2444 p->lines = (uint16_t*)mrb_malloc(mrb, sizeof(short)*p->icapa);
2446 p->lineno = prev->lineno;
2448 /* debug setting */
2449 p->debug_start_pos = 0;
2450 if(p->filename) {
2451 mrb_debug_info_alloc(mrb, p->irep);
2452 p->irep->filename = p->filename;
2453 p->irep->lines = p->lines;
2455 else {
2456 p->irep->debug_info = NULL;
2458 p->parser = prev->parser;
2459 p->filename_index = prev->filename_index;
2461 return p;
2464 static void
2465 scope_finish(codegen_scope *s)
2467 mrb_state *mrb = s->mrb;
2468 mrb_irep *irep = s->irep;
2469 size_t fname_len;
2470 char *fname;
2472 irep->flags = 0;
2473 if (s->iseq) {
2474 irep->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc);
2475 irep->ilen = s->pc;
2476 if (s->lines) {
2477 irep->lines = (uint16_t *)codegen_realloc(s, s->lines, sizeof(uint16_t)*s->pc);
2479 else {
2480 irep->lines = 0;
2483 irep->pool = (mrb_value*)codegen_realloc(s, irep->pool, sizeof(mrb_value)*irep->plen);
2484 irep->syms = (mrb_sym*)codegen_realloc(s, irep->syms, sizeof(mrb_sym)*irep->slen);
2485 irep->reps = (mrb_irep**)codegen_realloc(s, irep->reps, sizeof(mrb_irep*)*irep->rlen);
2486 if (s->filename) {
2487 s->irep->filename = mrb_parser_get_filename(s->parser, s->filename_index);
2488 mrb_debug_info_append_file(mrb, s->irep, s->debug_start_pos, s->pc);
2490 fname_len = strlen(s->filename);
2491 fname = (char*)codegen_malloc(s, fname_len + 1);
2492 memcpy(fname, s->filename, fname_len);
2493 fname[fname_len] = '\0';
2494 irep->filename = fname;
2497 irep->nlocals = s->nlocals;
2498 irep->nregs = s->nregs;
2500 mrb_gc_arena_restore(mrb, s->ai);
2501 mrb_pool_close(s->mpool);
2504 static struct loopinfo*
2505 loop_push(codegen_scope *s, enum looptype t)
2507 struct loopinfo *p = (struct loopinfo *)codegen_palloc(s, sizeof(struct loopinfo));
2509 p->type = t;
2510 p->pc1 = p->pc2 = p->pc3 = 0;
2511 p->prev = s->loop;
2512 p->ensure_level = s->ensure_level;
2513 p->acc = cursp();
2514 s->loop = p;
2516 return p;
2519 static void
2520 loop_break(codegen_scope *s, node *tree)
2522 if (!s->loop) {
2523 codegen(s, tree, NOVAL);
2524 raise_error(s, "unexpected break");
2526 else {
2527 struct loopinfo *loop;
2529 if (tree) {
2530 codegen(s, tree, VAL);
2531 pop();
2534 loop = s->loop;
2535 while (loop->type == LOOP_BEGIN) {
2536 genop_peep(s, MKOP_A(OP_POPERR, 1), NOVAL);
2537 loop = loop->prev;
2539 while (loop->type == LOOP_RESCUE) {
2540 loop = loop->prev;
2542 if (loop->type == LOOP_NORMAL) {
2543 int tmp;
2545 if (s->ensure_level > s->loop->ensure_level) {
2546 genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL);
2548 if (tree) {
2549 genop_peep(s, MKOP_AB(OP_MOVE, loop->acc, cursp()), NOVAL);
2551 tmp = genop(s, MKOP_sBx(OP_JMP, loop->pc3));
2552 loop->pc3 = tmp;
2554 else {
2555 genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_BREAK));
2560 static void
2561 loop_pop(codegen_scope *s, int val)
2563 if (val) {
2564 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2566 dispatch_linked(s, s->loop->pc3);
2567 s->loop = s->loop->prev;
2568 if (val) push();
2571 static void
2572 codedump(mrb_state *mrb, mrb_irep *irep)
2574 #ifdef ENABLE_STDIO
2575 int i;
2576 int ai;
2577 mrb_code c;
2579 if (!irep) return;
2580 printf("irep %p nregs=%d nlocals=%d pools=%d syms=%d reps=%d\n", irep,
2581 irep->nregs, irep->nlocals, (int)irep->plen, (int)irep->slen, (int)irep->rlen);
2583 mrb_assert(irep->ilen <= INT_MAX);
2584 for (i = 0; i < (int)(irep->ilen); i++) {
2585 ai = mrb_gc_arena_save(mrb);
2586 printf("%03d ", i);
2587 c = irep->iseq[i];
2588 switch (GET_OPCODE(c)) {
2589 case OP_NOP:
2590 printf("OP_NOP\n");
2591 break;
2592 case OP_MOVE:
2593 printf("OP_MOVE\tR%d\tR%d\n", GETARG_A(c), GETARG_B(c));
2594 break;
2595 case OP_LOADL:
2596 printf("OP_LOADL\tR%d\tL(%d)\n", GETARG_A(c), GETARG_Bx(c));
2597 break;
2598 case OP_LOADI:
2599 printf("OP_LOADI\tR%d\t%d\n", GETARG_A(c), GETARG_sBx(c));
2600 break;
2601 case OP_LOADSYM:
2602 printf("OP_LOADSYM\tR%d\t:%s\n", GETARG_A(c),
2603 mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
2604 break;
2605 case OP_LOADNIL:
2606 printf("OP_LOADNIL\tR%d\n", GETARG_A(c));
2607 break;
2608 case OP_LOADSELF:
2609 printf("OP_LOADSELF\tR%d\n", GETARG_A(c));
2610 break;
2611 case OP_LOADT:
2612 printf("OP_LOADT\tR%d\n", GETARG_A(c));
2613 break;
2614 case OP_LOADF:
2615 printf("OP_LOADF\tR%d\n", GETARG_A(c));
2616 break;
2617 case OP_GETGLOBAL:
2618 printf("OP_GETGLOBAL\tR%d\t:%s\n", GETARG_A(c),
2619 mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
2620 break;
2621 case OP_SETGLOBAL:
2622 printf("OP_SETGLOBAL\t:%s\tR%d\n",
2623 mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
2624 GETARG_A(c));
2625 break;
2626 case OP_GETCONST:
2627 printf("OP_GETCONST\tR%d\t:%s\n", GETARG_A(c),
2628 mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
2629 break;
2630 case OP_SETCONST:
2631 printf("OP_SETCONST\t:%s\tR%d\n",
2632 mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
2633 GETARG_A(c));
2634 break;
2635 case OP_GETMCNST:
2636 printf("OP_GETMCNST\tR%d\tR%d::%s\n", GETARG_A(c), GETARG_A(c),
2637 mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
2638 break;
2639 case OP_SETMCNST:
2640 printf("OP_SETMCNST\tR%d::%s\tR%d\n", GETARG_A(c)+1,
2641 mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
2642 GETARG_A(c));
2643 break;
2644 case OP_GETIV:
2645 printf("OP_GETIV\tR%d\t%s\n", GETARG_A(c),
2646 mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
2647 break;
2648 case OP_SETIV:
2649 printf("OP_SETIV\t%s\tR%d\n",
2650 mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
2651 GETARG_A(c));
2652 break;
2653 case OP_GETUPVAR:
2654 printf("OP_GETUPVAR\tR%d\t%d\t%d\n",
2655 GETARG_A(c), GETARG_B(c), GETARG_C(c));
2656 break;
2657 case OP_SETUPVAR:
2658 printf("OP_SETUPVAR\tR%d\t%d\t%d\n",
2659 GETARG_A(c), GETARG_B(c), GETARG_C(c));
2660 break;
2661 case OP_GETCV:
2662 printf("OP_GETCV\tR%d\t%s\n", GETARG_A(c),
2663 mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
2664 break;
2665 case OP_SETCV:
2666 printf("OP_SETCV\t%s\tR%d\n",
2667 mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
2668 GETARG_A(c));
2669 break;
2670 case OP_JMP:
2671 printf("OP_JMP\t\t%03d\n", i+GETARG_sBx(c));
2672 break;
2673 case OP_JMPIF:
2674 printf("OP_JMPIF\tR%d\t%03d\n", GETARG_A(c), i+GETARG_sBx(c));
2675 break;
2676 case OP_JMPNOT:
2677 printf("OP_JMPNOT\tR%d\t%03d\n", GETARG_A(c), i+GETARG_sBx(c));
2678 break;
2679 case OP_SEND:
2680 printf("OP_SEND\tR%d\t:%s\t%d\n", GETARG_A(c),
2681 mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
2682 GETARG_C(c));
2683 break;
2684 case OP_SENDB:
2685 printf("OP_SENDB\tR%d\t:%s\t%d\n", GETARG_A(c),
2686 mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
2687 GETARG_C(c));
2688 break;
2689 case OP_TAILCALL:
2690 printf("OP_TAILCALL\tR%d\t:%s\t%d\n", GETARG_A(c),
2691 mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
2692 GETARG_C(c));
2693 break;
2694 case OP_SUPER:
2695 printf("OP_SUPER\tR%d\t%d\n", GETARG_A(c),
2696 GETARG_C(c));
2697 break;
2698 case OP_ARGARY:
2699 printf("OP_ARGARY\tR%d\t%d:%d:%d:%d\n", GETARG_A(c),
2700 (GETARG_Bx(c)>>10)&0x3f,
2701 (GETARG_Bx(c)>>9)&0x1,
2702 (GETARG_Bx(c)>>4)&0x1f,
2703 (GETARG_Bx(c)>>0)&0xf);
2704 break;
2706 case OP_ENTER:
2707 printf("OP_ENTER\t%d:%d:%d:%d:%d:%d:%d\n",
2708 (GETARG_Ax(c)>>18)&0x1f,
2709 (GETARG_Ax(c)>>13)&0x1f,
2710 (GETARG_Ax(c)>>12)&0x1,
2711 (GETARG_Ax(c)>>7)&0x1f,
2712 (GETARG_Ax(c)>>2)&0x1f,
2713 (GETARG_Ax(c)>>1)&0x1,
2714 GETARG_Ax(c) & 0x1);
2715 break;
2716 case OP_RETURN:
2717 printf("OP_RETURN\tR%d", GETARG_A(c));
2718 switch (GETARG_B(c)) {
2719 case OP_R_NORMAL:
2720 printf("\n"); break;
2721 case OP_R_RETURN:
2722 printf("\treturn\n"); break;
2723 case OP_R_BREAK:
2724 printf("\tbreak\n"); break;
2725 default:
2726 printf("\tbroken\n"); break;
2727 break;
2729 break;
2730 case OP_BLKPUSH:
2731 printf("OP_BLKPUSH\tR%d\t%d:%d:%d:%d\n", GETARG_A(c),
2732 (GETARG_Bx(c)>>10)&0x3f,
2733 (GETARG_Bx(c)>>9)&0x1,
2734 (GETARG_Bx(c)>>4)&0x1f,
2735 (GETARG_Bx(c)>>0)&0xf);
2736 break;
2738 case OP_LAMBDA:
2739 printf("OP_LAMBDA\tR%d\tI(%+d)\t%d\n", GETARG_A(c), GETARG_b(c)+1, GETARG_c(c));
2740 break;
2741 case OP_RANGE:
2742 printf("OP_RANGE\tR%d\tR%d\t%d\n", GETARG_A(c), GETARG_B(c), GETARG_C(c));
2743 break;
2744 case OP_METHOD:
2745 printf("OP_METHOD\tR%d\t:%s\n", GETARG_A(c),
2746 mrb_sym2name(mrb, irep->syms[GETARG_B(c)]));
2747 break;
2749 case OP_ADD:
2750 printf("OP_ADD\tR%d\t:%s\t%d\n", GETARG_A(c),
2751 mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
2752 GETARG_C(c));
2753 break;
2754 case OP_ADDI:
2755 printf("OP_ADDI\tR%d\t:%s\t%d\n", GETARG_A(c),
2756 mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
2757 GETARG_C(c));
2758 break;
2759 case OP_SUB:
2760 printf("OP_SUB\tR%d\t:%s\t%d\n", GETARG_A(c),
2761 mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
2762 GETARG_C(c));
2763 break;
2764 case OP_SUBI:
2765 printf("OP_SUBI\tR%d\t:%s\t%d\n", GETARG_A(c),
2766 mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
2767 GETARG_C(c));
2768 break;
2769 case OP_MUL:
2770 printf("OP_MUL\tR%d\t:%s\t%d\n", GETARG_A(c),
2771 mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
2772 GETARG_C(c));
2773 break;
2774 case OP_DIV:
2775 printf("OP_DIV\tR%d\t:%s\t%d\n", GETARG_A(c),
2776 mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
2777 GETARG_C(c));
2778 break;
2779 case OP_LT:
2780 printf("OP_LT\tR%d\t:%s\t%d\n", GETARG_A(c),
2781 mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
2782 GETARG_C(c));
2783 break;
2784 case OP_LE:
2785 printf("OP_LE\tR%d\t:%s\t%d\n", GETARG_A(c),
2786 mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
2787 GETARG_C(c));
2788 break;
2789 case OP_GT:
2790 printf("OP_GT\tR%d\t:%s\t%d\n", GETARG_A(c),
2791 mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
2792 GETARG_C(c));
2793 break;
2794 case OP_GE:
2795 printf("OP_GE\tR%d\t:%s\t%d\n", GETARG_A(c),
2796 mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
2797 GETARG_C(c));
2798 break;
2799 case OP_EQ:
2800 printf("OP_EQ\tR%d\t:%s\t%d\n", GETARG_A(c),
2801 mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
2802 GETARG_C(c));
2803 break;
2805 case OP_STOP:
2806 printf("OP_STOP\n");
2807 break;
2809 case OP_ARRAY:
2810 printf("OP_ARRAY\tR%d\tR%d\t%d\n", GETARG_A(c), GETARG_B(c), GETARG_C(c));
2811 break;
2812 case OP_ARYCAT:
2813 printf("OP_ARYCAT\tR%d\tR%d\n", GETARG_A(c), GETARG_B(c));
2814 break;
2815 case OP_ARYPUSH:
2816 printf("OP_ARYPUSH\tR%d\tR%d\n", GETARG_A(c), GETARG_B(c));
2817 break;
2818 case OP_AREF:
2819 printf("OP_AREF\tR%d\tR%d\t%d\n", GETARG_A(c), GETARG_B(c), GETARG_C(c));
2820 break;
2821 case OP_APOST:
2822 printf("OP_APOST\tR%d\t%d\t%d\n", GETARG_A(c), GETARG_B(c), GETARG_C(c));
2823 break;
2824 case OP_STRING:
2826 mrb_value v = irep->pool[GETARG_Bx(c)];
2827 mrb_value s = mrb_str_dump(mrb, mrb_str_new(mrb, RSTRING_PTR(v), RSTRING_LEN(v)));
2828 printf("OP_STRING\tR%d\t%s\n", GETARG_A(c), RSTRING_PTR(s));
2830 break;
2831 case OP_STRCAT:
2832 printf("OP_STRCAT\tR%d\tR%d\n", GETARG_A(c), GETARG_B(c));
2833 break;
2834 case OP_HASH:
2835 printf("OP_HASH\tR%d\tR%d\t%d\n", GETARG_A(c), GETARG_B(c), GETARG_C(c));
2836 break;
2838 case OP_OCLASS:
2839 printf("OP_OCLASS\tR%d\n", GETARG_A(c));
2840 break;
2841 case OP_CLASS:
2842 printf("OP_CLASS\tR%d\t:%s\n", GETARG_A(c),
2843 mrb_sym2name(mrb, irep->syms[GETARG_B(c)]));
2844 break;
2845 case OP_MODULE:
2846 printf("OP_MODULE\tR%d\t:%s\n", GETARG_A(c),
2847 mrb_sym2name(mrb, irep->syms[GETARG_B(c)]));
2848 break;
2849 case OP_EXEC:
2850 printf("OP_EXEC\tR%d\tI(%+d)\n", GETARG_A(c), GETARG_Bx(c)+1);
2851 break;
2852 case OP_SCLASS:
2853 printf("OP_SCLASS\tR%d\tR%d\n", GETARG_A(c), GETARG_B(c));
2854 break;
2855 case OP_TCLASS:
2856 printf("OP_TCLASS\tR%d\n", GETARG_A(c));
2857 break;
2858 case OP_ERR:
2860 mrb_value v = irep->pool[GETARG_Bx(c)];
2861 mrb_value s = mrb_str_dump(mrb, mrb_str_new(mrb, RSTRING_PTR(v), RSTRING_LEN(v)));
2862 printf("OP_ERR\t%s\n", RSTRING_PTR(s));
2864 break;
2865 case OP_EPUSH:
2866 printf("OP_EPUSH\t:I(%+d)\n", GETARG_Bx(c)+1);
2867 break;
2868 case OP_ONERR:
2869 printf("OP_ONERR\t%03d\n", i+GETARG_sBx(c));
2870 break;
2871 case OP_RESCUE:
2872 printf("OP_RESCUE\tR%d\n", GETARG_A(c));
2873 break;
2874 case OP_RAISE:
2875 printf("OP_RAISE\tR%d\n", GETARG_A(c));
2876 break;
2877 case OP_POPERR:
2878 printf("OP_POPERR\t%d\n", GETARG_A(c));
2879 break;
2880 case OP_EPOP:
2881 printf("OP_EPOP\t%d\n", GETARG_A(c));
2882 break;
2884 default:
2885 printf("OP_unknown %d\t%d\t%d\t%d\n", GET_OPCODE(c),
2886 GETARG_A(c), GETARG_B(c), GETARG_C(c));
2887 break;
2889 mrb_gc_arena_restore(mrb, ai);
2891 printf("\n");
2892 #endif
2895 static void
2896 codedump_recur(mrb_state *mrb, mrb_irep *irep)
2898 size_t i;
2900 codedump(mrb, irep);
2901 for (i=0; i<irep->rlen; i++) {
2902 codedump_recur(mrb, irep->reps[i]);
2906 void
2907 mrb_codedump_all(mrb_state *mrb, struct RProc *proc)
2909 codedump_recur(mrb, proc->body.irep);
2912 struct RProc*
2913 mrb_generate_code(mrb_state *mrb, parser_state *p)
2915 codegen_scope *scope = scope_new(mrb, 0, 0);
2916 struct RProc *proc;
2918 if (!scope) {
2919 return NULL;
2921 scope->mrb = mrb;
2922 scope->parser = p;
2923 scope->filename = p->filename;
2924 scope->filename_index = p->current_filename_index;
2926 MRB_TRY(&scope->jmp) {
2927 /* prepare irep */
2928 codegen(scope, p->tree, NOVAL);
2929 proc = mrb_proc_new(mrb, scope->irep);
2930 mrb_irep_decref(mrb, scope->irep);
2931 mrb_pool_close(scope->mpool);
2932 return proc;
2934 MRB_CATCH(&scope->jmp) {
2935 if (scope->filename == scope->irep->filename) {
2936 scope->irep->filename = NULL;
2938 mrb_irep_decref(mrb, scope->irep);
2939 mrb_pool_close(scope->mpool);
2940 return NULL;
2942 MRB_END_EXC(&scope->jmp);