summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/mruby-compiler/core/codegen.c
diff options
context:
space:
mode:
Diffstat (limited to 'mrbgems/mruby-compiler/core/codegen.c')
-rw-r--r--mrbgems/mruby-compiler/core/codegen.c115
1 files changed, 69 insertions, 46 deletions
diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c
index 927cc3a0f..8379dfd97 100644
--- a/mrbgems/mruby-compiler/core/codegen.c
+++ b/mrbgems/mruby-compiler/core/codegen.c
@@ -102,12 +102,13 @@ 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_sym && s->lineno) {
- const char *filename = mrb_sym2name_len(s->mrb, s->filename_sym, NULL);
+ const char *filename = mrb_sym_name_len(s->mrb, s->filename_sym, NULL);
fprintf(stderr, "codegen error:%s:%d: %s\n", filename, s->lineno, message);
}
else {
@@ -272,8 +273,7 @@ genop_W(codegen_scope *s, mrb_code i, uint32_t a)
#define NOVAL 0
#define VAL 1
-//static
-mrb_bool
+static mrb_bool
no_optimize(codegen_scope *s)
{
if (s && s->parser && s->parser->no_optimize)
@@ -291,7 +291,7 @@ on_eval(codegen_scope *s)
}
struct mrb_insn_data
-mrb_decode_insn(mrb_code *pc)
+mrb_decode_insn(const mrb_code *pc)
{
struct mrb_insn_data data = { 0 };
mrb_code insn = READ_B();
@@ -559,7 +559,7 @@ new_lit(codegen_scope *s, mrb_value val)
mrb_int len;
pv = &s->irep->pool[i];
- if (mrb_type(*pv) != MRB_TT_STRING) continue;
+ if (!mrb_string_p(*pv)) continue;
if ((len = RSTRING_LEN(*pv)) != RSTRING_LEN(val)) continue;
if (memcmp(RSTRING_PTR(*pv), RSTRING_PTR(val), len) == 0)
return i;
@@ -570,7 +570,7 @@ new_lit(codegen_scope *s, mrb_value val)
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_p(*pv)) continue;
f1 = mrb_float(*pv);
f2 = mrb_float(val);
if (f1 == f2 && !signbit(f1) == !signbit(f2)) return i;
@@ -686,9 +686,6 @@ for_body(codegen_scope *s, node *tree)
codegen(s, tree->cdr->car, VAL);
/* generate loop-block */
s = scope_new(s->mrb, s, NULL);
- if (s == NULL) {
- raise_error(prev, "unexpected scope");
- }
push(); /* push for a block parameter */
@@ -724,9 +721,6 @@ lambda_body(codegen_scope *s, node *tree, int blk)
{
codegen_scope *parent = s;
s = scope_new(s->mrb, s, tree->car);
- if (s == NULL) {
- raise_error(parent, "unexpected scope");
- }
s->mscope = !blk;
@@ -888,9 +882,6 @@ static int
scope_body(codegen_scope *s, node *tree, int val)
{
codegen_scope *scope = scope_new(s->mrb, s, tree->car);
- if (scope == NULL) {
- codegen_error(s, "unexpected scope");
- }
codegen(scope, tree->cdr, VAL);
gen_return(scope, OP_RETURN, scope->sp-1);
@@ -922,7 +913,7 @@ attrsym(codegen_scope *s, mrb_sym a)
mrb_int len;
char *name2;
- name = mrb_sym2name_len(s->mrb, a, &len);
+ name = mrb_sym_name_len(s->mrb, a, &len);
name2 = (char *)codegen_palloc(s,
(size_t)len
+ 1 /* '=' */
@@ -956,7 +947,12 @@ gen_values(codegen_scope *s, node *t, int val, int extra)
}
else {
pop_n(n);
- genop_2(s, OP_ARRAY, cursp(), n);
+ if (n == 0 && is_splat) {
+ genop_1(s, OP_LOADNIL, cursp());
+ }
+ else {
+ genop_2(s, OP_ARRAY, cursp(), n);
+ }
push();
codegen(s, t->car, VAL);
pop(); pop();
@@ -1041,7 +1037,7 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe)
pop_n(n+1);
{
mrb_int symlen;
- const char *symname = mrb_sym2name_len(s->mrb, sym, &symlen);
+ const char *symname = mrb_sym_name_len(s->mrb, sym, &symlen);
if (!noop && symlen == 1 && symname[0] == '+' && n == 1) {
gen_addsub(s, OP_ADD, cursp());
@@ -1401,7 +1397,7 @@ codegen(codegen_scope *s, node *tree, int val)
}
if (s->irep && s->filename_index != tree->filename_index) {
mrb_sym fname = mrb_parser_get_filename(s->parser, s->filename_index);
- const char *filename = mrb_sym2name_len(s->mrb, fname, NULL);
+ const char *filename = mrb_sym_name_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);
@@ -1553,7 +1549,7 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_IF:
{
- int pos1, pos2;
+ int pos1, pos2, nil_p = FALSE;
node *elsepart = tree->cdr->cdr->car;
if (!tree->car) {
@@ -1570,32 +1566,59 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_NIL:
codegen(s, elsepart, val);
goto exit;
+ case NODE_CALL:
+ {
+ node *n = tree->car->cdr;
+ mrb_sym mid = nsym(n->cdr->car);
+ mrb_sym mnil = mrb_intern_lit(s->mrb, "nil?");
+ if (mid == mnil && n->cdr->cdr->car == NULL) {
+ nil_p = TRUE;
+ codegen(s, n->car, VAL);
+ }
+ }
+ break;
+ }
+ if (!nil_p) {
+ codegen(s, tree->car, VAL);
}
- codegen(s, tree->car, VAL);
pop();
- pos1 = genjmp2(s, OP_JMPNOT, cursp(), 0, val);
-
- codegen(s, tree->cdr->car, val);
- if (elsepart) {
+ if (val || tree->cdr->car) {
+ if (nil_p) {
+ pos2 = genjmp2(s, OP_JMPNIL, cursp(), 0, val);
+ pos1 = genjmp(s, OP_JMP, 0);
+ dispatch(s, pos2);
+ }
+ else {
+ pos1 = genjmp2(s, OP_JMPNOT, cursp(), 0, val);
+ }
+ codegen(s, tree->cdr->car, val);
if (val) pop();
- pos2 = genjmp(s, OP_JMP, 0);
- dispatch(s, pos1);
- codegen(s, elsepart, val);
- dispatch(s, pos2);
- }
- else {
- if (val) {
- pop();
+ if (elsepart || val) {
pos2 = genjmp(s, OP_JMP, 0);
dispatch(s, pos1);
- genop_1(s, OP_LOADNIL, cursp());
+ codegen(s, elsepart, val);
dispatch(s, pos2);
- push();
}
else {
dispatch(s, pos1);
}
}
+ else { /* empty then-part */
+ if (elsepart) {
+ if (nil_p) {
+ pos1 = genjmp2(s, OP_JMPNIL, cursp(), 0, val);
+ }
+ else {
+ pos1 = genjmp2(s, OP_JMPIF, cursp(), 0, val);
+ }
+ codegen(s, elsepart, val);
+ dispatch(s, pos1);
+ }
+ else if (val && !nil_p) {
+ genop_1(s, OP_LOADNIL, cursp());
+ push();
+ }
+ }
}
break;
@@ -1955,7 +1978,7 @@ codegen(codegen_scope *s, node *tree, int val)
{
mrb_sym sym = nsym(tree->cdr->car);
mrb_int len;
- const char *name = mrb_sym2name_len(s->mrb, sym, &len);
+ const char *name = mrb_sym_name_len(s->mrb, sym, &len);
int idx, callargs = -1, vsp = -1;
if ((len == 2 && name[0] == '|' && name[1] == '|') &&
@@ -2353,10 +2376,6 @@ codegen(codegen_scope *s, node *tree, int val)
}
break;
- case NODE_DEFINED:
- codegen(s, tree, val);
- break;
-
case NODE_BACK_REF:
if (val) {
char buf[] = {'$', nchar(tree)};
@@ -2373,7 +2392,7 @@ codegen(codegen_scope *s, node *tree, int val)
mrb_value str;
int sym;
- str = mrb_format(mrb, "$%S", mrb_fixnum_value(nint(tree)));
+ str = mrb_format(mrb, "$%d", nint(tree));
sym = new_sym(s, mrb_intern_str(mrb, str));
genop_2(s, OP_GETGV, cursp(), sym);
push();
@@ -2944,7 +2963,11 @@ scope_new(mrb_state *mrb, codegen_scope *prev, node *lv)
mrb_pool *pool = mrb_pool_open(mrb);
codegen_scope *p = (codegen_scope *)mrb_pool_alloc(pool, sizeof(codegen_scope));
- if (!p) return NULL;
+ if (!p) {
+ if (prev)
+ codegen_error(prev, "unexpected scope");
+ return NULL;
+ }
*p = codegen_scope_zero;
p->mrb = mrb;
p->mpool = pool;
@@ -3020,6 +3043,9 @@ scope_finish(codegen_scope *s)
mrb_state *mrb = s->mrb;
mrb_irep *irep = s->irep;
+ 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);
@@ -3030,7 +3056,7 @@ scope_finish(codegen_scope *s)
irep->reps = (mrb_irep**)codegen_realloc(s, irep->reps, sizeof(mrb_irep*)*irep->rlen);
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);
+ const char *filename = mrb_sym_name_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);
@@ -3134,9 +3160,6 @@ generate_code(mrb_state *mrb, parser_state *p, int val)
struct RProc *proc;
struct mrb_jmpbuf *prev_jmp = mrb->jmp;
- if (!scope) {
- return NULL;
- }
scope->mrb = mrb;
scope->parser = p;
scope->filename_sym = p->filename_sym;