source: EcnlProtoTool/trunk/mruby-1.3.0/mrbgems/mruby-compiler/core/codegen.c@ 331

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

prototoolに関連するプロジェクトをnewlibからmuslを使うよう変更・更新
ntshellをnewlibの下位の実装から、muslのsyscallの実装に変更・更新
以下のOSSをアップデート
・mruby-1.3.0
・musl-1.1.18
・onigmo-6.1.3
・tcc-0.9.27
以下のOSSを追加
・openssl-1.1.0e
・curl-7.57.0
・zlib-1.2.11
以下のmrbgemsを追加
・iij/mruby-digest
・iij/mruby-env
・iij/mruby-errno
・iij/mruby-iijson
・iij/mruby-ipaddr
・iij/mruby-mock
・iij/mruby-require
・iij/mruby-tls-openssl

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