diff options
Diffstat (limited to 'src/codegen.c')
| -rw-r--r-- | src/codegen.c | 159 |
1 files changed, 124 insertions, 35 deletions
diff --git a/src/codegen.c b/src/codegen.c index d71c0bbd2..bbce4aac2 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -4,8 +4,6 @@ ** See Copyright Notice in mruby.h */ -#define CODEGEN_DUMP - #include "mruby.h" #include "mruby/string.h" #include "mruby/irep.h" @@ -49,7 +47,7 @@ typedef struct scope { int pc; int lastlabel; int ainfo:15; - int mscope:1; + mrb_bool mscope:1; struct loopinfo *loop; int ensure_level; @@ -379,6 +377,7 @@ dispatch(codegen_scope *s, int pc) fprintf(stderr, "bug: dispatch on non JMP op\n"); #endif scope_error(s); + break; } s->iseq[pc] = MKOP_AsBx(c, GETARG_A(i), diff); } @@ -540,11 +539,11 @@ for_body(codegen_scope *s, node *tree) // generate loop variable n2 = tree->car; if (n2->car && !n2->car->cdr && !n2->cdr) { - genop(s, MKOP_Ax(OP_ENTER, 1<<18)); + genop(s, MKOP_Ax(OP_ENTER, 0x40000)); gen_assignment(s, n2->car->car, 1, NOVAL); } else { - genop(s, MKOP_Ax(OP_ENTER, 1<<18)); + genop(s, MKOP_Ax(OP_ENTER, 0x40000)); gen_vmassignment(s, n2, 1, VAL); } codegen(s, tree->cdr->cdr->car, VAL); @@ -559,7 +558,7 @@ for_body(codegen_scope *s, node *tree) s = prev; genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx - base, OP_L_BLOCK)); pop(); - idx = new_msym(s, mrb_intern(s->mrb, "each")); + idx = new_msym(s, mrb_intern2(s->mrb, "each", 4)); genop(s, MKOP_ABC(OP_SENDB, cursp(), idx, 0)); } @@ -579,7 +578,8 @@ lambda_body(codegen_scope *s, node *tree, int blk) } tree = tree->cdr; if (tree->car) { - int ma, oa, ra, pa, ka, kd, ba, a; + int32_t a; + int ma, oa, ra, pa, ka, kd, ba; int pos, i; node *n, *opt; @@ -594,8 +594,8 @@ lambda_body(codegen_scope *s, node *tree, int blk) ka = kd = 0; ba = tree->car->cdr->cdr->cdr->cdr ? 1 : 0; - a = ((ma & 0x1f) << 18) - | ((oa & 0x1f) << 13) + a = ((int32_t)(ma & 0x1f) << 18) + | ((int32_t)(oa & 0x1f) << 13) | ((ra & 1) << 12) | ((pa & 0x1f) << 7) | ((ka & 0x1f) << 2) @@ -690,7 +690,7 @@ static mrb_sym attrsym(codegen_scope *s, mrb_sym a) { const char *name; - int len; + size_t len; char *name2; name = mrb_sym2name_len(s->mrb, a, &len); @@ -708,7 +708,7 @@ gen_values(codegen_scope *s, node *t, int val) int n = 0; while (t) { - if ((intptr_t)t->car->car == NODE_SPLAT) { // splat mode + if (n >= 127 || (intptr_t)t->car->car == NODE_SPLAT) { // splat mode if (val) { pop_n(n); genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), n)); @@ -789,7 +789,7 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val) } pop_n(n+1); { - int len; + size_t len; const char *name = mrb_sym2name_len(s->mrb, sym, &len); if (!noop && len == 1 && name[0] == '+') { @@ -955,6 +955,68 @@ gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val) } 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)); + push(); +} +static void +gen_literal_array(codegen_scope *s, node *tree, int sym, int val) +{ + if (val) { + int i = 0, j = 0; + + while (tree) { + switch ((intptr_t)tree->car->car) { + case NODE_STR: + if ((tree->cdr == NULL) && ((intptr_t)tree->car->cdr->cdr == 0)) + break; + /* fall through */ + case NODE_BEGIN: + codegen(s, tree->car, VAL); + ++j; + break; + + case NODE_LITERAL_DELIM: + if (j > 0) { + j = 0; + ++i; + if (sym) + gen_send_intern(s); + } + break; + } + if (j >= 2) { + pop(); pop(); + genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL); + push(); + j = 1; + } + tree = tree->cdr; + } + if (j > 0) { + j = 0; + ++i; + if (sym) + gen_send_intern(s); + } + pop_n(i); + genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), i)); + push(); + } + else { + while (tree) { + switch ((intptr_t)tree->car->car) { + case NODE_BEGIN: case NODE_BLOCK: + codegen(s, tree->car, NOVAL); + } + tree = tree->cdr; + } + } +} + +static void raise_error(codegen_scope *s, const char *msg) { int idx = new_lit(s, mrb_str_new_cstr(s->mrb, msg)); @@ -1088,12 +1150,12 @@ 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_intern(s->mrb, "StandardError")))); + genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern2(s->mrb, "StandardError", 13)))); push(); } genop(s, MKOP_AB(OP_MOVE, cursp(), exc)); pop(); - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern(s->mrb, "===")), 1)); + 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)); pos2 = tmp; @@ -1297,7 +1359,7 @@ 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_intern(s->mrb, "===")), 1)); + genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern2(s->mrb, "===", 3)), 1)); } else { pop(); @@ -1491,7 +1553,7 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_OP_ASGN: { mrb_sym sym = sym(tree->cdr->car); - int len; + size_t len; const char *name = mrb_sym2name_len(s->mrb, sym, &len); int idx; @@ -1638,7 +1700,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_intern(s->mrb, "call")), n)); + genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern2(s->mrb, "call", 4)), n)); if (val) push(); } break; @@ -1786,12 +1848,13 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_BACK_REF: { - char buf[4]; - int len; + char buf[2] = { '$' }; + mrb_value str; int sym; - len = snprintf(buf, sizeof(buf), "$%c", (int)(intptr_t)tree); - sym = new_sym(s, mrb_intern2(s->mrb, buf, len)); + buf[1] = (char)(intptr_t)tree; + str = mrb_str_new(s->mrb, buf, 2); + sym = new_sym(s, mrb_intern_str(s->mrb, str)); genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym)); push(); } @@ -1799,12 +1862,14 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_NTH_REF: { - char buf[4]; - int len; int sym; + mrb_state *mrb = s->mrb; + mrb_value fix = mrb_fixnum_value((intptr_t)tree); + mrb_value str = mrb_str_buf_new(mrb, 4); - len = snprintf(buf, sizeof(buf), "$%d", (int)(intptr_t)tree); - sym = new_sym(s, mrb_intern2(s->mrb, buf, len)); + mrb_str_buf_cat(mrb, str, "$", 1); + mrb_str_buf_append(mrb, str, mrb_fix2str(mrb, fix, 10)); + sym = new_sym(s, mrb_intern_str(mrb, str)); genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym)); push(); } @@ -1905,7 +1970,7 @@ codegen(codegen_scope *s, node *tree, int val) default: { - int sym = new_msym(s, mrb_intern(s->mrb, "-")); + int sym = new_msym(s, mrb_intern2(s->mrb, "-", 1)); genop(s, MKOP_ABx(OP_LOADI, cursp(), 0)); push(); @@ -1932,9 +1997,7 @@ codegen(codegen_scope *s, node *tree, int val) break; case NODE_HEREDOC: - /*if(tree == NULL){printf("heredoc error 1\n");exit(11);}*/ tree = ((struct mrb_parser_heredoc_info *)tree)->doc; - /*if(tree == NULL){printf("heredoc error 2\n");exit(12);}*/ /* fall through */ case NODE_DSTR: if (val) { @@ -1962,6 +2025,34 @@ codegen(codegen_scope *s, node *tree, int val) } break; + case NODE_WORDS: + gen_literal_array(s, tree, FALSE, val); + break; + + case NODE_SYMBOLS: + gen_literal_array(s, tree, TRUE, val); + 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 off = new_lit(s, mrb_str_new(s->mrb, p, len)); + + 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)); + genop(s, MKOP_ABC(OP_SEND, cursp(), sym, 1)); + mrb_gc_arena_restore(s->mrb, ai); + push(); + } + break; + case NODE_REGX: if (val) { char *p1 = (char*)tree->car; @@ -1983,7 +2074,7 @@ codegen(codegen_scope *s, node *tree, int val) pop(); } pop(); - sym = new_sym(s, mrb_intern(s->mrb, "compile")); + sym = new_sym(s, mrb_intern2(s->mrb, "compile", 7)); genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc)); mrb_gc_arena_restore(s->mrb, ai); push(); @@ -2031,7 +2122,7 @@ codegen(codegen_scope *s, node *tree, int val) pop(); } pop(); - sym = new_sym(s, mrb_intern(s->mrb, "compile")); + sym = new_sym(s, mrb_intern2(s->mrb, "compile", 7)); genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc)); mrb_gc_arena_restore(s->mrb, ai); push(); @@ -2060,9 +2151,7 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_DSYM: codegen(s, tree, val); if (val) { - pop(); - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern(s->mrb, "intern")), 0)); - push(); + gen_send_intern(s); } break; @@ -2098,7 +2187,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_intern(s->mrb, "alias_method")); + int c = new_msym(s, mrb_intern2(s->mrb, "alias_method", 12)); genop(s, MKOP_A(OP_TCLASS, cursp())); push(); @@ -2117,7 +2206,7 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_UNDEF: { - int undef = new_msym(s, mrb_intern(s->mrb, "undef_method")); + int undef = new_msym(s, mrb_intern2(s->mrb, "undef_method", 12)); int num = 0; node *t = tree; |
