mbed I/F binding for mruby

Dependents:   mruby_mbed_web mirb_mbed

mbed-mruby

How to use

Class

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?

UserRevisionLine numberNew 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