Merge pull request #212 from XmiliaH/some-improvements

Improve type deduction
pull/216/head
Dibyendu Majumdar 3 years ago committed by GitHub
commit 754fcefc26
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1115,7 +1115,12 @@ 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 +1146,12 @@ 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 +1169,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 +1185,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 +1265,47 @@ 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_TNUMINT;
}
else if (e->ravi_type == RAVI_TTABLE) {
e->k = VRELOCABLE;
luaK_exp2anyreg(fs, e);
/* This is not incompatible with lua since a type annotation is require to get here or the table trivially has
* no metatable */
luaK_codeABC(fs, OP_RAVI_TOINT, e->u.info, 0, 0);
e->ravi_type = RAVI_TNUMINT;
luaK_fixline(fs, line);
return;
}
else {
e->ravi_type = RAVI_TANY;
}
break;
case OP_UNM:
e->u.info = luaK_codeABC(fs, OP_UNM, 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 +1324,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_TNUMINT || e1->ravi_type == RAVI_TNUMFLT) &&
(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 +1464,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 +1652,19 @@ 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 +1672,19 @@ 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 +1697,7 @@ 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 */
e1->ravi_type = RAVI_TANY;
}
else {
luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */

@ -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;

@ -1699,8 +1699,8 @@ function x()
end
assert(ravitype(x()) == 'number[]')
assert(x()[1] == 42.0)
check(x, 'NEW_IARRAY', 'LOADK', 'SETLIST', 'TEST',
'JMP', 'NEW_FARRAY', 'LOADK', 'SETLIST', 'TOFARRAY',
check(x, 'NEW_IARRAY', 'LOADK', 'SETLIST',
'NEW_FARRAY', 'LOADK', 'SETLIST',
'RETURN', 'RETURN')
print 'Test 74 OK'
@ -1797,10 +1797,14 @@ print 'Test 83 OK'
function x(x:number)
return (~x)+1
end
check(x, 'TOFLT', 'BNOT', 'ADD', 'RETURN', 'RETURN')
check(x, 'TOFLT', 'BNOT', 'ADDII', 'RETURN', 'RETURN')
assert(x(1.0) == -1)
compile(x)
assert(x(1.0) == -1)
function x(x:table)
return (~x)+1
end
check(x, 'TOTAB', 'BNOT', 'ADD', 'RETURN', 'RETURN')
print 'Test 84 OK'
-- Test that #() applied to non integer type produces any type

Loading…
Cancel
Save