Refactored code around generation of OP_SEND in NODE_OP_ASGN
[mruby.git] / mrbgems / mruby-compiler / core / codegen.c
blob9d7392c2dc8c05308f1590999be13b1c45f1aae3
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 push();pop(); /* space for a block */
635 pop();
636 idx = new_msym(s, mrb_intern_lit(s->mrb, "each"));
637 genop(s, MKOP_ABC(OP_SENDB, cursp(), idx, 0));
640 static int
641 lambda_body(codegen_scope *s, node *tree, int blk)
643 mrb_code c;
644 codegen_scope *parent = s;
645 s = scope_new(s->mrb, s, tree->car);
646 if (s == NULL) {
647 raise_error(parent, "unexpected scope");
650 s->mscope = !blk;
652 if (blk) {
653 struct loopinfo *lp = loop_push(s, LOOP_BLOCK);
654 lp->pc1 = new_label(s);
656 tree = tree->cdr;
657 if (tree->car) {
658 mrb_aspec a;
659 int ma, oa, ra, pa, ka, kd, ba;
660 int pos, i;
661 node *n, *opt;
663 ma = node_len(tree->car->car);
664 n = tree->car->car;
665 while (n) {
666 n = n->cdr;
668 oa = node_len(tree->car->cdr->car);
669 ra = tree->car->cdr->cdr->car ? 1 : 0;
670 pa = node_len(tree->car->cdr->cdr->cdr->car);
671 ka = kd = 0;
672 ba = tree->car->cdr->cdr->cdr->cdr ? 1 : 0;
674 if (ma > 0x1f || oa > 0x1f || pa > 0x1f || ka > 0x1f) {
675 codegen_error(s, "too many formal arguments");
677 a = ((mrb_aspec)(ma & 0x1f) << 18)
678 | ((mrb_aspec)(oa & 0x1f) << 13)
679 | ((ra & 1) << 12)
680 | ((pa & 0x1f) << 7)
681 | ((ka & 0x1f) << 2)
682 | ((kd & 1)<< 1)
683 | (ba & 1);
684 s->ainfo = (((ma+oa) & 0x3f) << 6) /* (12bits = 6:1:5) */
685 | ((ra & 1) << 5)
686 | (pa & 0x1f);
687 genop(s, MKOP_Ax(OP_ENTER, a));
688 pos = new_label(s);
689 for (i=0; i<oa; i++) {
690 new_label(s);
691 genop(s, MKOP_sBx(OP_JMP, 0));
693 if (oa > 0) {
694 genop(s, MKOP_sBx(OP_JMP, 0));
696 opt = tree->car->cdr->car;
697 i = 0;
698 while (opt) {
699 int idx;
701 dispatch(s, pos+i);
702 codegen(s, opt->car->cdr, VAL);
703 idx = lv_idx(s, nsym(opt->car->car));
704 pop();
705 genop_peep(s, MKOP_AB(OP_MOVE, idx, cursp()), NOVAL);
706 i++;
707 opt = opt->cdr;
709 if (oa > 0) {
710 dispatch(s, pos+i);
713 codegen(s, tree->cdr->car, VAL);
714 pop();
715 if (s->pc > 0) {
716 c = s->iseq[s->pc-1];
717 if (GET_OPCODE(c) != OP_RETURN || GETARG_B(c) != OP_R_NORMAL || s->pc == s->lastlabel) {
718 if (s->nregs == 0) {
719 genop(s, MKOP_A(OP_LOADNIL, 0));
720 genop(s, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
722 else {
723 genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
727 if (blk) {
728 loop_pop(s, NOVAL);
730 scope_finish(s);
731 return parent->irep->rlen - 1;
734 static int
735 scope_body(codegen_scope *s, node *tree, int val)
737 codegen_scope *scope = scope_new(s->mrb, s, tree->car);
738 if (scope == NULL) {
739 raise_error(s, "unexpected scope");
742 codegen(scope, tree->cdr, VAL);
743 if (!s->iseq) {
744 genop(scope, MKOP_A(OP_STOP, 0));
746 else if (!val) {
747 genop(scope, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
749 else {
750 if (scope->nregs == 0) {
751 genop(scope, MKOP_A(OP_LOADNIL, 0));
752 genop(scope, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
754 else {
755 genop_peep(scope, MKOP_AB(OP_RETURN, scope->sp-1, OP_R_NORMAL), NOVAL);
758 scope_finish(scope);
759 if (!s->irep) {
760 /* should not happen */
761 return 0;
763 return s->irep->rlen - 1;
766 #define nint(x) ((int)(intptr_t)(x))
767 #define nchar(x) ((char)(intptr_t)(x))
769 static mrb_bool
770 nosplat(node *t)
772 while (t) {
773 if (nint(t->car->car) == NODE_SPLAT) return FALSE;
774 t = t->cdr;
776 return TRUE;
779 static mrb_sym
780 attrsym(codegen_scope *s, mrb_sym a)
782 const char *name;
783 mrb_int len;
784 char *name2;
786 name = mrb_sym2name_len(s->mrb, a, &len);
787 name2 = (char *)codegen_palloc(s,
788 (size_t)len
789 + 1 /* '=' */
790 + 1 /* '\0' */
792 mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX);
793 memcpy(name2, name, (size_t)len);
794 name2[len] = '=';
795 name2[len+1] = '\0';
797 return mrb_intern(s->mrb, name2, len+1);
800 #define CALL_MAXARGS 127
802 static int
803 gen_values(codegen_scope *s, node *t, int val, int extra)
805 int n = 0;
806 int is_splat;
808 while (t) {
809 is_splat = nint(t->car->car) == NODE_SPLAT; /* splat mode */
810 if (
811 n+extra >= CALL_MAXARGS - 1 /* need to subtract one because vm.c expects an array if n == CALL_MAXARGS */
812 || is_splat) {
813 if (val) {
814 if (is_splat && n == 0 && nint(t->car->cdr->car) == NODE_ARRAY) {
815 codegen(s, t->car->cdr, VAL);
816 pop();
818 else {
819 pop_n(n);
820 genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), n));
821 push();
822 codegen(s, t->car, VAL);
823 pop(); pop();
824 if (is_splat) {
825 genop(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1));
827 else {
828 genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
831 t = t->cdr;
832 while (t) {
833 push();
834 codegen(s, t->car, VAL);
835 pop(); pop();
836 if (nint(t->car->car) == NODE_SPLAT) {
837 genop(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1));
839 else {
840 genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
842 t = t->cdr;
845 else {
846 while (t) {
847 codegen(s, t->car, NOVAL);
848 t = t->cdr;
851 return -1;
853 /* normal (no splat) mode */
854 codegen(s, t->car, val);
855 n++;
856 t = t->cdr;
858 return n;
861 static void
862 gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe)
864 mrb_sym sym = name ? name : nsym(tree->cdr->car);
865 int idx, skip = 0;
866 int n = 0, noop = 0, sendv = 0, blk = 0;
868 codegen(s, tree->car, VAL); /* receiver */
869 if (safe) {
870 int recv = cursp()-1;
871 genop(s, MKOP_A(OP_LOADNIL, cursp()));
872 push();
873 genop(s, MKOP_AB(OP_MOVE, cursp(), recv));
874 push_n(2); pop_n(2); /* space for one arg and a block */
875 pop();
876 idx = new_msym(s, mrb_intern_lit(s->mrb, "=="));
877 genop(s, MKOP_ABC(OP_EQ, cursp(), idx, 1));
878 skip = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), 0));
880 idx = new_msym(s, sym);
881 tree = tree->cdr->cdr->car;
882 if (tree) {
883 n = gen_values(s, tree->car, VAL, sp?1:0);
884 if (n < 0) {
885 n = noop = sendv = 1;
886 push();
889 if (sp) {
890 if (sendv) {
891 pop();
892 genop(s, MKOP_AB(OP_ARYPUSH, cursp(), sp));
893 push();
895 else {
896 genop(s, MKOP_AB(OP_MOVE, cursp(), sp));
897 push();
898 n++;
901 if (tree && tree->cdr) {
902 noop = 1;
903 codegen(s, tree->cdr, VAL);
904 pop();
906 else {
907 blk = cursp();
909 push();pop();
910 pop_n(n+1);
912 mrb_int symlen;
913 const char *symname = mrb_sym2name_len(s->mrb, sym, &symlen);
915 if (!noop && symlen == 1 && symname[0] == '+' && n == 1) {
916 genop_peep(s, MKOP_ABC(OP_ADD, cursp(), idx, n), val);
918 else if (!noop && symlen == 1 && symname[0] == '-' && n == 1) {
919 genop_peep(s, MKOP_ABC(OP_SUB, cursp(), idx, n), val);
921 else if (!noop && symlen == 1 && symname[0] == '*' && n == 1) {
922 genop(s, MKOP_ABC(OP_MUL, cursp(), idx, n));
924 else if (!noop && symlen == 1 && symname[0] == '/' && n == 1) {
925 genop(s, MKOP_ABC(OP_DIV, cursp(), idx, n));
927 else if (!noop && symlen == 1 && symname[0] == '<' && n == 1) {
928 genop(s, MKOP_ABC(OP_LT, cursp(), idx, n));
930 else if (!noop && symlen == 2 && symname[0] == '<' && symname[1] == '=' && n == 1) {
931 genop(s, MKOP_ABC(OP_LE, cursp(), idx, n));
933 else if (!noop && symlen == 1 && symname[0] == '>' && n == 1) {
934 genop(s, MKOP_ABC(OP_GT, cursp(), idx, n));
936 else if (!noop && symlen == 2 && symname[0] == '>' && symname[1] == '=' && n == 1) {
937 genop(s, MKOP_ABC(OP_GE, cursp(), idx, n));
939 else if (!noop && symlen == 2 && symname[0] == '=' && symname[1] == '=' && n == 1) {
940 genop(s, MKOP_ABC(OP_EQ, cursp(), idx, n));
942 else {
943 if (sendv) n = CALL_MAXARGS;
944 if (blk > 0) { /* no block */
945 genop(s, MKOP_ABC(OP_SEND, cursp(), idx, n));
947 else {
948 genop(s, MKOP_ABC(OP_SENDB, cursp(), idx, n));
952 if (safe) {
953 dispatch(s, skip);
955 if (val) {
956 push();
960 static void
961 gen_assignment(codegen_scope *s, node *tree, int sp, int val)
963 int idx;
964 int type = nint(tree->car);
966 tree = tree->cdr;
967 switch (type) {
968 case NODE_GVAR:
969 idx = new_sym(s, nsym(tree));
970 genop_peep(s, MKOP_ABx(OP_SETGLOBAL, sp, idx), val);
971 break;
972 case NODE_LVAR:
973 idx = lv_idx(s, nsym(tree));
974 if (idx > 0) {
975 if (idx != sp) {
976 genop_peep(s, MKOP_AB(OP_MOVE, idx, sp), val);
978 break;
980 else { /* upvar */
981 int lv = 0;
982 codegen_scope *up = s->prev;
984 while (up) {
985 idx = lv_idx(up, nsym(tree));
986 if (idx > 0) {
987 genop_peep(s, MKOP_ABC(OP_SETUPVAR, sp, idx, lv), val);
988 break;
990 lv++;
991 up = up->prev;
994 break;
995 case NODE_IVAR:
996 idx = new_sym(s, nsym(tree));
997 genop_peep(s, MKOP_ABx(OP_SETIV, sp, idx), val);
998 break;
999 case NODE_CVAR:
1000 idx = new_sym(s, nsym(tree));
1001 genop_peep(s, MKOP_ABx(OP_SETCV, sp, idx), val);
1002 break;
1003 case NODE_CONST:
1004 idx = new_sym(s, nsym(tree));
1005 genop_peep(s, MKOP_ABx(OP_SETCONST, sp, idx), val);
1006 break;
1007 case NODE_COLON2:
1008 idx = new_sym(s, nsym(tree->cdr));
1009 genop_peep(s, MKOP_AB(OP_MOVE, cursp(), sp), NOVAL);
1010 push();
1011 codegen(s, tree->car, VAL);
1012 pop_n(2);
1013 genop_peep(s, MKOP_ABx(OP_SETMCNST, cursp(), idx), val);
1014 break;
1016 case NODE_CALL:
1017 case NODE_SCALL:
1018 push();
1019 gen_call(s, tree, attrsym(s, nsym(tree->cdr->car)), sp, NOVAL,
1020 type == NODE_SCALL);
1021 pop();
1022 if (val) {
1023 genop_peep(s, MKOP_AB(OP_MOVE, cursp(), sp), val);
1025 break;
1027 case NODE_MASGN:
1028 gen_vmassignment(s, tree->car, sp, val);
1029 break;
1031 /* splat without assignment */
1032 case NODE_NIL:
1033 break;
1035 default:
1036 #ifndef MRB_DISABLE_STDIO
1037 fprintf(stderr, "unknown lhs %d\n", type);
1038 #endif
1039 break;
1041 if (val) push();
1044 static void
1045 gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val)
1047 int n = 0, post = 0;
1048 node *t, *p;
1050 if (tree->car) { /* pre */
1051 t = tree->car;
1052 n = 0;
1053 while (t) {
1054 genop(s, MKOP_ABC(OP_AREF, cursp(), rhs, n));
1055 gen_assignment(s, t->car, cursp(), NOVAL);
1056 n++;
1057 t = t->cdr;
1060 t = tree->cdr;
1061 if (t) {
1062 if (t->cdr) { /* post count */
1063 p = t->cdr->car;
1064 while (p) {
1065 post++;
1066 p = p->cdr;
1069 if (val) {
1070 genop(s, MKOP_AB(OP_MOVE, cursp(), rhs));
1072 else {
1073 pop();
1075 push_n(post);
1076 pop_n(post);
1077 genop(s, MKOP_ABC(OP_APOST, cursp(), n, post));
1078 n = 1;
1079 if (t->car) { /* rest */
1080 gen_assignment(s, t->car, cursp(), NOVAL);
1082 if (t->cdr && t->cdr->car) {
1083 t = t->cdr->car;
1084 while (t) {
1085 gen_assignment(s, t->car, cursp()+n, NOVAL);
1086 t = t->cdr;
1087 n++;
1090 if (!val) {
1091 push();
1096 static void
1097 gen_send_intern(codegen_scope *s)
1099 push();pop(); /* space for a block */
1100 pop();
1101 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "intern")), 0));
1102 push();
1104 static void
1105 gen_literal_array(codegen_scope *s, node *tree, mrb_bool sym, int val)
1107 if (val) {
1108 int i = 0, j = 0;
1110 while (tree) {
1111 switch (nint(tree->car->car)) {
1112 case NODE_STR:
1113 if ((tree->cdr == NULL) && (nint(tree->car->cdr->cdr) == 0))
1114 break;
1115 /* fall through */
1116 case NODE_BEGIN:
1117 codegen(s, tree->car, VAL);
1118 ++j;
1119 break;
1121 case NODE_LITERAL_DELIM:
1122 if (j > 0) {
1123 j = 0;
1124 ++i;
1125 if (sym)
1126 gen_send_intern(s);
1128 break;
1130 if (j >= 2) {
1131 pop(); pop();
1132 genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
1133 push();
1134 j = 1;
1136 tree = tree->cdr;
1138 if (j > 0) {
1139 ++i;
1140 if (sym)
1141 gen_send_intern(s);
1143 pop_n(i);
1144 genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), i));
1145 push();
1147 else {
1148 while (tree) {
1149 switch (nint(tree->car->car)) {
1150 case NODE_BEGIN: case NODE_BLOCK:
1151 codegen(s, tree->car, NOVAL);
1153 tree = tree->cdr;
1158 static void
1159 raise_error(codegen_scope *s, const char *msg)
1161 int idx = new_lit(s, mrb_str_new_cstr(s->mrb, msg));
1163 genop(s, MKOP_ABx(OP_ERR, 1, idx));
1166 static double
1167 readint_float(codegen_scope *s, const char *p, int base)
1169 const char *e = p + strlen(p);
1170 double f = 0;
1171 int n;
1173 if (*p == '+') p++;
1174 while (p < e) {
1175 char c = *p;
1176 c = tolower((unsigned char)c);
1177 for (n=0; n<base; n++) {
1178 if (mrb_digitmap[n] == c) {
1179 f *= base;
1180 f += n;
1181 break;
1184 if (n == base) {
1185 codegen_error(s, "malformed readint input");
1187 p++;
1189 return f;
1192 static mrb_int
1193 readint_mrb_int(codegen_scope *s, const char *p, int base, mrb_bool neg, mrb_bool *overflow)
1195 const char *e = p + strlen(p);
1196 mrb_int result = 0;
1197 int n;
1199 mrb_assert(base >= 2 && base <= 36);
1200 if (*p == '+') p++;
1201 while (p < e) {
1202 char c = *p;
1203 c = tolower((unsigned char)c);
1204 for (n=0; n<base; n++) {
1205 if (mrb_digitmap[n] == c) {
1206 break;
1209 if (n == base) {
1210 codegen_error(s, "malformed readint input");
1213 if (neg) {
1214 if ((MRB_INT_MIN + n)/base > result) {
1215 *overflow = TRUE;
1216 return 0;
1218 result *= base;
1219 result -= n;
1221 else {
1222 if ((MRB_INT_MAX - n)/base < result) {
1223 *overflow = TRUE;
1224 return 0;
1226 result *= base;
1227 result += n;
1229 p++;
1231 *overflow = FALSE;
1232 return result;
1235 static void
1236 gen_retval(codegen_scope *s, node *tree)
1238 if (nint(tree->car) == NODE_SPLAT) {
1239 genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), 0));
1240 push();
1241 codegen(s, tree, VAL);
1242 pop(); pop();
1243 genop(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1));
1245 else {
1246 codegen(s, tree, VAL);
1247 pop();
1251 static void
1252 codegen(codegen_scope *s, node *tree, int val)
1254 int nt;
1255 int rlev = s->rlev;
1257 if (!tree) {
1258 if (val) {
1259 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1260 push();
1262 return;
1265 s->rlev++;
1266 if (s->rlev > MRB_CODEGEN_LEVEL_MAX) {
1267 codegen_error(s, "too complex expression");
1269 if (s->irep && s->filename_index != tree->filename_index) {
1270 s->irep->filename = mrb_parser_get_filename(s->parser, s->filename_index);
1271 mrb_debug_info_append_file(s->mrb, s->irep, s->debug_start_pos, s->pc);
1272 s->debug_start_pos = s->pc;
1273 s->filename_index = tree->filename_index;
1274 s->filename = mrb_parser_get_filename(s->parser, tree->filename_index);
1277 nt = nint(tree->car);
1278 s->lineno = tree->lineno;
1279 tree = tree->cdr;
1280 switch (nt) {
1281 case NODE_BEGIN:
1282 if (val && !tree) {
1283 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1284 push();
1286 while (tree) {
1287 codegen(s, tree->car, tree->cdr ? NOVAL : val);
1288 tree = tree->cdr;
1290 break;
1292 case NODE_RESCUE:
1294 int onerr, noexc, exend, pos1, pos2, tmp;
1295 struct loopinfo *lp;
1297 if (tree->car == NULL) goto exit;
1298 onerr = genop(s, MKOP_Bx(OP_ONERR, 0));
1299 lp = loop_push(s, LOOP_BEGIN);
1300 lp->pc1 = onerr;
1301 codegen(s, tree->car, VAL);
1302 pop();
1303 lp->type = LOOP_RESCUE;
1304 noexc = genop(s, MKOP_Bx(OP_JMP, 0));
1305 dispatch(s, onerr);
1306 tree = tree->cdr;
1307 exend = 0;
1308 pos1 = 0;
1309 if (tree->car) {
1310 node *n2 = tree->car;
1311 int exc = cursp();
1313 genop(s, MKOP_ABC(OP_RESCUE, exc, 0, 0));
1314 push();
1315 while (n2) {
1316 node *n3 = n2->car;
1317 node *n4 = n3->car;
1319 if (pos1) dispatch(s, pos1);
1320 pos2 = 0;
1321 do {
1322 if (n4 && n4->car && nint(n4->car->car) == NODE_SPLAT) {
1323 codegen(s, n4->car, VAL);
1324 genop(s, MKOP_AB(OP_MOVE, cursp(), exc));
1325 push_n(2); pop_n(2); /* space for one arg and a block */
1326 pop();
1327 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1));
1329 else {
1330 if (n4) {
1331 codegen(s, n4->car, VAL);
1333 else {
1334 genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "StandardError"))));
1335 push();
1337 pop();
1338 genop(s, MKOP_ABC(OP_RESCUE, exc, cursp(), 1));
1340 tmp = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2));
1341 pos2 = tmp;
1342 if (n4) {
1343 n4 = n4->cdr;
1345 } while (n4);
1346 pos1 = genop(s, MKOP_sBx(OP_JMP, 0));
1347 dispatch_linked(s, pos2);
1349 pop();
1350 if (n3->cdr->car) {
1351 gen_assignment(s, n3->cdr->car, exc, NOVAL);
1353 if (n3->cdr->cdr->car) {
1354 codegen(s, n3->cdr->cdr->car, val);
1355 if (val) pop();
1357 tmp = genop(s, MKOP_sBx(OP_JMP, exend));
1358 exend = tmp;
1359 n2 = n2->cdr;
1360 push();
1362 if (pos1) {
1363 dispatch(s, pos1);
1364 genop(s, MKOP_A(OP_RAISE, exc));
1367 pop();
1368 tree = tree->cdr;
1369 dispatch(s, noexc);
1370 genop(s, MKOP_A(OP_POPERR, 1));
1371 if (tree->car) {
1372 codegen(s, tree->car, val);
1374 else if (val) {
1375 push();
1377 dispatch_linked(s, exend);
1378 loop_pop(s, NOVAL);
1380 break;
1382 case NODE_ENSURE:
1383 if (!tree->cdr || !tree->cdr->cdr ||
1384 (nint(tree->cdr->cdr->car) == NODE_BEGIN &&
1385 tree->cdr->cdr->cdr)) {
1386 int idx;
1387 int epush = s->pc;
1389 genop(s, MKOP_Bx(OP_EPUSH, 0));
1390 s->ensure_level++;
1391 codegen(s, tree->car, val);
1392 idx = scope_body(s, tree->cdr, NOVAL);
1393 s->iseq[epush] = MKOP_Bx(OP_EPUSH, idx);
1394 s->ensure_level--;
1395 genop_peep(s, MKOP_A(OP_EPOP, 1), NOVAL);
1397 else { /* empty ensure ignored */
1398 codegen(s, tree->car, val);
1400 break;
1402 case NODE_LAMBDA:
1403 if (val) {
1404 int idx = lambda_body(s, tree, 1);
1406 genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_LAMBDA));
1407 push();
1409 break;
1411 case NODE_BLOCK:
1412 if (val) {
1413 int idx = lambda_body(s, tree, 1);
1415 genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_BLOCK));
1416 push();
1418 break;
1420 case NODE_IF:
1422 int pos1, pos2;
1423 node *e = tree->cdr->cdr->car;
1425 if (!tree->car) {
1426 codegen(s, e, val);
1427 goto exit;
1429 switch (nint(tree->car->car)) {
1430 case NODE_TRUE:
1431 case NODE_INT:
1432 case NODE_STR:
1433 codegen(s, tree->cdr->car, val);
1434 goto exit;
1435 case NODE_FALSE:
1436 case NODE_NIL:
1437 codegen(s, e, val);
1438 goto exit;
1440 codegen(s, tree->car, VAL);
1441 pop();
1442 pos1 = genop_peep(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0), NOVAL);
1444 codegen(s, tree->cdr->car, val);
1445 if (e) {
1446 if (val) pop();
1447 pos2 = genop(s, MKOP_sBx(OP_JMP, 0));
1448 dispatch(s, pos1);
1449 codegen(s, e, val);
1450 dispatch(s, pos2);
1452 else {
1453 if (val) {
1454 pop();
1455 pos2 = genop(s, MKOP_sBx(OP_JMP, 0));
1456 dispatch(s, pos1);
1457 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1458 dispatch(s, pos2);
1459 push();
1461 else {
1462 dispatch(s, pos1);
1466 break;
1468 case NODE_AND:
1470 int pos;
1472 codegen(s, tree->car, VAL);
1473 pop();
1474 pos = genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0));
1475 codegen(s, tree->cdr, val);
1476 dispatch(s, pos);
1478 break;
1480 case NODE_OR:
1482 int pos;
1484 codegen(s, tree->car, VAL);
1485 pop();
1486 pos = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), 0));
1487 codegen(s, tree->cdr, val);
1488 dispatch(s, pos);
1490 break;
1492 case NODE_WHILE:
1494 struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
1496 lp->pc1 = genop(s, MKOP_sBx(OP_JMP, 0));
1497 lp->pc2 = new_label(s);
1498 codegen(s, tree->cdr, NOVAL);
1499 dispatch(s, lp->pc1);
1500 codegen(s, tree->car, VAL);
1501 pop();
1502 genop(s, MKOP_AsBx(OP_JMPIF, cursp(), lp->pc2 - s->pc));
1504 loop_pop(s, val);
1506 break;
1508 case NODE_UNTIL:
1510 struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
1512 lp->pc1 = genop(s, MKOP_sBx(OP_JMP, 0));
1513 lp->pc2 = new_label(s);
1514 codegen(s, tree->cdr, NOVAL);
1515 dispatch(s, lp->pc1);
1516 codegen(s, tree->car, VAL);
1517 pop();
1518 genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), lp->pc2 - s->pc));
1520 loop_pop(s, val);
1522 break;
1524 case NODE_FOR:
1525 for_body(s, tree);
1526 if (val) push();
1527 break;
1529 case NODE_CASE:
1531 int head = 0;
1532 int pos1, pos2, pos3, tmp;
1533 node *n;
1535 pos3 = 0;
1536 if (tree->car) {
1537 head = cursp();
1538 codegen(s, tree->car, VAL);
1540 tree = tree->cdr;
1541 while (tree) {
1542 n = tree->car->car;
1543 pos1 = pos2 = 0;
1544 while (n) {
1545 codegen(s, n->car, VAL);
1546 if (head) {
1547 genop(s, MKOP_AB(OP_MOVE, cursp(), head));
1548 push_n(2); pop_n(2); /* space for one arg and a block */
1549 pop();
1550 if (nint(n->car->car) == NODE_SPLAT) {
1551 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1));
1553 else {
1554 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "===")), 1));
1557 else {
1558 pop();
1560 tmp = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2));
1561 pos2 = tmp;
1562 n = n->cdr;
1564 if (tree->car->car) {
1565 pos1 = genop(s, MKOP_sBx(OP_JMP, 0));
1566 dispatch_linked(s, pos2);
1568 codegen(s, tree->car->cdr, val);
1569 if (val) pop();
1570 tmp = genop(s, MKOP_sBx(OP_JMP, pos3));
1571 pos3 = tmp;
1572 if (pos1) dispatch(s, pos1);
1573 tree = tree->cdr;
1575 if (val) {
1576 int pos = cursp();
1577 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1578 if (pos3) dispatch_linked(s, pos3);
1579 if (head) pop();
1580 if (cursp() != pos) {
1581 genop(s, MKOP_AB(OP_MOVE, cursp(), pos));
1583 push();
1585 else {
1586 if (pos3) {
1587 dispatch_linked(s, pos3);
1589 if (head) {
1590 pop();
1594 break;
1596 case NODE_SCOPE:
1597 scope_body(s, tree, NOVAL);
1598 break;
1600 case NODE_FCALL:
1601 case NODE_CALL:
1602 gen_call(s, tree, 0, 0, val, 0);
1603 break;
1604 case NODE_SCALL:
1605 gen_call(s, tree, 0, 0, val, 1);
1606 break;
1608 case NODE_DOT2:
1609 codegen(s, tree->car, val);
1610 codegen(s, tree->cdr, val);
1611 if (val) {
1612 pop(); pop();
1613 genop(s, MKOP_ABC(OP_RANGE, cursp(), cursp(), FALSE));
1614 push();
1616 break;
1618 case NODE_DOT3:
1619 codegen(s, tree->car, val);
1620 codegen(s, tree->cdr, val);
1621 if (val) {
1622 pop(); pop();
1623 genop(s, MKOP_ABC(OP_RANGE, cursp(), cursp(), TRUE));
1624 push();
1626 break;
1628 case NODE_COLON2:
1630 int sym = new_sym(s, nsym(tree->cdr));
1632 codegen(s, tree->car, VAL);
1633 pop();
1634 genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
1635 if (val) push();
1637 break;
1639 case NODE_COLON3:
1641 int sym = new_sym(s, nsym(tree));
1643 genop(s, MKOP_A(OP_OCLASS, cursp()));
1644 genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
1645 if (val) push();
1647 break;
1649 case NODE_ARRAY:
1651 int n;
1653 n = gen_values(s, tree, val, 0);
1654 if (n >= 0) {
1655 if (val) {
1656 pop_n(n);
1657 genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), n));
1658 push();
1661 else if (val) {
1662 push();
1665 break;
1667 case NODE_HASH:
1669 int len = 0;
1670 mrb_bool update = FALSE;
1672 while (tree) {
1673 codegen(s, tree->car->car, val);
1674 codegen(s, tree->car->cdr, val);
1675 len++;
1676 tree = tree->cdr;
1677 if (val && len == 126) {
1678 pop_n(len*2);
1679 genop(s, MKOP_ABC(OP_HASH, cursp(), cursp(), len));
1680 if (update) {
1681 pop();
1682 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__update")), 1));
1684 push();
1685 update = TRUE;
1686 len = 0;
1689 if (val) {
1690 pop_n(len*2);
1691 genop(s, MKOP_ABC(OP_HASH, cursp(), cursp(), len));
1692 if (update) {
1693 pop();
1694 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__update")), 1));
1696 push();
1699 break;
1701 case NODE_SPLAT:
1702 codegen(s, tree, val);
1703 break;
1705 case NODE_ASGN:
1706 codegen(s, tree->cdr, VAL);
1707 pop();
1708 gen_assignment(s, tree->car, cursp(), val);
1709 break;
1711 case NODE_MASGN:
1713 int len = 0, n = 0, post = 0;
1714 node *t = tree->cdr, *p;
1715 int rhs = cursp();
1717 if (nint(t->car) == NODE_ARRAY && t->cdr && nosplat(t->cdr)) {
1718 /* fixed rhs */
1719 t = t->cdr;
1720 while (t) {
1721 codegen(s, t->car, VAL);
1722 len++;
1723 t = t->cdr;
1725 tree = tree->car;
1726 if (tree->car) { /* pre */
1727 t = tree->car;
1728 n = 0;
1729 while (t) {
1730 if (n < len) {
1731 gen_assignment(s, t->car, rhs+n, NOVAL);
1732 n++;
1734 else {
1735 genop(s, MKOP_A(OP_LOADNIL, rhs+n));
1736 gen_assignment(s, t->car, rhs+n, NOVAL);
1738 t = t->cdr;
1741 t = tree->cdr;
1742 if (t) {
1743 if (t->cdr) { /* post count */
1744 p = t->cdr->car;
1745 while (p) {
1746 post++;
1747 p = p->cdr;
1750 if (t->car) { /* rest (len - pre - post) */
1751 int rn;
1753 if (len < post + n) {
1754 rn = 0;
1756 else {
1757 rn = len - post - n;
1759 genop(s, MKOP_ABC(OP_ARRAY, cursp(), rhs+n, rn));
1760 gen_assignment(s, t->car, cursp(), NOVAL);
1761 n += rn;
1763 if (t->cdr && t->cdr->car) {
1764 t = t->cdr->car;
1765 while (n<len) {
1766 gen_assignment(s, t->car, rhs+n, NOVAL);
1767 t = t->cdr;
1768 n++;
1772 pop_n(len);
1773 if (val) {
1774 genop(s, MKOP_ABC(OP_ARRAY, rhs, rhs, len));
1775 push();
1778 else {
1779 /* variable rhs */
1780 codegen(s, t, VAL);
1781 gen_vmassignment(s, tree->car, rhs, val);
1782 if (!val) {
1783 pop();
1787 break;
1789 case NODE_OP_ASGN:
1791 mrb_sym sym = nsym(tree->cdr->car);
1792 mrb_int len;
1793 const char *name = mrb_sym2name_len(s->mrb, sym, &len);
1794 int idx, callargs = -1, vsp = -1;
1796 if ((len == 2 && name[0] == '|' && name[1] == '|') &&
1797 (nint(tree->car->car) == NODE_CONST ||
1798 nint(tree->car->car) == NODE_CVAR)) {
1799 int onerr, noexc, exc;
1800 struct loopinfo *lp;
1802 onerr = genop(s, MKOP_Bx(OP_ONERR, 0));
1803 lp = loop_push(s, LOOP_BEGIN);
1804 lp->pc1 = onerr;
1805 exc = cursp();
1806 codegen(s, tree->car, VAL);
1807 lp->type = LOOP_RESCUE;
1808 genop(s, MKOP_A(OP_POPERR, 1));
1809 noexc = genop(s, MKOP_Bx(OP_JMP, 0));
1810 dispatch(s, onerr);
1811 genop(s, MKOP_ABC(OP_RESCUE, exc, 0, 0));
1812 genop(s, MKOP_A(OP_LOADF, exc));
1813 dispatch(s, noexc);
1814 loop_pop(s, NOVAL);
1816 else if (nint(tree->car->car) == NODE_CALL) {
1817 node *n = tree->car->cdr;
1818 int base, i, nargs = 0;
1819 callargs = 0;
1821 if (val) {
1822 vsp = cursp();
1823 push();
1825 codegen(s, n->car, VAL); /* receiver */
1826 idx = new_msym(s, nsym(n->cdr->car));
1827 base = cursp()-1;
1828 if (n->cdr->cdr->car) {
1829 nargs = gen_values(s, n->cdr->cdr->car->car, VAL, 1);
1830 if (nargs >= 0) {
1831 callargs = nargs;
1833 else { /* varargs */
1834 push();
1835 nargs = 1;
1836 callargs = CALL_MAXARGS;
1839 /* copy receiver and arguments */
1840 genop(s, MKOP_AB(OP_MOVE, cursp(), base));
1841 for (i=0; i<nargs; i++) {
1842 genop(s, MKOP_AB(OP_MOVE, cursp()+i+1, base+i+1));
1844 push_n(nargs+1);pop_n(nargs+1);
1845 genop(s, MKOP_ABC(OP_SEND, cursp(), idx, callargs));
1846 push();
1848 else {
1849 codegen(s, tree->car, VAL);
1851 if (len == 2 &&
1852 ((name[0] == '|' && name[1] == '|') ||
1853 (name[0] == '&' && name[1] == '&'))) {
1854 int pos;
1856 pop();
1857 if (val) {
1858 if (vsp >= 0) {
1859 genop(s, MKOP_AB(OP_MOVE, vsp, cursp()));
1861 pos = genop(s, MKOP_AsBx(name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0));
1863 else {
1864 pos = genop_peep(s, MKOP_AsBx(name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0), NOVAL);
1866 codegen(s, tree->cdr->cdr->car, VAL);
1867 pop();
1868 if (val && vsp >= 0) {
1869 genop(s, MKOP_AB(OP_MOVE, vsp, cursp()));
1871 if (nint(tree->car->car) == NODE_CALL) {
1872 if (callargs == CALL_MAXARGS) {
1873 pop();
1874 genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
1876 else {
1877 pop_n(callargs);
1878 callargs++;
1880 pop();
1881 idx = new_msym(s, attrsym(s, nsym(tree->car->cdr->cdr->car)));
1882 genop(s, MKOP_ABC(OP_SEND, cursp(), idx, callargs));
1884 else {
1885 gen_assignment(s, tree->car, cursp(), val);
1887 dispatch(s, pos);
1888 goto exit;
1890 codegen(s, tree->cdr->cdr->car, VAL);
1891 push(); pop();
1892 pop(); pop();
1894 idx = new_msym(s, sym);
1895 if (len == 1 && name[0] == '+') {
1896 genop_peep(s, MKOP_ABC(OP_ADD, cursp(), idx, 1), val);
1898 else if (len == 1 && name[0] == '-') {
1899 genop_peep(s, MKOP_ABC(OP_SUB, cursp(), idx, 1), val);
1901 else if (len == 1 && name[0] == '*') {
1902 genop(s, MKOP_ABC(OP_MUL, cursp(), idx, 1));
1904 else if (len == 1 && name[0] == '/') {
1905 genop(s, MKOP_ABC(OP_DIV, cursp(), idx, 1));
1907 else if (len == 1 && name[0] == '<') {
1908 genop(s, MKOP_ABC(OP_LT, cursp(), idx, 1));
1910 else if (len == 2 && name[0] == '<' && name[1] == '=') {
1911 genop(s, MKOP_ABC(OP_LE, cursp(), idx, 1));
1913 else if (len == 1 && name[0] == '>') {
1914 genop(s, MKOP_ABC(OP_GT, cursp(), idx, 1));
1916 else if (len == 2 && name[0] == '>' && name[1] == '=') {
1917 genop(s, MKOP_ABC(OP_GE, cursp(), idx, 1));
1919 else {
1920 genop(s, MKOP_ABC(OP_SEND, cursp(), idx, 1));
1922 if (callargs < 0) {
1923 gen_assignment(s, tree->car, cursp(), val);
1925 else {
1926 if (val && vsp >= 0) {
1927 genop(s, MKOP_AB(OP_MOVE, vsp, cursp()));
1929 if (callargs == CALL_MAXARGS) {
1930 pop();
1931 genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
1933 else {
1934 pop_n(callargs);
1935 callargs++;
1937 pop();
1938 idx = new_msym(s, attrsym(s,nsym(tree->car->cdr->cdr->car)));
1939 genop(s, MKOP_ABC(OP_SEND, cursp(), idx, callargs));
1942 break;
1944 case NODE_SUPER:
1946 codegen_scope *s2 = s;
1947 int lv = 0;
1948 int n = 0, noop = 0, sendv = 0;
1950 push(); /* room for receiver */
1951 while (!s2->mscope) {
1952 lv++;
1953 s2 = s2->prev;
1954 if (!s2) break;
1956 genop(s, MKOP_ABx(OP_ARGARY, cursp(), (lv & 0xf)));
1957 push(); push(); /* ARGARY pushes two values */
1958 pop(); pop();
1959 if (tree) {
1960 node *args = tree->car;
1961 if (args) {
1962 n = gen_values(s, args, VAL, 0);
1963 if (n < 0) {
1964 n = noop = sendv = 1;
1965 push();
1969 if (tree && tree->cdr) {
1970 codegen(s, tree->cdr, VAL);
1971 pop();
1973 else {
1974 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1975 push(); pop();
1977 pop_n(n+1);
1978 if (sendv) n = CALL_MAXARGS;
1979 genop(s, MKOP_ABC(OP_SUPER, cursp(), 0, n));
1980 if (val) push();
1982 break;
1984 case NODE_ZSUPER:
1986 codegen_scope *s2 = s;
1987 int lv = 0, ainfo = 0;
1989 push(); /* room for receiver */
1990 while (!s2->mscope) {
1991 lv++;
1992 s2 = s2->prev;
1993 if (!s2) break;
1995 if (s2) ainfo = s2->ainfo;
1996 genop(s, MKOP_ABx(OP_ARGARY, cursp(), (ainfo<<4)|(lv & 0xf)));
1997 push(); push(); pop(); /* ARGARY pushes two values */
1998 if (tree && tree->cdr) {
1999 codegen(s, tree->cdr, VAL);
2000 pop();
2002 pop(); pop();
2003 genop(s, MKOP_ABC(OP_SUPER, cursp(), 0, CALL_MAXARGS));
2004 if (val) push();
2006 break;
2008 case NODE_RETURN:
2009 if (tree) {
2010 gen_retval(s, tree);
2012 else {
2013 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2015 if (s->loop) {
2016 genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_RETURN));
2018 else {
2019 genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
2021 if (val) push();
2022 break;
2024 case NODE_YIELD:
2026 codegen_scope *s2 = s;
2027 int lv = 0, ainfo = 0;
2028 int n = 0, sendv = 0;
2030 while (!s2->mscope) {
2031 lv++;
2032 s2 = s2->prev;
2033 if (!s2) break;
2035 if (s2) ainfo = s2->ainfo;
2036 push();
2037 if (tree) {
2038 n = gen_values(s, tree, VAL, 0);
2039 if (n < 0) {
2040 n = sendv = 1;
2041 push();
2044 push();pop(); /* space for a block */
2045 pop_n(n+1);
2046 genop(s, MKOP_ABx(OP_BLKPUSH, cursp(), (ainfo<<4)|(lv & 0xf)));
2047 if (sendv) n = CALL_MAXARGS;
2048 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "call")), n));
2049 if (val) push();
2051 break;
2053 case NODE_BREAK:
2054 loop_break(s, tree);
2055 if (val) push();
2056 break;
2058 case NODE_NEXT:
2059 if (!s->loop) {
2060 raise_error(s, "unexpected next");
2062 else if (s->loop->type == LOOP_NORMAL) {
2063 if (s->ensure_level > s->loop->ensure_level) {
2064 genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL);
2066 codegen(s, tree, NOVAL);
2067 genop(s, MKOP_sBx(OP_JMP, s->loop->pc1 - s->pc));
2069 else {
2070 if (tree) {
2071 codegen(s, tree, VAL);
2072 pop();
2074 else {
2075 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2077 genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
2079 if (val) push();
2080 break;
2082 case NODE_REDO:
2083 if (!s->loop || s->loop->type == LOOP_BEGIN || s->loop->type == LOOP_RESCUE) {
2084 raise_error(s, "unexpected redo");
2086 else {
2087 if (s->ensure_level > s->loop->ensure_level) {
2088 genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL);
2090 genop(s, MKOP_sBx(OP_JMP, s->loop->pc2 - s->pc));
2092 if (val) push();
2093 break;
2095 case NODE_RETRY:
2097 const char *msg = "unexpected retry";
2099 if (!s->loop) {
2100 raise_error(s, msg);
2102 else {
2103 struct loopinfo *lp = s->loop;
2104 int n = 0;
2106 while (lp && lp->type != LOOP_RESCUE) {
2107 if (lp->type == LOOP_BEGIN) {
2108 n++;
2110 lp = lp->prev;
2112 if (!lp) {
2113 raise_error(s, msg);
2115 else {
2116 if (n > 0) {
2117 genop_peep(s, MKOP_A(OP_POPERR, n), NOVAL);
2119 if (s->ensure_level > lp->ensure_level) {
2120 genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - lp->ensure_level), NOVAL);
2122 genop(s, MKOP_sBx(OP_JMP, lp->pc1 - s->pc));
2125 if (val) push();
2127 break;
2129 case NODE_LVAR:
2130 if (val) {
2131 int idx = lv_idx(s, nsym(tree));
2133 if (idx > 0) {
2134 genop_peep(s, MKOP_AB(OP_MOVE, cursp(), idx), NOVAL);
2136 else {
2137 int lv = 0;
2138 codegen_scope *up = s->prev;
2140 while (up) {
2141 idx = lv_idx(up, nsym(tree));
2142 if (idx > 0) {
2143 genop(s, MKOP_ABC(OP_GETUPVAR, cursp(), idx, lv));
2144 break;
2146 lv++;
2147 up = up->prev;
2150 push();
2152 break;
2154 case NODE_GVAR:
2155 if (val) {
2156 int sym = new_sym(s, nsym(tree));
2158 genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
2159 push();
2161 break;
2163 case NODE_IVAR:
2164 if (val) {
2165 int sym = new_sym(s, nsym(tree));
2167 genop(s, MKOP_ABx(OP_GETIV, cursp(), sym));
2168 push();
2170 break;
2172 case NODE_CVAR:
2173 if (val) {
2174 int sym = new_sym(s, nsym(tree));
2176 genop(s, MKOP_ABx(OP_GETCV, cursp(), sym));
2177 push();
2179 break;
2181 case NODE_CONST:
2183 int sym = new_sym(s, nsym(tree));
2185 genop(s, MKOP_ABx(OP_GETCONST, cursp(), sym));
2186 if (val) {
2187 push();
2190 break;
2192 case NODE_DEFINED:
2193 codegen(s, tree, VAL);
2194 break;
2196 case NODE_BACK_REF:
2197 if (val) {
2198 char buf[3];
2199 int sym;
2201 buf[0] = '$';
2202 buf[1] = nchar(tree);
2203 buf[2] = 0;
2204 sym = new_sym(s, mrb_intern_cstr(s->mrb, buf));
2205 genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
2206 push();
2208 break;
2210 case NODE_NTH_REF:
2211 if (val) {
2212 mrb_state *mrb = s->mrb;
2213 mrb_value str;
2214 int sym;
2216 str = mrb_format(mrb, "$%S", mrb_fixnum_value(nint(tree)));
2217 sym = new_sym(s, mrb_intern_str(mrb, str));
2218 genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
2219 push();
2221 break;
2223 case NODE_ARG:
2224 /* should not happen */
2225 break;
2227 case NODE_BLOCK_ARG:
2228 codegen(s, tree, VAL);
2229 break;
2231 case NODE_INT:
2232 if (val) {
2233 char *p = (char*)tree->car;
2234 int base = nint(tree->cdr->car);
2235 mrb_int i;
2236 mrb_code co;
2237 mrb_bool overflow;
2239 i = readint_mrb_int(s, p, base, FALSE, &overflow);
2240 if (overflow) {
2241 double f = readint_float(s, p, base);
2242 int off = new_lit(s, mrb_float_value(s->mrb, f));
2244 genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
2246 else {
2247 if (i < MAXARG_sBx && i > -MAXARG_sBx) {
2248 co = MKOP_AsBx(OP_LOADI, cursp(), i);
2250 else {
2251 int off = new_lit(s, mrb_fixnum_value(i));
2252 co = MKOP_ABx(OP_LOADL, cursp(), off);
2254 genop(s, co);
2256 push();
2258 break;
2260 case NODE_FLOAT:
2261 if (val) {
2262 char *p = (char*)tree;
2263 mrb_float f = mrb_float_read(p, NULL);
2264 int off = new_lit(s, mrb_float_value(s->mrb, f));
2266 genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
2267 push();
2269 break;
2271 case NODE_NEGATE:
2273 nt = nint(tree->car);
2274 tree = tree->cdr;
2275 switch (nt) {
2276 case NODE_FLOAT:
2277 if (val) {
2278 char *p = (char*)tree;
2279 mrb_float f = mrb_float_read(p, NULL);
2280 int off = new_lit(s, mrb_float_value(s->mrb, -f));
2282 genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
2283 push();
2285 break;
2287 case NODE_INT:
2288 if (val) {
2289 char *p = (char*)tree->car;
2290 int base = nint(tree->cdr->car);
2291 mrb_int i;
2292 mrb_code co;
2293 mrb_bool overflow;
2295 i = readint_mrb_int(s, p, base, TRUE, &overflow);
2296 if (overflow) {
2297 double f = readint_float(s, p, base);
2298 int off = new_lit(s, mrb_float_value(s->mrb, -f));
2300 genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
2302 else {
2303 if (i < MAXARG_sBx && i > -MAXARG_sBx) {
2304 co = MKOP_AsBx(OP_LOADI, cursp(), i);
2306 else {
2307 int off = new_lit(s, mrb_fixnum_value(i));
2308 co = MKOP_ABx(OP_LOADL, cursp(), off);
2310 genop(s, co);
2312 push();
2314 break;
2316 default:
2317 if (val) {
2318 int sym = new_msym(s, mrb_intern_lit(s->mrb, "-"));
2320 genop(s, MKOP_ABx(OP_LOADI, cursp(), 0));
2321 push();
2322 codegen(s, tree, VAL);
2323 pop(); pop();
2324 genop(s, MKOP_ABC(OP_SUB, cursp(), sym, 2));
2326 else {
2327 codegen(s, tree, NOVAL);
2329 break;
2332 break;
2334 case NODE_STR:
2335 if (val) {
2336 char *p = (char*)tree->car;
2337 size_t len = (intptr_t)tree->cdr;
2338 int ai = mrb_gc_arena_save(s->mrb);
2339 int off = new_lit(s, mrb_str_new(s->mrb, p, len));
2341 mrb_gc_arena_restore(s->mrb, ai);
2342 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2343 push();
2345 break;
2347 case NODE_HEREDOC:
2348 tree = ((struct mrb_parser_heredoc_info *)tree)->doc;
2349 /* fall through */
2350 case NODE_DSTR:
2351 if (val) {
2352 node *n = tree;
2354 if (!n) {
2355 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2356 push();
2357 break;
2359 codegen(s, n->car, VAL);
2360 n = n->cdr;
2361 while (n) {
2362 codegen(s, n->car, VAL);
2363 pop(); pop();
2364 genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
2365 push();
2366 n = n->cdr;
2369 else {
2370 node *n = tree;
2372 while (n) {
2373 if (nint(n->car->car) != NODE_STR) {
2374 codegen(s, n->car, NOVAL);
2376 n = n->cdr;
2379 break;
2381 case NODE_WORDS:
2382 gen_literal_array(s, tree, FALSE, val);
2383 break;
2385 case NODE_SYMBOLS:
2386 gen_literal_array(s, tree, TRUE, val);
2387 break;
2389 case NODE_DXSTR:
2391 node *n;
2392 int ai = mrb_gc_arena_save(s->mrb);
2393 int sym = new_sym(s, mrb_intern_lit(s->mrb, "Kernel"));
2395 genop(s, MKOP_A(OP_LOADSELF, cursp()));
2396 push();
2397 codegen(s, tree->car, VAL);
2398 n = tree->cdr;
2399 while (n) {
2400 if (nint(n->car->car) == NODE_XSTR) {
2401 n->car->car = (struct mrb_ast_node*)(intptr_t)NODE_STR;
2402 mrb_assert(!n->cdr); /* must be the end */
2404 codegen(s, n->car, VAL);
2405 pop(); pop();
2406 genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
2407 push();
2408 n = n->cdr;
2410 push(); /* for block */
2411 pop_n(3);
2412 sym = new_sym(s, mrb_intern_lit(s->mrb, "`"));
2413 genop(s, MKOP_ABC(OP_SEND, cursp(), sym, 1));
2414 if (val) push();
2415 mrb_gc_arena_restore(s->mrb, ai);
2417 break;
2419 case NODE_XSTR:
2421 char *p = (char*)tree->car;
2422 size_t len = (intptr_t)tree->cdr;
2423 int ai = mrb_gc_arena_save(s->mrb);
2424 int off = new_lit(s, mrb_str_new(s->mrb, p, len));
2425 int sym;
2427 genop(s, MKOP_A(OP_LOADSELF, cursp()));
2428 push();
2429 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2430 push(); push();
2431 pop_n(3);
2432 sym = new_sym(s, mrb_intern_lit(s->mrb, "`"));
2433 genop(s, MKOP_ABC(OP_SEND, cursp(), sym, 1));
2434 if (val) push();
2435 mrb_gc_arena_restore(s->mrb, ai);
2437 break;
2439 case NODE_REGX:
2440 if (val) {
2441 char *p1 = (char*)tree->car;
2442 char *p2 = (char*)tree->cdr->car;
2443 char *p3 = (char*)tree->cdr->cdr;
2444 int ai = mrb_gc_arena_save(s->mrb);
2445 int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS));
2446 int off = new_lit(s, mrb_str_new_cstr(s->mrb, p1));
2447 int argc = 1;
2449 genop(s, MKOP_A(OP_OCLASS, cursp()));
2450 genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
2451 push();
2452 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2453 if (p2 || p3) {
2454 push();
2455 if (p2) {
2456 off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
2457 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2459 else {
2460 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2462 argc++;
2463 if (p3) {
2464 push();
2465 off = new_lit(s, mrb_str_new(s->mrb, p3, 1));
2466 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2467 argc++;
2468 pop();
2470 pop();
2472 pop();
2473 sym = new_sym(s, mrb_intern_lit(s->mrb, "compile"));
2474 genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc));
2475 mrb_gc_arena_restore(s->mrb, ai);
2476 push();
2478 break;
2480 case NODE_DREGX:
2481 if (val) {
2482 node *n = tree->car;
2483 int ai = mrb_gc_arena_save(s->mrb);
2484 int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS));
2485 int argc = 1;
2486 int off;
2487 char *p;
2489 genop(s, MKOP_A(OP_OCLASS, cursp()));
2490 genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
2491 push();
2492 codegen(s, n->car, VAL);
2493 n = n->cdr;
2494 while (n) {
2495 codegen(s, n->car, VAL);
2496 pop(); pop();
2497 genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
2498 push();
2499 n = n->cdr;
2501 n = tree->cdr->cdr;
2502 if (n->car) {
2503 p = (char*)n->car;
2504 off = new_lit(s, mrb_str_new_cstr(s->mrb, p));
2505 codegen(s, tree->car, VAL);
2506 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2507 pop();
2508 genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
2510 if (n->cdr->car) {
2511 char *p2 = (char*)n->cdr->car;
2513 push();
2514 off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
2515 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2516 argc++;
2518 if (n->cdr->cdr) {
2519 char *p2 = (char*)n->cdr->cdr;
2521 push();
2522 off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
2523 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2524 argc++;
2526 pop_n(argc);
2527 sym = new_sym(s, mrb_intern_lit(s->mrb, "compile"));
2528 genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc));
2529 mrb_gc_arena_restore(s->mrb, ai);
2530 push();
2532 else {
2533 node *n = tree->car;
2535 while (n) {
2536 if (nint(n->car->car) != NODE_STR) {
2537 codegen(s, n->car, NOVAL);
2539 n = n->cdr;
2542 break;
2544 case NODE_SYM:
2545 if (val) {
2546 int sym = new_sym(s, nsym(tree));
2548 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym));
2549 push();
2551 break;
2553 case NODE_DSYM:
2554 codegen(s, tree, val);
2555 if (val) {
2556 gen_send_intern(s);
2558 break;
2560 case NODE_SELF:
2561 if (val) {
2562 genop(s, MKOP_A(OP_LOADSELF, cursp()));
2563 push();
2565 break;
2567 case NODE_NIL:
2568 if (val) {
2569 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2570 push();
2572 break;
2574 case NODE_TRUE:
2575 if (val) {
2576 genop(s, MKOP_A(OP_LOADT, cursp()));
2577 push();
2579 break;
2581 case NODE_FALSE:
2582 if (val) {
2583 genop(s, MKOP_A(OP_LOADF, cursp()));
2584 push();
2586 break;
2588 case NODE_ALIAS:
2590 int a = new_msym(s, nsym(tree->car));
2591 int b = new_msym(s, nsym(tree->cdr));
2592 int c = new_msym(s, mrb_intern_lit(s->mrb, "alias_method"));
2594 genop(s, MKOP_A(OP_TCLASS, cursp()));
2595 push();
2596 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), a));
2597 push();
2598 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), b));
2599 push();
2600 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2601 push(); /* space for a block */
2602 pop_n(4);
2603 genop(s, MKOP_ABC(OP_SEND, cursp(), c, 2));
2604 if (val) {
2605 push();
2608 break;
2610 case NODE_UNDEF:
2612 int undef = new_msym(s, mrb_intern_lit(s->mrb, "undef_method"));
2613 int num = 0;
2614 node *t = tree;
2616 genop(s, MKOP_A(OP_TCLASS, cursp()));
2617 push();
2618 while (t) {
2619 int symbol;
2620 if (num >= CALL_MAXARGS - 1) {
2621 pop_n(num);
2622 genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), num));
2623 while (t) {
2624 symbol = new_msym(s, nsym(t->car));
2625 push();
2626 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), symbol));
2627 pop();
2628 genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
2629 t = t->cdr;
2631 num = CALL_MAXARGS;
2632 break;
2634 symbol = new_msym(s, nsym(t->car));
2635 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), symbol));
2636 push();
2637 t = t->cdr;
2638 num++;
2640 push();pop(); /* space for a block */
2641 pop();
2642 if (num < CALL_MAXARGS) {
2643 pop_n(num);
2645 genop(s, MKOP_ABC(OP_SEND, cursp(), undef, num));
2646 if (val) {
2647 push();
2650 break;
2652 case NODE_CLASS:
2654 int idx;
2656 if (tree->car->car == (node*)0) {
2657 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2658 push();
2660 else if (tree->car->car == (node*)1) {
2661 genop(s, MKOP_A(OP_OCLASS, cursp()));
2662 push();
2664 else {
2665 codegen(s, tree->car->car, VAL);
2667 if (tree->cdr->car) {
2668 codegen(s, tree->cdr->car, VAL);
2670 else {
2671 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2672 push();
2674 pop(); pop();
2675 idx = new_msym(s, nsym(tree->car->cdr));
2676 genop(s, MKOP_AB(OP_CLASS, cursp(), idx));
2677 idx = scope_body(s, tree->cdr->cdr->car, val);
2678 genop(s, MKOP_ABx(OP_EXEC, cursp(), idx));
2679 if (val) {
2680 push();
2683 break;
2685 case NODE_MODULE:
2687 int idx;
2689 if (tree->car->car == (node*)0) {
2690 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2691 push();
2693 else if (tree->car->car == (node*)1) {
2694 genop(s, MKOP_A(OP_OCLASS, cursp()));
2695 push();
2697 else {
2698 codegen(s, tree->car->car, VAL);
2700 pop();
2701 idx = new_msym(s, nsym(tree->car->cdr));
2702 genop(s, MKOP_AB(OP_MODULE, cursp(), idx));
2703 idx = scope_body(s, tree->cdr->car, val);
2704 genop(s, MKOP_ABx(OP_EXEC, cursp(), idx));
2705 if (val) {
2706 push();
2709 break;
2711 case NODE_SCLASS:
2713 int idx;
2715 codegen(s, tree->car, VAL);
2716 pop();
2717 genop(s, MKOP_AB(OP_SCLASS, cursp(), cursp()));
2718 idx = scope_body(s, tree->cdr->car, val);
2719 genop(s, MKOP_ABx(OP_EXEC, cursp(), idx));
2720 if (val) {
2721 push();
2724 break;
2726 case NODE_DEF:
2728 int sym = new_msym(s, nsym(tree->car));
2729 int idx = lambda_body(s, tree->cdr, 0);
2731 genop(s, MKOP_A(OP_TCLASS, cursp()));
2732 push();
2733 genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_METHOD));
2734 push(); pop();
2735 pop();
2736 genop(s, MKOP_AB(OP_METHOD, cursp(), sym));
2737 if (val) {
2738 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym));
2739 push();
2742 break;
2744 case NODE_SDEF:
2746 node *recv = tree->car;
2747 int sym = new_msym(s, nsym(tree->cdr->car));
2748 int idx = lambda_body(s, tree->cdr->cdr, 0);
2750 codegen(s, recv, VAL);
2751 pop();
2752 genop(s, MKOP_AB(OP_SCLASS, cursp(), cursp()));
2753 push();
2754 genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_METHOD));
2755 pop();
2756 genop(s, MKOP_AB(OP_METHOD, cursp(), sym));
2757 if (val) {
2758 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym));
2759 push();
2762 break;
2764 case NODE_POSTEXE:
2765 codegen(s, tree, NOVAL);
2766 break;
2768 default:
2769 break;
2771 exit:
2772 s->rlev = rlev;
2775 static void
2776 scope_add_irep(codegen_scope *s, mrb_irep *irep)
2778 if (s->irep == NULL) {
2779 s->irep = irep;
2780 return;
2782 if (s->irep->rlen == s->rcapa) {
2783 s->rcapa *= 2;
2784 s->irep->reps = (mrb_irep**)codegen_realloc(s, s->irep->reps, sizeof(mrb_irep*)*s->rcapa);
2786 s->irep->reps[s->irep->rlen] = irep;
2787 s->irep->rlen++;
2790 static codegen_scope*
2791 scope_new(mrb_state *mrb, codegen_scope *prev, node *lv)
2793 static const codegen_scope codegen_scope_zero = { 0 };
2794 mrb_pool *pool = mrb_pool_open(mrb);
2795 codegen_scope *p = (codegen_scope *)mrb_pool_alloc(pool, sizeof(codegen_scope));
2797 if (!p) return NULL;
2798 *p = codegen_scope_zero;
2799 p->mrb = mrb;
2800 p->mpool = pool;
2801 if (!prev) return p;
2802 p->prev = prev;
2803 p->ainfo = -1;
2804 p->mscope = 0;
2806 p->irep = mrb_add_irep(mrb);
2807 scope_add_irep(prev, p->irep);
2809 p->rcapa = 8;
2810 p->irep->reps = (mrb_irep**)mrb_malloc(mrb, sizeof(mrb_irep*)*p->rcapa);
2812 p->icapa = 1024;
2813 p->iseq = (mrb_code*)mrb_malloc(mrb, sizeof(mrb_code)*p->icapa);
2814 p->irep->iseq = NULL;
2816 p->pcapa = 32;
2817 p->irep->pool = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value)*p->pcapa);
2818 p->irep->plen = 0;
2820 p->scapa = MAXMSYMLEN;
2821 p->irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*p->scapa);
2822 p->irep->slen = 0;
2824 p->lv = lv;
2825 p->sp += node_len(lv)+1; /* add self */
2826 p->nlocals = p->sp;
2827 if (lv) {
2828 node *n = lv;
2829 size_t i = 0;
2831 p->irep->lv = (struct mrb_locals*)mrb_malloc(mrb, sizeof(struct mrb_locals) * (p->nlocals - 1));
2832 for (i=0, n=lv; n; i++,n=n->cdr) {
2833 p->irep->lv[i].name = lv_name(n);
2834 if (lv_name(n)) {
2835 p->irep->lv[i].r = lv_idx(p, lv_name(n));
2837 else {
2838 p->irep->lv[i].r = 0;
2841 mrb_assert(i + 1 == p->nlocals);
2843 p->ai = mrb_gc_arena_save(mrb);
2845 p->filename = prev->filename;
2846 if (p->filename) {
2847 p->lines = (uint16_t*)mrb_malloc(mrb, sizeof(short)*p->icapa);
2849 p->lineno = prev->lineno;
2851 /* debug setting */
2852 p->debug_start_pos = 0;
2853 if (p->filename) {
2854 mrb_debug_info_alloc(mrb, p->irep);
2855 p->irep->filename = p->filename;
2856 p->irep->lines = p->lines;
2858 else {
2859 p->irep->debug_info = NULL;
2861 p->parser = prev->parser;
2862 p->filename_index = prev->filename_index;
2864 p->rlev = prev->rlev+1;
2866 return p;
2869 static void
2870 scope_finish(codegen_scope *s)
2872 mrb_state *mrb = s->mrb;
2873 mrb_irep *irep = s->irep;
2874 size_t fname_len;
2875 char *fname;
2877 irep->flags = 0;
2878 if (s->iseq) {
2879 irep->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc);
2880 irep->ilen = s->pc;
2881 if (s->lines) {
2882 irep->lines = (uint16_t *)codegen_realloc(s, s->lines, sizeof(uint16_t)*s->pc);
2884 else {
2885 irep->lines = 0;
2888 irep->pool = (mrb_value*)codegen_realloc(s, irep->pool, sizeof(mrb_value)*irep->plen);
2889 irep->syms = (mrb_sym*)codegen_realloc(s, irep->syms, sizeof(mrb_sym)*irep->slen);
2890 irep->reps = (mrb_irep**)codegen_realloc(s, irep->reps, sizeof(mrb_irep*)*irep->rlen);
2891 if (s->filename) {
2892 irep->filename = mrb_parser_get_filename(s->parser, s->filename_index);
2893 mrb_debug_info_append_file(mrb, irep, s->debug_start_pos, s->pc);
2895 fname_len = strlen(s->filename);
2896 fname = (char*)codegen_malloc(s, fname_len + 1);
2897 memcpy(fname, s->filename, fname_len);
2898 fname[fname_len] = '\0';
2899 irep->filename = fname;
2900 irep->own_filename = TRUE;
2903 irep->nlocals = s->nlocals;
2904 irep->nregs = s->nregs;
2906 mrb_gc_arena_restore(mrb, s->ai);
2907 mrb_pool_close(s->mpool);
2910 static struct loopinfo*
2911 loop_push(codegen_scope *s, enum looptype t)
2913 struct loopinfo *p = (struct loopinfo *)codegen_palloc(s, sizeof(struct loopinfo));
2915 p->type = t;
2916 p->pc1 = p->pc2 = p->pc3 = 0;
2917 p->prev = s->loop;
2918 p->ensure_level = s->ensure_level;
2919 p->acc = cursp();
2920 s->loop = p;
2922 return p;
2925 static void
2926 loop_break(codegen_scope *s, node *tree)
2928 if (!s->loop) {
2929 codegen(s, tree, NOVAL);
2930 raise_error(s, "unexpected break");
2932 else {
2933 struct loopinfo *loop;
2934 int n = 0;
2936 if (tree) {
2937 gen_retval(s, tree);
2940 loop = s->loop;
2941 while (loop) {
2942 if (loop->type == LOOP_BEGIN) {
2943 n++;
2944 loop = loop->prev;
2946 else if (loop->type == LOOP_RESCUE) {
2947 loop = loop->prev;
2949 else{
2950 break;
2953 if (!loop) {
2954 raise_error(s, "unexpected break");
2955 return;
2957 if (n > 0) {
2958 genop_peep(s, MKOP_A(OP_POPERR, n), NOVAL);
2961 if (loop->type == LOOP_NORMAL) {
2962 int tmp;
2964 if (s->ensure_level > s->loop->ensure_level) {
2965 genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL);
2967 if (tree) {
2968 genop_peep(s, MKOP_AB(OP_MOVE, loop->acc, cursp()), NOVAL);
2970 tmp = genop(s, MKOP_sBx(OP_JMP, loop->pc3));
2971 loop->pc3 = tmp;
2973 else {
2974 if (!tree) {
2975 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2977 genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_BREAK));
2982 static void
2983 loop_pop(codegen_scope *s, int val)
2985 if (val) {
2986 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2988 dispatch_linked(s, s->loop->pc3);
2989 s->loop = s->loop->prev;
2990 if (val) push();
2993 MRB_API struct RProc*
2994 mrb_generate_code(mrb_state *mrb, parser_state *p)
2996 codegen_scope *scope = scope_new(mrb, 0, 0);
2997 struct RProc *proc;
2998 struct mrb_jmpbuf *prev_jmp = mrb->jmp;
3000 if (!scope) {
3001 return NULL;
3003 scope->mrb = mrb;
3004 scope->parser = p;
3005 scope->filename = p->filename;
3006 scope->filename_index = p->current_filename_index;
3008 MRB_TRY(&scope->jmp) {
3009 mrb->jmp = &scope->jmp;
3010 /* prepare irep */
3011 codegen(scope, p->tree, NOVAL);
3012 proc = mrb_proc_new(mrb, scope->irep);
3013 mrb_irep_decref(mrb, scope->irep);
3014 mrb_pool_close(scope->mpool);
3015 proc->c = NULL;
3016 mrb->jmp = prev_jmp;
3017 return proc;
3019 MRB_CATCH(&scope->jmp) {
3020 mrb_irep_decref(mrb, scope->irep);
3021 mrb_pool_close(scope->mpool);
3022 mrb->jmp = prev_jmp;
3023 return NULL;
3025 MRB_END_EXC(&scope->jmp);