Fixed register windows of OP_SENDs generated by NODE_{SCALL,CASE,YIELD,UNDEF}; ref...
[mruby.git] / mrbgems / mruby-compiler / core / codegen.c
blob167ceb3cb989adbef0be4fba648f2da19d9c1ecc
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 <mruby/opcode.h>
19 #include <mruby/re.h>
20 #include <mruby/throw.h>
22 #ifndef MRB_CODEGEN_LEVEL_MAX
23 #define MRB_CODEGEN_LEVEL_MAX 1024
24 #endif
26 typedef mrb_ast_node node;
27 typedef struct mrb_parser_state parser_state;
29 enum looptype {
30 LOOP_NORMAL,
31 LOOP_BLOCK,
32 LOOP_FOR,
33 LOOP_BEGIN,
34 LOOP_RESCUE,
37 struct loopinfo {
38 enum looptype type;
39 int pc1, pc2, pc3, acc;
40 int ensure_level;
41 struct loopinfo *prev;
44 typedef struct scope {
45 mrb_state *mrb;
46 mrb_pool *mpool;
47 struct mrb_jmpbuf jmp;
49 struct scope *prev;
51 node *lv;
53 int sp;
54 int pc;
55 int lastlabel;
56 int ainfo:15;
57 mrb_bool mscope:1;
59 struct loopinfo *loop;
60 int ensure_level;
61 char const *filename;
62 uint16_t lineno;
64 mrb_code *iseq;
65 uint16_t *lines;
66 int icapa;
68 mrb_irep *irep;
69 int pcapa, scapa, rcapa;
71 uint16_t nlocals;
72 uint16_t nregs;
73 int ai;
75 int debug_start_pos;
76 uint16_t filename_index;
77 parser_state* parser;
79 int rlev; /* recursion levels */
80 } codegen_scope;
82 static codegen_scope* scope_new(mrb_state *mrb, codegen_scope *prev, node *lv);
83 static void scope_finish(codegen_scope *s);
84 static struct loopinfo *loop_push(codegen_scope *s, enum looptype t);
85 static void loop_break(codegen_scope *s, node *tree);
86 static void loop_pop(codegen_scope *s, int val);
88 static void gen_assignment(codegen_scope *s, node *tree, int sp, int val);
89 static void gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val);
91 static void codegen(codegen_scope *s, node *tree, int val);
92 static void raise_error(codegen_scope *s, const char *msg);
94 static void
95 codegen_error(codegen_scope *s, const char *message)
97 if (!s) return;
98 while (s->prev) {
99 codegen_scope *tmp = s->prev;
100 mrb_free(s->mrb, s->iseq);
101 mrb_pool_close(s->mpool);
102 s = tmp;
104 #ifndef MRB_DISABLE_STDIO
105 if (s->filename && s->lineno) {
106 fprintf(stderr, "codegen error:%s:%d: %s\n", s->filename, s->lineno, message);
108 else {
109 fprintf(stderr, "codegen error: %s\n", message);
111 #endif
112 MRB_THROW(&s->jmp);
115 static void*
116 codegen_palloc(codegen_scope *s, size_t len)
118 void *p = mrb_pool_alloc(s->mpool, len);
120 if (!p) codegen_error(s, "pool memory allocation");
121 return p;
124 static void*
125 codegen_malloc(codegen_scope *s, size_t len)
127 void *p = mrb_malloc_simple(s->mrb, len);
129 if (!p) codegen_error(s, "mrb_malloc");
130 return p;
133 static void*
134 codegen_realloc(codegen_scope *s, void *p, size_t len)
136 p = mrb_realloc_simple(s->mrb, p, len);
138 if (!p && len > 0) codegen_error(s, "mrb_realloc");
139 return p;
142 static int
143 new_label(codegen_scope *s)
145 s->lastlabel = s->pc;
146 return s->pc;
149 static inline int
150 genop(codegen_scope *s, mrb_code i)
152 if (s->pc == s->icapa) {
153 s->icapa *= 2;
154 s->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->icapa);
155 if (s->lines) {
156 s->lines = (uint16_t*)codegen_realloc(s, s->lines, sizeof(short)*s->icapa);
157 s->irep->lines = s->lines;
160 s->iseq[s->pc] = i;
161 if (s->lines) {
162 s->lines[s->pc] = s->lineno;
164 return s->pc++;
167 #define NOVAL 0
168 #define VAL 1
170 static mrb_bool
171 no_optimize(codegen_scope *s)
173 if (s && s->parser && s->parser->no_optimize)
174 return TRUE;
175 return FALSE;
178 static int
179 genop_peep(codegen_scope *s, mrb_code i, int val)
181 /* peephole optimization */
182 if (!no_optimize(s) && s->lastlabel != s->pc && s->pc > 0) {
183 mrb_code i0 = s->iseq[s->pc-1];
184 int c1 = GET_OPCODE(i);
185 int c0 = GET_OPCODE(i0);
187 switch (c1) {
188 case OP_MOVE:
189 if (GETARG_A(i) == GETARG_B(i)) {
190 /* skip useless OP_MOVE */
191 return 0;
193 if (val) break;
194 switch (c0) {
195 case OP_MOVE:
196 if (GETARG_A(i) == GETARG_A(i0)) {
197 /* skip overriden OP_MOVE */
198 s->pc--;
199 s->iseq[s->pc] = i;
201 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i) == GETARG_B(i0)) {
202 /* skip swapping OP_MOVE */
203 return 0;
205 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
206 s->pc--;
207 return genop_peep(s, MKOP_AB(OP_MOVE, GETARG_A(i), GETARG_B(i0)), val);
209 break;
210 case OP_LOADI:
211 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
212 s->iseq[s->pc-1] = MKOP_AsBx(OP_LOADI, GETARG_A(i), GETARG_sBx(i0));
213 return 0;
215 break;
216 case OP_ARRAY:
217 case OP_HASH:
218 case OP_RANGE:
219 case OP_AREF:
220 case OP_GETUPVAR:
221 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
222 s->iseq[s->pc-1] = MKOP_ABC(c0, GETARG_A(i), GETARG_B(i0), GETARG_C(i0));
223 return 0;
225 break;
226 case OP_LOADSYM:
227 case OP_GETGLOBAL:
228 case OP_GETIV:
229 case OP_GETCV:
230 case OP_GETCONST:
231 case OP_GETSPECIAL:
232 case OP_LOADL:
233 case OP_STRING:
234 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
235 s->iseq[s->pc-1] = MKOP_ABx(c0, GETARG_A(i), GETARG_Bx(i0));
236 return 0;
238 break;
239 case OP_SCLASS:
240 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
241 s->iseq[s->pc-1] = MKOP_AB(c0, GETARG_A(i), GETARG_B(i0));
242 return 0;
244 break;
245 case OP_LOADNIL:
246 case OP_LOADSELF:
247 case OP_LOADT:
248 case OP_LOADF:
249 case OP_OCLASS:
250 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
251 s->iseq[s->pc-1] = MKOP_A(c0, GETARG_A(i));
252 return 0;
254 break;
255 default:
256 break;
258 break;
259 case OP_SETIV:
260 case OP_SETCV:
261 case OP_SETCONST:
262 case OP_SETMCNST:
263 case OP_SETGLOBAL:
264 if (val) break;
265 if (c0 == OP_MOVE) {
266 if (GETARG_A(i) == GETARG_A(i0)) {
267 s->iseq[s->pc-1] = MKOP_ABx(c1, GETARG_B(i0), GETARG_Bx(i));
268 return 0;
271 break;
272 case OP_SETUPVAR:
273 if (val) break;
274 if (c0 == OP_MOVE) {
275 if (GETARG_A(i) == GETARG_A(i0)) {
276 s->iseq[s->pc-1] = MKOP_ABC(c1, GETARG_B(i0), GETARG_B(i), GETARG_C(i));
277 return 0;
280 break;
281 case OP_EPOP:
282 if (c0 == OP_EPOP) {
283 s->iseq[s->pc-1] = MKOP_A(OP_EPOP, GETARG_A(i0)+GETARG_A(i));
284 return 0;
286 break;
287 case OP_POPERR:
288 if (c0 == OP_POPERR) {
289 s->iseq[s->pc-1] = MKOP_A(OP_POPERR, GETARG_A(i0)+GETARG_A(i));
290 return 0;
292 break;
293 case OP_RETURN:
294 switch (c0) {
295 case OP_RETURN:
296 return 0;
297 case OP_MOVE:
298 if (GETARG_A(i0) >= s->nlocals) {
299 s->iseq[s->pc-1] = MKOP_AB(OP_RETURN, GETARG_B(i0), OP_R_NORMAL);
300 return 0;
302 break;
303 case OP_SETIV:
304 case OP_SETCV:
305 case OP_SETCONST:
306 case OP_SETMCNST:
307 case OP_SETUPVAR:
308 case OP_SETGLOBAL:
309 s->pc--;
310 genop_peep(s, i0, NOVAL);
311 i0 = s->iseq[s->pc-1];
312 return genop(s, MKOP_AB(OP_RETURN, GETARG_A(i0), OP_R_NORMAL));
313 #if 0
314 case OP_SEND:
315 if (GETARG_B(i) == OP_R_NORMAL && GETARG_A(i) == GETARG_A(i0)) {
316 s->iseq[s->pc-1] = MKOP_ABC(OP_TAILCALL, GETARG_A(i0), GETARG_B(i0), GETARG_C(i0));
317 return;
319 break;
320 #endif
321 default:
322 break;
324 break;
325 case OP_ADD:
326 case OP_SUB:
327 if (c0 == OP_LOADI) {
328 int c = GETARG_sBx(i0);
330 if (c1 == OP_SUB) c = -c;
331 if (c > 127 || c < -127) break;
332 if (0 <= c)
333 s->iseq[s->pc-1] = MKOP_ABC(OP_ADDI, GETARG_A(i), GETARG_B(i), c);
334 else
335 s->iseq[s->pc-1] = MKOP_ABC(OP_SUBI, GETARG_A(i), GETARG_B(i), -c);
336 return 0;
338 case OP_STRCAT:
339 if (c0 == OP_STRING) {
340 mrb_value v = s->irep->pool[GETARG_Bx(i0)];
342 if (mrb_string_p(v) && RSTRING_LEN(v) == 0) {
343 s->pc--;
344 return 0;
347 if (c0 == OP_LOADNIL) {
348 if (GETARG_B(i) == GETARG_A(i0)) {
349 s->pc--;
350 return 0;
353 break;
354 case OP_JMPIF:
355 case OP_JMPNOT:
356 if (c0 == OP_MOVE && GETARG_A(i) == GETARG_A(i0)) {
357 s->iseq[s->pc-1] = MKOP_AsBx(c1, GETARG_B(i0), GETARG_sBx(i));
358 return s->pc-1;
360 break;
361 default:
362 break;
365 return genop(s, i);
368 static void
369 scope_error(codegen_scope *s)
371 exit(EXIT_FAILURE);
374 static inline void
375 dispatch(codegen_scope *s, int pc)
377 int diff = s->pc - pc;
378 mrb_code i = s->iseq[pc];
379 int c = GET_OPCODE(i);
381 s->lastlabel = s->pc;
382 switch (c) {
383 case OP_JMP:
384 case OP_JMPIF:
385 case OP_JMPNOT:
386 case OP_ONERR:
387 break;
388 default:
389 #ifndef MRB_DISABLE_STDIO
390 fprintf(stderr, "bug: dispatch on non JMP op\n");
391 #endif
392 scope_error(s);
393 break;
395 if (diff > MAXARG_sBx) {
396 codegen_error(s, "too distant jump address");
398 s->iseq[pc] = MKOP_AsBx(c, GETARG_A(i), diff);
401 static void
402 dispatch_linked(codegen_scope *s, int pc)
404 mrb_code i;
405 int pos;
407 if (!pc) return;
408 for (;;) {
409 i = s->iseq[pc];
410 pos = GETARG_sBx(i);
411 dispatch(s, pc);
412 if (!pos) break;
413 pc = pos;
417 #define nregs_update do {if (s->sp > s->nregs) s->nregs = s->sp;} while (0)
418 static void
419 push_(codegen_scope *s)
421 if (s->sp > 511) {
422 codegen_error(s, "too complex expression");
424 s->sp++;
425 nregs_update;
428 static void
429 push_n_(codegen_scope *s, int n)
431 if (s->sp+n > 511) {
432 codegen_error(s, "too complex expression");
434 s->sp+=n;
435 nregs_update;
438 #define push() push_(s)
439 #define push_n(n) push_n_(s,n)
440 #define pop_(s) ((s)->sp--)
441 #define pop() pop_(s)
442 #define pop_n(n) (s->sp-=(n))
443 #define cursp() (s->sp)
445 static inline int
446 new_lit(codegen_scope *s, mrb_value val)
448 int i;
449 mrb_value *pv;
451 switch (mrb_type(val)) {
452 case MRB_TT_STRING:
453 for (i=0; i<s->irep->plen; i++) {
454 mrb_int len;
455 pv = &s->irep->pool[i];
457 if (mrb_type(*pv) != MRB_TT_STRING) continue;
458 if ((len = RSTRING_LEN(*pv)) != RSTRING_LEN(val)) continue;
459 if (memcmp(RSTRING_PTR(*pv), RSTRING_PTR(val), len) == 0)
460 return i;
462 break;
463 case MRB_TT_FLOAT:
464 for (i=0; i<s->irep->plen; i++) {
465 pv = &s->irep->pool[i];
466 if (mrb_type(*pv) != MRB_TT_FLOAT) continue;
467 if (mrb_float(*pv) == mrb_float(val)) return i;
469 break;
470 case MRB_TT_FIXNUM:
471 for (i=0; i<s->irep->plen; i++) {
472 pv = &s->irep->pool[i];
473 if (!mrb_fixnum_p(*pv)) continue;
474 if (mrb_fixnum(*pv) == mrb_fixnum(val)) return i;
476 break;
477 default:
478 /* should not happen */
479 return 0;
482 if (s->irep->plen == s->pcapa) {
483 s->pcapa *= 2;
484 s->irep->pool = (mrb_value *)codegen_realloc(s, s->irep->pool, sizeof(mrb_value)*s->pcapa);
487 pv = &s->irep->pool[s->irep->plen];
488 i = s->irep->plen++;
490 switch (mrb_type(val)) {
491 case MRB_TT_STRING:
492 *pv = mrb_str_pool(s->mrb, val);
493 break;
495 case MRB_TT_FLOAT:
496 #ifdef MRB_WORD_BOXING
497 *pv = mrb_float_pool(s->mrb, mrb_float(val));
498 break;
499 #endif
500 case MRB_TT_FIXNUM:
501 *pv = val;
502 break;
504 default:
505 /* should not happen */
506 break;
508 return i;
511 /* method symbols should be fit in 9 bits */
512 #define MAXMSYMLEN 512
513 /* maximum symbol numbers */
514 #define MAXSYMLEN 65536
516 static int
517 new_msym(codegen_scope *s, mrb_sym sym)
519 int i, len;
521 mrb_assert(s->irep);
523 len = s->irep->slen;
524 if (len > MAXMSYMLEN) len = MAXMSYMLEN;
525 for (i=0; i<len; i++) {
526 if (s->irep->syms[i] == sym) return i;
527 if (s->irep->syms[i] == 0) break;
529 if (i == MAXMSYMLEN) {
530 codegen_error(s, "too many symbols (max " MRB_STRINGIZE(MAXMSYMLEN) ")");
532 s->irep->syms[i] = sym;
533 if (i == s->irep->slen) s->irep->slen++;
534 return i;
537 static int
538 new_sym(codegen_scope *s, mrb_sym sym)
540 int i;
542 for (i=0; i<s->irep->slen; i++) {
543 if (s->irep->syms[i] == sym) return i;
545 if (s->irep->slen == MAXSYMLEN) {
546 codegen_error(s, "too many symbols (max " MRB_STRINGIZE(MAXSYMLEN) ")");
549 if (s->irep->slen > MAXMSYMLEN/2 && s->scapa == MAXMSYMLEN) {
550 s->scapa = MAXSYMLEN;
551 s->irep->syms = (mrb_sym *)codegen_realloc(s, s->irep->syms, sizeof(mrb_sym)*MAXSYMLEN);
552 for (i = s->irep->slen; i < MAXMSYMLEN; i++) {
553 static const mrb_sym mrb_sym_zero = { 0 };
554 s->irep->syms[i] = mrb_sym_zero;
556 s->irep->slen = MAXMSYMLEN;
558 s->irep->syms[s->irep->slen] = sym;
559 return s->irep->slen++;
562 static int
563 node_len(node *tree)
565 int n = 0;
567 while (tree) {
568 n++;
569 tree = tree->cdr;
571 return n;
574 #define nsym(x) ((mrb_sym)(intptr_t)(x))
575 #define lv_name(lv) nsym((lv)->car)
576 static int
577 lv_idx(codegen_scope *s, mrb_sym id)
579 node *lv = s->lv;
580 int n = 1;
582 while (lv) {
583 if (lv_name(lv) == id) return n;
584 n++;
585 lv = lv->cdr;
587 return 0;
590 static void
591 for_body(codegen_scope *s, node *tree)
593 codegen_scope *prev = s;
594 int idx;
595 struct loopinfo *lp;
596 node *n2;
597 mrb_code c;
599 /* generate receiver */
600 codegen(s, tree->cdr->car, VAL);
601 /* generate loop-block */
602 s = scope_new(s->mrb, s, NULL);
603 if (s == NULL) {
604 raise_error(prev, "unexpected scope");
607 push(); /* push for a block parameter */
609 /* generate loop variable */
610 n2 = tree->car;
611 genop(s, MKOP_Ax(OP_ENTER, 0x40000));
612 if (n2->car && !n2->car->cdr && !n2->cdr) {
613 gen_assignment(s, n2->car->car, 1, NOVAL);
615 else {
616 gen_vmassignment(s, n2, 1, VAL);
618 /* construct loop */
619 lp = loop_push(s, LOOP_FOR);
620 lp->pc2 = new_label(s);
622 /* loop body */
623 codegen(s, tree->cdr->cdr->car, VAL);
624 pop();
625 if (s->pc > 0) {
626 c = s->iseq[s->pc-1];
627 if (GET_OPCODE(c) != OP_RETURN || GETARG_B(c) != OP_R_NORMAL || s->pc == s->lastlabel)
628 genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
630 loop_pop(s, NOVAL);
631 scope_finish(s);
632 s = prev;
633 genop(s, MKOP_Abc(OP_LAMBDA, cursp(), s->irep->rlen-1, OP_L_BLOCK));
634 pop();
635 idx = new_msym(s, mrb_intern_lit(s->mrb, "each"));
636 genop(s, MKOP_ABC(OP_SENDB, cursp(), idx, 0));
639 static int
640 lambda_body(codegen_scope *s, node *tree, int blk)
642 mrb_code c;
643 codegen_scope *parent = s;
644 s = scope_new(s->mrb, s, tree->car);
645 if (s == NULL) {
646 raise_error(parent, "unexpected scope");
649 s->mscope = !blk;
651 if (blk) {
652 struct loopinfo *lp = loop_push(s, LOOP_BLOCK);
653 lp->pc1 = new_label(s);
655 tree = tree->cdr;
656 if (tree->car) {
657 mrb_aspec a;
658 int ma, oa, ra, pa, ka, kd, ba;
659 int pos, i;
660 node *n, *opt;
662 ma = node_len(tree->car->car);
663 n = tree->car->car;
664 while (n) {
665 n = n->cdr;
667 oa = node_len(tree->car->cdr->car);
668 ra = tree->car->cdr->cdr->car ? 1 : 0;
669 pa = node_len(tree->car->cdr->cdr->cdr->car);
670 ka = kd = 0;
671 ba = tree->car->cdr->cdr->cdr->cdr ? 1 : 0;
673 if (ma > 0x1f || oa > 0x1f || pa > 0x1f || ka > 0x1f) {
674 codegen_error(s, "too many formal arguments");
676 a = ((mrb_aspec)(ma & 0x1f) << 18)
677 | ((mrb_aspec)(oa & 0x1f) << 13)
678 | ((ra & 1) << 12)
679 | ((pa & 0x1f) << 7)
680 | ((ka & 0x1f) << 2)
681 | ((kd & 1)<< 1)
682 | (ba & 1);
683 s->ainfo = (((ma+oa) & 0x3f) << 6) /* (12bits = 6:1:5) */
684 | ((ra & 1) << 5)
685 | (pa & 0x1f);
686 genop(s, MKOP_Ax(OP_ENTER, a));
687 pos = new_label(s);
688 for (i=0; i<oa; i++) {
689 new_label(s);
690 genop(s, MKOP_sBx(OP_JMP, 0));
692 if (oa > 0) {
693 genop(s, MKOP_sBx(OP_JMP, 0));
695 opt = tree->car->cdr->car;
696 i = 0;
697 while (opt) {
698 int idx;
700 dispatch(s, pos+i);
701 codegen(s, opt->car->cdr, VAL);
702 idx = lv_idx(s, nsym(opt->car->car));
703 pop();
704 genop_peep(s, MKOP_AB(OP_MOVE, idx, cursp()), NOVAL);
705 i++;
706 opt = opt->cdr;
708 if (oa > 0) {
709 dispatch(s, pos+i);
712 codegen(s, tree->cdr->car, VAL);
713 pop();
714 if (s->pc > 0) {
715 c = s->iseq[s->pc-1];
716 if (GET_OPCODE(c) != OP_RETURN || GETARG_B(c) != OP_R_NORMAL || s->pc == s->lastlabel) {
717 if (s->nregs == 0) {
718 genop(s, MKOP_A(OP_LOADNIL, 0));
719 genop(s, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
721 else {
722 genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
726 if (blk) {
727 loop_pop(s, NOVAL);
729 scope_finish(s);
730 return parent->irep->rlen - 1;
733 static int
734 scope_body(codegen_scope *s, node *tree, int val)
736 codegen_scope *scope = scope_new(s->mrb, s, tree->car);
737 if (scope == NULL) {
738 raise_error(s, "unexpected scope");
741 codegen(scope, tree->cdr, VAL);
742 if (!s->iseq) {
743 genop(scope, MKOP_A(OP_STOP, 0));
745 else if (!val) {
746 genop(scope, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
748 else {
749 if (scope->nregs == 0) {
750 genop(scope, MKOP_A(OP_LOADNIL, 0));
751 genop(scope, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
753 else {
754 genop_peep(scope, MKOP_AB(OP_RETURN, scope->sp-1, OP_R_NORMAL), NOVAL);
757 scope_finish(scope);
758 if (!s->irep) {
759 /* should not happen */
760 return 0;
762 return s->irep->rlen - 1;
765 #define nint(x) ((int)(intptr_t)(x))
766 #define nchar(x) ((char)(intptr_t)(x))
768 static mrb_bool
769 nosplat(node *t)
771 while (t) {
772 if (nint(t->car->car) == NODE_SPLAT) return FALSE;
773 t = t->cdr;
775 return TRUE;
778 static mrb_sym
779 attrsym(codegen_scope *s, mrb_sym a)
781 const char *name;
782 mrb_int len;
783 char *name2;
785 name = mrb_sym2name_len(s->mrb, a, &len);
786 name2 = (char *)codegen_palloc(s,
787 (size_t)len
788 + 1 /* '=' */
789 + 1 /* '\0' */
791 mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX);
792 memcpy(name2, name, (size_t)len);
793 name2[len] = '=';
794 name2[len+1] = '\0';
796 return mrb_intern(s->mrb, name2, len+1);
799 #define CALL_MAXARGS 127
801 static int
802 gen_values(codegen_scope *s, node *t, int val, int extra)
804 int n = 0;
805 int is_splat;
807 while (t) {
808 is_splat = nint(t->car->car) == NODE_SPLAT; /* splat mode */
809 if (
810 n+extra >= CALL_MAXARGS - 1 /* need to subtract one because vm.c expects an array if n == CALL_MAXARGS */
811 || is_splat) {
812 if (val) {
813 if (is_splat && n == 0 && nint(t->car->cdr->car) == NODE_ARRAY) {
814 codegen(s, t->car->cdr, VAL);
815 pop();
817 else {
818 pop_n(n);
819 genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), n));
820 push();
821 codegen(s, t->car, VAL);
822 pop(); pop();
823 if (is_splat) {
824 genop(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1));
826 else {
827 genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
830 t = t->cdr;
831 while (t) {
832 push();
833 codegen(s, t->car, VAL);
834 pop(); pop();
835 if (nint(t->car->car) == NODE_SPLAT) {
836 genop(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1));
838 else {
839 genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
841 t = t->cdr;
844 else {
845 while (t) {
846 codegen(s, t->car, NOVAL);
847 t = t->cdr;
850 return -1;
852 /* normal (no splat) mode */
853 codegen(s, t->car, val);
854 n++;
855 t = t->cdr;
857 return n;
860 static void
861 gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe)
863 mrb_sym sym = name ? name : nsym(tree->cdr->car);
864 int idx, skip = 0;
865 int n = 0, noop = 0, sendv = 0, blk = 0;
867 codegen(s, tree->car, VAL); /* receiver */
868 if (safe) {
869 int recv = cursp()-1;
870 genop(s, MKOP_A(OP_LOADNIL, cursp()));
871 push();
872 genop(s, MKOP_AB(OP_MOVE, cursp(), recv));
873 push_n(2); pop_n(2); /* space for one arg and a block */
874 pop();
875 idx = new_msym(s, mrb_intern_lit(s->mrb, "=="));
876 genop(s, MKOP_ABC(OP_EQ, cursp(), idx, 1));
877 skip = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), 0));
879 idx = new_msym(s, sym);
880 tree = tree->cdr->cdr->car;
881 if (tree) {
882 n = gen_values(s, tree->car, VAL, sp?1:0);
883 if (n < 0) {
884 n = noop = sendv = 1;
885 push();
888 if (sp) {
889 if (sendv) {
890 pop();
891 genop(s, MKOP_AB(OP_ARYPUSH, cursp(), sp));
892 push();
894 else {
895 genop(s, MKOP_AB(OP_MOVE, cursp(), sp));
896 push();
897 n++;
900 if (tree && tree->cdr) {
901 noop = 1;
902 codegen(s, tree->cdr, VAL);
903 pop();
905 else {
906 blk = cursp();
908 push();pop();
909 pop_n(n+1);
911 mrb_int symlen;
912 const char *symname = mrb_sym2name_len(s->mrb, sym, &symlen);
914 if (!noop && symlen == 1 && symname[0] == '+' && n == 1) {
915 genop_peep(s, MKOP_ABC(OP_ADD, cursp(), idx, n), val);
917 else if (!noop && symlen == 1 && symname[0] == '-' && n == 1) {
918 genop_peep(s, MKOP_ABC(OP_SUB, cursp(), idx, n), val);
920 else if (!noop && symlen == 1 && symname[0] == '*' && n == 1) {
921 genop(s, MKOP_ABC(OP_MUL, cursp(), idx, n));
923 else if (!noop && symlen == 1 && symname[0] == '/' && n == 1) {
924 genop(s, MKOP_ABC(OP_DIV, cursp(), idx, n));
926 else if (!noop && symlen == 1 && symname[0] == '<' && n == 1) {
927 genop(s, MKOP_ABC(OP_LT, cursp(), idx, n));
929 else if (!noop && symlen == 2 && symname[0] == '<' && symname[1] == '=' && n == 1) {
930 genop(s, MKOP_ABC(OP_LE, cursp(), idx, n));
932 else if (!noop && symlen == 1 && symname[0] == '>' && n == 1) {
933 genop(s, MKOP_ABC(OP_GT, cursp(), idx, n));
935 else if (!noop && symlen == 2 && symname[0] == '>' && symname[1] == '=' && n == 1) {
936 genop(s, MKOP_ABC(OP_GE, cursp(), idx, n));
938 else if (!noop && symlen == 2 && symname[0] == '=' && symname[1] == '=' && n == 1) {
939 genop(s, MKOP_ABC(OP_EQ, cursp(), idx, n));
941 else {
942 if (sendv) n = CALL_MAXARGS;
943 if (blk > 0) { /* no block */
944 genop(s, MKOP_ABC(OP_SEND, cursp(), idx, n));
946 else {
947 genop(s, MKOP_ABC(OP_SENDB, cursp(), idx, n));
951 if (safe) {
952 dispatch(s, skip);
954 if (val) {
955 push();
959 static void
960 gen_assignment(codegen_scope *s, node *tree, int sp, int val)
962 int idx;
963 int type = nint(tree->car);
965 tree = tree->cdr;
966 switch (type) {
967 case NODE_GVAR:
968 idx = new_sym(s, nsym(tree));
969 genop_peep(s, MKOP_ABx(OP_SETGLOBAL, sp, idx), val);
970 break;
971 case NODE_LVAR:
972 idx = lv_idx(s, nsym(tree));
973 if (idx > 0) {
974 if (idx != sp) {
975 genop_peep(s, MKOP_AB(OP_MOVE, idx, sp), val);
977 break;
979 else { /* upvar */
980 int lv = 0;
981 codegen_scope *up = s->prev;
983 while (up) {
984 idx = lv_idx(up, nsym(tree));
985 if (idx > 0) {
986 genop_peep(s, MKOP_ABC(OP_SETUPVAR, sp, idx, lv), val);
987 break;
989 lv++;
990 up = up->prev;
993 break;
994 case NODE_IVAR:
995 idx = new_sym(s, nsym(tree));
996 genop_peep(s, MKOP_ABx(OP_SETIV, sp, idx), val);
997 break;
998 case NODE_CVAR:
999 idx = new_sym(s, nsym(tree));
1000 genop_peep(s, MKOP_ABx(OP_SETCV, sp, idx), val);
1001 break;
1002 case NODE_CONST:
1003 idx = new_sym(s, nsym(tree));
1004 genop_peep(s, MKOP_ABx(OP_SETCONST, sp, idx), val);
1005 break;
1006 case NODE_COLON2:
1007 idx = new_sym(s, nsym(tree->cdr));
1008 genop_peep(s, MKOP_AB(OP_MOVE, cursp(), sp), NOVAL);
1009 push();
1010 codegen(s, tree->car, VAL);
1011 pop_n(2);
1012 genop_peep(s, MKOP_ABx(OP_SETMCNST, cursp(), idx), val);
1013 break;
1015 case NODE_CALL:
1016 case NODE_SCALL:
1017 push();
1018 gen_call(s, tree, attrsym(s, nsym(tree->cdr->car)), sp, NOVAL,
1019 type == NODE_SCALL);
1020 pop();
1021 if (val) {
1022 genop_peep(s, MKOP_AB(OP_MOVE, cursp(), sp), val);
1024 break;
1026 case NODE_MASGN:
1027 gen_vmassignment(s, tree->car, sp, val);
1028 break;
1030 /* splat without assignment */
1031 case NODE_NIL:
1032 break;
1034 default:
1035 #ifndef MRB_DISABLE_STDIO
1036 fprintf(stderr, "unknown lhs %d\n", type);
1037 #endif
1038 break;
1040 if (val) push();
1043 static void
1044 gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val)
1046 int n = 0, post = 0;
1047 node *t, *p;
1049 if (tree->car) { /* pre */
1050 t = tree->car;
1051 n = 0;
1052 while (t) {
1053 genop(s, MKOP_ABC(OP_AREF, cursp(), rhs, n));
1054 gen_assignment(s, t->car, cursp(), NOVAL);
1055 n++;
1056 t = t->cdr;
1059 t = tree->cdr;
1060 if (t) {
1061 if (t->cdr) { /* post count */
1062 p = t->cdr->car;
1063 while (p) {
1064 post++;
1065 p = p->cdr;
1068 if (val) {
1069 genop(s, MKOP_AB(OP_MOVE, cursp(), rhs));
1071 else {
1072 pop();
1074 push_n(post);
1075 pop_n(post);
1076 genop(s, MKOP_ABC(OP_APOST, cursp(), n, post));
1077 n = 1;
1078 if (t->car) { /* rest */
1079 gen_assignment(s, t->car, cursp(), NOVAL);
1081 if (t->cdr && t->cdr->car) {
1082 t = t->cdr->car;
1083 while (t) {
1084 gen_assignment(s, t->car, cursp()+n, NOVAL);
1085 t = t->cdr;
1086 n++;
1089 if (!val) {
1090 push();
1095 static void
1096 gen_send_intern(codegen_scope *s)
1098 pop();
1099 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "intern")), 0));
1100 push();
1102 static void
1103 gen_literal_array(codegen_scope *s, node *tree, mrb_bool sym, int val)
1105 if (val) {
1106 int i = 0, j = 0;
1108 while (tree) {
1109 switch (nint(tree->car->car)) {
1110 case NODE_STR:
1111 if ((tree->cdr == NULL) && (nint(tree->car->cdr->cdr) == 0))
1112 break;
1113 /* fall through */
1114 case NODE_BEGIN:
1115 codegen(s, tree->car, VAL);
1116 ++j;
1117 break;
1119 case NODE_LITERAL_DELIM:
1120 if (j > 0) {
1121 j = 0;
1122 ++i;
1123 if (sym)
1124 gen_send_intern(s);
1126 break;
1128 if (j >= 2) {
1129 pop(); pop();
1130 genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
1131 push();
1132 j = 1;
1134 tree = tree->cdr;
1136 if (j > 0) {
1137 ++i;
1138 if (sym)
1139 gen_send_intern(s);
1141 pop_n(i);
1142 genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), i));
1143 push();
1145 else {
1146 while (tree) {
1147 switch (nint(tree->car->car)) {
1148 case NODE_BEGIN: case NODE_BLOCK:
1149 codegen(s, tree->car, NOVAL);
1151 tree = tree->cdr;
1156 static void
1157 raise_error(codegen_scope *s, const char *msg)
1159 int idx = new_lit(s, mrb_str_new_cstr(s->mrb, msg));
1161 genop(s, MKOP_ABx(OP_ERR, 1, idx));
1164 static double
1165 readint_float(codegen_scope *s, const char *p, int base)
1167 const char *e = p + strlen(p);
1168 double f = 0;
1169 int n;
1171 if (*p == '+') p++;
1172 while (p < e) {
1173 char c = *p;
1174 c = tolower((unsigned char)c);
1175 for (n=0; n<base; n++) {
1176 if (mrb_digitmap[n] == c) {
1177 f *= base;
1178 f += n;
1179 break;
1182 if (n == base) {
1183 codegen_error(s, "malformed readint input");
1185 p++;
1187 return f;
1190 static mrb_int
1191 readint_mrb_int(codegen_scope *s, const char *p, int base, mrb_bool neg, mrb_bool *overflow)
1193 const char *e = p + strlen(p);
1194 mrb_int result = 0;
1195 int n;
1197 mrb_assert(base >= 2 && base <= 36);
1198 if (*p == '+') p++;
1199 while (p < e) {
1200 char c = *p;
1201 c = tolower((unsigned char)c);
1202 for (n=0; n<base; n++) {
1203 if (mrb_digitmap[n] == c) {
1204 break;
1207 if (n == base) {
1208 codegen_error(s, "malformed readint input");
1211 if (neg) {
1212 if ((MRB_INT_MIN + n)/base > result) {
1213 *overflow = TRUE;
1214 return 0;
1216 result *= base;
1217 result -= n;
1219 else {
1220 if ((MRB_INT_MAX - n)/base < result) {
1221 *overflow = TRUE;
1222 return 0;
1224 result *= base;
1225 result += n;
1227 p++;
1229 *overflow = FALSE;
1230 return result;
1233 static void
1234 gen_retval(codegen_scope *s, node *tree)
1236 if (nint(tree->car) == NODE_SPLAT) {
1237 genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), 0));
1238 push();
1239 codegen(s, tree, VAL);
1240 pop(); pop();
1241 genop(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1));
1243 else {
1244 codegen(s, tree, VAL);
1245 pop();
1249 static void
1250 codegen(codegen_scope *s, node *tree, int val)
1252 int nt;
1253 int rlev = s->rlev;
1255 if (!tree) {
1256 if (val) {
1257 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1258 push();
1260 return;
1263 s->rlev++;
1264 if (s->rlev > MRB_CODEGEN_LEVEL_MAX) {
1265 codegen_error(s, "too complex expression");
1267 if (s->irep && s->filename_index != tree->filename_index) {
1268 s->irep->filename = mrb_parser_get_filename(s->parser, s->filename_index);
1269 mrb_debug_info_append_file(s->mrb, s->irep, s->debug_start_pos, s->pc);
1270 s->debug_start_pos = s->pc;
1271 s->filename_index = tree->filename_index;
1272 s->filename = mrb_parser_get_filename(s->parser, tree->filename_index);
1275 nt = nint(tree->car);
1276 s->lineno = tree->lineno;
1277 tree = tree->cdr;
1278 switch (nt) {
1279 case NODE_BEGIN:
1280 if (val && !tree) {
1281 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1282 push();
1284 while (tree) {
1285 codegen(s, tree->car, tree->cdr ? NOVAL : val);
1286 tree = tree->cdr;
1288 break;
1290 case NODE_RESCUE:
1292 int onerr, noexc, exend, pos1, pos2, tmp;
1293 struct loopinfo *lp;
1295 if (tree->car == NULL) goto exit;
1296 onerr = genop(s, MKOP_Bx(OP_ONERR, 0));
1297 lp = loop_push(s, LOOP_BEGIN);
1298 lp->pc1 = onerr;
1299 codegen(s, tree->car, VAL);
1300 pop();
1301 lp->type = LOOP_RESCUE;
1302 noexc = genop(s, MKOP_Bx(OP_JMP, 0));
1303 dispatch(s, onerr);
1304 tree = tree->cdr;
1305 exend = 0;
1306 pos1 = 0;
1307 if (tree->car) {
1308 node *n2 = tree->car;
1309 int exc = cursp();
1311 genop(s, MKOP_ABC(OP_RESCUE, exc, 0, 0));
1312 push();
1313 while (n2) {
1314 node *n3 = n2->car;
1315 node *n4 = n3->car;
1317 if (pos1) dispatch(s, pos1);
1318 pos2 = 0;
1319 do {
1320 if (n4 && n4->car && nint(n4->car->car) == NODE_SPLAT) {
1321 codegen(s, n4->car, VAL);
1322 genop(s, MKOP_AB(OP_MOVE, cursp(), exc));
1323 push_n(2); pop_n(3);
1324 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1));
1326 else {
1327 if (n4) {
1328 codegen(s, n4->car, VAL);
1330 else {
1331 genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "StandardError"))));
1332 push();
1334 pop();
1335 genop(s, MKOP_ABC(OP_RESCUE, exc, cursp(), 1));
1337 tmp = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2));
1338 pos2 = tmp;
1339 if (n4) {
1340 n4 = n4->cdr;
1342 } while (n4);
1343 pos1 = genop(s, MKOP_sBx(OP_JMP, 0));
1344 dispatch_linked(s, pos2);
1346 pop();
1347 if (n3->cdr->car) {
1348 gen_assignment(s, n3->cdr->car, exc, NOVAL);
1350 if (n3->cdr->cdr->car) {
1351 codegen(s, n3->cdr->cdr->car, val);
1352 if (val) pop();
1354 tmp = genop(s, MKOP_sBx(OP_JMP, exend));
1355 exend = tmp;
1356 n2 = n2->cdr;
1357 push();
1359 if (pos1) {
1360 dispatch(s, pos1);
1361 genop(s, MKOP_A(OP_RAISE, exc));
1364 pop();
1365 tree = tree->cdr;
1366 dispatch(s, noexc);
1367 genop(s, MKOP_A(OP_POPERR, 1));
1368 if (tree->car) {
1369 codegen(s, tree->car, val);
1371 else if (val) {
1372 push();
1374 dispatch_linked(s, exend);
1375 loop_pop(s, NOVAL);
1377 break;
1379 case NODE_ENSURE:
1380 if (!tree->cdr || !tree->cdr->cdr ||
1381 (nint(tree->cdr->cdr->car) == NODE_BEGIN &&
1382 tree->cdr->cdr->cdr)) {
1383 int idx;
1384 int epush = s->pc;
1386 genop(s, MKOP_Bx(OP_EPUSH, 0));
1387 s->ensure_level++;
1388 codegen(s, tree->car, val);
1389 idx = scope_body(s, tree->cdr, NOVAL);
1390 s->iseq[epush] = MKOP_Bx(OP_EPUSH, idx);
1391 s->ensure_level--;
1392 genop_peep(s, MKOP_A(OP_EPOP, 1), NOVAL);
1394 else { /* empty ensure ignored */
1395 codegen(s, tree->car, val);
1397 break;
1399 case NODE_LAMBDA:
1400 if (val) {
1401 int idx = lambda_body(s, tree, 1);
1403 genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_LAMBDA));
1404 push();
1406 break;
1408 case NODE_BLOCK:
1409 if (val) {
1410 int idx = lambda_body(s, tree, 1);
1412 genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_BLOCK));
1413 push();
1415 break;
1417 case NODE_IF:
1419 int pos1, pos2;
1420 node *e = tree->cdr->cdr->car;
1422 if (!tree->car) {
1423 codegen(s, e, val);
1424 goto exit;
1426 switch (nint(tree->car->car)) {
1427 case NODE_TRUE:
1428 case NODE_INT:
1429 case NODE_STR:
1430 codegen(s, tree->cdr->car, val);
1431 goto exit;
1432 case NODE_FALSE:
1433 case NODE_NIL:
1434 codegen(s, e, val);
1435 goto exit;
1437 codegen(s, tree->car, VAL);
1438 pop();
1439 pos1 = genop_peep(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0), NOVAL);
1441 codegen(s, tree->cdr->car, val);
1442 if (e) {
1443 if (val) pop();
1444 pos2 = genop(s, MKOP_sBx(OP_JMP, 0));
1445 dispatch(s, pos1);
1446 codegen(s, e, val);
1447 dispatch(s, pos2);
1449 else {
1450 if (val) {
1451 pop();
1452 pos2 = genop(s, MKOP_sBx(OP_JMP, 0));
1453 dispatch(s, pos1);
1454 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1455 dispatch(s, pos2);
1456 push();
1458 else {
1459 dispatch(s, pos1);
1463 break;
1465 case NODE_AND:
1467 int pos;
1469 codegen(s, tree->car, VAL);
1470 pop();
1471 pos = genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0));
1472 codegen(s, tree->cdr, val);
1473 dispatch(s, pos);
1475 break;
1477 case NODE_OR:
1479 int pos;
1481 codegen(s, tree->car, VAL);
1482 pop();
1483 pos = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), 0));
1484 codegen(s, tree->cdr, val);
1485 dispatch(s, pos);
1487 break;
1489 case NODE_WHILE:
1491 struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
1493 lp->pc1 = genop(s, MKOP_sBx(OP_JMP, 0));
1494 lp->pc2 = new_label(s);
1495 codegen(s, tree->cdr, NOVAL);
1496 dispatch(s, lp->pc1);
1497 codegen(s, tree->car, VAL);
1498 pop();
1499 genop(s, MKOP_AsBx(OP_JMPIF, cursp(), lp->pc2 - s->pc));
1501 loop_pop(s, val);
1503 break;
1505 case NODE_UNTIL:
1507 struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
1509 lp->pc1 = genop(s, MKOP_sBx(OP_JMP, 0));
1510 lp->pc2 = new_label(s);
1511 codegen(s, tree->cdr, NOVAL);
1512 dispatch(s, lp->pc1);
1513 codegen(s, tree->car, VAL);
1514 pop();
1515 genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), lp->pc2 - s->pc));
1517 loop_pop(s, val);
1519 break;
1521 case NODE_FOR:
1522 for_body(s, tree);
1523 if (val) push();
1524 break;
1526 case NODE_CASE:
1528 int head = 0;
1529 int pos1, pos2, pos3, tmp;
1530 node *n;
1532 pos3 = 0;
1533 if (tree->car) {
1534 head = cursp();
1535 codegen(s, tree->car, VAL);
1537 tree = tree->cdr;
1538 while (tree) {
1539 n = tree->car->car;
1540 pos1 = pos2 = 0;
1541 while (n) {
1542 codegen(s, n->car, VAL);
1543 if (head) {
1544 genop(s, MKOP_AB(OP_MOVE, cursp(), head));
1545 push_n(2); pop_n(2); /* space for one arg and a block */
1546 pop();
1547 if (nint(n->car->car) == NODE_SPLAT) {
1548 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1));
1550 else {
1551 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "===")), 1));
1554 else {
1555 pop();
1557 tmp = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2));
1558 pos2 = tmp;
1559 n = n->cdr;
1561 if (tree->car->car) {
1562 pos1 = genop(s, MKOP_sBx(OP_JMP, 0));
1563 dispatch_linked(s, pos2);
1565 codegen(s, tree->car->cdr, val);
1566 if (val) pop();
1567 tmp = genop(s, MKOP_sBx(OP_JMP, pos3));
1568 pos3 = tmp;
1569 if (pos1) dispatch(s, pos1);
1570 tree = tree->cdr;
1572 if (val) {
1573 int pos = cursp();
1574 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1575 if (pos3) dispatch_linked(s, pos3);
1576 if (head) pop();
1577 if (cursp() != pos) {
1578 genop(s, MKOP_AB(OP_MOVE, cursp(), pos));
1580 push();
1582 else {
1583 if (pos3) {
1584 dispatch_linked(s, pos3);
1586 if (head) {
1587 pop();
1591 break;
1593 case NODE_SCOPE:
1594 scope_body(s, tree, NOVAL);
1595 break;
1597 case NODE_FCALL:
1598 case NODE_CALL:
1599 gen_call(s, tree, 0, 0, val, 0);
1600 break;
1601 case NODE_SCALL:
1602 gen_call(s, tree, 0, 0, val, 1);
1603 break;
1605 case NODE_DOT2:
1606 codegen(s, tree->car, val);
1607 codegen(s, tree->cdr, val);
1608 if (val) {
1609 pop(); pop();
1610 genop(s, MKOP_ABC(OP_RANGE, cursp(), cursp(), FALSE));
1611 push();
1613 break;
1615 case NODE_DOT3:
1616 codegen(s, tree->car, val);
1617 codegen(s, tree->cdr, val);
1618 if (val) {
1619 pop(); pop();
1620 genop(s, MKOP_ABC(OP_RANGE, cursp(), cursp(), TRUE));
1621 push();
1623 break;
1625 case NODE_COLON2:
1627 int sym = new_sym(s, nsym(tree->cdr));
1629 codegen(s, tree->car, VAL);
1630 pop();
1631 genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
1632 if (val) push();
1634 break;
1636 case NODE_COLON3:
1638 int sym = new_sym(s, nsym(tree));
1640 genop(s, MKOP_A(OP_OCLASS, cursp()));
1641 genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
1642 if (val) push();
1644 break;
1646 case NODE_ARRAY:
1648 int n;
1650 n = gen_values(s, tree, val, 0);
1651 if (n >= 0) {
1652 if (val) {
1653 pop_n(n);
1654 genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), n));
1655 push();
1658 else if (val) {
1659 push();
1662 break;
1664 case NODE_HASH:
1666 int len = 0;
1667 mrb_bool update = FALSE;
1669 while (tree) {
1670 codegen(s, tree->car->car, val);
1671 codegen(s, tree->car->cdr, val);
1672 len++;
1673 tree = tree->cdr;
1674 if (val && len == 126) {
1675 pop_n(len*2);
1676 genop(s, MKOP_ABC(OP_HASH, cursp(), cursp(), len));
1677 if (update) {
1678 pop();
1679 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__update")), 1));
1681 push();
1682 update = TRUE;
1683 len = 0;
1686 if (val) {
1687 pop_n(len*2);
1688 genop(s, MKOP_ABC(OP_HASH, cursp(), cursp(), len));
1689 if (update) {
1690 pop();
1691 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__update")), 1));
1693 push();
1696 break;
1698 case NODE_SPLAT:
1699 codegen(s, tree, val);
1700 break;
1702 case NODE_ASGN:
1703 codegen(s, tree->cdr, VAL);
1704 pop();
1705 gen_assignment(s, tree->car, cursp(), val);
1706 break;
1708 case NODE_MASGN:
1710 int len = 0, n = 0, post = 0;
1711 node *t = tree->cdr, *p;
1712 int rhs = cursp();
1714 if (nint(t->car) == NODE_ARRAY && t->cdr && nosplat(t->cdr)) {
1715 /* fixed rhs */
1716 t = t->cdr;
1717 while (t) {
1718 codegen(s, t->car, VAL);
1719 len++;
1720 t = t->cdr;
1722 tree = tree->car;
1723 if (tree->car) { /* pre */
1724 t = tree->car;
1725 n = 0;
1726 while (t) {
1727 if (n < len) {
1728 gen_assignment(s, t->car, rhs+n, NOVAL);
1729 n++;
1731 else {
1732 genop(s, MKOP_A(OP_LOADNIL, rhs+n));
1733 gen_assignment(s, t->car, rhs+n, NOVAL);
1735 t = t->cdr;
1738 t = tree->cdr;
1739 if (t) {
1740 if (t->cdr) { /* post count */
1741 p = t->cdr->car;
1742 while (p) {
1743 post++;
1744 p = p->cdr;
1747 if (t->car) { /* rest (len - pre - post) */
1748 int rn;
1750 if (len < post + n) {
1751 rn = 0;
1753 else {
1754 rn = len - post - n;
1756 genop(s, MKOP_ABC(OP_ARRAY, cursp(), rhs+n, rn));
1757 gen_assignment(s, t->car, cursp(), NOVAL);
1758 n += rn;
1760 if (t->cdr && t->cdr->car) {
1761 t = t->cdr->car;
1762 while (n<len) {
1763 gen_assignment(s, t->car, rhs+n, NOVAL);
1764 t = t->cdr;
1765 n++;
1769 pop_n(len);
1770 if (val) {
1771 genop(s, MKOP_ABC(OP_ARRAY, rhs, rhs, len));
1772 push();
1775 else {
1776 /* variable rhs */
1777 codegen(s, t, VAL);
1778 gen_vmassignment(s, tree->car, rhs, val);
1779 if (!val) {
1780 pop();
1784 break;
1786 case NODE_OP_ASGN:
1788 mrb_sym sym = nsym(tree->cdr->car);
1789 mrb_int len;
1790 const char *name = mrb_sym2name_len(s->mrb, sym, &len);
1791 int idx, callargs = -1, vsp = -1;
1793 if ((len == 2 && name[0] == '|' && name[1] == '|') &&
1794 (nint(tree->car->car) == NODE_CONST ||
1795 nint(tree->car->car) == NODE_CVAR)) {
1796 int onerr, noexc, exc;
1797 struct loopinfo *lp;
1799 onerr = genop(s, MKOP_Bx(OP_ONERR, 0));
1800 lp = loop_push(s, LOOP_BEGIN);
1801 lp->pc1 = onerr;
1802 exc = cursp();
1803 codegen(s, tree->car, VAL);
1804 lp->type = LOOP_RESCUE;
1805 genop(s, MKOP_A(OP_POPERR, 1));
1806 noexc = genop(s, MKOP_Bx(OP_JMP, 0));
1807 dispatch(s, onerr);
1808 genop(s, MKOP_ABC(OP_RESCUE, exc, 0, 0));
1809 genop(s, MKOP_A(OP_LOADF, exc));
1810 dispatch(s, noexc);
1811 loop_pop(s, NOVAL);
1813 else if (nint(tree->car->car) == NODE_CALL) {
1814 node *n = tree->car->cdr;
1816 if (val) {
1817 vsp = cursp();
1818 push();
1820 codegen(s, n->car, VAL); /* receiver */
1821 idx = new_msym(s, nsym(n->cdr->car));
1822 if (n->cdr->cdr->car) {
1823 int base = cursp()-1;
1824 int nargs = gen_values(s, n->cdr->cdr->car->car, VAL, 1);
1826 /* copy receiver and arguments */
1827 if (nargs >= 0) {
1828 int i;
1830 genop(s, MKOP_AB(OP_MOVE, cursp(), base));
1831 for (i=0; i<nargs; i++) {
1832 genop(s, MKOP_AB(OP_MOVE, cursp()+i+1, base+i+1));
1834 push_n(nargs+1);
1835 pop_n(nargs+1);
1836 callargs = nargs;
1838 else {
1839 /* varargs */
1840 push();
1841 genop(s, MKOP_AB(OP_MOVE, cursp(), base));
1842 genop(s, MKOP_AB(OP_MOVE, cursp()+1, base+1));
1843 callargs = CALL_MAXARGS;
1845 genop(s, MKOP_ABC(OP_SEND, cursp(), idx, callargs));
1847 else {
1848 genop(s, MKOP_AB(OP_MOVE, cursp(), cursp()-1));
1849 genop(s, MKOP_ABC(OP_SEND, cursp(), idx, 0));
1850 callargs = 0;
1852 push();
1854 else {
1855 codegen(s, tree->car, VAL);
1857 if (len == 2 &&
1858 ((name[0] == '|' && name[1] == '|') ||
1859 (name[0] == '&' && name[1] == '&'))) {
1860 int pos;
1862 pop();
1863 if (val) {
1864 if (vsp >= 0) {
1865 genop(s, MKOP_AB(OP_MOVE, vsp, cursp()));
1867 pos = genop(s, MKOP_AsBx(name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0));
1869 else {
1870 pos = genop_peep(s, MKOP_AsBx(name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0), NOVAL);
1872 codegen(s, tree->cdr->cdr->car, VAL);
1873 pop();
1874 if (val && vsp >= 0) {
1875 genop(s, MKOP_AB(OP_MOVE, vsp, cursp()));
1877 if (nint(tree->car->car) == NODE_CALL) {
1878 mrb_sym m = nsym(tree->car->cdr->cdr->car);
1879 mrb_sym m2 = attrsym(s, m);
1881 idx = new_msym(s, m2);
1882 pop();
1883 if (callargs == CALL_MAXARGS) {
1884 genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
1885 pop();
1886 genop(s, MKOP_ABC(OP_SEND, cursp(), idx, callargs));
1888 else {
1889 pop_n(callargs);
1890 genop(s, MKOP_ABC(OP_SEND, cursp(), idx, callargs+1));
1893 else {
1894 gen_assignment(s, tree->car, cursp(), val);
1896 dispatch(s, pos);
1897 goto exit;
1899 codegen(s, tree->cdr->cdr->car, VAL);
1900 push(); pop();
1901 pop(); pop();
1903 idx = new_msym(s, sym);
1904 if (len == 1 && name[0] == '+') {
1905 genop_peep(s, MKOP_ABC(OP_ADD, cursp(), idx, 1), val);
1907 else if (len == 1 && name[0] == '-') {
1908 genop_peep(s, MKOP_ABC(OP_SUB, cursp(), idx, 1), val);
1910 else if (len == 1 && name[0] == '*') {
1911 genop(s, MKOP_ABC(OP_MUL, cursp(), idx, 1));
1913 else if (len == 1 && name[0] == '/') {
1914 genop(s, MKOP_ABC(OP_DIV, cursp(), idx, 1));
1916 else if (len == 1 && name[0] == '<') {
1917 genop(s, MKOP_ABC(OP_LT, cursp(), idx, 1));
1919 else if (len == 2 && name[0] == '<' && name[1] == '=') {
1920 genop(s, MKOP_ABC(OP_LE, cursp(), idx, 1));
1922 else if (len == 1 && name[0] == '>') {
1923 genop(s, MKOP_ABC(OP_GT, cursp(), idx, 1));
1925 else if (len == 2 && name[0] == '>' && name[1] == '=') {
1926 genop(s, MKOP_ABC(OP_GE, cursp(), idx, 1));
1928 else {
1929 genop(s, MKOP_ABC(OP_SEND, cursp(), idx, 1));
1931 if (callargs < 0) {
1932 gen_assignment(s, tree->car, cursp(), val);
1934 else {
1935 if (val && vsp >= 0) {
1936 genop(s, MKOP_AB(OP_MOVE, vsp, cursp()));
1938 if (callargs == CALL_MAXARGS) {
1939 pop();
1940 genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
1942 else {
1943 pop_n(callargs);
1944 callargs++;
1946 pop();
1947 idx = new_msym(s, attrsym(s,nsym(tree->car->cdr->cdr->car)));
1948 genop(s, MKOP_ABC(OP_SEND, cursp(), idx, callargs));
1951 break;
1953 case NODE_SUPER:
1955 codegen_scope *s2 = s;
1956 int lv = 0;
1957 int n = 0, noop = 0, sendv = 0;
1959 push(); /* room for receiver */
1960 while (!s2->mscope) {
1961 lv++;
1962 s2 = s2->prev;
1963 if (!s2) break;
1965 genop(s, MKOP_ABx(OP_ARGARY, cursp(), (lv & 0xf)));
1966 push(); push(); /* ARGARY pushes two values */
1967 pop(); pop();
1968 if (tree) {
1969 node *args = tree->car;
1970 if (args) {
1971 n = gen_values(s, args, VAL, 0);
1972 if (n < 0) {
1973 n = noop = sendv = 1;
1974 push();
1978 if (tree && tree->cdr) {
1979 codegen(s, tree->cdr, VAL);
1980 pop();
1982 else {
1983 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1984 push(); pop();
1986 pop_n(n+1);
1987 if (sendv) n = CALL_MAXARGS;
1988 genop(s, MKOP_ABC(OP_SUPER, cursp(), 0, n));
1989 if (val) push();
1991 break;
1993 case NODE_ZSUPER:
1995 codegen_scope *s2 = s;
1996 int lv = 0, ainfo = 0;
1998 push(); /* room for receiver */
1999 while (!s2->mscope) {
2000 lv++;
2001 s2 = s2->prev;
2002 if (!s2) break;
2004 if (s2) ainfo = s2->ainfo;
2005 genop(s, MKOP_ABx(OP_ARGARY, cursp(), (ainfo<<4)|(lv & 0xf)));
2006 push(); push(); pop(); /* ARGARY pushes two values */
2007 if (tree && tree->cdr) {
2008 codegen(s, tree->cdr, VAL);
2009 pop();
2011 pop(); pop();
2012 genop(s, MKOP_ABC(OP_SUPER, cursp(), 0, CALL_MAXARGS));
2013 if (val) push();
2015 break;
2017 case NODE_RETURN:
2018 if (tree) {
2019 gen_retval(s, tree);
2021 else {
2022 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2024 if (s->loop) {
2025 genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_RETURN));
2027 else {
2028 genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
2030 if (val) push();
2031 break;
2033 case NODE_YIELD:
2035 codegen_scope *s2 = s;
2036 int lv = 0, ainfo = 0;
2037 int n = 0, sendv = 0;
2039 while (!s2->mscope) {
2040 lv++;
2041 s2 = s2->prev;
2042 if (!s2) break;
2044 if (s2) ainfo = s2->ainfo;
2045 push();
2046 if (tree) {
2047 n = gen_values(s, tree, VAL, 0);
2048 if (n < 0) {
2049 n = sendv = 1;
2050 push();
2053 push();pop(); /* space for a block */
2054 pop_n(n+1);
2055 genop(s, MKOP_ABx(OP_BLKPUSH, cursp(), (ainfo<<4)|(lv & 0xf)));
2056 if (sendv) n = CALL_MAXARGS;
2057 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "call")), n));
2058 if (val) push();
2060 break;
2062 case NODE_BREAK:
2063 loop_break(s, tree);
2064 if (val) push();
2065 break;
2067 case NODE_NEXT:
2068 if (!s->loop) {
2069 raise_error(s, "unexpected next");
2071 else if (s->loop->type == LOOP_NORMAL) {
2072 if (s->ensure_level > s->loop->ensure_level) {
2073 genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL);
2075 codegen(s, tree, NOVAL);
2076 genop(s, MKOP_sBx(OP_JMP, s->loop->pc1 - s->pc));
2078 else {
2079 if (tree) {
2080 codegen(s, tree, VAL);
2081 pop();
2083 else {
2084 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2086 genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
2088 if (val) push();
2089 break;
2091 case NODE_REDO:
2092 if (!s->loop || s->loop->type == LOOP_BEGIN || s->loop->type == LOOP_RESCUE) {
2093 raise_error(s, "unexpected redo");
2095 else {
2096 if (s->ensure_level > s->loop->ensure_level) {
2097 genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL);
2099 genop(s, MKOP_sBx(OP_JMP, s->loop->pc2 - s->pc));
2101 if (val) push();
2102 break;
2104 case NODE_RETRY:
2106 const char *msg = "unexpected retry";
2108 if (!s->loop) {
2109 raise_error(s, msg);
2111 else {
2112 struct loopinfo *lp = s->loop;
2113 int n = 0;
2115 while (lp && lp->type != LOOP_RESCUE) {
2116 if (lp->type == LOOP_BEGIN) {
2117 n++;
2119 lp = lp->prev;
2121 if (!lp) {
2122 raise_error(s, msg);
2124 else {
2125 if (n > 0) {
2126 genop_peep(s, MKOP_A(OP_POPERR, n), NOVAL);
2128 if (s->ensure_level > lp->ensure_level) {
2129 genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - lp->ensure_level), NOVAL);
2131 genop(s, MKOP_sBx(OP_JMP, lp->pc1 - s->pc));
2134 if (val) push();
2136 break;
2138 case NODE_LVAR:
2139 if (val) {
2140 int idx = lv_idx(s, nsym(tree));
2142 if (idx > 0) {
2143 genop_peep(s, MKOP_AB(OP_MOVE, cursp(), idx), NOVAL);
2145 else {
2146 int lv = 0;
2147 codegen_scope *up = s->prev;
2149 while (up) {
2150 idx = lv_idx(up, nsym(tree));
2151 if (idx > 0) {
2152 genop(s, MKOP_ABC(OP_GETUPVAR, cursp(), idx, lv));
2153 break;
2155 lv++;
2156 up = up->prev;
2159 push();
2161 break;
2163 case NODE_GVAR:
2164 if (val) {
2165 int sym = new_sym(s, nsym(tree));
2167 genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
2168 push();
2170 break;
2172 case NODE_IVAR:
2173 if (val) {
2174 int sym = new_sym(s, nsym(tree));
2176 genop(s, MKOP_ABx(OP_GETIV, cursp(), sym));
2177 push();
2179 break;
2181 case NODE_CVAR:
2182 if (val) {
2183 int sym = new_sym(s, nsym(tree));
2185 genop(s, MKOP_ABx(OP_GETCV, cursp(), sym));
2186 push();
2188 break;
2190 case NODE_CONST:
2192 int sym = new_sym(s, nsym(tree));
2194 genop(s, MKOP_ABx(OP_GETCONST, cursp(), sym));
2195 if (val) {
2196 push();
2199 break;
2201 case NODE_DEFINED:
2202 codegen(s, tree, VAL);
2203 break;
2205 case NODE_BACK_REF:
2206 if (val) {
2207 char buf[3];
2208 int sym;
2210 buf[0] = '$';
2211 buf[1] = nchar(tree);
2212 buf[2] = 0;
2213 sym = new_sym(s, mrb_intern_cstr(s->mrb, buf));
2214 genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
2215 push();
2217 break;
2219 case NODE_NTH_REF:
2220 if (val) {
2221 mrb_state *mrb = s->mrb;
2222 mrb_value str;
2223 int sym;
2225 str = mrb_format(mrb, "$%S", mrb_fixnum_value(nint(tree)));
2226 sym = new_sym(s, mrb_intern_str(mrb, str));
2227 genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
2228 push();
2230 break;
2232 case NODE_ARG:
2233 /* should not happen */
2234 break;
2236 case NODE_BLOCK_ARG:
2237 codegen(s, tree, VAL);
2238 break;
2240 case NODE_INT:
2241 if (val) {
2242 char *p = (char*)tree->car;
2243 int base = nint(tree->cdr->car);
2244 mrb_int i;
2245 mrb_code co;
2246 mrb_bool overflow;
2248 i = readint_mrb_int(s, p, base, FALSE, &overflow);
2249 if (overflow) {
2250 double f = readint_float(s, p, base);
2251 int off = new_lit(s, mrb_float_value(s->mrb, f));
2253 genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
2255 else {
2256 if (i < MAXARG_sBx && i > -MAXARG_sBx) {
2257 co = MKOP_AsBx(OP_LOADI, cursp(), i);
2259 else {
2260 int off = new_lit(s, mrb_fixnum_value(i));
2261 co = MKOP_ABx(OP_LOADL, cursp(), off);
2263 genop(s, co);
2265 push();
2267 break;
2269 case NODE_FLOAT:
2270 if (val) {
2271 char *p = (char*)tree;
2272 mrb_float f = mrb_float_read(p, NULL);
2273 int off = new_lit(s, mrb_float_value(s->mrb, f));
2275 genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
2276 push();
2278 break;
2280 case NODE_NEGATE:
2282 nt = nint(tree->car);
2283 tree = tree->cdr;
2284 switch (nt) {
2285 case NODE_FLOAT:
2286 if (val) {
2287 char *p = (char*)tree;
2288 mrb_float f = mrb_float_read(p, NULL);
2289 int off = new_lit(s, mrb_float_value(s->mrb, -f));
2291 genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
2292 push();
2294 break;
2296 case NODE_INT:
2297 if (val) {
2298 char *p = (char*)tree->car;
2299 int base = nint(tree->cdr->car);
2300 mrb_int i;
2301 mrb_code co;
2302 mrb_bool overflow;
2304 i = readint_mrb_int(s, p, base, TRUE, &overflow);
2305 if (overflow) {
2306 double f = readint_float(s, p, base);
2307 int off = new_lit(s, mrb_float_value(s->mrb, -f));
2309 genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
2311 else {
2312 if (i < MAXARG_sBx && i > -MAXARG_sBx) {
2313 co = MKOP_AsBx(OP_LOADI, cursp(), i);
2315 else {
2316 int off = new_lit(s, mrb_fixnum_value(i));
2317 co = MKOP_ABx(OP_LOADL, cursp(), off);
2319 genop(s, co);
2321 push();
2323 break;
2325 default:
2326 if (val) {
2327 int sym = new_msym(s, mrb_intern_lit(s->mrb, "-"));
2329 genop(s, MKOP_ABx(OP_LOADI, cursp(), 0));
2330 push();
2331 codegen(s, tree, VAL);
2332 pop(); pop();
2333 genop(s, MKOP_ABC(OP_SUB, cursp(), sym, 2));
2335 else {
2336 codegen(s, tree, NOVAL);
2338 break;
2341 break;
2343 case NODE_STR:
2344 if (val) {
2345 char *p = (char*)tree->car;
2346 size_t len = (intptr_t)tree->cdr;
2347 int ai = mrb_gc_arena_save(s->mrb);
2348 int off = new_lit(s, mrb_str_new(s->mrb, p, len));
2350 mrb_gc_arena_restore(s->mrb, ai);
2351 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2352 push();
2354 break;
2356 case NODE_HEREDOC:
2357 tree = ((struct mrb_parser_heredoc_info *)tree)->doc;
2358 /* fall through */
2359 case NODE_DSTR:
2360 if (val) {
2361 node *n = tree;
2363 if (!n) {
2364 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2365 push();
2366 break;
2368 codegen(s, n->car, VAL);
2369 n = n->cdr;
2370 while (n) {
2371 codegen(s, n->car, VAL);
2372 pop(); pop();
2373 genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
2374 push();
2375 n = n->cdr;
2378 else {
2379 node *n = tree;
2381 while (n) {
2382 if (nint(n->car->car) != NODE_STR) {
2383 codegen(s, n->car, NOVAL);
2385 n = n->cdr;
2388 break;
2390 case NODE_WORDS:
2391 gen_literal_array(s, tree, FALSE, val);
2392 break;
2394 case NODE_SYMBOLS:
2395 gen_literal_array(s, tree, TRUE, val);
2396 break;
2398 case NODE_DXSTR:
2400 node *n;
2401 int ai = mrb_gc_arena_save(s->mrb);
2402 int sym = new_sym(s, mrb_intern_lit(s->mrb, "Kernel"));
2404 genop(s, MKOP_A(OP_LOADSELF, cursp()));
2405 push();
2406 codegen(s, tree->car, VAL);
2407 n = tree->cdr;
2408 while (n) {
2409 if (nint(n->car->car) == NODE_XSTR) {
2410 n->car->car = (struct mrb_ast_node*)(intptr_t)NODE_STR;
2411 mrb_assert(!n->cdr); /* must be the end */
2413 codegen(s, n->car, VAL);
2414 pop(); pop();
2415 genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
2416 push();
2417 n = n->cdr;
2419 push(); /* for block */
2420 pop_n(3);
2421 sym = new_sym(s, mrb_intern_lit(s->mrb, "`"));
2422 genop(s, MKOP_ABC(OP_SEND, cursp(), sym, 1));
2423 if (val) push();
2424 mrb_gc_arena_restore(s->mrb, ai);
2426 break;
2428 case NODE_XSTR:
2430 char *p = (char*)tree->car;
2431 size_t len = (intptr_t)tree->cdr;
2432 int ai = mrb_gc_arena_save(s->mrb);
2433 int off = new_lit(s, mrb_str_new(s->mrb, p, len));
2434 int sym;
2436 genop(s, MKOP_A(OP_LOADSELF, cursp()));
2437 push();
2438 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2439 push(); push();
2440 pop_n(3);
2441 sym = new_sym(s, mrb_intern_lit(s->mrb, "`"));
2442 genop(s, MKOP_ABC(OP_SEND, cursp(), sym, 1));
2443 if (val) push();
2444 mrb_gc_arena_restore(s->mrb, ai);
2446 break;
2448 case NODE_REGX:
2449 if (val) {
2450 char *p1 = (char*)tree->car;
2451 char *p2 = (char*)tree->cdr->car;
2452 char *p3 = (char*)tree->cdr->cdr;
2453 int ai = mrb_gc_arena_save(s->mrb);
2454 int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS));
2455 int off = new_lit(s, mrb_str_new_cstr(s->mrb, p1));
2456 int argc = 1;
2458 genop(s, MKOP_A(OP_OCLASS, cursp()));
2459 genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
2460 push();
2461 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2462 if (p2 || p3) {
2463 push();
2464 if (p2) {
2465 off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
2466 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2468 else {
2469 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2471 argc++;
2472 if (p3) {
2473 push();
2474 off = new_lit(s, mrb_str_new(s->mrb, p3, 1));
2475 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2476 argc++;
2477 pop();
2479 pop();
2481 pop();
2482 sym = new_sym(s, mrb_intern_lit(s->mrb, "compile"));
2483 genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc));
2484 mrb_gc_arena_restore(s->mrb, ai);
2485 push();
2487 break;
2489 case NODE_DREGX:
2490 if (val) {
2491 node *n = tree->car;
2492 int ai = mrb_gc_arena_save(s->mrb);
2493 int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS));
2494 int argc = 1;
2495 int off;
2496 char *p;
2498 genop(s, MKOP_A(OP_OCLASS, cursp()));
2499 genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
2500 push();
2501 codegen(s, n->car, VAL);
2502 n = n->cdr;
2503 while (n) {
2504 codegen(s, n->car, VAL);
2505 pop(); pop();
2506 genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
2507 push();
2508 n = n->cdr;
2510 n = tree->cdr->cdr;
2511 if (n->car) {
2512 p = (char*)n->car;
2513 off = new_lit(s, mrb_str_new_cstr(s->mrb, p));
2514 codegen(s, tree->car, VAL);
2515 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2516 pop();
2517 genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
2519 if (n->cdr->car) {
2520 char *p2 = (char*)n->cdr->car;
2522 push();
2523 off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
2524 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2525 argc++;
2527 if (n->cdr->cdr) {
2528 char *p2 = (char*)n->cdr->cdr;
2530 push();
2531 off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
2532 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2533 argc++;
2535 pop_n(argc);
2536 sym = new_sym(s, mrb_intern_lit(s->mrb, "compile"));
2537 genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc));
2538 mrb_gc_arena_restore(s->mrb, ai);
2539 push();
2541 else {
2542 node *n = tree->car;
2544 while (n) {
2545 if (nint(n->car->car) != NODE_STR) {
2546 codegen(s, n->car, NOVAL);
2548 n = n->cdr;
2551 break;
2553 case NODE_SYM:
2554 if (val) {
2555 int sym = new_sym(s, nsym(tree));
2557 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym));
2558 push();
2560 break;
2562 case NODE_DSYM:
2563 codegen(s, tree, val);
2564 if (val) {
2565 gen_send_intern(s);
2567 break;
2569 case NODE_SELF:
2570 if (val) {
2571 genop(s, MKOP_A(OP_LOADSELF, cursp()));
2572 push();
2574 break;
2576 case NODE_NIL:
2577 if (val) {
2578 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2579 push();
2581 break;
2583 case NODE_TRUE:
2584 if (val) {
2585 genop(s, MKOP_A(OP_LOADT, cursp()));
2586 push();
2588 break;
2590 case NODE_FALSE:
2591 if (val) {
2592 genop(s, MKOP_A(OP_LOADF, cursp()));
2593 push();
2595 break;
2597 case NODE_ALIAS:
2599 int a = new_msym(s, nsym(tree->car));
2600 int b = new_msym(s, nsym(tree->cdr));
2601 int c = new_msym(s, mrb_intern_lit(s->mrb, "alias_method"));
2603 genop(s, MKOP_A(OP_TCLASS, cursp()));
2604 push();
2605 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), a));
2606 push();
2607 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), b));
2608 push();
2609 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2610 push();
2611 pop_n(4);
2612 genop(s, MKOP_ABC(OP_SEND, cursp(), c, 2));
2613 if (val) {
2614 push();
2617 break;
2619 case NODE_UNDEF:
2621 int undef = new_msym(s, mrb_intern_lit(s->mrb, "undef_method"));
2622 int num = 0;
2623 node *t = tree;
2625 genop(s, MKOP_A(OP_TCLASS, cursp()));
2626 push();
2627 while (t) {
2628 int symbol;
2629 if (num >= CALL_MAXARGS - 1) {
2630 pop_n(num);
2631 genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), num));
2632 while (t) {
2633 symbol = new_msym(s, nsym(t->car));
2634 push();
2635 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), symbol));
2636 pop();
2637 genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
2638 t = t->cdr;
2640 num = CALL_MAXARGS;
2641 break;
2643 symbol = new_msym(s, nsym(t->car));
2644 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), symbol));
2645 push();
2646 t = t->cdr;
2647 num++;
2649 push();pop(); /* space for a block */
2650 pop();
2651 if (num < CALL_MAXARGS) {
2652 pop_n(num);
2654 genop(s, MKOP_ABC(OP_SEND, cursp(), undef, num));
2655 if (val) {
2656 push();
2659 break;
2661 case NODE_CLASS:
2663 int idx;
2665 if (tree->car->car == (node*)0) {
2666 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2667 push();
2669 else if (tree->car->car == (node*)1) {
2670 genop(s, MKOP_A(OP_OCLASS, cursp()));
2671 push();
2673 else {
2674 codegen(s, tree->car->car, VAL);
2676 if (tree->cdr->car) {
2677 codegen(s, tree->cdr->car, VAL);
2679 else {
2680 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2681 push();
2683 pop(); pop();
2684 idx = new_msym(s, nsym(tree->car->cdr));
2685 genop(s, MKOP_AB(OP_CLASS, cursp(), idx));
2686 idx = scope_body(s, tree->cdr->cdr->car, val);
2687 genop(s, MKOP_ABx(OP_EXEC, cursp(), idx));
2688 if (val) {
2689 push();
2692 break;
2694 case NODE_MODULE:
2696 int idx;
2698 if (tree->car->car == (node*)0) {
2699 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2700 push();
2702 else if (tree->car->car == (node*)1) {
2703 genop(s, MKOP_A(OP_OCLASS, cursp()));
2704 push();
2706 else {
2707 codegen(s, tree->car->car, VAL);
2709 pop();
2710 idx = new_msym(s, nsym(tree->car->cdr));
2711 genop(s, MKOP_AB(OP_MODULE, cursp(), idx));
2712 idx = scope_body(s, tree->cdr->car, val);
2713 genop(s, MKOP_ABx(OP_EXEC, cursp(), idx));
2714 if (val) {
2715 push();
2718 break;
2720 case NODE_SCLASS:
2722 int idx;
2724 codegen(s, tree->car, VAL);
2725 pop();
2726 genop(s, MKOP_AB(OP_SCLASS, cursp(), cursp()));
2727 idx = scope_body(s, tree->cdr->car, val);
2728 genop(s, MKOP_ABx(OP_EXEC, cursp(), idx));
2729 if (val) {
2730 push();
2733 break;
2735 case NODE_DEF:
2737 int sym = new_msym(s, nsym(tree->car));
2738 int idx = lambda_body(s, tree->cdr, 0);
2740 genop(s, MKOP_A(OP_TCLASS, cursp()));
2741 push();
2742 genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_METHOD));
2743 push(); pop();
2744 pop();
2745 genop(s, MKOP_AB(OP_METHOD, cursp(), sym));
2746 if (val) {
2747 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym));
2748 push();
2751 break;
2753 case NODE_SDEF:
2755 node *recv = tree->car;
2756 int sym = new_msym(s, nsym(tree->cdr->car));
2757 int idx = lambda_body(s, tree->cdr->cdr, 0);
2759 codegen(s, recv, VAL);
2760 pop();
2761 genop(s, MKOP_AB(OP_SCLASS, cursp(), cursp()));
2762 push();
2763 genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_METHOD));
2764 pop();
2765 genop(s, MKOP_AB(OP_METHOD, cursp(), sym));
2766 if (val) {
2767 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym));
2768 push();
2771 break;
2773 case NODE_POSTEXE:
2774 codegen(s, tree, NOVAL);
2775 break;
2777 default:
2778 break;
2780 exit:
2781 s->rlev = rlev;
2784 static void
2785 scope_add_irep(codegen_scope *s, mrb_irep *irep)
2787 if (s->irep == NULL) {
2788 s->irep = irep;
2789 return;
2791 if (s->irep->rlen == s->rcapa) {
2792 s->rcapa *= 2;
2793 s->irep->reps = (mrb_irep**)codegen_realloc(s, s->irep->reps, sizeof(mrb_irep*)*s->rcapa);
2795 s->irep->reps[s->irep->rlen] = irep;
2796 s->irep->rlen++;
2799 static codegen_scope*
2800 scope_new(mrb_state *mrb, codegen_scope *prev, node *lv)
2802 static const codegen_scope codegen_scope_zero = { 0 };
2803 mrb_pool *pool = mrb_pool_open(mrb);
2804 codegen_scope *p = (codegen_scope *)mrb_pool_alloc(pool, sizeof(codegen_scope));
2806 if (!p) return NULL;
2807 *p = codegen_scope_zero;
2808 p->mrb = mrb;
2809 p->mpool = pool;
2810 if (!prev) return p;
2811 p->prev = prev;
2812 p->ainfo = -1;
2813 p->mscope = 0;
2815 p->irep = mrb_add_irep(mrb);
2816 scope_add_irep(prev, p->irep);
2818 p->rcapa = 8;
2819 p->irep->reps = (mrb_irep**)mrb_malloc(mrb, sizeof(mrb_irep*)*p->rcapa);
2821 p->icapa = 1024;
2822 p->iseq = (mrb_code*)mrb_malloc(mrb, sizeof(mrb_code)*p->icapa);
2823 p->irep->iseq = NULL;
2825 p->pcapa = 32;
2826 p->irep->pool = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value)*p->pcapa);
2827 p->irep->plen = 0;
2829 p->scapa = MAXMSYMLEN;
2830 p->irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*p->scapa);
2831 p->irep->slen = 0;
2833 p->lv = lv;
2834 p->sp += node_len(lv)+1; /* add self */
2835 p->nlocals = p->sp;
2836 if (lv) {
2837 node *n = lv;
2838 size_t i = 0;
2840 p->irep->lv = (struct mrb_locals*)mrb_malloc(mrb, sizeof(struct mrb_locals) * (p->nlocals - 1));
2841 for (i=0, n=lv; n; i++,n=n->cdr) {
2842 p->irep->lv[i].name = lv_name(n);
2843 if (lv_name(n)) {
2844 p->irep->lv[i].r = lv_idx(p, lv_name(n));
2846 else {
2847 p->irep->lv[i].r = 0;
2850 mrb_assert(i + 1 == p->nlocals);
2852 p->ai = mrb_gc_arena_save(mrb);
2854 p->filename = prev->filename;
2855 if (p->filename) {
2856 p->lines = (uint16_t*)mrb_malloc(mrb, sizeof(short)*p->icapa);
2858 p->lineno = prev->lineno;
2860 /* debug setting */
2861 p->debug_start_pos = 0;
2862 if (p->filename) {
2863 mrb_debug_info_alloc(mrb, p->irep);
2864 p->irep->filename = p->filename;
2865 p->irep->lines = p->lines;
2867 else {
2868 p->irep->debug_info = NULL;
2870 p->parser = prev->parser;
2871 p->filename_index = prev->filename_index;
2873 p->rlev = prev->rlev+1;
2875 return p;
2878 static void
2879 scope_finish(codegen_scope *s)
2881 mrb_state *mrb = s->mrb;
2882 mrb_irep *irep = s->irep;
2883 size_t fname_len;
2884 char *fname;
2886 irep->flags = 0;
2887 if (s->iseq) {
2888 irep->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc);
2889 irep->ilen = s->pc;
2890 if (s->lines) {
2891 irep->lines = (uint16_t *)codegen_realloc(s, s->lines, sizeof(uint16_t)*s->pc);
2893 else {
2894 irep->lines = 0;
2897 irep->pool = (mrb_value*)codegen_realloc(s, irep->pool, sizeof(mrb_value)*irep->plen);
2898 irep->syms = (mrb_sym*)codegen_realloc(s, irep->syms, sizeof(mrb_sym)*irep->slen);
2899 irep->reps = (mrb_irep**)codegen_realloc(s, irep->reps, sizeof(mrb_irep*)*irep->rlen);
2900 if (s->filename) {
2901 irep->filename = mrb_parser_get_filename(s->parser, s->filename_index);
2902 mrb_debug_info_append_file(mrb, irep, s->debug_start_pos, s->pc);
2904 fname_len = strlen(s->filename);
2905 fname = (char*)codegen_malloc(s, fname_len + 1);
2906 memcpy(fname, s->filename, fname_len);
2907 fname[fname_len] = '\0';
2908 irep->filename = fname;
2909 irep->own_filename = TRUE;
2912 irep->nlocals = s->nlocals;
2913 irep->nregs = s->nregs;
2915 mrb_gc_arena_restore(mrb, s->ai);
2916 mrb_pool_close(s->mpool);
2919 static struct loopinfo*
2920 loop_push(codegen_scope *s, enum looptype t)
2922 struct loopinfo *p = (struct loopinfo *)codegen_palloc(s, sizeof(struct loopinfo));
2924 p->type = t;
2925 p->pc1 = p->pc2 = p->pc3 = 0;
2926 p->prev = s->loop;
2927 p->ensure_level = s->ensure_level;
2928 p->acc = cursp();
2929 s->loop = p;
2931 return p;
2934 static void
2935 loop_break(codegen_scope *s, node *tree)
2937 if (!s->loop) {
2938 codegen(s, tree, NOVAL);
2939 raise_error(s, "unexpected break");
2941 else {
2942 struct loopinfo *loop;
2943 int n = 0;
2945 if (tree) {
2946 gen_retval(s, tree);
2949 loop = s->loop;
2950 while (loop) {
2951 if (loop->type == LOOP_BEGIN) {
2952 n++;
2953 loop = loop->prev;
2955 else if (loop->type == LOOP_RESCUE) {
2956 loop = loop->prev;
2958 else{
2959 break;
2962 if (!loop) {
2963 raise_error(s, "unexpected break");
2964 return;
2966 if (n > 0) {
2967 genop_peep(s, MKOP_A(OP_POPERR, n), NOVAL);
2970 if (loop->type == LOOP_NORMAL) {
2971 int tmp;
2973 if (s->ensure_level > s->loop->ensure_level) {
2974 genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL);
2976 if (tree) {
2977 genop_peep(s, MKOP_AB(OP_MOVE, loop->acc, cursp()), NOVAL);
2979 tmp = genop(s, MKOP_sBx(OP_JMP, loop->pc3));
2980 loop->pc3 = tmp;
2982 else {
2983 if (!tree) {
2984 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2986 genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_BREAK));
2991 static void
2992 loop_pop(codegen_scope *s, int val)
2994 if (val) {
2995 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2997 dispatch_linked(s, s->loop->pc3);
2998 s->loop = s->loop->prev;
2999 if (val) push();
3002 MRB_API struct RProc*
3003 mrb_generate_code(mrb_state *mrb, parser_state *p)
3005 codegen_scope *scope = scope_new(mrb, 0, 0);
3006 struct RProc *proc;
3007 struct mrb_jmpbuf *prev_jmp = mrb->jmp;
3009 if (!scope) {
3010 return NULL;
3012 scope->mrb = mrb;
3013 scope->parser = p;
3014 scope->filename = p->filename;
3015 scope->filename_index = p->current_filename_index;
3017 MRB_TRY(&scope->jmp) {
3018 mrb->jmp = &scope->jmp;
3019 /* prepare irep */
3020 codegen(scope, p->tree, NOVAL);
3021 proc = mrb_proc_new(mrb, scope->irep);
3022 mrb_irep_decref(mrb, scope->irep);
3023 mrb_pool_close(scope->mpool);
3024 proc->c = NULL;
3025 mrb->jmp = prev_jmp;
3026 return proc;
3028 MRB_CATCH(&scope->jmp) {
3029 mrb_irep_decref(mrb, scope->irep);
3030 mrb_pool_close(scope->mpool);
3031 mrb->jmp = prev_jmp;
3032 return NULL;
3034 MRB_END_EXC(&scope->jmp);