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; break;
} }
default: { 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; break;
} }
} }
@ -1141,7 +1146,12 @@ void luaK_goiffalse (FuncState *fs, expdesc *e) {
break; break;
} }
default: { 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; break;
} }
} }
@ -1159,12 +1169,10 @@ static void codenot (FuncState *fs, expdesc *e) {
switch (e->k) { switch (e->k) {
case VNIL: case VFALSE: { case VNIL: case VFALSE: {
e->k = VTRUE; /* true == not nil == not false */ e->k = VTRUE; /* true == not nil == not false */
e->ravi_type = RAVI_TANY; /* RAVI TODO */
break; break;
} }
case VK: case VKFLT: case VKINT: case VTRUE: { case VK: case VKFLT: case VKINT: case VTRUE: {
e->k = VFALSE; /* false == not "x" == not 0.5 == not 1 == not true */ e->k = VFALSE; /* false == not "x" == not 0.5 == not 1 == not true */
e->ravi_type = RAVI_TANY; /* RAVI TODO*/
break; break;
} }
case VJMP: { case VJMP: {
@ -1177,11 +1185,11 @@ static void codenot (FuncState *fs, expdesc *e) {
freeexp(fs, e); freeexp(fs, e);
e->u.info = luaK_codeABC(fs, OP_NOT, 0, e->u.info, 0); e->u.info = luaK_codeABC(fs, OP_NOT, 0, e->u.info, 0);
e->k = VRELOCABLE; e->k = VRELOCABLE;
e->ravi_type = RAVI_TANY; /* RAVI TODO */
break; break;
} }
default: lua_assert(0); /* cannot happen */ default: lua_assert(0); /* cannot happen */
} }
e->ravi_type = RAVI_TBOOLEAN;
/* interchange true and false lists */ /* interchange true and false lists */
{ int temp = e->f; e->f = e->t; e->t = temp; } { int temp = e->f; e->f = e->t; e->t = temp; }
removevalues(fs, e->f); /* values are useless when negated */ 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) { static void codeunexpval (FuncState *fs, OpCode op, expdesc *e, int line) {
int r = luaK_exp2anyreg(fs, e); /* opcodes operate only on registers */ int r = luaK_exp2anyreg(fs, e); /* opcodes operate only on registers */
ravitype_t e_type = e->ravi_type;
freeexp(fs, e); freeexp(fs, e);
if (op == OP_BNOT) { switch (op) {
if (e->ravi_type == RAVI_TNUMINT) case OP_BNOT:
op = OP_RAVI_BNOT_I; if (e->ravi_type == RAVI_TNUMINT) {
else e->u.info = luaK_codeABC(fs, OP_RAVI_BNOT_I, 0, r, 0);
e->ravi_type = RAVI_TANY; /* Since it could be a float*/ e->ravi_type = RAVI_TNUMINT;
} break;
e->u.info = luaK_codeABC(fs, op, 0, r, 0); /* generate opcode */ }
e->k = VRELOCABLE; /* all those operations are relocatable */ e->u.info = luaK_codeABC(fs, OP_BNOT, 0, r, 0);
if (op == OP_LEN) { e->ravi_type = e->ravi_type == RAVI_TNUMFLT ? RAVI_TNUMINT : RAVI_TANY;
if (e_type == RAVI_TARRAYINT || e_type == RAVI_TARRAYFLT) break;
e->ravi_type = RAVI_TNUMINT; case OP_LEN:
else if (e_type == RAVI_TTABLE) { e->u.info = luaK_codeABC(fs, OP_LEN, 0, r, 0);
luaK_exp2anyreg(fs, e); if (e->ravi_type == RAVI_TARRAYINT || e->ravi_type == RAVI_TARRAYFLT) {
luaK_codeABC(fs, OP_RAVI_TOINT, e->u.info, 0, 0); e->ravi_type = RAVI_TNUMINT;
e->ravi_type = RAVI_TNUMINT; }
} else if (e->ravi_type == RAVI_TTABLE) {
else { 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->ravi_type = RAVI_TANY;
}
} }
e->k = VRELOCABLE; /* all those operations are relocatable */
luaK_fixline(fs, line); 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 rk2 = luaK_exp2RK(fs, e2); /* both operands are "RK" */
int rk1 = luaK_exp2RK(fs, e1); int rk1 = luaK_exp2RK(fs, e1);
freeexps(fs, e1, e2); 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); #define RAVI_OPCODE_SPECIALIZED(op, t) OP_RAVI_##op##t
} #define RAVI_OPCODE_GENERIC(op, t) OP_##op
else if (op == OP_ADD && e1->ravi_type == RAVI_TNUMFLT && e2->ravi_type == RAVI_TNUMINT) { #define RAVI_COMMUTATIVE(op, t) luaK_codeABC(fs, t(op, FI), 0, rk2, rk1)
e1->u.info = luaK_codeABC(fs, OP_RAVI_ADDFI, 0, rk1, rk2); #define RAVI_NON_COMMUTATIVE(op, t) luaK_codeABC(fs, t(op, IF), 0, rk1, rk2)
} #define RAVI_GEN_ARITH(op, co, ii, t) \
else if (op == OP_ADD && e1->ravi_type == RAVI_TNUMINT && e2->ravi_type == RAVI_TNUMFLT) { case OP_##op: \
e1->u.info = luaK_codeABC(fs, OP_RAVI_ADDFI, 0, rk2, rk1); if (e1->ravi_type == RAVI_TNUMFLT) { \
} if (e2->ravi_type == RAVI_TNUMFLT) { \
else if (op == OP_ADD && e1->ravi_type == RAVI_TNUMINT && e2->ravi_type == RAVI_TNUMINT) { e1->u.info = luaK_codeABC(fs, t(op, FF), 0, rk1, rk2); \
e1->u.info = luaK_codeABC(fs, OP_RAVI_ADDII, 0, rk1, rk2); e1->ravi_type = RAVI_TNUMFLT; \
} break; \
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 (e2->ravi_type == RAVI_TNUMINT) { \
} e1->u.info = luaK_codeABC(fs, t(op, FI), 0, rk1, rk2); \
else if (op == OP_MUL && e1->ravi_type == RAVI_TNUMFLT && e2->ravi_type == RAVI_TNUMINT) { e1->ravi_type = RAVI_TNUMFLT; \
e1->u.info = luaK_codeABC(fs, OP_RAVI_MULFI, 0, rk1, rk2); break; \
} } \
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 (e1->ravi_type == RAVI_TNUMINT) { \
} if (e2->ravi_type == RAVI_TNUMFLT) { \
else if (op == OP_MUL && e1->ravi_type == RAVI_TNUMINT && e2->ravi_type == RAVI_TNUMINT) { e1->u.info = co(op, t); \
e1->u.info = luaK_codeABC(fs, OP_RAVI_MULII, 0, rk1, rk2); e1->ravi_type = RAVI_TNUMFLT; \
} break; \
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 (e2->ravi_type == RAVI_TNUMINT) { \
} e1->u.info = luaK_codeABC(fs, t(op, II), 0, rk1, rk2); \
else if (op == OP_SUB && e1->ravi_type == RAVI_TNUMFLT && e2->ravi_type == RAVI_TNUMINT) { e1->ravi_type = ii; \
e1->u.info = luaK_codeABC(fs, OP_RAVI_SUBFI, 0, rk1, rk2); break; \
} } \
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); e1->u.info = luaK_codeABC(fs, OP_##op, 0, rk1, rk2); \
} e1->ravi_type = RAVI_TANY; \
else if (op == OP_SUB && e1->ravi_type == RAVI_TNUMINT && e2->ravi_type == RAVI_TNUMINT) { break
e1->u.info = luaK_codeABC(fs, OP_RAVI_SUBII, 0, rk1, rk2);
} #define RAVI_GEN_INT_OP(op) \
else if (op == OP_DIV && e1->ravi_type == RAVI_TNUMFLT && e2->ravi_type == RAVI_TNUMFLT) { case OP_##op: \
e1->u.info = luaK_codeABC(fs, OP_RAVI_DIVFF, 0, rk1, rk2); if (e1->ravi_type == RAVI_TNUMINT && e2->ravi_type == RAVI_TNUMINT) { \
} e1->u.info = luaK_codeABC(fs, OP_RAVI_##op##_II, 0, rk1, rk2); \
else if (op == OP_DIV && e1->ravi_type == RAVI_TNUMFLT && e2->ravi_type == RAVI_TNUMINT) { e1->ravi_type = RAVI_TNUMINT; \
e1->u.info = luaK_codeABC(fs, OP_RAVI_DIVFI, 0, rk1, rk2); } \
} else if ((e1->ravi_type == RAVI_TNUMFLT || e1->ravi_type == RAVI_TNUMINT) && \
else if (op == OP_DIV && e1->ravi_type == RAVI_TNUMINT && e2->ravi_type == RAVI_TNUMFLT) { (e2->ravi_type == RAVI_TNUMFLT || e2->ravi_type == RAVI_TNUMINT)) { \
e1->u.info = luaK_codeABC(fs, OP_RAVI_DIVIF, 0, rk1, rk2); e1->u.info = luaK_codeABC(fs, OP_##op, 0, rk1, rk2); \
} e1->ravi_type = RAVI_TNUMINT; \
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 { \
} e1->u.info = luaK_codeABC(fs, OP_##op, 0, rk1, rk2); \
else if (op == OP_BAND && e1->ravi_type == RAVI_TNUMINT && e2->ravi_type == RAVI_TNUMINT) { e1->ravi_type = RAVI_TANY; \
e1->u.info = luaK_codeABC(fs, OP_RAVI_BAND_II, 0, rk1, rk2); } \
} break
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); switch (op) {
} RAVI_GEN_ARITH(ADD, RAVI_COMMUTATIVE, RAVI_TNUMINT, RAVI_OPCODE_SPECIALIZED);
else if (op == OP_BXOR && e1->ravi_type == RAVI_TNUMINT && e2->ravi_type == RAVI_TNUMINT) { RAVI_GEN_ARITH(SUB, RAVI_NON_COMMUTATIVE, RAVI_TNUMINT, RAVI_OPCODE_SPECIALIZED);
e1->u.info = luaK_codeABC(fs, OP_RAVI_BXOR_II, 0, rk1, rk2); RAVI_GEN_ARITH(MUL, RAVI_COMMUTATIVE, RAVI_TNUMINT, RAVI_OPCODE_SPECIALIZED);
} RAVI_GEN_ARITH(DIV, RAVI_NON_COMMUTATIVE, RAVI_TNUMFLT, RAVI_OPCODE_SPECIALIZED);
else if (op == OP_SHL && e1->ravi_type == RAVI_TNUMINT && e2->ravi_type == RAVI_TNUMINT) { RAVI_GEN_ARITH(IDIV, RAVI_NON_COMMUTATIVE, RAVI_TNUMINT, RAVI_OPCODE_GENERIC);
e1->u.info = luaK_codeABC(fs, OP_RAVI_SHL_II, 0, rk1, rk2); RAVI_GEN_ARITH(MOD, RAVI_NON_COMMUTATIVE, RAVI_TNUMINT, RAVI_OPCODE_GENERIC);
} RAVI_GEN_ARITH(POW, RAVI_NON_COMMUTATIVE, RAVI_TNUMFLT, RAVI_OPCODE_GENERIC);
else if (op == OP_SHR && e1->ravi_type == RAVI_TNUMINT && e2->ravi_type == RAVI_TNUMINT) { RAVI_GEN_INT_OP(BAND);
e1->u.info = luaK_codeABC(fs, OP_RAVI_SHR_II, 0, rk1, rk2); RAVI_GEN_INT_OP(BOR);
} RAVI_GEN_INT_OP(BXOR);
else { RAVI_GEN_INT_OP(SHL);
e1->u.info = luaK_codeABC(fs, op, 0, rk1, rk2); /* generate opcode */ 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 */ 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); luaK_fixline(fs, line);
} }
@ -1453,7 +1464,7 @@ static void codecomp (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) {
} }
} }
e1->k = VJMP; 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' */ lua_assert(e1->t == NO_JUMP); /* list closed by 'luK_infix' */
luaK_dischargevars(fs, e2); luaK_dischargevars(fs, e2);
luaK_concat(fs, &e2->f, e1->f); 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; *e1 = *e2;
break; break;
} }
@ -1649,7 +1672,19 @@ void luaK_posfix (FuncState *fs, BinOpr op,
lua_assert(e1->f == NO_JUMP); /* list closed by 'luK_infix' */ lua_assert(e1->f == NO_JUMP); /* list closed by 'luK_infix' */
luaK_dischargevars(fs, e2); luaK_dischargevars(fs, e2);
luaK_concat(fs, &e2->t, e1->t); 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; *e1 = *e2;
break; break;
} }
@ -1662,7 +1697,7 @@ void luaK_posfix (FuncState *fs, BinOpr op,
SETARG_B(getinstruction(fs, e2), e1->u.info); 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)); 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->k = VRELOCABLE; e1->u.info = e2->u.info;
e1->ravi_type = RAVI_TANY; /* RAVI TODO check */ e1->ravi_type = RAVI_TANY;
} }
else { else {
luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ 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 */ /* read sub-expression with higher priority */
nextop = subexpr(ls, &v2, priority[op].right); nextop = subexpr(ls, &v2, priority[op].right);
DEBUG_EXPR(raviY_printf(ls->fs, "subexpr-> %e binop(%d) %e\n", v, (int)op, &v2)); 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); luaK_posfix(ls->fs, op, v, &v2, line);
DEBUG_EXPR(raviY_printf(ls->fs, "subexpr-> after posfix %e\n", v)); DEBUG_EXPR(raviY_printf(ls->fs, "subexpr-> after posfix %e\n", v));
op = nextop; op = nextop;

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

Loading…
Cancel
Save