should splat and iterate elements when "*ary" speficied in the case-when clause;...
[mruby.git] / src / codegen.c
blob83018c62709456b80da1e7d1c1ab266bdb4d5364
1 /*
2 ** codegen.c - mruby code generator
3 **
4 ** See Copyright Notice in mruby.h
5 */
7 #include <ctype.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include "mruby.h"
11 #include "mruby/compile.h"
12 #include "mruby/proc.h"
13 #include "mruby/numeric.h"
14 #include "mruby/string.h"
15 #include "mruby/debug.h"
16 #include "node.h"
17 #include "opcode.h"
18 #include "re.h"
20 typedef mrb_ast_node node;
21 typedef struct mrb_parser_state parser_state;
23 enum looptype {
24 LOOP_NORMAL,
25 LOOP_BLOCK,
26 LOOP_FOR,
27 LOOP_BEGIN,
28 LOOP_RESCUE,
29 } type;
31 struct loopinfo {
32 enum looptype type;
33 int pc1, pc2, pc3, acc;
34 int ensure_level;
35 struct loopinfo *prev;
38 typedef struct scope {
39 mrb_state *mrb;
40 mrb_pool *mpool;
41 jmp_buf jmp;
43 struct scope *prev;
45 node *lv;
47 int sp;
48 int pc;
49 int lastlabel;
50 int ainfo:15;
51 mrb_bool mscope:1;
53 struct loopinfo *loop;
54 int ensure_level;
55 char const *filename;
56 uint16_t lineno;
58 mrb_code *iseq;
59 uint16_t *lines;
60 int icapa;
62 mrb_irep *irep;
63 size_t pcapa;
64 size_t scapa;
65 size_t rcapa;
67 int nlocals;
68 int nregs;
69 int ai;
71 int debug_start_pos;
72 uint16_t filename_index;
73 parser_state* parser;
74 } codegen_scope;
76 static codegen_scope* scope_new(mrb_state *mrb, codegen_scope *prev, node *lv);
77 static void scope_finish(codegen_scope *s);
78 static struct loopinfo *loop_push(codegen_scope *s, enum looptype t);
79 static void loop_break(codegen_scope *s, node *tree);
80 static void loop_pop(codegen_scope *s, int val);
82 static void gen_assignment(codegen_scope *s, node *node, int sp, int val);
83 static void gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val);
85 static void codegen(codegen_scope *s, node *tree, int val);
87 static void
88 codegen_error(codegen_scope *s, const char *message)
90 if (!s) return;
91 while (s->prev) {
92 codegen_scope *tmp = s->prev;
93 mrb_pool_close(s->mpool);
94 s = tmp;
96 #ifdef ENABLE_STDIO
97 if (s->filename && s->lineno) {
98 fprintf(stderr, "codegen error:%s:%d: %s\n", s->filename, s->lineno, message);
100 else {
101 fprintf(stderr, "codegen error: %s\n", message);
103 #endif
104 longjmp(s->jmp, 1);
107 static void*
108 codegen_palloc(codegen_scope *s, size_t len)
110 void *p = mrb_pool_alloc(s->mpool, len);
112 if (!p) codegen_error(s, "pool memory allocation");
113 return p;
116 static void*
117 codegen_malloc(codegen_scope *s, size_t len)
119 void *p = mrb_malloc_simple(s->mrb, len);
121 if (!p) codegen_error(s, "mrb_malloc");
122 return p;
125 static void*
126 codegen_realloc(codegen_scope *s, void *p, size_t len)
128 p = mrb_realloc_simple(s->mrb, p, len);
130 if (!p && len > 0) codegen_error(s, "mrb_realloc");
131 return p;
134 static int
135 new_label(codegen_scope *s)
137 s->lastlabel = s->pc;
138 return s->pc;
141 static inline void
142 genop(codegen_scope *s, mrb_code i)
144 if (s->pc == s->icapa) {
145 s->icapa *= 2;
146 s->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->icapa);
147 if (s->lines) {
148 s->lines = (uint16_t*)codegen_realloc(s, s->lines, sizeof(short)*s->icapa);
149 s->irep->lines = s->lines;
152 s->iseq[s->pc] = i;
153 if (s->lines) {
154 s->lines[s->pc] = s->lineno;
156 s->pc++;
159 #define NOVAL 0
160 #define VAL 1
162 static void
163 genop_peep(codegen_scope *s, mrb_code i, int val)
165 /* peephole optimization */
166 if (s->lastlabel != s->pc && s->pc > 0) {
167 mrb_code i0 = s->iseq[s->pc-1];
168 int c1 = GET_OPCODE(i);
169 int c0 = GET_OPCODE(i0);
171 switch (c1) {
172 case OP_MOVE:
173 if (GETARG_A(i) == GETARG_B(i)) {
174 /* skip useless OP_MOVE */
175 return;
177 if (val) break;
178 switch (c0) {
179 case OP_MOVE:
180 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i) == GETARG_B(i0) && GETARG_A(i) >= s->nlocals) {
181 /* skip swapping OP_MOVE */
182 return;
184 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
185 s->iseq[s->pc-1] = MKOP_AB(OP_MOVE, GETARG_A(i), GETARG_B(i0));
186 return;
188 break;
189 case OP_LOADI:
190 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
191 s->iseq[s->pc-1] = MKOP_AsBx(OP_LOADI, GETARG_A(i), GETARG_sBx(i0));
192 return;
194 break;
195 case OP_ARRAY:
196 case OP_HASH:
197 case OP_RANGE:
198 case OP_AREF:
199 case OP_GETUPVAR:
200 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
201 s->iseq[s->pc-1] = MKOP_ABC(c0, GETARG_A(i), GETARG_B(i0), GETARG_C(i0));
202 return;
204 break;
205 case OP_LOADSYM:
206 case OP_GETGLOBAL:
207 case OP_GETIV:
208 case OP_GETCV:
209 case OP_GETCONST:
210 case OP_GETSPECIAL:
211 case OP_LOADL:
212 case OP_STRING:
213 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
214 s->iseq[s->pc-1] = MKOP_ABx(c0, GETARG_A(i), GETARG_Bx(i0));
215 return;
217 break;
218 case OP_SCLASS:
219 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
220 s->iseq[s->pc-1] = MKOP_AB(c0, GETARG_A(i), GETARG_B(i0));
221 return;
223 break;
224 case OP_LOADNIL:
225 case OP_LOADSELF:
226 case OP_LOADT:
227 case OP_LOADF:
228 case OP_OCLASS:
229 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
230 s->iseq[s->pc-1] = MKOP_A(c0, GETARG_A(i));
231 return;
233 break;
234 default:
235 break;
237 break;
238 case OP_SETIV:
239 case OP_SETCV:
240 case OP_SETCONST:
241 case OP_SETMCNST:
242 case OP_SETGLOBAL:
243 if (val) break;
244 if (c0 == OP_MOVE) {
245 if (GETARG_A(i) == GETARG_A(i0)) {
246 s->iseq[s->pc-1] = MKOP_ABx(c1, GETARG_B(i0), GETARG_Bx(i));
247 return;
250 break;
251 case OP_SETUPVAR:
252 if (val) break;
253 if (c0 == OP_MOVE) {
254 if (GETARG_A(i) == GETARG_A(i0)) {
255 s->iseq[s->pc-1] = MKOP_ABC(c1, GETARG_B(i0), GETARG_B(i), GETARG_C(i));
256 return;
259 break;
260 case OP_EPOP:
261 if (c0 == OP_EPOP) {
262 s->iseq[s->pc-1] = MKOP_A(OP_EPOP, GETARG_A(i0)+GETARG_A(i));
263 return;
265 break;
266 case OP_POPERR:
267 if (c0 == OP_POPERR) {
268 s->iseq[s->pc-1] = MKOP_A(OP_POPERR, GETARG_A(i0)+GETARG_A(i));
269 return;
271 break;
272 case OP_RETURN:
273 switch (c0) {
274 case OP_RETURN:
275 return;
276 case OP_MOVE:
277 s->iseq[s->pc-1] = MKOP_AB(OP_RETURN, GETARG_B(i0), OP_R_NORMAL);
278 return;
279 case OP_SETIV:
280 case OP_SETCV:
281 case OP_SETCONST:
282 case OP_SETMCNST:
283 case OP_SETUPVAR:
284 case OP_SETGLOBAL:
285 s->pc--;
286 genop_peep(s, i0, NOVAL);
287 i0 = s->iseq[s->pc-1];
288 genop(s, MKOP_AB(OP_RETURN, GETARG_A(i0), OP_R_NORMAL));
289 return;
290 #if 0
291 case OP_SEND:
292 if (GETARG_B(i) == OP_R_NORMAL && GETARG_A(i) == GETARG_A(i0)) {
293 s->iseq[s->pc-1] = MKOP_ABC(OP_TAILCALL, GETARG_A(i0), GETARG_B(i0), GETARG_C(i0));
294 return;
296 break;
297 #endif
298 default:
299 break;
301 break;
302 case OP_ADD:
303 case OP_SUB:
304 if (c0 == OP_LOADI) {
305 int c = GETARG_sBx(i0);
307 if (c1 == OP_SUB) c = -c;
308 if (c > 127 || c < -127) break;
309 if (0 <= c)
310 s->iseq[s->pc-1] = MKOP_ABC(OP_ADDI, GETARG_A(i), GETARG_B(i), c);
311 else
312 s->iseq[s->pc-1] = MKOP_ABC(OP_SUBI, GETARG_A(i), GETARG_B(i), -c);
313 return;
315 case OP_STRCAT:
316 if (c0 == OP_STRING) {
317 int i = GETARG_Bx(i0);
319 if (mrb_type(s->irep->pool[i]) == MRB_TT_STRING &&
320 RSTRING_LEN(s->irep->pool[i]) == 0) {
321 s->pc--;
322 return;
325 break;
326 default:
327 break;
330 genop(s, i);
333 static void
334 scope_error(codegen_scope *s)
336 exit(EXIT_FAILURE);
339 static inline void
340 dispatch(codegen_scope *s, int pc)
342 int diff = s->pc - pc;
343 mrb_code i = s->iseq[pc];
344 int c = GET_OPCODE(i);
346 s->lastlabel = s->pc;
347 switch (c) {
348 case OP_JMP:
349 case OP_JMPIF:
350 case OP_JMPNOT:
351 case OP_ONERR:
352 break;
353 default:
354 #ifdef ENABLE_STDIO
355 fprintf(stderr, "bug: dispatch on non JMP op\n");
356 #endif
357 scope_error(s);
358 break;
360 s->iseq[pc] = MKOP_AsBx(c, GETARG_A(i), diff);
363 static void
364 dispatch_linked(codegen_scope *s, int pc)
366 mrb_code i;
367 int pos;
369 if (!pc) return;
370 for (;;) {
371 i = s->iseq[pc];
372 pos = GETARG_sBx(i);
373 dispatch(s, pc);
374 if (!pos) break;
375 pc = pos;
379 #define nregs_update do {if (s->sp > s->nregs) s->nregs = s->sp;} while (0)
380 static void
381 push_(codegen_scope *s)
383 if (s->sp > 511) {
384 codegen_error(s, "too complex expression");
386 s->sp++;
387 nregs_update;
390 #define push() push_(s)
391 #define pop_(s) ((s)->sp--)
392 #define pop() pop_(s)
393 #define pop_n(n) (s->sp-=(n))
394 #define cursp() (s->sp)
396 static inline int
397 new_lit(codegen_scope *s, mrb_value val)
399 size_t i;
400 mrb_value *pv;
402 switch (mrb_type(val)) {
403 case MRB_TT_STRING:
404 for (i=0; i<s->irep->plen; i++) {
405 mrb_int len;
406 pv = &s->irep->pool[i];
408 if (mrb_type(*pv) != MRB_TT_STRING) continue;
409 if ((len = RSTRING_LEN(*pv)) != RSTRING_LEN(val)) continue;
410 if (memcmp(RSTRING_PTR(*pv), RSTRING_PTR(val), len) == 0)
411 return i;
413 break;
414 case MRB_TT_FLOAT:
415 for (i=0; i<s->irep->plen; i++) {
416 pv = &s->irep->pool[i];
417 if (mrb_type(*pv) != MRB_TT_FLOAT) continue;
418 if (mrb_float(*pv) == mrb_float(val)) return i;
420 break;
421 case MRB_TT_FIXNUM:
422 for (i=0; i<s->irep->plen; i++) {
423 pv = &s->irep->pool[i];
424 if (!mrb_fixnum_p(*pv)) continue;
425 if (mrb_fixnum(*pv) == mrb_fixnum(val)) return i;
427 break;
428 default:
429 /* should not happen */
430 return 0;
433 if (s->irep->plen == s->pcapa) {
434 s->pcapa *= 2;
435 s->irep->pool = (mrb_value *)codegen_realloc(s, s->irep->pool, sizeof(mrb_value)*s->pcapa);
438 pv = &s->irep->pool[s->irep->plen];
439 i = s->irep->plen++;
441 switch (mrb_type(val)) {
442 case MRB_TT_STRING:
443 *pv = mrb_str_pool(s->mrb, val);
444 break;
446 case MRB_TT_FLOAT:
447 #ifdef MRB_WORD_BOXING
448 *pv = mrb_float_pool(s->mrb, mrb_float(val));
449 break;
450 #endif
451 case MRB_TT_FIXNUM:
452 *pv = val;
453 break;
455 default:
456 /* should not happen */
457 break;
459 return i;
462 static inline int
463 new_msym(codegen_scope *s, mrb_sym sym)
465 size_t i, len;
467 len = s->irep->slen;
468 if (len > 256) len = 256;
469 for (i=0; i<len; i++) {
470 if (s->irep->syms[i] == sym) return i;
471 if (s->irep->syms[i] == 0) break;
473 if (i == 256) {
474 codegen_error(s, "too many symbols (max 256)");
476 s->irep->syms[i] = sym;
477 if (i == s->irep->slen) s->irep->slen++;
478 return i;
481 static inline int
482 new_sym(codegen_scope *s, mrb_sym sym)
484 size_t i;
486 for (i=0; i<s->irep->slen; i++) {
487 if (s->irep->syms[i] == sym) return i;
489 if (s->irep->slen > 125 && s->irep->slen < 256) {
490 s->irep->syms = (mrb_sym *)codegen_realloc(s, s->irep->syms, sizeof(mrb_sym)*65536);
491 for (i = 0; i < 256 - s->irep->slen; i++) {
492 static const mrb_sym mrb_sym_zero = { 0 };
493 s->irep->syms[i + s->irep->slen] = mrb_sym_zero;
495 s->irep->slen = 256;
497 s->irep->syms[s->irep->slen] = sym;
498 return s->irep->slen++;
501 static int
502 node_len(node *tree)
504 int n = 0;
506 while (tree) {
507 n++;
508 tree = tree->cdr;
510 return n;
513 #define sym(x) ((mrb_sym)(intptr_t)(x))
514 #define lv_name(lv) sym((lv)->car)
515 static int
516 lv_idx(codegen_scope *s, mrb_sym id)
518 node *lv = s->lv;
519 int n = 1;
521 while (lv) {
522 if (lv_name(lv) == id) return n;
523 n++;
524 lv = lv->cdr;
526 return 0;
529 static void
530 for_body(codegen_scope *s, node *tree)
532 codegen_scope *prev = s;
533 int idx;
534 struct loopinfo *lp;
535 node *n2;
536 mrb_code c;
538 // generate receiver
539 codegen(s, tree->cdr->car, VAL);
540 // generate loop-block
541 s = scope_new(s->mrb, s, tree->car);
543 lp = loop_push(s, LOOP_FOR);
544 lp->pc1 = new_label(s);
546 // generate loop variable
547 n2 = tree->car;
548 if (n2->car && !n2->car->cdr && !n2->cdr) {
549 genop(s, MKOP_Ax(OP_ENTER, 0x40000));
550 gen_assignment(s, n2->car->car, 1, NOVAL);
552 else {
553 genop(s, MKOP_Ax(OP_ENTER, 0x40000));
554 gen_vmassignment(s, n2, 1, VAL);
556 codegen(s, tree->cdr->cdr->car, VAL);
557 pop();
558 if (s->pc > 0) {
559 c = s->iseq[s->pc-1];
560 if (GET_OPCODE(c) != OP_RETURN || GETARG_B(c) != OP_R_NORMAL || s->pc == s->lastlabel)
561 genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
563 loop_pop(s, NOVAL);
564 scope_finish(s);
565 s = prev;
566 genop(s, MKOP_Abc(OP_LAMBDA, cursp(), s->irep->rlen-1, OP_L_BLOCK));
567 pop();
568 idx = new_msym(s, mrb_intern_lit(s->mrb, "each"));
569 genop(s, MKOP_ABC(OP_SENDB, cursp(), idx, 0));
572 static int
573 lambda_body(codegen_scope *s, node *tree, int blk)
575 mrb_code c;
576 codegen_scope *parent = s;
577 s = scope_new(s->mrb, s, tree->car);
578 s->mscope = !blk;
580 if (blk) {
581 struct loopinfo *lp = loop_push(s, LOOP_BLOCK);
582 lp->pc1 = new_label(s);
584 tree = tree->cdr;
585 if (tree->car) {
586 mrb_aspec a;
587 int ma, oa, ra, pa, ka, kd, ba;
588 int pos, i;
589 node *n, *opt;
591 ma = node_len(tree->car->car);
592 n = tree->car->car;
593 while (n) {
594 n = n->cdr;
596 oa = node_len(tree->car->cdr->car);
597 ra = tree->car->cdr->cdr->car ? 1 : 0;
598 pa = node_len(tree->car->cdr->cdr->cdr->car);
599 ka = kd = 0;
600 ba = tree->car->cdr->cdr->cdr->cdr ? 1 : 0;
602 a = ((mrb_aspec)(ma & 0x1f) << 18)
603 | ((mrb_aspec)(oa & 0x1f) << 13)
604 | ((ra & 1) << 12)
605 | ((pa & 0x1f) << 7)
606 | ((ka & 0x1f) << 2)
607 | ((kd & 1)<< 1)
608 | (ba & 1);
609 s->ainfo = (((ma+oa) & 0x3f) << 6) /* (12bits = 6:1:5) */
610 | ((ra & 1) << 5)
611 | (pa & 0x1f);
612 genop(s, MKOP_Ax(OP_ENTER, a));
613 pos = new_label(s);
614 for (i=0; i<oa; i++) {
615 new_label(s);
616 genop(s, MKOP_sBx(OP_JMP, 0));
618 if (oa > 0) {
619 genop(s, MKOP_sBx(OP_JMP, 0));
621 opt = tree->car->cdr->car;
622 i = 0;
623 while (opt) {
624 int idx;
626 dispatch(s, pos+i);
627 codegen(s, opt->car->cdr, VAL);
628 idx = lv_idx(s, (mrb_sym)(intptr_t)opt->car->car);
629 pop();
630 genop_peep(s, MKOP_AB(OP_MOVE, idx, cursp()), NOVAL);
631 i++;
632 opt = opt->cdr;
634 if (oa > 0) {
635 dispatch(s, pos+i);
638 codegen(s, tree->cdr->car, VAL);
639 pop();
640 if (s->pc > 0) {
641 c = s->iseq[s->pc-1];
642 if (GET_OPCODE(c) != OP_RETURN || GETARG_B(c) != OP_R_NORMAL || s->pc == s->lastlabel) {
643 if (s->nregs == 0) {
644 genop(s, MKOP_A(OP_LOADNIL, 0));
645 genop(s, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
647 else {
648 genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
652 if (blk) {
653 loop_pop(s, NOVAL);
655 scope_finish(s);
656 return parent->irep->rlen - 1;
659 static int
660 scope_body(codegen_scope *s, node *tree, int val)
662 codegen_scope *scope = scope_new(s->mrb, s, tree->car);
664 codegen(scope, tree->cdr, VAL);
665 if (!s->iseq) {
666 genop(scope, MKOP_A(OP_STOP, 0));
668 else if (!val) {
669 genop(scope, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
671 else {
672 if (scope->nregs == 0) {
673 genop(scope, MKOP_A(OP_LOADNIL, 0));
674 genop(scope, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
676 else {
677 genop_peep(scope, MKOP_AB(OP_RETURN, scope->sp-1, OP_R_NORMAL), NOVAL);
680 scope_finish(scope);
681 if (!s->irep) {
682 /* should not happen */
683 return 0;
685 return s->irep->rlen - 1;
688 static mrb_bool
689 nosplat(node *t)
691 while (t) {
692 if ((intptr_t)t->car->car == NODE_SPLAT) return FALSE;
693 t = t->cdr;
695 return TRUE;
698 static mrb_sym
699 attrsym(codegen_scope *s, mrb_sym a)
701 const char *name;
702 size_t len;
703 char *name2;
705 name = mrb_sym2name_len(s->mrb, a, &len);
706 name2 = (char *)codegen_palloc(s, len+1);
707 memcpy(name2, name, len);
708 name2[len] = '=';
709 name2[len+1] = '\0';
711 return mrb_intern(s->mrb, name2, len+1);
714 static int
715 gen_values(codegen_scope *s, node *t, int val)
717 int n = 0;
718 int is_splat;
720 while (t) {
721 is_splat = (intptr_t)t->car->car == NODE_SPLAT; // splat mode
722 if (n >= 127 || is_splat) {
723 if (val) {
724 pop_n(n);
725 genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), n));
726 push();
727 codegen(s, t->car, VAL);
728 pop(); pop();
729 if (is_splat) {
730 genop(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1));
732 else {
733 genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
735 t = t->cdr;
736 while (t) {
737 push();
738 codegen(s, t->car, VAL);
739 pop(); pop();
740 if ((intptr_t)t->car->car == NODE_SPLAT) {
741 genop(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1));
743 else {
744 genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
746 t = t->cdr;
749 else {
750 codegen(s, t->car->cdr, NOVAL);
751 t = t->cdr;
752 while (t) {
753 codegen(s, t->car, NOVAL);
754 t = t->cdr;
757 return -1;
759 // normal (no splat) mode
760 codegen(s, t->car, val);
761 n++;
762 t = t->cdr;
764 return n;
767 #define CALL_MAXARGS 127
769 static void
770 gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val)
772 mrb_sym sym = name ? name : sym(tree->cdr->car);
773 int idx;
774 int n = 0, noop = 0, sendv = 0, blk = 0;
776 codegen(s, tree->car, VAL); /* receiver */
777 idx = new_msym(s, sym);
778 tree = tree->cdr->cdr->car;
779 if (tree) {
780 n = gen_values(s, tree->car, VAL);
781 if (n < 0) {
782 n = noop = sendv = 1;
783 push();
786 if (sp) {
787 if (sendv) {
788 pop();
789 genop(s, MKOP_AB(OP_ARYPUSH, cursp(), sp));
790 push();
792 else {
793 genop(s, MKOP_AB(OP_MOVE, cursp(), sp));
794 push();
795 n++;
798 if (tree && tree->cdr) {
799 noop = 1;
800 codegen(s, tree->cdr, VAL);
801 pop();
803 else {
804 blk = cursp();
806 pop_n(n+1);
808 size_t len;
809 const char *name = mrb_sym2name_len(s->mrb, sym, &len);
811 if (!noop && len == 1 && name[0] == '+') {
812 genop_peep(s, MKOP_ABC(OP_ADD, cursp(), idx, n), val);
814 else if (!noop && len == 1 && name[0] == '-') {
815 genop_peep(s, MKOP_ABC(OP_SUB, cursp(), idx, n), val);
817 else if (!noop && len == 1 && name[0] == '*') {
818 genop(s, MKOP_ABC(OP_MUL, cursp(), idx, n));
820 else if (!noop && len == 1 && name[0] == '/') {
821 genop(s, MKOP_ABC(OP_DIV, cursp(), idx, n));
823 else if (!noop && len == 1 && name[0] == '<') {
824 genop(s, MKOP_ABC(OP_LT, cursp(), idx, n));
826 else if (!noop && len == 2 && name[0] == '<' && name[1] == '=') {
827 genop(s, MKOP_ABC(OP_LE, cursp(), idx, n));
829 else if (!noop && len == 1 && name[0] == '>') {
830 genop(s, MKOP_ABC(OP_GT, cursp(), idx, n));
832 else if (!noop && len == 2 && name[0] == '>' && name[1] == '=') {
833 genop(s, MKOP_ABC(OP_GE, cursp(), idx, n));
835 else if (!noop && len == 2 && name[0] == '=' && name[1] == '=') {
836 genop(s, MKOP_ABC(OP_EQ, cursp(), idx, n));
838 else {
839 if (sendv) n = CALL_MAXARGS;
840 if (blk > 0) { /* no block */
841 genop(s, MKOP_ABC(OP_SEND, cursp(), idx, n));
843 else {
844 genop(s, MKOP_ABC(OP_SENDB, cursp(), idx, n));
848 if (val) {
849 push();
853 static void
854 gen_assignment(codegen_scope *s, node *node, int sp, int val)
856 int idx;
857 int type = (intptr_t)node->car;
859 node = node->cdr;
860 switch ((intptr_t)type) {
861 case NODE_GVAR:
862 idx = new_sym(s, sym(node));
863 genop_peep(s, MKOP_ABx(OP_SETGLOBAL, sp, idx), val);
864 break;
865 case NODE_LVAR:
866 idx = lv_idx(s, sym(node));
867 if (idx > 0) {
868 if (idx != sp) {
869 genop_peep(s, MKOP_AB(OP_MOVE, idx, sp), val);
871 break;
873 else { /* upvar */
874 int lv = 0;
875 codegen_scope *up = s->prev;
877 while (up) {
878 idx = lv_idx(up, sym(node));
879 if (idx > 0) {
880 genop_peep(s, MKOP_ABC(OP_SETUPVAR, sp, idx, lv), val);
881 break;
883 lv++;
884 up = up->prev;
887 break;
888 case NODE_IVAR:
889 idx = new_sym(s, sym(node));
890 genop_peep(s, MKOP_ABx(OP_SETIV, sp, idx), val);
891 break;
892 case NODE_CVAR:
893 idx = new_sym(s, sym(node));
894 genop_peep(s, MKOP_ABx(OP_SETCV, sp, idx), val);
895 break;
896 case NODE_CONST:
897 idx = new_sym(s, sym(node));
898 genop_peep(s, MKOP_ABx(OP_SETCONST, sp, idx), val);
899 break;
900 case NODE_COLON2:
901 idx = new_sym(s, sym(node->cdr));
902 genop_peep(s, MKOP_AB(OP_MOVE, cursp(), sp), NOVAL);
903 push();
904 codegen(s, node->car, VAL);
905 pop_n(2);
906 genop_peep(s, MKOP_ABx(OP_SETMCNST, cursp(), idx), val);
907 break;
909 case NODE_CALL:
910 push();
911 gen_call(s, node, attrsym(s, sym(node->cdr->car)), sp, NOVAL);
912 pop();
913 if (val) {
914 genop_peep(s, MKOP_AB(OP_MOVE, cursp(), sp), val);
916 break;
918 default:
919 #ifdef ENABLE_STDIO
920 printf("unknown lhs %d\n", type);
921 #endif
922 break;
924 if (val) push();
927 static void
928 gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val)
930 int n = 0, post = 0;
931 node *t, *p;
933 if (tree->car) { /* pre */
934 t = tree->car;
935 n = 0;
936 while (t) {
937 genop(s, MKOP_ABC(OP_AREF, cursp(), rhs, n));
938 gen_assignment(s, t->car, cursp(), NOVAL);
939 n++;
940 t = t->cdr;
943 t = tree->cdr;
944 if (t) {
945 if (t->cdr) { /* post count */
946 p = t->cdr->car;
947 while (p) {
948 post++;
949 p = p->cdr;
952 if (val) {
953 genop(s, MKOP_AB(OP_MOVE, cursp(), rhs));
954 push();
956 pop();
957 genop(s, MKOP_ABC(OP_APOST, cursp(), n, post));
958 n = 1;
959 if (t->car) { /* rest */
960 gen_assignment(s, t->car, cursp(), NOVAL);
962 if (t->cdr && t->cdr->car) {
963 t = t->cdr->car;
964 while (t) {
965 gen_assignment(s, t->car, cursp()+n, NOVAL);
966 t = t->cdr;
967 n++;
971 else {
972 pop();
976 static void
977 gen_send_intern(codegen_scope *s)
979 pop();
980 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "intern")), 0));
981 push();
983 static void
984 gen_literal_array(codegen_scope *s, node *tree, int sym, int val)
986 if (val) {
987 int i = 0, j = 0;
989 while (tree) {
990 switch ((intptr_t)tree->car->car) {
991 case NODE_STR:
992 if ((tree->cdr == NULL) && ((intptr_t)tree->car->cdr->cdr == 0))
993 break;
994 /* fall through */
995 case NODE_BEGIN:
996 codegen(s, tree->car, VAL);
997 ++j;
998 break;
1000 case NODE_LITERAL_DELIM:
1001 if (j > 0) {
1002 j = 0;
1003 ++i;
1004 if (sym)
1005 gen_send_intern(s);
1007 break;
1009 if (j >= 2) {
1010 pop(); pop();
1011 genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
1012 push();
1013 j = 1;
1015 tree = tree->cdr;
1017 if (j > 0) {
1018 ++i;
1019 if (sym)
1020 gen_send_intern(s);
1022 pop_n(i);
1023 genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), i));
1024 push();
1026 else {
1027 while (tree) {
1028 switch ((intptr_t)tree->car->car) {
1029 case NODE_BEGIN: case NODE_BLOCK:
1030 codegen(s, tree->car, NOVAL);
1032 tree = tree->cdr;
1037 static void
1038 raise_error(codegen_scope *s, const char *msg)
1040 int idx = new_lit(s, mrb_str_new_cstr(s->mrb, msg));
1042 genop(s, MKOP_ABx(OP_ERR, 1, idx));
1045 static double
1046 readint_float(codegen_scope *s, const char *p, int base)
1048 const char *e = p + strlen(p);
1049 double f = 0;
1050 int n;
1052 if (*p == '+') p++;
1053 while (p < e) {
1054 char c = *p;
1055 c = tolower((unsigned char)c);
1056 for (n=0; n<base; n++) {
1057 if (mrb_digitmap[n] == c) {
1058 f *= base;
1059 f += n;
1060 break;
1063 if (n == base) {
1064 codegen_error(s, "malformed readint input");
1066 p++;
1068 return f;
1071 static mrb_int
1072 readint_mrb_int(codegen_scope *s, const char *p, int base, int neg, int *overflow)
1074 const char *e = p + strlen(p);
1075 mrb_int result = 0;
1076 int n;
1078 if (*p == '+') p++;
1079 while (p < e) {
1080 char c = *p;
1081 c = tolower((unsigned char)c);
1082 for (n=0; n<base; n++) {
1083 if (mrb_digitmap[n] == c) {
1084 break;
1087 if (n == base) {
1088 codegen_error(s, "malformed readint input");
1091 if (neg) {
1092 if ((MRB_INT_MIN + n)/base > result) {
1093 *overflow = TRUE;
1094 return 0;
1096 result *= base;
1097 result -= n;
1099 else {
1100 if ((MRB_INT_MAX - n)/base < result) {
1101 *overflow = TRUE;
1102 return 0;
1104 result *= base;
1105 result += n;
1107 p++;
1109 *overflow = FALSE;
1110 return result;
1113 static void
1114 codegen(codegen_scope *s, node *tree, int val)
1116 int nt;
1118 if (!tree) return;
1120 if (s->irep && s->pc > 0 && s->filename_index != tree->filename_index) {
1121 s->irep->filename = mrb_parser_get_filename(s->parser, s->filename_index);
1122 mrb_debug_info_append_file(s->mrb, s->irep, s->debug_start_pos, s->pc);
1123 s->debug_start_pos = s->pc;
1124 s->filename_index = tree->filename_index;
1125 s->filename = mrb_parser_get_filename(s->parser, tree->filename_index);
1128 nt = (intptr_t)tree->car;
1129 s->lineno = tree->lineno;
1130 tree = tree->cdr;
1131 switch (nt) {
1132 case NODE_BEGIN:
1133 if (val && !tree) {
1134 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1135 push();
1137 while (tree) {
1138 codegen(s, tree->car, tree->cdr ? NOVAL : val);
1139 tree = tree->cdr;
1141 break;
1143 case NODE_RESCUE:
1145 int onerr, noexc, exend, pos1, pos2, tmp;
1146 struct loopinfo *lp;
1148 onerr = new_label(s);
1149 genop(s, MKOP_Bx(OP_ONERR, 0));
1150 lp = loop_push(s, LOOP_BEGIN);
1151 lp->pc1 = onerr;
1152 if (tree->car) {
1153 codegen(s, tree->car, val);
1154 if (val) pop();
1156 lp->type = LOOP_RESCUE;
1157 noexc = new_label(s);
1158 genop(s, MKOP_Bx(OP_JMP, 0));
1159 dispatch(s, onerr);
1160 tree = tree->cdr;
1161 exend = 0;
1162 pos1 = 0;
1163 if (tree->car) {
1164 node *n2 = tree->car;
1165 int exc = cursp();
1167 genop(s, MKOP_A(OP_RESCUE, exc));
1168 push();
1169 while (n2) {
1170 node *n3 = n2->car;
1171 node *n4 = n3->car;
1173 if (pos1) dispatch(s, pos1);
1174 pos2 = 0;
1175 do {
1176 if (n4) {
1177 codegen(s, n4->car, VAL);
1179 else {
1180 genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "StandardError"))));
1181 push();
1183 genop(s, MKOP_AB(OP_MOVE, cursp(), exc));
1184 pop();
1185 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "===")), 1));
1186 tmp = new_label(s);
1187 genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2));
1188 pos2 = tmp;
1189 if (n4) {
1190 n4 = n4->cdr;
1192 } while (n4);
1193 pos1 = new_label(s);
1194 genop(s, MKOP_sBx(OP_JMP, 0));
1195 dispatch_linked(s, pos2);
1197 pop();
1198 if (n3->cdr->car) {
1199 gen_assignment(s, n3->cdr->car, exc, NOVAL);
1201 if (n3->cdr->cdr->car) {
1202 codegen(s, n3->cdr->cdr->car, val);
1203 if (val) pop();
1205 tmp = new_label(s);
1206 genop(s, MKOP_sBx(OP_JMP, exend));
1207 exend = tmp;
1208 n2 = n2->cdr;
1209 push();
1211 if (pos1) {
1212 dispatch(s, pos1);
1213 genop(s, MKOP_A(OP_RAISE, exc));
1216 pop();
1217 tree = tree->cdr;
1218 dispatch(s, noexc);
1219 genop(s, MKOP_A(OP_POPERR, 1));
1220 if (tree->car) {
1221 codegen(s, tree->car, val);
1223 else if (val) {
1224 push();
1226 dispatch_linked(s, exend);
1227 loop_pop(s, NOVAL);
1229 break;
1231 case NODE_ENSURE:
1233 int idx;
1234 int epush = s->pc;
1236 genop(s, MKOP_Bx(OP_EPUSH, 0));
1237 s->ensure_level++;
1238 codegen(s, tree->car, val);
1239 idx = scope_body(s, tree->cdr, NOVAL);
1240 s->iseq[epush] = MKOP_Bx(OP_EPUSH, idx);
1241 s->ensure_level--;
1242 genop_peep(s, MKOP_A(OP_EPOP, 1), NOVAL);
1244 break;
1246 case NODE_LAMBDA:
1248 int idx = lambda_body(s, tree, 1);
1250 genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_LAMBDA));
1251 push();
1253 break;
1255 case NODE_BLOCK:
1257 int idx = lambda_body(s, tree, 1);
1259 genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_BLOCK));
1260 push();
1262 break;
1264 case NODE_IF:
1266 int pos1, pos2;
1267 node *e = tree->cdr->cdr->car;
1269 codegen(s, tree->car, VAL);
1270 pop();
1271 pos1 = new_label(s);
1272 genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0));
1274 codegen(s, tree->cdr->car, val);
1275 if (val && !(tree->cdr->car)) {
1276 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1277 push();
1279 if (e) {
1280 if (val) pop();
1281 pos2 = new_label(s);
1282 genop(s, MKOP_sBx(OP_JMP, 0));
1283 dispatch(s, pos1);
1284 codegen(s, e, val);
1285 dispatch(s, pos2);
1287 else {
1288 if (val) {
1289 pop();
1290 pos2 = new_label(s);
1291 genop(s, MKOP_sBx(OP_JMP, 0));
1292 dispatch(s, pos1);
1293 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1294 dispatch(s, pos2);
1295 push();
1297 else {
1298 dispatch(s, pos1);
1302 break;
1304 case NODE_AND:
1306 int pos;
1308 codegen(s, tree->car, VAL);
1309 pos = new_label(s);
1310 pop();
1311 genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0));
1312 codegen(s, tree->cdr, val);
1313 dispatch(s, pos);
1315 break;
1317 case NODE_OR:
1319 int pos;
1321 codegen(s, tree->car, VAL);
1322 pos = new_label(s);
1323 pop();
1324 genop(s, MKOP_AsBx(OP_JMPIF, cursp(), 0));
1325 codegen(s, tree->cdr, val);
1326 dispatch(s, pos);
1328 break;
1330 case NODE_WHILE:
1332 struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
1334 lp->pc1 = new_label(s);
1335 genop(s, MKOP_sBx(OP_JMP, 0));
1336 lp->pc2 = new_label(s);
1337 codegen(s, tree->cdr, NOVAL);
1338 dispatch(s, lp->pc1);
1339 codegen(s, tree->car, VAL);
1340 pop();
1341 genop(s, MKOP_AsBx(OP_JMPIF, cursp(), lp->pc2 - s->pc));
1343 loop_pop(s, val);
1345 break;
1347 case NODE_UNTIL:
1349 struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
1351 lp->pc1 = new_label(s);
1352 genop(s, MKOP_sBx(OP_JMP, 0));
1353 lp->pc2 = new_label(s);
1354 codegen(s, tree->cdr, NOVAL);
1355 dispatch(s, lp->pc1);
1356 codegen(s, tree->car, VAL);
1357 pop();
1358 genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), lp->pc2 - s->pc));
1360 loop_pop(s, val);
1362 break;
1364 case NODE_FOR:
1365 for_body(s, tree);
1366 if (val) push();
1367 break;
1369 case NODE_CASE:
1371 int head = 0;
1372 int pos1, pos2, pos3, tmp;
1373 node *n;
1375 pos3 = 0;
1376 if (tree->car) {
1377 head = cursp();
1378 codegen(s, tree->car, VAL);
1380 tree = tree->cdr;
1381 while (tree) {
1382 n = tree->car->car;
1383 pos1 = pos2 = 0;
1384 while (n) {
1385 codegen(s, n->car, VAL);
1386 if (head) {
1387 genop(s, MKOP_AB(OP_MOVE, cursp(), head));
1388 pop();
1389 if ((intptr_t)n->car->car == NODE_SPLAT) {
1390 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1));
1392 else {
1393 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "===")), 1));
1396 else {
1397 pop();
1399 tmp = new_label(s);
1400 genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2));
1401 pos2 = tmp;
1402 n = n->cdr;
1404 if (tree->car->car) {
1405 pos1 = new_label(s);
1406 genop(s, MKOP_sBx(OP_JMP, 0));
1407 dispatch_linked(s, pos2);
1409 codegen(s, tree->car->cdr, val);
1410 if (val) pop();
1411 tmp = new_label(s);
1412 genop(s, MKOP_sBx(OP_JMP, pos3));
1413 pos3 = tmp;
1414 if (pos1) dispatch(s, pos1);
1415 tree = tree->cdr;
1417 if (val) {
1418 int pos = cursp();
1419 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1420 if (pos3) dispatch_linked(s, pos3);
1421 pop();
1422 genop(s, MKOP_AB(OP_MOVE, cursp(), pos));
1423 push();
1425 else if (pos3) {
1426 dispatch_linked(s, pos3);
1429 break;
1431 case NODE_SCOPE:
1432 scope_body(s, tree, NOVAL);
1433 break;
1435 case NODE_FCALL:
1436 case NODE_CALL:
1437 gen_call(s, tree, 0, 0, val);
1438 break;
1440 case NODE_DOT2:
1441 codegen(s, tree->car, val);
1442 codegen(s, tree->cdr, val);
1443 if (val) {
1444 pop(); pop();
1445 genop(s, MKOP_ABC(OP_RANGE, cursp(), cursp(), 0));
1446 push();
1448 break;
1450 case NODE_DOT3:
1451 codegen(s, tree->car, val);
1452 codegen(s, tree->cdr, val);
1453 if (val) {
1454 pop(); pop();
1455 genop(s, MKOP_ABC(OP_RANGE, cursp(), cursp(), 1));
1456 push();
1458 break;
1460 case NODE_COLON2:
1462 int sym = new_sym(s, sym(tree->cdr));
1464 codegen(s, tree->car, VAL);
1465 pop();
1466 genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
1467 if (val) push();
1469 break;
1471 case NODE_COLON3:
1473 int sym = new_sym(s, sym(tree));
1475 genop(s, MKOP_A(OP_OCLASS, cursp()));
1476 genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
1477 if (val) push();
1479 break;
1481 case NODE_ARRAY:
1483 int n;
1485 n = gen_values(s, tree, val);
1486 if (n >= 0) {
1487 if (val) {
1488 pop_n(n);
1489 genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), n));
1490 push();
1493 else if (val) {
1494 push();
1497 break;
1499 case NODE_HASH:
1501 int len = 0;
1503 while (tree) {
1504 codegen(s, tree->car->car, val);
1505 codegen(s, tree->car->cdr, val);
1506 len++;
1507 tree = tree->cdr;
1509 if (val) {
1510 pop_n(len*2);
1511 genop(s, MKOP_ABC(OP_HASH, cursp(), cursp(), len));
1512 push();
1515 break;
1517 case NODE_SPLAT:
1519 int idx = new_msym(s, mrb_intern_lit(s->mrb, "to_a"));
1521 codegen(s, tree, VAL);
1522 pop();
1523 genop(s, MKOP_ABC(OP_SEND, cursp(), idx, 0));
1524 push();
1526 break;
1528 case NODE_ASGN:
1529 codegen(s, tree->cdr, VAL);
1530 pop();
1531 gen_assignment(s, tree->car, cursp(), val);
1532 break;
1534 case NODE_MASGN:
1536 int len = 0, n = 0, post = 0;
1537 node *t = tree->cdr, *p;
1538 int rhs = cursp();
1540 if ((intptr_t)t->car == NODE_ARRAY && nosplat(t->cdr)) {
1541 // fixed rhs
1542 t = t->cdr;
1543 while (t) {
1544 codegen(s, t->car, VAL);
1545 len++;
1546 t = t->cdr;
1548 tree = tree->car;
1549 if (tree->car) { /* pre */
1550 t = tree->car;
1551 n = 0;
1552 while (t) {
1553 gen_assignment(s, t->car, rhs+n, NOVAL);
1554 n++;
1555 t = t->cdr;
1558 t = tree->cdr;
1559 if (t) {
1560 if (t->cdr) { /* post count */
1561 p = t->cdr->car;
1562 while (p) {
1563 post++;
1564 p = p->cdr;
1567 if (t->car) { /* rest (len - pre - post) */
1568 int rn = len - post - n;
1570 genop(s, MKOP_ABC(OP_ARRAY, cursp(), rhs+n, rn));
1571 gen_assignment(s, t->car, cursp(), NOVAL);
1572 n += rn;
1574 if (t->cdr && t->cdr->car) {
1575 t = t->cdr->car;
1576 while (n<len) {
1577 gen_assignment(s, t->car, rhs+n, NOVAL);
1578 t = t->cdr;
1579 n++;
1583 pop_n(len);
1584 if (val) {
1585 genop(s, MKOP_ABC(OP_ARRAY, rhs, rhs, len));
1586 push();
1589 else {
1590 // variable rhs
1591 codegen(s, t, VAL);
1592 gen_vmassignment(s, tree->car, rhs, val);
1595 break;
1597 case NODE_OP_ASGN:
1599 mrb_sym sym = sym(tree->cdr->car);
1600 size_t len;
1601 const char *name = mrb_sym2name_len(s->mrb, sym, &len);
1602 int idx;
1604 codegen(s, tree->car, VAL);
1605 if (len == 2 &&
1606 ((name[0] == '|' && name[1] == '|') ||
1607 (name[0] == '&' && name[1] == '&'))) {
1608 int pos;
1610 pop();
1611 pos = new_label(s);
1612 genop(s, MKOP_AsBx(name[0] == '|' ? OP_JMPIF : OP_JMPNOT, cursp(), 0));
1613 codegen(s, tree->cdr->cdr->car, VAL);
1614 pop();
1615 gen_assignment(s, tree->car, cursp(), val);
1616 dispatch(s, pos);
1617 break;
1619 codegen(s, tree->cdr->cdr->car, VAL);
1620 pop(); pop();
1622 idx = new_msym(s, sym);
1623 if (len == 1 && name[0] == '+') {
1624 genop_peep(s, MKOP_ABC(OP_ADD, cursp(), idx, 1), val);
1626 else if (len == 1 && name[0] == '-') {
1627 genop_peep(s, MKOP_ABC(OP_SUB, cursp(), idx, 1), val);
1629 else if (len == 1 && name[0] == '*') {
1630 genop(s, MKOP_ABC(OP_MUL, cursp(), idx, 1));
1632 else if (len == 1 && name[0] == '/') {
1633 genop(s, MKOP_ABC(OP_DIV, cursp(), idx, 1));
1635 else if (len == 1 && name[0] == '<') {
1636 genop(s, MKOP_ABC(OP_LT, cursp(), idx, 1));
1638 else if (len == 2 && name[0] == '<' && name[1] == '=') {
1639 genop(s, MKOP_ABC(OP_LE, cursp(), idx, 1));
1641 else if (len == 1 && name[0] == '>') {
1642 genop(s, MKOP_ABC(OP_GT, cursp(), idx, 1));
1644 else if (len == 2 && name[0] == '>' && name[1] == '=') {
1645 genop(s, MKOP_ABC(OP_GE, cursp(), idx, 1));
1647 else {
1648 genop(s, MKOP_ABC(OP_SEND, cursp(), idx, 1));
1651 gen_assignment(s, tree->car, cursp(), val);
1652 break;
1654 case NODE_SUPER:
1656 int n = 0, noop = 0, sendv = 0;
1658 push(); /* room for receiver */
1659 if (tree) {
1660 node *args = tree->car;
1661 if (args) {
1662 n = gen_values(s, args, VAL);
1663 if (n < 0) {
1664 n = noop = sendv = 1;
1665 push();
1669 if (tree && tree->cdr) {
1670 codegen(s, tree->cdr, VAL);
1671 pop();
1673 else {
1674 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1676 pop_n(n+1);
1677 if (sendv) n = CALL_MAXARGS;
1678 genop(s, MKOP_ABC(OP_SUPER, cursp(), 0, n));
1679 if (val) push();
1681 break;
1683 case NODE_ZSUPER:
1685 codegen_scope *s2 = s;
1686 int lv = 0, ainfo = 0;
1688 push(); /* room for receiver */
1689 while (!s2->mscope) {
1690 lv++;
1691 s2 = s2->prev;
1692 if (!s2) break;
1694 if (s2) ainfo = s2->ainfo;
1695 genop(s, MKOP_ABx(OP_ARGARY, cursp(), (ainfo<<4)|(lv & 0xf)));
1696 if (tree && tree->cdr) {
1697 push();
1698 codegen(s, tree->cdr, VAL);
1699 pop_n(2);
1701 pop();
1702 genop(s, MKOP_ABC(OP_SUPER, cursp(), 0, CALL_MAXARGS));
1703 if (val) push();
1705 break;
1707 case NODE_RETURN:
1708 if (tree) {
1709 codegen(s, tree, VAL);
1710 pop();
1712 else {
1713 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1715 if (s->loop) {
1716 genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_RETURN));
1718 else {
1719 genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
1721 if (val) push();
1722 break;
1724 case NODE_YIELD:
1726 codegen_scope *s2 = s;
1727 int lv = 0, ainfo = 0;
1728 int n = 0, sendv = 0;
1730 while (!s2->mscope) {
1731 lv++;
1732 s2 = s2->prev;
1733 if (!s2) break;
1735 if (s2) ainfo = s2->ainfo;
1736 genop(s, MKOP_ABx(OP_BLKPUSH, cursp(), (ainfo<<4)|(lv & 0xf)));
1737 push();
1738 if (tree) {
1739 n = gen_values(s, tree, VAL);
1740 if (n < 0) {
1741 n = sendv = 1;
1742 push();
1745 pop_n(n+1);
1746 if (sendv) n = CALL_MAXARGS;
1747 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "call")), n));
1748 if (val) push();
1750 break;
1752 case NODE_BREAK:
1753 loop_break(s, tree);
1754 if (val) push();
1755 break;
1757 case NODE_NEXT:
1758 if (!s->loop) {
1759 raise_error(s, "unexpected next");
1761 else if (s->loop->type == LOOP_NORMAL) {
1762 if (s->ensure_level > s->loop->ensure_level) {
1763 genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL);
1765 codegen(s, tree, NOVAL);
1766 genop(s, MKOP_sBx(OP_JMP, s->loop->pc1 - s->pc));
1768 else {
1769 if (tree) {
1770 codegen(s, tree, VAL);
1771 pop();
1773 else {
1774 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1776 genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
1778 if (val) push();
1779 break;
1781 case NODE_REDO:
1782 if (!s->loop) {
1783 raise_error(s, "unexpected redo");
1785 else {
1786 if (s->ensure_level > s->loop->ensure_level) {
1787 genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL);
1789 genop(s, MKOP_sBx(OP_JMP, s->loop->pc2 - s->pc));
1791 break;
1793 case NODE_RETRY:
1795 const char *msg = "unexpected retry";
1797 if (!s->loop) {
1798 raise_error(s, msg);
1800 else {
1801 struct loopinfo *lp = s->loop;
1802 int n = 0;
1804 while (lp && lp->type != LOOP_RESCUE) {
1805 if (lp->type == LOOP_BEGIN) {
1806 n++;
1808 lp = lp->prev;
1810 if (!lp) {
1811 raise_error(s, msg);
1813 else {
1814 if (n > 0) {
1815 while (n--) {
1816 genop_peep(s, MKOP_A(OP_POPERR, 1), NOVAL);
1819 if (s->ensure_level > lp->ensure_level) {
1820 genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - lp->ensure_level), NOVAL);
1822 genop(s, MKOP_sBx(OP_JMP, lp->pc1 - s->pc));
1826 break;
1828 case NODE_LVAR:
1829 if (val) {
1830 int idx = lv_idx(s, sym(tree));
1832 if (idx > 0) {
1833 genop(s, MKOP_AB(OP_MOVE, cursp(), idx));
1835 else {
1836 int lv = 0;
1837 codegen_scope *up = s->prev;
1839 while (up) {
1840 idx = lv_idx(up, sym(tree));
1841 if (idx > 0) {
1842 genop(s, MKOP_ABC(OP_GETUPVAR, cursp(), idx, lv));
1843 break;
1845 lv++;
1846 up = up->prev;
1849 push();
1851 break;
1853 case NODE_GVAR:
1855 int sym = new_sym(s, sym(tree));
1857 genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
1858 push();
1860 break;
1862 case NODE_IVAR:
1864 int sym = new_sym(s, sym(tree));
1866 genop(s, MKOP_ABx(OP_GETIV, cursp(), sym));
1867 push();
1869 break;
1871 case NODE_CVAR:
1873 int sym = new_sym(s, sym(tree));
1875 genop(s, MKOP_ABx(OP_GETCV, cursp(), sym));
1876 push();
1878 break;
1880 case NODE_CONST:
1882 int sym = new_sym(s, sym(tree));
1884 genop(s, MKOP_ABx(OP_GETCONST, cursp(), sym));
1885 push();
1887 break;
1889 case NODE_DEFINED:
1890 codegen(s, tree, VAL);
1891 break;
1893 case NODE_BACK_REF:
1895 char buf[2] = { '$' };
1896 mrb_value str;
1897 int sym;
1899 buf[1] = (char)(intptr_t)tree;
1900 str = mrb_str_new(s->mrb, buf, 2);
1901 sym = new_sym(s, mrb_intern_str(s->mrb, str));
1902 genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
1903 push();
1905 break;
1907 case NODE_NTH_REF:
1909 int sym;
1910 mrb_state *mrb = s->mrb;
1911 mrb_value fix = mrb_fixnum_value((intptr_t)tree);
1912 mrb_value str = mrb_str_buf_new(mrb, 4);
1914 mrb_str_buf_cat(mrb, str, "$", 1);
1915 mrb_str_buf_append(mrb, str, mrb_fixnum_to_str(mrb, fix, 10));
1916 sym = new_sym(s, mrb_intern_str(mrb, str));
1917 genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
1918 push();
1920 break;
1922 case NODE_ARG:
1923 // should not happen
1924 break;
1926 case NODE_BLOCK_ARG:
1927 codegen(s, tree, VAL);
1928 break;
1930 case NODE_INT:
1931 if (val) {
1932 char *p = (char*)tree->car;
1933 int base = (intptr_t)tree->cdr->car;
1934 mrb_int i;
1935 mrb_code co;
1936 int overflow;
1938 i = readint_mrb_int(s, p, base, FALSE, &overflow);
1939 if (overflow) {
1940 double f = readint_float(s, p, base);
1941 int off = new_lit(s, mrb_float_value(s->mrb, f));
1943 genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
1945 else {
1946 if (i < MAXARG_sBx && i > -MAXARG_sBx) {
1947 co = MKOP_AsBx(OP_LOADI, cursp(), i);
1949 else {
1950 int off = new_lit(s, mrb_fixnum_value(i));
1951 co = MKOP_ABx(OP_LOADL, cursp(), off);
1953 genop(s, co);
1955 push();
1957 break;
1959 case NODE_FLOAT:
1960 if (val) {
1961 char *p = (char*)tree;
1962 mrb_float f = str_to_mrb_float(p);
1963 int off = new_lit(s, mrb_float_value(s->mrb, f));
1965 genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
1966 push();
1968 break;
1970 case NODE_NEGATE:
1972 nt = (intptr_t)tree->car;
1973 tree = tree->cdr;
1974 switch (nt) {
1975 case NODE_FLOAT:
1977 char *p = (char*)tree;
1978 mrb_float f = str_to_mrb_float(p);
1979 int off = new_lit(s, mrb_float_value(s->mrb, -f));
1981 genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
1982 push();
1984 break;
1986 case NODE_INT:
1988 char *p = (char*)tree->car;
1989 int base = (intptr_t)tree->cdr->car;
1990 mrb_int i;
1991 mrb_code co;
1992 int overflow;
1994 i = readint_mrb_int(s, p, base, TRUE, &overflow);
1995 if (overflow) {
1996 double f = readint_float(s, p, base);
1997 int off = new_lit(s, mrb_float_value(s->mrb, -f));
1999 genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
2001 else {
2002 if (i < MAXARG_sBx && i > -MAXARG_sBx) {
2003 co = MKOP_AsBx(OP_LOADI, cursp(), i);
2005 else {
2006 int off = new_lit(s, mrb_fixnum_value(i));
2007 co = MKOP_ABx(OP_LOADL, cursp(), off);
2009 genop(s, co);
2011 push();
2013 break;
2015 default:
2017 int sym = new_msym(s, mrb_intern_lit(s->mrb, "-"));
2019 genop(s, MKOP_ABx(OP_LOADI, cursp(), 0));
2020 push();
2021 codegen(s, tree, VAL);
2022 pop(); pop();
2023 genop(s, MKOP_ABC(OP_SUB, cursp(), sym, 2));
2025 break;
2028 break;
2030 case NODE_STR:
2031 if (val) {
2032 char *p = (char*)tree->car;
2033 size_t len = (intptr_t)tree->cdr;
2034 int ai = mrb_gc_arena_save(s->mrb);
2035 int off = new_lit(s, mrb_str_new(s->mrb, p, len));
2037 mrb_gc_arena_restore(s->mrb, ai);
2038 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2039 push();
2041 break;
2043 case NODE_HEREDOC:
2044 tree = ((struct mrb_parser_heredoc_info *)tree)->doc;
2045 /* fall through */
2046 case NODE_DSTR:
2047 if (val) {
2048 node *n = tree;
2050 codegen(s, n->car, VAL);
2051 n = n->cdr;
2052 while (n) {
2053 codegen(s, n->car, VAL);
2054 pop(); pop();
2055 genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
2056 push();
2057 n = n->cdr;
2060 else {
2061 node *n = tree;
2063 while (n) {
2064 if ((intptr_t)n->car->car != NODE_STR) {
2065 codegen(s, n->car, NOVAL);
2067 n = n->cdr;
2070 break;
2072 case NODE_WORDS:
2073 gen_literal_array(s, tree, FALSE, val);
2074 break;
2076 case NODE_SYMBOLS:
2077 gen_literal_array(s, tree, TRUE, val);
2078 break;
2080 case NODE_XSTR:
2081 if (val) {
2082 char *p = (char*)tree->car;
2083 size_t len = (intptr_t)tree->cdr;
2084 int ai = mrb_gc_arena_save(s->mrb);
2085 int sym = new_sym(s, mrb_intern_lit(s->mrb, "Kernel"));
2086 int off = new_lit(s, mrb_str_new(s->mrb, p, len));
2088 genop(s, MKOP_A(OP_OCLASS, cursp()));
2089 genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
2090 push();
2091 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2092 pop();
2093 sym = new_sym(s, mrb_intern_lit(s->mrb, "`"));
2094 genop(s, MKOP_ABC(OP_SEND, cursp(), sym, 1));
2095 mrb_gc_arena_restore(s->mrb, ai);
2096 push();
2098 break;
2100 case NODE_REGX:
2101 if (val) {
2102 char *p1 = (char*)tree->car;
2103 char *p2 = (char*)tree->cdr;
2104 int ai = mrb_gc_arena_save(s->mrb);
2105 int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS));
2106 int off = new_lit(s, mrb_str_new(s->mrb, p1, strlen(p1)));
2107 int argc = 1;
2109 genop(s, MKOP_A(OP_OCLASS, cursp()));
2110 genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
2111 push();
2112 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2113 if (p2) {
2114 push();
2115 off = new_lit(s, mrb_str_new(s->mrb, p2, strlen(p2)));
2116 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2117 argc++;
2118 pop();
2120 pop();
2121 sym = new_sym(s, mrb_intern_lit(s->mrb, "compile"));
2122 genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc));
2123 mrb_gc_arena_restore(s->mrb, ai);
2124 push();
2126 break;
2128 case NODE_DREGX:
2129 if (val) {
2130 node *n = tree->car;
2131 int ai = mrb_gc_arena_save(s->mrb);
2132 int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS));
2133 int argc = 1;
2134 int off;
2135 char *p;
2137 genop(s, MKOP_A(OP_OCLASS, cursp()));
2138 genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
2139 push();
2140 codegen(s, n->car, VAL);
2141 n = n->cdr;
2142 while (n) {
2143 codegen(s, n->car, VAL);
2144 pop(); pop();
2145 genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
2146 push();
2147 n = n->cdr;
2149 n = tree->cdr->cdr;
2150 if (n->car) {
2151 p = (char*)n->car;
2152 off = new_lit(s, mrb_str_new(s->mrb, p, strlen(p)));
2153 codegen(s, tree->car, VAL);
2154 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2155 pop();
2156 genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
2158 if (n->cdr) {
2159 char *p2 = (char*)n->cdr;
2160 int off;
2162 push();
2163 off = new_lit(s, mrb_str_new(s->mrb, p2, strlen(p2)));
2164 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2165 argc++;
2166 pop();
2168 pop();
2169 sym = new_sym(s, mrb_intern_lit(s->mrb, "compile"));
2170 genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc));
2171 mrb_gc_arena_restore(s->mrb, ai);
2172 push();
2174 else {
2175 node *n = tree->car;
2177 while (n) {
2178 if ((intptr_t)n->car->car != NODE_STR) {
2179 codegen(s, n->car, NOVAL);
2181 n = n->cdr;
2184 break;
2186 case NODE_SYM:
2187 if (val) {
2188 int sym = new_sym(s, sym(tree));
2190 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym));
2191 push();
2193 break;
2195 case NODE_DSYM:
2196 codegen(s, tree, val);
2197 if (val) {
2198 gen_send_intern(s);
2200 break;
2202 case NODE_SELF:
2203 if (val) {
2204 genop(s, MKOP_A(OP_LOADSELF, cursp()));
2205 push();
2207 break;
2209 case NODE_NIL:
2210 if (val) {
2211 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2212 push();
2214 break;
2216 case NODE_TRUE:
2217 if (val) {
2218 genop(s, MKOP_A(OP_LOADT, cursp()));
2219 push();
2221 break;
2223 case NODE_FALSE:
2224 if (val) {
2225 genop(s, MKOP_A(OP_LOADF, cursp()));
2226 push();
2228 break;
2230 case NODE_ALIAS:
2232 int a = new_msym(s, sym(tree->car));
2233 int b = new_msym(s, sym(tree->cdr));
2234 int c = new_msym(s, mrb_intern_lit(s->mrb,"alias_method"));
2236 genop(s, MKOP_A(OP_TCLASS, cursp()));
2237 push();
2238 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), a));
2239 push();
2240 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), b));
2241 push();
2242 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2243 pop_n(3);
2244 genop(s, MKOP_ABC(OP_SEND, cursp(), c, 2));
2245 if (val) {
2246 push();
2249 break;
2251 case NODE_UNDEF:
2253 int undef = new_msym(s, mrb_intern_lit(s->mrb, "undef_method"));
2254 int num = 0;
2255 node *t = tree;
2257 genop(s, MKOP_A(OP_TCLASS, cursp()));
2258 push();
2259 while (t) {
2260 int symbol = new_msym(s, sym(t->car));
2261 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), symbol));
2262 push();
2263 t = t->cdr;
2264 num++;
2266 pop_n(num + 1);
2267 genop(s, MKOP_ABC(OP_SEND, cursp(), undef, num));
2268 if (val) {
2269 push();
2272 break;
2274 case NODE_CLASS:
2276 int idx;
2278 if (tree->car->car == (node*)0) {
2279 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2280 push();
2282 else if (tree->car->car == (node*)1) {
2283 genop(s, MKOP_A(OP_OCLASS, cursp()));
2284 push();
2286 else {
2287 codegen(s, tree->car->car, VAL);
2289 if (tree->cdr->car) {
2290 codegen(s, tree->cdr->car, VAL);
2292 else {
2293 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2294 push();
2296 pop(); pop();
2297 idx = new_msym(s, sym(tree->car->cdr));
2298 genop(s, MKOP_AB(OP_CLASS, cursp(), idx));
2299 idx = scope_body(s, tree->cdr->cdr->car, val);
2300 genop(s, MKOP_ABx(OP_EXEC, cursp(), idx));
2301 if (val) {
2302 push();
2305 break;
2307 case NODE_MODULE:
2309 int idx;
2311 if (tree->car->car == (node*)0) {
2312 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2313 push();
2315 else if (tree->car->car == (node*)1) {
2316 genop(s, MKOP_A(OP_OCLASS, cursp()));
2317 push();
2319 else {
2320 codegen(s, tree->car->car, VAL);
2322 pop();
2323 idx = new_msym(s, sym(tree->car->cdr));
2324 genop(s, MKOP_AB(OP_MODULE, cursp(), idx));
2325 idx = scope_body(s, tree->cdr->car, val);
2326 genop(s, MKOP_ABx(OP_EXEC, cursp(), idx));
2327 if (val) {
2328 push();
2331 break;
2333 case NODE_SCLASS:
2335 int idx;
2337 codegen(s, tree->car, VAL);
2338 pop();
2339 genop(s, MKOP_AB(OP_SCLASS, cursp(), cursp()));
2340 idx = scope_body(s, tree->cdr->car, val);
2341 genop(s, MKOP_ABx(OP_EXEC, cursp(), idx));
2342 if (val) {
2343 push();
2346 break;
2348 case NODE_DEF:
2350 int sym = new_msym(s, sym(tree->car));
2351 int idx = lambda_body(s, tree->cdr, 0);
2353 genop(s, MKOP_A(OP_TCLASS, cursp()));
2354 push();
2355 genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_METHOD));
2356 pop();
2357 genop(s, MKOP_AB(OP_METHOD, cursp(), sym));
2358 if (val) {
2359 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym));
2360 push();
2363 break;
2365 case NODE_SDEF:
2367 node *recv = tree->car;
2368 int sym = new_msym(s, sym(tree->cdr->car));
2369 int idx = lambda_body(s, tree->cdr->cdr, 0);
2371 codegen(s, recv, VAL);
2372 pop();
2373 genop(s, MKOP_AB(OP_SCLASS, cursp(), cursp()));
2374 push();
2375 genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_METHOD));
2376 pop();
2377 genop(s, MKOP_AB(OP_METHOD, cursp(), sym));
2378 if (val) {
2379 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym));
2380 push();
2383 break;
2385 case NODE_POSTEXE:
2386 codegen(s, tree, NOVAL);
2387 break;
2389 default:
2390 break;
2394 static void
2395 scope_add_irep(codegen_scope *s, mrb_irep *irep)
2397 if (s->irep == NULL) {
2398 s->irep = irep;
2399 return;
2401 if (s->irep->rlen == s->rcapa) {
2402 s->rcapa *= 2;
2403 s->irep->reps = (mrb_irep**)codegen_realloc(s, s->irep->reps, sizeof(mrb_irep*)*s->rcapa);
2405 s->irep->reps[s->irep->rlen] = irep;
2406 s->irep->rlen++;
2409 static codegen_scope*
2410 scope_new(mrb_state *mrb, codegen_scope *prev, node *lv)
2412 static const codegen_scope codegen_scope_zero = { 0 };
2413 mrb_pool *pool = mrb_pool_open(mrb);
2414 codegen_scope *p = (codegen_scope *)mrb_pool_alloc(pool, sizeof(codegen_scope));
2416 if (!p) return 0;
2417 *p = codegen_scope_zero;
2418 p->mrb = mrb;
2419 p->mpool = pool;
2420 if (!prev) return p;
2421 p->prev = prev;
2422 p->ainfo = -1;
2423 p->mscope = 0;
2425 p->irep = mrb_add_irep(mrb);
2426 scope_add_irep(prev, p->irep);
2428 p->rcapa = 8;
2429 p->irep->reps = (mrb_irep**)mrb_malloc(mrb, sizeof(mrb_irep*)*p->rcapa);
2431 p->icapa = 1024;
2432 p->iseq = (mrb_code*)mrb_malloc(mrb, sizeof(mrb_code)*p->icapa);
2433 p->irep->iseq = p->iseq;
2435 p->pcapa = 32;
2436 p->irep->pool = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value)*p->pcapa);
2437 p->irep->plen = 0;
2439 p->scapa = 256;
2440 p->irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*p->scapa);
2441 p->irep->slen = 0;
2443 p->lv = lv;
2444 p->sp += node_len(lv)+1; /* add self */
2445 p->nlocals = p->sp;
2446 p->ai = mrb_gc_arena_save(mrb);
2448 p->filename = prev->filename;
2449 if (p->filename) {
2450 p->lines = (uint16_t*)mrb_malloc(mrb, sizeof(short)*p->icapa);
2452 p->lineno = prev->lineno;
2454 // debug setting
2455 p->debug_start_pos = 0;
2456 if(p->filename) {
2457 mrb_debug_info_alloc(mrb, p->irep);
2458 p->irep->filename = p->filename;
2459 p->irep->lines = p->lines;
2461 else {
2462 p->irep->debug_info = NULL;
2464 p->parser = prev->parser;
2465 p->filename_index = prev->filename_index;
2467 return p;
2470 static void
2471 scope_finish(codegen_scope *s)
2473 mrb_state *mrb = s->mrb;
2474 mrb_irep *irep = s->irep;
2475 size_t fname_len;
2476 char *fname;
2478 irep->flags = 0;
2479 if (s->iseq) {
2480 irep->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc);
2481 irep->ilen = s->pc;
2482 if (s->lines) {
2483 irep->lines = (uint16_t *)codegen_realloc(s, s->lines, sizeof(uint16_t)*s->pc);
2485 else {
2486 irep->lines = 0;
2489 irep->pool = (mrb_value*)codegen_realloc(s, irep->pool, sizeof(mrb_value)*irep->plen);
2490 irep->syms = (mrb_sym*)codegen_realloc(s, irep->syms, sizeof(mrb_sym)*irep->slen);
2491 irep->reps = (mrb_irep**)codegen_realloc(s, irep->reps, sizeof(mrb_irep*)*irep->rlen);
2492 if (s->filename) {
2493 s->irep->filename = mrb_parser_get_filename(s->parser, s->filename_index);
2494 mrb_debug_info_append_file(mrb, s->irep, s->debug_start_pos, s->pc);
2496 fname_len = strlen(s->filename);
2497 fname = codegen_malloc(s, fname_len + 1);
2498 memcpy(fname, s->filename, fname_len);
2499 fname[fname_len] = '\0';
2500 irep->filename = fname;
2503 irep->nlocals = s->nlocals;
2504 irep->nregs = s->nregs;
2506 mrb_gc_arena_restore(mrb, s->ai);
2507 mrb_pool_close(s->mpool);
2510 static struct loopinfo*
2511 loop_push(codegen_scope *s, enum looptype t)
2513 struct loopinfo *p = (struct loopinfo *)codegen_palloc(s, sizeof(struct loopinfo));
2515 p->type = t;
2516 p->pc1 = p->pc2 = p->pc3 = 0;
2517 p->prev = s->loop;
2518 p->ensure_level = s->ensure_level;
2519 p->acc = cursp();
2520 s->loop = p;
2522 return p;
2525 static void
2526 loop_break(codegen_scope *s, node *tree)
2528 if (!s->loop) {
2529 codegen(s, tree, NOVAL);
2530 raise_error(s, "unexpected break");
2532 else {
2533 struct loopinfo *loop;
2535 if (tree) {
2536 codegen(s, tree, VAL);
2537 pop();
2540 loop = s->loop;
2541 while (loop->type == LOOP_BEGIN) {
2542 genop_peep(s, MKOP_A(OP_POPERR, 1), NOVAL);
2543 loop = loop->prev;
2545 while (loop->type == LOOP_RESCUE) {
2546 loop = loop->prev;
2548 if (loop->type == LOOP_NORMAL) {
2549 int tmp;
2551 if (s->ensure_level > s->loop->ensure_level) {
2552 genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL);
2554 if (tree) {
2555 genop_peep(s, MKOP_AB(OP_MOVE, loop->acc, cursp()), NOVAL);
2557 tmp = new_label(s);
2558 genop(s, MKOP_sBx(OP_JMP, loop->pc3));
2559 loop->pc3 = tmp;
2561 else {
2562 genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_BREAK));
2567 static void
2568 loop_pop(codegen_scope *s, int val)
2570 if (val) {
2571 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2573 dispatch_linked(s, s->loop->pc3);
2574 s->loop = s->loop->prev;
2575 if (val) push();
2578 static void
2579 codedump(mrb_state *mrb, mrb_irep *irep)
2581 #ifdef ENABLE_STDIO
2582 uint32_t i;
2583 int ai;
2584 mrb_code c;
2586 if (!irep) return;
2587 printf("irep %p nregs=%d nlocals=%d pools=%d syms=%d reps=%d\n", irep,
2588 irep->nregs, irep->nlocals, (int)irep->plen, (int)irep->slen, (int)irep->rlen);
2589 for (i=0; i<irep->ilen; i++) {
2590 ai = mrb_gc_arena_save(mrb);
2591 printf("%03d ", i);
2592 c = irep->iseq[i];
2593 switch (GET_OPCODE(c)) {
2594 case OP_NOP:
2595 printf("OP_NOP\n");
2596 break;
2597 case OP_MOVE:
2598 printf("OP_MOVE\tR%d\tR%d\n", GETARG_A(c), GETARG_B(c));
2599 break;
2600 case OP_LOADL:
2601 printf("OP_LOADL\tR%d\tL(%d)\n", GETARG_A(c), GETARG_Bx(c));
2602 break;
2603 case OP_LOADI:
2604 printf("OP_LOADI\tR%d\t%d\n", GETARG_A(c), GETARG_sBx(c));
2605 break;
2606 case OP_LOADSYM:
2607 printf("OP_LOADSYM\tR%d\t:%s\n", GETARG_A(c),
2608 mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
2609 break;
2610 case OP_LOADNIL:
2611 printf("OP_LOADNIL\tR%d\n", GETARG_A(c));
2612 break;
2613 case OP_LOADSELF:
2614 printf("OP_LOADSELF\tR%d\n", GETARG_A(c));
2615 break;
2616 case OP_LOADT:
2617 printf("OP_LOADT\tR%d\n", GETARG_A(c));
2618 break;
2619 case OP_LOADF:
2620 printf("OP_LOADF\tR%d\n", GETARG_A(c));
2621 break;
2622 case OP_GETGLOBAL:
2623 printf("OP_GETGLOBAL\tR%d\t:%s\n", GETARG_A(c),
2624 mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
2625 break;
2626 case OP_SETGLOBAL:
2627 printf("OP_SETGLOBAL\t:%s\tR%d\n",
2628 mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
2629 GETARG_A(c));
2630 break;
2631 case OP_GETCONST:
2632 printf("OP_GETCONST\tR%d\t:%s\n", GETARG_A(c),
2633 mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
2634 break;
2635 case OP_SETCONST:
2636 printf("OP_SETCONST\t:%s\tR%d\n",
2637 mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
2638 GETARG_A(c));
2639 break;
2640 case OP_GETMCNST:
2641 printf("OP_GETMCNST\tR%d\tR%d::%s\n", GETARG_A(c), GETARG_A(c),
2642 mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
2643 break;
2644 case OP_SETMCNST:
2645 printf("OP_SETMCNST\tR%d::%s\tR%d\n", GETARG_A(c)+1,
2646 mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
2647 GETARG_A(c));
2648 break;
2649 case OP_GETIV:
2650 printf("OP_GETIV\tR%d\t%s\n", GETARG_A(c),
2651 mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
2652 break;
2653 case OP_SETIV:
2654 printf("OP_SETIV\t%s\tR%d\n",
2655 mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
2656 GETARG_A(c));
2657 break;
2658 case OP_GETUPVAR:
2659 printf("OP_GETUPVAR\tR%d\t%d\t%d\n",
2660 GETARG_A(c), GETARG_B(c), GETARG_C(c));
2661 break;
2662 case OP_SETUPVAR:
2663 printf("OP_SETUPVAR\tR%d\t%d\t%d\n",
2664 GETARG_A(c), GETARG_B(c), GETARG_C(c));
2665 break;
2666 case OP_GETCV:
2667 printf("OP_GETCV\tR%d\t%s\n", GETARG_A(c),
2668 mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
2669 break;
2670 case OP_SETCV:
2671 printf("OP_SETCV\t%s\tR%d\n",
2672 mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
2673 GETARG_A(c));
2674 break;
2675 case OP_JMP:
2676 printf("OP_JMP\t\t%03d\n", i+GETARG_sBx(c));
2677 break;
2678 case OP_JMPIF:
2679 printf("OP_JMPIF\tR%d\t%03d\n", GETARG_A(c), i+GETARG_sBx(c));
2680 break;
2681 case OP_JMPNOT:
2682 printf("OP_JMPNOT\tR%d\t%03d\n", GETARG_A(c), i+GETARG_sBx(c));
2683 break;
2684 case OP_SEND:
2685 printf("OP_SEND\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_SENDB:
2690 printf("OP_SENDB\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_TAILCALL:
2695 printf("OP_TAILCALL\tR%d\t:%s\t%d\n", GETARG_A(c),
2696 mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
2697 GETARG_C(c));
2698 break;
2699 case OP_SUPER:
2700 printf("OP_SUPER\tR%d\t%d\n", GETARG_A(c),
2701 GETARG_C(c));
2702 break;
2703 case OP_ARGARY:
2704 printf("OP_ARGARY\tR%d\t%d:%d:%d:%d\n", GETARG_A(c),
2705 (GETARG_Bx(c)>>10)&0x3f,
2706 (GETARG_Bx(c)>>9)&0x1,
2707 (GETARG_Bx(c)>>4)&0x1f,
2708 (GETARG_Bx(c)>>0)&0xf);
2709 break;
2711 case OP_ENTER:
2712 printf("OP_ENTER\t%d:%d:%d:%d:%d:%d:%d\n",
2713 (GETARG_Ax(c)>>18)&0x1f,
2714 (GETARG_Ax(c)>>13)&0x1f,
2715 (GETARG_Ax(c)>>12)&0x1,
2716 (GETARG_Ax(c)>>7)&0x1f,
2717 (GETARG_Ax(c)>>2)&0x1f,
2718 (GETARG_Ax(c)>>1)&0x1,
2719 GETARG_Ax(c) & 0x1);
2720 break;
2721 case OP_RETURN:
2722 printf("OP_RETURN\tR%d", GETARG_A(c));
2723 switch (GETARG_B(c)) {
2724 case OP_R_NORMAL:
2725 printf("\n"); break;
2726 case OP_R_RETURN:
2727 printf("\treturn\n"); break;
2728 case OP_R_BREAK:
2729 printf("\tbreak\n"); break;
2730 default:
2731 printf("\tbroken\n"); break;
2732 break;
2734 break;
2735 case OP_BLKPUSH:
2736 printf("OP_BLKPUSH\tR%d\t%d:%d:%d:%d\n", GETARG_A(c),
2737 (GETARG_Bx(c)>>10)&0x3f,
2738 (GETARG_Bx(c)>>9)&0x1,
2739 (GETARG_Bx(c)>>4)&0x1f,
2740 (GETARG_Bx(c)>>0)&0xf);
2741 break;
2743 case OP_LAMBDA:
2744 printf("OP_LAMBDA\tR%d\tI(%+d)\t%d\n", GETARG_A(c), GETARG_b(c), GETARG_c(c));
2745 break;
2746 case OP_RANGE:
2747 printf("OP_RANGE\tR%d\tR%d\t%d\n", GETARG_A(c), GETARG_B(c), GETARG_C(c));
2748 break;
2749 case OP_METHOD:
2750 printf("OP_METHOD\tR%d\t:%s\n", GETARG_A(c),
2751 mrb_sym2name(mrb, irep->syms[GETARG_B(c)]));
2752 break;
2754 case OP_ADD:
2755 printf("OP_ADD\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_ADDI:
2760 printf("OP_ADDI\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_SUB:
2765 printf("OP_SUB\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_SUBI:
2770 printf("OP_SUBI\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_MUL:
2775 printf("OP_MUL\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_DIV:
2780 printf("OP_DIV\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_LT:
2785 printf("OP_LT\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_LE:
2790 printf("OP_LE\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_GT:
2795 printf("OP_GT\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_GE:
2800 printf("OP_GE\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;
2804 case OP_EQ:
2805 printf("OP_EQ\tR%d\t:%s\t%d\n", GETARG_A(c),
2806 mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
2807 GETARG_C(c));
2808 break;
2810 case OP_STOP:
2811 printf("OP_STOP\n");
2812 break;
2814 case OP_ARRAY:
2815 printf("OP_ARRAY\tR%d\tR%d\t%d\n", GETARG_A(c), GETARG_B(c), GETARG_C(c));
2816 break;
2817 case OP_ARYCAT:
2818 printf("OP_ARYCAT\tR%d\tR%d\n", GETARG_A(c), GETARG_B(c));
2819 break;
2820 case OP_ARYPUSH:
2821 printf("OP_ARYPUSH\tR%d\tR%d\n", GETARG_A(c), GETARG_B(c));
2822 break;
2823 case OP_AREF:
2824 printf("OP_AREF\tR%d\tR%d\t%d\n", GETARG_A(c), GETARG_B(c), GETARG_C(c));
2825 break;
2826 case OP_APOST:
2827 printf("OP_APOST\tR%d\t%d\t%d\n", GETARG_A(c), GETARG_B(c), GETARG_C(c));
2828 break;
2829 case OP_STRING:
2831 mrb_value v = irep->pool[GETARG_Bx(c)];
2832 mrb_value s = mrb_str_dump(mrb, mrb_str_new(mrb, RSTRING_PTR(v), RSTRING_LEN(v)));
2833 printf("OP_STRING\tR%d\t%s\n", GETARG_A(c), RSTRING_PTR(s));
2835 break;
2836 case OP_STRCAT:
2837 printf("OP_STRCAT\tR%d\tR%d\n", GETARG_A(c), GETARG_B(c));
2838 break;
2839 case OP_HASH:
2840 printf("OP_HASH\tR%d\tR%d\t%d\n", GETARG_A(c), GETARG_B(c), GETARG_C(c));
2841 break;
2843 case OP_OCLASS:
2844 printf("OP_OCLASS\tR%d\n", GETARG_A(c));
2845 break;
2846 case OP_CLASS:
2847 printf("OP_CLASS\tR%d\t:%s\n", GETARG_A(c),
2848 mrb_sym2name(mrb, irep->syms[GETARG_B(c)]));
2849 break;
2850 case OP_MODULE:
2851 printf("OP_MODULE\tR%d\t:%s\n", GETARG_A(c),
2852 mrb_sym2name(mrb, irep->syms[GETARG_B(c)]));
2853 break;
2854 case OP_EXEC:
2855 printf("OP_EXEC\tR%d\tI(%+d)\n", GETARG_A(c), GETARG_Bx(c));
2856 break;
2857 case OP_SCLASS:
2858 printf("OP_SCLASS\tR%d\tR%d\n", GETARG_A(c), GETARG_B(c));
2859 break;
2860 case OP_TCLASS:
2861 printf("OP_TCLASS\tR%d\n", GETARG_A(c));
2862 break;
2863 case OP_ERR:
2864 printf("OP_ERR\tL(%d)\n", GETARG_Bx(c));
2865 break;
2866 case OP_EPUSH:
2867 printf("OP_EPUSH\t:I(%+d)\n", GETARG_Bx(c));
2868 break;
2869 case OP_ONERR:
2870 printf("OP_ONERR\t%03d\n", i+GETARG_sBx(c));
2871 break;
2872 case OP_RESCUE:
2873 printf("OP_RESCUE\tR%d\n", GETARG_A(c));
2874 break;
2875 case OP_RAISE:
2876 printf("OP_RAISE\tR%d\n", GETARG_A(c));
2877 break;
2878 case OP_POPERR:
2879 printf("OP_POPERR\t%d\n", GETARG_A(c));
2880 break;
2881 case OP_EPOP:
2882 printf("OP_EPOP\t%d\n", GETARG_A(c));
2883 break;
2885 default:
2886 printf("OP_unknown %d\t%d\t%d\t%d\n", GET_OPCODE(c),
2887 GETARG_A(c), GETARG_B(c), GETARG_C(c));
2888 break;
2890 mrb_gc_arena_restore(mrb, ai);
2892 printf("\n");
2893 #endif
2896 static void
2897 codedump_recur(mrb_state *mrb, mrb_irep *irep)
2899 size_t i;
2901 codedump(mrb, irep);
2902 for (i=0; i<irep->rlen; i++) {
2903 codedump_recur(mrb, irep->reps[i]);
2907 void
2908 codedump_all(mrb_state *mrb, struct RProc *proc)
2910 codedump_recur(mrb, proc->body.irep);
2913 struct RProc*
2914 mrb_generate_code(mrb_state *mrb, parser_state *p)
2916 codegen_scope *scope = scope_new(mrb, 0, 0);
2917 struct RProc *proc;
2919 if (!scope) {
2920 return NULL;
2922 scope->mrb = mrb;
2923 scope->parser = p;
2924 scope->filename = p->filename;
2925 scope->filename_index = p->current_filename_index;
2926 if (setjmp(scope->jmp) == 0) {
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 else {
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;