summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/mruby-compiler
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2019-07-17 10:35:41 +0900
committerGitHub <[email protected]>2019-07-17 10:35:41 +0900
commitd605b72c1d6fa4564a0a5e88535504b6850463b5 (patch)
tree774fc0de56002abb3bb2b1c3387ff08f91876d17 /mrbgems/mruby-compiler
parent2af92d0ebcbeca6d3d85a27c8193273080a63090 (diff)
parent9af3b7c6258de327218dd04e69d76ae68caf17b1 (diff)
downloadmruby-d605b72c1d6fa4564a0a5e88535504b6850463b5.tar.gz
mruby-d605b72c1d6fa4564a0a5e88535504b6850463b5.zip
Merge branch 'master' into i110/inspect-recursion
Diffstat (limited to 'mrbgems/mruby-compiler')
-rw-r--r--mrbgems/mruby-compiler/core/codegen.c1657
-rw-r--r--mrbgems/mruby-compiler/core/node.h24
-rw-r--r--mrbgems/mruby-compiler/core/parse.y1103
-rw-r--r--mrbgems/mruby-compiler/mrbgem.rake6
4 files changed, 1692 insertions, 1098 deletions
diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c
index f71de9b4b..ed8fc3150 100644
--- a/mrbgems/mruby-compiler/core/codegen.c
+++ b/mrbgems/mruby-compiler/core/codegen.c
@@ -8,6 +8,7 @@
#include <limits.h>
#include <stdlib.h>
#include <string.h>
+#include <math.h>
#include <mruby.h>
#include <mruby/compile.h>
#include <mruby/proc.h>
@@ -23,6 +24,8 @@
#define MRB_CODEGEN_LEVEL_MAX 1024
#endif
+#define MAXARG_S (1<<16)
+
typedef mrb_ast_node node;
typedef struct mrb_parser_state parser_state;
@@ -36,7 +39,7 @@ enum looptype {
struct loopinfo {
enum looptype type;
- int pc1, pc2, pc3, acc;
+ int pc0, pc1, pc2, pc3, acc;
int ensure_level;
struct loopinfo *prev;
};
@@ -50,23 +53,24 @@ typedef struct scope {
node *lv;
- int sp;
- int pc;
- int lastlabel;
+ uint16_t sp;
+ uint16_t pc;
+ uint16_t lastpc;
+ uint16_t lastlabel;
int ainfo:15;
mrb_bool mscope:1;
struct loopinfo *loop;
int ensure_level;
- char const *filename;
+ mrb_sym filename_sym;
uint16_t lineno;
mrb_code *iseq;
uint16_t *lines;
- int icapa;
+ uint32_t icapa;
mrb_irep *irep;
- int pcapa, scapa, rcapa;
+ uint32_t pcapa, scapa, rcapa;
uint16_t nlocals;
uint16_t nregs;
@@ -98,12 +102,14 @@ codegen_error(codegen_scope *s, const char *message)
while (s->prev) {
codegen_scope *tmp = s->prev;
mrb_free(s->mrb, s->iseq);
+ mrb_free(s->mrb, s->lines);
mrb_pool_close(s->mpool);
s = tmp;
}
#ifndef MRB_DISABLE_STDIO
- if (s->filename && s->lineno) {
- fprintf(stderr, "codegen error:%s:%d: %s\n", s->filename, s->lineno, message);
+ if (s->filename_sym && s->lineno) {
+ const char *filename = mrb_sym2name_len(s->mrb, s->filename_sym, NULL);
+ fprintf(stderr, "codegen error:%s:%d: %s\n", filename, s->lineno, message);
}
else {
fprintf(stderr, "codegen error: %s\n", message);
@@ -122,15 +128,6 @@ codegen_palloc(codegen_scope *s, size_t len)
}
static void*
-codegen_malloc(codegen_scope *s, size_t len)
-{
- void *p = mrb_malloc_simple(s->mrb, len);
-
- if (!p) codegen_error(s, "mrb_malloc");
- return p;
-}
-
-static void*
codegen_realloc(codegen_scope *s, void *p, size_t len)
{
p = mrb_realloc_simple(s->mrb, p, len);
@@ -142,32 +139,135 @@ codegen_realloc(codegen_scope *s, void *p, size_t len)
static int
new_label(codegen_scope *s)
{
- s->lastlabel = s->pc;
- return s->pc;
+ return s->lastlabel = s->pc;
}
-static inline int
-genop(codegen_scope *s, mrb_code i)
+static void
+emit_B(codegen_scope *s, uint32_t pc, uint8_t i)
{
- if (s->pc >= s->icapa) {
+ if (pc >= MAXARG_S || s->icapa >= MAXARG_S) {
+ codegen_error(s, "too big code block");
+ }
+ if (pc >= s->icapa) {
s->icapa *= 2;
- if (s->pc >= MAXARG_sBx) {
- codegen_error(s, "too big code block");
- }
- if (s->icapa > MAXARG_sBx) {
- s->icapa = MAXARG_sBx;
+ if (s->icapa > MAXARG_S) {
+ s->icapa = MAXARG_S;
}
s->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->icapa);
if (s->lines) {
- s->lines = (uint16_t*)codegen_realloc(s, s->lines, sizeof(short)*s->icapa);
- s->irep->lines = s->lines;
+ s->lines = (uint16_t*)codegen_realloc(s, s->lines, sizeof(uint16_t)*s->icapa);
}
}
- s->iseq[s->pc] = i;
if (s->lines) {
- s->lines[s->pc] = s->lineno;
+ if (s->lineno > 0 || pc == 0)
+ s->lines[pc] = s->lineno;
+ else
+ s->lines[pc] = s->lines[pc-1];
+ }
+ s->iseq[pc] = i;
+}
+
+static void
+emit_S(codegen_scope *s, int pc, uint16_t i)
+{
+ uint8_t hi = i>>8;
+ uint8_t lo = i&0xff;
+
+ emit_B(s, pc, hi);
+ emit_B(s, pc+1, lo);
+}
+
+static void
+gen_B(codegen_scope *s, uint8_t i)
+{
+ emit_B(s, s->pc, i);
+ s->pc++;
+}
+
+static void
+gen_S(codegen_scope *s, uint16_t i)
+{
+ emit_S(s, s->pc, i);
+ s->pc += 2;
+}
+
+static void
+genop_0(codegen_scope *s, mrb_code i)
+{
+ s->lastpc = s->pc;
+ gen_B(s, i);
+}
+
+static void
+genop_1(codegen_scope *s, mrb_code i, uint16_t a)
+{
+ s->lastpc = s->pc;
+ if (a > 0xff) {
+ gen_B(s, OP_EXT1);
+ gen_B(s, i);
+ gen_S(s, a);
}
- return s->pc++;
+ else {
+ gen_B(s, i);
+ gen_B(s, (uint8_t)a);
+ }
+}
+
+static void
+genop_2(codegen_scope *s, mrb_code i, uint16_t a, uint16_t b)
+{
+ s->lastpc = s->pc;
+ if (a > 0xff && b > 0xff) {
+ gen_B(s, OP_EXT3);
+ gen_B(s, i);
+ gen_S(s, a);
+ gen_S(s, b);
+ }
+ else if (b > 0xff) {
+ gen_B(s, OP_EXT2);
+ gen_B(s, i);
+ gen_B(s, (uint8_t)a);
+ gen_S(s, b);
+ }
+ else if (a > 0xff) {
+ gen_B(s, OP_EXT1);
+ gen_B(s, i);
+ gen_S(s, a);
+ gen_B(s, (uint8_t)b);
+ }
+ else {
+ gen_B(s, i);
+ gen_B(s, (uint8_t)a);
+ gen_B(s, (uint8_t)b);
+ }
+}
+
+static void
+genop_3(codegen_scope *s, mrb_code i, uint16_t a, uint16_t b, uint8_t c)
+{
+ genop_2(s, i, a, b);
+ gen_B(s, c);
+}
+
+static void
+genop_2S(codegen_scope *s, mrb_code i, uint16_t a, uint16_t b)
+{
+ genop_1(s, i, a);
+ gen_S(s, b);
+}
+
+static void
+genop_W(codegen_scope *s, mrb_code i, uint32_t a)
+{
+ uint8_t a1 = (a>>16) & 0xff;
+ uint8_t a2 = (a>>8) & 0xff;
+ uint8_t a3 = a & 0xff;
+
+ s->lastpc = s->pc;
+ gen_B(s, i);
+ gen_B(s, a1);
+ gen_B(s, a2);
+ gen_B(s, a3);
}
#define NOVAL 0
@@ -181,298 +281,270 @@ no_optimize(codegen_scope *s)
return FALSE;
}
-static int
-genop_peep(codegen_scope *s, mrb_code i, int val)
+static
+mrb_bool
+on_eval(codegen_scope *s)
{
- /* peephole optimization */
- if (!no_optimize(s) && s->lastlabel != s->pc && s->pc > 0) {
- mrb_code i0 = s->iseq[s->pc-1];
- int c1 = GET_OPCODE(i);
- int c0 = GET_OPCODE(i0);
+ if (s && s->parser && s->parser->on_eval)
+ return TRUE;
+ return FALSE;
+}
- switch (c1) {
- case OP_MOVE:
- if (GETARG_A(i) == GETARG_B(i)) {
- /* skip useless OP_MOVE */
- return 0;
- }
- if (val) break;
- switch (c0) {
- case OP_MOVE:
- if (GETARG_A(i) == GETARG_A(i0)) {
- /* skip overriden OP_MOVE */
- s->pc--;
- s->iseq[s->pc] = i;
- }
- if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i) == GETARG_B(i0)) {
- /* skip swapping OP_MOVE */
- return 0;
- }
- if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
- s->pc--;
- return genop_peep(s, MKOP_AB(OP_MOVE, GETARG_A(i), GETARG_B(i0)), val);
- }
- break;
- case OP_LOADI:
- if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
- s->iseq[s->pc-1] = MKOP_AsBx(OP_LOADI, GETARG_A(i), GETARG_sBx(i0));
- return 0;
- }
- break;
- case OP_ARRAY:
- case OP_HASH:
- case OP_RANGE:
- case OP_AREF:
- case OP_GETUPVAR:
- if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
- s->iseq[s->pc-1] = MKOP_ABC(c0, GETARG_A(i), GETARG_B(i0), GETARG_C(i0));
- return 0;
- }
- break;
- case OP_LOADSYM:
- case OP_GETGLOBAL:
- case OP_GETIV:
- case OP_GETCV:
- case OP_GETCONST:
- case OP_GETSPECIAL:
- case OP_LOADL:
- case OP_STRING:
- if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
- s->iseq[s->pc-1] = MKOP_ABx(c0, GETARG_A(i), GETARG_Bx(i0));
- return 0;
- }
- break;
- case OP_SCLASS:
- if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
- s->iseq[s->pc-1] = MKOP_AB(c0, GETARG_A(i), GETARG_B(i0));
- return 0;
- }
- break;
- case OP_LOADNIL:
- case OP_LOADSELF:
- case OP_LOADT:
- case OP_LOADF:
- case OP_OCLASS:
- if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
- s->iseq[s->pc-1] = MKOP_A(c0, GETARG_A(i));
- return 0;
- }
- break;
- default:
- break;
- }
- break;
- case OP_SETIV:
- case OP_SETCV:
- case OP_SETCONST:
- case OP_SETMCNST:
- case OP_SETGLOBAL:
- if (val) break;
- if (c0 == OP_MOVE) {
- if (GETARG_A(i) == GETARG_A(i0)) {
- s->iseq[s->pc-1] = MKOP_ABx(c1, GETARG_B(i0), GETARG_Bx(i));
- return 0;
- }
- }
- break;
- case OP_SETUPVAR:
- if (val) break;
- if (c0 == OP_MOVE) {
- if (GETARG_A(i) == GETARG_A(i0)) {
- s->iseq[s->pc-1] = MKOP_ABC(c1, GETARG_B(i0), GETARG_B(i), GETARG_C(i));
- return 0;
- }
- }
- break;
- case OP_GETUPVAR:
- if (c0 == OP_SETUPVAR) {
- if (GETARG_B(i) == GETARG_B(i0) && GETARG_C(i) == GETARG_C(i0)) {
- if (GETARG_A(i) == GETARG_A(i0)) {
- /* just skip OP_SETUPVAR */
- return 0;
- }
- else {
- return genop(s, MKOP_AB(OP_MOVE, GETARG_A(i), GETARG_A(i0)));
- }
- }
- }
- break;
- case OP_EPOP:
- if (c0 == OP_EPOP) {
- s->iseq[s->pc-1] = MKOP_A(OP_EPOP, GETARG_A(i0)+GETARG_A(i));
- return 0;
- }
- break;
- case OP_POPERR:
- if (c0 == OP_POPERR) {
- s->iseq[s->pc-1] = MKOP_A(OP_POPERR, GETARG_A(i0)+GETARG_A(i));
- return 0;
- }
- break;
- case OP_RETURN:
- switch (c0) {
- case OP_RETURN:
- return 0;
- case OP_MOVE:
- if (GETARG_A(i0) >= s->nlocals) {
- s->iseq[s->pc-1] = MKOP_AB(OP_RETURN, GETARG_B(i0), OP_R_NORMAL);
- return 0;
- }
- break;
- case OP_SETIV:
- case OP_SETCV:
- case OP_SETCONST:
- case OP_SETMCNST:
- case OP_SETUPVAR:
- case OP_SETGLOBAL:
- s->pc--;
- genop_peep(s, i0, NOVAL);
- i0 = s->iseq[s->pc-1];
- return genop(s, MKOP_AB(OP_RETURN, GETARG_A(i0), OP_R_NORMAL));
-#if 0
- case OP_SEND:
- if (GETARG_B(i) == OP_R_NORMAL && GETARG_A(i) == GETARG_A(i0)) {
- s->iseq[s->pc-1] = MKOP_ABC(OP_TAILCALL, GETARG_A(i0), GETARG_B(i0), GETARG_C(i0));
- return;
- }
- break;
-#endif
- default:
- break;
- }
- break;
- case OP_ADD:
- case OP_SUB:
- if (c0 == OP_LOADI) {
- int c = GETARG_sBx(i0);
-
- if (c1 == OP_SUB) c = -c;
- if (c > 127 || c < -127) break;
- if (0 <= c)
- s->iseq[s->pc-1] = MKOP_ABC(OP_ADDI, GETARG_A(i), GETARG_B(i), c);
- else
- s->iseq[s->pc-1] = MKOP_ABC(OP_SUBI, GETARG_A(i), GETARG_B(i), -c);
- return 0;
- }
- break;
- case OP_ARYCAT:
- case OP_ARYPUSH:
- if (c0 == OP_MOVE && GETARG_A(i0) >= s->nlocals) {
- s->iseq[s->pc-1] = MKOP_AB(c1, GETARG_A(i), GETARG_B(i0));
- return 0;
- }
- break;
- case OP_STRCAT:
- if (c0 == OP_STRING) {
- mrb_value v = s->irep->pool[GETARG_Bx(i0)];
+struct mrb_insn_data
+mrb_decode_insn(mrb_code *pc)
+{
+ struct mrb_insn_data data = { 0 };
+ mrb_code insn = READ_B();
+ uint16_t a = 0;
+ uint16_t b = 0;
+ uint8_t c = 0;
+
+ switch (insn) {
+#define FETCH_Z() /* empty */
+#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x (); break;
+#include "mruby/ops.h"
+#undef OPCODE
+ }
+ switch (insn) {
+ case OP_EXT1:
+ insn = READ_B();
+ switch (insn) {
+#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _1 (); break;
+#include "mruby/ops.h"
+#undef OPCODE
+ }
+ break;
+ case OP_EXT2:
+ insn = READ_B();
+ switch (insn) {
+#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _2 (); break;
+#include "mruby/ops.h"
+#undef OPCODE
+ }
+ break;
+ case OP_EXT3:
+ insn = READ_B();
+ switch (insn) {
+#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _3 (); break;
+#include "mruby/ops.h"
+#undef OPCODE
+ }
+ break;
+ default:
+ break;
+ }
+ data.insn = insn;
+ data.a = a;
+ data.b = b;
+ data.c = c;
+ return data;
+}
- if (mrb_string_p(v) && RSTRING_LEN(v) == 0) {
- s->pc--;
- return 0;
- }
- }
- if (c0 == OP_LOADNIL) {
- if (GETARG_B(i) == GETARG_A(i0)) {
- s->pc--;
- return 0;
- }
- }
+static struct mrb_insn_data
+mrb_last_insn(codegen_scope *s)
+{
+ if (s->pc == s->lastpc) {
+ struct mrb_insn_data data;
+
+ data.insn = OP_NOP;
+ return data;
+ }
+ return mrb_decode_insn(&s->iseq[s->lastpc]);
+}
+
+static mrb_bool
+no_peephole(codegen_scope *s)
+{
+ return no_optimize(s) || s->lastlabel == s->pc || s->pc == 0 || s->pc == s->lastpc;
+}
+
+static uint16_t
+genjmp(codegen_scope *s, mrb_code i, uint16_t pc)
+{
+ uint16_t pos;
+
+ s->lastpc = s->pc;
+ gen_B(s, i);
+ pos = s->pc;
+ gen_S(s, pc);
+ return pos;
+}
+
+static uint16_t
+genjmp2(codegen_scope *s, mrb_code i, uint16_t a, int pc, int val)
+{
+ uint16_t pos;
+
+ if (!no_peephole(s) && !val) {
+ struct mrb_insn_data data = mrb_last_insn(s);
+
+ if (data.insn == OP_MOVE && data.a == a) {
+ s->pc = s->lastpc;
+ a = data.b;
+ }
+ }
+
+ s->lastpc = s->pc;
+ if (a > 0xff) {
+ gen_B(s, OP_EXT1);
+ gen_B(s, i);
+ gen_S(s, a);
+ pos = s->pc;
+ gen_S(s, pc);
+ }
+ else {
+ gen_B(s, i);
+ gen_B(s, (uint8_t)a);
+ pos = s->pc;
+ gen_S(s, pc);
+ }
+ return pos;
+}
+
+static void
+gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep)
+{
+ if (no_peephole(s)) {
+ normal:
+ genop_2(s, OP_MOVE, dst, src);
+ if (on_eval(s)) {
+ genop_0(s, OP_NOP);
+ }
+ return;
+ }
+ else {
+ struct mrb_insn_data data = mrb_last_insn(s);
+
+ switch (data.insn) {
+ case OP_MOVE:
+ if (dst == src) return; /* remove useless MOVE */
+ if (data.b == dst && data.a == src) /* skip swapping MOVE */
+ return;
+ goto normal;
+ case OP_LOADNIL: case OP_LOADSELF: case OP_LOADT: case OP_LOADF:
+ case OP_LOADI__1:
+ case OP_LOADI_0: case OP_LOADI_1: case OP_LOADI_2: case OP_LOADI_3:
+ case OP_LOADI_4: case OP_LOADI_5: case OP_LOADI_6: case OP_LOADI_7:
+ if (nopeep || data.a != src || data.a < s->nlocals) goto normal;
+ s->pc = s->lastpc;
+ genop_1(s, data.insn, dst);
break;
- case OP_JMPIF:
- case OP_JMPNOT:
- if (c0 == OP_MOVE && GETARG_A(i) == GETARG_A(i0)) {
- s->iseq[s->pc-1] = MKOP_AsBx(c1, GETARG_B(i0), GETARG_sBx(i));
- return s->pc-1;
- }
+ case OP_LOADI: case OP_LOADINEG: case OP_LOADL: case OP_LOADSYM:
+ case OP_GETGV: case OP_GETSV: case OP_GETIV: case OP_GETCV:
+ case OP_GETCONST: case OP_STRING:
+ case OP_LAMBDA: case OP_BLOCK: case OP_METHOD: case OP_BLKPUSH:
+ if (nopeep || data.a != src || data.a < s->nlocals) goto normal;
+ s->pc = s->lastpc;
+ genop_2(s, data.insn, dst, data.b);
break;
default:
- break;
+ goto normal;
}
}
- return genop(s, i);
}
static void
-scope_error(codegen_scope *s)
+gen_return(codegen_scope *s, uint8_t op, uint16_t src)
{
- exit(EXIT_FAILURE);
+ if (no_peephole(s)) {
+ genop_1(s, op, src);
+ }
+ else {
+ struct mrb_insn_data data = mrb_last_insn(s);
+
+ if (data.insn == OP_MOVE && src == data.a) {
+ s->pc = s->lastpc;
+ genop_1(s, op, data.b);
+ }
+ else if (data.insn != OP_RETURN) {
+ genop_1(s, op, src);
+ }
+ }
}
static void
-distcheck(codegen_scope *s, int diff)
+gen_addsub(codegen_scope *s, uint8_t op, uint16_t dst)
{
- if (diff > MAXARG_sBx || diff < -MAXARG_sBx) {
- codegen_error(s, "too distant jump address");
+ if (no_peephole(s)) {
+ normal:
+ genop_1(s, op, dst);
+ return;
+ }
+ else {
+ struct mrb_insn_data data = mrb_last_insn(s);
+
+ switch (data.insn) {
+ case OP_LOADI__1:
+ if (op == OP_ADD) op = OP_SUB;
+ else op = OP_ADD;
+ data.b = 1;
+ goto replace;
+ case OP_LOADI_0: case OP_LOADI_1: case OP_LOADI_2: case OP_LOADI_3:
+ case OP_LOADI_4: case OP_LOADI_5: case OP_LOADI_6: case OP_LOADI_7:
+ data.b = data.insn - OP_LOADI_0;
+ /* fall through */
+ case OP_LOADI:
+ replace:
+ if (data.b >= 128) goto normal;
+ s->pc = s->lastpc;
+ if (op == OP_ADD) {
+ genop_2(s, OP_ADDI, dst, (uint8_t)data.b);
+ }
+ else {
+ genop_2(s, OP_SUBI, dst, (uint8_t)data.b);
+ }
+ break;
+ default:
+ goto normal;
+ }
}
}
-static inline void
-dispatch(codegen_scope *s, int pc)
+static int
+dispatch(codegen_scope *s, uint16_t pos0)
{
- int diff = s->pc - pc;
- mrb_code i = s->iseq[pc];
- int c = GET_OPCODE(i);
+ uint16_t newpos;
s->lastlabel = s->pc;
- switch (c) {
- case OP_JMP:
- case OP_JMPIF:
- case OP_JMPNOT:
- case OP_ONERR:
- break;
- default:
-#ifndef MRB_DISABLE_STDIO
- fprintf(stderr, "bug: dispatch on non JMP op\n");
-#endif
- scope_error(s);
- break;
- }
- distcheck(s, diff);
- s->iseq[pc] = MKOP_AsBx(c, GETARG_A(i), diff);
+ newpos = PEEK_S(s->iseq+pos0);
+ emit_S(s, pos0, s->pc);
+ return newpos;
}
static void
-dispatch_linked(codegen_scope *s, int pc)
+dispatch_linked(codegen_scope *s, uint16_t pos)
{
- mrb_code i;
- int pos;
-
- if (!pc) return;
+ if (pos==0) return;
for (;;) {
- i = s->iseq[pc];
- pos = GETARG_sBx(i);
- dispatch(s, pc);
- if (!pos) break;
- pc = pos;
+ pos = dispatch(s, pos);
+ if (pos==0) break;
}
}
#define nregs_update do {if (s->sp > s->nregs) s->nregs = s->sp;} while (0)
static void
-push_(codegen_scope *s)
+push_n_(codegen_scope *s, int n)
{
- if (s->sp > 511) {
+ if (s->sp+n >= 0xffff) {
codegen_error(s, "too complex expression");
}
- s->sp++;
+ s->sp+=n;
nregs_update;
}
static void
-push_n_(codegen_scope *s, int n)
+pop_n_(codegen_scope *s, int n)
{
- if (s->sp+n > 511) {
- codegen_error(s, "too complex expression");
+ if ((int)s->sp-n < 0) {
+ codegen_error(s, "stack pointer underflow");
}
- s->sp+=n;
- nregs_update;
+ s->sp-=n;
}
-#define push() push_(s)
+#define push() push_n_(s,1)
#define push_n(n) push_n_(s,n)
-#define pop_(s) ((s)->sp--)
-#define pop() pop_(s)
-#define pop_n(n) (s->sp-=(n))
+#define pop() pop_n_(s,1)
+#define pop_n(n) pop_n_(s,n)
#define cursp() (s->sp)
static inline int
@@ -496,9 +568,12 @@ new_lit(codegen_scope *s, mrb_value val)
#ifndef MRB_WITHOUT_FLOAT
case MRB_TT_FLOAT:
for (i=0; i<s->irep->plen; i++) {
+ mrb_float f1, f2;
pv = &s->irep->pool[i];
if (mrb_type(*pv) != MRB_TT_FLOAT) continue;
- if (mrb_float(*pv) == mrb_float(val)) return i;
+ f1 = mrb_float(*pv);
+ f2 = mrb_float(val);
+ if (f1 == f2 && !signbit(f1) == !signbit(f2)) return i;
}
break;
#endif
@@ -545,52 +620,23 @@ new_lit(codegen_scope *s, mrb_value val)
return i;
}
-/* method symbols should be fit in 9 bits */
-#define MAXMSYMLEN 512
/* maximum symbol numbers */
-#define MAXSYMLEN 65536
+#define MAXSYMLEN 0x10000
static int
-new_msym(codegen_scope *s, mrb_sym sym)
+new_sym(codegen_scope *s, mrb_sym sym)
{
int i, len;
mrb_assert(s->irep);
len = s->irep->slen;
- if (len > MAXMSYMLEN) len = MAXMSYMLEN;
for (i=0; i<len; i++) {
if (s->irep->syms[i] == sym) return i;
- if (s->irep->syms[i] == 0) break;
}
- if (i == MAXMSYMLEN) {
- codegen_error(s, "too many symbols (max " MRB_STRINGIZE(MAXMSYMLEN) ")");
- }
- s->irep->syms[i] = sym;
- if (i == s->irep->slen) s->irep->slen++;
- return i;
-}
-
-static int
-new_sym(codegen_scope *s, mrb_sym sym)
-{
- int i;
-
- for (i=0; i<s->irep->slen; i++) {
- if (s->irep->syms[i] == sym) return i;
- }
- if (s->irep->slen == MAXSYMLEN) {
- codegen_error(s, "too many symbols (max " MRB_STRINGIZE(MAXSYMLEN) ")");
- }
-
- if (s->irep->slen > MAXMSYMLEN/2 && s->scapa == MAXMSYMLEN) {
- s->scapa = MAXSYMLEN;
- s->irep->syms = (mrb_sym *)codegen_realloc(s, s->irep->syms, sizeof(mrb_sym)*MAXSYMLEN);
- for (i = s->irep->slen; i < MAXMSYMLEN; i++) {
- static const mrb_sym mrb_sym_zero = { 0 };
- s->irep->syms[i] = mrb_sym_zero;
- }
- s->irep->slen = MAXMSYMLEN;
+ if (s->irep->slen >= s->scapa) {
+ s->scapa *= 2;
+ s->irep->syms = (mrb_sym*)codegen_realloc(s, s->irep->syms, sizeof(mrb_sym)*s->scapa);
}
s->irep->syms[s->irep->slen] = sym;
return s->irep->slen++;
@@ -608,8 +654,12 @@ node_len(node *tree)
return n;
}
+#define nint(x) ((int)(intptr_t)(x))
+#define nchar(x) ((char)(intptr_t)(x))
#define nsym(x) ((mrb_sym)(intptr_t)(x))
+
#define lv_name(lv) nsym((lv)->car)
+
static int
lv_idx(codegen_scope *s, mrb_sym id)
{
@@ -631,7 +681,6 @@ for_body(codegen_scope *s, node *tree)
int idx;
struct loopinfo *lp;
node *n2;
- mrb_code c;
/* generate receiver */
codegen(s, tree->cdr->car, VAL);
@@ -645,7 +694,7 @@ for_body(codegen_scope *s, node *tree)
/* generate loop variable */
n2 = tree->car;
- genop(s, MKOP_Ax(OP_ENTER, 0x40000));
+ genop_W(s, OP_ENTER, 0x40000);
if (n2->car && !n2->car->cdr && !n2->cdr) {
gen_assignment(s, n2->car->car, 1, NOVAL);
}
@@ -659,25 +708,20 @@ for_body(codegen_scope *s, node *tree)
/* loop body */
codegen(s, tree->cdr->cdr->car, VAL);
pop();
- if (s->pc > 0) {
- c = s->iseq[s->pc-1];
- if (GET_OPCODE(c) != OP_RETURN || GETARG_B(c) != OP_R_NORMAL || s->pc == s->lastlabel)
- genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
- }
+ gen_return(s, OP_RETURN, cursp());
loop_pop(s, NOVAL);
scope_finish(s);
s = prev;
- genop(s, MKOP_Abc(OP_LAMBDA, cursp(), s->irep->rlen-1, OP_L_BLOCK));
+ genop_2(s, OP_BLOCK, cursp(), s->irep->rlen-1);
push();pop(); /* space for a block */
pop();
- idx = new_msym(s, mrb_intern_lit(s->mrb, "each"));
- genop(s, MKOP_ABC(OP_SENDB, cursp(), idx, 0));
+ idx = new_sym(s, mrb_intern_lit(s->mrb, "each"));
+ genop_3(s, OP_SENDB, cursp(), idx, 0);
}
static int
lambda_body(codegen_scope *s, node *tree, int blk)
{
- mrb_code c;
codegen_scope *parent = s;
s = scope_new(s->mrb, s, tree->car);
if (s == NULL) {
@@ -688,78 +732,150 @@ lambda_body(codegen_scope *s, node *tree, int blk)
if (blk) {
struct loopinfo *lp = loop_push(s, LOOP_BLOCK);
- lp->pc1 = new_label(s);
+ lp->pc0 = new_label(s);
}
tree = tree->cdr;
- if (tree->car) {
+ if (tree->car == NULL) {
+ genop_W(s, OP_ENTER, 0);
+ }
+ else {
mrb_aspec a;
int ma, oa, ra, pa, ka, kd, ba;
int pos, i;
- node *n, *opt;
+ node *opt;
+ node *margs, *pargs;
+ node *tail;
+ /* mandatory arguments */
ma = node_len(tree->car->car);
- n = tree->car->car;
- while (n) {
- n = n->cdr;
- }
+ margs = tree->car->car;
+ tail = tree->car->cdr->cdr->cdr->cdr;
+
+ /* optional arguments */
oa = node_len(tree->car->cdr->car);
+ /* rest argument? */
ra = tree->car->cdr->cdr->car ? 1 : 0;
+ /* mandatory arugments after rest argument */
pa = node_len(tree->car->cdr->cdr->cdr->car);
- ka = kd = 0;
- ba = tree->car->cdr->cdr->cdr->cdr ? 1 : 0;
+ pargs = tree->car->cdr->cdr->cdr->car;
+ /* keyword arguments */
+ ka = tail? node_len(tail->cdr->car) : 0;
+ /* keyword dictionary? */
+ kd = tail && tail->cdr->cdr->car? 1 : 0;
+ /* block argument? */
+ ba = tail && tail->cdr->cdr->cdr->car ? 1 : 0;
if (ma > 0x1f || oa > 0x1f || pa > 0x1f || ka > 0x1f) {
codegen_error(s, "too many formal arguments");
}
- a = ((mrb_aspec)(ma & 0x1f) << 18)
- | ((mrb_aspec)(oa & 0x1f) << 13)
- | ((ra & 1) << 12)
- | ((pa & 0x1f) << 7)
- | ((ka & 0x1f) << 2)
- | ((kd & 1)<< 1)
- | (ba & 1);
- s->ainfo = (((ma+oa) & 0x3f) << 6) /* (12bits = 6:1:5) */
- | ((ra & 1) << 5)
- | (pa & 0x1f);
- genop(s, MKOP_Ax(OP_ENTER, a));
+ a = MRB_ARGS_REQ(ma)
+ | MRB_ARGS_OPT(oa)
+ | (ra? MRB_ARGS_REST() : 0)
+ | MRB_ARGS_POST(pa)
+ | MRB_ARGS_KEY(ka, kd)
+ | (ba? MRB_ARGS_BLOCK() : 0);
+ s->ainfo = (((ma+oa) & 0x3f) << 7) /* (12bits = 5:1:5:1) */
+ | ((ra & 0x1) << 6)
+ | ((pa & 0x1f) << 1)
+ | (kd & 0x1);
+ genop_W(s, OP_ENTER, a);
+ /* generate jump table for optional arguments initializer */
pos = new_label(s);
for (i=0; i<oa; i++) {
new_label(s);
- genop(s, MKOP_sBx(OP_JMP, 0));
+ genjmp(s, OP_JMP, 0);
}
if (oa > 0) {
- genop(s, MKOP_sBx(OP_JMP, 0));
+ genjmp(s, OP_JMP, 0);
}
opt = tree->car->cdr->car;
i = 0;
while (opt) {
int idx;
- dispatch(s, pos+i);
+ dispatch(s, pos+i*3+1);
codegen(s, opt->car->cdr, VAL);
- idx = lv_idx(s, nsym(opt->car->car));
pop();
- genop_peep(s, MKOP_AB(OP_MOVE, idx, cursp()), NOVAL);
+ idx = lv_idx(s, nsym(opt->car->car));
+ gen_move(s, idx, cursp(), 0);
i++;
opt = opt->cdr;
}
if (oa > 0) {
- dispatch(s, pos+i);
+ dispatch(s, pos+i*3+1);
+ }
+
+ /* keyword arguments */
+ if (tail) {
+ node *kwds = tail->cdr->car;
+ int kwrest = 0;
+
+ if (tail->cdr->cdr->car) {
+ kwrest = 1;
+ }
+ mrb_assert(nint(tail->car) == NODE_ARGS_TAIL);
+ mrb_assert(node_len(tail) == 4);
+
+ while (kwds) {
+ int jmpif_key_p, jmp_def_set = -1;
+ node *kwd = kwds->car, *def_arg = kwd->cdr->cdr->car;
+ mrb_sym kwd_sym = nsym(kwd->cdr->car);
+
+ mrb_assert(nint(kwd->car) == NODE_KW_ARG);
+
+ if (def_arg) {
+ genop_2(s, OP_KEY_P, lv_idx(s, kwd_sym), new_sym(s, kwd_sym));
+ jmpif_key_p = genjmp2(s, OP_JMPIF, lv_idx(s, kwd_sym), 0, 0);
+ codegen(s, def_arg, VAL);
+ pop();
+ gen_move(s, lv_idx(s, kwd_sym), cursp(), 0);
+ jmp_def_set = genjmp(s, OP_JMP, 0);
+ dispatch(s, jmpif_key_p);
+ }
+ genop_2(s, OP_KARG, lv_idx(s, kwd_sym), new_sym(s, kwd_sym));
+ if (jmp_def_set != -1) {
+ dispatch(s, jmp_def_set);
+ }
+ i++;
+
+ kwds = kwds->cdr;
+ }
+ if (tail->cdr->car && !kwrest) {
+ genop_0(s, OP_KEYEND);
+ }
+ }
+
+ /* argument destructuring */
+ if (margs) {
+ node *n = margs;
+
+ pos = 1;
+ while (n) {
+ if (nint(n->car->car) == NODE_MASGN) {
+ gen_vmassignment(s, n->car->cdr->car, pos, NOVAL);
+ }
+ pos++;
+ n = n->cdr;
+ }
+ }
+ if (pargs) {
+ node *n = margs;
+
+ pos = ma+oa+ra+1;
+ while (n) {
+ if (nint(n->car->car) == NODE_MASGN) {
+ gen_vmassignment(s, n->car->cdr->car, pos, NOVAL);
+ }
+ pos++;
+ n = n->cdr;
+ }
}
}
+
codegen(s, tree->cdr->car, VAL);
pop();
if (s->pc > 0) {
- c = s->iseq[s->pc-1];
- if (GET_OPCODE(c) != OP_RETURN || GETARG_B(c) != OP_R_NORMAL || s->pc == s->lastlabel) {
- if (s->nregs == 0) {
- genop(s, MKOP_A(OP_LOADNIL, 0));
- genop(s, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
- }
- else {
- genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
- }
- }
+ gen_return(s, OP_RETURN, cursp());
}
if (blk) {
loop_pop(s, NOVAL);
@@ -773,24 +889,13 @@ scope_body(codegen_scope *s, node *tree, int val)
{
codegen_scope *scope = scope_new(s->mrb, s, tree->car);
if (scope == NULL) {
- raise_error(s, "unexpected scope");
+ codegen_error(s, "unexpected scope");
}
codegen(scope, tree->cdr, VAL);
+ gen_return(scope, OP_RETURN, scope->sp-1);
if (!s->iseq) {
- genop(scope, MKOP_A(OP_STOP, 0));
- }
- else if (!val) {
- genop(scope, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
- }
- else {
- if (scope->nregs == 0) {
- genop(scope, MKOP_A(OP_LOADNIL, 0));
- genop(scope, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
- }
- else {
- genop_peep(scope, MKOP_AB(OP_RETURN, scope->sp-1, OP_R_NORMAL), NOVAL);
- }
+ genop_0(scope, OP_STOP);
}
scope_finish(scope);
if (!s->irep) {
@@ -800,9 +905,6 @@ scope_body(codegen_scope *s, node *tree, int val)
return s->irep->rlen - 1;
}
-#define nint(x) ((int)(intptr_t)(x))
-#define nchar(x) ((char)(intptr_t)(x))
-
static mrb_bool
nosplat(node *t)
{
@@ -854,15 +956,15 @@ gen_values(codegen_scope *s, node *t, int val, int extra)
}
else {
pop_n(n);
- genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), n));
+ genop_2(s, OP_ARRAY, cursp(), n);
push();
codegen(s, t->car, VAL);
pop(); pop();
if (is_splat) {
- genop_peep(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1), NOVAL);
+ genop_1(s, OP_ARYCAT, cursp());
}
else {
- genop_peep(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1), NOVAL);
+ genop_1(s, OP_ARYPUSH, cursp());
}
}
t = t->cdr;
@@ -871,10 +973,10 @@ gen_values(codegen_scope *s, node *t, int val, int extra)
codegen(s, t->car, VAL);
pop(); pop();
if (nint(t->car->car) == NODE_SPLAT) {
- genop_peep(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1), NOVAL);
+ genop_1(s, OP_ARYCAT, cursp());
}
else {
- genop_peep(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1), NOVAL);
+ genop_1(s, OP_ARYPUSH, cursp());
}
t = t->cdr;
}
@@ -899,22 +1001,15 @@ static void
gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe)
{
mrb_sym sym = name ? name : nsym(tree->cdr->car);
- int idx, skip = 0;
+ int skip = 0;
int n = 0, noop = 0, sendv = 0, blk = 0;
codegen(s, tree->car, VAL); /* receiver */
if (safe) {
int recv = cursp()-1;
- genop(s, MKOP_A(OP_LOADNIL, cursp()));
- push();
- genop(s, MKOP_AB(OP_MOVE, cursp(), recv));
- push_n(2); pop_n(2); /* space for one arg and a block */
- pop();
- idx = new_msym(s, mrb_intern_lit(s->mrb, "=="));
- genop(s, MKOP_ABC(OP_EQ, cursp(), idx, 1));
- skip = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), 0));
+ gen_move(s, cursp(), recv, 1);
+ skip = genjmp2(s, OP_JMPNIL, cursp(), 0, val);
}
- idx = new_msym(s, sym);
tree = tree->cdr->cdr->car;
if (tree) {
n = gen_values(s, tree->car, VAL, sp?1:0);
@@ -923,14 +1018,15 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe)
push();
}
}
- if (sp) {
+ if (sp) { /* last argument pushed (attr=) */
if (sendv) {
+ gen_move(s, cursp(), sp, 0);
pop();
- genop(s, MKOP_AB(OP_ARYPUSH, cursp(), sp));
+ genop_1(s, OP_ARYPUSH, cursp());
push();
}
else {
- genop(s, MKOP_AB(OP_MOVE, cursp(), sp));
+ gen_move(s, cursp(), sp, 0);
push();
n++;
}
@@ -939,9 +1035,7 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe)
noop = 1;
codegen(s, tree->cdr, VAL);
pop();
- }
- else {
- blk = cursp();
+ blk = 1;
}
push();pop();
pop_n(n+1);
@@ -950,39 +1044,40 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe)
const char *symname = mrb_sym2name_len(s->mrb, sym, &symlen);
if (!noop && symlen == 1 && symname[0] == '+' && n == 1) {
- genop_peep(s, MKOP_ABC(OP_ADD, cursp(), idx, n), val);
+ gen_addsub(s, OP_ADD, cursp());
}
else if (!noop && symlen == 1 && symname[0] == '-' && n == 1) {
- genop_peep(s, MKOP_ABC(OP_SUB, cursp(), idx, n), val);
+ gen_addsub(s, OP_SUB, cursp());
}
else if (!noop && symlen == 1 && symname[0] == '*' && n == 1) {
- genop(s, MKOP_ABC(OP_MUL, cursp(), idx, n));
+ genop_1(s, OP_MUL, cursp());
}
else if (!noop && symlen == 1 && symname[0] == '/' && n == 1) {
- genop(s, MKOP_ABC(OP_DIV, cursp(), idx, n));
+ genop_1(s, OP_DIV, cursp());
}
else if (!noop && symlen == 1 && symname[0] == '<' && n == 1) {
- genop(s, MKOP_ABC(OP_LT, cursp(), idx, n));
+ genop_1(s, OP_LT, cursp());
}
else if (!noop && symlen == 2 && symname[0] == '<' && symname[1] == '=' && n == 1) {
- genop(s, MKOP_ABC(OP_LE, cursp(), idx, n));
+ genop_1(s, OP_LE, cursp());
}
else if (!noop && symlen == 1 && symname[0] == '>' && n == 1) {
- genop(s, MKOP_ABC(OP_GT, cursp(), idx, n));
+ genop_1(s, OP_GT, cursp());
}
else if (!noop && symlen == 2 && symname[0] == '>' && symname[1] == '=' && n == 1) {
- genop(s, MKOP_ABC(OP_GE, cursp(), idx, n));
+ genop_1(s, OP_GE, cursp());
}
else if (!noop && symlen == 2 && symname[0] == '=' && symname[1] == '=' && n == 1) {
- genop(s, MKOP_ABC(OP_EQ, cursp(), idx, n));
+ genop_1(s, OP_EQ, cursp());
}
else {
- if (sendv) n = CALL_MAXARGS;
- if (blk > 0) { /* no block */
- genop(s, MKOP_ABC(OP_SEND, cursp(), idx, n));
+ int idx = new_sym(s, sym);
+
+ if (sendv) {
+ genop_2(s, blk ? OP_SENDVB : OP_SENDV, cursp(), idx);
}
else {
- genop(s, MKOP_ABC(OP_SENDB, cursp(), idx, n));
+ genop_3(s, blk ? OP_SENDB : OP_SEND, cursp(), idx, n);
}
}
}
@@ -1004,13 +1099,15 @@ gen_assignment(codegen_scope *s, node *tree, int sp, int val)
switch (type) {
case NODE_GVAR:
idx = new_sym(s, nsym(tree));
- genop_peep(s, MKOP_ABx(OP_SETGLOBAL, sp, idx), val);
+ genop_2(s, OP_SETGV, sp, idx);
break;
+ case NODE_ARG:
case NODE_LVAR:
idx = lv_idx(s, nsym(tree));
if (idx > 0) {
if (idx != sp) {
- genop_peep(s, MKOP_AB(OP_MOVE, idx, sp), val);
+ gen_move(s, idx, sp, val);
+ if (val && on_eval(s)) genop_0(s, OP_NOP);
}
break;
}
@@ -1021,7 +1118,7 @@ gen_assignment(codegen_scope *s, node *tree, int sp, int val)
while (up) {
idx = lv_idx(up, nsym(tree));
if (idx > 0) {
- genop_peep(s, MKOP_ABC(OP_SETUPVAR, sp, idx, lv), val);
+ genop_3(s, OP_SETUPVAR, sp, idx, lv);
break;
}
lv++;
@@ -1031,23 +1128,23 @@ gen_assignment(codegen_scope *s, node *tree, int sp, int val)
break;
case NODE_IVAR:
idx = new_sym(s, nsym(tree));
- genop_peep(s, MKOP_ABx(OP_SETIV, sp, idx), val);
+ genop_2(s, OP_SETIV, sp, idx);
break;
case NODE_CVAR:
idx = new_sym(s, nsym(tree));
- genop_peep(s, MKOP_ABx(OP_SETCV, sp, idx), val);
+ genop_2(s, OP_SETCV, sp, idx);
break;
case NODE_CONST:
idx = new_sym(s, nsym(tree));
- genop_peep(s, MKOP_ABx(OP_SETCONST, sp, idx), val);
+ genop_2(s, OP_SETCONST, sp, idx);
break;
case NODE_COLON2:
- idx = new_sym(s, nsym(tree->cdr));
- genop_peep(s, MKOP_AB(OP_MOVE, cursp(), sp), NOVAL);
+ gen_move(s, cursp(), sp, 0);
push();
codegen(s, tree->car, VAL);
pop_n(2);
- genop_peep(s, MKOP_ABx(OP_SETMCNST, cursp(), idx), val);
+ idx = new_sym(s, nsym(tree->cdr));
+ genop_2(s, OP_SETMCNST, sp, idx);
break;
case NODE_CALL:
@@ -1057,7 +1154,7 @@ gen_assignment(codegen_scope *s, node *tree, int sp, int val)
type == NODE_SCALL);
pop();
if (val) {
- genop_peep(s, MKOP_AB(OP_MOVE, cursp(), sp), val);
+ gen_move(s, cursp(), sp, 0);
}
break;
@@ -1090,7 +1187,7 @@ gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val)
while (t) {
int sp = cursp();
- genop(s, MKOP_ABC(OP_AREF, sp, rhs, n));
+ genop_3(s, OP_AREF, sp, rhs, n);
push();
gen_assignment(s, t->car, sp, NOVAL);
pop();
@@ -1107,12 +1204,12 @@ gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val)
p = p->cdr;
}
}
- genop(s, MKOP_AB(OP_MOVE, cursp(), rhs));
+ gen_move(s, cursp(), rhs, val);
push_n(post+1);
pop_n(post+1);
- genop(s, MKOP_ABC(OP_APOST, cursp(), n, post));
+ genop_3(s, OP_APOST, cursp(), n, post);
n = 1;
- if (t->car) { /* rest */
+ if (t->car && t->car != (node*)-1) { /* rest */
gen_assignment(s, t->car, cursp(), NOVAL);
}
if (t->cdr && t->cdr->car) {
@@ -1124,19 +1221,19 @@ gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val)
}
}
if (val) {
- genop(s, MKOP_AB(OP_MOVE, cursp(), rhs));
+ gen_move(s, cursp(), rhs, 0);
}
}
}
static void
-gen_send_intern(codegen_scope *s)
+gen_intern(codegen_scope *s)
{
- push();pop(); /* space for a block */
pop();
- genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "intern")), 0));
+ genop_1(s, OP_INTERN, cursp());
push();
}
+
static void
gen_literal_array(codegen_scope *s, node *tree, mrb_bool sym, int val)
{
@@ -1159,25 +1256,25 @@ gen_literal_array(codegen_scope *s, node *tree, mrb_bool sym, int val)
j = 0;
++i;
if (sym)
- gen_send_intern(s);
+ gen_intern(s);
}
break;
}
- if (j >= 2) {
+ while (j >= 2) {
pop(); pop();
- genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
+ genop_1(s, OP_STRCAT, cursp());
push();
- j = 1;
+ j--;
}
tree = tree->cdr;
}
if (j > 0) {
++i;
if (sym)
- gen_send_intern(s);
+ gen_intern(s);
}
pop_n(i);
- genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), i));
+ genop_2(s, OP_ARRAY, cursp(), i);
push();
}
else {
@@ -1196,7 +1293,7 @@ raise_error(codegen_scope *s, const char *msg)
{
int idx = new_lit(s, mrb_str_new_cstr(s->mrb, msg));
- genop(s, MKOP_ABx(OP_ERR, 1, idx));
+ genop_1(s, OP_ERR, idx);
}
#ifndef MRB_WITHOUT_FLOAT
@@ -1274,11 +1371,9 @@ static void
gen_retval(codegen_scope *s, node *tree)
{
if (nint(tree->car) == NODE_SPLAT) {
- genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), 0));
- push();
codegen(s, tree, VAL);
- pop(); pop();
- genop(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1));
+ pop();
+ genop_1(s, OP_ARYDUP, cursp());
}
else {
codegen(s, tree, VAL);
@@ -1294,7 +1389,7 @@ codegen(codegen_scope *s, node *tree, int val)
if (!tree) {
if (val) {
- genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ genop_1(s, OP_LOADNIL, cursp());
push();
}
return;
@@ -1305,11 +1400,14 @@ codegen(codegen_scope *s, node *tree, int val)
codegen_error(s, "too complex expression");
}
if (s->irep && s->filename_index != tree->filename_index) {
- s->irep->filename = mrb_parser_get_filename(s->parser, s->filename_index);
- mrb_debug_info_append_file(s->mrb, s->irep, s->debug_start_pos, s->pc);
+ mrb_sym fname = mrb_parser_get_filename(s->parser, s->filename_index);
+ const char *filename = mrb_sym2name_len(s->mrb, fname, NULL);
+
+ mrb_debug_info_append_file(s->mrb, s->irep->debug_info,
+ filename, s->lines, s->debug_start_pos, s->pc);
s->debug_start_pos = s->pc;
s->filename_index = tree->filename_index;
- s->filename = mrb_parser_get_filename(s->parser, tree->filename_index);
+ s->filename_sym = mrb_parser_get_filename(s->parser, tree->filename_index);
}
nt = nint(tree->car);
@@ -1318,7 +1416,7 @@ codegen(codegen_scope *s, node *tree, int val)
switch (nt) {
case NODE_BEGIN:
if (val && !tree) {
- genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ genop_1(s, OP_LOADNIL, cursp());
push();
}
while (tree) {
@@ -1329,18 +1427,18 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_RESCUE:
{
- int onerr, noexc, exend, pos1, pos2, tmp;
+ int noexc, exend, pos1, pos2, tmp;
struct loopinfo *lp;
if (tree->car == NULL) goto exit;
- onerr = genop(s, MKOP_Bx(OP_ONERR, 0));
lp = loop_push(s, LOOP_BEGIN);
- lp->pc1 = onerr;
+ lp->pc0 = new_label(s);
+ lp->pc1 = genjmp(s, OP_ONERR, 0);
codegen(s, tree->car, VAL);
pop();
lp->type = LOOP_RESCUE;
- noexc = genop(s, MKOP_Bx(OP_JMP, 0));
- dispatch(s, onerr);
+ noexc = genjmp(s, OP_JMP, 0);
+ dispatch(s, lp->pc1);
tree = tree->cdr;
exend = 0;
pos1 = 0;
@@ -1348,7 +1446,7 @@ codegen(codegen_scope *s, node *tree, int val)
node *n2 = tree->car;
int exc = cursp();
- genop(s, MKOP_ABC(OP_RESCUE, exc, 0, 0));
+ genop_1(s, OP_EXCEPT, exc);
push();
while (n2) {
node *n3 = n2->car;
@@ -1359,30 +1457,29 @@ codegen(codegen_scope *s, node *tree, int val)
do {
if (n4 && n4->car && nint(n4->car->car) == NODE_SPLAT) {
codegen(s, n4->car, VAL);
- genop(s, MKOP_AB(OP_MOVE, cursp(), exc));
+ gen_move(s, cursp(), exc, 0);
push_n(2); pop_n(2); /* space for one arg and a block */
pop();
- genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1));
+ genop_3(s, OP_SEND, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1);
}
else {
if (n4) {
codegen(s, n4->car, VAL);
}
else {
- genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "StandardError"))));
+ genop_2(s, OP_GETCONST, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "StandardError")));
push();
}
pop();
- genop(s, MKOP_ABC(OP_RESCUE, exc, cursp(), 1));
+ genop_2(s, OP_RESCUE, exc, cursp());
}
- distcheck(s, pos2);
- tmp = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2));
+ tmp = genjmp2(s, OP_JMPIF, cursp(), pos2, val);
pos2 = tmp;
if (n4) {
n4 = n4->cdr;
}
} while (n4);
- pos1 = genop(s, MKOP_sBx(OP_JMP, 0));
+ pos1 = genjmp(s, OP_JMP, 0);
dispatch_linked(s, pos2);
pop();
@@ -1393,21 +1490,20 @@ codegen(codegen_scope *s, node *tree, int val)
codegen(s, n3->cdr->cdr->car, val);
if (val) pop();
}
- distcheck(s, exend);
- tmp = genop(s, MKOP_sBx(OP_JMP, exend));
+ tmp = genjmp(s, OP_JMP, exend);
exend = tmp;
n2 = n2->cdr;
push();
}
if (pos1) {
dispatch(s, pos1);
- genop(s, MKOP_A(OP_RAISE, exc));
+ genop_1(s, OP_RAISE, exc);
}
}
pop();
tree = tree->cdr;
dispatch(s, noexc);
- genop(s, MKOP_A(OP_POPERR, 1));
+ genop_1(s, OP_POPERR, 1);
if (tree->car) {
codegen(s, tree->car, val);
}
@@ -1424,15 +1520,13 @@ codegen(codegen_scope *s, node *tree, int val)
(nint(tree->cdr->cdr->car) == NODE_BEGIN &&
tree->cdr->cdr->cdr)) {
int idx;
- int epush = s->pc;
- genop(s, MKOP_Bx(OP_EPUSH, 0));
s->ensure_level++;
- codegen(s, tree->car, val);
idx = scope_body(s, tree->cdr, NOVAL);
- s->iseq[epush] = MKOP_Bx(OP_EPUSH, idx);
+ genop_1(s, OP_EPUSH, idx);
+ codegen(s, tree->car, val);
s->ensure_level--;
- genop_peep(s, MKOP_A(OP_EPOP, 1), NOVAL);
+ genop_1(s, OP_EPOP, 1);
}
else { /* empty ensure ignored */
codegen(s, tree->car, val);
@@ -1443,7 +1537,7 @@ codegen(codegen_scope *s, node *tree, int val)
if (val) {
int idx = lambda_body(s, tree, 1);
- genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_LAMBDA));
+ genop_2(s, OP_LAMBDA, cursp(), idx);
push();
}
break;
@@ -1452,7 +1546,7 @@ codegen(codegen_scope *s, node *tree, int val)
if (val) {
int idx = lambda_body(s, tree, 1);
- genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_BLOCK));
+ genop_2(s, OP_BLOCK, cursp(), idx);
push();
}
break;
@@ -1460,10 +1554,10 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_IF:
{
int pos1, pos2;
- node *e = tree->cdr->cdr->car;
+ node *elsepart = tree->cdr->cdr->car;
if (!tree->car) {
- codegen(s, e, val);
+ codegen(s, elsepart, val);
goto exit;
}
switch (nint(tree->car->car)) {
@@ -1474,27 +1568,27 @@ codegen(codegen_scope *s, node *tree, int val)
goto exit;
case NODE_FALSE:
case NODE_NIL:
- codegen(s, e, val);
+ codegen(s, elsepart, val);
goto exit;
}
codegen(s, tree->car, VAL);
pop();
- pos1 = genop_peep(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0), NOVAL);
+ pos1 = genjmp2(s, OP_JMPNOT, cursp(), 0, val);
codegen(s, tree->cdr->car, val);
- if (e) {
+ if (elsepart) {
if (val) pop();
- pos2 = genop(s, MKOP_sBx(OP_JMP, 0));
+ pos2 = genjmp(s, OP_JMP, 0);
dispatch(s, pos1);
- codegen(s, e, val);
+ codegen(s, elsepart, val);
dispatch(s, pos2);
}
else {
if (val) {
pop();
- pos2 = genop(s, MKOP_sBx(OP_JMP, 0));
+ pos2 = genjmp(s, OP_JMP, 0);
dispatch(s, pos1);
- genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ genop_1(s, OP_LOADNIL, cursp());
dispatch(s, pos2);
push();
}
@@ -1511,7 +1605,7 @@ codegen(codegen_scope *s, node *tree, int val)
codegen(s, tree->car, VAL);
pop();
- pos = genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0));
+ pos = genjmp2(s, OP_JMPNOT, cursp(), 0, val);
codegen(s, tree->cdr, val);
dispatch(s, pos);
}
@@ -1523,7 +1617,7 @@ codegen(codegen_scope *s, node *tree, int val)
codegen(s, tree->car, VAL);
pop();
- pos = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), 0));
+ pos = genjmp2(s, OP_JMPIF, cursp(), 0, val);
codegen(s, tree->cdr, val);
dispatch(s, pos);
}
@@ -1533,14 +1627,14 @@ codegen(codegen_scope *s, node *tree, int val)
{
struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
- lp->pc1 = genop(s, MKOP_sBx(OP_JMP, 0));
+ lp->pc0 = new_label(s);
+ lp->pc1 = genjmp(s, OP_JMP, 0);
lp->pc2 = new_label(s);
codegen(s, tree->cdr, NOVAL);
dispatch(s, lp->pc1);
codegen(s, tree->car, VAL);
pop();
- distcheck(s, lp->pc2 - s->pc);
- genop(s, MKOP_AsBx(OP_JMPIF, cursp(), lp->pc2 - s->pc));
+ genjmp2(s, OP_JMPIF, cursp(), lp->pc2, NOVAL);
loop_pop(s, val);
}
@@ -1550,14 +1644,14 @@ codegen(codegen_scope *s, node *tree, int val)
{
struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
- lp->pc1 = genop(s, MKOP_sBx(OP_JMP, 0));
+ lp->pc0 = new_label(s);
+ lp->pc1 = genjmp(s, OP_JMP, 0);
lp->pc2 = new_label(s);
codegen(s, tree->cdr, NOVAL);
dispatch(s, lp->pc1);
codegen(s, tree->car, VAL);
pop();
- distcheck(s, lp->pc2 - s->pc);
- genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), lp->pc2 - s->pc));
+ genjmp2(s, OP_JMPNOT, cursp(), lp->pc2, NOVAL);
loop_pop(s, val);
}
@@ -1586,43 +1680,40 @@ codegen(codegen_scope *s, node *tree, int val)
while (n) {
codegen(s, n->car, VAL);
if (head) {
- genop(s, MKOP_AB(OP_MOVE, cursp(), head));
- push_n(2); pop_n(2); /* space for one arg and a block */
- pop();
+ gen_move(s, cursp(), head, 0);
+ push(); push(); pop(); pop(); pop();
if (nint(n->car->car) == NODE_SPLAT) {
- genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1));
+ genop_3(s, OP_SEND, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1);
}
else {
- genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "===")), 1));
+ genop_3(s, OP_SEND, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "===")), 1);
}
}
else {
pop();
}
- distcheck(s, pos2);
- tmp = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2));
+ tmp = genjmp2(s, OP_JMPIF, cursp(), pos2, NOVAL);
pos2 = tmp;
n = n->cdr;
}
if (tree->car->car) {
- pos1 = genop(s, MKOP_sBx(OP_JMP, 0));
+ pos1 = genjmp(s, OP_JMP, 0);
dispatch_linked(s, pos2);
}
codegen(s, tree->car->cdr, val);
if (val) pop();
- distcheck(s, pos3);
- tmp = genop(s, MKOP_sBx(OP_JMP, pos3));
+ tmp = genjmp(s, OP_JMP, pos3);
pos3 = tmp;
if (pos1) dispatch(s, pos1);
tree = tree->cdr;
}
if (val) {
int pos = cursp();
- genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ genop_1(s, OP_LOADNIL, cursp());
if (pos3) dispatch_linked(s, pos3);
if (head) pop();
if (cursp() != pos) {
- genop(s, MKOP_AB(OP_MOVE, cursp(), pos));
+ gen_move(s, cursp(), pos, 0);
}
push();
}
@@ -1654,7 +1745,7 @@ codegen(codegen_scope *s, node *tree, int val)
codegen(s, tree->cdr, val);
if (val) {
pop(); pop();
- genop(s, MKOP_ABC(OP_RANGE, cursp(), cursp(), FALSE));
+ genop_1(s, OP_RANGE_INC, cursp());
push();
}
break;
@@ -1664,7 +1755,7 @@ codegen(codegen_scope *s, node *tree, int val)
codegen(s, tree->cdr, val);
if (val) {
pop(); pop();
- genop(s, MKOP_ABC(OP_RANGE, cursp(), cursp(), TRUE));
+ genop_1(s, OP_RANGE_EXC, cursp());
push();
}
break;
@@ -1675,7 +1766,7 @@ codegen(codegen_scope *s, node *tree, int val)
codegen(s, tree->car, VAL);
pop();
- genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
+ genop_2(s, OP_GETMCNST, cursp(), sym);
if (val) push();
}
break;
@@ -1684,8 +1775,8 @@ codegen(codegen_scope *s, node *tree, int val)
{
int sym = new_sym(s, nsym(tree));
- genop(s, MKOP_A(OP_OCLASS, cursp()));
- genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
+ genop_1(s, OP_OCLASS, cursp());
+ genop_2(s, OP_GETMCNST, cursp(), sym);
if (val) push();
}
break;
@@ -1698,7 +1789,7 @@ codegen(codegen_scope *s, node *tree, int val)
if (n >= 0) {
if (val) {
pop_n(n);
- genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), n));
+ genop_2(s, OP_ARRAY, cursp(), n);
push();
}
}
@@ -1709,21 +1800,47 @@ codegen(codegen_scope *s, node *tree, int val)
break;
case NODE_HASH:
+ case NODE_KW_HASH:
{
int len = 0;
mrb_bool update = FALSE;
while (tree) {
- codegen(s, tree->car->car, val);
- codegen(s, tree->car->cdr, val);
- len++;
+ if (nint(tree->car->car->car) == NODE_KW_REST_ARGS) {
+ if (len > 0) {
+ pop_n(len*2);
+ if (!update) {
+ genop_2(s, OP_HASH, cursp(), len);
+ }
+ else {
+ pop();
+ genop_2(s, OP_HASHADD, cursp(), len);
+ }
+ push();
+ }
+ codegen(s, tree->car->cdr, VAL);
+ if (len > 0 || update) {
+ pop(); pop();
+ genop_1(s, OP_HASHCAT, cursp());
+ push();
+ }
+ update = TRUE;
+ len = 0;
+ }
+ else {
+ codegen(s, tree->car->car, val);
+ codegen(s, tree->car->cdr, val);
+ len++;
+ }
tree = tree->cdr;
- if (val && len == 126) {
+ if (val && len == 255) {
pop_n(len*2);
- genop(s, MKOP_ABC(OP_HASH, cursp(), cursp(), len));
- if (update) {
+ if (!update) {
+ genop_2(s, OP_HASH, cursp(), len);
+ }
+ else {
pop();
- genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__update")), 1));
+ genop_2(s, OP_HASHADD, cursp(), len);
}
push();
update = TRUE;
@@ -1732,10 +1849,14 @@ codegen(codegen_scope *s, node *tree, int val)
}
if (val) {
pop_n(len*2);
- genop(s, MKOP_ABC(OP_HASH, cursp(), cursp(), len));
- if (update) {
+ if (!update) {
+ genop_2(s, OP_HASH, cursp(), len);
+ }
+ else {
pop();
- genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__update")), 1));
+ if (len > 0) {
+ genop_2(s, OP_HASHADD, cursp(), len);
+ }
}
push();
}
@@ -1776,7 +1897,7 @@ codegen(codegen_scope *s, node *tree, int val)
n++;
}
else {
- genop(s, MKOP_A(OP_LOADNIL, rhs+n));
+ genop_1(s, OP_LOADNIL, rhs+n);
gen_assignment(s, t->car, rhs+n, NOVAL);
}
t = t->cdr;
@@ -1800,7 +1921,7 @@ codegen(codegen_scope *s, node *tree, int val)
else {
rn = len - post - n;
}
- genop(s, MKOP_ABC(OP_ARRAY, cursp(), rhs+n, rn));
+ genop_3(s, OP_ARRAY2, cursp(), rhs+n, rn);
gen_assignment(s, t->car, cursp(), NOVAL);
n += rn;
}
@@ -1815,7 +1936,7 @@ codegen(codegen_scope *s, node *tree, int val)
}
pop_n(len);
if (val) {
- genop(s, MKOP_ABC(OP_ARRAY, rhs, rhs, len));
+ genop_2(s, OP_ARRAY, rhs, len);
push();
}
}
@@ -1843,17 +1964,17 @@ codegen(codegen_scope *s, node *tree, int val)
int onerr, noexc, exc;
struct loopinfo *lp;
- onerr = genop(s, MKOP_Bx(OP_ONERR, 0));
+ onerr = genjmp(s, OP_ONERR, 0);
lp = loop_push(s, LOOP_BEGIN);
lp->pc1 = onerr;
exc = cursp();
codegen(s, tree->car, VAL);
lp->type = LOOP_RESCUE;
- genop(s, MKOP_A(OP_POPERR, 1));
- noexc = genop(s, MKOP_Bx(OP_JMP, 0));
+ genop_1(s, OP_POPERR, 1);
+ noexc = genjmp(s, OP_JMP, 0);
dispatch(s, onerr);
- genop(s, MKOP_ABC(OP_RESCUE, exc, 0, 0));
- genop(s, MKOP_A(OP_LOADF, exc));
+ genop_1(s, OP_EXCEPT, exc);
+ genop_1(s, OP_LOADF, exc);
dispatch(s, noexc);
loop_pop(s, NOVAL);
}
@@ -1867,7 +1988,7 @@ codegen(codegen_scope *s, node *tree, int val)
push();
}
codegen(s, n->car, VAL); /* receiver */
- idx = new_msym(s, nsym(n->cdr->car));
+ idx = new_sym(s, nsym(n->cdr->car));
base = cursp()-1;
if (n->cdr->cdr->car) {
nargs = gen_values(s, n->cdr->cdr->car->car, VAL, 1);
@@ -1881,12 +2002,12 @@ codegen(codegen_scope *s, node *tree, int val)
}
}
/* copy receiver and arguments */
- genop(s, MKOP_AB(OP_MOVE, cursp(), base));
+ gen_move(s, cursp(), base, 1);
for (i=0; i<nargs; i++) {
- genop(s, MKOP_AB(OP_MOVE, cursp()+i+1, base+i+1));
+ gen_move(s, cursp()+i+1, base+i+1, 1);
}
push_n(nargs+2);pop_n(nargs+2); /* space for receiver, arguments and a block */
- genop(s, MKOP_ABC(OP_SEND, cursp(), idx, callargs));
+ genop_3(s, OP_SEND, cursp(), idx, callargs);
push();
}
else {
@@ -1900,30 +2021,30 @@ codegen(codegen_scope *s, node *tree, int val)
pop();
if (val) {
if (vsp >= 0) {
- genop(s, MKOP_AB(OP_MOVE, vsp, cursp()));
+ gen_move(s, vsp, cursp(), 1);
}
- pos = genop(s, MKOP_AsBx(name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0));
+ pos = genjmp2(s, name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0, val);
}
else {
- pos = genop_peep(s, MKOP_AsBx(name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0), NOVAL);
+ pos = genjmp2(s, name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0, val);
}
codegen(s, tree->cdr->cdr->car, VAL);
pop();
if (val && vsp >= 0) {
- genop(s, MKOP_AB(OP_MOVE, vsp, cursp()));
+ gen_move(s, vsp, cursp(), 1);
}
if (nint(tree->car->car) == NODE_CALL) {
if (callargs == CALL_MAXARGS) {
pop();
- genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
+ genop_1(s, OP_ARYPUSH, cursp());
}
else {
pop_n(callargs);
callargs++;
}
pop();
- idx = new_msym(s, attrsym(s, nsym(tree->car->cdr->cdr->car)));
- genop(s, MKOP_ABC(OP_SEND, cursp(), idx, callargs));
+ idx = new_sym(s, attrsym(s, nsym(tree->car->cdr->cdr->car)));
+ genop_3(s, OP_SEND, cursp(), idx, callargs);
}
else {
gen_assignment(s, tree->car, cursp(), val);
@@ -1935,52 +2056,52 @@ codegen(codegen_scope *s, node *tree, int val)
push(); pop();
pop(); pop();
- idx = new_msym(s, sym);
if (len == 1 && name[0] == '+') {
- genop_peep(s, MKOP_ABC(OP_ADD, cursp(), idx, 1), val);
+ gen_addsub(s, OP_ADD, cursp());
}
else if (len == 1 && name[0] == '-') {
- genop_peep(s, MKOP_ABC(OP_SUB, cursp(), idx, 1), val);
+ gen_addsub(s, OP_SUB, cursp());
}
else if (len == 1 && name[0] == '*') {
- genop(s, MKOP_ABC(OP_MUL, cursp(), idx, 1));
+ genop_1(s, OP_MUL, cursp());
}
else if (len == 1 && name[0] == '/') {
- genop(s, MKOP_ABC(OP_DIV, cursp(), idx, 1));
+ genop_1(s, OP_DIV, cursp());
}
else if (len == 1 && name[0] == '<') {
- genop(s, MKOP_ABC(OP_LT, cursp(), idx, 1));
+ genop_1(s, OP_LT, cursp());
}
else if (len == 2 && name[0] == '<' && name[1] == '=') {
- genop(s, MKOP_ABC(OP_LE, cursp(), idx, 1));
+ genop_1(s, OP_LE, cursp());
}
else if (len == 1 && name[0] == '>') {
- genop(s, MKOP_ABC(OP_GT, cursp(), idx, 1));
+ genop_1(s, OP_GT, cursp());
}
else if (len == 2 && name[0] == '>' && name[1] == '=') {
- genop(s, MKOP_ABC(OP_GE, cursp(), idx, 1));
+ genop_1(s, OP_GE, cursp());
}
else {
- genop(s, MKOP_ABC(OP_SEND, cursp(), idx, 1));
+ idx = new_sym(s, sym);
+ genop_3(s, OP_SEND, cursp(), idx, 1);
}
if (callargs < 0) {
gen_assignment(s, tree->car, cursp(), val);
}
else {
if (val && vsp >= 0) {
- genop(s, MKOP_AB(OP_MOVE, vsp, cursp()));
+ gen_move(s, vsp, cursp(), 0);
}
if (callargs == CALL_MAXARGS) {
pop();
- genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
+ genop_1(s, OP_ARYPUSH, cursp());
}
else {
pop_n(callargs);
callargs++;
}
pop();
- idx = new_msym(s, attrsym(s,nsym(tree->car->cdr->cdr->car)));
- genop(s, MKOP_ABC(OP_SEND, cursp(), idx, callargs));
+ idx = new_sym(s, attrsym(s,nsym(tree->car->cdr->cdr->car)));
+ genop_3(s, OP_SEND, cursp(), idx, callargs);
}
}
break;
@@ -1997,7 +2118,7 @@ codegen(codegen_scope *s, node *tree, int val)
s2 = s2->prev;
if (!s2) break;
}
- genop(s, MKOP_ABx(OP_ARGARY, cursp(), (lv & 0xf)));
+ genop_2S(s, OP_ARGARY, cursp(), (lv & 0xf));
push(); push(); /* ARGARY pushes two values */
pop(); pop();
if (tree) {
@@ -2015,12 +2136,12 @@ codegen(codegen_scope *s, node *tree, int val)
pop();
}
else {
- genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ genop_1(s, OP_LOADNIL, cursp());
push(); pop();
}
pop_n(n+1);
if (sendv) n = CALL_MAXARGS;
- genop(s, MKOP_ABC(OP_SUPER, cursp(), 0, n));
+ genop_2(s, OP_SUPER, cursp(), n);
if (val) push();
}
break;
@@ -2037,14 +2158,14 @@ codegen(codegen_scope *s, node *tree, int val)
if (!s2) break;
}
if (s2) ainfo = s2->ainfo;
- genop(s, MKOP_ABx(OP_ARGARY, cursp(), (ainfo<<4)|(lv & 0xf)));
+ genop_2S(s, OP_ARGARY, cursp(), (ainfo<<4)|(lv & 0xf));
push(); push(); pop(); /* ARGARY pushes two values */
if (tree && tree->cdr) {
codegen(s, tree->cdr, VAL);
pop();
}
pop(); pop();
- genop(s, MKOP_ABC(OP_SUPER, cursp(), 0, CALL_MAXARGS));
+ genop_2(s, OP_SUPER, cursp(), CALL_MAXARGS);
if (val) push();
}
break;
@@ -2054,13 +2175,13 @@ codegen(codegen_scope *s, node *tree, int val)
gen_retval(s, tree);
}
else {
- genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ genop_1(s, OP_LOADNIL, cursp());
}
if (s->loop) {
- genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_RETURN));
+ gen_return(s, OP_RETURN_BLK, cursp());
}
else {
- genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
+ gen_return(s, OP_RETURN, cursp());
}
if (val) push();
break;
@@ -2087,9 +2208,9 @@ codegen(codegen_scope *s, node *tree, int val)
}
push();pop(); /* space for a block */
pop_n(n+1);
- genop(s, MKOP_ABx(OP_BLKPUSH, cursp(), (ainfo<<4)|(lv & 0xf)));
+ genop_2S(s, OP_BLKPUSH, cursp(), (ainfo<<4)|(lv & 0xf));
if (sendv) n = CALL_MAXARGS;
- genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "call")), n));
+ genop_3(s, OP_SEND, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "call")), n);
if (val) push();
}
break;
@@ -2105,11 +2226,10 @@ codegen(codegen_scope *s, node *tree, int val)
}
else if (s->loop->type == LOOP_NORMAL) {
if (s->ensure_level > s->loop->ensure_level) {
- genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL);
+ genop_1(s, OP_EPOP, s->ensure_level - s->loop->ensure_level);
}
codegen(s, tree, NOVAL);
- distcheck(s, s->loop->pc1 - s->pc);
- genop(s, MKOP_sBx(OP_JMP, s->loop->pc1 - s->pc));
+ genjmp(s, OP_JMP, s->loop->pc0);
}
else {
if (tree) {
@@ -2117,9 +2237,9 @@ codegen(codegen_scope *s, node *tree, int val)
pop();
}
else {
- genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ genop_1(s, OP_LOADNIL, cursp());
}
- genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
+ gen_return(s, OP_RETURN, cursp());
}
if (val) push();
break;
@@ -2130,10 +2250,9 @@ codegen(codegen_scope *s, node *tree, int val)
}
else {
if (s->ensure_level > s->loop->ensure_level) {
- genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL);
+ genop_1(s, OP_EPOP, s->ensure_level - s->loop->ensure_level);
}
- distcheck(s, s->loop->pc2 - s->pc);
- genop(s, MKOP_sBx(OP_JMP, s->loop->pc2 - s->pc));
+ genjmp(s, OP_JMP, s->loop->pc2);
}
if (val) push();
break;
@@ -2160,13 +2279,12 @@ codegen(codegen_scope *s, node *tree, int val)
}
else {
if (n > 0) {
- genop_peep(s, MKOP_A(OP_POPERR, n), NOVAL);
+ genop_1(s, OP_POPERR, n);
}
if (s->ensure_level > lp->ensure_level) {
- genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - lp->ensure_level), NOVAL);
+ genop_1(s, OP_EPOP, s->ensure_level - lp->ensure_level);
}
- distcheck(s, s->loop->pc1 - s->pc);
- genop(s, MKOP_sBx(OP_JMP, lp->pc1 - s->pc));
+ genjmp(s, OP_JMP, lp->pc0);
}
}
if (val) push();
@@ -2178,7 +2296,8 @@ codegen(codegen_scope *s, node *tree, int val)
int idx = lv_idx(s, nsym(tree));
if (idx > 0) {
- genop_peep(s, MKOP_AB(OP_MOVE, cursp(), idx), NOVAL);
+ gen_move(s, cursp(), idx, val);
+ if (val && on_eval(s)) genop_0(s, OP_NOP);
}
else {
int lv = 0;
@@ -2187,7 +2306,7 @@ codegen(codegen_scope *s, node *tree, int val)
while (up) {
idx = lv_idx(up, nsym(tree));
if (idx > 0) {
- genop_peep(s, MKOP_ABC(OP_GETUPVAR, cursp(), idx, lv), VAL);
+ genop_3(s, OP_GETUPVAR, cursp(), idx, lv);
break;
}
lv++;
@@ -2199,29 +2318,29 @@ codegen(codegen_scope *s, node *tree, int val)
break;
case NODE_GVAR:
- if (val) {
+ {
int sym = new_sym(s, nsym(tree));
- genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
- push();
+ genop_2(s, OP_GETGV, cursp(), sym);
+ if (val) push();
}
break;
case NODE_IVAR:
- if (val) {
+ {
int sym = new_sym(s, nsym(tree));
- genop(s, MKOP_ABx(OP_GETIV, cursp(), sym));
- push();
+ genop_2(s, OP_GETIV, cursp(), sym);
+ if (val) push();
}
break;
case NODE_CVAR:
- if (val) {
+ {
int sym = new_sym(s, nsym(tree));
- genop(s, MKOP_ABx(OP_GETCV, cursp(), sym));
- push();
+ genop_2(s, OP_GETCV, cursp(), sym);
+ if (val) push();
}
break;
@@ -2229,27 +2348,21 @@ codegen(codegen_scope *s, node *tree, int val)
{
int sym = new_sym(s, nsym(tree));
- genop(s, MKOP_ABx(OP_GETCONST, cursp(), sym));
- if (val) {
- push();
- }
+ genop_2(s, OP_GETCONST, cursp(), sym);
+ if (val) push();
}
break;
case NODE_DEFINED:
- codegen(s, tree, VAL);
+ codegen(s, tree, val);
break;
case NODE_BACK_REF:
if (val) {
- char buf[3];
- int sym;
+ char buf[] = {'$', nchar(tree)};
+ int sym = new_sym(s, mrb_intern(s->mrb, buf, sizeof(buf)));
- buf[0] = '$';
- buf[1] = nchar(tree);
- buf[2] = 0;
- sym = new_sym(s, mrb_intern_cstr(s->mrb, buf));
- genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
+ genop_2(s, OP_GETGV, cursp(), sym);
push();
}
break;
@@ -2262,7 +2375,7 @@ codegen(codegen_scope *s, node *tree, int val)
str = mrb_format(mrb, "$%S", mrb_fixnum_value(nint(tree)));
sym = new_sym(s, mrb_intern_str(mrb, str));
- genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
+ genop_2(s, OP_GETGV, cursp(), sym);
push();
}
break;
@@ -2272,7 +2385,7 @@ codegen(codegen_scope *s, node *tree, int val)
break;
case NODE_BLOCK_ARG:
- codegen(s, tree, VAL);
+ codegen(s, tree, val);
break;
case NODE_INT:
@@ -2280,7 +2393,6 @@ codegen(codegen_scope *s, node *tree, int val)
char *p = (char*)tree->car;
int base = nint(tree->cdr->car);
mrb_int i;
- mrb_code co;
mrb_bool overflow;
i = readint_mrb_int(s, p, base, FALSE, &overflow);
@@ -2289,19 +2401,19 @@ codegen(codegen_scope *s, node *tree, int val)
double f = readint_float(s, p, base);
int off = new_lit(s, mrb_float_value(s->mrb, f));
- genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
+ genop_2(s, OP_LOADL, cursp(), off);
}
else
#endif
{
- if (i < MAXARG_sBx && i > -MAXARG_sBx) {
- co = MKOP_AsBx(OP_LOADI, cursp(), i);
- }
+ if (i == -1) genop_1(s, OP_LOADI__1, cursp());
+ else if (i < 0) genop_2(s, OP_LOADINEG, cursp(), (uint16_t)-i);
+ else if (i < 8) genop_1(s, OP_LOADI_0 + (uint8_t)i, cursp());
+ else if (i <= 0xffff) genop_2(s, OP_LOADI, cursp(), (uint16_t)i);
else {
int off = new_lit(s, mrb_fixnum_value(i));
- co = MKOP_ABx(OP_LOADL, cursp(), off);
+ genop_2(s, OP_LOADL, cursp(), off);
}
- genop(s, co);
}
push();
}
@@ -2314,7 +2426,7 @@ codegen(codegen_scope *s, node *tree, int val)
mrb_float f = mrb_float_read(p, NULL);
int off = new_lit(s, mrb_float_value(s->mrb, f));
- genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
+ genop_2(s, OP_LOADL, cursp(), off);
push();
}
break;
@@ -2323,16 +2435,15 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_NEGATE:
{
nt = nint(tree->car);
- tree = tree->cdr;
switch (nt) {
#ifndef MRB_WITHOUT_FLOAT
case NODE_FLOAT:
if (val) {
- char *p = (char*)tree;
+ char *p = (char*)tree->cdr;
mrb_float f = mrb_float_read(p, NULL);
int off = new_lit(s, mrb_float_value(s->mrb, -f));
- genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
+ genop_2(s, OP_LOADL, cursp(), off);
push();
}
break;
@@ -2340,10 +2451,9 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_INT:
if (val) {
- char *p = (char*)tree->car;
- int base = nint(tree->cdr->car);
+ char *p = (char*)tree->cdr->car;
+ int base = nint(tree->cdr->cdr->car);
mrb_int i;
- mrb_code co;
mrb_bool overflow;
i = readint_mrb_int(s, p, base, TRUE, &overflow);
@@ -2352,18 +2462,18 @@ codegen(codegen_scope *s, node *tree, int val)
double f = readint_float(s, p, base);
int off = new_lit(s, mrb_float_value(s->mrb, -f));
- genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
+ genop_2(s, OP_LOADL, cursp(), off);
}
else {
#endif
- if (i < MAXARG_sBx && i > -MAXARG_sBx) {
- co = MKOP_AsBx(OP_LOADI, cursp(), i);
+ if (i == -1) genop_1(s, OP_LOADI__1, cursp());
+ else if (i >= -0xffff) {
+ genop_2(s, OP_LOADINEG, cursp(), (uint16_t)-i);
}
else {
int off = new_lit(s, mrb_fixnum_value(i));
- co = MKOP_ABx(OP_LOADL, cursp(), off);
+ genop_2(s, OP_LOADL, cursp(), off);
}
- genop(s, co);
#ifndef MRB_WITHOUT_FLOAT
}
#endif
@@ -2373,13 +2483,11 @@ codegen(codegen_scope *s, node *tree, int val)
default:
if (val) {
- int sym = new_msym(s, mrb_intern_lit(s->mrb, "-"));
-
- genop(s, MKOP_ABx(OP_LOADI, cursp(), 0));
- push();
+ int sym = new_sym(s, mrb_intern_lit(s->mrb, "-@"));
codegen(s, tree, VAL);
- pop(); pop();
- genop(s, MKOP_ABC(OP_SUB, cursp(), sym, 2));
+ pop();
+ genop_3(s, OP_SEND, cursp(), sym, 0);
+ push();
}
else {
codegen(s, tree, NOVAL);
@@ -2397,7 +2505,7 @@ codegen(codegen_scope *s, node *tree, int val)
int off = new_lit(s, mrb_str_new(s->mrb, p, len));
mrb_gc_arena_restore(s->mrb, ai);
- genop(s, MKOP_ABx(OP_STRING, cursp(), off));
+ genop_2(s, OP_STRING, cursp(), off);
push();
}
break;
@@ -2410,7 +2518,7 @@ codegen(codegen_scope *s, node *tree, int val)
node *n = tree;
if (!n) {
- genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ genop_1(s, OP_LOADNIL, cursp());
push();
break;
}
@@ -2419,7 +2527,7 @@ codegen(codegen_scope *s, node *tree, int val)
while (n) {
codegen(s, n->car, VAL);
pop(); pop();
- genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
+ genop_1(s, OP_STRCAT, cursp());
push();
n = n->cdr;
}
@@ -2450,7 +2558,7 @@ codegen(codegen_scope *s, node *tree, int val)
int ai = mrb_gc_arena_save(s->mrb);
int sym = new_sym(s, mrb_intern_lit(s->mrb, "Kernel"));
- genop(s, MKOP_A(OP_LOADSELF, cursp()));
+ genop_1(s, OP_LOADSELF, cursp());
push();
codegen(s, tree->car, VAL);
n = tree->cdr;
@@ -2461,14 +2569,14 @@ codegen(codegen_scope *s, node *tree, int val)
}
codegen(s, n->car, VAL);
pop(); pop();
- genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
+ genop_1(s, OP_STRCAT, cursp());
push();
n = n->cdr;
}
push(); /* for block */
pop_n(3);
sym = new_sym(s, mrb_intern_lit(s->mrb, "`"));
- genop(s, MKOP_ABC(OP_SEND, cursp(), sym, 1));
+ genop_3(s, OP_SEND, cursp(), sym, 1);
if (val) push();
mrb_gc_arena_restore(s->mrb, ai);
}
@@ -2482,13 +2590,13 @@ codegen(codegen_scope *s, node *tree, int val)
int off = new_lit(s, mrb_str_new(s->mrb, p, len));
int sym;
- genop(s, MKOP_A(OP_LOADSELF, cursp()));
+ genop_1(s, OP_LOADSELF, cursp());
push();
- genop(s, MKOP_ABx(OP_STRING, cursp(), off));
+ genop_2(s, OP_STRING, cursp(), off);
push(); push();
pop_n(3);
sym = new_sym(s, mrb_intern_lit(s->mrb, "`"));
- genop(s, MKOP_ABC(OP_SEND, cursp(), sym, 1));
+ genop_3(s, OP_SEND, cursp(), sym, 1);
if (val) push();
mrb_gc_arena_restore(s->mrb, ai);
}
@@ -2504,24 +2612,24 @@ codegen(codegen_scope *s, node *tree, int val)
int off = new_lit(s, mrb_str_new_cstr(s->mrb, p1));
int argc = 1;
- genop(s, MKOP_A(OP_OCLASS, cursp()));
- genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
+ genop_1(s, OP_OCLASS, cursp());
+ genop_2(s, OP_GETMCNST, cursp(), sym);
push();
- genop(s, MKOP_ABx(OP_STRING, cursp(), off));
+ genop_2(s, OP_STRING, cursp(), off);
push();
if (p2 || p3) {
if (p2) { /* opt */
off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
- genop(s, MKOP_ABx(OP_STRING, cursp(), off));
+ genop_2(s, OP_STRING, cursp(), off);
}
else {
- genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ genop_1(s, OP_LOADNIL, cursp());
}
push();
argc++;
if (p3) { /* enc */
off = new_lit(s, mrb_str_new(s->mrb, p3, 1));
- genop(s, MKOP_ABx(OP_STRING, cursp(), off));
+ genop_2(s, OP_STRING, cursp(), off);
push();
argc++;
}
@@ -2529,7 +2637,7 @@ codegen(codegen_scope *s, node *tree, int val)
push(); /* space for a block */
pop_n(argc+2);
sym = new_sym(s, mrb_intern_lit(s->mrb, "compile"));
- genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc));
+ genop_3(s, OP_SEND, cursp(), sym, argc);
mrb_gc_arena_restore(s->mrb, ai);
push();
}
@@ -2544,15 +2652,15 @@ codegen(codegen_scope *s, node *tree, int val)
int off;
char *p;
- genop(s, MKOP_A(OP_OCLASS, cursp()));
- genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
+ genop_1(s, OP_OCLASS, cursp());
+ genop_2(s, OP_GETMCNST, cursp(), sym);
push();
codegen(s, n->car, VAL);
n = n->cdr;
while (n) {
codegen(s, n->car, VAL);
pop(); pop();
- genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
+ genop_1(s, OP_STRCAT, cursp());
push();
n = n->cdr;
}
@@ -2561,29 +2669,29 @@ codegen(codegen_scope *s, node *tree, int val)
p = (char*)n->car;
off = new_lit(s, mrb_str_new_cstr(s->mrb, p));
codegen(s, tree->car, VAL);
- genop(s, MKOP_ABx(OP_STRING, cursp(), off));
+ genop_2(s, OP_STRING, cursp(), off);
pop();
- genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
+ genop_1(s, OP_STRCAT, cursp());
push();
}
if (n->cdr->car) { /* opt */
char *p2 = (char*)n->cdr->car;
off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
- genop(s, MKOP_ABx(OP_STRING, cursp(), off));
+ genop_2(s, OP_STRING, cursp(), off);
push();
argc++;
}
if (n->cdr->cdr) { /* enc */
char *p2 = (char*)n->cdr->cdr;
off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
- genop(s, MKOP_ABx(OP_STRING, cursp(), off));
+ genop_2(s, OP_STRING, cursp(), off);
push();
argc++;
}
push(); /* space for a block */
pop_n(argc+2);
sym = new_sym(s, mrb_intern_lit(s->mrb, "compile"));
- genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc));
+ genop_3(s, OP_SEND, cursp(), sym, argc);
mrb_gc_arena_restore(s->mrb, ai);
push();
}
@@ -2603,7 +2711,7 @@ codegen(codegen_scope *s, node *tree, int val)
if (val) {
int sym = new_sym(s, nsym(tree));
- genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym));
+ genop_2(s, OP_LOADSYM, cursp(), sym);
push();
}
break;
@@ -2611,55 +2719,46 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_DSYM:
codegen(s, tree, val);
if (val) {
- gen_send_intern(s);
+ gen_intern(s);
}
break;
case NODE_SELF:
if (val) {
- genop(s, MKOP_A(OP_LOADSELF, cursp()));
+ genop_1(s, OP_LOADSELF, cursp());
push();
}
break;
case NODE_NIL:
if (val) {
- genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ genop_1(s, OP_LOADNIL, cursp());
push();
}
break;
case NODE_TRUE:
if (val) {
- genop(s, MKOP_A(OP_LOADT, cursp()));
+ genop_1(s, OP_LOADT, cursp());
push();
}
break;
case NODE_FALSE:
if (val) {
- genop(s, MKOP_A(OP_LOADF, cursp()));
+ genop_1(s, OP_LOADF, cursp());
push();
}
break;
case NODE_ALIAS:
{
- int a = new_msym(s, nsym(tree->car));
- int b = new_msym(s, nsym(tree->cdr));
- int c = new_msym(s, mrb_intern_lit(s->mrb, "alias_method"));
+ int a = new_sym(s, nsym(tree->car));
+ int b = new_sym(s, nsym(tree->cdr));
- genop(s, MKOP_A(OP_TCLASS, cursp()));
- push();
- genop(s, MKOP_ABx(OP_LOADSYM, cursp(), a));
- push();
- genop(s, MKOP_ABx(OP_LOADSYM, cursp(), b));
- push();
- genop(s, MKOP_A(OP_LOADNIL, cursp()));
- push(); /* space for a block */
- pop_n(4);
- genop(s, MKOP_ABC(OP_SEND, cursp(), c, 2));
+ genop_2(s, OP_ALIAS, a, b);
if (val) {
+ genop_1(s, OP_LOADNIL, cursp());
push();
}
}
@@ -2667,41 +2766,15 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_UNDEF:
{
- int undef = new_msym(s, mrb_intern_lit(s->mrb, "undef_method"));
- int num = 0;
node *t = tree;
- genop(s, MKOP_A(OP_TCLASS, cursp()));
- push();
while (t) {
- int symbol;
- if (num >= CALL_MAXARGS - 1) {
- pop_n(num);
- genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), num));
- while (t) {
- symbol = new_msym(s, nsym(t->car));
- push();
- genop(s, MKOP_ABx(OP_LOADSYM, cursp(), symbol));
- pop();
- genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
- t = t->cdr;
- }
- num = CALL_MAXARGS;
- break;
- }
- symbol = new_msym(s, nsym(t->car));
- genop(s, MKOP_ABx(OP_LOADSYM, cursp(), symbol));
- push();
+ int symbol = new_sym(s, nsym(t->car));
+ genop_1(s, OP_UNDEF, symbol);
t = t->cdr;
- num++;
- }
- push();pop(); /* space for a block */
- pop();
- if (num < CALL_MAXARGS) {
- pop_n(num);
}
- genop(s, MKOP_ABC(OP_SEND, cursp(), undef, num));
if (val) {
+ genop_1(s, OP_LOADNIL, cursp());
push();
}
}
@@ -2710,13 +2783,14 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_CLASS:
{
int idx;
+ node *body;
if (tree->car->car == (node*)0) {
- genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ genop_1(s, OP_LOADNIL, cursp());
push();
}
else if (tree->car->car == (node*)1) {
- genop(s, MKOP_A(OP_OCLASS, cursp()));
+ genop_1(s, OP_OCLASS, cursp());
push();
}
else {
@@ -2726,14 +2800,20 @@ codegen(codegen_scope *s, node *tree, int val)
codegen(s, tree->cdr->car, VAL);
}
else {
- genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ genop_1(s, OP_LOADNIL, cursp());
push();
}
pop(); pop();
- idx = new_msym(s, nsym(tree->car->cdr));
- genop(s, MKOP_AB(OP_CLASS, cursp(), idx));
- idx = scope_body(s, tree->cdr->cdr->car, val);
- genop(s, MKOP_ABx(OP_EXEC, cursp(), idx));
+ idx = new_sym(s, nsym(tree->car->cdr));
+ genop_2(s, OP_CLASS, cursp(), idx);
+ body = tree->cdr->cdr->car;
+ if (nint(body->cdr->car) == NODE_BEGIN && body->cdr->cdr == NULL) {
+ genop_1(s, OP_LOADNIL, cursp());
+ }
+ else {
+ idx = scope_body(s, body, val);
+ genop_2(s, OP_EXEC, cursp(), idx);
+ }
if (val) {
push();
}
@@ -2745,21 +2825,27 @@ codegen(codegen_scope *s, node *tree, int val)
int idx;
if (tree->car->car == (node*)0) {
- genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ genop_1(s, OP_LOADNIL, cursp());
push();
}
else if (tree->car->car == (node*)1) {
- genop(s, MKOP_A(OP_OCLASS, cursp()));
+ genop_1(s, OP_OCLASS, cursp());
push();
}
else {
codegen(s, tree->car->car, VAL);
}
pop();
- idx = new_msym(s, nsym(tree->car->cdr));
- genop(s, MKOP_AB(OP_MODULE, cursp(), idx));
- idx = scope_body(s, tree->cdr->car, val);
- genop(s, MKOP_ABx(OP_EXEC, cursp(), idx));
+ idx = new_sym(s, nsym(tree->car->cdr));
+ genop_2(s, OP_MODULE, cursp(), idx);
+ if (nint(tree->cdr->car->cdr->car) == NODE_BEGIN &&
+ tree->cdr->car->cdr->cdr == NULL) {
+ genop_1(s, OP_LOADNIL, cursp());
+ }
+ else {
+ idx = scope_body(s, tree->cdr->car, val);
+ genop_2(s, OP_EXEC, cursp(), idx);
+ }
if (val) {
push();
}
@@ -2772,9 +2858,15 @@ codegen(codegen_scope *s, node *tree, int val)
codegen(s, tree->car, VAL);
pop();
- genop(s, MKOP_AB(OP_SCLASS, cursp(), cursp()));
- idx = scope_body(s, tree->cdr->car, val);
- genop(s, MKOP_ABx(OP_EXEC, cursp(), idx));
+ genop_1(s, OP_SCLASS, cursp());
+ if (nint(tree->cdr->car->cdr->car) == NODE_BEGIN &&
+ tree->cdr->car->cdr->cdr == NULL) {
+ genop_1(s, OP_LOADNIL, cursp());
+ }
+ else {
+ idx = scope_body(s, tree->cdr->car, val);
+ genop_2(s, OP_EXEC, cursp(), idx);
+ }
if (val) {
push();
}
@@ -2783,17 +2875,17 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_DEF:
{
- int sym = new_msym(s, nsym(tree->car));
+ int sym = new_sym(s, nsym(tree->car));
int idx = lambda_body(s, tree->cdr, 0);
- genop(s, MKOP_A(OP_TCLASS, cursp()));
+ genop_1(s, OP_TCLASS, cursp());
push();
- genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_METHOD));
+ genop_2(s, OP_METHOD, cursp(), idx);
push(); pop();
pop();
- genop(s, MKOP_AB(OP_METHOD, cursp(), sym));
+ genop_2(s, OP_DEF, cursp(), sym);
if (val) {
- genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym));
+ genop_2(s, OP_LOADSYM, cursp(), sym);
push();
}
}
@@ -2802,18 +2894,18 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_SDEF:
{
node *recv = tree->car;
- int sym = new_msym(s, nsym(tree->cdr->car));
+ int sym = new_sym(s, nsym(tree->cdr->car));
int idx = lambda_body(s, tree->cdr->cdr, 0);
codegen(s, recv, VAL);
pop();
- genop(s, MKOP_AB(OP_SCLASS, cursp(), cursp()));
+ genop_1(s, OP_SCLASS, cursp());
push();
- genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_METHOD));
+ genop_2(s, OP_METHOD, cursp(), idx);
pop();
- genop(s, MKOP_AB(OP_METHOD, cursp(), sym));
+ genop_2(s, OP_DEF, cursp(), sym);
if (val) {
- genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym));
+ genop_2(s, OP_LOADSYM, cursp(), sym);
push();
}
}
@@ -2875,7 +2967,7 @@ scope_new(mrb_state *mrb, codegen_scope *prev, node *lv)
p->irep->pool = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value)*p->pcapa);
p->irep->plen = 0;
- p->scapa = MAXMSYMLEN;
+ p->scapa = 256;
p->irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*p->scapa);
p->irep->slen = 0;
@@ -2900,18 +2992,16 @@ scope_new(mrb_state *mrb, codegen_scope *prev, node *lv)
}
p->ai = mrb_gc_arena_save(mrb);
- p->filename = prev->filename;
- if (p->filename) {
+ p->filename_sym = prev->filename_sym;
+ if (p->filename_sym) {
p->lines = (uint16_t*)mrb_malloc(mrb, sizeof(short)*p->icapa);
}
p->lineno = prev->lineno;
/* debug setting */
p->debug_start_pos = 0;
- if (p->filename) {
+ if (p->filename_sym) {
mrb_debug_info_alloc(mrb, p->irep);
- p->irep->filename = p->filename;
- p->irep->lines = p->lines;
}
else {
p->irep->debug_info = NULL;
@@ -2929,34 +3019,26 @@ scope_finish(codegen_scope *s)
{
mrb_state *mrb = s->mrb;
mrb_irep *irep = s->irep;
- size_t fname_len;
- char *fname;
+ if (s->nlocals >= 0x3ff) {
+ codegen_error(s, "too many local variables");
+ }
irep->flags = 0;
if (s->iseq) {
irep->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc);
irep->ilen = s->pc;
- if (s->lines) {
- irep->lines = (uint16_t *)codegen_realloc(s, s->lines, sizeof(uint16_t)*s->pc);
- }
- else {
- irep->lines = 0;
- }
}
irep->pool = (mrb_value*)codegen_realloc(s, irep->pool, sizeof(mrb_value)*irep->plen);
irep->syms = (mrb_sym*)codegen_realloc(s, irep->syms, sizeof(mrb_sym)*irep->slen);
irep->reps = (mrb_irep**)codegen_realloc(s, irep->reps, sizeof(mrb_irep*)*irep->rlen);
- if (s->filename) {
- irep->filename = mrb_parser_get_filename(s->parser, s->filename_index);
- mrb_debug_info_append_file(mrb, irep, s->debug_start_pos, s->pc);
+ if (s->filename_sym) {
+ mrb_sym fname = mrb_parser_get_filename(s->parser, s->filename_index);
+ const char *filename = mrb_sym2name_len(s->mrb, fname, NULL);
- fname_len = strlen(s->filename);
- fname = (char*)codegen_malloc(s, fname_len + 1);
- memcpy(fname, s->filename, fname_len);
- fname[fname_len] = '\0';
- irep->filename = fname;
- irep->own_filename = TRUE;
+ mrb_debug_info_append_file(s->mrb, s->irep->debug_info,
+ filename, s->lines, s->debug_start_pos, s->pc);
}
+ mrb_free(s->mrb, s->lines);
irep->nlocals = s->nlocals;
irep->nregs = s->nregs;
@@ -2971,7 +3053,7 @@ loop_push(codegen_scope *s, enum looptype t)
struct loopinfo *p = (struct loopinfo *)codegen_palloc(s, sizeof(struct loopinfo));
p->type = t;
- p->pc1 = p->pc2 = p->pc3 = 0;
+ p->pc0 = p->pc1 = p->pc2 = p->pc3 = 0;
p->prev = s->loop;
p->ensure_level = s->ensure_level;
p->acc = cursp();
@@ -3013,27 +3095,26 @@ loop_break(codegen_scope *s, node *tree)
return;
}
if (n > 0) {
- genop_peep(s, MKOP_A(OP_POPERR, n), NOVAL);
+ genop_1(s, OP_POPERR, n);
}
if (loop->type == LOOP_NORMAL) {
int tmp;
if (s->ensure_level > s->loop->ensure_level) {
- genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL);
+ genop_1(s, OP_EPOP, s->ensure_level - s->loop->ensure_level);
}
if (tree) {
- genop_peep(s, MKOP_AB(OP_MOVE, loop->acc, cursp()), NOVAL);
+ gen_move(s, loop->acc, cursp(), 0);
}
- distcheck(s, s->loop->pc3);
- tmp = genop(s, MKOP_sBx(OP_JMP, loop->pc3));
+ tmp = genjmp(s, OP_JMP, loop->pc3);
loop->pc3 = tmp;
}
else {
if (!tree) {
- genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ genop_1(s, OP_LOADNIL, cursp());
}
- genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_BREAK));
+ gen_return(s, OP_BREAK, cursp());
}
}
}
@@ -3042,7 +3123,7 @@ static void
loop_pop(codegen_scope *s, int val)
{
if (val) {
- genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ genop_1(s, OP_LOADNIL, cursp());
}
dispatch_linked(s, s->loop->pc3);
s->loop = s->loop->prev;
@@ -3061,11 +3142,11 @@ generate_code(mrb_state *mrb, parser_state *p, int val)
}
scope->mrb = mrb;
scope->parser = p;
- scope->filename = p->filename;
+ scope->filename_sym = p->filename_sym;
scope->filename_index = p->current_filename_index;
MRB_TRY(&scope->jmp) {
- mrb->jmp = &scope->jmp;
+ mrb->jmp = &scope->jmp;
/* prepare irep */
codegen(scope, p->tree, val);
proc = mrb_proc_new(mrb, scope->irep);
@@ -3092,3 +3173,71 @@ mrb_generate_code(mrb_state *mrb, parser_state *p)
{
return generate_code(mrb, p, VAL);
}
+
+void
+mrb_irep_remove_lv(mrb_state *mrb, mrb_irep *irep)
+{
+ int i;
+
+ if (irep->lv) {
+ mrb_free(mrb, irep->lv);
+ irep->lv = NULL;
+ }
+
+ for (i = 0; i < irep->rlen; ++i) {
+ mrb_irep_remove_lv(mrb, irep->reps[i]);
+ }
+}
+
+#undef OPCODE
+#define Z 1
+#define S 3
+#define W 4
+/* instruction sizes */
+uint8_t mrb_insn_size[] = {
+#define B 2
+#define BB 3
+#define BBB 4
+#define BS 4
+#define SB 4
+#define OPCODE(_,x) x,
+#include "mruby/ops.h"
+#undef OPCODE
+#undef B
+#undef BB
+#undef BS
+#undef SB
+#undef BBB
+};
+/* EXT1 instruction sizes */
+uint8_t mrb_insn_size1[] = {
+#define B 3
+#define BB 4
+#define BBB 5
+#define BS 5
+#define SB 5
+#define OPCODE(_,x) x,
+#include "mruby/ops.h"
+#undef OPCODE
+#undef B
+};
+/* EXT2 instruction sizes */
+uint8_t mrb_insn_size2[] = {
+#define B 2
+#define OPCODE(_,x) x,
+#include "mruby/ops.h"
+#undef OPCODE
+#undef BB
+#undef BBB
+#undef BS
+#undef SB
+};
+/* EXT3 instruction sizes */
+#define BB 5
+#define BBB 6
+#define BS 4
+#define SB 5
+uint8_t mrb_insn_size3[] = {
+#define OPCODE(_,x) x,
+#include "mruby/ops.h"
+};
diff --git a/mrbgems/mruby-compiler/core/node.h b/mrbgems/mruby-compiler/core/node.h
index 9636dd759..219bddab0 100644
--- a/mrbgems/mruby-compiler/core/node.h
+++ b/mrbgems/mruby-compiler/core/node.h
@@ -9,14 +9,11 @@
enum node_type {
NODE_METHOD,
- NODE_FBODY,
- NODE_CFUNC,
NODE_SCOPE,
NODE_BLOCK,
NODE_IF,
NODE_CASE,
NODE_WHEN,
- NODE_OPT_N,
NODE_WHILE,
NODE_UNTIL,
NODE_ITER,
@@ -40,12 +37,12 @@ enum node_type {
NODE_CALL,
NODE_SCALL,
NODE_FCALL,
- NODE_VCALL,
NODE_SUPER,
NODE_ZSUPER,
NODE_ARRAY,
NODE_ZARRAY,
NODE_HASH,
+ NODE_KW_HASH,
NODE_RETURN,
NODE_YIELD,
NODE_LVAR,
@@ -57,8 +54,6 @@ enum node_type {
NODE_NTH_REF,
NODE_BACK_REF,
NODE_MATCH,
- NODE_MATCH2,
- NODE_MATCH3,
NODE_INT,
NODE_FLOAT,
NODE_NEGATE,
@@ -71,10 +66,10 @@ enum node_type {
NODE_REGX,
NODE_DREGX,
NODE_DREGX_ONCE,
- NODE_LIST,
NODE_ARG,
- NODE_ARGSCAT,
- NODE_ARGSPUSH,
+ NODE_ARGS_TAIL,
+ NODE_KW_ARG,
+ NODE_KW_REST_ARGS,
NODE_SPLAT,
NODE_TO_ARY,
NODE_SVALUE,
@@ -88,26 +83,15 @@ enum node_type {
NODE_SCLASS,
NODE_COLON2,
NODE_COLON3,
- NODE_CREF,
NODE_DOT2,
NODE_DOT3,
- NODE_FLIP2,
- NODE_FLIP3,
- NODE_ATTRSET,
NODE_SELF,
NODE_NIL,
NODE_TRUE,
NODE_FALSE,
NODE_DEFINED,
- NODE_NEWLINE,
NODE_POSTEXE,
- NODE_ALLOCA,
- NODE_DMETHOD,
- NODE_BMETHOD,
- NODE_MEMO,
- NODE_IFUNC,
NODE_DSYM,
- NODE_ATTRASGN,
NODE_HEREDOC,
NODE_LITERAL_DELIM,
NODE_WORDS,
diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y
index 7f848b4df..ac59a8b0b 100644
--- a/mrbgems/mruby-compiler/core/parse.y
+++ b/mrbgems/mruby-compiler/core/parse.y
@@ -10,13 +10,7 @@
# define YYDEBUG 1
#endif
#define YYERROR_VERBOSE 1
-/*
- * Force yacc to use our memory management. This is a little evil because
- * the macros assume that "parser_state *p" is in scope
- */
-#define YYMALLOC(n) mrb_malloc(p->mrb, (n))
-#define YYFREE(o) mrb_free(p->mrb, (o))
-#define YYSTACK_USE_ALLOCA 0
+#define YYSTACK_USE_ALLOCA 1
#include <ctype.h>
#include <errno.h>
@@ -76,6 +70,24 @@ typedef unsigned int stack_type;
#define nint(x) ((node*)(intptr_t)(x))
#define intn(x) ((int)(intptr_t)(x))
+#if defined(MRB_COMPLEX_NUMBERS) || defined(MRB_RATIONAL_NUMBERS)
+ #define MRB_SUFFIX_SUPPORT
+
+ #ifdef MRB_RATIONAL_NUMBERS
+ #define NUM_SUFFIX_R (1<<0)
+ #else
+ #define NUM_SUFFIX_R 0
+ #endif
+
+ #ifdef MRB_COMPLEX_NUMBERS
+ #define NUM_SUFFIX_I (1<<1)
+ #else
+ #define NUM_SUFFIX_I 0
+ #endif
+
+ #define NUM_SUFFIX_ALL (NUM_SUFFIX_R | NUM_SUFFIX_I)
+#endif
+
static inline mrb_sym
intern_cstr_gen(parser_state *p, const char *s)
{
@@ -133,6 +145,10 @@ cons_gen(parser_state *p, node *car, node *cdr)
c->cdr = cdr;
c->lineno = p->lineno;
c->filename_index = p->current_filename_index;
+ /* beginning of next partial file; need to point the previous file */
+ if (p->lineno == 0 && p->current_filename_index > 0) {
+ c->filename_index-- ;
+ }
return c;
}
#define cons(a,b) cons_gen(p,(a),(b))
@@ -216,6 +232,26 @@ parser_strdup(parser_state *p, const char *s)
#undef strdup
#define strdup(s) parser_strdup(p, s)
+static void
+dump_int(uint16_t i, char *s)
+{
+ char *p = s;
+ char *t = s;
+
+ while (i > 0) {
+ *p++ = (i % 10)+'0';
+ i /= 10;
+ }
+ if (p == s) *p++ = '0';
+ *p = 0;
+ p--; /* point the last char */
+ while (t < p) {
+ char c = *t;
+ *t++ = *p;
+ *p-- = c;
+ }
+}
+
/* xxx ----------------------------- */
static node*
@@ -279,6 +315,20 @@ local_add(parser_state *p, mrb_sym sym)
}
}
+static void
+local_add_blk(parser_state *p, mrb_sym blk)
+{
+ /* allocate register for block */
+ local_add_f(p, blk ? blk : mrb_intern_lit(p->mrb, "&"));
+}
+
+static void
+local_add_kw(parser_state *p, mrb_sym kwd)
+{
+ /* allocate register for keywords hash */
+ local_add_f(p, kwd ? kwd : mrb_intern_lit(p->mrb, "**"));
+}
+
static node*
locals_node(parser_state *p)
{
@@ -568,6 +618,13 @@ new_hash(parser_state *p, node *a)
return cons((node*)NODE_HASH, a);
}
+/* (:kw_hash (k . v) (k . v)...) */
+static node*
+new_kw_hash(parser_state *p, node *a)
+{
+ return cons((node*)NODE_KW_HASH, a);
+}
+
/* (:sym . a) */
static node*
new_sym(parser_state *p, mrb_sym sym)
@@ -671,23 +728,80 @@ new_arg(parser_state *p, mrb_sym sym)
return cons((node*)NODE_ARG, nsym(sym));
}
-/* (m o r m2 b) */
+static void
+local_add_margs(parser_state *p, node *n)
+{
+ while (n) {
+ if (n->car->car == (node*)NODE_MASGN) {
+ node *t = n->car->cdr->cdr;
+
+ n->car->cdr->cdr = NULL;
+ while (t) {
+ local_add_f(p, sym(t->car));
+ t = t->cdr;
+ }
+ local_add_margs(p, n->car->cdr->car->car);
+ local_add_margs(p, n->car->cdr->car->cdr->cdr->car);
+ }
+ n = n->cdr;
+ }
+}
+
+/* (m o r m2 tail) */
/* m: (a b c) */
/* o: ((a . e1) (b . e2)) */
/* r: a */
/* m2: (a b c) */
/* b: a */
static node*
-new_args(parser_state *p, node *m, node *opt, mrb_sym rest, node *m2, mrb_sym blk)
+new_args(parser_state *p, node *m, node *opt, mrb_sym rest, node *m2, node *tail)
{
node *n;
- n = cons(m2, nsym(blk));
+ local_add_margs(p, m);
+ local_add_margs(p, m2);
+ n = cons(m2, tail);
n = cons(nsym(rest), n);
n = cons(opt, n);
return cons(m, n);
}
+/* (:args_tail keywords rest_keywords_sym block_sym) */
+static node*
+new_args_tail(parser_state *p, node *kws, node *kwrest, mrb_sym blk)
+{
+ node *k;
+
+ if (kws || kwrest) {
+ local_add_kw(p, (kwrest && kwrest->cdr)? sym(kwrest->cdr) : 0);
+ }
+
+ local_add_blk(p, blk);
+
+ // allocate register for keywords arguments
+ // order is for Proc#parameters
+ for (k = kws; k; k = k->cdr) {
+ if (!k->car->cdr->cdr->car) { // allocate required keywords
+ local_add_f(p, sym(k->car->cdr->car));
+ }
+ }
+ for (k = kws; k; k = k->cdr) {
+ if (k->car->cdr->cdr->car) { // allocate keywords with default
+ local_add_f(p, sym(k->car->cdr->car));
+ }
+ }
+
+ return list4((node*)NODE_ARGS_TAIL, kws, kwrest, nsym(blk));
+}
+
+/* (:kw_arg kw_sym def_arg) */
+static node*
+new_kw_arg(parser_state *p, mrb_sym kw, node *def_arg)
+{
+ mrb_assert(kw);
+ return list3((node*)NODE_KW_ARG, nsym(kw), def_arg);
+}
+
/* (:block_arg . a) */
static node*
new_block_arg(parser_state *p, node *a)
@@ -725,6 +839,13 @@ new_masgn(parser_state *p, node *a, node *b)
return cons((node*)NODE_MASGN, cons(a, b));
}
+/* (:masgn mlhs mrhs) no check */
+static node*
+new_masgn_param(parser_state *p, node *a, node *b)
+{
+ return cons((node*)NODE_MASGN, cons(a, b));
+}
+
/* (:asgn lhs rhs) */
static node*
new_op_asgn(parser_state *p, node *a, mrb_sym op, node *b)
@@ -733,19 +854,57 @@ new_op_asgn(parser_state *p, node *a, mrb_sym op, node *b)
return list4((node*)NODE_OP_ASGN, a, nsym(op), b);
}
+#ifdef MRB_COMPLEX_NUMBERS
+static node*
+new_imaginary(parser_state *p, node *imaginary)
+{
+ return new_call(p, new_const(p, intern_cstr("Kernel")), intern_cstr("Complex"), list1(list2(list3((node*)NODE_INT, (node*)strdup("0"), nint(10)), imaginary)), 1);
+}
+#endif
+
+#ifdef MRB_RATIONAL_NUMBERS
+static node*
+new_rational(parser_state *p, node *rational)
+{
+ return new_call(p, new_const(p, intern_cstr("Kernel")), intern_cstr("Rational"), list1(list1(rational)), 1);
+}
+#endif
+
/* (:int . i) */
static node*
-new_int(parser_state *p, const char *s, int base)
+new_int(parser_state *p, const char *s, int base, int suffix)
{
- return list3((node*)NODE_INT, (node*)strdup(s), nint(base));
+ node* result = list3((node*)NODE_INT, (node*)strdup(s), nint(base));
+#ifdef MRB_RATIONAL_NUMBERS
+ if (suffix & NUM_SUFFIX_R) {
+ result = new_rational(p, result);
+ }
+#endif
+#ifdef MRB_COMPLEX_NUMBERS
+ if (suffix & NUM_SUFFIX_I) {
+ result = new_imaginary(p, result);
+ }
+#endif
+ return result;
}
#ifndef MRB_WITHOUT_FLOAT
/* (:float . i) */
static node*
-new_float(parser_state *p, const char *s)
+new_float(parser_state *p, const char *s, int suffix)
{
- return cons((node*)NODE_FLOAT, (node*)strdup(s));
+ node* result = cons((node*)NODE_FLOAT, (node*)strdup(s));
+#ifdef MRB_RATIONAL_NUMBERS
+ if (suffix & NUM_SUFFIX_R) {
+ result = new_rational(p, result);
+ }
+#endif
+#ifdef MRB_COMPLEX_NUMBERS
+ if (suffix & NUM_SUFFIX_I) {
+ result = new_imaginary(p, result);
+ }
+#endif
+ return result;
}
#endif
@@ -763,6 +922,86 @@ new_dstr(parser_state *p, node *a)
return cons((node*)NODE_DSTR, a);
}
+static int
+string_node_p(node *n)
+{
+ return (int)((enum node_type)(intptr_t)n->car == NODE_STR);
+}
+
+static node*
+composite_string_node(parser_state *p, node *a, node *b)
+{
+ size_t newlen = (size_t)a->cdr + (size_t)b->cdr;
+ char *str = (char*)mrb_pool_realloc(p->pool, a->car, (size_t)a->cdr + 1, newlen + 1);
+ memcpy(str + (size_t)a->cdr, b->car, (size_t)b->cdr);
+ str[newlen] = '\0';
+ a->car = (node*)str;
+ a->cdr = (node*)newlen;
+ cons_free(b);
+ return a;
+}
+
+static node*
+concat_string(parser_state *p, node *a, node *b)
+{
+ if (string_node_p(a)) {
+ if (string_node_p(b)) {
+ /* a == NODE_STR && b == NODE_STR */
+ composite_string_node(p, a->cdr, b->cdr);
+ cons_free(b);
+ return a;
+ }
+ else {
+ /* a == NODE_STR && b == NODE_DSTR */
+
+ if (string_node_p(b->cdr->car)) {
+ /* a == NODE_STR && b->[NODE_STR, ...] */
+ composite_string_node(p, a->cdr, b->cdr->car->cdr);
+ cons_free(b->cdr->car);
+ b->cdr->car = a;
+ return b;
+ }
+ }
+ }
+ else {
+ node *c; /* last node of a */
+ for (c = a; c->cdr != NULL; c = c->cdr) ;
+
+ if (string_node_p(b)) {
+ /* a == NODE_DSTR && b == NODE_STR */
+ if (string_node_p(c->car)) {
+ /* a->[..., NODE_STR] && b == NODE_STR */
+ composite_string_node(p, c->car->cdr, b->cdr);
+ cons_free(b);
+ return a;
+ }
+
+ push(a, b);
+ return a;
+ }
+ else {
+ /* a == NODE_DSTR && b == NODE_DSTR */
+ if (string_node_p(c->car) && string_node_p(b->cdr->car)) {
+ /* a->[..., NODE_STR] && b->[NODE_STR, ...] */
+ node *d = b->cdr;
+ cons_free(b);
+ composite_string_node(p, c->car->cdr, d->car->cdr);
+ cons_free(d->car);
+ c->cdr = d->cdr;
+ cons_free(d);
+ return a;
+ }
+ else {
+ c->cdr = b->cdr;
+ cons_free(b);
+ return a;
+ }
+ }
+ }
+
+ return new_dstr(p, list2(a, b));
+}
+
/* (:str . (s . len)) */
static node*
new_xstr(parser_state *p, const char *s, int len)
@@ -1029,7 +1268,6 @@ heredoc_end(parser_state *p)
end_strterm(p);
p->lex_strterm = p->lex_strterm_before_heredoc;
p->lex_strterm_before_heredoc = NULL;
- p->heredoc_end_now = TRUE;
}
else {
/* next heredoc */
@@ -1112,7 +1350,7 @@ heredoc_end(parser_state *p)
%token <nd> tNTH_REF tBACK_REF
%token <num> tREGEXP_END
-%type <nd> singleton string string_rep string_interp xstring regexp
+%type <nd> singleton string string_fragment string_rep string_interp xstring regexp
%type <nd> literal numeric cpath symbol
%type <nd> top_compstmt top_stmts top_stmt
%type <nd> bodystmt compstmt stmts stmt expr arg primary command command_call method_call
@@ -1123,7 +1361,7 @@ heredoc_end(parser_state *p)
%type <nd> command_args aref_args opt_block_arg block_arg var_ref var_lhs
%type <nd> command_asgn command_rhs mrhs superclass block_call block_command
%type <nd> f_block_optarg f_block_opt
-%type <nd> f_arglist f_args f_arg f_arg_item f_optarg f_marg f_marg_list f_margs
+%type <nd> f_arglist f_args f_arg f_arg_item f_optarg f_margs
%type <nd> assoc_list assocs assoc undef_list backref for_var
%type <nd> block_param opt_block_param block_param_def f_opt
%type <nd> bv_decls opt_bv_decl bvar f_larglist lambda_body
@@ -1134,6 +1372,10 @@ heredoc_end(parser_state *p)
%type <nd> heredoc words symbols
%type <num> call_op call_op2 /* 0:'&.', 1:'.', 2:'::' */
+%type <nd> args_tail opt_args_tail f_kwarg f_kw f_kwrest
+%type <nd> f_block_kwarg f_block_kw block_args_tail opt_block_args_tail
+%type <id> f_label
+
%token tUPLUS /* unary+ */
%token tUMINUS /* unary- */
%token tPOW /* ** */
@@ -1159,6 +1401,7 @@ heredoc_end(parser_state *p)
%token tLBRACE /* { */
%token tLBRACE_ARG /* { */
%token tSTAR /* * */
+%token tDSTAR /* ** */
%token tAMPER /* & */
%token tLAMBDA /* -> */
%token tANDDOT /* &. */
@@ -1736,6 +1979,7 @@ op : '|' { $$ = intern_c('|'); }
| '/' { $$ = intern_c('/'); }
| '%' { $$ = intern_c('%'); }
| tPOW { $$ = intern("**",2); }
+ | tDSTAR { $$ = intern("**",2); }
| '!' { $$ = intern_c('!'); }
| '~' { $$ = intern_c('~'); }
| tUPLUS { $$ = intern("+@",2); }
@@ -1944,11 +2188,11 @@ aref_args : none
}
| args comma assocs trailer
{
- $$ = push($1, new_hash(p, $3));
+ $$ = push($1, new_kw_hash(p, $3));
}
| assocs trailer
{
- $$ = cons(new_hash(p, $1), 0);
+ $$ = cons(new_kw_hash(p, $1), 0);
NODE_LINENO($$, $1);
}
;
@@ -1984,12 +2228,12 @@ opt_call_args : none
}
| args comma assocs ','
{
- $$ = cons(push($1, new_hash(p, $3)), 0);
+ $$ = cons(push($1, new_kw_hash(p, $3)), 0);
NODE_LINENO($$, $1);
}
| assocs ','
{
- $$ = cons(list1(new_hash(p, $1)), 0);
+ $$ = cons(list1(new_kw_hash(p, $1)), 0);
NODE_LINENO($$, $1);
}
;
@@ -2007,12 +2251,12 @@ call_args : command
}
| assocs opt_block_arg
{
- $$ = cons(list1(new_hash(p, $1)), $2);
+ $$ = cons(list1(new_kw_hash(p, $1)), $2);
NODE_LINENO($$, $1);
}
| args comma assocs opt_block_arg
{
- $$ = cons(push($1, new_hash(p, $3)), $4);
+ $$ = cons(push($1, new_kw_hash(p, $3)), $4);
NODE_LINENO($$, $1);
}
| block_arg
@@ -2393,43 +2637,24 @@ for_var : lhs
| mlhs
;
-f_marg : f_norm_arg
- {
- $$ = new_arg(p, $1);
- }
- | tLPAREN f_margs rparen
- {
- $$ = new_masgn(p, $2, 0);
- }
- ;
-
-f_marg_list : f_marg
- {
- $$ = list1($1);
- }
- | f_marg_list ',' f_marg
- {
- $$ = push($1, $3);
- }
- ;
-
-f_margs : f_marg_list
+f_margs : f_arg
{
$$ = list3($1,0,0);
}
- | f_marg_list ',' tSTAR f_norm_arg
+ | f_arg ',' tSTAR f_norm_arg
{
$$ = list3($1, new_arg(p, $4), 0);
}
- | f_marg_list ',' tSTAR f_norm_arg ',' f_marg_list
+ | f_arg ',' tSTAR f_norm_arg ',' f_arg
{
$$ = list3($1, new_arg(p, $4), $6);
}
- | f_marg_list ',' tSTAR
+ | f_arg ',' tSTAR
{
+ local_add_f(p, 0);
$$ = list3($1, (node*)-1, 0);
}
- | f_marg_list ',' tSTAR ',' f_marg_list
+ | f_arg ',' tSTAR ',' f_arg
{
$$ = list3($1, (node*)-1, $5);
}
@@ -2437,96 +2662,134 @@ f_margs : f_marg_list
{
$$ = list3(0, new_arg(p, $2), 0);
}
- | tSTAR f_norm_arg ',' f_marg_list
+ | tSTAR f_norm_arg ',' f_arg
{
$$ = list3(0, new_arg(p, $2), $4);
}
| tSTAR
{
+ local_add_f(p, 0);
$$ = list3(0, (node*)-1, 0);
}
- | tSTAR ',' f_marg_list
+ | tSTAR ','
{
- $$ = list3(0, (node*)-1, $3);
+ local_add_f(p, 0);
+ }
+ f_arg
+ {
+ $$ = list3(0, (node*)-1, $4);
}
;
-block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_f_block_arg
+block_args_tail : f_block_kwarg ',' f_kwrest opt_f_block_arg
+ {
+ $$ = new_args_tail(p, $1, $3, $4);
+ }
+ | f_block_kwarg opt_f_block_arg
+ {
+ $$ = new_args_tail(p, $1, 0, $2);
+ }
+ | f_kwrest opt_f_block_arg
+ {
+ $$ = new_args_tail(p, 0, $1, $2);
+ }
+ | f_block_arg
+ {
+ $$ = new_args_tail(p, 0, 0, $1);
+ }
+ ;
+
+opt_block_args_tail : ',' block_args_tail
+ {
+ $$ = $2;
+ }
+ | /* none */
+ {
+ $$ = new_args_tail(p, 0, 0, 0);
+ }
+ ;
+
+block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_block_args_tail
{
$$ = new_args(p, $1, $3, $5, 0, $6);
}
- | f_arg ',' f_block_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
+ | f_arg ',' f_block_optarg ',' f_rest_arg ',' f_arg opt_block_args_tail
{
$$ = new_args(p, $1, $3, $5, $7, $8);
}
- | f_arg ',' f_block_optarg opt_f_block_arg
+ | f_arg ',' f_block_optarg opt_block_args_tail
{
$$ = new_args(p, $1, $3, 0, 0, $4);
}
- | f_arg ',' f_block_optarg ',' f_arg opt_f_block_arg
+ | f_arg ',' f_block_optarg ',' f_arg opt_block_args_tail
{
$$ = new_args(p, $1, $3, 0, $5, $6);
}
- | f_arg ',' f_rest_arg opt_f_block_arg
+ | f_arg ',' f_rest_arg opt_block_args_tail
{
$$ = new_args(p, $1, 0, $3, 0, $4);
}
- | f_arg ','
+ | f_arg ',' opt_block_args_tail
{
- $$ = new_args(p, $1, 0, 0, 0, 0);
+ $$ = new_args(p, $1, 0, 0, 0, $3);
}
- | f_arg ',' f_rest_arg ',' f_arg opt_f_block_arg
+ | f_arg ',' f_rest_arg ',' f_arg opt_block_args_tail
{
$$ = new_args(p, $1, 0, $3, $5, $6);
}
- | f_arg opt_f_block_arg
+ | f_arg opt_block_args_tail
{
$$ = new_args(p, $1, 0, 0, 0, $2);
}
- | f_block_optarg ',' f_rest_arg opt_f_block_arg
+ | f_block_optarg ',' f_rest_arg opt_block_args_tail
{
$$ = new_args(p, 0, $1, $3, 0, $4);
}
- | f_block_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
+ | f_block_optarg ',' f_rest_arg ',' f_arg opt_block_args_tail
{
$$ = new_args(p, 0, $1, $3, $5, $6);
}
- | f_block_optarg opt_f_block_arg
+ | f_block_optarg opt_block_args_tail
{
$$ = new_args(p, 0, $1, 0, 0, $2);
}
- | f_block_optarg ',' f_arg opt_f_block_arg
+ | f_block_optarg ',' f_arg opt_block_args_tail
{
$$ = new_args(p, 0, $1, 0, $3, $4);
}
- | f_rest_arg opt_f_block_arg
+ | f_rest_arg opt_block_args_tail
{
$$ = new_args(p, 0, 0, $1, 0, $2);
}
- | f_rest_arg ',' f_arg opt_f_block_arg
+ | f_rest_arg ',' f_arg opt_block_args_tail
{
$$ = new_args(p, 0, 0, $1, $3, $4);
}
- | f_block_arg
+ | block_args_tail
{
$$ = new_args(p, 0, 0, 0, 0, $1);
}
;
opt_block_param : none
- | block_param_def
{
+ local_add_blk(p, 0);
+ $$ = 0;
+ }
+ | block_param_def
+ {
p->cmd_start = TRUE;
$$ = $1;
}
;
-block_param_def : '|' opt_bv_decl '|'
+block_param_def : '|' {local_add_blk(p, 0);} opt_bv_decl '|'
{
$$ = 0;
}
| tOROP
{
+ local_add_blk(p, 0);
$$ = 0;
}
| '|' block_param opt_bv_decl '|'
@@ -2739,7 +3002,14 @@ literal : numeric
| symbols
;
-string : tCHAR
+string : string_fragment
+ | string string_fragment
+ {
+ $$ = concat_string(p, $1, $2);
+ }
+ ;
+
+string_fragment : tCHAR
| tSTRING
| tSTRING_BEG tSTRING
{
@@ -2961,7 +3231,7 @@ var_ref : variable
}
| keyword__FILE__
{
- const char *fn = p->filename;
+ const char *fn = mrb_sym2name_len(p->mrb, p->filename_sym, NULL);
if (!fn) {
fn = "(null)";
}
@@ -2971,8 +3241,8 @@ var_ref : variable
{
char buf[16];
- snprintf(buf, sizeof(buf), "%d", p->lineno);
- $$ = new_int(p, buf, 10);
+ dump_int(p->lineno, buf);
+ $$ = new_int(p, buf, 10, 0);
}
| keyword__ENCODING__
{
@@ -3021,65 +3291,151 @@ f_arglist : '(' f_args rparen
}
;
-f_args : f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg
+f_label : tIDENTIFIER tLABEL_TAG
+ ;
+
+f_kw : f_label arg
+ {
+ void_expr_error(p, $2);
+ $$ = new_kw_arg(p, $1, $2);
+ }
+ | f_label
+ {
+ $$ = new_kw_arg(p, $1, 0);
+ }
+ ;
+
+f_block_kw : f_label primary_value
+ {
+ $$ = new_kw_arg(p, $1, $2);
+ }
+ | f_label
+ {
+ $$ = new_kw_arg(p, $1, 0);
+ }
+ ;
+
+f_block_kwarg : f_block_kw
+ {
+ $$ = list1($1);
+ }
+ | f_block_kwarg ',' f_block_kw
+ {
+ $$ = push($1, $3);
+ }
+ ;
+
+f_kwarg : f_kw
+ {
+ $$ = list1($1);
+ }
+ | f_kwarg ',' f_kw
+ {
+ $$ = push($1, $3);
+ }
+ ;
+
+kwrest_mark : tPOW
+ | tDSTAR
+ ;
+
+f_kwrest : kwrest_mark tIDENTIFIER
+ {
+ $$ = cons((node*)NODE_KW_REST_ARGS, nsym($2));
+ }
+ | kwrest_mark
+ {
+ $$ = cons((node*)NODE_KW_REST_ARGS, 0);
+ }
+ ;
+
+args_tail : f_kwarg ',' f_kwrest opt_f_block_arg
+ {
+ $$ = new_args_tail(p, $1, $3, $4);
+ }
+ | f_kwarg opt_f_block_arg
+ {
+ $$ = new_args_tail(p, $1, 0, $2);
+ }
+ | f_kwrest opt_f_block_arg
+ {
+ $$ = new_args_tail(p, 0, $1, $2);
+ }
+ | f_block_arg
+ {
+ $$ = new_args_tail(p, 0, 0, $1);
+ }
+ ;
+
+opt_args_tail : ',' args_tail
+ {
+ $$ = $2;
+ }
+ | /* none */
+ {
+ $$ = new_args_tail(p, 0, 0, 0);
+ }
+ ;
+
+f_args : f_arg ',' f_optarg ',' f_rest_arg opt_args_tail
{
$$ = new_args(p, $1, $3, $5, 0, $6);
}
- | f_arg ',' f_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
+ | f_arg ',' f_optarg ',' f_rest_arg ',' f_arg opt_args_tail
{
$$ = new_args(p, $1, $3, $5, $7, $8);
}
- | f_arg ',' f_optarg opt_f_block_arg
+ | f_arg ',' f_optarg opt_args_tail
{
$$ = new_args(p, $1, $3, 0, 0, $4);
}
- | f_arg ',' f_optarg ',' f_arg opt_f_block_arg
+ | f_arg ',' f_optarg ',' f_arg opt_args_tail
{
$$ = new_args(p, $1, $3, 0, $5, $6);
}
- | f_arg ',' f_rest_arg opt_f_block_arg
+ | f_arg ',' f_rest_arg opt_args_tail
{
$$ = new_args(p, $1, 0, $3, 0, $4);
}
- | f_arg ',' f_rest_arg ',' f_arg opt_f_block_arg
+ | f_arg ',' f_rest_arg ',' f_arg opt_args_tail
{
$$ = new_args(p, $1, 0, $3, $5, $6);
}
- | f_arg opt_f_block_arg
+ | f_arg opt_args_tail
{
$$ = new_args(p, $1, 0, 0, 0, $2);
}
- | f_optarg ',' f_rest_arg opt_f_block_arg
+ | f_optarg ',' f_rest_arg opt_args_tail
{
$$ = new_args(p, 0, $1, $3, 0, $4);
}
- | f_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
+ | f_optarg ',' f_rest_arg ',' f_arg opt_args_tail
{
$$ = new_args(p, 0, $1, $3, $5, $6);
}
- | f_optarg opt_f_block_arg
+ | f_optarg opt_args_tail
{
$$ = new_args(p, 0, $1, 0, 0, $2);
}
- | f_optarg ',' f_arg opt_f_block_arg
+ | f_optarg ',' f_arg opt_args_tail
{
$$ = new_args(p, 0, $1, 0, $3, $4);
}
- | f_rest_arg opt_f_block_arg
+ | f_rest_arg opt_args_tail
{
$$ = new_args(p, 0, 0, $1, 0, $2);
}
- | f_rest_arg ',' f_arg opt_f_block_arg
+ | f_rest_arg ',' f_arg opt_args_tail
{
$$ = new_args(p, 0, 0, $1, $3, $4);
}
- | f_block_arg
+ | args_tail
{
$$ = new_args(p, 0, 0, 0, 0, $1);
}
| /* none */
{
- local_add_f(p, 0);
+ local_add_f(p, mrb_intern_lit(p->mrb, "&"));
$$ = new_args(p, 0, 0, 0, 0, 0);
}
;
@@ -3121,9 +3477,15 @@ f_arg_item : f_norm_arg
{
$$ = new_arg(p, $1);
}
- | tLPAREN f_margs rparen
+ | tLPAREN
+ {
+ $<nd>$ = local_switch(p);
+ }
+ f_margs rparen
{
- $$ = new_masgn(p, $2, 0);
+ $$ = new_masgn_param(p, $3, p->locals->car);
+ local_resume(p, $<nd>2);
+ local_add_f(p, 0);
}
;
@@ -3189,7 +3551,7 @@ f_rest_arg : restarg_mark tIDENTIFIER
}
| restarg_mark
{
- local_add_f(p, 0);
+ local_add_f(p, mrb_intern_lit(p->mrb, "*"));
$$ = -1;
}
;
@@ -3200,7 +3562,6 @@ blkarg_mark : '&'
f_block_arg : blkarg_mark tIDENTIFIER
{
- local_add_f(p, $2);
$$ = $2;
}
;
@@ -3211,7 +3572,6 @@ opt_f_block_arg : ',' f_block_arg
}
| none
{
- local_add_f(p, 0);
$$ = 0;
}
;
@@ -3275,7 +3635,7 @@ assoc : arg tASSOC arg
void_expr_error(p, $3);
$$ = cons(new_sym(p, $1), $3);
}
- | string tLABEL_TAG arg
+ | string_fragment tLABEL_TAG arg
{
void_expr_error(p, $3);
if ($1->car == (node*)NODE_DSTR) {
@@ -3285,6 +3645,11 @@ assoc : arg tASSOC arg
$$ = cons(new_sym(p, new_strsym(p, $1)), $3);
}
}
+ | tDSTAR arg
+ {
+ void_expr_error(p, $2);
+ $$ = cons(cons((node*)NODE_KW_REST_ARGS, 0), $2);
+ }
;
operation : tIDENTIFIER
@@ -3375,8 +3740,9 @@ yyerror(parser_state *p, const char *s)
if (! p->capture_errors) {
#ifndef MRB_DISABLE_STDIO
- if (p->filename) {
- fprintf(stderr, "%s:%d:%d: %s\n", p->filename, p->lineno, p->column, s);
+ if (p->filename_sym) {
+ const char *filename = mrb_sym2name_len(p->mrb, p->filename_sym, NULL);
+ fprintf(stderr, "%s:%d:%d: %s\n", filename, p->lineno, p->column, s);
}
else {
fprintf(stderr, "line %d:%d: %s\n", p->lineno, p->column, s);
@@ -3395,11 +3761,13 @@ yyerror(parser_state *p, const char *s)
}
static void
-yyerror_i(parser_state *p, const char *fmt, int i)
+yyerror_c(parser_state *p, const char *msg, char c)
{
char buf[256];
- snprintf(buf, sizeof(buf), fmt, i);
+ strncpy(buf, msg, sizeof(buf) - 2);
+ buf[sizeof(buf) - 2] = '\0';
+ strncat(buf, &c, 1);
yyerror(p, buf);
}
@@ -3411,11 +3779,12 @@ yywarn(parser_state *p, const char *s)
if (! p->capture_errors) {
#ifndef MRB_DISABLE_STDIO
- if (p->filename) {
- fprintf(stderr, "%s:%d:%d: %s\n", p->filename, p->lineno, p->column, s);
+ if (p->filename_sym) {
+ const char *filename = mrb_sym2name_len(p->mrb, p->filename_sym, NULL);
+ fprintf(stderr, "%s:%d:%d: warning: %s\n", filename, p->lineno, p->column, s);
}
else {
- fprintf(stderr, "line %d:%d: %s\n", p->lineno, p->column, s);
+ fprintf(stderr, "line %d:%d: warning: %s\n", p->lineno, p->column, s);
}
#endif
}
@@ -3437,11 +3806,14 @@ yywarning(parser_state *p, const char *s)
}
static void
-yywarning_s(parser_state *p, const char *fmt, const char *s)
+yywarning_s(parser_state *p, const char *msg, const char *s)
{
char buf[256];
- snprintf(buf, sizeof(buf), fmt, s);
+ strncpy(buf, msg, sizeof(buf) - 1);
+ buf[sizeof(buf) - 1] = '\0';
+ strncat(buf, ": ", sizeof(buf) - strlen(buf) - 1);
+ strncat(buf, s, sizeof(buf) - strlen(buf) - 1);
yywarning(p, buf);
}
@@ -3450,13 +3822,13 @@ backref_error(parser_state *p, node *n)
{
int c;
- c = (int)(intptr_t)n->car;
+ c = intn(n->car);
if (c == NODE_NTH_REF) {
- yyerror_i(p, "can't set variable $%" MRB_PRId, (int)(intptr_t)n->cdr);
+ yyerror_c(p, "can't set variable $", (char)intn(n->cdr)+'0');
}
else if (c == NODE_BACK_REF) {
- yyerror_i(p, "can't set variable $%c", (int)(intptr_t)n->cdr);
+ yyerror_c(p, "can't set variable $", (char)intn(n->cdr));
}
else {
mrb_bug(p->mrb, "Internal error in backref_error() : n=>car == %S", mrb_fixnum_value(c));
@@ -3469,7 +3841,7 @@ void_expr_error(parser_state *p, node *n)
int c;
if (n == NULL) return;
- c = (int)(intptr_t)n->car;
+ c = intn(n->car);
switch (c) {
case NODE_BREAK:
case NODE_RETURN:
@@ -3480,8 +3852,10 @@ void_expr_error(parser_state *p, node *n)
break;
case NODE_AND:
case NODE_OR:
- void_expr_error(p, n->cdr->car);
- void_expr_error(p, n->cdr->cdr);
+ if (n->cdr) {
+ void_expr_error(p, n->cdr->car);
+ void_expr_error(p, n->cdr->cdr);
+ }
break;
case NODE_BEGIN:
if (n->cdr) {
@@ -3508,7 +3882,7 @@ nextc(parser_state *p)
if (p->pb) {
node *tmp;
- c = (int)(intptr_t)p->pb->car;
+ c = intn(p->pb->car);
tmp = p->pb;
p->pb = p->pb->cdr;
cons_free(tmp);
@@ -3532,14 +3906,6 @@ nextc(parser_state *p)
if (c >= 0) {
p->column++;
}
- if (c == '\r') {
- c = nextc(p);
- if (c != '\n') {
- pushback(p, c);
- return '\r';
- }
- return c;
- }
return c;
eof:
@@ -3557,7 +3923,7 @@ pushback(parser_state *p, int c)
if (c >= 0) {
p->column--;
}
- p->pb = cons((node*)(intptr_t)c, p->pb);
+ p->pb = cons(nint(c), p->pb);
}
static void
@@ -3582,7 +3948,7 @@ peekc_n(parser_state *p, int n)
c0 = nextc(p);
if (c0 == -1) return c0; /* do not skip partial EOF */
if (c0 >= 0) --p->column;
- list = push(list, (node*)(intptr_t)c0);
+ list = push(list, nint(c0));
} while(n--);
if (p->pb) {
p->pb = append((node*)list, p->pb);
@@ -4006,8 +4372,17 @@ parse_string(parser_state *p)
}
if (c < 0) {
char buf[256];
- snprintf(buf, sizeof(buf), "can't find heredoc delimiter \"%s\" anywhere before EOF", hinf->term);
- yyerror(p, buf);
+ const char s1[] = "can't find heredoc delimiter \"";
+ const char s2[] = "\" anywhere before EOF";
+
+ if (sizeof(s1)+sizeof(s2)+strlen(hinf->term)+1 >= sizeof(buf)) {
+ yyerror(p, "can't find heredoc delimiter anywhere before EOF");
+ } else {
+ strcpy(buf, s1);
+ strcat(buf, hinf->term);
+ strcat(buf, s2);
+ yyerror(p, buf);
+ }
return 0;
}
pylval.nd = new_str(p, tok(p), toklen(p));
@@ -4019,11 +4394,11 @@ parse_string(parser_state *p)
}
else if (c == beg) {
nest_level++;
- p->lex_strterm->cdr->car = (node*)(intptr_t)nest_level;
+ p->lex_strterm->cdr->car = nint(nest_level);
}
else if (c == end) {
nest_level--;
- p->lex_strterm->cdr->car = (node*)(intptr_t)nest_level;
+ p->lex_strterm->cdr->car = nint(nest_level);
}
else if (c == '\\') {
c = nextc(p);
@@ -4157,9 +4532,14 @@ parse_string(parser_state *p)
pushback(p, re_opt);
if (toklen(p)) {
char msg[128];
+
+ strcpy(msg, "unknown regexp option");
tokfix(p);
- snprintf(msg, sizeof(msg), "unknown regexp option%s - %s",
- toklen(p) > 1 ? "s" : "", tok(p));
+ if (toklen(p) > 1) {
+ strcat(msg, "s");
+ }
+ strcat(msg, " - ");
+ strncat(msg, tok(p), sizeof(msg) - strlen(msg) - 1);
yyerror(p, msg);
}
if (f != 0) {
@@ -4190,6 +4570,45 @@ parse_string(parser_state *p)
return tSTRING;
}
+#ifdef MRB_SUFFIX_SUPPORT
+static int
+number_literal_suffix(parser_state *p, int mask)
+{
+ int c, result = 0;
+ node *list = 0;
+ int column = p->column;
+
+ while ((c = nextc(p)) != -1) {
+ list = push(list, (node*)(intptr_t)c);
+
+ if ((mask & NUM_SUFFIX_I) && c == 'i') {
+ result |= (mask & NUM_SUFFIX_I);
+ mask &= ~NUM_SUFFIX_I;
+ /* r after i, rational of complex is disallowed */
+ mask &= ~NUM_SUFFIX_R;
+ continue;
+ }
+ if ((mask & NUM_SUFFIX_R) && c == 'r') {
+ result |= (mask & NUM_SUFFIX_R);
+ mask &= ~NUM_SUFFIX_R;
+ continue;
+ }
+ if (!ISASCII(c) || ISALPHA(c) || c == '_') {
+ p->column = column;
+ if (p->pb) {
+ p->pb = append((node*)list, p->pb);
+ }
+ else {
+ p->pb = list;
+ }
+ return 0;
+ }
+ pushback(p, c);
+ break;
+ }
+ return result;
+}
+#endif
static int
heredoc_identifier(parser_state *p)
@@ -4310,52 +4729,68 @@ parser_yylex(parser_state *p)
/* fall through */
case -2: /* end of a file */
case '\n':
- maybe_heredoc:
+ maybe_heredoc:
heredoc_treat_nextline(p);
- switch (p->lstate) {
- case EXPR_BEG:
- case EXPR_FNAME:
- case EXPR_DOT:
- case EXPR_CLASS:
- case EXPR_VALUE:
- p->lineno++;
- p->column = 0;
- if (p->parsing_heredoc != NULL) {
- if (p->lex_strterm) {
- return parse_string(p);
+ switch (p->lstate) {
+ case EXPR_BEG:
+ case EXPR_FNAME:
+ case EXPR_DOT:
+ case EXPR_CLASS:
+ case EXPR_VALUE:
+ p->lineno++;
+ p->column = 0;
+ if (p->parsing_heredoc != NULL) {
+ if (p->lex_strterm) {
+ return parse_string(p);
+ }
}
- }
- goto retry;
- default:
- break;
- }
- if (p->parsing_heredoc != NULL) {
- return '\n';
- }
- while ((c = nextc(p))) {
- switch (c) {
- case ' ': case '\t': case '\f': case '\r':
- case '\13': /* '\v' */
- space_seen = 1;
+ goto retry;
+ default:
break;
- case '.':
- if ((c = nextc(p)) != '.') {
- pushback(p, c);
- pushback(p, '.');
+ }
+ if (p->parsing_heredoc != NULL) {
+ return '\n';
+ }
+ while ((c = nextc(p))) {
+ switch (c) {
+ case ' ': case '\t': case '\f': case '\r':
+ case '\13': /* '\v' */
+ space_seen = 1;
+ break;
+ case '#': /* comment as a whitespace */
+ pushback(p, '#');
goto retry;
+ case '\n': /* consecutive newlines */
+ p->lineno++;
+ p->column = 0;
+ pushback(p, '\n');
+ goto retry;
+ case '.':
+ if (!peek(p, '.')) {
+ pushback(p, '.');
+ goto retry;
+ }
+ pushback(p, c);
+ goto normal_newline;
+ case '&':
+ if (peek(p, '.')) {
+ pushback(p, '&');
+ goto retry;
+ }
+ pushback(p, c);
+ goto normal_newline;
+ case -1: /* EOF */
+ case -2: /* end of a file */
+ goto normal_newline;
+ default:
+ pushback(p, c);
+ goto normal_newline;
}
- case -1: /* EOF */
- case -2: /* end of a file */
- goto normal_newline;
- default:
- pushback(p, c);
- goto normal_newline;
}
- }
normal_newline:
- p->cmd_start = TRUE;
- p->lstate = EXPR_BEG;
- return '\n';
+ p->cmd_start = TRUE;
+ p->lstate = EXPR_BEG;
+ return '\n';
case '*':
if ((c = nextc(p)) == '*') {
@@ -4365,7 +4800,16 @@ parser_yylex(parser_state *p)
return tOP_ASGN;
}
pushback(p, c);
- c = tPOW;
+ if (IS_SPCARG(c)) {
+ yywarning(p, "'**' interpreted as argument prefix");
+ c = tDSTAR;
+ }
+ else if (IS_BEG()) {
+ c = tDSTAR;
+ }
+ else {
+ c = tPOW; /* "**", "argument prefix" */
+ }
}
else {
if (c == '=') {
@@ -4578,7 +5022,10 @@ parser_yylex(parser_state *p)
}
if (c2) {
char buf[256];
- snprintf(buf, sizeof(buf), "invalid character syntax; use ?\\%c", c2);
+ char cc = (char)c2;
+
+ strcpy(buf, "invalid character syntax; use ?\\");
+ strncat(buf, &cc, 1);
yyerror(p, buf);
}
}
@@ -4589,10 +5036,10 @@ parser_yylex(parser_state *p)
}
newtok(p);
/* need support UTF-8 if configured */
- if ((isalnum(c) || c == '_')) {
+ if ((ISALNUM(c) || c == '_')) {
int c2 = nextc(p);
pushback(p, c2);
- if ((isalnum(c2) || c2 == '_')) {
+ if ((ISALNUM(c2) || c2 == '_')) {
goto ternary;
}
}
@@ -4752,6 +5199,7 @@ parser_yylex(parser_state *p)
case '5': case '6': case '7': case '8': case '9':
{
int is_float, seen_point, seen_e, nondigit;
+ int suffix = 0;
is_float = seen_point = seen_e = nondigit = 0;
p->lstate = EXPR_ENDARG;
@@ -4785,7 +5233,10 @@ parser_yylex(parser_state *p)
no_digits();
}
else if (nondigit) goto trailing_uc;
- pylval.nd = new_int(p, tok(p), 16);
+ #ifdef MRB_SUFFIX_SUPPORT
+ suffix = number_literal_suffix(p, NUM_SUFFIX_ALL);
+ #endif
+ pylval.nd = new_int(p, tok(p), 16, suffix);
return tINTEGER;
}
if (c == 'b' || c == 'B') {
@@ -4809,7 +5260,10 @@ parser_yylex(parser_state *p)
no_digits();
}
else if (nondigit) goto trailing_uc;
- pylval.nd = new_int(p, tok(p), 2);
+ #ifdef MRB_SUFFIX_SUPPORT
+ suffix = number_literal_suffix(p, NUM_SUFFIX_ALL);
+ #endif
+ pylval.nd = new_int(p, tok(p), 2, suffix);
return tINTEGER;
}
if (c == 'd' || c == 'D') {
@@ -4833,7 +5287,10 @@ parser_yylex(parser_state *p)
no_digits();
}
else if (nondigit) goto trailing_uc;
- pylval.nd = new_int(p, tok(p), 10);
+ #ifdef MRB_SUFFIX_SUPPORT
+ suffix = number_literal_suffix(p, NUM_SUFFIX_ALL);
+ #endif
+ pylval.nd = new_int(p, tok(p), 10, suffix);
return tINTEGER;
}
if (c == '_') {
@@ -4866,7 +5323,10 @@ parser_yylex(parser_state *p)
pushback(p, c);
tokfix(p);
if (nondigit) goto trailing_uc;
- pylval.nd = new_int(p, tok(p), 8);
+ #ifdef MRB_SUFFIX_SUPPORT
+ suffix = number_literal_suffix(p, NUM_SUFFIX_ALL);
+ #endif
+ pylval.nd = new_int(p, tok(p), 8, suffix);
return tINTEGER;
}
if (nondigit) {
@@ -4883,7 +5343,10 @@ parser_yylex(parser_state *p)
}
else {
pushback(p, c);
- pylval.nd = new_int(p, "0", 10);
+ #ifdef MRB_SUFFIX_SUPPORT
+ suffix = number_literal_suffix(p, NUM_SUFFIX_ALL);
+ #endif
+ pylval.nd = new_int(p, "0", 10, suffix);
return tINTEGER;
}
}
@@ -4951,13 +5414,13 @@ parser_yylex(parser_state *p)
pushback(p, c);
if (nondigit) {
trailing_uc:
- yyerror_i(p, "trailing '%c' in number", nondigit);
+ yyerror_c(p, "trailing non digit in number: ", (char)nondigit);
}
tokfix(p);
if (is_float) {
#ifdef MRB_WITHOUT_FLOAT
- yywarning_s(p, "floating point numbers are not supported", tok(p));
- pylval.nd = new_int(p, "0", 10);
+ yywarning(p, "floating point numbers are not supported");
+ pylval.nd = new_int(p, "0", 10, 0);
return tINTEGER;
#else
double d;
@@ -4966,17 +5429,23 @@ parser_yylex(parser_state *p)
errno = 0;
d = mrb_float_read(tok(p), &endp);
if (d == 0 && endp == tok(p)) {
- yywarning_s(p, "corrupted float value %s", tok(p));
+ yywarning_s(p, "corrupted float value", tok(p));
}
else if (errno == ERANGE) {
- yywarning_s(p, "float %s out of range", tok(p));
+ yywarning_s(p, "float out of range", tok(p));
errno = 0;
}
- pylval.nd = new_float(p, tok(p));
+ #ifdef MRB_SUFFIX_SUPPORT
+ suffix = number_literal_suffix(p, NUM_SUFFIX_ALL);
+ #endif
+ pylval.nd = new_float(p, tok(p), suffix);
return tFLOAT;
#endif
}
- pylval.nd = new_int(p, tok(p), 10);
+ #ifdef MRB_SUFFIX_SUPPORT
+ suffix = number_literal_suffix(p, NUM_SUFFIX_ALL);
+ #endif
+ pylval.nd = new_int(p, tok(p), 10, suffix);
return tINTEGER;
}
@@ -5160,7 +5629,7 @@ parser_yylex(parser_state *p)
}
else {
term = nextc(p);
- if (isalnum(term)) {
+ if (ISALNUM(term)) {
yyerror(p, "unknown type of %string");
return 0;
}
@@ -5304,14 +5773,14 @@ parser_yylex(parser_state *p)
do {
tokadd(p, c);
c = nextc(p);
- } while (c >= 0 && isdigit(c));
+ } while (c >= 0 && ISDIGIT(c));
pushback(p, c);
if (last_state == EXPR_FNAME) goto gvar;
tokfix(p);
{
unsigned long n = strtoul(tok(p), NULL, 10);
if (n > INT_MAX) {
- yyerror_i(p, "capture group index must be <= %d", INT_MAX);
+ yyerror(p, "capture group index must be <= " MRB_STRINGIZE(INT_MAX));
return 0;
}
pylval.nd = new_nth_ref(p, (int)n);
@@ -5346,12 +5815,12 @@ parser_yylex(parser_state *p)
}
return 0;
}
- else if (isdigit(c)) {
+ else if (ISDIGIT(c)) {
if (p->tidx == 1) {
- yyerror_i(p, "'@%c' is not allowed as an instance variable name", c);
+ yyerror_c(p, "wrong instance variable name: @", c);
}
else {
- yyerror_i(p, "'@@%c' is not allowed as a class variable name", c);
+ yyerror_c(p, "wrong class variable name: @@", c);
}
return 0;
}
@@ -5367,7 +5836,15 @@ parser_yylex(parser_state *p)
default:
if (!identchar(c)) {
- yyerror_i(p, "Invalid char '\\x%02X' in expression", c);
+ char buf[36];
+ const char s[] = "Invalid char in expression: 0x";
+ const char hexdigits[] = "0123456789ABCDEF";
+
+ strcpy(buf, s);
+ buf[sizeof(s)-1] = hexdigits[(c & 0xf0) >> 4];
+ buf[sizeof(s)] = hexdigits[(c & 0x0f)];
+ buf[sizeof(s)+1] = 0;
+ yyerror(p, buf);
goto retry;
}
@@ -5503,7 +5980,7 @@ parser_yylex(parser_state *p)
mrb_sym ident = intern_cstr(tok(p));
pylval.id = ident;
- if (last_state != EXPR_DOT && islower(tok(p)[0]) && local_var_p(p, ident)) {
+ if (last_state != EXPR_DOT && ISLOWER(tok(p)[0]) && local_var_p(p, ident)) {
p->lstate = EXPR_END;
}
}
@@ -5534,6 +6011,7 @@ parser_init_cxt(parser_state *p, mrbc_context *cxt)
}
p->capture_errors = cxt->capture_errors;
p->no_optimize = cxt->no_optimize;
+ p->on_eval = cxt->on_eval;
if (cxt->partial_hook) {
p->cxt = cxt;
}
@@ -5546,7 +6024,7 @@ parser_update_cxt(parser_state *p, mrbc_context *cxt)
int i = 0;
if (!cxt) return;
- if ((int)(intptr_t)p->tree->car != NODE_SCOPE) return;
+ if (intn(p->tree->car) != NODE_SCOPE) return;
n0 = n = p->tree->cdr->car;
while (n) {
i++;
@@ -5712,7 +6190,7 @@ mrb_parser_set_filename(struct mrb_parser_state *p, const char *f)
mrb_sym* new_table;
sym = mrb_intern_cstr(p->mrb, f);
- p->filename = mrb_sym2name_len(p->mrb, sym, NULL);
+ p->filename_sym = sym;
p->lineno = (p->filename_table_length > 0)? 0 : 1;
for (i = 0; i < p->filename_table_length; ++i) {
@@ -5722,7 +6200,11 @@ mrb_parser_set_filename(struct mrb_parser_state *p, const char *f)
}
}
- p->current_filename_index = (int)p->filename_table_length++;
+ if (p->filename_table_length == UINT16_MAX) {
+ yyerror(p, "too many files to compile");
+ return;
+ }
+ p->current_filename_index = p->filename_table_length++;
new_table = (mrb_sym*)parser_palloc(p, sizeof(mrb_sym) * p->filename_table_length);
if (p->filename_table) {
@@ -5732,11 +6214,11 @@ mrb_parser_set_filename(struct mrb_parser_state *p, const char *f)
p->filename_table[p->filename_table_length - 1] = sym;
}
-MRB_API char const*
+MRB_API mrb_sym
mrb_parser_get_filename(struct mrb_parser_state* p, uint16_t idx) {
- if (idx >= p->filename_table_length) { return NULL; }
+ if (idx >= p->filename_table_length) return 0;
else {
- return mrb_sym2name_len(p->mrb, p->filename_table[idx], NULL);
+ return p->filename_table[idx];
}
}
@@ -5791,11 +6273,12 @@ mrb_load_exec(mrb_state *mrb, struct mrb_parser_state *p, mrbc_context *c)
if (c) c->parser_nerr = p->nerr;
if (p->capture_errors) {
char buf[256];
- int n;
- n = snprintf(buf, sizeof(buf), "line %d: %s\n",
- p->error_buffer[0].lineno, p->error_buffer[0].message);
- mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SYNTAX_ERROR, buf, n));
+ strcpy(buf, "line ");
+ dump_int(p->error_buffer[0].lineno, buf+5);
+ strcat(buf, ": ");
+ strncat(buf, p->error_buffer[0].message, sizeof(buf) - strlen(buf) - 1);
+ mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SYNTAX_ERROR, buf, strlen(buf)));
mrb_parser_free(p);
return mrb_undef_value();
}
@@ -5896,6 +6379,48 @@ dump_recur(mrb_state *mrb, node *tree, int offset)
}
}
+static void
+dump_args(mrb_state *mrb, node *n, int offset)
+{
+ if (n->car) {
+ dump_prefix(n, offset+1);
+ printf("mandatory args:\n");
+ dump_recur(mrb, n->car, offset+2);
+ }
+ n = n->cdr;
+ if (n->car) {
+ dump_prefix(n, offset+1);
+ printf("optional args:\n");
+ {
+ node *n2 = n->car;
+
+ while (n2) {
+ dump_prefix(n2, offset+2);
+ printf("%s=\n", mrb_sym2name(mrb, sym(n2->car->car)));
+ mrb_parser_dump(mrb, n2->car->cdr, offset+3);
+ n2 = n2->cdr;
+ }
+ }
+ }
+ n = n->cdr;
+ if (n->car) {
+ dump_prefix(n, offset+1);
+ printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car)));
+ }
+ n = n->cdr;
+ if (n->car) {
+ dump_prefix(n, offset+1);
+ printf("post mandatory args:\n");
+ dump_recur(mrb, n->car, offset+2);
+ }
+
+ n = n->cdr;
+ if (n) {
+ mrb_assert(intn(n->car) == NODE_ARGS_TAIL);
+ mrb_parser_dump(mrb, n, offset);
+ }
+}
+
#endif
void
@@ -5907,7 +6432,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
if (!tree) return;
again:
dump_prefix(tree, offset);
- nodetype = (int)(intptr_t)tree->car;
+ nodetype = intn(tree->car);
tree = tree->cdr;
switch (nodetype) {
case NODE_BEGIN:
@@ -5967,7 +6492,8 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
break;
case NODE_LAMBDA:
- printf("NODE_BLOCK:\n");
+ printf("NODE_LAMBDA:\n");
+ dump_prefix(tree, offset);
goto block;
case NODE_BLOCK:
@@ -5975,43 +6501,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
printf("NODE_BLOCK:\n");
tree = tree->cdr;
if (tree->car) {
- node *n = tree->car;
-
- if (n->car) {
- dump_prefix(n, offset+1);
- printf("mandatory args:\n");
- dump_recur(mrb, n->car, offset+2);
- }
- n = n->cdr;
- if (n->car) {
- dump_prefix(n, offset+1);
- printf("optional args:\n");
- {
- node *n2 = n->car;
-
- while (n2) {
- dump_prefix(n2, offset+2);
- printf("%s=", mrb_sym2name(mrb, sym(n2->car->car)));
- mrb_parser_dump(mrb, n2->car->cdr, 0);
- n2 = n2->cdr;
- }
- }
- }
- n = n->cdr;
- if (n->car) {
- dump_prefix(n, offset+1);
- printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car)));
- }
- n = n->cdr;
- if (n->car) {
- dump_prefix(n, offset+1);
- printf("post mandatory args:\n");
- dump_recur(mrb, n->car, offset+2);
- }
- if (n->cdr) {
- dump_prefix(n, offset+1);
- printf("blk=&%s\n", mrb_sym2name(mrb, sym(n->cdr)));
- }
+ dump_args(mrb, tree->car, offset+1);
}
dump_prefix(tree, offset+1);
printf("body:\n");
@@ -6163,7 +6653,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
dump_prefix(tree, offset+1);
printf("method='%s' (%d)\n",
mrb_sym2name(mrb, sym(tree->cdr->car)),
- (int)(intptr_t)tree->cdr->car);
+ intn(tree->cdr->car));
tree = tree->cdr->cdr->car;
if (tree) {
dump_prefix(tree, offset+1);
@@ -6218,6 +6708,19 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
}
break;
+ case NODE_KW_HASH:
+ printf("NODE_KW_HASH:\n");
+ while (tree) {
+ dump_prefix(tree, offset+1);
+ printf("key:\n");
+ mrb_parser_dump(mrb, tree->car->car, offset+2);
+ dump_prefix(tree, offset+1);
+ printf("value:\n");
+ mrb_parser_dump(mrb, tree->car->cdr, offset+2);
+ tree = tree->cdr;
+ }
+ break;
+
case NODE_SPLAT:
printf("NODE_SPLAT:\n");
mrb_parser_dump(mrb, tree, offset+1);
@@ -6280,7 +6783,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
mrb_parser_dump(mrb, tree->car, offset+2);
tree = tree->cdr;
dump_prefix(tree, offset+1);
- printf("op='%s' (%d)\n", mrb_sym2name(mrb, sym(tree->car)), (int)(intptr_t)tree->car);
+ printf("op='%s' (%d)\n", mrb_sym2name(mrb, sym(tree->car)), intn(tree->car));
tree = tree->cdr;
mrb_parser_dump(mrb, tree->car, offset+1);
break;
@@ -6362,11 +6865,11 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
break;
case NODE_BACK_REF:
- printf("NODE_BACK_REF: $%c\n", (int)(intptr_t)tree);
+ printf("NODE_BACK_REF: $%c\n", intn(tree));
break;
case NODE_NTH_REF:
- printf("NODE_NTH_REF: $%" MRB_PRId "\n", (mrb_int)(intptr_t)tree);
+ printf("NODE_NTH_REF: $%d\n", intn(tree));
break;
case NODE_ARG:
@@ -6379,7 +6882,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
break;
case NODE_INT:
- printf("NODE_INT %s base %d\n", (char*)tree->car, (int)(intptr_t)tree->cdr->car);
+ printf("NODE_INT %s base %d\n", (char*)tree->car, intn(tree->cdr->car));
break;
case NODE_FLOAT:
@@ -6392,7 +6895,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
break;
case NODE_STR:
- printf("NODE_STR \"%s\" len %d\n", (char*)tree->car, (int)(intptr_t)tree->cdr);
+ printf("NODE_STR \"%s\" len %d\n", (char*)tree->car, intn(tree->cdr));
break;
case NODE_DSTR:
@@ -6401,7 +6904,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
break;
case NODE_XSTR:
- printf("NODE_XSTR \"%s\" len %d\n", (char*)tree->car, (int)(intptr_t)tree->cdr);
+ printf("NODE_XSTR \"%s\" len %d\n", (char*)tree->car, intn(tree->cdr));
break;
case NODE_DXSTR:
@@ -6430,7 +6933,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
case NODE_SYM:
printf("NODE_SYM :%s (%d)\n", mrb_sym2name(mrb, sym(tree)),
- (int)(intptr_t)tree);
+ intn(tree));
break;
case NODE_SELF:
@@ -6546,43 +7049,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
}
tree = tree->cdr;
if (tree->car) {
- node *n = tree->car;
-
- if (n->car) {
- dump_prefix(n, offset+1);
- printf("mandatory args:\n");
- dump_recur(mrb, n->car, offset+2);
- }
- n = n->cdr;
- if (n->car) {
- dump_prefix(n, offset+1);
- printf("optional args:\n");
- {
- node *n2 = n->car;
-
- while (n2) {
- dump_prefix(n2, offset+2);
- printf("%s=", mrb_sym2name(mrb, sym(n2->car->car)));
- mrb_parser_dump(mrb, n2->car->cdr, 0);
- n2 = n2->cdr;
- }
- }
- }
- n = n->cdr;
- if (n->car) {
- dump_prefix(n, offset+1);
- printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car)));
- }
- n = n->cdr;
- if (n->car) {
- dump_prefix(n, offset+1);
- printf("post mandatory args:\n");
- dump_recur(mrb, n->car, offset+2);
- }
- if (n->cdr) {
- dump_prefix(n, offset+1);
- printf("blk=&%s\n", mrb_sym2name(mrb, sym(n->cdr)));
- }
+ dump_args(mrb, tree->car, offset);
}
mrb_parser_dump(mrb, tree->cdr->car, offset+1);
break;
@@ -6595,44 +7062,7 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
printf(":%s\n", mrb_sym2name(mrb, sym(tree->car)));
tree = tree->cdr->cdr;
if (tree->car) {
- node *n = tree->car;
-
- if (n->car) {
- dump_prefix(n, offset+1);
- printf("mandatory args:\n");
- dump_recur(mrb, n->car, offset+2);
- }
- n = n->cdr;
- if (n->car) {
- dump_prefix(n, offset+1);
- printf("optional args:\n");
- {
- node *n2 = n->car;
-
- while (n2) {
- dump_prefix(n2, offset+2);
- printf("%s=", mrb_sym2name(mrb, sym(n2->car->car)));
- mrb_parser_dump(mrb, n2->car->cdr, 0);
- n2 = n2->cdr;
- }
- }
- }
- n = n->cdr;
- if (n->car) {
- dump_prefix(n, offset+1);
- printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car)));
- }
- n = n->cdr;
- if (n->car) {
- dump_prefix(n, offset+1);
- printf("post mandatory args:\n");
- dump_recur(mrb, n->car, offset+2);
- }
- n = n->cdr;
- if (n) {
- dump_prefix(n, offset+1);
- printf("blk=&%s\n", mrb_sym2name(mrb, sym(n)));
- }
+ dump_args(mrb, tree->car, offset+1);
}
tree = tree->cdr;
mrb_parser_dump(mrb, tree->car, offset+1);
@@ -6648,6 +7078,37 @@ mrb_parser_dump(mrb_state *mrb, node *tree, int offset)
dump_recur(mrb, ((parser_heredoc_info*)tree)->doc, offset+1);
break;
+ case NODE_ARGS_TAIL:
+ printf("NODE_ARGS_TAIL:\n");
+ {
+ node *kws = tree->car;
+
+ while (kws) {
+ mrb_parser_dump(mrb, kws->car, offset+1);
+ kws = kws->cdr;
+ }
+ }
+ tree = tree->cdr;
+ if (tree->car) {
+ mrb_assert(intn(tree->car->car) == NODE_KW_REST_ARGS);
+ mrb_parser_dump(mrb, tree->car, offset+1);
+ }
+ tree = tree->cdr;
+ if (tree->car) {
+ dump_prefix(tree, offset+1);
+ printf("block='%s'\n", mrb_sym2name(mrb, sym(tree->car)));
+ }
+ break;
+
+ case NODE_KW_ARG:
+ printf("NODE_KW_ARG %s\n", mrb_sym2name(mrb, sym(tree->car)));
+ mrb_parser_dump(mrb, tree->cdr->car, offset + 1);
+ break;
+
+ case NODE_KW_REST_ARGS:
+ printf("NODE_KW_REST_ARGS %s\n", mrb_sym2name(mrb, sym(tree)));
+ break;
+
default:
printf("node type: %d (0x%x)\n", nodetype, (unsigned)nodetype);
break;
diff --git a/mrbgems/mruby-compiler/mrbgem.rake b/mrbgems/mruby-compiler/mrbgem.rake
index 3bf6d6ae3..fa191e69b 100644
--- a/mrbgems/mruby-compiler/mrbgem.rake
+++ b/mrbgems/mruby-compiler/mrbgem.rake
@@ -23,10 +23,10 @@ MRuby::Gem::Specification.new 'mruby-compiler' do |spec|
cc.run t.name, t.prerequisites.first, [], ["#{current_dir}/core"]
end
end
- file objfile("#{current_build_dir}/core/y.tab") => lex_def
# Parser
- file "#{current_build_dir}/core/y.tab.c" => ["#{current_dir}/core/parse.y"] do |t|
+ file "#{current_build_dir}/core/y.tab.c" => ["#{current_dir}/core/parse.y", lex_def] do |t|
+ FileUtils.mkdir_p File.dirname t.name
yacc.run t.name, t.prerequisites.first
end
@@ -35,6 +35,6 @@ MRuby::Gem::Specification.new 'mruby-compiler' do |spec|
gperf.run t.name, t.prerequisites.first
end
- file libfile("#{build.build_dir}/lib/libmruby_core") => core_objs
+ file build.libmruby_core_static => core_objs
build.libmruby << core_objs
end