diff options
Diffstat (limited to 'mrbgems/mruby-compiler/core/codegen.c')
| -rw-r--r-- | mrbgems/mruby-compiler/core/codegen.c | 115 |
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; |
