Merge pull request #3637 from dabroz/fix-32-bit
[mruby.git] / mrbgems / mruby-compiler / core / codegen.c
blobf863ef337bc4f0cfb4b63e1ce3691386e77d97b6
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 typedef mrb_ast_node node;
23 typedef struct mrb_parser_state parser_state;
25 enum looptype {
26 LOOP_NORMAL,
27 LOOP_BLOCK,
28 LOOP_FOR,
29 LOOP_BEGIN,
30 LOOP_RESCUE,
33 struct loopinfo {
34 enum looptype type;
35 int pc1, pc2, pc3, acc;
36 int ensure_level;
37 struct loopinfo *prev;
40 typedef struct scope {
41 mrb_state *mrb;
42 mrb_pool *mpool;
43 struct mrb_jmpbuf jmp;
45 struct scope *prev;
47 node *lv;
49 int sp;
50 int pc;
51 int lastlabel;
52 int ainfo:15;
53 mrb_bool mscope:1;
55 struct loopinfo *loop;
56 int ensure_level;
57 char const *filename;
58 uint16_t lineno;
60 mrb_code *iseq;
61 uint16_t *lines;
62 int icapa;
64 mrb_irep *irep;
65 size_t pcapa;
66 size_t scapa;
67 size_t rcapa;
69 uint16_t nlocals;
70 uint16_t nregs;
71 int ai;
73 int debug_start_pos;
74 uint16_t filename_index;
75 parser_state* parser;
76 } codegen_scope;
78 static codegen_scope* scope_new(mrb_state *mrb, codegen_scope *prev, node *lv);
79 static void scope_finish(codegen_scope *s);
80 static struct loopinfo *loop_push(codegen_scope *s, enum looptype t);
81 static void loop_break(codegen_scope *s, node *tree);
82 static void loop_pop(codegen_scope *s, int val);
84 static void gen_assignment(codegen_scope *s, node *tree, int sp, int val);
85 static void gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val);
87 static void codegen(codegen_scope *s, node *tree, int val);
88 static void raise_error(codegen_scope *s, const char *msg);
90 static void
91 codegen_error(codegen_scope *s, const char *message)
93 if (!s) return;
94 while (s->prev) {
95 codegen_scope *tmp = s->prev;
96 mrb_free(s->mrb, s->iseq);
97 mrb_pool_close(s->mpool);
98 s = tmp;
100 #ifndef MRB_DISABLE_STDIO
101 if (s->filename && s->lineno) {
102 fprintf(stderr, "codegen error:%s:%d: %s\n", s->filename, s->lineno, message);
104 else {
105 fprintf(stderr, "codegen error: %s\n", message);
107 #endif
108 MRB_THROW(&s->jmp);
111 static void*
112 codegen_palloc(codegen_scope *s, size_t len)
114 void *p = mrb_pool_alloc(s->mpool, len);
116 if (!p) codegen_error(s, "pool memory allocation");
117 return p;
120 static void*
121 codegen_malloc(codegen_scope *s, size_t len)
123 void *p = mrb_malloc_simple(s->mrb, len);
125 if (!p) codegen_error(s, "mrb_malloc");
126 return p;
129 static void*
130 codegen_realloc(codegen_scope *s, void *p, size_t len)
132 p = mrb_realloc_simple(s->mrb, p, len);
134 if (!p && len > 0) codegen_error(s, "mrb_realloc");
135 return p;
138 static int
139 new_label(codegen_scope *s)
141 s->lastlabel = s->pc;
142 return s->pc;
145 static inline int
146 genop(codegen_scope *s, mrb_code i)
148 if (s->pc == s->icapa) {
149 s->icapa *= 2;
150 s->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->icapa);
151 if (s->lines) {
152 s->lines = (uint16_t*)codegen_realloc(s, s->lines, sizeof(short)*s->icapa);
153 s->irep->lines = s->lines;
156 s->iseq[s->pc] = i;
157 if (s->lines) {
158 s->lines[s->pc] = s->lineno;
160 return s->pc++;
163 #define NOVAL 0
164 #define VAL 1
166 static mrb_bool
167 no_optimize(codegen_scope *s)
169 if (s && s->parser && s->parser->no_optimize)
170 return TRUE;
171 return FALSE;
174 static int
175 genop_peep(codegen_scope *s, mrb_code i, int val)
177 /* peephole optimization */
178 if (!no_optimize(s) && s->lastlabel != s->pc && s->pc > 0) {
179 mrb_code i0 = s->iseq[s->pc-1];
180 int c1 = GET_OPCODE(i);
181 int c0 = GET_OPCODE(i0);
183 switch (c1) {
184 case OP_MOVE:
185 if (GETARG_A(i) == GETARG_B(i)) {
186 /* skip useless OP_MOVE */
187 return 0;
189 if (val) break;
190 switch (c0) {
191 case OP_MOVE:
192 if (GETARG_A(i) == GETARG_A(i0)) {
193 /* skip overriden OP_MOVE */
194 s->pc--;
195 s->iseq[s->pc] = i;
197 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i) == GETARG_B(i0)) {
198 /* skip swapping OP_MOVE */
199 return 0;
201 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
202 s->pc--;
203 return genop_peep(s, MKOP_AB(OP_MOVE, GETARG_A(i), GETARG_B(i0)), val);
205 break;
206 case OP_LOADI:
207 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
208 s->iseq[s->pc-1] = MKOP_AsBx(OP_LOADI, GETARG_A(i), GETARG_sBx(i0));
209 return 0;
211 break;
212 case OP_ARRAY:
213 case OP_HASH:
214 case OP_RANGE:
215 case OP_AREF:
216 case OP_GETUPVAR:
217 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
218 s->iseq[s->pc-1] = MKOP_ABC(c0, GETARG_A(i), GETARG_B(i0), GETARG_C(i0));
219 return 0;
221 break;
222 case OP_LOADSYM:
223 case OP_GETGLOBAL:
224 case OP_GETIV:
225 case OP_GETCV:
226 case OP_GETCONST:
227 case OP_GETSPECIAL:
228 case OP_LOADL:
229 case OP_STRING:
230 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
231 s->iseq[s->pc-1] = MKOP_ABx(c0, GETARG_A(i), GETARG_Bx(i0));
232 return 0;
234 break;
235 case OP_SCLASS:
236 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
237 s->iseq[s->pc-1] = MKOP_AB(c0, GETARG_A(i), GETARG_B(i0));
238 return 0;
240 break;
241 case OP_LOADNIL:
242 case OP_LOADSELF:
243 case OP_LOADT:
244 case OP_LOADF:
245 case OP_OCLASS:
246 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
247 s->iseq[s->pc-1] = MKOP_A(c0, GETARG_A(i));
248 return 0;
250 break;
251 default:
252 break;
254 break;
255 case OP_SETIV:
256 case OP_SETCV:
257 case OP_SETCONST:
258 case OP_SETMCNST:
259 case OP_SETGLOBAL:
260 if (val) break;
261 if (c0 == OP_MOVE) {
262 if (GETARG_A(i) == GETARG_A(i0)) {
263 s->iseq[s->pc-1] = MKOP_ABx(c1, GETARG_B(i0), GETARG_Bx(i));
264 return 0;
267 break;
268 case OP_SETUPVAR:
269 if (val) break;
270 if (c0 == OP_MOVE) {
271 if (GETARG_A(i) == GETARG_A(i0)) {
272 s->iseq[s->pc-1] = MKOP_ABC(c1, GETARG_B(i0), GETARG_B(i), GETARG_C(i));
273 return 0;
276 break;
277 case OP_EPOP:
278 if (c0 == OP_EPOP) {
279 s->iseq[s->pc-1] = MKOP_A(OP_EPOP, GETARG_A(i0)+GETARG_A(i));
280 return 0;
282 break;
283 case OP_POPERR:
284 if (c0 == OP_POPERR) {
285 s->iseq[s->pc-1] = MKOP_A(OP_POPERR, GETARG_A(i0)+GETARG_A(i));
286 return 0;
288 break;
289 case OP_RETURN:
290 switch (c0) {
291 case OP_RETURN:
292 return 0;
293 case OP_MOVE:
294 if (GETARG_A(i0) >= s->nlocals) {
295 s->iseq[s->pc-1] = MKOP_AB(OP_RETURN, GETARG_B(i0), OP_R_NORMAL);
296 return 0;
298 break;
299 case OP_SETIV:
300 case OP_SETCV:
301 case OP_SETCONST:
302 case OP_SETMCNST:
303 case OP_SETUPVAR:
304 case OP_SETGLOBAL:
305 s->pc--;
306 genop_peep(s, i0, NOVAL);
307 i0 = s->iseq[s->pc-1];
308 return genop(s, MKOP_AB(OP_RETURN, GETARG_A(i0), OP_R_NORMAL));
309 #if 0
310 case OP_SEND:
311 if (GETARG_B(i) == OP_R_NORMAL && GETARG_A(i) == GETARG_A(i0)) {
312 s->iseq[s->pc-1] = MKOP_ABC(OP_TAILCALL, GETARG_A(i0), GETARG_B(i0), GETARG_C(i0));
313 return;
315 break;
316 #endif
317 default:
318 break;
320 break;
321 case OP_ADD:
322 case OP_SUB:
323 if (c0 == OP_LOADI) {
324 int c = GETARG_sBx(i0);
326 if (c1 == OP_SUB) c = -c;
327 if (c > 127 || c < -127) break;
328 if (0 <= c)
329 s->iseq[s->pc-1] = MKOP_ABC(OP_ADDI, GETARG_A(i), GETARG_B(i), c);
330 else
331 s->iseq[s->pc-1] = MKOP_ABC(OP_SUBI, GETARG_A(i), GETARG_B(i), -c);
332 return 0;
334 case OP_STRCAT:
335 if (c0 == OP_STRING) {
336 mrb_value v = s->irep->pool[GETARG_Bx(i0)];
338 if (mrb_string_p(v) && RSTRING_LEN(v) == 0) {
339 s->pc--;
340 return 0;
343 if (c0 == OP_LOADNIL) {
344 if (GETARG_B(i) == GETARG_A(i0)) {
345 s->pc--;
346 return 0;
349 break;
350 case OP_JMPIF:
351 case OP_JMPNOT:
352 if (c0 == OP_MOVE && GETARG_A(i) == GETARG_A(i0)) {
353 s->iseq[s->pc-1] = MKOP_AsBx(c1, GETARG_B(i0), GETARG_sBx(i));
354 return s->pc-1;
356 break;
357 default:
358 break;
361 return genop(s, i);
364 static void
365 scope_error(codegen_scope *s)
367 exit(EXIT_FAILURE);
370 static inline void
371 dispatch(codegen_scope *s, int pc)
373 int diff = s->pc - pc;
374 mrb_code i = s->iseq[pc];
375 int c = GET_OPCODE(i);
377 s->lastlabel = s->pc;
378 switch (c) {
379 case OP_JMP:
380 case OP_JMPIF:
381 case OP_JMPNOT:
382 case OP_ONERR:
383 break;
384 default:
385 #ifndef MRB_DISABLE_STDIO
386 fprintf(stderr, "bug: dispatch on non JMP op\n");
387 #endif
388 scope_error(s);
389 break;
391 if (diff > MAXARG_sBx) {
392 codegen_error(s, "too distant jump address");
394 s->iseq[pc] = MKOP_AsBx(c, GETARG_A(i), diff);
397 static void
398 dispatch_linked(codegen_scope *s, int pc)
400 mrb_code i;
401 int pos;
403 if (!pc) return;
404 for (;;) {
405 i = s->iseq[pc];
406 pos = GETARG_sBx(i);
407 dispatch(s, pc);
408 if (!pos) break;
409 pc = pos;
413 #define nregs_update do {if (s->sp > s->nregs) s->nregs = s->sp;} while (0)
414 static void
415 push_(codegen_scope *s)
417 if (s->sp > 511) {
418 codegen_error(s, "too complex expression");
420 s->sp++;
421 nregs_update;
424 static void
425 push_n_(codegen_scope *s, size_t n)
427 if (s->sp+n > 511) {
428 codegen_error(s, "too complex expression");
430 s->sp+=n;
431 nregs_update;
434 #define push() push_(s)
435 #define push_n(n) push_n_(s,n)
436 #define pop_(s) ((s)->sp--)
437 #define pop() pop_(s)
438 #define pop_n(n) (s->sp-=(n))
439 #define cursp() (s->sp)
441 static inline int
442 new_lit(codegen_scope *s, mrb_value val)
444 size_t i;
445 mrb_value *pv;
447 switch (mrb_type(val)) {
448 case MRB_TT_STRING:
449 for (i=0; i<s->irep->plen; i++) {
450 mrb_int len;
451 pv = &s->irep->pool[i];
453 if (mrb_type(*pv) != MRB_TT_STRING) continue;
454 if ((len = RSTRING_LEN(*pv)) != RSTRING_LEN(val)) continue;
455 if (memcmp(RSTRING_PTR(*pv), RSTRING_PTR(val), len) == 0)
456 return i;
458 break;
459 case MRB_TT_FLOAT:
460 for (i=0; i<s->irep->plen; i++) {
461 pv = &s->irep->pool[i];
462 if (mrb_type(*pv) != MRB_TT_FLOAT) continue;
463 if (mrb_float(*pv) == mrb_float(val)) return i;
465 break;
466 case MRB_TT_FIXNUM:
467 for (i=0; i<s->irep->plen; i++) {
468 pv = &s->irep->pool[i];
469 if (!mrb_fixnum_p(*pv)) continue;
470 if (mrb_fixnum(*pv) == mrb_fixnum(val)) return i;
472 break;
473 default:
474 /* should not happen */
475 return 0;
478 if (s->irep->plen == s->pcapa) {
479 s->pcapa *= 2;
480 s->irep->pool = (mrb_value *)codegen_realloc(s, s->irep->pool, sizeof(mrb_value)*s->pcapa);
483 pv = &s->irep->pool[s->irep->plen];
484 i = s->irep->plen++;
486 switch (mrb_type(val)) {
487 case MRB_TT_STRING:
488 *pv = mrb_str_pool(s->mrb, val);
489 break;
491 case MRB_TT_FLOAT:
492 #ifdef MRB_WORD_BOXING
493 *pv = mrb_float_pool(s->mrb, mrb_float(val));
494 break;
495 #endif
496 case MRB_TT_FIXNUM:
497 *pv = val;
498 break;
500 default:
501 /* should not happen */
502 break;
504 return i;
507 /* method symbols should be fit in 9 bits */
508 #define MAXMSYMLEN 512
509 /* maximum symbol numbers */
510 #define MAXSYMLEN 65536
512 static int
513 new_msym(codegen_scope *s, mrb_sym sym)
515 size_t i, len;
517 mrb_assert(s->irep);
519 len = s->irep->slen;
520 if (len > MAXMSYMLEN) len = MAXMSYMLEN;
521 for (i=0; i<len; i++) {
522 if (s->irep->syms[i] == sym) return i;
523 if (s->irep->syms[i] == 0) break;
525 if (i == MAXMSYMLEN) {
526 codegen_error(s, "too many symbols (max " MRB_STRINGIZE(MAXMSYMLEN) ")");
528 s->irep->syms[i] = sym;
529 if (i == s->irep->slen) s->irep->slen++;
530 return i;
533 static int
534 new_sym(codegen_scope *s, mrb_sym sym)
536 size_t i;
538 for (i=0; i<s->irep->slen; i++) {
539 if (s->irep->syms[i] == sym) return i;
541 if (s->irep->slen == MAXSYMLEN) {
542 codegen_error(s, "too many symbols (max " MRB_STRINGIZE(MAXSYMLEN) ")");
545 if (s->irep->slen > MAXMSYMLEN/2 && s->scapa == MAXMSYMLEN) {
546 s->scapa = MAXSYMLEN;
547 s->irep->syms = (mrb_sym *)codegen_realloc(s, s->irep->syms, sizeof(mrb_sym)*MAXSYMLEN);
548 for (i = s->irep->slen; i < MAXMSYMLEN; i++) {
549 static const mrb_sym mrb_sym_zero = { 0 };
550 s->irep->syms[i] = mrb_sym_zero;
552 s->irep->slen = MAXMSYMLEN;
554 s->irep->syms[s->irep->slen] = sym;
555 return s->irep->slen++;
558 static int
559 node_len(node *tree)
561 int n = 0;
563 while (tree) {
564 n++;
565 tree = tree->cdr;
567 return n;
570 #define sym(x) ((mrb_sym)(intptr_t)(x))
571 #define lv_name(lv) sym((lv)->car)
572 static int
573 lv_idx(codegen_scope *s, mrb_sym id)
575 node *lv = s->lv;
576 int n = 1;
578 while (lv) {
579 if (lv_name(lv) == id) return n;
580 n++;
581 lv = lv->cdr;
583 return 0;
586 static void
587 for_body(codegen_scope *s, node *tree)
589 codegen_scope *prev = s;
590 int idx;
591 struct loopinfo *lp;
592 node *n2;
593 mrb_code c;
595 /* generate receiver */
596 codegen(s, tree->cdr->car, VAL);
597 /* generate loop-block */
598 s = scope_new(s->mrb, s, NULL);
599 if (s == NULL) {
600 raise_error(prev, "unexpected scope");
603 push(); /* push for a block parameter */
605 /* generate loop variable */
606 n2 = tree->car;
607 genop(s, MKOP_Ax(OP_ENTER, 0x40000));
608 if (n2->car && !n2->car->cdr && !n2->cdr) {
609 gen_assignment(s, n2->car->car, 1, NOVAL);
611 else {
612 gen_vmassignment(s, n2, 1, VAL);
614 /* construct loop */
615 lp = loop_push(s, LOOP_FOR);
616 lp->pc2 = new_label(s);
618 /* loop body */
619 codegen(s, tree->cdr->cdr->car, VAL);
620 pop();
621 if (s->pc > 0) {
622 c = s->iseq[s->pc-1];
623 if (GET_OPCODE(c) != OP_RETURN || GETARG_B(c) != OP_R_NORMAL || s->pc == s->lastlabel)
624 genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
626 loop_pop(s, NOVAL);
627 scope_finish(s);
628 s = prev;
629 genop(s, MKOP_Abc(OP_LAMBDA, cursp(), s->irep->rlen-1, OP_L_BLOCK));
630 pop();
631 idx = new_msym(s, mrb_intern_lit(s->mrb, "each"));
632 genop(s, MKOP_ABC(OP_SENDB, cursp(), idx, 0));
635 static int
636 lambda_body(codegen_scope *s, node *tree, int blk)
638 mrb_code c;
639 codegen_scope *parent = s;
640 s = scope_new(s->mrb, s, tree->car);
641 if (s == NULL) {
642 raise_error(parent, "unexpected scope");
645 s->mscope = !blk;
647 if (blk) {
648 struct loopinfo *lp = loop_push(s, LOOP_BLOCK);
649 lp->pc1 = new_label(s);
651 tree = tree->cdr;
652 if (tree->car) {
653 mrb_aspec a;
654 int ma, oa, ra, pa, ka, kd, ba;
655 int pos, i;
656 node *n, *opt;
658 ma = node_len(tree->car->car);
659 n = tree->car->car;
660 while (n) {
661 n = n->cdr;
663 oa = node_len(tree->car->cdr->car);
664 ra = tree->car->cdr->cdr->car ? 1 : 0;
665 pa = node_len(tree->car->cdr->cdr->cdr->car);
666 ka = kd = 0;
667 ba = tree->car->cdr->cdr->cdr->cdr ? 1 : 0;
669 if (ma > 0x1f || oa > 0x1f || pa > 0x1f || ka > 0x1f) {
670 codegen_error(s, "too many formal arguments");
672 a = ((mrb_aspec)(ma & 0x1f) << 18)
673 | ((mrb_aspec)(oa & 0x1f) << 13)
674 | ((ra & 1) << 12)
675 | ((pa & 0x1f) << 7)
676 | ((ka & 0x1f) << 2)
677 | ((kd & 1)<< 1)
678 | (ba & 1);
679 s->ainfo = (((ma+oa) & 0x3f) << 6) /* (12bits = 6:1:5) */
680 | ((ra & 1) << 5)
681 | (pa & 0x1f);
682 genop(s, MKOP_Ax(OP_ENTER, a));
683 pos = new_label(s);
684 for (i=0; i<oa; i++) {
685 new_label(s);
686 genop(s, MKOP_sBx(OP_JMP, 0));
688 if (oa > 0) {
689 genop(s, MKOP_sBx(OP_JMP, 0));
691 opt = tree->car->cdr->car;
692 i = 0;
693 while (opt) {
694 int idx;
696 dispatch(s, pos+i);
697 codegen(s, opt->car->cdr, VAL);
698 idx = lv_idx(s, (mrb_sym)(intptr_t)opt->car->car);
699 pop();
700 genop_peep(s, MKOP_AB(OP_MOVE, idx, cursp()), NOVAL);
701 i++;
702 opt = opt->cdr;
704 if (oa > 0) {
705 dispatch(s, pos+i);
708 codegen(s, tree->cdr->car, VAL);
709 pop();
710 if (s->pc > 0) {
711 c = s->iseq[s->pc-1];
712 if (GET_OPCODE(c) != OP_RETURN || GETARG_B(c) != OP_R_NORMAL || s->pc == s->lastlabel) {
713 if (s->nregs == 0) {
714 genop(s, MKOP_A(OP_LOADNIL, 0));
715 genop(s, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
717 else {
718 genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
722 if (blk) {
723 loop_pop(s, NOVAL);
725 scope_finish(s);
726 return parent->irep->rlen - 1;
729 static int
730 scope_body(codegen_scope *s, node *tree, int val)
732 codegen_scope *scope = scope_new(s->mrb, s, tree->car);
733 if (scope == NULL) {
734 raise_error(s, "unexpected scope");
737 codegen(scope, tree->cdr, VAL);
738 if (!s->iseq) {
739 genop(scope, MKOP_A(OP_STOP, 0));
741 else if (!val) {
742 genop(scope, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
744 else {
745 if (scope->nregs == 0) {
746 genop(scope, MKOP_A(OP_LOADNIL, 0));
747 genop(scope, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
749 else {
750 genop_peep(scope, MKOP_AB(OP_RETURN, scope->sp-1, OP_R_NORMAL), NOVAL);
753 scope_finish(scope);
754 if (!s->irep) {
755 /* should not happen */
756 return 0;
758 return s->irep->rlen - 1;
761 static mrb_bool
762 nosplat(node *t)
764 while (t) {
765 if ((intptr_t)t->car->car == NODE_SPLAT) return FALSE;
766 t = t->cdr;
768 return TRUE;
771 static mrb_sym
772 attrsym(codegen_scope *s, mrb_sym a)
774 const char *name;
775 mrb_int len;
776 char *name2;
778 name = mrb_sym2name_len(s->mrb, a, &len);
779 name2 = (char *)codegen_palloc(s,
780 (size_t)len
781 + 1 /* '=' */
782 + 1 /* '\0' */
784 mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX);
785 memcpy(name2, name, (size_t)len);
786 name2[len] = '=';
787 name2[len+1] = '\0';
789 return mrb_intern(s->mrb, name2, len+1);
792 #define CALL_MAXARGS 127
794 static int
795 gen_values(codegen_scope *s, node *t, int val, int extra)
797 int n = 0;
798 int is_splat;
800 while (t) {
801 is_splat = (intptr_t)t->car->car == NODE_SPLAT; /* splat mode */
802 if (
803 n+extra >= CALL_MAXARGS - 1 /* need to subtract one because vm.c expects an array if n == CALL_MAXARGS */
804 || is_splat) {
805 if (val) {
806 if (is_splat && n == 0 && (intptr_t)t->car->cdr->car == NODE_ARRAY) {
807 codegen(s, t->car->cdr, VAL);
808 pop();
810 else {
811 pop_n(n);
812 genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), n));
813 push();
814 codegen(s, t->car, VAL);
815 pop(); pop();
816 if (is_splat) {
817 genop(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1));
819 else {
820 genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
823 t = t->cdr;
824 while (t) {
825 push();
826 codegen(s, t->car, VAL);
827 pop(); pop();
828 if ((intptr_t)t->car->car == NODE_SPLAT) {
829 genop(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1));
831 else {
832 genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
834 t = t->cdr;
837 else {
838 while (t) {
839 codegen(s, t->car, NOVAL);
840 t = t->cdr;
843 return -1;
845 /* normal (no splat) mode */
846 codegen(s, t->car, val);
847 n++;
848 t = t->cdr;
850 return n;
853 static void
854 gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe)
856 mrb_sym sym = name ? name : sym(tree->cdr->car);
857 int idx, skip = 0;
858 int n = 0, noop = 0, sendv = 0, blk = 0;
860 codegen(s, tree->car, VAL); /* receiver */
861 if (safe) {
862 int recv = cursp()-1;
863 genop(s, MKOP_A(OP_LOADNIL, cursp()));
864 push();
865 genop(s, MKOP_AB(OP_MOVE, cursp(), recv));
866 push(); pop(); /* space for a block */
867 pop();
868 idx = new_msym(s, mrb_intern_lit(s->mrb, "=="));
869 genop(s, MKOP_ABC(OP_EQ, cursp(), idx, 1));
870 skip = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), 0));
872 idx = new_msym(s, sym);
873 tree = tree->cdr->cdr->car;
874 if (tree) {
875 n = gen_values(s, tree->car, VAL, sp?1:0);
876 if (n < 0) {
877 n = noop = sendv = 1;
878 push();
881 if (sp) {
882 if (sendv) {
883 pop();
884 genop(s, MKOP_AB(OP_ARYPUSH, cursp(), sp));
885 push();
887 else {
888 genop(s, MKOP_AB(OP_MOVE, cursp(), sp));
889 push();
890 n++;
893 if (tree && tree->cdr) {
894 noop = 1;
895 codegen(s, tree->cdr, VAL);
896 pop();
898 else {
899 blk = cursp();
901 push();pop();
902 pop_n(n+1);
904 mrb_int symlen;
905 const char *symname = mrb_sym2name_len(s->mrb, sym, &symlen);
907 if (!noop && symlen == 1 && symname[0] == '+' && n == 1) {
908 genop_peep(s, MKOP_ABC(OP_ADD, cursp(), idx, n), val);
910 else if (!noop && symlen == 1 && symname[0] == '-' && n == 1) {
911 genop_peep(s, MKOP_ABC(OP_SUB, cursp(), idx, n), val);
913 else if (!noop && symlen == 1 && symname[0] == '*' && n == 1) {
914 genop(s, MKOP_ABC(OP_MUL, cursp(), idx, n));
916 else if (!noop && symlen == 1 && symname[0] == '/' && n == 1) {
917 genop(s, MKOP_ABC(OP_DIV, cursp(), idx, n));
919 else if (!noop && symlen == 1 && symname[0] == '<' && n == 1) {
920 genop(s, MKOP_ABC(OP_LT, cursp(), idx, n));
922 else if (!noop && symlen == 2 && symname[0] == '<' && symname[1] == '=' && n == 1) {
923 genop(s, MKOP_ABC(OP_LE, cursp(), idx, n));
925 else if (!noop && symlen == 1 && symname[0] == '>' && n == 1) {
926 genop(s, MKOP_ABC(OP_GT, cursp(), idx, n));
928 else if (!noop && symlen == 2 && symname[0] == '>' && symname[1] == '=' && n == 1) {
929 genop(s, MKOP_ABC(OP_GE, cursp(), idx, n));
931 else if (!noop && symlen == 2 && symname[0] == '=' && symname[1] == '=' && n == 1) {
932 genop(s, MKOP_ABC(OP_EQ, cursp(), idx, n));
934 else {
935 if (sendv) n = CALL_MAXARGS;
936 if (blk > 0) { /* no block */
937 genop(s, MKOP_ABC(OP_SEND, cursp(), idx, n));
939 else {
940 genop(s, MKOP_ABC(OP_SENDB, cursp(), idx, n));
944 if (safe) {
945 dispatch(s, skip);
947 if (val) {
948 push();
952 static void
953 gen_assignment(codegen_scope *s, node *tree, int sp, int val)
955 int idx;
956 int type = (intptr_t)tree->car;
958 tree = tree->cdr;
959 switch ((intptr_t)type) {
960 case NODE_GVAR:
961 idx = new_sym(s, sym(tree));
962 genop_peep(s, MKOP_ABx(OP_SETGLOBAL, sp, idx), val);
963 break;
964 case NODE_LVAR:
965 idx = lv_idx(s, sym(tree));
966 if (idx > 0) {
967 if (idx != sp) {
968 genop_peep(s, MKOP_AB(OP_MOVE, idx, sp), val);
970 break;
972 else { /* upvar */
973 int lv = 0;
974 codegen_scope *up = s->prev;
976 while (up) {
977 idx = lv_idx(up, sym(tree));
978 if (idx > 0) {
979 genop_peep(s, MKOP_ABC(OP_SETUPVAR, sp, idx, lv), val);
980 break;
982 lv++;
983 up = up->prev;
986 break;
987 case NODE_IVAR:
988 idx = new_sym(s, sym(tree));
989 genop_peep(s, MKOP_ABx(OP_SETIV, sp, idx), val);
990 break;
991 case NODE_CVAR:
992 idx = new_sym(s, sym(tree));
993 genop_peep(s, MKOP_ABx(OP_SETCV, sp, idx), val);
994 break;
995 case NODE_CONST:
996 idx = new_sym(s, sym(tree));
997 genop_peep(s, MKOP_ABx(OP_SETCONST, sp, idx), val);
998 break;
999 case NODE_COLON2:
1000 idx = new_sym(s, sym(tree->cdr));
1001 genop_peep(s, MKOP_AB(OP_MOVE, cursp(), sp), NOVAL);
1002 push();
1003 codegen(s, tree->car, VAL);
1004 pop_n(2);
1005 genop_peep(s, MKOP_ABx(OP_SETMCNST, cursp(), idx), val);
1006 break;
1008 case NODE_CALL:
1009 push();
1010 gen_call(s, tree, attrsym(s, sym(tree->cdr->car)), sp, NOVAL, 0);
1011 pop();
1012 if (val) {
1013 genop_peep(s, MKOP_AB(OP_MOVE, cursp(), sp), val);
1015 break;
1017 case NODE_MASGN:
1018 gen_vmassignment(s, tree->car, sp, val);
1019 break;
1021 /* splat without assignment */
1022 case NODE_NIL:
1023 break;
1025 default:
1026 #ifndef MRB_DISABLE_STDIO
1027 fprintf(stderr, "unknown lhs %d\n", type);
1028 #endif
1029 return;
1031 if (val) push();
1034 static void
1035 gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val)
1037 int n = 0, post = 0;
1038 node *t, *p;
1040 if (tree->car) { /* pre */
1041 t = tree->car;
1042 n = 0;
1043 while (t) {
1044 genop(s, MKOP_ABC(OP_AREF, cursp(), rhs, n));
1045 gen_assignment(s, t->car, cursp(), NOVAL);
1046 n++;
1047 t = t->cdr;
1050 t = tree->cdr;
1051 if (t) {
1052 if (t->cdr) { /* post count */
1053 p = t->cdr->car;
1054 while (p) {
1055 post++;
1056 p = p->cdr;
1059 if (val) {
1060 genop(s, MKOP_AB(OP_MOVE, cursp(), rhs));
1062 else {
1063 pop();
1065 push_n(post);
1066 pop_n(post);
1067 genop(s, MKOP_ABC(OP_APOST, cursp(), n, post));
1068 n = 1;
1069 if (t->car) { /* rest */
1070 gen_assignment(s, t->car, cursp(), NOVAL);
1072 if (t->cdr && t->cdr->car) {
1073 t = t->cdr->car;
1074 while (t) {
1075 gen_assignment(s, t->car, cursp()+n, NOVAL);
1076 t = t->cdr;
1077 n++;
1080 if (!val) {
1081 push();
1086 static void
1087 gen_send_intern(codegen_scope *s)
1089 pop();
1090 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "intern")), 0));
1091 push();
1093 static void
1094 gen_literal_array(codegen_scope *s, node *tree, mrb_bool sym, int val)
1096 if (val) {
1097 int i = 0, j = 0;
1099 while (tree) {
1100 switch ((intptr_t)tree->car->car) {
1101 case NODE_STR:
1102 if ((tree->cdr == NULL) && ((intptr_t)tree->car->cdr->cdr == 0))
1103 break;
1104 /* fall through */
1105 case NODE_BEGIN:
1106 codegen(s, tree->car, VAL);
1107 ++j;
1108 break;
1110 case NODE_LITERAL_DELIM:
1111 if (j > 0) {
1112 j = 0;
1113 ++i;
1114 if (sym)
1115 gen_send_intern(s);
1117 break;
1119 if (j >= 2) {
1120 pop(); pop();
1121 genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
1122 push();
1123 j = 1;
1125 tree = tree->cdr;
1127 if (j > 0) {
1128 ++i;
1129 if (sym)
1130 gen_send_intern(s);
1132 pop_n(i);
1133 genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), i));
1134 push();
1136 else {
1137 while (tree) {
1138 switch ((intptr_t)tree->car->car) {
1139 case NODE_BEGIN: case NODE_BLOCK:
1140 codegen(s, tree->car, NOVAL);
1142 tree = tree->cdr;
1147 static void
1148 raise_error(codegen_scope *s, const char *msg)
1150 int idx = new_lit(s, mrb_str_new_cstr(s->mrb, msg));
1152 genop(s, MKOP_ABx(OP_ERR, 1, idx));
1155 static double
1156 readint_float(codegen_scope *s, const char *p, int base)
1158 const char *e = p + strlen(p);
1159 double f = 0;
1160 int n;
1162 if (*p == '+') p++;
1163 while (p < e) {
1164 char c = *p;
1165 c = tolower((unsigned char)c);
1166 for (n=0; n<base; n++) {
1167 if (mrb_digitmap[n] == c) {
1168 f *= base;
1169 f += n;
1170 break;
1173 if (n == base) {
1174 codegen_error(s, "malformed readint input");
1176 p++;
1178 return f;
1181 static mrb_int
1182 readint_mrb_int(codegen_scope *s, const char *p, int base, mrb_bool neg, mrb_bool *overflow)
1184 const char *e = p + strlen(p);
1185 mrb_int result = 0;
1186 int n;
1188 mrb_assert(base >= 2 && base <= 36);
1189 if (*p == '+') p++;
1190 while (p < e) {
1191 char c = *p;
1192 c = tolower((unsigned char)c);
1193 for (n=0; n<base; n++) {
1194 if (mrb_digitmap[n] == c) {
1195 break;
1198 if (n == base) {
1199 codegen_error(s, "malformed readint input");
1202 if (neg) {
1203 if ((MRB_INT_MIN + n)/base > result) {
1204 *overflow = TRUE;
1205 return 0;
1207 result *= base;
1208 result -= n;
1210 else {
1211 if ((MRB_INT_MAX - n)/base < result) {
1212 *overflow = TRUE;
1213 return 0;
1215 result *= base;
1216 result += n;
1218 p++;
1220 *overflow = FALSE;
1221 return result;
1224 static void
1225 gen_retval(codegen_scope *s, node *tree)
1227 if ((intptr_t)tree->car == NODE_SPLAT) {
1228 genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), 0));
1229 push();
1230 codegen(s, tree, VAL);
1231 pop(); pop();
1232 genop(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1));
1234 else {
1235 codegen(s, tree, VAL);
1236 pop();
1240 static void
1241 codegen(codegen_scope *s, node *tree, int val)
1243 int nt;
1245 if (!tree) {
1246 if (val) {
1247 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1248 push();
1250 return;
1253 if (s->irep && s->filename_index != tree->filename_index) {
1254 s->irep->filename = mrb_parser_get_filename(s->parser, s->filename_index);
1255 mrb_debug_info_append_file(s->mrb, s->irep, s->debug_start_pos, s->pc);
1256 s->debug_start_pos = s->pc;
1257 s->filename_index = tree->filename_index;
1258 s->filename = mrb_parser_get_filename(s->parser, tree->filename_index);
1261 nt = (intptr_t)tree->car;
1262 s->lineno = tree->lineno;
1263 tree = tree->cdr;
1264 switch (nt) {
1265 case NODE_BEGIN:
1266 if (val && !tree) {
1267 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1268 push();
1270 while (tree) {
1271 codegen(s, tree->car, tree->cdr ? NOVAL : val);
1272 tree = tree->cdr;
1274 break;
1276 case NODE_RESCUE:
1278 int onerr, noexc, exend, pos1, pos2, tmp;
1279 struct loopinfo *lp;
1281 if (tree->car == NULL) return;
1282 onerr = genop(s, MKOP_Bx(OP_ONERR, 0));
1283 lp = loop_push(s, LOOP_BEGIN);
1284 lp->pc1 = onerr;
1285 codegen(s, tree->car, VAL);
1286 pop();
1287 lp->type = LOOP_RESCUE;
1288 noexc = genop(s, MKOP_Bx(OP_JMP, 0));
1289 dispatch(s, onerr);
1290 tree = tree->cdr;
1291 exend = 0;
1292 pos1 = 0;
1293 if (tree->car) {
1294 node *n2 = tree->car;
1295 int exc = cursp();
1297 genop(s, MKOP_ABC(OP_RESCUE, exc, 0, 0));
1298 push();
1299 while (n2) {
1300 node *n3 = n2->car;
1301 node *n4 = n3->car;
1303 if (pos1) dispatch(s, pos1);
1304 pos2 = 0;
1305 do {
1306 if (n4 && n4->car && (intptr_t)n4->car->car == NODE_SPLAT) {
1307 codegen(s, n4->car, VAL);
1308 genop(s, MKOP_AB(OP_MOVE, cursp(), exc));
1309 pop();
1310 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1));
1312 else {
1313 if (n4) {
1314 codegen(s, n4->car, VAL);
1316 else {
1317 genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "StandardError"))));
1318 push();
1320 pop();
1321 genop(s, MKOP_ABC(OP_RESCUE, exc, cursp(), 1));
1323 tmp = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2));
1324 pos2 = tmp;
1325 if (n4) {
1326 n4 = n4->cdr;
1328 } while (n4);
1329 pos1 = genop(s, MKOP_sBx(OP_JMP, 0));
1330 dispatch_linked(s, pos2);
1332 pop();
1333 if (n3->cdr->car) {
1334 gen_assignment(s, n3->cdr->car, exc, NOVAL);
1336 if (n3->cdr->cdr->car) {
1337 codegen(s, n3->cdr->cdr->car, val);
1338 if (val) pop();
1340 tmp = genop(s, MKOP_sBx(OP_JMP, exend));
1341 exend = tmp;
1342 n2 = n2->cdr;
1343 push();
1345 if (pos1) {
1346 dispatch(s, pos1);
1347 genop(s, MKOP_A(OP_RAISE, exc));
1350 pop();
1351 tree = tree->cdr;
1352 dispatch(s, noexc);
1353 genop(s, MKOP_A(OP_POPERR, 1));
1354 if (tree->car) {
1355 codegen(s, tree->car, val);
1357 else if (val) {
1358 push();
1360 dispatch_linked(s, exend);
1361 loop_pop(s, NOVAL);
1363 break;
1365 case NODE_ENSURE:
1366 if (!tree->cdr || !tree->cdr->cdr ||
1367 ((intptr_t)tree->cdr->cdr->car == NODE_BEGIN &&
1368 tree->cdr->cdr->cdr)) {
1369 int idx;
1370 int epush = s->pc;
1372 genop(s, MKOP_Bx(OP_EPUSH, 0));
1373 s->ensure_level++;
1374 codegen(s, tree->car, val);
1375 idx = scope_body(s, tree->cdr, NOVAL);
1376 s->iseq[epush] = MKOP_Bx(OP_EPUSH, idx);
1377 s->ensure_level--;
1378 genop_peep(s, MKOP_A(OP_EPOP, 1), NOVAL);
1380 else { /* empty ensure ignored */
1381 codegen(s, tree->car, val);
1383 break;
1385 case NODE_LAMBDA:
1386 if (val) {
1387 int idx = lambda_body(s, tree, 1);
1389 genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_LAMBDA));
1390 push();
1392 break;
1394 case NODE_BLOCK:
1395 if (val) {
1396 int idx = lambda_body(s, tree, 1);
1398 genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_BLOCK));
1399 push();
1401 break;
1403 case NODE_IF:
1405 int pos1, pos2;
1406 node *e = tree->cdr->cdr->car;
1408 if (!tree->car) {
1409 codegen(s, e, val);
1410 return;
1412 switch ((intptr_t)tree->car->car) {
1413 case NODE_TRUE:
1414 case NODE_INT:
1415 case NODE_STR:
1416 codegen(s, tree->cdr->car, val);
1417 return;
1418 case NODE_FALSE:
1419 case NODE_NIL:
1420 codegen(s, e, val);
1421 return;
1423 codegen(s, tree->car, VAL);
1424 pop();
1425 pos1 = genop_peep(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0), NOVAL);
1427 codegen(s, tree->cdr->car, val);
1428 if (e) {
1429 if (val) pop();
1430 pos2 = genop(s, MKOP_sBx(OP_JMP, 0));
1431 dispatch(s, pos1);
1432 codegen(s, e, val);
1433 dispatch(s, pos2);
1435 else {
1436 if (val) {
1437 pop();
1438 pos2 = genop(s, MKOP_sBx(OP_JMP, 0));
1439 dispatch(s, pos1);
1440 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1441 dispatch(s, pos2);
1442 push();
1444 else {
1445 dispatch(s, pos1);
1449 break;
1451 case NODE_AND:
1453 int pos;
1455 codegen(s, tree->car, VAL);
1456 pop();
1457 pos = genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0));
1458 codegen(s, tree->cdr, val);
1459 dispatch(s, pos);
1461 break;
1463 case NODE_OR:
1465 int pos;
1467 codegen(s, tree->car, VAL);
1468 pop();
1469 pos = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), 0));
1470 codegen(s, tree->cdr, val);
1471 dispatch(s, pos);
1473 break;
1475 case NODE_WHILE:
1477 struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
1479 lp->pc1 = genop(s, MKOP_sBx(OP_JMP, 0));
1480 lp->pc2 = new_label(s);
1481 codegen(s, tree->cdr, NOVAL);
1482 dispatch(s, lp->pc1);
1483 codegen(s, tree->car, VAL);
1484 pop();
1485 genop(s, MKOP_AsBx(OP_JMPIF, cursp(), lp->pc2 - s->pc));
1487 loop_pop(s, val);
1489 break;
1491 case NODE_UNTIL:
1493 struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
1495 lp->pc1 = genop(s, MKOP_sBx(OP_JMP, 0));
1496 lp->pc2 = new_label(s);
1497 codegen(s, tree->cdr, NOVAL);
1498 dispatch(s, lp->pc1);
1499 codegen(s, tree->car, VAL);
1500 pop();
1501 genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), lp->pc2 - s->pc));
1503 loop_pop(s, val);
1505 break;
1507 case NODE_FOR:
1508 for_body(s, tree);
1509 if (val) push();
1510 break;
1512 case NODE_CASE:
1514 int head = 0;
1515 int pos1, pos2, pos3, tmp;
1516 node *n;
1518 pos3 = 0;
1519 if (tree->car) {
1520 head = cursp();
1521 codegen(s, tree->car, VAL);
1523 tree = tree->cdr;
1524 while (tree) {
1525 n = tree->car->car;
1526 pos1 = pos2 = 0;
1527 while (n) {
1528 codegen(s, n->car, VAL);
1529 if (head) {
1530 genop(s, MKOP_AB(OP_MOVE, cursp(), head));
1531 pop();
1532 if ((intptr_t)n->car->car == NODE_SPLAT) {
1533 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1));
1535 else {
1536 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "===")), 1));
1539 else {
1540 pop();
1542 tmp = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2));
1543 pos2 = tmp;
1544 n = n->cdr;
1546 if (tree->car->car) {
1547 pos1 = genop(s, MKOP_sBx(OP_JMP, 0));
1548 dispatch_linked(s, pos2);
1550 codegen(s, tree->car->cdr, val);
1551 if (val) pop();
1552 tmp = genop(s, MKOP_sBx(OP_JMP, pos3));
1553 pos3 = tmp;
1554 if (pos1) dispatch(s, pos1);
1555 tree = tree->cdr;
1557 if (val) {
1558 int pos = cursp();
1559 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1560 if (pos3) dispatch_linked(s, pos3);
1561 if (head) pop();
1562 if (cursp() != pos) {
1563 genop(s, MKOP_AB(OP_MOVE, cursp(), pos));
1565 push();
1567 else {
1568 if (pos3) {
1569 dispatch_linked(s, pos3);
1571 if (head) {
1572 pop();
1576 break;
1578 case NODE_SCOPE:
1579 scope_body(s, tree, NOVAL);
1580 break;
1582 case NODE_FCALL:
1583 case NODE_CALL:
1584 gen_call(s, tree, 0, 0, val, 0);
1585 break;
1586 case NODE_SCALL:
1587 gen_call(s, tree, 0, 0, val, 1);
1588 break;
1590 case NODE_DOT2:
1591 codegen(s, tree->car, val);
1592 codegen(s, tree->cdr, val);
1593 if (val) {
1594 pop(); pop();
1595 genop(s, MKOP_ABC(OP_RANGE, cursp(), cursp(), FALSE));
1596 push();
1598 break;
1600 case NODE_DOT3:
1601 codegen(s, tree->car, val);
1602 codegen(s, tree->cdr, val);
1603 if (val) {
1604 pop(); pop();
1605 genop(s, MKOP_ABC(OP_RANGE, cursp(), cursp(), TRUE));
1606 push();
1608 break;
1610 case NODE_COLON2:
1612 int sym = new_sym(s, sym(tree->cdr));
1614 codegen(s, tree->car, VAL);
1615 pop();
1616 genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
1617 if (val) push();
1619 break;
1621 case NODE_COLON3:
1623 int sym = new_sym(s, sym(tree));
1625 genop(s, MKOP_A(OP_OCLASS, cursp()));
1626 genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
1627 if (val) push();
1629 break;
1631 case NODE_ARRAY:
1633 int n;
1635 n = gen_values(s, tree, val, 0);
1636 if (n >= 0) {
1637 if (val) {
1638 pop_n(n);
1639 genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), n));
1640 push();
1643 else if (val) {
1644 push();
1647 break;
1649 case NODE_HASH:
1651 int len = 0;
1652 mrb_bool update = FALSE;
1654 while (tree) {
1655 codegen(s, tree->car->car, val);
1656 codegen(s, tree->car->cdr, val);
1657 len++;
1658 tree = tree->cdr;
1659 if (val && len == 126) {
1660 pop_n(len*2);
1661 genop(s, MKOP_ABC(OP_HASH, cursp(), cursp(), len));
1662 if (update) {
1663 pop();
1664 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__update")), 1));
1666 push();
1667 update = TRUE;
1668 len = 0;
1671 if (val) {
1672 pop_n(len*2);
1673 genop(s, MKOP_ABC(OP_HASH, cursp(), cursp(), len));
1674 if (update) {
1675 pop();
1676 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__update")), 1));
1678 push();
1681 break;
1683 case NODE_SPLAT:
1684 codegen(s, tree, val);
1685 break;
1687 case NODE_ASGN:
1688 codegen(s, tree->cdr, VAL);
1689 pop();
1690 gen_assignment(s, tree->car, cursp(), val);
1691 break;
1693 case NODE_MASGN:
1695 int len = 0, n = 0, post = 0;
1696 node *t = tree->cdr, *p;
1697 int rhs = cursp();
1699 if ((intptr_t)t->car == NODE_ARRAY && t->cdr && nosplat(t->cdr)) {
1700 /* fixed rhs */
1701 t = t->cdr;
1702 while (t) {
1703 codegen(s, t->car, VAL);
1704 len++;
1705 t = t->cdr;
1707 tree = tree->car;
1708 if (tree->car) { /* pre */
1709 t = tree->car;
1710 n = 0;
1711 while (t) {
1712 if (n < len) {
1713 gen_assignment(s, t->car, rhs+n, NOVAL);
1714 n++;
1716 else {
1717 genop(s, MKOP_A(OP_LOADNIL, rhs+n));
1718 gen_assignment(s, t->car, rhs+n, NOVAL);
1720 t = t->cdr;
1723 t = tree->cdr;
1724 if (t) {
1725 if (t->cdr) { /* post count */
1726 p = t->cdr->car;
1727 while (p) {
1728 post++;
1729 p = p->cdr;
1732 if (t->car) { /* rest (len - pre - post) */
1733 int rn;
1735 if (len < post + n) {
1736 rn = 0;
1738 else {
1739 rn = len - post - n;
1741 genop(s, MKOP_ABC(OP_ARRAY, cursp(), rhs+n, rn));
1742 gen_assignment(s, t->car, cursp(), NOVAL);
1743 n += rn;
1745 if (t->cdr && t->cdr->car) {
1746 t = t->cdr->car;
1747 while (n<len) {
1748 gen_assignment(s, t->car, rhs+n, NOVAL);
1749 t = t->cdr;
1750 n++;
1754 pop_n(len);
1755 if (val) {
1756 genop(s, MKOP_ABC(OP_ARRAY, rhs, rhs, len));
1757 push();
1760 else {
1761 /* variable rhs */
1762 codegen(s, t, VAL);
1763 gen_vmassignment(s, tree->car, rhs, val);
1764 if (!val) {
1765 pop();
1769 break;
1771 case NODE_OP_ASGN:
1773 mrb_sym sym = sym(tree->cdr->car);
1774 mrb_int len;
1775 const char *name = mrb_sym2name_len(s->mrb, sym, &len);
1776 int idx, callargs = -1, vsp = -1;
1778 if ((len == 2 && name[0] == '|' && name[1] == '|') &&
1779 ((intptr_t)tree->car->car == NODE_CONST ||
1780 (intptr_t)tree->car->car == NODE_CVAR)) {
1781 int onerr, noexc, exc;
1782 struct loopinfo *lp;
1784 onerr = genop(s, MKOP_Bx(OP_ONERR, 0));
1785 lp = loop_push(s, LOOP_BEGIN);
1786 lp->pc1 = onerr;
1787 exc = cursp();
1788 codegen(s, tree->car, VAL);
1789 lp->type = LOOP_RESCUE;
1790 genop(s, MKOP_A(OP_POPERR, 1));
1791 noexc = genop(s, MKOP_Bx(OP_JMP, 0));
1792 dispatch(s, onerr);
1793 genop(s, MKOP_ABC(OP_RESCUE, exc, 0, 0));
1794 genop(s, MKOP_A(OP_LOADF, exc));
1795 dispatch(s, noexc);
1796 loop_pop(s, NOVAL);
1798 else if ((intptr_t)tree->car->car == NODE_CALL) {
1799 node *n = tree->car->cdr;
1801 if (val) {
1802 vsp = cursp();
1803 push();
1805 codegen(s, n->car, VAL); /* receiver */
1806 idx = new_msym(s, sym(n->cdr->car));
1807 if (n->cdr->cdr->car) {
1808 int base = cursp()-1;
1809 int nargs = gen_values(s, n->cdr->cdr->car->car, VAL, 1);
1811 /* copy receiver and arguments */
1812 if (nargs >= 0) {
1813 int i;
1815 genop(s, MKOP_AB(OP_MOVE, cursp(), base));
1816 for (i=0; i<nargs; i++) {
1817 genop(s, MKOP_AB(OP_MOVE, cursp()+i+1, base+i+1));
1819 push_n(nargs+1);
1820 pop_n(nargs+1);
1821 callargs = nargs;
1823 else {
1824 /* varargs */
1825 push();
1826 genop(s, MKOP_AB(OP_MOVE, cursp(), base));
1827 genop(s, MKOP_AB(OP_MOVE, cursp()+1, base+1));
1828 callargs = CALL_MAXARGS;
1830 genop(s, MKOP_ABC(OP_SEND, cursp(), idx, callargs));
1832 else {
1833 genop(s, MKOP_AB(OP_MOVE, cursp(), cursp()-1));
1834 genop(s, MKOP_ABC(OP_SEND, cursp(), idx, 0));
1835 callargs = 0;
1837 push();
1839 else {
1840 codegen(s, tree->car, VAL);
1842 if (len == 2 &&
1843 ((name[0] == '|' && name[1] == '|') ||
1844 (name[0] == '&' && name[1] == '&'))) {
1845 int pos;
1847 pop();
1848 if (val) {
1849 if (vsp >= 0) {
1850 genop(s, MKOP_AB(OP_MOVE, vsp, cursp()));
1852 pos = genop(s, MKOP_AsBx(name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0));
1854 else {
1855 pos = genop_peep(s, MKOP_AsBx(name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0), NOVAL);
1857 codegen(s, tree->cdr->cdr->car, VAL);
1858 pop();
1859 if (val && vsp >= 0) {
1860 genop(s, MKOP_AB(OP_MOVE, vsp, cursp()));
1862 if ((intptr_t)tree->car->car == NODE_CALL) {
1863 mrb_sym m = sym(tree->car->cdr->cdr->car);
1864 mrb_sym m2 = attrsym(s, m);
1866 idx = new_msym(s, m2);
1867 pop();
1868 if (callargs == CALL_MAXARGS) {
1869 genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
1870 pop();
1871 genop(s, MKOP_ABC(OP_SEND, cursp(), idx, callargs));
1873 else {
1874 pop_n(callargs);
1875 genop(s, MKOP_ABC(OP_SEND, cursp(), idx, callargs+1));
1878 else {
1879 gen_assignment(s, tree->car, cursp(), val);
1881 dispatch(s, pos);
1882 return;
1884 codegen(s, tree->cdr->cdr->car, VAL);
1885 push(); pop();
1886 pop(); pop();
1888 idx = new_msym(s, sym);
1889 if (len == 1 && name[0] == '+') {
1890 genop_peep(s, MKOP_ABC(OP_ADD, cursp(), idx, 1), val);
1892 else if (len == 1 && name[0] == '-') {
1893 genop_peep(s, MKOP_ABC(OP_SUB, cursp(), idx, 1), val);
1895 else if (len == 1 && name[0] == '*') {
1896 genop(s, MKOP_ABC(OP_MUL, cursp(), idx, 1));
1898 else if (len == 1 && name[0] == '/') {
1899 genop(s, MKOP_ABC(OP_DIV, cursp(), idx, 1));
1901 else if (len == 1 && name[0] == '<') {
1902 genop(s, MKOP_ABC(OP_LT, cursp(), idx, 1));
1904 else if (len == 2 && name[0] == '<' && name[1] == '=') {
1905 genop(s, MKOP_ABC(OP_LE, cursp(), idx, 1));
1907 else if (len == 1 && name[0] == '>') {
1908 genop(s, MKOP_ABC(OP_GT, cursp(), idx, 1));
1910 else if (len == 2 && name[0] == '>' && name[1] == '=') {
1911 genop(s, MKOP_ABC(OP_GE, cursp(), idx, 1));
1913 else {
1914 genop(s, MKOP_ABC(OP_SEND, cursp(), idx, 1));
1916 if (callargs < 0) {
1917 gen_assignment(s, tree->car, cursp(), val);
1919 else {
1920 if (val && vsp >= 0) {
1921 genop(s, MKOP_AB(OP_MOVE, vsp, cursp()));
1923 if (callargs == CALL_MAXARGS) {
1924 pop();
1925 genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
1927 else {
1928 pop_n(callargs);
1929 callargs++;
1931 pop();
1932 idx = new_msym(s, attrsym(s,sym(tree->car->cdr->cdr->car)));
1933 genop(s, MKOP_ABC(OP_SEND, cursp(), idx, callargs));
1936 break;
1938 case NODE_SUPER:
1940 int n = 0, noop = 0, sendv = 0;
1942 push(); /* room for receiver */
1943 if (tree) {
1944 node *args = tree->car;
1945 if (args) {
1946 n = gen_values(s, args, VAL, 0);
1947 if (n < 0) {
1948 n = noop = sendv = 1;
1949 push();
1953 if (tree && tree->cdr) {
1954 codegen(s, tree->cdr, VAL);
1955 pop();
1957 else {
1958 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1959 push(); pop();
1961 pop_n(n+1);
1962 if (sendv) n = CALL_MAXARGS;
1963 genop(s, MKOP_ABC(OP_SUPER, cursp(), 0, n));
1964 if (val) push();
1966 break;
1968 case NODE_ZSUPER:
1970 codegen_scope *s2 = s;
1971 int lv = 0, ainfo = 0;
1973 push(); /* room for receiver */
1974 while (!s2->mscope) {
1975 lv++;
1976 s2 = s2->prev;
1977 if (!s2) break;
1979 if (s2) ainfo = s2->ainfo;
1980 genop(s, MKOP_ABx(OP_ARGARY, cursp(), (ainfo<<4)|(lv & 0xf)));
1981 push(); push(); pop(); /* ARGARY pushes two values */
1982 if (tree && tree->cdr) {
1983 codegen(s, tree->cdr, VAL);
1984 pop();
1986 pop(); pop();
1987 genop(s, MKOP_ABC(OP_SUPER, cursp(), 0, CALL_MAXARGS));
1988 if (val) push();
1990 break;
1992 case NODE_RETURN:
1993 if (tree) {
1994 gen_retval(s, tree);
1996 else {
1997 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1999 if (s->loop) {
2000 genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_RETURN));
2002 else {
2003 genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
2005 if (val) push();
2006 break;
2008 case NODE_YIELD:
2010 codegen_scope *s2 = s;
2011 int lv = 0, ainfo = 0;
2012 int n = 0, sendv = 0;
2014 while (!s2->mscope) {
2015 lv++;
2016 s2 = s2->prev;
2017 if (!s2) break;
2019 if (s2) ainfo = s2->ainfo;
2020 push();
2021 if (tree) {
2022 n = gen_values(s, tree, VAL, 0);
2023 if (n < 0) {
2024 n = sendv = 1;
2025 push();
2028 pop_n(n+1);
2029 genop(s, MKOP_ABx(OP_BLKPUSH, cursp(), (ainfo<<4)|(lv & 0xf)));
2030 if (sendv) n = CALL_MAXARGS;
2031 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "call")), n));
2032 if (val) push();
2034 break;
2036 case NODE_BREAK:
2037 loop_break(s, tree);
2038 if (val) push();
2039 break;
2041 case NODE_NEXT:
2042 if (!s->loop) {
2043 raise_error(s, "unexpected next");
2045 else if (s->loop->type == LOOP_NORMAL) {
2046 if (s->ensure_level > s->loop->ensure_level) {
2047 genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL);
2049 codegen(s, tree, NOVAL);
2050 genop(s, MKOP_sBx(OP_JMP, s->loop->pc1 - s->pc));
2052 else {
2053 if (tree) {
2054 codegen(s, tree, VAL);
2055 pop();
2057 else {
2058 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2060 genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
2062 if (val) push();
2063 break;
2065 case NODE_REDO:
2066 if (!s->loop || s->loop->type == LOOP_BEGIN || s->loop->type == LOOP_RESCUE) {
2067 raise_error(s, "unexpected redo");
2069 else {
2070 if (s->ensure_level > s->loop->ensure_level) {
2071 genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL);
2073 genop(s, MKOP_sBx(OP_JMP, s->loop->pc2 - s->pc));
2075 if (val) push();
2076 break;
2078 case NODE_RETRY:
2080 const char *msg = "unexpected retry";
2082 if (!s->loop) {
2083 raise_error(s, msg);
2085 else {
2086 struct loopinfo *lp = s->loop;
2087 int n = 0;
2089 while (lp && lp->type != LOOP_RESCUE) {
2090 if (lp->type == LOOP_BEGIN) {
2091 n++;
2093 lp = lp->prev;
2095 if (!lp) {
2096 raise_error(s, msg);
2098 else {
2099 if (n > 0) {
2100 while (n--) {
2101 genop_peep(s, MKOP_A(OP_POPERR, 1), NOVAL);
2104 if (s->ensure_level > lp->ensure_level) {
2105 genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - lp->ensure_level), NOVAL);
2107 genop(s, MKOP_sBx(OP_JMP, lp->pc1 - s->pc));
2110 if (val) push();
2112 break;
2114 case NODE_LVAR:
2115 if (val) {
2116 int idx = lv_idx(s, sym(tree));
2118 if (idx > 0) {
2119 genop_peep(s, MKOP_AB(OP_MOVE, cursp(), idx), NOVAL);
2121 else {
2122 int lv = 0;
2123 codegen_scope *up = s->prev;
2125 while (up) {
2126 idx = lv_idx(up, sym(tree));
2127 if (idx > 0) {
2128 genop(s, MKOP_ABC(OP_GETUPVAR, cursp(), idx, lv));
2129 break;
2131 lv++;
2132 up = up->prev;
2135 push();
2137 break;
2139 case NODE_GVAR:
2140 if (val) {
2141 int sym = new_sym(s, sym(tree));
2143 genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
2144 push();
2146 break;
2148 case NODE_IVAR:
2149 if (val) {
2150 int sym = new_sym(s, sym(tree));
2152 genop(s, MKOP_ABx(OP_GETIV, cursp(), sym));
2153 push();
2155 break;
2157 case NODE_CVAR:
2158 if (val) {
2159 int sym = new_sym(s, sym(tree));
2161 genop(s, MKOP_ABx(OP_GETCV, cursp(), sym));
2162 push();
2164 break;
2166 case NODE_CONST:
2168 int sym = new_sym(s, sym(tree));
2170 genop(s, MKOP_ABx(OP_GETCONST, cursp(), sym));
2171 if (val) {
2172 push();
2175 break;
2177 case NODE_DEFINED:
2178 codegen(s, tree, VAL);
2179 break;
2181 case NODE_BACK_REF:
2182 if (val) {
2183 char buf[3];
2184 int sym;
2186 buf[0] = '$';
2187 buf[1] = (char)(intptr_t)tree;
2188 buf[2] = 0;
2189 sym = new_sym(s, mrb_intern_cstr(s->mrb, buf));
2190 genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
2191 push();
2193 break;
2195 case NODE_NTH_REF:
2196 if (val) {
2197 mrb_state *mrb = s->mrb;
2198 mrb_value str;
2199 int sym;
2201 str = mrb_format(mrb, "$%S", mrb_fixnum_value((mrb_int)(intptr_t)tree));
2202 sym = new_sym(s, mrb_intern_str(mrb, str));
2203 genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
2204 push();
2206 break;
2208 case NODE_ARG:
2209 /* should not happen */
2210 break;
2212 case NODE_BLOCK_ARG:
2213 codegen(s, tree, VAL);
2214 break;
2216 case NODE_INT:
2217 if (val) {
2218 char *p = (char*)tree->car;
2219 int base = (intptr_t)tree->cdr->car;
2220 mrb_int i;
2221 mrb_code co;
2222 mrb_bool overflow;
2224 i = readint_mrb_int(s, p, base, FALSE, &overflow);
2225 if (overflow) {
2226 double f = readint_float(s, p, base);
2227 int off = new_lit(s, mrb_float_value(s->mrb, f));
2229 genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
2231 else {
2232 if (i < MAXARG_sBx && i > -MAXARG_sBx) {
2233 co = MKOP_AsBx(OP_LOADI, cursp(), i);
2235 else {
2236 int off = new_lit(s, mrb_fixnum_value(i));
2237 co = MKOP_ABx(OP_LOADL, cursp(), off);
2239 genop(s, co);
2241 push();
2243 break;
2245 case NODE_FLOAT:
2246 if (val) {
2247 char *p = (char*)tree;
2248 mrb_float f = mrb_float_read(p, NULL);
2249 int off = new_lit(s, mrb_float_value(s->mrb, f));
2251 genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
2252 push();
2254 break;
2256 case NODE_NEGATE:
2258 nt = (intptr_t)tree->car;
2259 tree = tree->cdr;
2260 switch (nt) {
2261 case NODE_FLOAT:
2262 if (val) {
2263 char *p = (char*)tree;
2264 mrb_float f = mrb_float_read(p, NULL);
2265 int off = new_lit(s, mrb_float_value(s->mrb, -f));
2267 genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
2268 push();
2270 break;
2272 case NODE_INT:
2273 if (val) {
2274 char *p = (char*)tree->car;
2275 int base = (intptr_t)tree->cdr->car;
2276 mrb_int i;
2277 mrb_code co;
2278 mrb_bool overflow;
2280 i = readint_mrb_int(s, p, base, TRUE, &overflow);
2281 if (overflow) {
2282 double f = readint_float(s, p, base);
2283 int off = new_lit(s, mrb_float_value(s->mrb, -f));
2285 genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
2287 else {
2288 if (i < MAXARG_sBx && i > -MAXARG_sBx) {
2289 co = MKOP_AsBx(OP_LOADI, cursp(), i);
2291 else {
2292 int off = new_lit(s, mrb_fixnum_value(i));
2293 co = MKOP_ABx(OP_LOADL, cursp(), off);
2295 genop(s, co);
2297 push();
2299 break;
2301 default:
2302 if (val) {
2303 int sym = new_msym(s, mrb_intern_lit(s->mrb, "-"));
2305 genop(s, MKOP_ABx(OP_LOADI, cursp(), 0));
2306 push();
2307 codegen(s, tree, VAL);
2308 pop(); pop();
2309 genop(s, MKOP_ABC(OP_SUB, cursp(), sym, 2));
2311 else {
2312 codegen(s, tree, NOVAL);
2314 break;
2317 break;
2319 case NODE_STR:
2320 if (val) {
2321 char *p = (char*)tree->car;
2322 size_t len = (intptr_t)tree->cdr;
2323 int ai = mrb_gc_arena_save(s->mrb);
2324 int off = new_lit(s, mrb_str_new(s->mrb, p, len));
2326 mrb_gc_arena_restore(s->mrb, ai);
2327 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2328 push();
2330 break;
2332 case NODE_HEREDOC:
2333 tree = ((struct mrb_parser_heredoc_info *)tree)->doc;
2334 /* fall through */
2335 case NODE_DSTR:
2336 if (val) {
2337 node *n = tree;
2339 if (!n) {
2340 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2341 push();
2342 break;
2344 codegen(s, n->car, VAL);
2345 n = n->cdr;
2346 while (n) {
2347 codegen(s, n->car, VAL);
2348 pop(); pop();
2349 genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
2350 push();
2351 n = n->cdr;
2354 else {
2355 node *n = tree;
2357 while (n) {
2358 if ((intptr_t)n->car->car != NODE_STR) {
2359 codegen(s, n->car, NOVAL);
2361 n = n->cdr;
2364 break;
2366 case NODE_WORDS:
2367 gen_literal_array(s, tree, FALSE, val);
2368 break;
2370 case NODE_SYMBOLS:
2371 gen_literal_array(s, tree, TRUE, val);
2372 break;
2374 case NODE_DXSTR:
2376 node *n;
2377 int ai = mrb_gc_arena_save(s->mrb);
2378 int sym = new_sym(s, mrb_intern_lit(s->mrb, "Kernel"));
2380 genop(s, MKOP_A(OP_LOADSELF, cursp()));
2381 push();
2382 codegen(s, tree->car, VAL);
2383 n = tree->cdr;
2384 while (n) {
2385 if ((intptr_t)n->car->car == NODE_XSTR) {
2386 n->car->car = (struct mrb_ast_node*)(intptr_t)NODE_STR;
2387 mrb_assert(!n->cdr); /* must be the end */
2389 codegen(s, n->car, VAL);
2390 pop(); pop();
2391 genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
2392 push();
2393 n = n->cdr;
2395 push(); /* for block */
2396 pop_n(3);
2397 sym = new_sym(s, mrb_intern_lit(s->mrb, "`"));
2398 genop(s, MKOP_ABC(OP_SEND, cursp(), sym, 1));
2399 if (val) push();
2400 mrb_gc_arena_restore(s->mrb, ai);
2402 break;
2404 case NODE_XSTR:
2406 char *p = (char*)tree->car;
2407 size_t len = (intptr_t)tree->cdr;
2408 int ai = mrb_gc_arena_save(s->mrb);
2409 int off = new_lit(s, mrb_str_new(s->mrb, p, len));
2410 int sym;
2412 genop(s, MKOP_A(OP_LOADSELF, cursp()));
2413 push();
2414 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2415 push(); push();
2416 pop_n(3);
2417 sym = new_sym(s, mrb_intern_lit(s->mrb, "`"));
2418 genop(s, MKOP_ABC(OP_SEND, cursp(), sym, 1));
2419 if (val) push();
2420 mrb_gc_arena_restore(s->mrb, ai);
2422 break;
2424 case NODE_REGX:
2425 if (val) {
2426 char *p1 = (char*)tree->car;
2427 char *p2 = (char*)tree->cdr->car;
2428 char *p3 = (char*)tree->cdr->cdr;
2429 int ai = mrb_gc_arena_save(s->mrb);
2430 int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS));
2431 int off = new_lit(s, mrb_str_new_cstr(s->mrb, p1));
2432 int argc = 1;
2434 genop(s, MKOP_A(OP_OCLASS, cursp()));
2435 genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
2436 push();
2437 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2438 if (p2 || p3) {
2439 push();
2440 if (p2) {
2441 off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
2442 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2444 else {
2445 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2447 argc++;
2448 if (p3) {
2449 push();
2450 off = new_lit(s, mrb_str_new(s->mrb, p3, 1));
2451 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2452 argc++;
2453 pop();
2455 pop();
2457 pop();
2458 sym = new_sym(s, mrb_intern_lit(s->mrb, "compile"));
2459 genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc));
2460 mrb_gc_arena_restore(s->mrb, ai);
2461 push();
2463 break;
2465 case NODE_DREGX:
2466 if (val) {
2467 node *n = tree->car;
2468 int ai = mrb_gc_arena_save(s->mrb);
2469 int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS));
2470 int argc = 1;
2471 int off;
2472 char *p;
2474 genop(s, MKOP_A(OP_OCLASS, cursp()));
2475 genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
2476 push();
2477 codegen(s, n->car, VAL);
2478 n = n->cdr;
2479 while (n) {
2480 codegen(s, n->car, VAL);
2481 pop(); pop();
2482 genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
2483 push();
2484 n = n->cdr;
2486 n = tree->cdr->cdr;
2487 if (n->car) {
2488 p = (char*)n->car;
2489 off = new_lit(s, mrb_str_new_cstr(s->mrb, p));
2490 codegen(s, tree->car, VAL);
2491 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2492 pop();
2493 genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
2495 if (n->cdr->car) {
2496 char *p2 = (char*)n->cdr->car;
2498 push();
2499 off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
2500 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2501 argc++;
2503 if (n->cdr->cdr) {
2504 char *p2 = (char*)n->cdr->cdr;
2506 push();
2507 off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
2508 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2509 argc++;
2511 pop_n(argc);
2512 sym = new_sym(s, mrb_intern_lit(s->mrb, "compile"));
2513 genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc));
2514 mrb_gc_arena_restore(s->mrb, ai);
2515 push();
2517 else {
2518 node *n = tree->car;
2520 while (n) {
2521 if ((intptr_t)n->car->car != NODE_STR) {
2522 codegen(s, n->car, NOVAL);
2524 n = n->cdr;
2527 break;
2529 case NODE_SYM:
2530 if (val) {
2531 int sym = new_sym(s, sym(tree));
2533 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym));
2534 push();
2536 break;
2538 case NODE_DSYM:
2539 codegen(s, tree, val);
2540 if (val) {
2541 gen_send_intern(s);
2543 break;
2545 case NODE_SELF:
2546 if (val) {
2547 genop(s, MKOP_A(OP_LOADSELF, cursp()));
2548 push();
2550 break;
2552 case NODE_NIL:
2553 if (val) {
2554 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2555 push();
2557 break;
2559 case NODE_TRUE:
2560 if (val) {
2561 genop(s, MKOP_A(OP_LOADT, cursp()));
2562 push();
2564 break;
2566 case NODE_FALSE:
2567 if (val) {
2568 genop(s, MKOP_A(OP_LOADF, cursp()));
2569 push();
2571 break;
2573 case NODE_ALIAS:
2575 int a = new_msym(s, sym(tree->car));
2576 int b = new_msym(s, sym(tree->cdr));
2577 int c = new_msym(s, mrb_intern_lit(s->mrb, "alias_method"));
2579 genop(s, MKOP_A(OP_TCLASS, cursp()));
2580 push();
2581 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), a));
2582 push();
2583 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), b));
2584 push();
2585 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2586 push();
2587 pop_n(4);
2588 genop(s, MKOP_ABC(OP_SEND, cursp(), c, 2));
2589 if (val) {
2590 push();
2593 break;
2595 case NODE_UNDEF:
2597 int undef = new_msym(s, mrb_intern_lit(s->mrb, "undef_method"));
2598 int num = 0;
2599 node *t = tree;
2601 genop(s, MKOP_A(OP_TCLASS, cursp()));
2602 push();
2603 while (t) {
2604 int symbol;
2605 if (num >= CALL_MAXARGS - 1) {
2606 pop_n(num);
2607 genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), num));
2608 while (t) {
2609 symbol = new_msym(s, sym(t->car));
2610 push();
2611 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), symbol));
2612 pop();
2613 genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
2614 t = t->cdr;
2616 num = CALL_MAXARGS;
2617 break;
2619 symbol = new_msym(s, sym(t->car));
2620 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), symbol));
2621 push();
2622 t = t->cdr;
2623 num++;
2625 pop();
2626 if (num < CALL_MAXARGS) {
2627 pop_n(num);
2629 genop(s, MKOP_ABC(OP_SEND, cursp(), undef, num));
2630 if (val) {
2631 push();
2634 break;
2636 case NODE_CLASS:
2638 int idx;
2640 if (tree->car->car == (node*)0) {
2641 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2642 push();
2644 else if (tree->car->car == (node*)1) {
2645 genop(s, MKOP_A(OP_OCLASS, cursp()));
2646 push();
2648 else {
2649 codegen(s, tree->car->car, VAL);
2651 if (tree->cdr->car) {
2652 codegen(s, tree->cdr->car, VAL);
2654 else {
2655 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2656 push();
2658 pop(); pop();
2659 idx = new_msym(s, sym(tree->car->cdr));
2660 genop(s, MKOP_AB(OP_CLASS, cursp(), idx));
2661 idx = scope_body(s, tree->cdr->cdr->car, val);
2662 genop(s, MKOP_ABx(OP_EXEC, cursp(), idx));
2663 if (val) {
2664 push();
2667 break;
2669 case NODE_MODULE:
2671 int idx;
2673 if (tree->car->car == (node*)0) {
2674 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2675 push();
2677 else if (tree->car->car == (node*)1) {
2678 genop(s, MKOP_A(OP_OCLASS, cursp()));
2679 push();
2681 else {
2682 codegen(s, tree->car->car, VAL);
2684 pop();
2685 idx = new_msym(s, sym(tree->car->cdr));
2686 genop(s, MKOP_AB(OP_MODULE, cursp(), idx));
2687 idx = scope_body(s, tree->cdr->car, val);
2688 genop(s, MKOP_ABx(OP_EXEC, cursp(), idx));
2689 if (val) {
2690 push();
2693 break;
2695 case NODE_SCLASS:
2697 int idx;
2699 codegen(s, tree->car, VAL);
2700 pop();
2701 genop(s, MKOP_AB(OP_SCLASS, cursp(), cursp()));
2702 idx = scope_body(s, tree->cdr->car, val);
2703 genop(s, MKOP_ABx(OP_EXEC, cursp(), idx));
2704 if (val) {
2705 push();
2708 break;
2710 case NODE_DEF:
2712 int sym = new_msym(s, sym(tree->car));
2713 int idx = lambda_body(s, tree->cdr, 0);
2715 genop(s, MKOP_A(OP_TCLASS, cursp()));
2716 push();
2717 genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_METHOD));
2718 push(); pop();
2719 pop();
2720 genop(s, MKOP_AB(OP_METHOD, cursp(), sym));
2721 if (val) {
2722 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym));
2723 push();
2726 break;
2728 case NODE_SDEF:
2730 node *recv = tree->car;
2731 int sym = new_msym(s, sym(tree->cdr->car));
2732 int idx = lambda_body(s, tree->cdr->cdr, 0);
2734 codegen(s, recv, VAL);
2735 pop();
2736 genop(s, MKOP_AB(OP_SCLASS, cursp(), cursp()));
2737 push();
2738 genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_METHOD));
2739 pop();
2740 genop(s, MKOP_AB(OP_METHOD, cursp(), sym));
2741 if (val) {
2742 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym));
2743 push();
2746 break;
2748 case NODE_POSTEXE:
2749 codegen(s, tree, NOVAL);
2750 break;
2752 default:
2753 break;
2757 static void
2758 scope_add_irep(codegen_scope *s, mrb_irep *irep)
2760 if (s->irep == NULL) {
2761 s->irep = irep;
2762 return;
2764 if (s->irep->rlen == s->rcapa) {
2765 s->rcapa *= 2;
2766 s->irep->reps = (mrb_irep**)codegen_realloc(s, s->irep->reps, sizeof(mrb_irep*)*s->rcapa);
2768 s->irep->reps[s->irep->rlen] = irep;
2769 s->irep->rlen++;
2772 static codegen_scope*
2773 scope_new(mrb_state *mrb, codegen_scope *prev, node *lv)
2775 static const codegen_scope codegen_scope_zero = { 0 };
2776 mrb_pool *pool = mrb_pool_open(mrb);
2777 codegen_scope *p = (codegen_scope *)mrb_pool_alloc(pool, sizeof(codegen_scope));
2779 if (!p) return NULL;
2780 *p = codegen_scope_zero;
2781 p->mrb = mrb;
2782 p->mpool = pool;
2783 if (!prev) return p;
2784 p->prev = prev;
2785 p->ainfo = -1;
2786 p->mscope = 0;
2788 p->irep = mrb_add_irep(mrb);
2789 scope_add_irep(prev, p->irep);
2791 p->rcapa = 8;
2792 p->irep->reps = (mrb_irep**)mrb_malloc(mrb, sizeof(mrb_irep*)*p->rcapa);
2794 p->icapa = 1024;
2795 p->iseq = (mrb_code*)mrb_malloc(mrb, sizeof(mrb_code)*p->icapa);
2796 p->irep->iseq = NULL;
2798 p->pcapa = 32;
2799 p->irep->pool = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value)*p->pcapa);
2800 p->irep->plen = 0;
2802 p->scapa = MAXMSYMLEN;
2803 p->irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*p->scapa);
2804 p->irep->slen = 0;
2806 p->lv = lv;
2807 p->sp += node_len(lv)+1; /* add self */
2808 p->nlocals = p->sp;
2809 if (lv) {
2810 node *n = lv;
2811 size_t i = 0;
2813 p->irep->lv = (struct mrb_locals*)mrb_malloc(mrb, sizeof(struct mrb_locals) * (p->nlocals - 1));
2814 for (i=0, n=lv; n; i++,n=n->cdr) {
2815 p->irep->lv[i].name = lv_name(n);
2816 if (lv_name(n)) {
2817 p->irep->lv[i].r = lv_idx(p, lv_name(n));
2819 else {
2820 p->irep->lv[i].r = 0;
2823 mrb_assert(i + 1 == p->nlocals);
2825 p->ai = mrb_gc_arena_save(mrb);
2827 p->filename = prev->filename;
2828 if (p->filename) {
2829 p->lines = (uint16_t*)mrb_malloc(mrb, sizeof(short)*p->icapa);
2831 p->lineno = prev->lineno;
2833 /* debug setting */
2834 p->debug_start_pos = 0;
2835 if (p->filename) {
2836 mrb_debug_info_alloc(mrb, p->irep);
2837 p->irep->filename = p->filename;
2838 p->irep->lines = p->lines;
2840 else {
2841 p->irep->debug_info = NULL;
2843 p->parser = prev->parser;
2844 p->filename_index = prev->filename_index;
2846 return p;
2849 static void
2850 scope_finish(codegen_scope *s)
2852 mrb_state *mrb = s->mrb;
2853 mrb_irep *irep = s->irep;
2854 size_t fname_len;
2855 char *fname;
2857 irep->flags = 0;
2858 if (s->iseq) {
2859 irep->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc);
2860 irep->ilen = s->pc;
2861 if (s->lines) {
2862 irep->lines = (uint16_t *)codegen_realloc(s, s->lines, sizeof(uint16_t)*s->pc);
2864 else {
2865 irep->lines = 0;
2868 irep->pool = (mrb_value*)codegen_realloc(s, irep->pool, sizeof(mrb_value)*irep->plen);
2869 irep->syms = (mrb_sym*)codegen_realloc(s, irep->syms, sizeof(mrb_sym)*irep->slen);
2870 irep->reps = (mrb_irep**)codegen_realloc(s, irep->reps, sizeof(mrb_irep*)*irep->rlen);
2871 if (s->filename) {
2872 irep->filename = mrb_parser_get_filename(s->parser, s->filename_index);
2873 mrb_debug_info_append_file(mrb, irep, s->debug_start_pos, s->pc);
2875 fname_len = strlen(s->filename);
2876 fname = (char*)codegen_malloc(s, fname_len + 1);
2877 memcpy(fname, s->filename, fname_len);
2878 fname[fname_len] = '\0';
2879 irep->filename = fname;
2880 irep->own_filename = TRUE;
2883 irep->nlocals = s->nlocals;
2884 irep->nregs = s->nregs;
2886 mrb_gc_arena_restore(mrb, s->ai);
2887 mrb_pool_close(s->mpool);
2890 static struct loopinfo*
2891 loop_push(codegen_scope *s, enum looptype t)
2893 struct loopinfo *p = (struct loopinfo *)codegen_palloc(s, sizeof(struct loopinfo));
2895 p->type = t;
2896 p->pc1 = p->pc2 = p->pc3 = 0;
2897 p->prev = s->loop;
2898 p->ensure_level = s->ensure_level;
2899 p->acc = cursp();
2900 s->loop = p;
2902 return p;
2905 static void
2906 loop_break(codegen_scope *s, node *tree)
2908 if (!s->loop) {
2909 codegen(s, tree, NOVAL);
2910 raise_error(s, "unexpected break");
2912 else {
2913 struct loopinfo *loop;
2915 if (tree) {
2916 gen_retval(s, tree);
2919 loop = s->loop;
2920 while (loop && loop->type == LOOP_BEGIN) {
2921 genop_peep(s, MKOP_A(OP_POPERR, 1), NOVAL);
2922 loop = loop->prev;
2924 while (loop && loop->type == LOOP_RESCUE) {
2925 loop = loop->prev;
2927 if (!loop) {
2928 raise_error(s, "unexpected break");
2929 return;
2932 if (loop->type == LOOP_NORMAL) {
2933 int tmp;
2935 if (s->ensure_level > s->loop->ensure_level) {
2936 genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL);
2938 if (tree) {
2939 genop_peep(s, MKOP_AB(OP_MOVE, loop->acc, cursp()), NOVAL);
2941 tmp = genop(s, MKOP_sBx(OP_JMP, loop->pc3));
2942 loop->pc3 = tmp;
2944 else {
2945 if (!tree) {
2946 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2948 genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_BREAK));
2953 static void
2954 loop_pop(codegen_scope *s, int val)
2956 dispatch_linked(s, s->loop->pc3);
2957 if (val) {
2958 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2960 s->loop = s->loop->prev;
2961 if (val) push();
2964 MRB_API struct RProc*
2965 mrb_generate_code(mrb_state *mrb, parser_state *p)
2967 codegen_scope *scope = scope_new(mrb, 0, 0);
2968 struct RProc *proc;
2970 if (!scope) {
2971 return NULL;
2973 scope->mrb = mrb;
2974 scope->parser = p;
2975 scope->filename = p->filename;
2976 scope->filename_index = p->current_filename_index;
2978 MRB_TRY(&scope->jmp) {
2979 /* prepare irep */
2980 codegen(scope, p->tree, NOVAL);
2981 proc = mrb_proc_new(mrb, scope->irep);
2982 mrb_irep_decref(mrb, scope->irep);
2983 mrb_pool_close(scope->mpool);
2984 return proc;
2986 MRB_CATCH(&scope->jmp) {
2987 mrb_irep_decref(mrb, scope->irep);
2988 mrb_pool_close(scope->mpool);
2989 return NULL;
2991 MRB_END_EXC(&scope->jmp);