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