source: EcnlProtoTool/trunk/mruby-1.2.0/mrbgems/mruby-compiler/core/codegen.c@ 270

Last change on this file since 270 was 270, checked in by coas-nagasima, 7 years ago

mruby版ECNLプロトタイピング・ツールを追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc
File size: 62.7 KB
Line 
1/*
2** codegen.c - mruby code generator
3**
4** See Copyright Notice in mruby.h
5*/
6
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"
21
22typedef mrb_ast_node node;
23typedef struct mrb_parser_state parser_state;
24
25enum looptype {
26 LOOP_NORMAL,
27 LOOP_BLOCK,
28 LOOP_FOR,
29 LOOP_BEGIN,
30 LOOP_RESCUE,
31};
32
33struct loopinfo {
34 enum looptype type;
35 int pc1, pc2, pc3, acc;
36 int ensure_level;
37 struct loopinfo *prev;
38};
39
40typedef struct scope {
41 mrb_state *mrb;
42 mrb_pool *mpool;
43 struct mrb_jmpbuf jmp;
44
45 struct scope *prev;
46
47 node *lv;
48
49 int sp;
50 int pc;
51 int lastlabel;
52 int ainfo:15;
53 mrb_bool mscope:1;
54
55 struct loopinfo *loop;
56 int ensure_level;
57 char const *filename;
58 uint16_t lineno;
59
60 mrb_code *iseq;
61 uint16_t *lines;
62 int icapa;
63
64 mrb_irep *irep;
65 size_t pcapa;
66 size_t scapa;
67 size_t rcapa;
68
69 uint16_t nlocals;
70 uint16_t nregs;
71 int ai;
72
73 int debug_start_pos;
74 uint16_t filename_index;
75 parser_state* parser;
76} codegen_scope;
77
78static codegen_scope* scope_new(mrb_state *mrb, codegen_scope *prev, node *lv);
79static void scope_finish(codegen_scope *s);
80static struct loopinfo *loop_push(codegen_scope *s, enum looptype t);
81static void loop_break(codegen_scope *s, node *tree);
82static void loop_pop(codegen_scope *s, int val);
83
84static void gen_assignment(codegen_scope *s, node *tree, int sp, int val);
85static void gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val);
86
87static void codegen(codegen_scope *s, node *tree, int val);
88static void raise_error(codegen_scope *s, const char *msg);
89
90static void
91codegen_error(codegen_scope *s, const char *message)
92{
93 if (!s) return;
94 while (s->prev) {
95 codegen_scope *tmp = s->prev;
96 mrb_pool_close(s->mpool);
97 s = tmp;
98 }
99#ifndef MBB_DISABLE_STDIO
100 if (s->filename && s->lineno) {
101 fprintf(stderr, "codegen error:%s:%d: %s\n", s->filename, s->lineno, message);
102 }
103 else {
104 fprintf(stderr, "codegen error: %s\n", message);
105 }
106#endif
107 MRB_THROW(&s->jmp);
108}
109
110static void*
111codegen_palloc(codegen_scope *s, size_t len)
112{
113 void *p = mrb_pool_alloc(s->mpool, len);
114
115 if (!p) codegen_error(s, "pool memory allocation");
116 return p;
117}
118
119static void*
120codegen_malloc(codegen_scope *s, size_t len)
121{
122 void *p = mrb_malloc_simple(s->mrb, len);
123
124 if (!p) codegen_error(s, "mrb_malloc");
125 return p;
126}
127
128static void*
129codegen_realloc(codegen_scope *s, void *p, size_t len)
130{
131 p = mrb_realloc_simple(s->mrb, p, len);
132
133 if (!p && len > 0) codegen_error(s, "mrb_realloc");
134 return p;
135}
136
137static int
138new_label(codegen_scope *s)
139{
140 s->lastlabel = s->pc;
141 return s->pc;
142}
143
144static inline int
145genop(codegen_scope *s, mrb_code i)
146{
147 if (s->pc == s->icapa) {
148 s->icapa *= 2;
149 s->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->icapa);
150 if (s->lines) {
151 s->lines = (uint16_t*)codegen_realloc(s, s->lines, sizeof(short)*s->icapa);
152 s->irep->lines = s->lines;
153 }
154 }
155 s->iseq[s->pc] = i;
156 if (s->lines) {
157 s->lines[s->pc] = s->lineno;
158 }
159 return s->pc++;
160}
161
162#define NOVAL 0
163#define VAL 1
164
165static mrb_bool
166no_optimize(codegen_scope *s)
167{
168 if (s && s->parser && s->parser->no_optimize)
169 return TRUE;
170 return FALSE;
171}
172
173static int
174genop_peep(codegen_scope *s, mrb_code i, int val)
175{
176 /* peephole optimization */
177 if (!no_optimize(s) && s->lastlabel != s->pc && s->pc > 0) {
178 mrb_code i0 = s->iseq[s->pc-1];
179 int c1 = GET_OPCODE(i);
180 int c0 = GET_OPCODE(i0);
181
182 switch (c1) {
183 case OP_MOVE:
184 if (GETARG_A(i) == GETARG_B(i)) {
185 /* skip useless OP_MOVE */
186 return 0;
187 }
188 if (val) break;
189 switch (c0) {
190 case OP_MOVE:
191 if (GETARG_A(i) == GETARG_A(i0)) {
192 /* skip overriden OP_MOVE */
193 s->pc--;
194 s->iseq[s->pc] = i;
195 }
196 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i) == GETARG_B(i0)) {
197 /* skip swapping OP_MOVE */
198 return 0;
199 }
200 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
201 s->pc--;
202 return genop_peep(s, MKOP_AB(OP_MOVE, GETARG_A(i), GETARG_B(i0)), val);
203 }
204 break;
205 case OP_LOADI:
206 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
207 s->iseq[s->pc-1] = MKOP_AsBx(OP_LOADI, GETARG_A(i), GETARG_sBx(i0));
208 return 0;
209 }
210 break;
211 case OP_ARRAY:
212 case OP_HASH:
213 case OP_RANGE:
214 case OP_AREF:
215 case OP_GETUPVAR:
216 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
217 s->iseq[s->pc-1] = MKOP_ABC(c0, GETARG_A(i), GETARG_B(i0), GETARG_C(i0));
218 return 0;
219 }
220 break;
221 case OP_LOADSYM:
222 case OP_GETGLOBAL:
223 case OP_GETIV:
224 case OP_GETCV:
225 case OP_GETCONST:
226 case OP_GETSPECIAL:
227 case OP_LOADL:
228 case OP_STRING:
229 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
230 s->iseq[s->pc-1] = MKOP_ABx(c0, GETARG_A(i), GETARG_Bx(i0));
231 return 0;
232 }
233 break;
234 case OP_SCLASS:
235 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
236 s->iseq[s->pc-1] = MKOP_AB(c0, GETARG_A(i), GETARG_B(i0));
237 return 0;
238 }
239 break;
240 case OP_LOADNIL:
241 case OP_LOADSELF:
242 case OP_LOADT:
243 case OP_LOADF:
244 case OP_OCLASS:
245 if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
246 s->iseq[s->pc-1] = MKOP_A(c0, GETARG_A(i));
247 return 0;
248 }
249 break;
250 default:
251 break;
252 }
253 break;
254 case OP_SETIV:
255 case OP_SETCV:
256 case OP_SETCONST:
257 case OP_SETMCNST:
258 case OP_SETGLOBAL:
259 if (val) break;
260 if (c0 == OP_MOVE) {
261 if (GETARG_A(i) == GETARG_A(i0)) {
262 s->iseq[s->pc-1] = MKOP_ABx(c1, GETARG_B(i0), GETARG_Bx(i));
263 return 0;
264 }
265 }
266 break;
267 case OP_SETUPVAR:
268 if (val) break;
269 if (c0 == OP_MOVE) {
270 if (GETARG_A(i) == GETARG_A(i0)) {
271 s->iseq[s->pc-1] = MKOP_ABC(c1, GETARG_B(i0), GETARG_B(i), GETARG_C(i));
272 return 0;
273 }
274 }
275 break;
276 case OP_EPOP:
277 if (c0 == OP_EPOP) {
278 s->iseq[s->pc-1] = MKOP_A(OP_EPOP, GETARG_A(i0)+GETARG_A(i));
279 return 0;
280 }
281 break;
282 case OP_POPERR:
283 if (c0 == OP_POPERR) {
284 s->iseq[s->pc-1] = MKOP_A(OP_POPERR, GETARG_A(i0)+GETARG_A(i));
285 return 0;
286 }
287 break;
288 case OP_RETURN:
289 switch (c0) {
290 case OP_RETURN:
291 return 0;
292 case OP_MOVE:
293 if (GETARG_A(i0) >= s->nlocals) {
294 s->iseq[s->pc-1] = MKOP_AB(OP_RETURN, GETARG_B(i0), OP_R_NORMAL);
295 return 0;
296 }
297 break;
298 case OP_SETIV:
299 case OP_SETCV:
300 case OP_SETCONST:
301 case OP_SETMCNST:
302 case OP_SETUPVAR:
303 case OP_SETGLOBAL:
304 s->pc--;
305 genop_peep(s, i0, NOVAL);
306 i0 = s->iseq[s->pc-1];
307 return genop(s, MKOP_AB(OP_RETURN, GETARG_A(i0), OP_R_NORMAL));
308#if 0
309 case OP_SEND:
310 if (GETARG_B(i) == OP_R_NORMAL && GETARG_A(i) == GETARG_A(i0)) {
311 s->iseq[s->pc-1] = MKOP_ABC(OP_TAILCALL, GETARG_A(i0), GETARG_B(i0), GETARG_C(i0));
312 return;
313 }
314 break;
315#endif
316 default:
317 break;
318 }
319 break;
320 case OP_ADD:
321 case OP_SUB:
322 if (c0 == OP_LOADI) {
323 int c = GETARG_sBx(i0);
324
325 if (c1 == OP_SUB) c = -c;
326 if (c > 127 || c < -127) break;
327 if (0 <= c)
328 s->iseq[s->pc-1] = MKOP_ABC(OP_ADDI, GETARG_A(i), GETARG_B(i), c);
329 else
330 s->iseq[s->pc-1] = MKOP_ABC(OP_SUBI, GETARG_A(i), GETARG_B(i), -c);
331 return 0;
332 }
333 case OP_STRCAT:
334 if (c0 == OP_STRING) {
335 mrb_value v = s->irep->pool[GETARG_Bx(i0)];
336
337 if (mrb_string_p(v) && RSTRING_LEN(v) == 0) {
338 s->pc--;
339 return 0;
340 }
341 }
342 break;
343 case OP_JMPIF:
344 case OP_JMPNOT:
345 if (c0 == OP_MOVE && GETARG_A(i) == GETARG_A(i0)) {
346 s->iseq[s->pc-1] = MKOP_AsBx(c1, GETARG_B(i0), GETARG_sBx(i));
347 return s->pc-1;
348 }
349 break;
350 default:
351 break;
352 }
353 }
354 return genop(s, i);
355}
356
357static void
358scope_error(codegen_scope *s)
359{
360 exit(EXIT_FAILURE);
361}
362
363static inline void
364dispatch(codegen_scope *s, int pc)
365{
366 int diff = s->pc - pc;
367 mrb_code i = s->iseq[pc];
368 int c = GET_OPCODE(i);
369
370 s->lastlabel = s->pc;
371 switch (c) {
372 case OP_JMP:
373 case OP_JMPIF:
374 case OP_JMPNOT:
375 case OP_ONERR:
376 break;
377 default:
378#ifndef MRB_DISABLE_STDIO
379 fprintf(stderr, "bug: dispatch on non JMP op\n");
380#endif
381 scope_error(s);
382 break;
383 }
384 s->iseq[pc] = MKOP_AsBx(c, GETARG_A(i), diff);
385}
386
387static void
388dispatch_linked(codegen_scope *s, int pc)
389{
390 mrb_code i;
391 int pos;
392
393 if (!pc) return;
394 for (;;) {
395 i = s->iseq[pc];
396 pos = GETARG_sBx(i);
397 dispatch(s, pc);
398 if (!pos) break;
399 pc = pos;
400 }
401}
402
403#define nregs_update do {if (s->sp > s->nregs) s->nregs = s->sp;} while (0)
404static void
405push_(codegen_scope *s)
406{
407 if (s->sp > 511) {
408 codegen_error(s, "too complex expression");
409 }
410 s->sp++;
411 nregs_update;
412}
413
414static void
415push_n_(codegen_scope *s, size_t n)
416{
417 if (s->sp+n > 511) {
418 codegen_error(s, "too complex expression");
419 }
420 s->sp+=n;
421 nregs_update;
422}
423
424#define push() push_(s)
425#define push_n(n) push_n_(s,n)
426#define pop_(s) ((s)->sp--)
427#define pop() pop_(s)
428#define pop_n(n) (s->sp-=(n))
429#define cursp() (s->sp)
430
431static inline int
432new_lit(codegen_scope *s, mrb_value val)
433{
434 size_t i;
435 mrb_value *pv;
436
437 switch (mrb_type(val)) {
438 case MRB_TT_STRING:
439 for (i=0; i<s->irep->plen; i++) {
440 mrb_int len;
441 pv = &s->irep->pool[i];
442
443 if (mrb_type(*pv) != MRB_TT_STRING) continue;
444 if ((len = RSTRING_LEN(*pv)) != RSTRING_LEN(val)) continue;
445 if (memcmp(RSTRING_PTR(*pv), RSTRING_PTR(val), len) == 0)
446 return i;
447 }
448 break;
449 case MRB_TT_FLOAT:
450 for (i=0; i<s->irep->plen; i++) {
451 pv = &s->irep->pool[i];
452 if (mrb_type(*pv) != MRB_TT_FLOAT) continue;
453 if (mrb_float(*pv) == mrb_float(val)) return i;
454 }
455 break;
456 case MRB_TT_FIXNUM:
457 for (i=0; i<s->irep->plen; i++) {
458 pv = &s->irep->pool[i];
459 if (!mrb_fixnum_p(*pv)) continue;
460 if (mrb_fixnum(*pv) == mrb_fixnum(val)) return i;
461 }
462 break;
463 default:
464 /* should not happen */
465 return 0;
466 }
467
468 if (s->irep->plen == s->pcapa) {
469 s->pcapa *= 2;
470 s->irep->pool = (mrb_value *)codegen_realloc(s, s->irep->pool, sizeof(mrb_value)*s->pcapa);
471 }
472
473 pv = &s->irep->pool[s->irep->plen];
474 i = s->irep->plen++;
475
476 switch (mrb_type(val)) {
477 case MRB_TT_STRING:
478 *pv = mrb_str_pool(s->mrb, val);
479 break;
480
481 case MRB_TT_FLOAT:
482#ifdef MRB_WORD_BOXING
483 *pv = mrb_float_pool(s->mrb, mrb_float(val));
484 break;
485#endif
486 case MRB_TT_FIXNUM:
487 *pv = val;
488 break;
489
490 default:
491 /* should not happen */
492 break;
493 }
494 return i;
495}
496
497static inline int
498new_msym(codegen_scope *s, mrb_sym sym)
499{
500 size_t i, len;
501
502 mrb_assert(s->irep);
503
504 len = s->irep->slen;
505 if (len > 256) len = 256;
506 for (i=0; i<len; i++) {
507 if (s->irep->syms[i] == sym) return i;
508 if (s->irep->syms[i] == 0) break;
509 }
510 if (i == 256) {
511 codegen_error(s, "too many symbols (max 256)");
512 }
513 s->irep->syms[i] = sym;
514 if (i == s->irep->slen) s->irep->slen++;
515 return i;
516}
517
518static inline int
519new_sym(codegen_scope *s, mrb_sym sym)
520{
521 size_t i;
522
523 for (i=0; i<s->irep->slen; i++) {
524 if (s->irep->syms[i] == sym) return i;
525 }
526 if (s->irep->slen > 125 && s->irep->slen < 256) {
527 s->irep->syms = (mrb_sym *)codegen_realloc(s, s->irep->syms, sizeof(mrb_sym)*65536);
528 for (i = 0; i < 256 - s->irep->slen; i++) {
529 static const mrb_sym mrb_sym_zero = { 0 };
530 s->irep->syms[i + s->irep->slen] = mrb_sym_zero;
531 }
532 s->irep->slen = 256;
533 }
534 s->irep->syms[s->irep->slen] = sym;
535 return s->irep->slen++;
536}
537
538static int
539node_len(node *tree)
540{
541 int n = 0;
542
543 while (tree) {
544 n++;
545 tree = tree->cdr;
546 }
547 return n;
548}
549
550#define sym(x) ((mrb_sym)(intptr_t)(x))
551#define lv_name(lv) sym((lv)->car)
552static int
553lv_idx(codegen_scope *s, mrb_sym id)
554{
555 node *lv = s->lv;
556 int n = 1;
557
558 while (lv) {
559 if (lv_name(lv) == id) return n;
560 n++;
561 lv = lv->cdr;
562 }
563 return 0;
564}
565
566static void
567for_body(codegen_scope *s, node *tree)
568{
569 codegen_scope *prev = s;
570 int idx;
571 struct loopinfo *lp;
572 node *n2;
573 mrb_code c;
574
575 /* generate receiver */
576 codegen(s, tree->cdr->car, VAL);
577 /* generate loop-block */
578 s = scope_new(s->mrb, s, NULL);
579 if (s == NULL) {
580 raise_error(prev, "unexpected scope");
581 }
582
583 push(); /* push for a block parameter */
584
585 lp = loop_push(s, LOOP_FOR);
586 lp->pc1 = new_label(s);
587
588 /* generate loop variable */
589 n2 = tree->car;
590 genop(s, MKOP_Ax(OP_ENTER, 0x40000));
591 if (n2->car && !n2->car->cdr && !n2->cdr) {
592 gen_assignment(s, n2->car->car, 1, NOVAL);
593 }
594 else {
595 gen_vmassignment(s, n2, 1, VAL);
596 }
597 codegen(s, tree->cdr->cdr->car, VAL);
598 pop();
599 if (s->pc > 0) {
600 c = s->iseq[s->pc-1];
601 if (GET_OPCODE(c) != OP_RETURN || GETARG_B(c) != OP_R_NORMAL || s->pc == s->lastlabel)
602 genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
603 }
604 loop_pop(s, NOVAL);
605 scope_finish(s);
606 s = prev;
607 genop(s, MKOP_Abc(OP_LAMBDA, cursp(), s->irep->rlen-1, OP_L_BLOCK));
608 pop();
609 idx = new_msym(s, mrb_intern_lit(s->mrb, "each"));
610 genop(s, MKOP_ABC(OP_SENDB, cursp(), idx, 0));
611}
612
613static int
614lambda_body(codegen_scope *s, node *tree, int blk)
615{
616 mrb_code c;
617 codegen_scope *parent = s;
618 s = scope_new(s->mrb, s, tree->car);
619 if (s == NULL) {
620 raise_error(parent, "unexpected scope");
621 }
622
623 s->mscope = !blk;
624
625 if (blk) {
626 struct loopinfo *lp = loop_push(s, LOOP_BLOCK);
627 lp->pc1 = new_label(s);
628 }
629 tree = tree->cdr;
630 if (tree->car) {
631 mrb_aspec a;
632 int ma, oa, ra, pa, ka, kd, ba;
633 int pos, i;
634 node *n, *opt;
635
636 ma = node_len(tree->car->car);
637 n = tree->car->car;
638 while (n) {
639 n = n->cdr;
640 }
641 oa = node_len(tree->car->cdr->car);
642 ra = tree->car->cdr->cdr->car ? 1 : 0;
643 pa = node_len(tree->car->cdr->cdr->cdr->car);
644 ka = kd = 0;
645 ba = tree->car->cdr->cdr->cdr->cdr ? 1 : 0;
646
647 a = ((mrb_aspec)(ma & 0x1f) << 18)
648 | ((mrb_aspec)(oa & 0x1f) << 13)
649 | ((ra & 1) << 12)
650 | ((pa & 0x1f) << 7)
651 | ((ka & 0x1f) << 2)
652 | ((kd & 1)<< 1)
653 | (ba & 1);
654 s->ainfo = (((ma+oa) & 0x3f) << 6) /* (12bits = 6:1:5) */
655 | ((ra & 1) << 5)
656 | (pa & 0x1f);
657 genop(s, MKOP_Ax(OP_ENTER, a));
658 pos = new_label(s);
659 for (i=0; i<oa; i++) {
660 new_label(s);
661 genop(s, MKOP_sBx(OP_JMP, 0));
662 }
663 if (oa > 0) {
664 genop(s, MKOP_sBx(OP_JMP, 0));
665 }
666 opt = tree->car->cdr->car;
667 i = 0;
668 while (opt) {
669 int idx;
670
671 dispatch(s, pos+i);
672 codegen(s, opt->car->cdr, VAL);
673 idx = lv_idx(s, (mrb_sym)(intptr_t)opt->car->car);
674 pop();
675 genop_peep(s, MKOP_AB(OP_MOVE, idx, cursp()), NOVAL);
676 i++;
677 opt = opt->cdr;
678 }
679 if (oa > 0) {
680 dispatch(s, pos+i);
681 }
682 }
683 codegen(s, tree->cdr->car, VAL);
684 pop();
685 if (s->pc > 0) {
686 c = s->iseq[s->pc-1];
687 if (GET_OPCODE(c) != OP_RETURN || GETARG_B(c) != OP_R_NORMAL || s->pc == s->lastlabel) {
688 if (s->nregs == 0) {
689 genop(s, MKOP_A(OP_LOADNIL, 0));
690 genop(s, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
691 }
692 else {
693 genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
694 }
695 }
696 }
697 if (blk) {
698 loop_pop(s, NOVAL);
699 }
700 scope_finish(s);
701 return parent->irep->rlen - 1;
702}
703
704static int
705scope_body(codegen_scope *s, node *tree, int val)
706{
707 codegen_scope *scope = scope_new(s->mrb, s, tree->car);
708 if (scope == NULL) {
709 raise_error(s, "unexpected scope");
710 }
711
712 codegen(scope, tree->cdr, VAL);
713 if (!s->iseq) {
714 genop(scope, MKOP_A(OP_STOP, 0));
715 }
716 else if (!val) {
717 genop(scope, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
718 }
719 else {
720 if (scope->nregs == 0) {
721 genop(scope, MKOP_A(OP_LOADNIL, 0));
722 genop(scope, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
723 }
724 else {
725 genop_peep(scope, MKOP_AB(OP_RETURN, scope->sp-1, OP_R_NORMAL), NOVAL);
726 }
727 }
728 scope_finish(scope);
729 if (!s->irep) {
730 /* should not happen */
731 return 0;
732 }
733 return s->irep->rlen - 1;
734}
735
736static mrb_bool
737nosplat(node *t)
738{
739 while (t) {
740 if ((intptr_t)t->car->car == NODE_SPLAT) return FALSE;
741 t = t->cdr;
742 }
743 return TRUE;
744}
745
746static mrb_sym
747attrsym(codegen_scope *s, mrb_sym a)
748{
749 const char *name;
750 mrb_int len;
751 char *name2;
752
753 name = mrb_sym2name_len(s->mrb, a, &len);
754 name2 = (char *)codegen_palloc(s,
755 (size_t)len
756 + 1 /* '=' */
757 + 1 /* '\0' */
758 );
759 mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX);
760 memcpy(name2, name, (size_t)len);
761 name2[len] = '=';
762 name2[len+1] = '\0';
763
764 return mrb_intern(s->mrb, name2, len+1);
765}
766
767static int
768gen_values(codegen_scope *s, node *t, int val)
769{
770 int n = 0;
771 int is_splat;
772
773 while (t) {
774 is_splat = (intptr_t)t->car->car == NODE_SPLAT; /* splat mode */
775 if (n >= 127 || is_splat) {
776 if (val) {
777 pop_n(n);
778 genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), n));
779 push();
780 codegen(s, t->car, VAL);
781 pop(); pop();
782 if (is_splat) {
783 genop(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1));
784 }
785 else {
786 genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
787 }
788 t = t->cdr;
789 while (t) {
790 push();
791 codegen(s, t->car, VAL);
792 pop(); pop();
793 if ((intptr_t)t->car->car == NODE_SPLAT) {
794 genop(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1));
795 }
796 else {
797 genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
798 }
799 t = t->cdr;
800 }
801 }
802 else {
803 codegen(s, t->car->cdr, NOVAL);
804 t = t->cdr;
805 while (t) {
806 codegen(s, t->car, NOVAL);
807 t = t->cdr;
808 }
809 }
810 return -1;
811 }
812 /* normal (no splat) mode */
813 codegen(s, t->car, val);
814 n++;
815 t = t->cdr;
816 }
817 return n;
818}
819
820#define CALL_MAXARGS 127
821
822static void
823gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val)
824{
825 mrb_sym sym = name ? name : sym(tree->cdr->car);
826 int idx;
827 int n = 0, noop = 0, sendv = 0, blk = 0;
828
829 codegen(s, tree->car, VAL); /* receiver */
830 idx = new_msym(s, sym);
831 tree = tree->cdr->cdr->car;
832 if (tree) {
833 n = gen_values(s, tree->car, VAL);
834 if (n < 0) {
835 n = noop = sendv = 1;
836 push();
837 }
838 }
839 if (sp) {
840 if (sendv) {
841 pop();
842 genop(s, MKOP_AB(OP_ARYPUSH, cursp(), sp));
843 push();
844 }
845 else {
846 genop(s, MKOP_AB(OP_MOVE, cursp(), sp));
847 push();
848 n++;
849 }
850 }
851 if (tree && tree->cdr) {
852 noop = 1;
853 codegen(s, tree->cdr, VAL);
854 pop();
855 }
856 else {
857 blk = cursp();
858 }
859 push();pop();
860 pop_n(n+1);
861 {
862 mrb_int symlen;
863 const char *symname = mrb_sym2name_len(s->mrb, sym, &symlen);
864
865 if (!noop && symlen == 1 && symname[0] == '+') {
866 genop_peep(s, MKOP_ABC(OP_ADD, cursp(), idx, n), val);
867 }
868 else if (!noop && symlen == 1 && symname[0] == '-') {
869 genop_peep(s, MKOP_ABC(OP_SUB, cursp(), idx, n), val);
870 }
871 else if (!noop && symlen == 1 && symname[0] == '*') {
872 genop(s, MKOP_ABC(OP_MUL, cursp(), idx, n));
873 }
874 else if (!noop && symlen == 1 && symname[0] == '/') {
875 genop(s, MKOP_ABC(OP_DIV, cursp(), idx, n));
876 }
877 else if (!noop && symlen == 1 && symname[0] == '<') {
878 genop(s, MKOP_ABC(OP_LT, cursp(), idx, n));
879 }
880 else if (!noop && symlen == 2 && symname[0] == '<' && symname[1] == '=') {
881 genop(s, MKOP_ABC(OP_LE, cursp(), idx, n));
882 }
883 else if (!noop && symlen == 1 && symname[0] == '>') {
884 genop(s, MKOP_ABC(OP_GT, cursp(), idx, n));
885 }
886 else if (!noop && symlen == 2 && symname[0] == '>' && symname[1] == '=') {
887 genop(s, MKOP_ABC(OP_GE, cursp(), idx, n));
888 }
889 else if (!noop && symlen == 2 && symname[0] == '=' && symname[1] == '=') {
890 genop(s, MKOP_ABC(OP_EQ, cursp(), idx, n));
891 }
892 else {
893 if (sendv) n = CALL_MAXARGS;
894 if (blk > 0) { /* no block */
895 genop(s, MKOP_ABC(OP_SEND, cursp(), idx, n));
896 }
897 else {
898 genop(s, MKOP_ABC(OP_SENDB, cursp(), idx, n));
899 }
900 }
901 }
902 if (val) {
903 push();
904 }
905}
906
907static void
908gen_assignment(codegen_scope *s, node *tree, int sp, int val)
909{
910 int idx;
911 int type = (intptr_t)tree->car;
912
913 tree = tree->cdr;
914 switch ((intptr_t)type) {
915 case NODE_GVAR:
916 idx = new_sym(s, sym(tree));
917 genop_peep(s, MKOP_ABx(OP_SETGLOBAL, sp, idx), val);
918 break;
919 case NODE_LVAR:
920 idx = lv_idx(s, sym(tree));
921 if (idx > 0) {
922 if (idx != sp) {
923 genop_peep(s, MKOP_AB(OP_MOVE, idx, sp), val);
924 }
925 break;
926 }
927 else { /* upvar */
928 int lv = 0;
929 codegen_scope *up = s->prev;
930
931 while (up) {
932 idx = lv_idx(up, sym(tree));
933 if (idx > 0) {
934 genop_peep(s, MKOP_ABC(OP_SETUPVAR, sp, idx, lv), val);
935 break;
936 }
937 lv++;
938 up = up->prev;
939 }
940 }
941 break;
942 case NODE_IVAR:
943 idx = new_sym(s, sym(tree));
944 genop_peep(s, MKOP_ABx(OP_SETIV, sp, idx), val);
945 break;
946 case NODE_CVAR:
947 idx = new_sym(s, sym(tree));
948 genop_peep(s, MKOP_ABx(OP_SETCV, sp, idx), val);
949 break;
950 case NODE_CONST:
951 idx = new_sym(s, sym(tree));
952 genop_peep(s, MKOP_ABx(OP_SETCONST, sp, idx), val);
953 break;
954 case NODE_COLON2:
955 idx = new_sym(s, sym(tree->cdr));
956 genop_peep(s, MKOP_AB(OP_MOVE, cursp(), sp), NOVAL);
957 push();
958 codegen(s, tree->car, VAL);
959 pop_n(2);
960 genop_peep(s, MKOP_ABx(OP_SETMCNST, cursp(), idx), val);
961 break;
962
963 case NODE_CALL:
964 push();
965 gen_call(s, tree, attrsym(s, sym(tree->cdr->car)), sp, NOVAL);
966 pop();
967 if (val) {
968 genop_peep(s, MKOP_AB(OP_MOVE, cursp(), sp), val);
969 }
970 break;
971
972 case NODE_MASGN:
973 gen_vmassignment(s, tree->car, sp, val);
974 break;
975
976 /* splat without assignment */
977 case NODE_NIL:
978 break;
979
980 default:
981#ifndef MRB_DISABLE_STDIO
982 printf("unknown lhs %d\n", type);
983#endif
984 break;
985 }
986 if (val) push();
987}
988
989static void
990gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val)
991{
992 int n = 0, post = 0;
993 node *t, *p;
994
995 if (tree->car) { /* pre */
996 t = tree->car;
997 n = 0;
998 while (t) {
999 genop(s, MKOP_ABC(OP_AREF, cursp(), rhs, n));
1000 gen_assignment(s, t->car, cursp(), NOVAL);
1001 n++;
1002 t = t->cdr;
1003 }
1004 }
1005 t = tree->cdr;
1006 if (t) {
1007 if (t->cdr) { /* post count */
1008 p = t->cdr->car;
1009 while (p) {
1010 post++;
1011 p = p->cdr;
1012 }
1013 }
1014 if (val) {
1015 genop(s, MKOP_AB(OP_MOVE, cursp(), rhs));
1016 }
1017 else {
1018 pop();
1019 }
1020 push_n(post);
1021 pop_n(post);
1022 genop(s, MKOP_ABC(OP_APOST, cursp(), n, post));
1023 n = 1;
1024 if (t->car) { /* rest */
1025 gen_assignment(s, t->car, cursp(), NOVAL);
1026 }
1027 if (t->cdr && t->cdr->car) {
1028 t = t->cdr->car;
1029 while (t) {
1030 gen_assignment(s, t->car, cursp()+n, NOVAL);
1031 t = t->cdr;
1032 n++;
1033 }
1034 }
1035 push();
1036 }
1037}
1038
1039static void
1040gen_send_intern(codegen_scope *s)
1041{
1042 pop();
1043 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "intern")), 0));
1044 push();
1045}
1046static void
1047gen_literal_array(codegen_scope *s, node *tree, mrb_bool sym, int val)
1048{
1049 if (val) {
1050 int i = 0, j = 0;
1051
1052 while (tree) {
1053 switch ((intptr_t)tree->car->car) {
1054 case NODE_STR:
1055 if ((tree->cdr == NULL) && ((intptr_t)tree->car->cdr->cdr == 0))
1056 break;
1057 /* fall through */
1058 case NODE_BEGIN:
1059 codegen(s, tree->car, VAL);
1060 ++j;
1061 break;
1062
1063 case NODE_LITERAL_DELIM:
1064 if (j > 0) {
1065 j = 0;
1066 ++i;
1067 if (sym)
1068 gen_send_intern(s);
1069 }
1070 break;
1071 }
1072 if (j >= 2) {
1073 pop(); pop();
1074 genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
1075 push();
1076 j = 1;
1077 }
1078 tree = tree->cdr;
1079 }
1080 if (j > 0) {
1081 ++i;
1082 if (sym)
1083 gen_send_intern(s);
1084 }
1085 pop_n(i);
1086 genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), i));
1087 push();
1088 }
1089 else {
1090 while (tree) {
1091 switch ((intptr_t)tree->car->car) {
1092 case NODE_BEGIN: case NODE_BLOCK:
1093 codegen(s, tree->car, NOVAL);
1094 }
1095 tree = tree->cdr;
1096 }
1097 }
1098}
1099
1100static void
1101raise_error(codegen_scope *s, const char *msg)
1102{
1103 int idx = new_lit(s, mrb_str_new_cstr(s->mrb, msg));
1104
1105 genop(s, MKOP_ABx(OP_ERR, 1, idx));
1106}
1107
1108static double
1109readint_float(codegen_scope *s, const char *p, int base)
1110{
1111 const char *e = p + strlen(p);
1112 double f = 0;
1113 int n;
1114
1115 if (*p == '+') p++;
1116 while (p < e) {
1117 char c = *p;
1118 c = tolower((unsigned char)c);
1119 for (n=0; n<base; n++) {
1120 if (mrb_digitmap[n] == c) {
1121 f *= base;
1122 f += n;
1123 break;
1124 }
1125 }
1126 if (n == base) {
1127 codegen_error(s, "malformed readint input");
1128 }
1129 p++;
1130 }
1131 return f;
1132}
1133
1134static mrb_int
1135readint_mrb_int(codegen_scope *s, const char *p, int base, mrb_bool neg, mrb_bool *overflow)
1136{
1137 const char *e = p + strlen(p);
1138 mrb_int result = 0;
1139 int n;
1140
1141 mrb_assert(base >= 2 && base <= 36);
1142 if (*p == '+') p++;
1143 while (p < e) {
1144 char c = *p;
1145 c = tolower((unsigned char)c);
1146 for (n=0; n<base; n++) {
1147 if (mrb_digitmap[n] == c) {
1148 break;
1149 }
1150 }
1151 if (n == base) {
1152 codegen_error(s, "malformed readint input");
1153 }
1154
1155 if (neg) {
1156 if ((MRB_INT_MIN + n)/base > result) {
1157 *overflow = TRUE;
1158 return 0;
1159 }
1160 result *= base;
1161 result -= n;
1162 }
1163 else {
1164 if ((MRB_INT_MAX - n)/base < result) {
1165 *overflow = TRUE;
1166 return 0;
1167 }
1168 result *= base;
1169 result += n;
1170 }
1171 p++;
1172 }
1173 *overflow = FALSE;
1174 return result;
1175}
1176
1177static void
1178codegen(codegen_scope *s, node *tree, int val)
1179{
1180 int nt;
1181
1182 if (!tree) return;
1183
1184 if (s->irep && s->filename_index != tree->filename_index) {
1185 s->irep->filename = mrb_parser_get_filename(s->parser, s->filename_index);
1186 mrb_debug_info_append_file(s->mrb, s->irep, s->debug_start_pos, s->pc);
1187 s->debug_start_pos = s->pc;
1188 s->filename_index = tree->filename_index;
1189 s->filename = mrb_parser_get_filename(s->parser, tree->filename_index);
1190 }
1191
1192 nt = (intptr_t)tree->car;
1193 s->lineno = tree->lineno;
1194 tree = tree->cdr;
1195 switch (nt) {
1196 case NODE_BEGIN:
1197 if (val && !tree) {
1198 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1199 push();
1200 }
1201 while (tree) {
1202 codegen(s, tree->car, tree->cdr ? NOVAL : val);
1203 tree = tree->cdr;
1204 }
1205 break;
1206
1207 case NODE_RESCUE:
1208 {
1209 int onerr, noexc, exend, pos1, pos2, tmp;
1210 struct loopinfo *lp;
1211
1212 onerr = genop(s, MKOP_Bx(OP_ONERR, 0));
1213 lp = loop_push(s, LOOP_BEGIN);
1214 lp->pc1 = onerr;
1215 if (tree->car) {
1216 codegen(s, tree->car, val);
1217 if (val) pop();
1218 }
1219 lp->type = LOOP_RESCUE;
1220 noexc = genop(s, MKOP_Bx(OP_JMP, 0));
1221 dispatch(s, onerr);
1222 tree = tree->cdr;
1223 exend = 0;
1224 pos1 = 0;
1225 if (tree->car) {
1226 node *n2 = tree->car;
1227 int exc = cursp();
1228
1229 genop(s, MKOP_A(OP_RESCUE, exc));
1230 push();
1231 while (n2) {
1232 node *n3 = n2->car;
1233 node *n4 = n3->car;
1234
1235 if (pos1) dispatch(s, pos1);
1236 pos2 = 0;
1237 do {
1238 if (n4) {
1239 codegen(s, n4->car, VAL);
1240 }
1241 else {
1242 genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "StandardError"))));
1243 push();
1244 }
1245 genop(s, MKOP_AB(OP_MOVE, cursp(), exc));
1246 pop();
1247 if (n4 && n4->car && (intptr_t)n4->car->car == NODE_SPLAT) {
1248 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1));
1249 }
1250 else {
1251 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "===")), 1));
1252 }
1253 tmp = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2));
1254 pos2 = tmp;
1255 if (n4) {
1256 n4 = n4->cdr;
1257 }
1258 } while (n4);
1259 pos1 = genop(s, MKOP_sBx(OP_JMP, 0));
1260 dispatch_linked(s, pos2);
1261
1262 pop();
1263 if (n3->cdr->car) {
1264 gen_assignment(s, n3->cdr->car, exc, NOVAL);
1265 }
1266 if (n3->cdr->cdr->car) {
1267 codegen(s, n3->cdr->cdr->car, val);
1268 if (val) pop();
1269 }
1270 tmp = genop(s, MKOP_sBx(OP_JMP, exend));
1271 exend = tmp;
1272 n2 = n2->cdr;
1273 push();
1274 }
1275 if (pos1) {
1276 dispatch(s, pos1);
1277 genop(s, MKOP_A(OP_RAISE, exc));
1278 }
1279 }
1280 pop();
1281 tree = tree->cdr;
1282 dispatch(s, noexc);
1283 genop(s, MKOP_A(OP_POPERR, 1));
1284 if (tree->car) {
1285 codegen(s, tree->car, val);
1286 }
1287 else if (val) {
1288 push();
1289 }
1290 dispatch_linked(s, exend);
1291 loop_pop(s, NOVAL);
1292 }
1293 break;
1294
1295 case NODE_ENSURE:
1296 {
1297 int idx;
1298 int epush = s->pc;
1299
1300 genop(s, MKOP_Bx(OP_EPUSH, 0));
1301 s->ensure_level++;
1302 codegen(s, tree->car, val);
1303 idx = scope_body(s, tree->cdr, NOVAL);
1304 s->iseq[epush] = MKOP_Bx(OP_EPUSH, idx);
1305 s->ensure_level--;
1306 genop_peep(s, MKOP_A(OP_EPOP, 1), NOVAL);
1307 }
1308 break;
1309
1310 case NODE_LAMBDA:
1311 {
1312 int idx = lambda_body(s, tree, 1);
1313
1314 genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_LAMBDA));
1315 push();
1316 }
1317 break;
1318
1319 case NODE_BLOCK:
1320 {
1321 int idx = lambda_body(s, tree, 1);
1322
1323 genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_BLOCK));
1324 push();
1325 }
1326 break;
1327
1328 case NODE_IF:
1329 {
1330 int pos1, pos2;
1331 node *e = tree->cdr->cdr->car;
1332
1333 switch ((intptr_t)tree->car->car) {
1334 case NODE_TRUE:
1335 case NODE_INT:
1336 case NODE_STR:
1337 codegen(s, tree->cdr->car, val);
1338 return;
1339 case NODE_FALSE:
1340 case NODE_NIL:
1341 codegen(s, e, val);
1342 return;
1343 }
1344 codegen(s, tree->car, VAL);
1345 pop();
1346 pos1 = genop_peep(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0), NOVAL);
1347
1348 codegen(s, tree->cdr->car, val);
1349 if (val && !(tree->cdr->car)) {
1350 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1351 push();
1352 }
1353 if (e) {
1354 if (val) pop();
1355 pos2 = genop(s, MKOP_sBx(OP_JMP, 0));
1356 dispatch(s, pos1);
1357 codegen(s, e, val);
1358 dispatch(s, pos2);
1359 }
1360 else {
1361 if (val) {
1362 pop();
1363 pos2 = genop(s, MKOP_sBx(OP_JMP, 0));
1364 dispatch(s, pos1);
1365 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1366 dispatch(s, pos2);
1367 push();
1368 }
1369 else {
1370 dispatch(s, pos1);
1371 }
1372 }
1373 }
1374 break;
1375
1376 case NODE_AND:
1377 {
1378 int pos;
1379
1380 codegen(s, tree->car, VAL);
1381 pop();
1382 pos = genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0));
1383 codegen(s, tree->cdr, val);
1384 dispatch(s, pos);
1385 }
1386 break;
1387
1388 case NODE_OR:
1389 {
1390 int pos;
1391
1392 codegen(s, tree->car, VAL);
1393 pop();
1394 pos = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), 0));
1395 codegen(s, tree->cdr, val);
1396 dispatch(s, pos);
1397 }
1398 break;
1399
1400 case NODE_WHILE:
1401 {
1402 struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
1403
1404 lp->pc1 = genop(s, MKOP_sBx(OP_JMP, 0));
1405 lp->pc2 = new_label(s);
1406 codegen(s, tree->cdr, NOVAL);
1407 dispatch(s, lp->pc1);
1408 codegen(s, tree->car, VAL);
1409 pop();
1410 genop(s, MKOP_AsBx(OP_JMPIF, cursp(), lp->pc2 - s->pc));
1411
1412 loop_pop(s, val);
1413 }
1414 break;
1415
1416 case NODE_UNTIL:
1417 {
1418 struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
1419
1420 lp->pc1 = genop(s, MKOP_sBx(OP_JMP, 0));
1421 lp->pc2 = new_label(s);
1422 codegen(s, tree->cdr, NOVAL);
1423 dispatch(s, lp->pc1);
1424 codegen(s, tree->car, VAL);
1425 pop();
1426 genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), lp->pc2 - s->pc));
1427
1428 loop_pop(s, val);
1429 }
1430 break;
1431
1432 case NODE_FOR:
1433 for_body(s, tree);
1434 if (val) push();
1435 break;
1436
1437 case NODE_CASE:
1438 {
1439 int head = 0;
1440 int pos1, pos2, pos3, tmp;
1441 node *n;
1442
1443 pos3 = 0;
1444 if (tree->car) {
1445 head = cursp();
1446 codegen(s, tree->car, VAL);
1447 }
1448 tree = tree->cdr;
1449 while (tree) {
1450 n = tree->car->car;
1451 pos1 = pos2 = 0;
1452 while (n) {
1453 codegen(s, n->car, VAL);
1454 if (head) {
1455 genop(s, MKOP_AB(OP_MOVE, cursp(), head));
1456 pop();
1457 if ((intptr_t)n->car->car == NODE_SPLAT) {
1458 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1));
1459 }
1460 else {
1461 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "===")), 1));
1462 }
1463 }
1464 else {
1465 pop();
1466 }
1467 tmp = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2));
1468 pos2 = tmp;
1469 n = n->cdr;
1470 }
1471 if (tree->car->car) {
1472 pos1 = genop(s, MKOP_sBx(OP_JMP, 0));
1473 dispatch_linked(s, pos2);
1474 }
1475 codegen(s, tree->car->cdr, val);
1476 if (val) pop();
1477 tmp = genop(s, MKOP_sBx(OP_JMP, pos3));
1478 pos3 = tmp;
1479 if (pos1) dispatch(s, pos1);
1480 tree = tree->cdr;
1481 }
1482 if (val) {
1483 int pos = cursp();
1484 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1485 if (pos3) dispatch_linked(s, pos3);
1486 if (head) pop();
1487 genop(s, MKOP_AB(OP_MOVE, cursp(), pos));
1488 push();
1489 }
1490 else {
1491 if (pos3) {
1492 dispatch_linked(s, pos3);
1493 }
1494 if (head) {
1495 pop();
1496 }
1497 }
1498 }
1499 break;
1500
1501 case NODE_SCOPE:
1502 scope_body(s, tree, NOVAL);
1503 break;
1504
1505 case NODE_FCALL:
1506 case NODE_CALL:
1507 gen_call(s, tree, 0, 0, val);
1508 break;
1509
1510 case NODE_DOT2:
1511 codegen(s, tree->car, val);
1512 codegen(s, tree->cdr, val);
1513 if (val) {
1514 pop(); pop();
1515 genop(s, MKOP_ABC(OP_RANGE, cursp(), cursp(), FALSE));
1516 push();
1517 }
1518 break;
1519
1520 case NODE_DOT3:
1521 codegen(s, tree->car, val);
1522 codegen(s, tree->cdr, val);
1523 if (val) {
1524 pop(); pop();
1525 genop(s, MKOP_ABC(OP_RANGE, cursp(), cursp(), TRUE));
1526 push();
1527 }
1528 break;
1529
1530 case NODE_COLON2:
1531 {
1532 int sym = new_sym(s, sym(tree->cdr));
1533
1534 codegen(s, tree->car, VAL);
1535 pop();
1536 genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
1537 if (val) push();
1538 }
1539 break;
1540
1541 case NODE_COLON3:
1542 {
1543 int sym = new_sym(s, sym(tree));
1544
1545 genop(s, MKOP_A(OP_OCLASS, cursp()));
1546 genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
1547 if (val) push();
1548 }
1549 break;
1550
1551 case NODE_ARRAY:
1552 {
1553 int n;
1554
1555 n = gen_values(s, tree, val);
1556 if (n >= 0) {
1557 if (val) {
1558 pop_n(n);
1559 genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), n));
1560 push();
1561 }
1562 }
1563 else if (val) {
1564 push();
1565 }
1566 }
1567 break;
1568
1569 case NODE_HASH:
1570 {
1571 int len = 0;
1572 mrb_bool update = FALSE;
1573
1574 while (tree) {
1575 codegen(s, tree->car->car, val);
1576 codegen(s, tree->car->cdr, val);
1577 len++;
1578 tree = tree->cdr;
1579 if (val && len == 126) {
1580 pop_n(len*2);
1581 genop(s, MKOP_ABC(OP_HASH, cursp(), cursp(), len));
1582 if (update) {
1583 pop();
1584 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__update")), 1));
1585 }
1586 push();
1587 update = TRUE;
1588 len = 0;
1589 }
1590 }
1591 if (val) {
1592 pop_n(len*2);
1593 genop(s, MKOP_ABC(OP_HASH, cursp(), cursp(), len));
1594 if (update) {
1595 pop();
1596 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__update")), 1));
1597 }
1598 push();
1599 }
1600 }
1601 break;
1602
1603 case NODE_SPLAT:
1604 codegen(s, tree, VAL);
1605 break;
1606
1607 case NODE_ASGN:
1608 codegen(s, tree->cdr, VAL);
1609 pop();
1610 gen_assignment(s, tree->car, cursp(), val);
1611 break;
1612
1613 case NODE_MASGN:
1614 {
1615 int len = 0, n = 0, post = 0;
1616 node *t = tree->cdr, *p;
1617 int rhs = cursp();
1618
1619 if ((intptr_t)t->car == NODE_ARRAY && nosplat(t->cdr)) {
1620 /* fixed rhs */
1621 t = t->cdr;
1622 while (t) {
1623 codegen(s, t->car, VAL);
1624 len++;
1625 t = t->cdr;
1626 }
1627 tree = tree->car;
1628 if (tree->car) { /* pre */
1629 t = tree->car;
1630 n = 0;
1631 while (t) {
1632 gen_assignment(s, t->car, rhs+n, NOVAL);
1633 n++;
1634 t = t->cdr;
1635 }
1636 }
1637 t = tree->cdr;
1638 if (t) {
1639 if (t->cdr) { /* post count */
1640 p = t->cdr->car;
1641 while (p) {
1642 post++;
1643 p = p->cdr;
1644 }
1645 }
1646 if (t->car) { /* rest (len - pre - post) */
1647 int rn;
1648
1649 if (len < post + n) {
1650 rn = 0;
1651 }
1652 else {
1653 rn = len - post - n;
1654 }
1655 genop(s, MKOP_ABC(OP_ARRAY, cursp(), rhs+n, rn));
1656 gen_assignment(s, t->car, cursp(), NOVAL);
1657 n += rn;
1658 }
1659 if (t->cdr && t->cdr->car) {
1660 t = t->cdr->car;
1661 while (n<len) {
1662 gen_assignment(s, t->car, rhs+n, NOVAL);
1663 t = t->cdr;
1664 n++;
1665 }
1666 }
1667 }
1668 pop_n(len);
1669 if (val) {
1670 genop(s, MKOP_ABC(OP_ARRAY, rhs, rhs, len));
1671 push();
1672 }
1673 }
1674 else {
1675 /* variable rhs */
1676 codegen(s, t, VAL);
1677 gen_vmassignment(s, tree->car, rhs, val);
1678 if (!val) {
1679 pop();
1680 }
1681 }
1682 }
1683 break;
1684
1685 case NODE_OP_ASGN:
1686 {
1687 mrb_sym sym = sym(tree->cdr->car);
1688 mrb_int len;
1689 const char *name = mrb_sym2name_len(s->mrb, sym, &len);
1690 int idx;
1691
1692 codegen(s, tree->car, VAL);
1693 if (len == 2 &&
1694 ((name[0] == '|' && name[1] == '|') ||
1695 (name[0] == '&' && name[1] == '&'))) {
1696 int pos;
1697
1698 pop();
1699 pos = genop_peep(s, MKOP_AsBx(name[0] == '|' ? OP_JMPIF : OP_JMPNOT, cursp(), 0), NOVAL);
1700 codegen(s, tree->cdr->cdr->car, VAL);
1701 pop();
1702 gen_assignment(s, tree->car, cursp(), val);
1703 dispatch(s, pos);
1704 break;
1705 }
1706 codegen(s, tree->cdr->cdr->car, VAL);
1707 push(); pop();
1708 pop(); pop();
1709
1710 idx = new_msym(s, sym);
1711 if (len == 1 && name[0] == '+') {
1712 genop_peep(s, MKOP_ABC(OP_ADD, cursp(), idx, 1), val);
1713 }
1714 else if (len == 1 && name[0] == '-') {
1715 genop_peep(s, MKOP_ABC(OP_SUB, cursp(), idx, 1), val);
1716 }
1717 else if (len == 1 && name[0] == '*') {
1718 genop(s, MKOP_ABC(OP_MUL, cursp(), idx, 1));
1719 }
1720 else if (len == 1 && name[0] == '/') {
1721 genop(s, MKOP_ABC(OP_DIV, cursp(), idx, 1));
1722 }
1723 else if (len == 1 && name[0] == '<') {
1724 genop(s, MKOP_ABC(OP_LT, cursp(), idx, 1));
1725 }
1726 else if (len == 2 && name[0] == '<' && name[1] == '=') {
1727 genop(s, MKOP_ABC(OP_LE, cursp(), idx, 1));
1728 }
1729 else if (len == 1 && name[0] == '>') {
1730 genop(s, MKOP_ABC(OP_GT, cursp(), idx, 1));
1731 }
1732 else if (len == 2 && name[0] == '>' && name[1] == '=') {
1733 genop(s, MKOP_ABC(OP_GE, cursp(), idx, 1));
1734 }
1735 else {
1736 genop(s, MKOP_ABC(OP_SEND, cursp(), idx, 1));
1737 }
1738 }
1739 gen_assignment(s, tree->car, cursp(), val);
1740 break;
1741
1742 case NODE_SUPER:
1743 {
1744 int n = 0, noop = 0, sendv = 0;
1745
1746 push(); /* room for receiver */
1747 if (tree) {
1748 node *args = tree->car;
1749 if (args) {
1750 n = gen_values(s, args, VAL);
1751 if (n < 0) {
1752 n = noop = sendv = 1;
1753 push();
1754 }
1755 }
1756 }
1757 if (tree && tree->cdr) {
1758 codegen(s, tree->cdr, VAL);
1759 pop();
1760 }
1761 else {
1762 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1763 push(); pop();
1764 }
1765 pop_n(n+1);
1766 if (sendv) n = CALL_MAXARGS;
1767 genop(s, MKOP_ABC(OP_SUPER, cursp(), 0, n));
1768 if (val) push();
1769 }
1770 break;
1771
1772 case NODE_ZSUPER:
1773 {
1774 codegen_scope *s2 = s;
1775 int lv = 0, ainfo = 0;
1776
1777 push(); /* room for receiver */
1778 while (!s2->mscope) {
1779 lv++;
1780 s2 = s2->prev;
1781 if (!s2) break;
1782 }
1783 if (s2) ainfo = s2->ainfo;
1784 genop(s, MKOP_ABx(OP_ARGARY, cursp(), (ainfo<<4)|(lv & 0xf)));
1785 push(); push(); pop(); /* ARGARY pushes two values */
1786 if (tree && tree->cdr) {
1787 codegen(s, tree->cdr, VAL);
1788 pop();
1789 }
1790 pop(); pop();
1791 genop(s, MKOP_ABC(OP_SUPER, cursp(), 0, CALL_MAXARGS));
1792 if (val) push();
1793 }
1794 break;
1795
1796 case NODE_RETURN:
1797 if (tree) {
1798 codegen(s, tree, VAL);
1799 pop();
1800 }
1801 else {
1802 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1803 }
1804 if (s->loop) {
1805 genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_RETURN));
1806 }
1807 else {
1808 genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
1809 }
1810 if (val) push();
1811 break;
1812
1813 case NODE_YIELD:
1814 {
1815 codegen_scope *s2 = s;
1816 int lv = 0, ainfo = 0;
1817 int n = 0, sendv = 0;
1818
1819 while (!s2->mscope) {
1820 lv++;
1821 s2 = s2->prev;
1822 if (!s2) break;
1823 }
1824 if (s2) ainfo = s2->ainfo;
1825 genop(s, MKOP_ABx(OP_BLKPUSH, cursp(), (ainfo<<4)|(lv & 0xf)));
1826 push();
1827 if (tree) {
1828 n = gen_values(s, tree, VAL);
1829 if (n < 0) {
1830 n = sendv = 1;
1831 push();
1832 }
1833 }
1834 pop_n(n+1);
1835 if (sendv) n = CALL_MAXARGS;
1836 genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "call")), n));
1837 if (val) push();
1838 }
1839 break;
1840
1841 case NODE_BREAK:
1842 loop_break(s, tree);
1843 if (val) push();
1844 break;
1845
1846 case NODE_NEXT:
1847 if (!s->loop) {
1848 raise_error(s, "unexpected next");
1849 }
1850 else if (s->loop->type == LOOP_NORMAL) {
1851 if (s->ensure_level > s->loop->ensure_level) {
1852 genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL);
1853 }
1854 codegen(s, tree, NOVAL);
1855 genop(s, MKOP_sBx(OP_JMP, s->loop->pc1 - s->pc));
1856 }
1857 else {
1858 if (tree) {
1859 codegen(s, tree, VAL);
1860 pop();
1861 }
1862 else {
1863 genop(s, MKOP_A(OP_LOADNIL, cursp()));
1864 }
1865 genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
1866 }
1867 if (val) push();
1868 break;
1869
1870 case NODE_REDO:
1871 if (!s->loop) {
1872 raise_error(s, "unexpected redo");
1873 }
1874 else {
1875 if (s->ensure_level > s->loop->ensure_level) {
1876 genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL);
1877 }
1878 genop(s, MKOP_sBx(OP_JMP, s->loop->pc2 - s->pc));
1879 }
1880 break;
1881
1882 case NODE_RETRY:
1883 {
1884 const char *msg = "unexpected retry";
1885
1886 if (!s->loop) {
1887 raise_error(s, msg);
1888 }
1889 else {
1890 struct loopinfo *lp = s->loop;
1891 int n = 0;
1892
1893 while (lp && lp->type != LOOP_RESCUE) {
1894 if (lp->type == LOOP_BEGIN) {
1895 n++;
1896 }
1897 lp = lp->prev;
1898 }
1899 if (!lp) {
1900 raise_error(s, msg);
1901 }
1902 else {
1903 if (n > 0) {
1904 while (n--) {
1905 genop_peep(s, MKOP_A(OP_POPERR, 1), NOVAL);
1906 }
1907 }
1908 if (s->ensure_level > lp->ensure_level) {
1909 genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - lp->ensure_level), NOVAL);
1910 }
1911 genop(s, MKOP_sBx(OP_JMP, lp->pc1 - s->pc));
1912 }
1913 }
1914 }
1915 break;
1916
1917 case NODE_LVAR:
1918 if (val) {
1919 int idx = lv_idx(s, sym(tree));
1920
1921 if (idx > 0) {
1922 genop_peep(s, MKOP_AB(OP_MOVE, cursp(), idx), NOVAL);
1923 }
1924 else {
1925 int lv = 0;
1926 codegen_scope *up = s->prev;
1927
1928 while (up) {
1929 idx = lv_idx(up, sym(tree));
1930 if (idx > 0) {
1931 genop(s, MKOP_ABC(OP_GETUPVAR, cursp(), idx, lv));
1932 break;
1933 }
1934 lv++;
1935 up = up->prev;
1936 }
1937 }
1938 push();
1939 }
1940 break;
1941
1942 case NODE_GVAR:
1943 if (val) {
1944 int sym = new_sym(s, sym(tree));
1945
1946 genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
1947 push();
1948 }
1949 break;
1950
1951 case NODE_IVAR:
1952 if (val) {
1953 int sym = new_sym(s, sym(tree));
1954
1955 genop(s, MKOP_ABx(OP_GETIV, cursp(), sym));
1956 push();
1957 }
1958 break;
1959
1960 case NODE_CVAR:
1961 if (val) {
1962 int sym = new_sym(s, sym(tree));
1963
1964 genop(s, MKOP_ABx(OP_GETCV, cursp(), sym));
1965 push();
1966 }
1967 break;
1968
1969 case NODE_CONST:
1970 {
1971 int sym = new_sym(s, sym(tree));
1972
1973 genop(s, MKOP_ABx(OP_GETCONST, cursp(), sym));
1974 if (val) {
1975 push();
1976 }
1977 }
1978 break;
1979
1980 case NODE_DEFINED:
1981 codegen(s, tree, VAL);
1982 break;
1983
1984 case NODE_BACK_REF:
1985 if (val) {
1986 char buf[2] = { '$' };
1987 mrb_value str;
1988 int sym;
1989
1990 buf[1] = (char)(intptr_t)tree;
1991 str = mrb_str_new(s->mrb, buf, 2);
1992 sym = new_sym(s, mrb_intern_str(s->mrb, str));
1993 genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
1994 push();
1995 }
1996 break;
1997
1998 case NODE_NTH_REF:
1999 if (val) {
2000 int sym;
2001 mrb_state *mrb = s->mrb;
2002 mrb_value fix = mrb_fixnum_value((intptr_t)tree);
2003 mrb_value str = mrb_str_buf_new(mrb, 4);
2004
2005 mrb_str_cat_lit(mrb, str, "$");
2006 mrb_str_cat_str(mrb, str, mrb_fixnum_to_str(mrb, fix, 10));
2007 sym = new_sym(s, mrb_intern_str(mrb, str));
2008 genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
2009 push();
2010 }
2011 break;
2012
2013 case NODE_ARG:
2014 /* should not happen */
2015 break;
2016
2017 case NODE_BLOCK_ARG:
2018 codegen(s, tree, VAL);
2019 break;
2020
2021 case NODE_INT:
2022 if (val) {
2023 char *p = (char*)tree->car;
2024 int base = (intptr_t)tree->cdr->car;
2025 mrb_int i;
2026 mrb_code co;
2027 mrb_bool overflow;
2028
2029 i = readint_mrb_int(s, p, base, FALSE, &overflow);
2030 if (overflow) {
2031 double f = readint_float(s, p, base);
2032 int off = new_lit(s, mrb_float_value(s->mrb, f));
2033
2034 genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
2035 }
2036 else {
2037 if (i < MAXARG_sBx && i > -MAXARG_sBx) {
2038 co = MKOP_AsBx(OP_LOADI, cursp(), i);
2039 }
2040 else {
2041 int off = new_lit(s, mrb_fixnum_value(i));
2042 co = MKOP_ABx(OP_LOADL, cursp(), off);
2043 }
2044 genop(s, co);
2045 }
2046 push();
2047 }
2048 break;
2049
2050 case NODE_FLOAT:
2051 if (val) {
2052 char *p = (char*)tree;
2053 mrb_float f = str_to_mrb_float(p);
2054 int off = new_lit(s, mrb_float_value(s->mrb, f));
2055
2056 genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
2057 push();
2058 }
2059 break;
2060
2061 case NODE_NEGATE:
2062 {
2063 nt = (intptr_t)tree->car;
2064 tree = tree->cdr;
2065 switch (nt) {
2066 case NODE_FLOAT:
2067 {
2068 char *p = (char*)tree;
2069 mrb_float f = str_to_mrb_float(p);
2070 int off = new_lit(s, mrb_float_value(s->mrb, -f));
2071
2072 genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
2073 push();
2074 }
2075 break;
2076
2077 case NODE_INT:
2078 {
2079 char *p = (char*)tree->car;
2080 int base = (intptr_t)tree->cdr->car;
2081 mrb_int i;
2082 mrb_code co;
2083 mrb_bool overflow;
2084
2085 i = readint_mrb_int(s, p, base, TRUE, &overflow);
2086 if (overflow) {
2087 double f = readint_float(s, p, base);
2088 int off = new_lit(s, mrb_float_value(s->mrb, -f));
2089
2090 genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
2091 }
2092 else {
2093 if (i < MAXARG_sBx && i > -MAXARG_sBx) {
2094 co = MKOP_AsBx(OP_LOADI, cursp(), i);
2095 }
2096 else {
2097 int off = new_lit(s, mrb_fixnum_value(i));
2098 co = MKOP_ABx(OP_LOADL, cursp(), off);
2099 }
2100 genop(s, co);
2101 }
2102 push();
2103 }
2104 break;
2105
2106 default:
2107 {
2108 int sym = new_msym(s, mrb_intern_lit(s->mrb, "-"));
2109
2110 genop(s, MKOP_ABx(OP_LOADI, cursp(), 0));
2111 push();
2112 codegen(s, tree, VAL);
2113 pop(); pop();
2114 genop(s, MKOP_ABC(OP_SUB, cursp(), sym, 2));
2115 }
2116 break;
2117 }
2118 }
2119 break;
2120
2121 case NODE_STR:
2122 if (val) {
2123 char *p = (char*)tree->car;
2124 size_t len = (intptr_t)tree->cdr;
2125 int ai = mrb_gc_arena_save(s->mrb);
2126 int off = new_lit(s, mrb_str_new(s->mrb, p, len));
2127
2128 mrb_gc_arena_restore(s->mrb, ai);
2129 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2130 push();
2131 }
2132 break;
2133
2134 case NODE_HEREDOC:
2135 tree = ((struct mrb_parser_heredoc_info *)tree)->doc;
2136 /* fall through */
2137 case NODE_DSTR:
2138 if (val) {
2139 node *n = tree;
2140
2141 if (!n) break;
2142 codegen(s, n->car, VAL);
2143 n = n->cdr;
2144 while (n) {
2145 codegen(s, n->car, VAL);
2146 pop(); pop();
2147 genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
2148 push();
2149 n = n->cdr;
2150 }
2151 }
2152 else {
2153 node *n = tree;
2154
2155 while (n) {
2156 if ((intptr_t)n->car->car != NODE_STR) {
2157 codegen(s, n->car, NOVAL);
2158 }
2159 n = n->cdr;
2160 }
2161 }
2162 break;
2163
2164 case NODE_WORDS:
2165 gen_literal_array(s, tree, FALSE, val);
2166 break;
2167
2168 case NODE_SYMBOLS:
2169 gen_literal_array(s, tree, TRUE, val);
2170 break;
2171
2172 case NODE_DXSTR:
2173 {
2174 node *n;
2175 int ai = mrb_gc_arena_save(s->mrb);
2176 int sym = new_sym(s, mrb_intern_lit(s->mrb, "Kernel"));
2177
2178 if (val == NOVAL) { push(); }
2179 genop(s, MKOP_A(OP_OCLASS, cursp()));
2180 genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
2181 push();
2182 codegen(s, tree->car, VAL);
2183 n = tree->cdr;
2184 while (n) {
2185 if ((intptr_t)n->car->car == NODE_XSTR) {
2186 n->car->car = (struct mrb_ast_node*)(intptr_t)NODE_STR;
2187 mrb_assert(!n->cdr); /* must be the end */
2188 }
2189 codegen(s, n->car, VAL);
2190 pop(); pop();
2191 genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
2192 push();
2193 n = n->cdr;
2194 }
2195 pop();
2196 pop();
2197 sym = new_sym(s, mrb_intern_lit(s->mrb, "`"));
2198 genop(s, MKOP_ABC(OP_SEND, cursp(), sym, 1));
2199 if (val == NOVAL) { pop(); }
2200 else { push(); }
2201 mrb_gc_arena_restore(s->mrb, ai);
2202 }
2203 break;
2204
2205 case NODE_XSTR:
2206 {
2207 char *p = (char*)tree->car;
2208 size_t len = (intptr_t)tree->cdr;
2209 int ai = mrb_gc_arena_save(s->mrb);
2210 int sym = new_sym(s, mrb_intern_lit(s->mrb, "Kernel"));
2211 int off = new_lit(s, mrb_str_new(s->mrb, p, len));
2212
2213 if (val == NOVAL) { push(); }
2214 genop(s, MKOP_A(OP_OCLASS, cursp()));
2215 genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
2216 push();
2217 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2218 pop();
2219 sym = new_sym(s, mrb_intern_lit(s->mrb, "`"));
2220 genop(s, MKOP_ABC(OP_SEND, cursp(), sym, 1));
2221 if (val == NOVAL) { pop(); }
2222 else { push(); }
2223 mrb_gc_arena_restore(s->mrb, ai);
2224 }
2225 break;
2226
2227 case NODE_REGX:
2228 if (val) {
2229 char *p1 = (char*)tree->car;
2230 char *p2 = (char*)tree->cdr->car;
2231 char *p3 = (char*)tree->cdr->cdr;
2232 int ai = mrb_gc_arena_save(s->mrb);
2233 int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS));
2234 int off = new_lit(s, mrb_str_new_cstr(s->mrb, p1));
2235 int argc = 1;
2236
2237 genop(s, MKOP_A(OP_OCLASS, cursp()));
2238 genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
2239 push();
2240 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2241 if (p2 || p3) {
2242 push();
2243 if (p2) {
2244 off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
2245 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2246 } else {
2247 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2248 }
2249 argc++;
2250 if (p3) {
2251 push();
2252 off = new_lit(s, mrb_str_new(s->mrb, p3, 1));
2253 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2254 argc++;
2255 pop();
2256 }
2257 pop();
2258 }
2259 pop();
2260 sym = new_sym(s, mrb_intern_lit(s->mrb, "compile"));
2261 genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc));
2262 mrb_gc_arena_restore(s->mrb, ai);
2263 push();
2264 }
2265 break;
2266
2267 case NODE_DREGX:
2268 if (val) {
2269 node *n = tree->car;
2270 int ai = mrb_gc_arena_save(s->mrb);
2271 int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS));
2272 int argc = 1;
2273 int off;
2274 char *p;
2275
2276 genop(s, MKOP_A(OP_OCLASS, cursp()));
2277 genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
2278 push();
2279 codegen(s, n->car, VAL);
2280 n = n->cdr;
2281 while (n) {
2282 codegen(s, n->car, VAL);
2283 pop(); pop();
2284 genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
2285 push();
2286 n = n->cdr;
2287 }
2288 n = tree->cdr->cdr;
2289 if (n->car) {
2290 p = (char*)n->car;
2291 off = new_lit(s, mrb_str_new_cstr(s->mrb, p));
2292 codegen(s, tree->car, VAL);
2293 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2294 pop();
2295 genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
2296 }
2297 if (n->cdr) {
2298 char *p2 = (char*)n->cdr;
2299
2300 push();
2301 off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
2302 genop(s, MKOP_ABx(OP_STRING, cursp(), off));
2303 argc++;
2304 pop();
2305 }
2306 pop();
2307 sym = new_sym(s, mrb_intern_lit(s->mrb, "compile"));
2308 genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc));
2309 mrb_gc_arena_restore(s->mrb, ai);
2310 push();
2311 }
2312 else {
2313 node *n = tree->car;
2314
2315 while (n) {
2316 if ((intptr_t)n->car->car != NODE_STR) {
2317 codegen(s, n->car, NOVAL);
2318 }
2319 n = n->cdr;
2320 }
2321 }
2322 break;
2323
2324 case NODE_SYM:
2325 if (val) {
2326 int sym = new_sym(s, sym(tree));
2327
2328 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym));
2329 push();
2330 }
2331 break;
2332
2333 case NODE_DSYM:
2334 codegen(s, tree, val);
2335 if (val) {
2336 gen_send_intern(s);
2337 }
2338 break;
2339
2340 case NODE_SELF:
2341 if (val) {
2342 genop(s, MKOP_A(OP_LOADSELF, cursp()));
2343 push();
2344 }
2345 break;
2346
2347 case NODE_NIL:
2348 if (val) {
2349 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2350 push();
2351 }
2352 break;
2353
2354 case NODE_TRUE:
2355 if (val) {
2356 genop(s, MKOP_A(OP_LOADT, cursp()));
2357 push();
2358 }
2359 break;
2360
2361 case NODE_FALSE:
2362 if (val) {
2363 genop(s, MKOP_A(OP_LOADF, cursp()));
2364 push();
2365 }
2366 break;
2367
2368 case NODE_ALIAS:
2369 {
2370 int a = new_msym(s, sym(tree->car));
2371 int b = new_msym(s, sym(tree->cdr));
2372 int c = new_msym(s, mrb_intern_lit(s->mrb, "alias_method"));
2373
2374 genop(s, MKOP_A(OP_TCLASS, cursp()));
2375 push();
2376 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), a));
2377 push();
2378 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), b));
2379 push();
2380 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2381 pop_n(3);
2382 genop(s, MKOP_ABC(OP_SEND, cursp(), c, 2));
2383 if (val) {
2384 push();
2385 }
2386 }
2387 break;
2388
2389 case NODE_UNDEF:
2390 {
2391 int undef = new_msym(s, mrb_intern_lit(s->mrb, "undef_method"));
2392 int num = 0;
2393 node *t = tree;
2394
2395 genop(s, MKOP_A(OP_TCLASS, cursp()));
2396 push();
2397 while (t) {
2398 int symbol = new_msym(s, sym(t->car));
2399 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), symbol));
2400 push();
2401 t = t->cdr;
2402 num++;
2403 }
2404 pop_n(num + 1);
2405 genop(s, MKOP_ABC(OP_SEND, cursp(), undef, num));
2406 if (val) {
2407 push();
2408 }
2409 }
2410 break;
2411
2412 case NODE_CLASS:
2413 {
2414 int idx;
2415
2416 if (tree->car->car == (node*)0) {
2417 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2418 push();
2419 }
2420 else if (tree->car->car == (node*)1) {
2421 genop(s, MKOP_A(OP_OCLASS, cursp()));
2422 push();
2423 }
2424 else {
2425 codegen(s, tree->car->car, VAL);
2426 }
2427 if (tree->cdr->car) {
2428 codegen(s, tree->cdr->car, VAL);
2429 }
2430 else {
2431 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2432 push();
2433 }
2434 pop(); pop();
2435 idx = new_msym(s, sym(tree->car->cdr));
2436 genop(s, MKOP_AB(OP_CLASS, cursp(), idx));
2437 idx = scope_body(s, tree->cdr->cdr->car, val);
2438 genop(s, MKOP_ABx(OP_EXEC, cursp(), idx));
2439 if (val) {
2440 push();
2441 }
2442 }
2443 break;
2444
2445 case NODE_MODULE:
2446 {
2447 int idx;
2448
2449 if (tree->car->car == (node*)0) {
2450 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2451 push();
2452 }
2453 else if (tree->car->car == (node*)1) {
2454 genop(s, MKOP_A(OP_OCLASS, cursp()));
2455 push();
2456 }
2457 else {
2458 codegen(s, tree->car->car, VAL);
2459 }
2460 pop();
2461 idx = new_msym(s, sym(tree->car->cdr));
2462 genop(s, MKOP_AB(OP_MODULE, cursp(), idx));
2463 idx = scope_body(s, tree->cdr->car, val);
2464 genop(s, MKOP_ABx(OP_EXEC, cursp(), idx));
2465 if (val) {
2466 push();
2467 }
2468 }
2469 break;
2470
2471 case NODE_SCLASS:
2472 {
2473 int idx;
2474
2475 codegen(s, tree->car, VAL);
2476 pop();
2477 genop(s, MKOP_AB(OP_SCLASS, cursp(), cursp()));
2478 idx = scope_body(s, tree->cdr->car, val);
2479 genop(s, MKOP_ABx(OP_EXEC, cursp(), idx));
2480 if (val) {
2481 push();
2482 }
2483 }
2484 break;
2485
2486 case NODE_DEF:
2487 {
2488 int sym = new_msym(s, sym(tree->car));
2489 int idx = lambda_body(s, tree->cdr, 0);
2490
2491 genop(s, MKOP_A(OP_TCLASS, cursp()));
2492 push();
2493 genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_METHOD));
2494 push(); pop();
2495 pop();
2496 genop(s, MKOP_AB(OP_METHOD, cursp(), sym));
2497 if (val) {
2498 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym));
2499 push();
2500 }
2501 }
2502 break;
2503
2504 case NODE_SDEF:
2505 {
2506 node *recv = tree->car;
2507 int sym = new_msym(s, sym(tree->cdr->car));
2508 int idx = lambda_body(s, tree->cdr->cdr, 0);
2509
2510 codegen(s, recv, VAL);
2511 pop();
2512 genop(s, MKOP_AB(OP_SCLASS, cursp(), cursp()));
2513 push();
2514 genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_METHOD));
2515 pop();
2516 genop(s, MKOP_AB(OP_METHOD, cursp(), sym));
2517 if (val) {
2518 genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym));
2519 push();
2520 }
2521 }
2522 break;
2523
2524 case NODE_POSTEXE:
2525 codegen(s, tree, NOVAL);
2526 break;
2527
2528 default:
2529 break;
2530 }
2531}
2532
2533static void
2534scope_add_irep(codegen_scope *s, mrb_irep *irep)
2535{
2536 if (s->irep == NULL) {
2537 s->irep = irep;
2538 return;
2539 }
2540 if (s->irep->rlen == s->rcapa) {
2541 s->rcapa *= 2;
2542 s->irep->reps = (mrb_irep**)codegen_realloc(s, s->irep->reps, sizeof(mrb_irep*)*s->rcapa);
2543 }
2544 s->irep->reps[s->irep->rlen] = irep;
2545 s->irep->rlen++;
2546}
2547
2548static codegen_scope*
2549scope_new(mrb_state *mrb, codegen_scope *prev, node *lv)
2550{
2551 static const codegen_scope codegen_scope_zero = { 0 };
2552 mrb_pool *pool = mrb_pool_open(mrb);
2553 codegen_scope *p = (codegen_scope *)mrb_pool_alloc(pool, sizeof(codegen_scope));
2554
2555 if (!p) return NULL;
2556 *p = codegen_scope_zero;
2557 p->mrb = mrb;
2558 p->mpool = pool;
2559 if (!prev) return p;
2560 p->prev = prev;
2561 p->ainfo = -1;
2562 p->mscope = 0;
2563
2564 p->irep = mrb_add_irep(mrb);
2565 scope_add_irep(prev, p->irep);
2566
2567 p->rcapa = 8;
2568 p->irep->reps = (mrb_irep**)mrb_malloc(mrb, sizeof(mrb_irep*)*p->rcapa);
2569
2570 p->icapa = 1024;
2571 p->iseq = (mrb_code*)mrb_malloc(mrb, sizeof(mrb_code)*p->icapa);
2572 p->irep->iseq = p->iseq;
2573
2574 p->pcapa = 32;
2575 p->irep->pool = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value)*p->pcapa);
2576 p->irep->plen = 0;
2577
2578 p->scapa = 256;
2579 p->irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*p->scapa);
2580 p->irep->slen = 0;
2581
2582 p->lv = lv;
2583 p->sp += node_len(lv)+1; /* add self */
2584 p->nlocals = p->sp;
2585 if (lv) {
2586 node *n = lv;
2587 size_t i = 0;
2588
2589 p->irep->lv = (struct mrb_locals*)mrb_malloc(mrb, sizeof(struct mrb_locals) * (p->nlocals - 1));
2590 for (i=0, n=lv; n; i++,n=n->cdr) {
2591 p->irep->lv[i].name = lv_name(n);
2592 if (lv_name(n)) {
2593 p->irep->lv[i].r = lv_idx(p, lv_name(n));
2594 }
2595 else {
2596 p->irep->lv[i].r = 0;
2597 }
2598 }
2599 mrb_assert(i + 1 == p->nlocals);
2600 }
2601 p->ai = mrb_gc_arena_save(mrb);
2602
2603 p->filename = prev->filename;
2604 if (p->filename) {
2605 p->lines = (uint16_t*)mrb_malloc(mrb, sizeof(short)*p->icapa);
2606 }
2607 p->lineno = prev->lineno;
2608
2609 /* debug setting */
2610 p->debug_start_pos = 0;
2611 if (p->filename) {
2612 mrb_debug_info_alloc(mrb, p->irep);
2613 p->irep->filename = p->filename;
2614 p->irep->lines = p->lines;
2615 }
2616 else {
2617 p->irep->debug_info = NULL;
2618 }
2619 p->parser = prev->parser;
2620 p->filename_index = prev->filename_index;
2621
2622 return p;
2623}
2624
2625static void
2626scope_finish(codegen_scope *s)
2627{
2628 mrb_state *mrb = s->mrb;
2629 mrb_irep *irep = s->irep;
2630 size_t fname_len;
2631 char *fname;
2632
2633 irep->flags = 0;
2634 if (s->iseq) {
2635 irep->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc);
2636 irep->ilen = s->pc;
2637 if (s->lines) {
2638 irep->lines = (uint16_t *)codegen_realloc(s, s->lines, sizeof(uint16_t)*s->pc);
2639 }
2640 else {
2641 irep->lines = 0;
2642 }
2643 }
2644 irep->pool = (mrb_value*)codegen_realloc(s, irep->pool, sizeof(mrb_value)*irep->plen);
2645 irep->syms = (mrb_sym*)codegen_realloc(s, irep->syms, sizeof(mrb_sym)*irep->slen);
2646 irep->reps = (mrb_irep**)codegen_realloc(s, irep->reps, sizeof(mrb_irep*)*irep->rlen);
2647 if (s->filename) {
2648 s->irep->filename = mrb_parser_get_filename(s->parser, s->filename_index);
2649 mrb_debug_info_append_file(mrb, s->irep, s->debug_start_pos, s->pc);
2650
2651 fname_len = strlen(s->filename);
2652 fname = (char*)codegen_malloc(s, fname_len + 1);
2653 memcpy(fname, s->filename, fname_len);
2654 fname[fname_len] = '\0';
2655 irep->filename = fname;
2656 }
2657
2658 irep->nlocals = s->nlocals;
2659 irep->nregs = s->nregs;
2660
2661 mrb_gc_arena_restore(mrb, s->ai);
2662 mrb_pool_close(s->mpool);
2663}
2664
2665static struct loopinfo*
2666loop_push(codegen_scope *s, enum looptype t)
2667{
2668 struct loopinfo *p = (struct loopinfo *)codegen_palloc(s, sizeof(struct loopinfo));
2669
2670 p->type = t;
2671 p->pc1 = p->pc2 = p->pc3 = 0;
2672 p->prev = s->loop;
2673 p->ensure_level = s->ensure_level;
2674 p->acc = cursp();
2675 s->loop = p;
2676
2677 return p;
2678}
2679
2680static void
2681loop_break(codegen_scope *s, node *tree)
2682{
2683 if (!s->loop) {
2684 codegen(s, tree, NOVAL);
2685 raise_error(s, "unexpected break");
2686 }
2687 else {
2688 struct loopinfo *loop;
2689
2690 if (tree) {
2691 codegen(s, tree, VAL);
2692 pop();
2693 }
2694
2695 loop = s->loop;
2696 while (loop && loop->type == LOOP_BEGIN) {
2697 genop_peep(s, MKOP_A(OP_POPERR, 1), NOVAL);
2698 loop = loop->prev;
2699 }
2700 while (loop && loop->type == LOOP_RESCUE) {
2701 loop = loop->prev;
2702 }
2703 if (!loop) {
2704 codegen_error(s, "unexpected break");
2705 }
2706
2707 if (loop->type == LOOP_NORMAL) {
2708 int tmp;
2709
2710 if (s->ensure_level > s->loop->ensure_level) {
2711 genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL);
2712 }
2713 if (tree) {
2714 genop_peep(s, MKOP_AB(OP_MOVE, loop->acc, cursp()), NOVAL);
2715 }
2716 tmp = genop(s, MKOP_sBx(OP_JMP, loop->pc3));
2717 loop->pc3 = tmp;
2718 }
2719 else {
2720 genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_BREAK));
2721 }
2722 }
2723}
2724
2725static void
2726loop_pop(codegen_scope *s, int val)
2727{
2728 if (val) {
2729 genop(s, MKOP_A(OP_LOADNIL, cursp()));
2730 }
2731 dispatch_linked(s, s->loop->pc3);
2732 s->loop = s->loop->prev;
2733 if (val) push();
2734}
2735
2736MRB_API struct RProc*
2737mrb_generate_code(mrb_state *mrb, parser_state *p)
2738{
2739 codegen_scope *scope = scope_new(mrb, 0, 0);
2740 struct RProc *proc;
2741
2742 if (!scope) {
2743 return NULL;
2744 }
2745 scope->mrb = mrb;
2746 scope->parser = p;
2747 scope->filename = p->filename;
2748 scope->filename_index = p->current_filename_index;
2749
2750 MRB_TRY(&scope->jmp) {
2751 /* prepare irep */
2752 codegen(scope, p->tree, NOVAL);
2753 proc = mrb_proc_new(mrb, scope->irep);
2754 mrb_irep_decref(mrb, scope->irep);
2755 mrb_pool_close(scope->mpool);
2756 return proc;
2757 }
2758 MRB_CATCH(&scope->jmp) {
2759 if (scope->filename == scope->irep->filename) {
2760 scope->irep->filename = NULL;
2761 }
2762 mrb_irep_decref(mrb, scope->irep);
2763 mrb_pool_close(scope->mpool);
2764 return NULL;
2765 }
2766 MRB_END_EXC(&scope->jmp);
2767}
Note: See TracBrowser for help on using the repository browser.