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