summaryrefslogtreecommitdiffhomepage
path: root/src/codegen.c
diff options
context:
space:
mode:
authorPaolo Bosetti <[email protected]>2012-08-06 15:02:03 +0200
committerPaolo Bosetti <[email protected]>2012-08-06 15:02:56 +0200
commitaa0d2f91447c49363059f2e95cb9023f65a6fbef (patch)
tree2cfa325956e62648f2161564adfdf6dddc45b737 /src/codegen.c
parentfd097b8aff7b91bd105fc1daec5a4050a947b763 (diff)
parent193c98ae540d43d082795fd77ea81a4f6f7fd0f6 (diff)
downloadmruby-aa0d2f91447c49363059f2e95cb9023f65a6fbef.tar.gz
mruby-aa0d2f91447c49363059f2e95cb9023f65a6fbef.zip
Updated Xcode project build settings in conformity with 10.8/Xcode 4.4
Diffstat (limited to 'src/codegen.c')
-rw-r--r--src/codegen.c479
1 files changed, 329 insertions, 150 deletions
diff --git a/src/codegen.c b/src/codegen.c
index 505f0ad5b..bf6fd0b3e 100644
--- a/src/codegen.c
+++ b/src/codegen.c
@@ -10,12 +10,13 @@
#include "mruby.h"
#include "mruby/string.h"
#include "mruby/irep.h"
-#include "mruby/proc.h"
#include "mruby/compile.h"
+#include "mruby/numeric.h"
#include "opcode.h"
#include "node.h"
#include <string.h>
#include <stdlib.h>
+#include <ctype.h>
typedef mrb_ast_node node;
typedef struct mrb_parser_state parser_state;
@@ -47,7 +48,8 @@ typedef struct scope {
int sp;
int pc;
int lastlabel;
- int ainfo;
+ int ainfo:15;
+ int mscope:1;
struct loopinfo *loop;
int ensure_level;
@@ -89,7 +91,9 @@ codegen_error(codegen_scope *s, const char *message)
s = s->prev;
}
mrb_pool_close(s->mpool);
+#ifdef ENABLE_STDIO
fprintf(stderr, "codegen error: %s\n", message);
+#endif
longjmp(s->jmp, 1);
}
@@ -132,7 +136,7 @@ genop(codegen_scope *s, mrb_code i)
{
if (s->pc == s->icapa) {
s->icapa *= 2;
- s->iseq = codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->icapa);
+ s->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->icapa);
}
s->iseq[s->pc] = i;
s->pc++;
@@ -141,7 +145,7 @@ genop(codegen_scope *s, mrb_code i)
static void
genop_peep(codegen_scope *s, mrb_code i, int val)
{
- // peephole optimization
+ /* peephole optimization */
if (!val && s->lastlabel != s->pc && s->pc > 0) {
mrb_code i0 = s->iseq[s->pc-1];
int c1 = GET_OPCODE(i);
@@ -152,9 +156,13 @@ genop_peep(codegen_scope *s, mrb_code i, int val)
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
+ /* skip swapping OP_MOVE */
return;
}
+ 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;
+ }
break;
case OP_LOADI:
if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
@@ -180,7 +188,6 @@ genop_peep(codegen_scope *s, mrb_code i, int val)
case OP_GETSPECIAL:
case OP_LOADL:
case OP_STRING:
- case OP_GETMCNST:
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;
@@ -202,29 +209,27 @@ genop_peep(codegen_scope *s, mrb_code i, int val)
return;
}
break;
+ default:
+ break;
}
break;
case OP_SETIV:
case OP_SETCV:
case OP_SETCONST:
case OP_SETMCNST:
- switch (c0) {
- case OP_MOVE:
+ 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;
}
- break;
}
break;
case OP_SETUPVAR:
- switch (c0) {
- case OP_MOVE:
+ 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;
}
- break;
}
break;
case OP_EPOP:
@@ -239,6 +244,52 @@ genop_peep(codegen_scope *s, mrb_code i, int val)
return;
}
break;
+ case OP_RETURN:
+ switch (c0) {
+ 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;
+ 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;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
}
}
genop(s, i);
@@ -265,7 +316,9 @@ dispatch(codegen_scope *s, int pc)
case OP_ONERR:
break;
default:
+#ifdef ENABLE_STDIO
fprintf(stderr, "bug: dispatch on non JMP op\n");
+#endif
scope_error(s);
}
s->iseq[pc] = MKOP_AsBx(c, GETARG_A(i), diff);
@@ -297,21 +350,10 @@ push_(codegen_scope *s)
s->sp++;
nregs_update;
}
-#if 0
-static void
-push_n_(codegen_scope *s, int n)
-{
- if (s->sp + n > 511) {
- codegen_error(s, "too complex expression");
- }
- s->sp += n;
- nregs_update;
-}
-#endif
#define push() push_(s)
-#define push_n(n) push_n_(s, n)
-#define pop() (s->sp--)
+#define pop_(s) ((s)->sp--)
+#define pop() pop_(s)
#define pop_n(n) (s->sp-=(n))
#define cursp() (s->sp)
@@ -321,11 +363,11 @@ new_lit(codegen_scope *s, mrb_value val)
int i;
for (i=0; i<s->plen; i++) {
- if (memcmp(&s->pool[i], &val, sizeof(mrb_value)) == 0) return i;
+ if (mrb_obj_equal(s->mrb, s->pool[i], val)) return i;
}
if (s->plen == s->pcapa) {
s->pcapa *= 2;
- s->pool = codegen_realloc(s, s->pool, sizeof(mrb_value)*s->pcapa);
+ s->pool = (mrb_value *)codegen_realloc(s, s->pool, sizeof(mrb_value)*s->pcapa);
}
s->pool[s->plen] = val;
return s->plen++;
@@ -359,7 +401,7 @@ new_sym(codegen_scope *s, mrb_sym sym)
if (s->syms[i] == sym) return i;
}
if (s->slen > 125 && s->slen < 256) {
- s->syms = codegen_realloc(s, s->syms, sizeof(mrb_sym)*65536);
+ s->syms = (mrb_sym *)codegen_realloc(s, s->syms, sizeof(mrb_sym)*65536);
memset(s->syms+s->slen, 0, sizeof(mrb_sym)*(256-s->slen));
s->slen = 256;
}
@@ -429,7 +471,7 @@ for_body(codegen_scope *s, node *tree)
pop();
c = s->iseq[s->pc-1];
if (GET_OPCODE(c) != OP_RETURN || GETARG_B(c) != OP_R_NORMAL || s->pc == s->lastlabel) {
- genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL));
+ genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
}
loop_pop(s, NOVAL);
scope_finish(s, idx);
@@ -448,6 +490,7 @@ lambda_body(codegen_scope *s, node *tree, int blk)
s = scope_new(s->mrb, s, tree->car);
idx = s->idx;
+ s->mscope = !blk;
if (blk) {
struct loopinfo *lp = loop_push(s, LOOP_BLOCK);
@@ -484,10 +527,10 @@ lambda_body(codegen_scope *s, node *tree, int blk)
pos = new_label(s);
for (i=0; i<oa; i++) {
new_label(s);
- genop(s, MKOP_Ax(OP_JMP, 0));
+ genop(s, MKOP_sBx(OP_JMP, 0));
}
if (oa > 0) {
- genop(s, MKOP_Ax(OP_JMP, 0));
+ genop(s, MKOP_sBx(OP_JMP, 0));
}
opt = tree->car->cdr->car;
i = 0;
@@ -510,7 +553,13 @@ lambda_body(codegen_scope *s, node *tree, int blk)
pop();
c = s->iseq[s->pc-1];
if (GET_OPCODE(c) != OP_RETURN || GETARG_B(c) != OP_R_NORMAL || s->pc == s->lastlabel) {
- genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL));
+ if (s->nregs == 0) {
+ genop(s, MKOP_A(OP_LOADNIL, 0));
+ genop(s, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
+ }
+ else {
+ genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
+ }
}
if (blk) {
loop_pop(s, NOVAL);
@@ -526,13 +575,19 @@ scope_body(codegen_scope *s, node *tree)
codegen_scope *scope = scope_new(s->mrb, s, tree->car);
int idx = scope->idx;
+ codegen(scope, tree->cdr, VAL);
if (!s->iseq) {
- codegen(scope, tree->cdr, VAL);
genop(scope, MKOP_A(OP_STOP, 0));
}
else {
- codegen(scope, tree->cdr, VAL);
- genop(scope, MKOP_AB(OP_RETURN, scope->sp, OP_R_NORMAL));
+ pop_(scope);
+ 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);
+ }
}
scope_finish(scope, idx);
@@ -552,16 +607,17 @@ nosplat(node *t)
static mrb_sym
attrsym(codegen_scope *s, mrb_sym a)
{
- const char *name = mrb_sym2name(s->mrb, a);
+ const char *name;
+ int len;
char *name2;
- size_t len = strlen(name);
- name2 = codegen_palloc(s, len+1);
- strcpy(name2, name);
+ name = mrb_sym2name_len(s->mrb, a, &len);
+ name2 = (char *)codegen_palloc(s, len+1);
+ memcpy(name2, name, len);
name2[len] = '=';
name2[len+1] = '\0';
- return mrb_intern(s->mrb, name2);
+ return mrb_intern2(s->mrb, name2, len+1);
}
static int
@@ -607,7 +663,7 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val)
{
mrb_sym sym = name ? name : (mrb_sym)tree->cdr->car;
int idx;
- int n = 0, noop = 0, sendv = 0;
+ int n = 0, noop = 0, sendv = 0, blk = 0;
codegen(s, tree->car, VAL); /* receiver */
idx = new_msym(s, sym);
@@ -637,31 +693,44 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val)
pop();
}
else {
- genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ blk = cursp();
}
pop_n(n+1);
{
- const char *name = mrb_sym2name(s->mrb, sym);
+ int len;
+ const char *name = mrb_sym2name_len(s->mrb, sym, &len);
- if (!noop && name[0] == '+' && strlen(name) == 1) {
+ if (!noop && len == 1 && name[0] == '+') {
genop(s, MKOP_ABC(OP_ADD, cursp(), idx, n));
}
- else if (!noop && name[0] == '-' && strlen(name) == 1) {
+ else if (!noop && len == 1 && name[0] == '-') {
genop(s, MKOP_ABC(OP_SUB, cursp(), idx, n));
}
- else if (!noop && name[0] == '<' && strlen(name) == 1) {
+ else if (!noop && len == 1 && name[0] == '*') {
+ genop(s, MKOP_ABC(OP_MUL, cursp(), idx, n));
+ }
+ else if (!noop && len == 1 && name[0] == '/') {
+ genop(s, MKOP_ABC(OP_DIV, cursp(), idx, n));
+ }
+ else if (!noop && len == 1 && name[0] == '<') {
genop(s, MKOP_ABC(OP_LT, cursp(), idx, n));
}
- else if (!noop && name[0] == '<' && strlen(name) == 2 && name[1] == '=') {
+ else if (!noop && len == 2 && name[0] == '<' && name[1] == '=') {
genop(s, MKOP_ABC(OP_LE, cursp(), idx, n));
}
- else if (!noop && name[0] == '>' && strlen(name) == 1) {
+ else if (!noop && len == 1 && name[0] == '>') {
genop(s, MKOP_ABC(OP_GT, cursp(), idx, n));
}
- else if (!noop && name[0] == '>' && strlen(name) == 2 && name[1] == '=') {
+ else if (!noop && len == 2 && name[0] == '>' && name[1] == '=') {
genop(s, MKOP_ABC(OP_GE, cursp(), idx, n));
}
+ else if (!noop && len == 2 && name[0] == '=' && name[1] == '=') {
+ genop(s, MKOP_ABC(OP_EQ, cursp(), idx, n));
+ }
else {
+ if (blk > 0) { /* no block */
+ genop(s, MKOP_A(OP_LOADNIL, blk));
+ }
if (sendv) n = CALL_MAXARGS;
genop(s, MKOP_ABC(OP_SEND, cursp(), idx, n));
}
@@ -735,7 +804,9 @@ gen_assignment(codegen_scope *s, node *node, int sp, int val)
break;
default:
+#ifdef ENABLE_STDIO
printf("unknown lhs %d\n", type);
+#endif
break;
}
if (val) push();
@@ -795,6 +866,32 @@ raise_error(codegen_scope *s, const char *msg)
genop(s, MKOP_ABx(OP_ERR, 0, idx));
}
+static double
+readint_float(codegen_scope *s, const char *p, int base)
+{
+ const char *e = p + strlen(p);
+ double f = 0;
+ int n;
+
+ if (*p == '+') p++;
+ while (p < e) {
+ char c = *p;
+ c = tolower((unsigned char)c);
+ for (n=0; n<base; n++) {
+ if (mrb_digitmap[n] == c) {
+ f *= base;
+ f += n;
+ break;
+ }
+ }
+ if (n == base) {
+ codegen_error(s, "malformed readint input");
+ }
+ p++;
+ }
+ return f;
+}
+
static void
codegen(codegen_scope *s, node *tree, int val)
{
@@ -838,28 +935,34 @@ codegen(codegen_scope *s, node *tree, int val)
push();
while (n2) {
node *n3 = n2->car;
+ node *n4 = n3->car;
if (pos1) dispatch(s, pos1);
- if (n3->car) {
- node *n4 = n3->car;
-
- pos2 = 0;
- while (n4) {
+ pos2 = 0;
+ do {
+ if (n4) {
codegen(s, n4->car, VAL);
- genop(s, MKOP_AB(OP_MOVE, cursp(), exc));
+ }
+ else {
+ genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern(s->mrb, "StandardError"))));
push();
- genop(s, MKOP_A(OP_LOADNIL, cursp()));
- pop(); pop();
- genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern(s->mrb, "===")), 1));
- tmp = new_label(s);
- genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2));
- pos2 = tmp;
+ }
+ genop(s, MKOP_AB(OP_MOVE, cursp(), exc));
+ push();
+ genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ pop(); pop();
+ genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern(s->mrb, "===")), 1));
+ tmp = new_label(s);
+ genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2));
+ pos2 = tmp;
+ if (n4) {
n4 = n4->cdr;
}
- pos1 = new_label(s);
- genop(s, MKOP_Bx(OP_JMP, 0));
- dispatch_linked(s, pos2);
- }
+ } while (n4);
+ pos1 = new_label(s);
+ genop(s, MKOP_sBx(OP_JMP, 0));
+ dispatch_linked(s, pos2);
+
pop();
if (n3->cdr->car) {
gen_assignment(s, n3->cdr->car, exc, NOVAL);
@@ -868,7 +971,7 @@ codegen(codegen_scope *s, node *tree, int val)
codegen(s, n3->cdr->cdr->car, val);
}
tmp = new_label(s);
- genop(s, MKOP_AsBx(OP_JMP, cursp(), exend));
+ genop(s, MKOP_sBx(OP_JMP, exend));
exend = tmp;
n2 = n2->cdr;
push();
@@ -878,6 +981,7 @@ codegen(codegen_scope *s, node *tree, int val)
genop(s, MKOP_A(OP_RAISE, exc));
}
}
+ pop();
tree = tree->cdr;
dispatch(s, noexc);
genop(s, MKOP_A(OP_POPERR, 1));
@@ -983,13 +1087,14 @@ codegen(codegen_scope *s, node *tree, int val)
struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
lp->pc1 = new_label(s);
- codegen(s, tree->car, VAL);
- pop();
+ genop(s, MKOP_sBx(OP_JMP, 0));
lp->pc2 = new_label(s);
- genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0));
codegen(s, tree->cdr, NOVAL);
- genop(s, MKOP_sBx(OP_JMP, lp->pc1 - s->pc));
- dispatch(s, lp->pc2);
+ dispatch(s, lp->pc1);
+ codegen(s, tree->car, VAL);
+ pop();
+ genop(s, MKOP_AsBx(OP_JMPIF, cursp(), lp->pc2 - s->pc));
+
loop_pop(s, val);
}
break;
@@ -999,13 +1104,14 @@ codegen(codegen_scope *s, node *tree, int val)
struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
lp->pc1 = new_label(s);
- codegen(s, tree->car, VAL);
- pop();
+ genop(s, MKOP_sBx(OP_JMP, 0));
lp->pc2 = new_label(s);
- genop(s, MKOP_AsBx(OP_JMPIF, cursp(), 0));
codegen(s, tree->cdr, NOVAL);
- genop(s, MKOP_sBx(OP_JMP, lp->pc1 - s->pc));
- dispatch(s, lp->pc2);
+ dispatch(s, lp->pc1);
+ codegen(s, tree->car, VAL);
+ pop();
+ genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), lp->pc2 - s->pc));
+
loop_pop(s, val);
}
break;
@@ -1046,21 +1152,23 @@ codegen(codegen_scope *s, node *tree, int val)
}
if (tree->car->car) {
pos1 = new_label(s);
- genop(s, MKOP_AsBx(OP_JMP, cursp(), 0));
+ genop(s, MKOP_sBx(OP_JMP, 0));
dispatch_linked(s, pos2);
}
- pop(); pop();
+ pop();
codegen(s, tree->car->cdr, val);
+ pop();
tmp = new_label(s);
- genop(s, MKOP_AsBx(OP_JMP, cursp(), pos3));
+ genop(s, MKOP_sBx(OP_JMP, pos3));
pos3 = tmp;
if (pos1) dispatch(s, pos1);
tree = tree->cdr;
- push(); push();
+ push();
}
pop();
- if (pos3) dispatch_linked(s, pos3);
+ genop(s, MKOP_A(OP_LOADNIL, cursp()));
if (val) push();
+ if (pos3) dispatch_linked(s, pos3);
}
break;
@@ -1227,12 +1335,14 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_OP_ASGN:
{
mrb_sym sym = (mrb_sym)tree->cdr->car;
- const char *name = mrb_sym2name(s->mrb, sym);
- int idx;
+ int len;
+ const char *name = mrb_sym2name_len(s->mrb, sym, &len);
+ int idx, blk = 0;
codegen(s, tree->car, VAL);
- if ((name[0] == '|' && strlen(name) == 2 && name[1] == '|') ||
- (name[0] == '&' && strlen(name) == 2 && name[1] == '&')) {
+ if (len == 2 &&
+ ((name[0] == '|' && name[1] == '|') ||
+ (name[0] == '&' && name[1] == '&'))) {
int pos;
pop();
@@ -1245,29 +1355,32 @@ codegen(codegen_scope *s, node *tree, int val)
break;
}
codegen(s, tree->cdr->cdr->car, VAL);
- genop(s, MKOP_A(OP_LOADNIL, cursp()));
+ blk = cursp();
pop(); pop();
idx = new_msym(s, sym);
- if (name[0] == '+' && strlen(name) == 1) {
+ if (len == 1 && name[0] == '+') {
genop(s, MKOP_ABC(OP_ADD, cursp(), idx, 1));
}
- else if (name[0] == '-' && strlen(name) == 1) {
+ else if (len == 1 && name[0] == '-') {
genop(s, MKOP_ABC(OP_SUB, cursp(), idx, 1));
}
- else if (name[0] == '<' && strlen(name) == 1) {
+ else if (len == 1 && name[0] == '<') {
genop(s, MKOP_ABC(OP_LT, cursp(), idx, 1));
}
- else if (name[0] == '<' && strlen(name) == 2 && name[1] == '=') {
+ else if (len == 2 && name[0] == '<' && name[1] == '=') {
genop(s, MKOP_ABC(OP_LE, cursp(), idx, 1));
}
- else if (name[0] == '>' && strlen(name) == 1) {
+ else if (len == 1 && name[0] == '>') {
genop(s, MKOP_ABC(OP_GT, cursp(), idx, 1));
}
- else if (name[0] == '>' && strlen(name) == 2 && name[1] == '=') {
+ else if (len == 2 && name[0] == '>' && name[1] == '=') {
genop(s, MKOP_ABC(OP_GE, cursp(), idx, 1));
}
else {
+ if (blk > 0) {
+ genop(s, MKOP_A(OP_LOADNIL, blk));
+ }
genop(s, MKOP_ABC(OP_SEND, cursp(), idx, 1));
}
}
@@ -1276,16 +1389,18 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_SUPER:
{
- int n = 0;
+ int n = 0, noop = 0, sendv = 0;
- push();
+ push(); /* room for receiver */
if (tree) {
node *args = tree->car;
- while (args) {
- codegen(s, args->car, VAL);
- n++;
- args = args->cdr;
- }
+ if (args) {
+ n = gen_values(s, args);
+ if (n < 0) {
+ n = noop = sendv = 1;
+ push();
+ }
+ }
}
if (tree && tree->cdr) {
codegen(s, tree->cdr, VAL);
@@ -1295,6 +1410,7 @@ codegen(codegen_scope *s, node *tree, int val)
genop(s, MKOP_A(OP_LOADNIL, cursp()));
}
pop_n(n+1);
+ if (sendv) n = CALL_MAXARGS;
genop(s, MKOP_ABC(OP_SUPER, cursp(), 0, n));
if (val) push();
}
@@ -1305,14 +1421,19 @@ codegen(codegen_scope *s, node *tree, int val)
codegen_scope *s2 = s;
int lv = 0, ainfo = 0;
- while (s2->ainfo < 0) {
+ push(); /* room for receiver */
+ while (!s2->mscope) {
lv++;
s2 = s2->prev;
if (!s2) break;
}
if (s2) ainfo = s2->ainfo;
- push();
genop(s, MKOP_ABx(OP_ARGARY, cursp(), (ainfo<<4)|(lv & 0xf)));
+ if (tree && tree->cdr) {
+ push();
+ codegen(s, tree->cdr, VAL);
+ pop_n(2);
+ }
pop();
genop(s, MKOP_ABC(OP_SUPER, cursp(), 0, CALL_MAXARGS));
if (val) push();
@@ -1326,7 +1447,7 @@ codegen(codegen_scope *s, node *tree, int val)
genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_RETURN));
}
else {
- genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL));
+ genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
}
break;
@@ -1336,7 +1457,7 @@ codegen(codegen_scope *s, node *tree, int val)
int lv = 0, ainfo = 0;
int n = 0, sendv = 0;
- while (s2->ainfo < 0) {
+ while (!s2->mscope) {
lv++;
s2 = s2->prev;
if (!s2) break;
@@ -1378,7 +1499,7 @@ codegen(codegen_scope *s, node *tree, int val)
else {
codegen(s, tree, VAL);
pop();
- genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL));
+ genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
}
if (val) push();
break;
@@ -1498,10 +1619,11 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_BACK_REF:
{
char buf[4];
+ int len;
int sym;
- snprintf(buf, 3, "$%c", (int)(intptr_t)tree);
- sym = new_sym(s, mrb_intern(s->mrb, buf));
+ len = snprintf(buf, sizeof(buf), "$%c", (int)(intptr_t)tree);
+ sym = new_sym(s, mrb_intern2(s->mrb, buf, len));
genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
push();
}
@@ -1510,10 +1632,11 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_NTH_REF:
{
char buf[4];
+ int len;
int sym;
- snprintf(buf, 3, "$%d", (int)(intptr_t)tree);
- sym = new_sym(s, mrb_intern(s->mrb, buf));
+ len = snprintf(buf, sizeof(buf), "$%d", (int)(intptr_t)tree);
+ sym = new_sym(s, mrb_intern2(s->mrb, buf, len));
genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
push();
}
@@ -1531,17 +1654,27 @@ codegen(codegen_scope *s, node *tree, int val)
if (val) {
char *p = (char*)tree->car;
int base = (intptr_t)tree->cdr->car;
- int i = readint(p, base);
+ double f;
+ mrb_int i;
mrb_code co;
- if (i < MAXARG_sBx && i > -MAXARG_sBx) {
- co = MKOP_AsBx(OP_LOADI, cursp(), i);
+ f = readint_float(s, p, base);
+ if (!FIXABLE(f)) {
+ int off = new_lit(s, mrb_float_value(f));
+
+ genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
}
else {
- int off = new_lit(s, mrb_fixnum_value(i));
- co = MKOP_ABx(OP_LOADL, cursp(), off);
+ i = (mrb_int)f;
+ if (i < MAXARG_sBx && i > -MAXARG_sBx) {
+ co = MKOP_AsBx(OP_LOADI, cursp(), i);
+ }
+ else {
+ int off = new_lit(s, mrb_fixnum_value(i));
+ co = MKOP_ABx(OP_LOADL, cursp(), off);
+ }
+ genop(s, co);
}
- genop(s, co);
push();
}
break;
@@ -1577,18 +1710,27 @@ codegen(codegen_scope *s, node *tree, int val)
{
char *p = (char*)tree->car;
int base = (intptr_t)tree->cdr->car;
- int i = readint(p, base);
+ mrb_float f;
+ mrb_int i;
mrb_code co;
- i = -i;
- if (i < MAXARG_sBx && i > -MAXARG_sBx) {
- co = MKOP_AsBx(OP_LOADI, cursp(), i);
- }
- else {
- int off = new_lit(s, mrb_fixnum_value(i));
- co = MKOP_ABx(OP_LOADL, cursp(), off);
- }
- genop(s, co);
+ f = readint_float(s, p, base);
+ if (!FIXABLE(f)) {
+ int off = new_lit(s, mrb_float_value(-f));
+
+ genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
+ }
+ else {
+ i = (mrb_int)-f;
+ if (i < MAXARG_sBx && i > -MAXARG_sBx) {
+ co = MKOP_AsBx(OP_LOADI, cursp(), i);
+ }
+ else {
+ int off = new_lit(s, mrb_fixnum_value(i));
+ co = MKOP_ABx(OP_LOADL, cursp(), off);
+ }
+ genop(s, co);
+ }
push();
}
break;
@@ -1654,6 +1796,15 @@ codegen(codegen_scope *s, node *tree, int val)
}
break;
+ 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();
+ }
+ break;
+
case NODE_SELF:
if (val) {
genop(s, MKOP_A(OP_LOADSELF, cursp()));
@@ -1843,7 +1994,7 @@ static codegen_scope*
scope_new(mrb_state *mrb, codegen_scope *prev, node *lv)
{
mrb_pool *pool = mrb_pool_open(mrb);
- codegen_scope *p = mrb_pool_alloc(pool, sizeof(codegen_scope));
+ codegen_scope *p = (codegen_scope *)mrb_pool_alloc(pool, sizeof(codegen_scope));
if (!p) return 0;
memset(p, 0, sizeof(codegen_scope));
@@ -1852,15 +2003,16 @@ scope_new(mrb_state *mrb, codegen_scope *prev, node *lv)
if (!prev) return p;
p->prev = prev;
p->ainfo = -1;
+ p->mscope = 0;
p->mrb = prev->mrb;
p->icapa = 1024;
- p->iseq = mrb_malloc(mrb, sizeof(mrb_code)*p->icapa);
+ p->iseq = (mrb_code *)mrb_malloc(mrb, sizeof(mrb_code)*p->icapa);
p->pcapa = 32;
- p->pool = mrb_malloc(mrb, sizeof(mrb_value)*p->pcapa);
+ p->pool = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value)*p->pcapa);
- p->syms = mrb_malloc(mrb, sizeof(mrb_sym)*256);
+ p->syms = (mrb_sym *)mrb_malloc(mrb, sizeof(mrb_sym)*256);
p->lv = lv;
p->sp += node_len(lv)+2;
@@ -1879,20 +2031,20 @@ scope_finish(codegen_scope *s, int idx)
mrb_irep *irep;
mrb_add_irep(mrb, idx);
- irep = mrb->irep[idx] = mrb_malloc(mrb, sizeof(mrb_irep));
+ irep = mrb->irep[idx] = (mrb_irep *)mrb_malloc(mrb, sizeof(mrb_irep));
irep->idx = idx;
irep->flags = 0;
if (s->iseq) {
- irep->iseq = codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc);
+ irep->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc);
irep->ilen = s->pc;
}
if (s->pool) {
- irep->pool = codegen_realloc(s, s->pool, sizeof(mrb_value)*s->plen);
+ irep->pool = (mrb_value *)codegen_realloc(s, s->pool, sizeof(mrb_value)*s->plen);
irep->plen = s->plen;
}
if (s->syms) {
- irep->syms = codegen_realloc(s, s->syms, sizeof(mrb_sym)*s->slen);
+ irep->syms = (mrb_sym *)codegen_realloc(s, s->syms, sizeof(mrb_sym)*s->slen);
irep->slen = s->slen;
}
@@ -1906,7 +2058,7 @@ scope_finish(codegen_scope *s, int idx)
static struct loopinfo*
loop_push(codegen_scope *s, enum looptype t)
{
- struct loopinfo *p = codegen_palloc(s, sizeof(struct loopinfo));
+ struct loopinfo *p = (struct loopinfo *)codegen_palloc(s, sizeof(struct loopinfo));
p->type = t;
p->pc1 = p->pc2 = p->pc3 = 0;
@@ -1971,6 +2123,7 @@ loop_pop(codegen_scope *s, int val)
static void
codedump(mrb_state *mrb, int n)
{
+#ifdef ENABLE_STDIO
mrb_irep *irep = mrb->irep[n];
int i;
mrb_code c;
@@ -1995,7 +2148,7 @@ codedump(mrb_state *mrb, int n)
printf("OP_LOADI\tR%d\t%d\n", GETARG_A(c), GETARG_sBx(c));
break;
case OP_LOADSYM:
- printf("OP_LOADSYM\tR%d\t'%s'\n", GETARG_A(c),
+ printf("OP_LOADSYM\tR%d\t:%s\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
break;
case OP_LOADNIL:
@@ -2011,20 +2164,20 @@ codedump(mrb_state *mrb, int n)
printf("OP_LOADF\tR%d\n", GETARG_A(c));
break;
case OP_GETGLOBAL:
- printf("OP_GETGLOBAL\tR%d\t'%s'\n", GETARG_A(c),
+ printf("OP_GETGLOBAL\tR%d\t:%s\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
break;
case OP_SETGLOBAL:
- printf("OP_SETGLOBAL\t'%s'\tR%d\n",
+ printf("OP_SETGLOBAL\t:%s\tR%d\n",
mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
GETARG_A(c));
break;
case OP_GETCONST:
- printf("OP_GETCONST\tR%d\t'%s'\n", GETARG_A(c),
+ printf("OP_GETCONST\tR%d\t:%s\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]));
break;
case OP_SETCONST:
- printf("OP_SETCONST\t'%s'\tR%d\n",
+ printf("OP_SETCONST\t:%s\tR%d\n",
mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]),
GETARG_A(c));
break;
@@ -2073,7 +2226,12 @@ codedump(mrb_state *mrb, int n)
printf("OP_JMPNOT\tR%d\t%03d\n", GETARG_A(c), i+GETARG_sBx(c));
break;
case OP_SEND:
- printf("OP_SEND\tR%d\t'%s'\t%d\n", GETARG_A(c),
+ printf("OP_SEND\tR%d\t:%s\t%d\n", GETARG_A(c),
+ mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
+ GETARG_C(c));
+ break;
+ case OP_TAILCALL:
+ printf("OP_TAILCALL\tR%d\t:%s\t%d\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
GETARG_C(c));
break;
@@ -2128,37 +2286,52 @@ codedump(mrb_state *mrb, int n)
printf("OP_RANGE\tR%d\tR%d\t%d\n", GETARG_A(c), GETARG_B(c), GETARG_C(c));
break;
case OP_METHOD:
- printf("OP_METHOD\tR%d\t'%s'\n", GETARG_A(c),
+ printf("OP_METHOD\tR%d\t:%s\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]));
break;
case OP_ADD:
- printf("OP_ADD\tR%d\t'%s'\t%d\n", GETARG_A(c),
+ printf("OP_ADD\tR%d\t:%s\t%d\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
GETARG_C(c));
break;
case OP_SUB:
- printf("OP_SUB\tR%d\t'%s'\t%d\n", GETARG_A(c),
+ printf("OP_SUB\tR%d\t:%s\t%d\n", GETARG_A(c),
+ mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
+ GETARG_C(c));
+ break;
+ case OP_MUL:
+ printf("OP_MUL\tR%d\t:%s\t%d\n", GETARG_A(c),
+ mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
+ GETARG_C(c));
+ break;
+ case OP_DIV:
+ printf("OP_DIV\tR%d\t:%s\t%d\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
GETARG_C(c));
break;
case OP_LT:
- printf("OP_LT\tR%d\t'%s'\t%d\n", GETARG_A(c),
+ printf("OP_LT\tR%d\t:%s\t%d\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
GETARG_C(c));
break;
case OP_LE:
- printf("OP_LE\tR%d\t'%s'\t%d\n", GETARG_A(c),
+ printf("OP_LE\tR%d\t:%s\t%d\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
GETARG_C(c));
break;
case OP_GT:
- printf("OP_GT\tR%d\t'%s'\t%d\n", GETARG_A(c),
+ printf("OP_GT\tR%d\t:%s\t%d\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
GETARG_C(c));
break;
case OP_GE:
- printf("OP_GE\tR%d\t'%s'\t%d\n", GETARG_A(c),
+ printf("OP_GE\tR%d\t:%s\t%d\n", GETARG_A(c),
+ mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
+ GETARG_C(c));
+ break;
+ case OP_EQ:
+ printf("OP_EQ\tR%d\t:%s\t%d\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
GETARG_C(c));
break;
@@ -2183,7 +2356,12 @@ codedump(mrb_state *mrb, int n)
printf("OP_APOST\tR%d\t%d\t%d\n", GETARG_A(c), GETARG_B(c), GETARG_C(c));
break;
case OP_STRING:
- printf("OP_STRING\tR%d\t'%s'\n", GETARG_A(c), RSTRING_PTR(irep->pool[GETARG_Bx(c)]));
+ {
+ mrb_value s = irep->pool[GETARG_Bx(c)];
+
+ s = mrb_str_dump(mrb, s);
+ printf("OP_STRING\tR%d\t%s\n", GETARG_A(c), RSTRING_PTR(s));
+ }
break;
case OP_STRCAT:
printf("OP_STRCAT\tR%d\tR%d\n", GETARG_A(c), GETARG_B(c));
@@ -2196,11 +2374,11 @@ codedump(mrb_state *mrb, int n)
printf("OP_OCLASS\tR%d\n", GETARG_A(c));
break;
case OP_CLASS:
- printf("OP_CLASS\tR%d\t'%s'\n", GETARG_A(c),
+ printf("OP_CLASS\tR%d\t:%s\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]));
break;
case OP_MODULE:
- printf("OP_MODULE\tR%d\t'%s'\n", GETARG_A(c),
+ printf("OP_MODULE\tR%d\t:%s\n", GETARG_A(c),
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]));
break;
case OP_EXEC:
@@ -2213,7 +2391,7 @@ codedump(mrb_state *mrb, int n)
printf("OP_TCLASS\tR%d\n", GETARG_A(c));
break;
case OP_ERR:
- printf("OP_ERR\t:L(%d)\n", GETARG_Bx(c));
+ printf("OP_ERR\tL(%d)\n", GETARG_Bx(c));
break;
case OP_EPUSH:
printf("OP_EPUSH\t:I(%d)\n", n+GETARG_Bx(c));
@@ -2241,6 +2419,7 @@ codedump(mrb_state *mrb, int n)
}
}
printf("\n");
+#endif
}
void