*/
#include <ctype.h>
+#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include "mruby.h"
#include "mruby/debug.h"
#include "node.h"
#include "opcode.h"
-#include "re.h"
+#include "mruby/re.h"
+#include "mrb_throw.h"
typedef mrb_ast_node node;
typedef struct mrb_parser_state parser_state;
@@ -38,7 +40,7 @@ struct loopinfo {
typedef struct scope {
mrb_state *mrb;
mrb_pool *mpool;
- jmp_buf jmp;
+ struct mrb_jmpbuf jmp;
struct scope *prev;
@@ -101,7 +103,7 @@ codegen_error(codegen_scope *s, const char *message)
fprintf(stderr, "codegen error: %s\n", message);
}
#endif
- longjmp(s->jmp, 1);
+ MRB_THROW(&s->jmp);
}
static void*
@@ -138,7 +140,7 @@ new_label(codegen_scope *s)
return s->pc;
}
-static inline void
+static inline int
genop(codegen_scope *s, mrb_code i)
{
if (s->pc == s->icapa) {
@@ -153,13 +155,13 @@ genop(codegen_scope *s, mrb_code i)
if (s->lines) {
s->lines[s->pc] = s->lineno;
}
- s->pc++;
+ return s->pc++;
}
#define NOVAL 0
#define VAL 1
-static void
+static int
genop_peep(codegen_scope *s, mrb_code i, int val)
{
/* peephole optimization */
@@ -172,24 +174,24 @@ genop_peep(codegen_scope *s, mrb_code i, int val)
case OP_MOVE:
if (GETARG_A(i) == GETARG_B(i)) {
/* skip useless OP_MOVE */
- return;
+ return 0;
}
if (val) break;
switch (c0) {
case OP_MOVE:
if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i) == GETARG_B(i0) && GETARG_A(i) >= s->nlocals) {
/* skip swapping OP_MOVE */
- return;
+ return 0;
}
if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
s->iseq[s->pc-1] = MKOP_AB(OP_MOVE, GETARG_A(i), GETARG_B(i0));
- return;
+ return 0;
}
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;
+ return 0;
}
break;
case OP_ARRAY:
@@ -199,7 +201,7 @@ genop_peep(codegen_scope *s, mrb_code i, int val)
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;
+ return 0;
}
break;
case OP_LOADSYM:
@@ -212,13 +214,13 @@ genop_peep(codegen_scope *s, mrb_code i, int val)
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;
+ 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;
+ return 0;
}
break;
case OP_LOADNIL:
@@ -228,7 +230,7 @@ genop_peep(codegen_scope *s, mrb_code i, int val)
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;
+ return 0;
}
break;
default:
@@ -244,7 +246,7 @@ genop_peep(codegen_scope *s, mrb_code i, int val)
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;
+ return 0;
}
}
break;
@@ -253,29 +255,32 @@ genop_peep(codegen_scope *s, mrb_code i, int val)
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;
+ return 0;
}
}
break;
case OP_EPOP:
if (c0 == OP_EPOP) {
s->iseq[s->pc-1] = MKOP_A(OP_EPOP, GETARG_A(i0)+GETARG_A(i));
- return;
+ 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;
+ return 0;
}
break;
case OP_RETURN:
switch (c0) {
case OP_RETURN:
- return;
+ return 0;
case OP_MOVE:
- s->iseq[s->pc-1] = MKOP_AB(OP_RETURN, GETARG_B(i0), OP_R_NORMAL);
- return;
+ 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:
@@ -285,8 +290,7 @@ genop_peep(codegen_scope *s, mrb_code i, int val)
s->pc--;
genop_peep(s, i0, NOVAL);
i0 = s->iseq[s->pc-1];
- genop(s, MKOP_AB(OP_RETURN, GETARG_A(i0), OP_R_NORMAL));
- return;
+ 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)) {
@@ -310,7 +314,7 @@ genop_peep(codegen_scope *s, mrb_code i, int val)
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;
+ return 0;
}
case OP_STRCAT:
if (c0 == OP_STRING) {
@@ -319,15 +323,22 @@ genop_peep(codegen_scope *s, mrb_code i, int val)
if (mrb_type(s->irep->pool[i]) == MRB_TT_STRING &&
RSTRING_LEN(s->irep->pool[i]) == 0) {
s->pc--;
- return;
+ return 0;
}
}
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;
+ }
+ break;
default:
break;
}
}
- genop(s, i);
+ return genop(s, i);
}
static void
@@ -535,15 +546,15 @@ for_body(codegen_scope *s, node *tree)
node *n2;
mrb_code c;
- // generate receiver
+ /* generate receiver */
codegen(s, tree->cdr->car, VAL);
- // generate loop-block
+ /* generate loop-block */
s = scope_new(s->mrb, s, tree->car);
lp = loop_push(s, LOOP_FOR);
lp->pc1 = new_label(s);
- // generate loop variable
+ /* generate loop variable */
n2 = tree->car;
if (n2->car && !n2->car->cdr && !n2->cdr) {
genop(s, MKOP_Ax(OP_ENTER, 0x40000));
@@ -699,12 +710,17 @@ static mrb_sym
attrsym(codegen_scope *s, mrb_sym a)
{
const char *name;
- size_t len;
+ mrb_int len;
char *name2;
name = mrb_sym2name_len(s->mrb, a, &len);
- name2 = (char *)codegen_palloc(s, len+1);
- memcpy(name2, name, len);
+ name2 = (char *)codegen_palloc(s,
+ (size_t)len
+ + 1 /* '=' */
+ + 1 /* '\0' */
+ );
+ mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX);
+ memcpy(name2, name, (size_t)len);
name2[len] = '=';
name2[len+1] = '\0';
@@ -718,7 +734,7 @@ gen_values(codegen_scope *s, node *t, int val)
int is_splat;
while (t) {
- is_splat = (intptr_t)t->car->car == NODE_SPLAT; // splat mode
+ is_splat = (intptr_t)t->car->car == NODE_SPLAT; /* splat mode */
if (n >= 127 || is_splat) {
if (val) {
pop_n(n);
@@ -756,7 +772,7 @@ gen_values(codegen_scope *s, node *t, int val)
}
return -1;
}
- // normal (no splat) mode
+ /* normal (no splat) mode */
codegen(s, t->car, val);
n++;
t = t->cdr;
@@ -803,9 +819,10 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val)
else {
blk = cursp();
}
+ push();pop();
pop_n(n+1);
{
- size_t len;
+ mrb_int len;
const char *name = mrb_sym2name_len(s->mrb, sym, &len);
if (!noop && len == 1 && name[0] == '+') {
@@ -1145,8 +1162,7 @@ codegen(codegen_scope *s, node *tree, int val)
int onerr, noexc, exend, pos1, pos2, tmp;
struct loopinfo *lp;
- onerr = new_label(s);
- genop(s, MKOP_Bx(OP_ONERR, 0));
+ onerr = genop(s, MKOP_Bx(OP_ONERR, 0));
lp = loop_push(s, LOOP_BEGIN);
lp->pc1 = onerr;
if (tree->car) {
@@ -1154,8 +1170,7 @@ codegen(codegen_scope *s, node *tree, int val)
if (val) pop();
}
lp->type = LOOP_RESCUE;
- noexc = new_label(s);
- genop(s, MKOP_Bx(OP_JMP, 0));
+ noexc = genop(s, MKOP_Bx(OP_JMP, 0));
dispatch(s, onerr);
tree = tree->cdr;
exend = 0;
@@ -1182,16 +1197,19 @@ codegen(codegen_scope *s, node *tree, int val)
}
genop(s, MKOP_AB(OP_MOVE, cursp(), exc));
pop();
- genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "===")), 1));
- tmp = new_label(s);
- genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2));
+ if (n4 && n4->car && (intptr_t)n4->car->car == NODE_SPLAT) {
+ genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(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));
+ }
+ tmp = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2));
pos2 = tmp;
if (n4) {
n4 = n4->cdr;
}
} while (n4);
- pos1 = new_label(s);
- genop(s, MKOP_sBx(OP_JMP, 0));
+ pos1 = genop(s, MKOP_sBx(OP_JMP, 0));
dispatch_linked(s, pos2);
pop();
@@ -1202,8 +1220,7 @@ codegen(codegen_scope *s, node *tree, int val)
codegen(s, n3->cdr->cdr->car, val);
if (val) pop();
}
- tmp = new_label(s);
- genop(s, MKOP_sBx(OP_JMP, exend));
+ tmp = genop(s, MKOP_sBx(OP_JMP, exend));
exend = tmp;
n2 = n2->cdr;
push();
@@ -1268,8 +1285,7 @@ codegen(codegen_scope *s, node *tree, int val)
codegen(s, tree->car, VAL);
pop();
- pos1 = new_label(s);
- genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0));
+ pos1 = genop_peep(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0), NOVAL);
codegen(s, tree->cdr->car, val);
if (val && !(tree->cdr->car)) {
@@ -1278,17 +1294,15 @@ codegen(codegen_scope *s, node *tree, int val)
}
if (e) {
if (val) pop();
- pos2 = new_label(s);
- genop(s, MKOP_sBx(OP_JMP, 0));
- dispatch(s, pos1);
+ pos2 = genop(s, MKOP_sBx(OP_JMP, 0));
+ dispatch(s, pos1);
codegen(s, e, val);
dispatch(s, pos2);
}
else {
if (val) {
pop();
- pos2 = new_label(s);
- genop(s, MKOP_sBx(OP_JMP, 0));
+ pos2 = genop(s, MKOP_sBx(OP_JMP, 0));
dispatch(s, pos1);
genop(s, MKOP_A(OP_LOADNIL, cursp()));
dispatch(s, pos2);
@@ -1306,9 +1320,8 @@ codegen(codegen_scope *s, node *tree, int val)
int pos;
codegen(s, tree->car, VAL);
- pos = new_label(s);
pop();
- genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0));
+ pos = genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0));
codegen(s, tree->cdr, val);
dispatch(s, pos);
}
@@ -1319,9 +1332,8 @@ codegen(codegen_scope *s, node *tree, int val)
int pos;
codegen(s, tree->car, VAL);
- pos = new_label(s);
pop();
- genop(s, MKOP_AsBx(OP_JMPIF, cursp(), 0));
+ pos = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), 0));
codegen(s, tree->cdr, val);
dispatch(s, pos);
}
@@ -1331,8 +1343,7 @@ codegen(codegen_scope *s, node *tree, int val)
{
struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
- lp->pc1 = new_label(s);
- genop(s, MKOP_sBx(OP_JMP, 0));
+ lp->pc1 = genop(s, MKOP_sBx(OP_JMP, 0));
lp->pc2 = new_label(s);
codegen(s, tree->cdr, NOVAL);
dispatch(s, lp->pc1);
@@ -1348,8 +1359,7 @@ codegen(codegen_scope *s, node *tree, int val)
{
struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
- lp->pc1 = new_label(s);
- genop(s, MKOP_sBx(OP_JMP, 0));
+ lp->pc1 = genop(s, MKOP_sBx(OP_JMP, 0));
lp->pc2 = new_label(s);
codegen(s, tree->cdr, NOVAL);
dispatch(s, lp->pc1);
@@ -1396,20 +1406,17 @@ codegen(codegen_scope *s, node *tree, int val)
else {
pop();
}
- tmp = new_label(s);
- genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2));
+ tmp = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2));
pos2 = tmp;
n = n->cdr;
}
if (tree->car->car) {
- pos1 = new_label(s);
- genop(s, MKOP_sBx(OP_JMP, 0));
+ pos1 = genop(s, MKOP_sBx(OP_JMP, 0));
dispatch_linked(s, pos2);
}
codegen(s, tree->car->cdr, val);
if (val) pop();
- tmp = new_label(s);
- genop(s, MKOP_sBx(OP_JMP, pos3));
+ tmp = genop(s, MKOP_sBx(OP_JMP, pos3));
pos3 = tmp;
if (pos1) dispatch(s, pos1);
tree = tree->cdr;
@@ -1442,7 +1449,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(), 0));
+ genop(s, MKOP_ABC(OP_RANGE, cursp(), cursp(), FALSE));
push();
}
break;
@@ -1452,7 +1459,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(), 1));
+ genop(s, MKOP_ABC(OP_RANGE, cursp(), cursp(), TRUE));
push();
}
break;
@@ -1499,30 +1506,39 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_HASH:
{
int len = 0;
+ mrb_bool update = FALSE;
while (tree) {
codegen(s, tree->car->car, val);
codegen(s, tree->car->cdr, val);
len++;
tree = tree->cdr;
+ if (val && len == 126) {
+ pop_n(len*2);
+ genop(s, MKOP_ABC(OP_HASH, cursp(), cursp(), len));
+ if (update) {
+ pop();
+ genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__update")), 1));
+ }
+ push();
+ update = TRUE;
+ len = 0;
+ }
}
if (val) {
pop_n(len*2);
genop(s, MKOP_ABC(OP_HASH, cursp(), cursp(), len));
+ if (update) {
+ pop();
+ genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__update")), 1));
+ }
push();
}
}
break;
case NODE_SPLAT:
- {
- int idx = new_msym(s, mrb_intern_lit(s->mrb, "to_a"));
-
- codegen(s, tree, VAL);
- pop();
- genop(s, MKOP_ABC(OP_SEND, cursp(), idx, 0));
- push();
- }
+ codegen(s, tree, VAL);
break;
case NODE_ASGN:
@@ -1538,7 +1554,7 @@ codegen(codegen_scope *s, node *tree, int val)
int rhs = cursp();
if ((intptr_t)t->car == NODE_ARRAY && nosplat(t->cdr)) {
- // fixed rhs
+ /* fixed rhs */
t = t->cdr;
while (t) {
codegen(s, t->car, VAL);
@@ -1587,7 +1603,7 @@ codegen(codegen_scope *s, node *tree, int val)
}
}
else {
- // variable rhs
+ /* variable rhs */
codegen(s, t, VAL);
gen_vmassignment(s, tree->car, rhs, val);
}
@@ -1597,7 +1613,7 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_OP_ASGN:
{
mrb_sym sym = sym(tree->cdr->car);
- size_t len;
+ mrb_int len;
const char *name = mrb_sym2name_len(s->mrb, sym, &len);
int idx;
@@ -1608,8 +1624,7 @@ codegen(codegen_scope *s, node *tree, int val)
int pos;
pop();
- pos = new_label(s);
- genop(s, MKOP_AsBx(name[0] == '|' ? OP_JMPIF : OP_JMPNOT, cursp(), 0));
+ pos = genop_peep(s, MKOP_AsBx(name[0] == '|' ? OP_JMPIF : OP_JMPNOT, cursp(), 0), NOVAL);
codegen(s, tree->cdr->cdr->car, VAL);
pop();
gen_assignment(s, tree->car, cursp(), val);
@@ -1617,6 +1632,7 @@ codegen(codegen_scope *s, node *tree, int val)
break;
}
codegen(s, tree->cdr->cdr->car, VAL);
+ push(); pop();
pop(); pop();
idx = new_msym(s, sym);
@@ -1672,6 +1688,7 @@ codegen(codegen_scope *s, node *tree, int val)
}
else {
genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ push(); pop();
}
pop_n(n+1);
if (sendv) n = CALL_MAXARGS;
@@ -1693,12 +1710,12 @@ codegen(codegen_scope *s, node *tree, int val)
}
if (s2) ainfo = s2->ainfo;
genop(s, MKOP_ABx(OP_ARGARY, cursp(), (ainfo<<4)|(lv & 0xf)));
+ push(); push(); pop(); /* ARGARY pushes two values */
if (tree && tree->cdr) {
- push();
codegen(s, tree->cdr, VAL);
- pop_n(2);
+ pop();
}
- pop();
+ pop(); pop();
genop(s, MKOP_ABC(OP_SUPER, cursp(), 0, CALL_MAXARGS));
if (val) push();
}
@@ -1830,7 +1847,7 @@ codegen(codegen_scope *s, node *tree, int val)
int idx = lv_idx(s, sym(tree));
if (idx > 0) {
- genop(s, MKOP_AB(OP_MOVE, cursp(), idx));
+ genop_peep(s, MKOP_AB(OP_MOVE, cursp(), idx), NOVAL);
}
else {
int lv = 0;
@@ -1911,7 +1928,7 @@ codegen(codegen_scope *s, node *tree, int val)
mrb_value fix = mrb_fixnum_value((intptr_t)tree);
mrb_value str = mrb_str_buf_new(mrb, 4);
- mrb_str_buf_cat(mrb, str, "$", 1);
+ mrb_str_cat_lit(mrb, str, "$");
mrb_str_buf_append(mrb, str, mrb_fixnum_to_str(mrb, fix, 10));
sym = new_sym(s, mrb_intern_str(mrb, str));
genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
@@ -1920,7 +1937,7 @@ codegen(codegen_scope *s, node *tree, int val)
break;
case NODE_ARG:
- // should not happen
+ /* should not happen */
break;
case NODE_BLOCK_ARG:
@@ -2077,14 +2094,48 @@ codegen(codegen_scope *s, node *tree, int val)
gen_literal_array(s, tree, TRUE, val);
break;
+ case NODE_DXSTR:
+ {
+ node *n;
+ int ai = mrb_gc_arena_save(s->mrb);
+ int sym = new_sym(s, mrb_intern_lit(s->mrb, "Kernel"));
+
+ if (val == NOVAL) { push(); }
+ genop(s, MKOP_A(OP_OCLASS, cursp()));
+ genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
+ push();
+ codegen(s, tree->car, VAL);
+ n = tree->cdr;
+ while (n) {
+ if ((intptr_t)n->car->car == NODE_XSTR) {
+ n->car->car = (struct mrb_ast_node*)(intptr_t)NODE_STR;
+ mrb_assert(!n->cdr); /* must be the end */
+ }
+ codegen(s, n->car, VAL);
+ pop(); pop();
+ genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
+ push();
+ n = n->cdr;
+ }
+ pop();
+ pop();
+ sym = new_sym(s, mrb_intern_lit(s->mrb, "`"));
+ genop(s, MKOP_ABC(OP_SEND, cursp(), sym, 1));
+ if (val == NOVAL) { pop(); }
+ else { push(); }
+ mrb_gc_arena_restore(s->mrb, ai);
+ }
+ break;
+
case NODE_XSTR:
- if (val) {
+ {
char *p = (char*)tree->car;
size_t len = (intptr_t)tree->cdr;
int ai = mrb_gc_arena_save(s->mrb);
int sym = new_sym(s, mrb_intern_lit(s->mrb, "Kernel"));
int off = new_lit(s, mrb_str_new(s->mrb, p, len));
+ if (val == NOVAL) { push(); }
genop(s, MKOP_A(OP_OCLASS, cursp()));
genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
push();
@@ -2092,8 +2143,9 @@ codegen(codegen_scope *s, node *tree, int val)
pop();
sym = new_sym(s, mrb_intern_lit(s->mrb, "`"));
genop(s, MKOP_ABC(OP_SEND, cursp(), sym, 1));
+ if (val == NOVAL) { pop(); }
+ else { push(); }
mrb_gc_arena_restore(s->mrb, ai);
- push();
}
break;
@@ -2103,7 +2155,7 @@ codegen(codegen_scope *s, node *tree, int val)
char *p2 = (char*)tree->cdr;
int ai = mrb_gc_arena_save(s->mrb);
int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS));
- int off = new_lit(s, mrb_str_new(s->mrb, p1, strlen(p1)));
+ int off = new_lit(s, mrb_str_new_cstr(s->mrb, p1));
int argc = 1;
genop(s, MKOP_A(OP_OCLASS, cursp()));
@@ -2112,7 +2164,7 @@ codegen(codegen_scope *s, node *tree, int val)
genop(s, MKOP_ABx(OP_STRING, cursp(), off));
if (p2) {
push();
- off = new_lit(s, mrb_str_new(s->mrb, p2, strlen(p2)));
+ off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
genop(s, MKOP_ABx(OP_STRING, cursp(), off));
argc++;
pop();
@@ -2149,7 +2201,7 @@ codegen(codegen_scope *s, node *tree, int val)
n = tree->cdr->cdr;
if (n->car) {
p = (char*)n->car;
- off = new_lit(s, mrb_str_new(s->mrb, p, strlen(p)));
+ off = new_lit(s, mrb_str_new_cstr(s->mrb, p));
codegen(s, tree->car, VAL);
genop(s, MKOP_ABx(OP_STRING, cursp(), off));
pop();
@@ -2160,7 +2212,7 @@ codegen(codegen_scope *s, node *tree, int val)
int off;
push();
- off = new_lit(s, mrb_str_new(s->mrb, p2, strlen(p2)));
+ off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
genop(s, MKOP_ABx(OP_STRING, cursp(), off));
argc++;
pop();
@@ -2353,6 +2405,7 @@ codegen(codegen_scope *s, node *tree, int val)
genop(s, MKOP_A(OP_TCLASS, cursp()));
push();
genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_METHOD));
+ push(); pop();
pop();
genop(s, MKOP_AB(OP_METHOD, cursp(), sym));
if (val) {
@@ -2451,9 +2504,9 @@ scope_new(mrb_state *mrb, codegen_scope *prev, node *lv)
}
p->lineno = prev->lineno;
- // debug setting
+ /* debug setting */
p->debug_start_pos = 0;
- if(p->filename) {
+ if (p->filename) {
mrb_debug_info_alloc(mrb, p->irep);
p->irep->filename = p->filename;
p->irep->lines = p->lines;
@@ -2494,7 +2547,7 @@ scope_finish(codegen_scope *s)
mrb_debug_info_append_file(mrb, s->irep, s->debug_start_pos, s->pc);
fname_len = strlen(s->filename);
- fname = codegen_malloc(s, fname_len + 1);
+ fname = (char*)codegen_malloc(s, fname_len + 1);
memcpy(fname, s->filename, fname_len);
fname[fname_len] = '\0';
irep->filename = fname;
@@ -2554,8 +2607,7 @@ loop_break(codegen_scope *s, node *tree)
if (tree) {
genop_peep(s, MKOP_AB(OP_MOVE, loop->acc, cursp()), NOVAL);
}
- tmp = new_label(s);
- genop(s, MKOP_sBx(OP_JMP, loop->pc3));
+ tmp = genop(s, MKOP_sBx(OP_JMP, loop->pc3));
loop->pc3 = tmp;
}
else {
@@ -2579,14 +2631,15 @@ static void
codedump(mrb_state *mrb, mrb_irep *irep)
{
#ifdef ENABLE_STDIO
- uint32_t i;
+ int i;
int ai;
mrb_code c;
if (!irep) return;
printf("irep %p nregs=%d nlocals=%d pools=%d syms=%d reps=%d\n", irep,
irep->nregs, irep->nlocals, (int)irep->plen, (int)irep->slen, (int)irep->rlen);
- for (i=0; i<irep->ilen; i++) {
+
+ for (i = 0; i < (int)irep->ilen; i++) {
ai = mrb_gc_arena_save(mrb);
printf("%03d ", i);
c = irep->iseq[i];
@@ -2741,7 +2794,7 @@ codedump(mrb_state *mrb, mrb_irep *irep)
break;
case OP_LAMBDA:
- printf("OP_LAMBDA\tR%d\tI(%+d)\t%d\n", GETARG_A(c), GETARG_b(c), GETARG_c(c));
+ printf("OP_LAMBDA\tR%d\tI(%+d)\t%d\n", GETARG_A(c), GETARG_b(c)+1, GETARG_c(c));
break;
case OP_RANGE:
printf("OP_RANGE\tR%d\tR%d\t%d\n", GETARG_A(c), GETARG_B(c), GETARG_C(c));
@@ -2852,7 +2905,7 @@ codedump(mrb_state *mrb, mrb_irep *irep)
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]));
break;
case OP_EXEC:
- printf("OP_EXEC\tR%d\tI(%+d)\n", GETARG_A(c), GETARG_Bx(c));
+ printf("OP_EXEC\tR%d\tI(%+d)\n", GETARG_A(c), GETARG_Bx(c)+1);
break;
case OP_SCLASS:
printf("OP_SCLASS\tR%d\tR%d\n", GETARG_A(c), GETARG_B(c));
@@ -2861,10 +2914,14 @@ codedump(mrb_state *mrb, mrb_irep *irep)
printf("OP_TCLASS\tR%d\n", GETARG_A(c));
break;
case OP_ERR:
- printf("OP_ERR\tL(%d)\n", GETARG_Bx(c));
+ {
+ mrb_value v = irep->pool[GETARG_Bx(c)];
+ mrb_value s = mrb_str_dump(mrb, mrb_str_new(mrb, RSTRING_PTR(v), RSTRING_LEN(v)));
+ printf("OP_ERR\t%s\n", RSTRING_PTR(s));
+ }
break;
case OP_EPUSH:
- printf("OP_EPUSH\t:I(%+d)\n", GETARG_Bx(c));
+ printf("OP_EPUSH\t:I(%+d)\n", GETARG_Bx(c)+1);
break;
case OP_ONERR:
printf("OP_ONERR\t%03d\n", i+GETARG_sBx(c));
@@ -2923,15 +2980,16 @@ mrb_generate_code(mrb_state *mrb, parser_state *p)
scope->parser = p;
scope->filename = p->filename;
scope->filename_index = p->current_filename_index;
- if (setjmp(scope->jmp) == 0) {
- // prepare irep
+
+ MRB_TRY(&scope->jmp) {
+ /* prepare irep */
codegen(scope, p->tree, NOVAL);
proc = mrb_proc_new(mrb, scope->irep);
mrb_irep_decref(mrb, scope->irep);
mrb_pool_close(scope->mpool);
return proc;
}
- else {
+ MRB_CATCH(&scope->jmp) {
if (scope->filename == scope->irep->filename) {
scope->irep->filename = NULL;
}
@@ -2939,4 +2997,5 @@ mrb_generate_code(mrb_state *mrb, parser_state *p)
mrb_pool_close(scope->mpool);
return NULL;
}
+ MRB_END_EXC(&scope->jmp);
}