diff options
Diffstat (limited to 'src/codegen.c')
| -rw-r--r-- | src/codegen.c | 581 |
1 files changed, 357 insertions, 224 deletions
diff --git a/src/codegen.c b/src/codegen.c index 34ccd616f..c869285d9 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -5,16 +5,19 @@ */ #include <ctype.h> +#include <limits.h> #include <stdlib.h> #include <string.h> #include "mruby.h" #include "mruby/compile.h" -#include "mruby/irep.h" +#include "mruby/proc.h" #include "mruby/numeric.h" #include "mruby/string.h" +#include "mruby/debug.h" #include "node.h" #include "opcode.h" #include "re.h" +#include "mrb_throw.h" typedef mrb_ast_node node; typedef struct mrb_parser_state parser_state; @@ -25,7 +28,7 @@ enum looptype { LOOP_FOR, LOOP_BEGIN, LOOP_RESCUE, -} type; +}; struct loopinfo { enum looptype type; @@ -37,7 +40,7 @@ struct loopinfo { typedef struct scope { mrb_state *mrb; mrb_pool *mpool; - jmp_buf jmp; + struct mrb_jmpbuf jmp; struct scope *prev; @@ -51,22 +54,25 @@ typedef struct scope { struct loopinfo *loop; int ensure_level; - char *filename; - short lineno; + char const *filename; + uint16_t lineno; mrb_code *iseq; - short *lines; + uint16_t *lines; int icapa; mrb_irep *irep; size_t pcapa; - int scapa; + size_t scapa; + size_t rcapa; int nlocals; int nregs; int ai; - int idx; + int debug_start_pos; + uint16_t filename_index; + parser_state* parser; } codegen_scope; static codegen_scope* scope_new(mrb_state *mrb, codegen_scope *prev, node *lv); @@ -85,10 +91,10 @@ codegen_error(codegen_scope *s, const char *message) { if (!s) return; while (s->prev) { + codegen_scope *tmp = s->prev; mrb_pool_close(s->mpool); - s = s->prev; + s = tmp; } - mrb_pool_close(s->mpool); #ifdef ENABLE_STDIO if (s->filename && s->lineno) { fprintf(stderr, "codegen error:%s:%d: %s\n", s->filename, s->lineno, message); @@ -97,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* @@ -109,19 +115,19 @@ codegen_palloc(codegen_scope *s, size_t len) return p; } -void* +static void* codegen_malloc(codegen_scope *s, size_t len) { - void *p = mrb_malloc(s->mrb, len); + void *p = mrb_malloc_simple(s->mrb, len); if (!p) codegen_error(s, "mrb_malloc"); return p; } -void* +static void* codegen_realloc(codegen_scope *s, void *p, size_t len) { - p = mrb_realloc(s->mrb, p, len); + p = mrb_realloc_simple(s->mrb, p, len); if (!p && len > 0) codegen_error(s, "mrb_realloc"); return p; @@ -134,27 +140,28 @@ 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) { s->icapa *= 2; s->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->icapa); if (s->lines) { - s->lines = (short*)codegen_realloc(s, s->lines, sizeof(short)*s->icapa); + s->lines = (uint16_t*)codegen_realloc(s, s->lines, sizeof(short)*s->icapa); + s->irep->lines = s->lines; } } s->iseq[s->pc] = 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 */ @@ -167,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: @@ -194,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: @@ -207,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: @@ -223,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: @@ -239,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; @@ -248,41 +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; - case OP_LOADI: - s->iseq[s->pc-1] = MKOP_AsBx(OP_LOADI, 0, GETARG_sBx(i0)); - genop(s, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL)); - return; - case OP_ARRAY: - case OP_HASH: - case OP_RANGE: - case OP_AREF: - case OP_GETUPVAR: - s->iseq[s->pc-1] = MKOP_ABC(c0, 0, GETARG_B(i0), GETARG_C(i0)); - genop(s, MKOP_AB(OP_RETURN, 0, 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: @@ -292,31 +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; - case OP_LOADSYM: - case OP_GETGLOBAL: - case OP_GETIV: - case OP_GETCV: - case OP_GETCONST: - case OP_GETSPECIAL: - case OP_LOADL: - case OP_STRING: - s->iseq[s->pc-1] = MKOP_ABx(c0, 0, GETARG_Bx(i0)); - genop(s, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL)); - return; - case OP_SCLASS: - s->iseq[s->pc-1] = MKOP_AB(c0, GETARG_A(i), GETARG_B(i0)); - genop(s, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL)); - return; - case OP_LOADNIL: - case OP_LOADSELF: - case OP_LOADT: - case OP_LOADF: - case OP_OCLASS: - s->iseq[s->pc-1] = MKOP_A(c0, 0); - genop(s, MKOP_AB(OP_RETURN, 0, 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)) { @@ -340,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) { @@ -349,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 @@ -427,34 +408,65 @@ static inline int new_lit(codegen_scope *s, mrb_value val) { size_t i; + mrb_value *pv; switch (mrb_type(val)) { case MRB_TT_STRING: for (i=0; i<s->irep->plen; i++) { - mrb_value pv = s->irep->pool[i]; mrb_int len; + pv = &s->irep->pool[i]; - if (mrb_type(pv) != MRB_TT_STRING) continue; - if ((len = RSTRING_LEN(pv)) != RSTRING_LEN(val)) continue; - if (memcmp(RSTRING_PTR(pv), RSTRING_PTR(val), len) == 0) + if (mrb_type(*pv) != MRB_TT_STRING) continue; + if ((len = RSTRING_LEN(*pv)) != RSTRING_LEN(val)) continue; + if (memcmp(RSTRING_PTR(*pv), RSTRING_PTR(val), len) == 0) return i; } break; case MRB_TT_FLOAT: - default: for (i=0; i<s->irep->plen; i++) { - if (mrb_obj_equal(s->mrb, s->irep->pool[i], val)) return i; + pv = &s->irep->pool[i]; + if (mrb_type(*pv) != MRB_TT_FLOAT) continue; + if (mrb_float(*pv) == mrb_float(val)) return i; } break; + case MRB_TT_FIXNUM: + for (i=0; i<s->irep->plen; i++) { + pv = &s->irep->pool[i]; + if (!mrb_fixnum_p(*pv)) continue; + if (mrb_fixnum(*pv) == mrb_fixnum(val)) return i; + } + break; + default: + /* should not happen */ + return 0; } if (s->irep->plen == s->pcapa) { s->pcapa *= 2; s->irep->pool = (mrb_value *)codegen_realloc(s, s->irep->pool, sizeof(mrb_value)*s->pcapa); } - s->irep->pool[s->irep->plen] = val; + + pv = &s->irep->pool[s->irep->plen]; i = s->irep->plen++; + switch (mrb_type(val)) { + case MRB_TT_STRING: + *pv = mrb_str_pool(s->mrb, val); + break; + + case MRB_TT_FLOAT: +#ifdef MRB_WORD_BOXING + *pv = mrb_float_pool(s->mrb, mrb_float(val)); + break; +#endif + case MRB_TT_FIXNUM: + *pv = val; + break; + + default: + /* should not happen */ + break; + } return i; } @@ -529,21 +541,20 @@ static void for_body(codegen_scope *s, node *tree) { codegen_scope *prev = s; - int idx, base = s->idx; + int idx; struct loopinfo *lp; 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); - idx = s->idx; 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)); @@ -563,20 +574,18 @@ for_body(codegen_scope *s, node *tree) loop_pop(s, NOVAL); scope_finish(s); s = prev; - genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx - base, OP_L_BLOCK)); + genop(s, MKOP_Abc(OP_LAMBDA, cursp(), s->irep->rlen-1, OP_L_BLOCK)); pop(); - idx = new_msym(s, mrb_intern2(s->mrb, "each", 4)); + idx = new_msym(s, mrb_intern_lit(s->mrb, "each")); genop(s, MKOP_ABC(OP_SENDB, cursp(), idx, 0)); } static int lambda_body(codegen_scope *s, node *tree, int blk) { - int idx, base = s->idx; mrb_code c; - + codegen_scope *parent = s; s = scope_new(s->mrb, s, tree->car); - idx = s->idx; s->mscope = !blk; if (blk) { @@ -655,32 +664,36 @@ lambda_body(codegen_scope *s, node *tree, int blk) loop_pop(s, NOVAL); } scope_finish(s); - - return idx - base; + return parent->irep->rlen - 1; } static int -scope_body(codegen_scope *s, node *tree) +scope_body(codegen_scope *s, node *tree, int val) { codegen_scope *scope = scope_new(s->mrb, s, tree->car); - int idx = scope->idx; codegen(scope, tree->cdr, VAL); 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, OP_R_NORMAL), NOVAL); + genop_peep(scope, MKOP_AB(OP_RETURN, scope->sp-1, OP_R_NORMAL), NOVAL); } } scope_finish(scope); - - return idx - s->idx; + if (!s->irep) { + /* should not happen */ + return 0; + } + return s->irep->rlen - 1; } static mrb_bool @@ -697,32 +710,44 @@ 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(len <= SIZE_MAX); + memcpy(name2, name, (size_t)len); name2[len] = '='; name2[len+1] = '\0'; - return mrb_intern2(s->mrb, name2, len+1); + return mrb_intern(s->mrb, name2, len+1); } static int gen_values(codegen_scope *s, node *t, int val) { int n = 0; + int is_splat; while (t) { - if (n >= 127 || (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); genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), n)); push(); codegen(s, t->car, VAL); pop(); pop(); - genop(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1)); + if (is_splat) { + genop(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1)); + } + else { + genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1)); + } t = t->cdr; while (t) { push(); @@ -747,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; @@ -796,7 +821,7 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val) } 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] == '+') { @@ -959,17 +984,20 @@ gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val) } } } + else { + pop(); + } } static void gen_send_intern(codegen_scope *s) { pop(); - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern2(s->mrb, "intern", 6)), 0)); + genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "intern")), 0)); push(); } static void -gen_literal_array(codegen_scope *s, node *tree, int sym, int val) +gen_literal_array(codegen_scope *s, node *tree, mrb_bool sym, int val) { if (val) { int i = 0, j = 0; @@ -1057,7 +1085,7 @@ readint_float(codegen_scope *s, const char *p, int base) } static mrb_int -readint_mrb_int(codegen_scope *s, const char *p, int base, int neg, int *overflow) +readint_mrb_int(codegen_scope *s, const char *p, int base, mrb_bool neg, mrb_bool *overflow) { const char *e = p + strlen(p); mrb_int result = 0; @@ -1104,6 +1132,15 @@ codegen(codegen_scope *s, node *tree, int val) int nt; if (!tree) return; + + if (s->irep && s->pc > 0 && 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); + s->debug_start_pos = s->pc; + s->filename_index = tree->filename_index; + s->filename = mrb_parser_get_filename(s->parser, tree->filename_index); + } + nt = (intptr_t)tree->car; s->lineno = tree->lineno; tree = tree->cdr; @@ -1124,8 +1161,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) { @@ -1133,8 +1169,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; @@ -1156,21 +1191,24 @@ codegen(codegen_scope *s, node *tree, int val) codegen(s, n4->car, VAL); } else { - genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern2(s->mrb, "StandardError", 13)))); + genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "StandardError")))); push(); } genop(s, MKOP_AB(OP_MOVE, cursp(), exc)); pop(); - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern2(s->mrb, "===", 3)), 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(); @@ -1181,8 +1219,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(); @@ -1215,7 +1252,7 @@ codegen(codegen_scope *s, node *tree, int val) genop(s, MKOP_Bx(OP_EPUSH, 0)); s->ensure_level++; codegen(s, tree->car, val); - idx = scope_body(s, tree->cdr); + idx = scope_body(s, tree->cdr, NOVAL); s->iseq[epush] = MKOP_Bx(OP_EPUSH, idx); s->ensure_level--; genop_peep(s, MKOP_A(OP_EPOP, 1), NOVAL); @@ -1247,8 +1284,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)) { @@ -1257,17 +1293,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); @@ -1285,9 +1319,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); } @@ -1298,9 +1331,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); } @@ -1310,8 +1342,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); @@ -1327,8 +1358,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); @@ -1365,39 +1395,47 @@ codegen(codegen_scope *s, node *tree, int val) if (head) { genop(s, MKOP_AB(OP_MOVE, cursp(), head)); pop(); - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern2(s->mrb, "===", 3)), 1)); + if ((intptr_t)n->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)); + } } 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; } if (val) { + int pos = cursp(); genop(s, MKOP_A(OP_LOADNIL, cursp())); + if (pos3) dispatch_linked(s, pos3); + pop(); + genop(s, MKOP_AB(OP_MOVE, cursp(), pos)); push(); } - if (pos3) dispatch_linked(s, pos3); + else if (pos3) { + dispatch_linked(s, pos3); + } } break; case NODE_SCOPE: - scope_body(s, tree); + scope_body(s, tree, NOVAL); break; case NODE_FCALL: @@ -1467,16 +1505,32 @@ 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(); } } @@ -1499,7 +1553,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); @@ -1548,7 +1602,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); } @@ -1558,7 +1612,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; @@ -1569,8 +1623,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); @@ -1705,7 +1758,7 @@ codegen(codegen_scope *s, node *tree, int val) } pop_n(n+1); if (sendv) n = CALL_MAXARGS; - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern2(s->mrb, "call", 4)), n)); + genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "call")), n)); if (val) push(); } break; @@ -1872,7 +1925,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)); @@ -1881,7 +1934,7 @@ codegen(codegen_scope *s, node *tree, int val) break; case NODE_ARG: - // should not happen + /* should not happen */ break; case NODE_BLOCK_ARG: @@ -1894,7 +1947,7 @@ codegen(codegen_scope *s, node *tree, int val) int base = (intptr_t)tree->cdr->car; mrb_int i; mrb_code co; - int overflow; + mrb_bool overflow; i = readint_mrb_int(s, p, base, FALSE, &overflow); if (overflow) { @@ -1950,7 +2003,7 @@ codegen(codegen_scope *s, node *tree, int val) int base = (intptr_t)tree->cdr->car; mrb_int i; mrb_code co; - int overflow; + mrb_bool overflow; i = readint_mrb_int(s, p, base, TRUE, &overflow); if (overflow) { @@ -1975,7 +2028,7 @@ codegen(codegen_scope *s, node *tree, int val) default: { - int sym = new_msym(s, mrb_intern2(s->mrb, "-", 1)); + int sym = new_msym(s, mrb_intern_lit(s->mrb, "-")); genop(s, MKOP_ABx(OP_LOADI, cursp(), 0)); push(); @@ -2038,23 +2091,58 @@ 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_intern2(s->mrb, "Kernel", 6)); + 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(); genop(s, MKOP_ABx(OP_STRING, cursp(), off)); pop(); - sym = new_sym(s, mrb_intern2(s->mrb, "`", 1)); + 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; @@ -2063,8 +2151,8 @@ codegen(codegen_scope *s, node *tree, int val) char *p1 = (char*)tree->car; char *p2 = (char*)tree->cdr; int ai = mrb_gc_arena_save(s->mrb); - int sym = new_sym(s, mrb_intern2(s->mrb, REGEXP_CLASS, REGEXP_CLASS_CSTR_LEN)); - int off = new_lit(s, mrb_str_new(s->mrb, p1, strlen(p1))); + int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS)); + int off = new_lit(s, mrb_str_new_cstr(s->mrb, p1)); int argc = 1; genop(s, MKOP_A(OP_OCLASS, cursp())); @@ -2073,13 +2161,13 @@ 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(); } pop(); - sym = new_sym(s, mrb_intern2(s->mrb, "compile", 7)); + sym = new_sym(s, mrb_intern_lit(s->mrb, "compile")); genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc)); mrb_gc_arena_restore(s->mrb, ai); push(); @@ -2090,7 +2178,7 @@ codegen(codegen_scope *s, node *tree, int val) if (val) { node *n = tree->car; int ai = mrb_gc_arena_save(s->mrb); - int sym = new_sym(s, mrb_intern2(s->mrb, REGEXP_CLASS, REGEXP_CLASS_CSTR_LEN)); + int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS)); int argc = 1; int off; char *p; @@ -2110,7 +2198,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(); @@ -2121,13 +2209,13 @@ 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(); } pop(); - sym = new_sym(s, mrb_intern2(s->mrb, "compile", 7)); + sym = new_sym(s, mrb_intern_lit(s->mrb, "compile")); genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc)); mrb_gc_arena_restore(s->mrb, ai); push(); @@ -2192,7 +2280,7 @@ codegen(codegen_scope *s, node *tree, int val) { int a = new_msym(s, sym(tree->car)); int b = new_msym(s, sym(tree->cdr)); - int c = new_msym(s, mrb_intern2(s->mrb, "alias_method", 12)); + int c = new_msym(s, mrb_intern_lit(s->mrb,"alias_method")); genop(s, MKOP_A(OP_TCLASS, cursp())); push(); @@ -2211,7 +2299,7 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_UNDEF: { - int undef = new_msym(s, mrb_intern2(s->mrb, "undef_method", 12)); + int undef = new_msym(s, mrb_intern_lit(s->mrb, "undef_method")); int num = 0; node *t = tree; @@ -2257,7 +2345,7 @@ codegen(codegen_scope *s, node *tree, int val) pop(); pop(); idx = new_msym(s, sym(tree->car->cdr)); genop(s, MKOP_AB(OP_CLASS, cursp(), idx)); - idx = scope_body(s, tree->cdr->cdr->car); + idx = scope_body(s, tree->cdr->cdr->car, val); genop(s, MKOP_ABx(OP_EXEC, cursp(), idx)); if (val) { push(); @@ -2283,7 +2371,7 @@ codegen(codegen_scope *s, node *tree, int val) pop(); idx = new_msym(s, sym(tree->car->cdr)); genop(s, MKOP_AB(OP_MODULE, cursp(), idx)); - idx = scope_body(s, tree->cdr->car); + idx = scope_body(s, tree->cdr->car, val); genop(s, MKOP_ABx(OP_EXEC, cursp(), idx)); if (val) { push(); @@ -2298,7 +2386,7 @@ 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); + idx = scope_body(s, tree->cdr->car, val); genop(s, MKOP_ABx(OP_EXEC, cursp(), idx)); if (val) { push(); @@ -2317,7 +2405,7 @@ codegen(codegen_scope *s, node *tree, int val) pop(); genop(s, MKOP_AB(OP_METHOD, cursp(), sym)); if (val) { - genop(s, MKOP_A(OP_LOADNIL, cursp())); + genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym)); push(); } } @@ -2337,7 +2425,7 @@ codegen(codegen_scope *s, node *tree, int val) pop(); genop(s, MKOP_AB(OP_METHOD, cursp(), sym)); if (val) { - genop(s, MKOP_A(OP_LOADNIL, cursp())); + genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym)); push(); } } @@ -2352,6 +2440,21 @@ codegen(codegen_scope *s, node *tree, int val) } } +static void +scope_add_irep(codegen_scope *s, mrb_irep *irep) +{ + if (s->irep == NULL) { + s->irep = irep; + return; + } + if (s->irep->rlen == s->rcapa) { + s->rcapa *= 2; + s->irep->reps = (mrb_irep**)codegen_realloc(s, s->irep->reps, sizeof(mrb_irep*)*s->rcapa); + } + s->irep->reps[s->irep->rlen] = irep; + s->irep->rlen++; +} + static codegen_scope* scope_new(mrb_state *mrb, codegen_scope *prev, node *lv) { @@ -2369,17 +2472,21 @@ scope_new(mrb_state *mrb, codegen_scope *prev, node *lv) p->mscope = 0; p->irep = mrb_add_irep(mrb); - p->idx = p->irep->idx; + scope_add_irep(prev, p->irep); + + p->rcapa = 8; + p->irep->reps = (mrb_irep**)mrb_malloc(mrb, sizeof(mrb_irep*)*p->rcapa); p->icapa = 1024; p->iseq = (mrb_code*)mrb_malloc(mrb, sizeof(mrb_code)*p->icapa); + p->irep->iseq = p->iseq; p->pcapa = 32; p->irep->pool = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value)*p->pcapa); p->irep->plen = 0; p->scapa = 256; - p->irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*256); + p->irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*p->scapa); p->irep->slen = 0; p->lv = lv; @@ -2389,9 +2496,23 @@ scope_new(mrb_state *mrb, codegen_scope *prev, node *lv) p->filename = prev->filename; if (p->filename) { - p->lines = (short*)mrb_malloc(mrb, sizeof(short)*p->icapa); + 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) { + mrb_debug_info_alloc(mrb, p->irep); + p->irep->filename = p->filename; + p->irep->lines = p->lines; + } + else { + p->irep->debug_info = NULL; + } + p->parser = prev->parser; + p->filename_index = prev->filename_index; + return p; } @@ -2414,11 +2535,15 @@ scope_finish(codegen_scope *s) 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->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) { + s->irep->filename = mrb_parser_get_filename(s->parser, s->filename_index); + 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; @@ -2478,8 +2603,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 { @@ -2500,18 +2624,19 @@ loop_pop(codegen_scope *s, int val) } static void -codedump(mrb_state *mrb, int n) +codedump(mrb_state *mrb, mrb_irep *irep) { #ifdef ENABLE_STDIO - mrb_irep *irep = mrb->irep[n]; - uint32_t i; + int i; int ai; mrb_code c; if (!irep) return; - printf("irep %d nregs=%d nlocals=%d pools=%d syms=%d\n", n, - irep->nregs, irep->nlocals, (int)irep->plen, (int)irep->slen); - for (i=0; i<irep->ilen; i++) { + 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); + + mrb_assert(irep->ilen <= INT_MAX); + for (i = 0; i < (int)(irep->ilen); i++) { ai = mrb_gc_arena_save(mrb); printf("%03d ", i); c = irep->iseq[i]; @@ -2666,7 +2791,7 @@ codedump(mrb_state *mrb, int n) 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)); @@ -2753,9 +2878,8 @@ codedump(mrb_state *mrb, int n) break; case OP_STRING: { - mrb_value s = irep->pool[GETARG_Bx(c)]; - - s = mrb_str_dump(mrb, s); + 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_STRING\tR%d\t%s\n", GETARG_A(c), RSTRING_PTR(s)); } break; @@ -2778,7 +2902,7 @@ codedump(mrb_state *mrb, int n) mrb_sym2name(mrb, irep->syms[GETARG_B(c)])); break; case OP_EXEC: - printf("OP_EXEC\tR%d\tI(%d)\n", GETARG_A(c), n+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)); @@ -2787,10 +2911,14 @@ codedump(mrb_state *mrb, int n) 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", 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)); @@ -2819,47 +2947,52 @@ codedump(mrb_state *mrb, int n) #endif } -void -codedump_all(mrb_state *mrb, int start) +static void +codedump_recur(mrb_state *mrb, mrb_irep *irep) { size_t i; - for (i=start; i<mrb->irep_len; i++) { - codedump(mrb, i); + codedump(mrb, irep); + for (i=0; i<irep->rlen; i++) { + codedump_recur(mrb, irep->reps[i]); } } -static int -codegen_start(mrb_state *mrb, parser_state *p) +void +mrb_codedump_all(mrb_state *mrb, struct RProc *proc) +{ + codedump_recur(mrb, proc->body.irep); +} + +struct RProc* +mrb_generate_code(mrb_state *mrb, parser_state *p) { codegen_scope *scope = scope_new(mrb, 0, 0); + struct RProc *proc; if (!scope) { - return -1; + return NULL; } scope->mrb = mrb; - if (p->filename) { - scope->filename = p->filename; - } - if (setjmp(scope->jmp) == 0) { - // prepare irep + scope->parser = p; + scope->filename = p->filename; + scope->filename_index = p->current_filename_index; + + 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 0; + return proc; } - else { - return -1; + MRB_CATCH(&scope->jmp) { + if (scope->filename == scope->irep->filename) { + scope->irep->filename = NULL; + } + mrb_irep_decref(mrb, scope->irep); + mrb_pool_close(scope->mpool); + return NULL; } -} - -int -mrb_generate_code(mrb_state *mrb, parser_state *p) -{ - int start = mrb->irep_len; - int n; - - n = codegen_start(mrb, p); - if (n < 0) return n; - - return start; + MRB_END_EXC(&scope->jmp); } |
