diff --git a/src/lcode.c b/src/lcode.c index b7c462e..216b0f7 100644 --- a/src/lcode.c +++ b/src/lcode.c @@ -1115,7 +1115,11 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) { break; } default: { - pc = jumponcond(fs, e, 0); /* jump when false */ + if (e->ravi_type == RAVI_TNIL || e->ravi_type == RAVI_TANY || e->ravi_type == RAVI_TBOOLEAN) { + pc = jumponcond(fs, e, 0); /* jump when false */ + } else { + pc = NO_JUMP; /* always true; do nothing */ + } break; } } @@ -1141,7 +1145,11 @@ void luaK_goiffalse (FuncState *fs, expdesc *e) { break; } default: { - pc = jumponcond(fs, e, 1); /* jump if true */ + if (e->ravi_type == RAVI_TNIL) { + pc = NO_JUMP; /* always false; do nothing */ + } else { + pc = jumponcond(fs, e, 1); /* jump if true */ + } break; } } @@ -1159,12 +1167,10 @@ static void codenot (FuncState *fs, expdesc *e) { switch (e->k) { case VNIL: case VFALSE: { e->k = VTRUE; /* true == not nil == not false */ - e->ravi_type = RAVI_TANY; /* RAVI TODO */ break; } case VK: case VKFLT: case VKINT: case VTRUE: { e->k = VFALSE; /* false == not "x" == not 0.5 == not 1 == not true */ - e->ravi_type = RAVI_TANY; /* RAVI TODO*/ break; } case VJMP: { @@ -1177,11 +1183,11 @@ static void codenot (FuncState *fs, expdesc *e) { freeexp(fs, e); e->u.info = luaK_codeABC(fs, OP_NOT, 0, e->u.info, 0); e->k = VRELOCABLE; - e->ravi_type = RAVI_TANY; /* RAVI TODO */ break; } default: lua_assert(0); /* cannot happen */ } + e->ravi_type = RAVI_TBOOLEAN; /* interchange true and false lists */ { int temp = e->f; e->f = e->t; e->t = temp; } removevalues(fs, e->f); /* values are useless when negated */ @@ -1257,28 +1263,36 @@ static int constfolding (FuncState *fs, int op, expdesc *e1, */ static void codeunexpval (FuncState *fs, OpCode op, expdesc *e, int line) { int r = luaK_exp2anyreg(fs, e); /* opcodes operate only on registers */ - ravitype_t e_type = e->ravi_type; freeexp(fs, e); - if (op == OP_BNOT) { - if (e->ravi_type == RAVI_TNUMINT) - op = OP_RAVI_BNOT_I; - else - e->ravi_type = RAVI_TANY; /* Since it could be a float*/ - } - e->u.info = luaK_codeABC(fs, op, 0, r, 0); /* generate opcode */ - e->k = VRELOCABLE; /* all those operations are relocatable */ - if (op == OP_LEN) { - if (e_type == RAVI_TARRAYINT || e_type == RAVI_TARRAYFLT) - e->ravi_type = RAVI_TNUMINT; - else if (e_type == RAVI_TTABLE) { - luaK_exp2anyreg(fs, e); - luaK_codeABC(fs, OP_RAVI_TOINT, e->u.info, 0, 0); - e->ravi_type = RAVI_TNUMINT; - } - else { + switch(op) { + case OP_BNOT: + if(e->ravi_type == RAVI_TNUMINT) { + e->u.info = luaK_codeABC(fs, OP_RAVI_BNOT_I, 0, r, 0); + e->ravi_type = RAVI_TNUMINT; + break; + } + e->u.info = luaK_codeABC(fs, OP_BNOT, 0, r, 0); + e->ravi_type = e->ravi_type == RAVI_TNUMFLT ? RAVI_TNUMINT : RAVI_TANY; + break; + case OP_LEN: + e->u.info = luaK_codeABC(fs, OP_LEN, 0, r, 0); + if (e->ravi_type == RAVI_TARRAYINT || e->ravi_type == RAVI_TARRAYFLT || e->ravi_type == RAVI_TSTRING) { + e->ravi_type = RAVI_TNUMINT; + } else { + e->ravi_type = RAVI_TANY; + } + break; + case OPR_MINUS: + e->u.info = luaK_codeABC(fs, OPR_MINUS, 0, r, 0); + if(e->ravi_type != RAVI_TNUMINT && e->ravi_type != RAVI_TNUMFLT) { + e->ravi_type = RAVI_TANY; + } + break; + default: + e->u.info = luaK_codeABC(fs, op, 0, r, 0); e->ravi_type = RAVI_TANY; - } } + e->k = VRELOCABLE; /* all those operations are relocatable */ luaK_fixline(fs, line); } @@ -1297,103 +1311,87 @@ static void codebinexpval (FuncState *fs, OpCode op, int rk2 = luaK_exp2RK(fs, e2); /* both operands are "RK" */ int rk1 = luaK_exp2RK(fs, e1); freeexps(fs, e1, e2); - if (op == OP_ADD && e1->ravi_type == RAVI_TNUMFLT && e2->ravi_type == RAVI_TNUMFLT) { - e1->u.info = luaK_codeABC(fs, OP_RAVI_ADDFF, 0, rk1, rk2); - } - else if (op == OP_ADD && e1->ravi_type == RAVI_TNUMFLT && e2->ravi_type == RAVI_TNUMINT) { - e1->u.info = luaK_codeABC(fs, OP_RAVI_ADDFI, 0, rk1, rk2); - } - else if (op == OP_ADD && e1->ravi_type == RAVI_TNUMINT && e2->ravi_type == RAVI_TNUMFLT) { - e1->u.info = luaK_codeABC(fs, OP_RAVI_ADDFI, 0, rk2, rk1); - } - else if (op == OP_ADD && e1->ravi_type == RAVI_TNUMINT && e2->ravi_type == RAVI_TNUMINT) { - e1->u.info = luaK_codeABC(fs, OP_RAVI_ADDII, 0, rk1, rk2); - } - else if (op == OP_MUL && e1->ravi_type == RAVI_TNUMFLT && e2->ravi_type == RAVI_TNUMFLT) { - e1->u.info = luaK_codeABC(fs, OP_RAVI_MULFF, 0, rk1, rk2); - } - else if (op == OP_MUL && e1->ravi_type == RAVI_TNUMFLT && e2->ravi_type == RAVI_TNUMINT) { - e1->u.info = luaK_codeABC(fs, OP_RAVI_MULFI, 0, rk1, rk2); - } - else if (op == OP_MUL && e1->ravi_type == RAVI_TNUMINT && e2->ravi_type == RAVI_TNUMFLT) { - e1->u.info = luaK_codeABC(fs, OP_RAVI_MULFI, 0, rk2, rk1); - } - else if (op == OP_MUL && e1->ravi_type == RAVI_TNUMINT && e2->ravi_type == RAVI_TNUMINT) { - e1->u.info = luaK_codeABC(fs, OP_RAVI_MULII, 0, rk1, rk2); - } - else if (op == OP_SUB && e1->ravi_type == RAVI_TNUMFLT && e2->ravi_type == RAVI_TNUMFLT) { - e1->u.info = luaK_codeABC(fs, OP_RAVI_SUBFF, 0, rk1, rk2); - } - else if (op == OP_SUB && e1->ravi_type == RAVI_TNUMFLT && e2->ravi_type == RAVI_TNUMINT) { - e1->u.info = luaK_codeABC(fs, OP_RAVI_SUBFI, 0, rk1, rk2); - } - else if (op == OP_SUB && e1->ravi_type == RAVI_TNUMINT && e2->ravi_type == RAVI_TNUMFLT) { - e1->u.info = luaK_codeABC(fs, OP_RAVI_SUBIF, 0, rk1, rk2); - } - else if (op == OP_SUB && e1->ravi_type == RAVI_TNUMINT && e2->ravi_type == RAVI_TNUMINT) { - e1->u.info = luaK_codeABC(fs, OP_RAVI_SUBII, 0, rk1, rk2); - } - else if (op == OP_DIV && e1->ravi_type == RAVI_TNUMFLT && e2->ravi_type == RAVI_TNUMFLT) { - e1->u.info = luaK_codeABC(fs, OP_RAVI_DIVFF, 0, rk1, rk2); - } - else if (op == OP_DIV && e1->ravi_type == RAVI_TNUMFLT && e2->ravi_type == RAVI_TNUMINT) { - e1->u.info = luaK_codeABC(fs, OP_RAVI_DIVFI, 0, rk1, rk2); - } - else if (op == OP_DIV && e1->ravi_type == RAVI_TNUMINT && e2->ravi_type == RAVI_TNUMFLT) { - e1->u.info = luaK_codeABC(fs, OP_RAVI_DIVIF, 0, rk1, rk2); - } - else if (op == OP_DIV && e1->ravi_type == RAVI_TNUMINT && e2->ravi_type == RAVI_TNUMINT) { - e1->u.info = luaK_codeABC(fs, OP_RAVI_DIVII, 0, rk1, rk2); - } - else if (op == OP_BAND && e1->ravi_type == RAVI_TNUMINT && e2->ravi_type == RAVI_TNUMINT) { - e1->u.info = luaK_codeABC(fs, OP_RAVI_BAND_II, 0, rk1, rk2); - } - else if (op == OP_BOR && e1->ravi_type == RAVI_TNUMINT && e2->ravi_type == RAVI_TNUMINT) { - e1->u.info = luaK_codeABC(fs, OP_RAVI_BOR_II, 0, rk1, rk2); - } - else if (op == OP_BXOR && e1->ravi_type == RAVI_TNUMINT && e2->ravi_type == RAVI_TNUMINT) { - e1->u.info = luaK_codeABC(fs, OP_RAVI_BXOR_II, 0, rk1, rk2); - } - else if (op == OP_SHL && e1->ravi_type == RAVI_TNUMINT && e2->ravi_type == RAVI_TNUMINT) { - e1->u.info = luaK_codeABC(fs, OP_RAVI_SHL_II, 0, rk1, rk2); - } - else if (op == OP_SHR && e1->ravi_type == RAVI_TNUMINT && e2->ravi_type == RAVI_TNUMINT) { - e1->u.info = luaK_codeABC(fs, OP_RAVI_SHR_II, 0, rk1, rk2); - } - else { - e1->u.info = luaK_codeABC(fs, op, 0, rk1, rk2); /* generate opcode */ + +#define RAVI_OPCODE_SPECIALIZED(op,t) OP_RAVI_##op##t +#define RAVI_OPCODE_GENERIC(op,t) OP_##op +#define RAVI_COMMUTATIVE(op,t) luaK_codeABC(fs, t(op,FI), 0, rk2, rk1) +#define RAVI_NON_COMMUTATIVE(op,t) luaK_codeABC(fs, t(op,IF), 0, rk1, rk2) +#define RAVI_GEN_ARITH(op, co, ii, t) \ + case OP_##op: \ + if (e1->ravi_type == RAVI_TNUMFLT) { \ + if (e2->ravi_type == RAVI_TNUMFLT) { \ + e1->u.info = luaK_codeABC(fs, t(op, FF), 0, rk1, rk2); \ + e1->ravi_type = RAVI_TNUMFLT; \ + break; \ + } \ + else if (e2->ravi_type == RAVI_TNUMINT) { \ + e1->u.info = luaK_codeABC(fs, t(op, FI), 0, rk1, rk2); \ + e1->ravi_type = RAVI_TNUMFLT; \ + break; \ + } \ + } \ + else if (e1->ravi_type == RAVI_TNUMINT) { \ + if (e2->ravi_type == RAVI_TNUMFLT) { \ + e1->u.info = co(op, t); \ + e1->ravi_type = RAVI_TNUMFLT; \ + break; \ + } \ + else if (e2->ravi_type == RAVI_TNUMINT) { \ + e1->u.info = luaK_codeABC(fs, t(op, II), 0, rk1, rk2); \ + e1->ravi_type = ii; \ + break; \ + } \ + } \ + e1->u.info = luaK_codeABC(fs, OP_##op, 0, rk1, rk2); \ + e1->ravi_type = RAVI_TANY; \ + break + +#define RAVI_GEN_INT_OP(op) \ + case OP_##op: \ + if (e1->ravi_type == RAVI_TNUMINT && e2->ravi_type == RAVI_TNUMINT) { \ + e1->u.info = luaK_codeABC(fs, OP_RAVI_##op##_II, 0, rk1, rk2); \ + e1->ravi_type = RAVI_TNUMINT; \ + } \ + else if ((e1->ravi_type == RAVI_TNUMFLT || e1->ravi_type == RAVI_TNUMINT) && \ + (e2->ravi_type == RAVI_TNUMFLT || e2->ravi_type == RAVI_TNUMINT)) { \ + e1->u.info = luaK_codeABC(fs, OP_##op, 0, rk1, rk2); \ + e1->ravi_type = RAVI_TNUMINT; \ + } \ + else { \ + e1->u.info = luaK_codeABC(fs, OP_##op, 0, rk1, rk2); \ + e1->ravi_type = RAVI_TANY; \ + } \ + break + + switch (op) { + RAVI_GEN_ARITH(ADD, RAVI_COMMUTATIVE, RAVI_TNUMINT, RAVI_OPCODE_SPECIALIZED); + RAVI_GEN_ARITH(SUB, RAVI_NON_COMMUTATIVE, RAVI_TNUMINT, RAVI_OPCODE_SPECIALIZED); + RAVI_GEN_ARITH(MUL, RAVI_COMMUTATIVE, RAVI_TNUMINT, RAVI_OPCODE_SPECIALIZED); + RAVI_GEN_ARITH(DIV, RAVI_NON_COMMUTATIVE, RAVI_TNUMFLT, RAVI_OPCODE_SPECIALIZED); + RAVI_GEN_ARITH(IDIV, RAVI_NON_COMMUTATIVE, RAVI_TNUMINT, RAVI_OPCODE_GENERIC); + RAVI_GEN_ARITH(MOD, RAVI_NON_COMMUTATIVE, RAVI_TNUMINT, RAVI_OPCODE_GENERIC); + RAVI_GEN_ARITH(POW, RAVI_NON_COMMUTATIVE, RAVI_TNUMFLT, RAVI_OPCODE_GENERIC); + RAVI_GEN_INT_OP(BAND); + RAVI_GEN_INT_OP(BOR); + RAVI_GEN_INT_OP(BXOR); + RAVI_GEN_INT_OP(SHL); + RAVI_GEN_INT_OP(SHR); + case OP_CONCAT: + e1->u.info = luaK_codeABC(fs, op, 0, rk1, rk2); + if ((e1->ravi_type == RAVI_TSTRING || e1->ravi_type == RAVI_TNUMINT || e1->ravi_type == RAVI_TNUMFLT) || + (e2->ravi_type == RAVI_TSTRING || e2->ravi_type == RAVI_TNUMINT || e2->ravi_type == RAVI_TNUMFLT)) { + e1->ravi_type = RAVI_TSTRING; + } + else { + e1->ravi_type = RAVI_TANY; + } + break; + default: + e1->u.info = luaK_codeABC(fs, op, 0, rk1, rk2); + e1->ravi_type = RAVI_TANY; } + e1->k = VRELOCABLE; /* all those operations are relocatable */ - if ((op == OP_ADD || op == OP_SUB || op == OP_MUL || op == OP_DIV) && - e1->ravi_type == RAVI_TNUMFLT && e2->ravi_type == RAVI_TNUMFLT) - e1->ravi_type = RAVI_TNUMFLT; - else if ((op == OP_ADD || op == OP_SUB || op == OP_MUL || op == OP_DIV) - && e1->ravi_type == RAVI_TNUMFLT && e2->ravi_type == RAVI_TNUMINT) - e1->ravi_type = RAVI_TNUMFLT; - else if ((op == OP_ADD || op == OP_SUB || op == OP_MUL || op == OP_DIV) - && e1->ravi_type == RAVI_TNUMINT && e2->ravi_type == RAVI_TNUMFLT) - e1->ravi_type = RAVI_TNUMFLT; - else if ((op == OP_ADD || op == OP_SUB || op == OP_MUL) - && e1->ravi_type == RAVI_TNUMINT && e2->ravi_type == RAVI_TNUMINT) - e1->ravi_type = RAVI_TNUMINT; - else if ((op == OP_DIV) - && e1->ravi_type == RAVI_TNUMINT && e2->ravi_type == RAVI_TNUMINT) - e1->ravi_type = RAVI_TNUMFLT; - else if ((op == OP_IDIV) - && (e1->ravi_type == RAVI_TNUMINT) - && (e2->ravi_type == RAVI_TNUMINT)) - e1->ravi_type = RAVI_TNUMINT; - else if ((op == OP_BAND || op == OP_BOR || op == OP_BXOR || op == OP_SHL || op == OP_SHR) - && (e1->ravi_type == RAVI_TNUMINT || e1->ravi_type == RAVI_TNUMFLT) - && (e2->ravi_type == RAVI_TNUMINT || e2->ravi_type == RAVI_TNUMFLT)) - e1->ravi_type = RAVI_TNUMINT; - else if (op == OP_POW && (e1->ravi_type == RAVI_TNUMFLT || e1->ravi_type == RAVI_TNUMINT) && - (e2->ravi_type == RAVI_TNUMFLT || e2->ravi_type == RAVI_TNUMINT)) - e1->ravi_type = RAVI_TNUMFLT; - else if (op == OP_MOD && (e1->ravi_type == RAVI_TNUMINT && e2->ravi_type == RAVI_TNUMINT)) - e1->ravi_type = RAVI_TNUMINT; - else - e1->ravi_type = RAVI_TANY; luaK_fixline(fs, line); } @@ -1453,7 +1451,7 @@ static void codecomp (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) { } } e1->k = VJMP; - e1->ravi_type = RAVI_TANY; + e1->ravi_type = RAVI_TBOOLEAN; } @@ -1641,7 +1639,16 @@ void luaK_posfix (FuncState *fs, BinOpr op, lua_assert(e1->t == NO_JUMP); /* list closed by 'luK_infix' */ luaK_dischargevars(fs, e2); luaK_concat(fs, &e2->f, e1->f); - e2->ravi_type = e1->ravi_type; /* RAVI TODO why ? this seems to be needed but don't understand reason */ + if (e1->ravi_type == RAVI_TNIL) { + /* nil and something is still nil. */ + e2->ravi_type = RAVI_TNIL; + } else if (e1->ravi_type == RAVI_TBOOLEAN || e1->ravi_type == RAVI_TANY) { + /* In these cases the 'and' can go both ways. */ + if (e2->ravi_type != e1->ravi_type) + e2->ravi_type = RAVI_TANY; + } else { + /* Nothing to do here, since the first arg is always truish and therefore the second arg will be used every time. */ + } *e1 = *e2; break; } @@ -1649,7 +1656,16 @@ void luaK_posfix (FuncState *fs, BinOpr op, lua_assert(e1->f == NO_JUMP); /* list closed by 'luK_infix' */ luaK_dischargevars(fs, e2); luaK_concat(fs, &e2->t, e1->t); - e2->ravi_type = e1->ravi_type; /* RAVI TODO why ? this seems to be needed but don't understand reason */ + if (e1->ravi_type == RAVI_TNIL) { + /* Nothing to do here, since the first arg is always truish and therefore the second arg will be used every time. */ + } else if (e1->ravi_type == RAVI_TBOOLEAN || e1->ravi_type == RAVI_TANY) { + /* In these cases the 'or' can go both ways. */ + if (e2->ravi_type != e1->ravi_type) + e2->ravi_type = RAVI_TANY; + } else { + /* In this case the first argument is truish and will be the return from 'or' */ + e2->ravi_type = e1->ravi_type; + } *e1 = *e2; break; } @@ -1662,7 +1678,11 @@ void luaK_posfix (FuncState *fs, BinOpr op, SETARG_B(getinstruction(fs, e2), e1->u.info); DEBUG_CODEGEN(raviY_printf(fs, "[%d]* %o ; set A to %d\n", e2->u.info, getinstruction(fs,e2), e1->u.info)); e1->k = VRELOCABLE; e1->u.info = e2->u.info; - e1->ravi_type = RAVI_TANY; /* RAVI TODO check */ + if (e2->ravi_type == RAVI_TSTRING && (e1->ravi_type == RAVI_TSTRING || e1->ravi_type == RAVI_TNUMINT || e1->ravi_type == RAVI_TNUMFLT)) { + e1->ravi_type = RAVI_TSTRING; + } else { + e1->ravi_type = RAVI_TANY; + } } else { luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ diff --git a/src/lparser.c b/src/lparser.c index 8a5f2bf..cf2bee0 100644 --- a/src/lparser.c +++ b/src/lparser.c @@ -1758,18 +1758,7 @@ static BinOpr subexpr (LexState *ls, expdesc *v, int limit) { /* read sub-expression with higher priority */ nextop = subexpr(ls, &v2, priority[op].right); DEBUG_EXPR(raviY_printf(ls->fs, "subexpr-> %e binop(%d) %e\n", v, (int)op, &v2)); - /* - The bool 'and' and 'or' operators preserve the type of the - expression that gets selected, so if these are both integer or number types - then we know result will be integer or number, else the result is - unpredictable so we set both expressions to RAVI_TANY - */ - if (op == OPR_AND || op == OPR_OR) { - if (v->ravi_type != v2.ravi_type || (v->ravi_type != RAVI_TNUMINT && v->ravi_type != RAVI_TNUMFLT)) { - v->ravi_type = RAVI_TANY; - v2.ravi_type = RAVI_TANY; - } - } + luaK_posfix(ls->fs, op, v, &v2, line); DEBUG_EXPR(raviY_printf(ls->fs, "subexpr-> after posfix %e\n", v)); op = nextop;