From 4cce67ec13600511e0d22fce19f8446c98ddff10 Mon Sep 17 00:00:00 2001 From: XmiliaH Date: Thu, 18 Feb 2021 23:39:04 +0100 Subject: [PATCH 1/7] Improve type deduction --- src/lcode.c | 266 +++++++++++++++++++++++++++----------------------- src/lparser.c | 13 +-- 2 files changed, 144 insertions(+), 135 deletions(-) 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; From e85634270f498979cb96ab880604b92d78775495 Mon Sep 17 00:00:00 2001 From: XmiliaH Date: Fri, 19 Feb 2021 00:24:13 +0100 Subject: [PATCH 2/7] Add back that len of table is int and fix tests. --- src/lcode.c | 12 +++++++++++- tests/language/ravi_tests1.ravi | 12 ++++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/lcode.c b/src/lcode.c index 216b0f7..3a28761 100644 --- a/src/lcode.c +++ b/src/lcode.c @@ -1278,7 +1278,17 @@ static void codeunexpval (FuncState *fs, OpCode op, expdesc *e, int line) { 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 { + } 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; diff --git a/tests/language/ravi_tests1.ravi b/tests/language/ravi_tests1.ravi index 0512729..22f1e0e 100644 --- a/tests/language/ravi_tests1.ravi +++ b/tests/language/ravi_tests1.ravi @@ -1523,7 +1523,7 @@ print 'Test 58 OK' function x(s1: string, s2: string) return @string( s1 .. s2 ) end -check(x, 'TOSTRING', 'TOSTRING', 'MOVE', 'MOVE', 'CONCAT', 'TOSTRING', 'RETURN', 'RETURN') +check(x, 'TOSTRING', 'TOSTRING', 'MOVE', 'MOVE', 'CONCAT', 'RETURN', 'RETURN') assert(x('a', 'b') == 'ab') compile(x) assert(x('a', 'b') == 'ab') @@ -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 From 0b43c94a4dc1ebe50fece4a4bb9b94c91787ea23 Mon Sep 17 00:00:00 2001 From: XmiliaH Date: Fri, 19 Feb 2021 00:42:29 +0100 Subject: [PATCH 3/7] Use the right enum for opcodes --- src/lcode.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lcode.c b/src/lcode.c index 3a28761..e69218e 100644 --- a/src/lcode.c +++ b/src/lcode.c @@ -1292,9 +1292,9 @@ static void codeunexpval (FuncState *fs, OpCode op, expdesc *e, int line) { 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) { + 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; From 871b76fea2771ace8bfa5e13c3e3f02ef3e9f7ca Mon Sep 17 00:00:00 2001 From: XmiliaH Date: Fri, 19 Feb 2021 00:54:43 +0100 Subject: [PATCH 4/7] Format changed code --- src/lcode.c | 55 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/src/lcode.c b/src/lcode.c index e69218e..2f88f9e 100644 --- a/src/lcode.c +++ b/src/lcode.c @@ -1116,9 +1116,10 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) { } default: { 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 */ + pc = jumponcond(fs, e, 0); /* jump when false */ + } + else { + pc = NO_JUMP; /* always true; do nothing */ } break; } @@ -1146,9 +1147,10 @@ void luaK_goiffalse (FuncState *fs, expdesc *e) { } default: { if (e->ravi_type == RAVI_TNIL) { - pc = NO_JUMP; /* always false; do nothing */ - } else { - pc = jumponcond(fs, e, 1); /* jump if true */ + pc = NO_JUMP; /* always false; do nothing */ + } + else { + pc = jumponcond(fs, e, 1); /* jump if true */ } break; } @@ -1264,9 +1266,9 @@ 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 */ freeexp(fs, e); - switch(op) { + switch (op) { case OP_BNOT: - if(e->ravi_type == RAVI_TNUMINT) { + 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; @@ -1278,7 +1280,8 @@ static void codeunexpval (FuncState *fs, OpCode op, expdesc *e, int line) { 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 if(e->ravi_type == RAVI_TTABLE) { + } + 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 @@ -1322,10 +1325,10 @@ static void codebinexpval (FuncState *fs, OpCode op, int rk1 = luaK_exp2RK(fs, e1); freeexps(fs, e1, e2); -#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_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) { \ @@ -1372,7 +1375,7 @@ static void codebinexpval (FuncState *fs, OpCode op, 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); @@ -1652,12 +1655,15 @@ void luaK_posfix (FuncState *fs, BinOpr op, 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) { + } + 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. */ + } + 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; @@ -1667,12 +1673,15 @@ void luaK_posfix (FuncState *fs, BinOpr op, luaK_dischargevars(fs, e2); luaK_concat(fs, &e2->t, e1->t); 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) { + /* 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 { + } + else { /* In this case the first argument is truish and will be the return from 'or' */ e2->ravi_type = e1->ravi_type; } @@ -1688,9 +1697,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; - if (e2->ravi_type == RAVI_TSTRING && (e1->ravi_type == RAVI_TSTRING || e1->ravi_type == RAVI_TNUMINT || e1->ravi_type == RAVI_TNUMFLT)) { + 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 { + } + else { e1->ravi_type = RAVI_TANY; } } From 58cdc8d7dc6dcf46bce422e3a9f48e260b08d635 Mon Sep 17 00:00:00 2001 From: XmiliaH Date: Fri, 19 Feb 2021 13:40:55 +0100 Subject: [PATCH 5/7] RAVI_TSTRINGs can be nil --- src/lcode.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/lcode.c b/src/lcode.c index 2f88f9e..0077128 100644 --- a/src/lcode.c +++ b/src/lcode.c @@ -1278,7 +1278,7 @@ static void codeunexpval (FuncState *fs, OpCode op, expdesc *e, int line) { 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) { + if (e->ravi_type == RAVI_TARRAYINT || e->ravi_type == RAVI_TARRAYFLT) { e->ravi_type = RAVI_TNUMINT; } else if (e->ravi_type == RAVI_TTABLE) { @@ -1391,8 +1391,8 @@ static void codebinexpval (FuncState *fs, OpCode op, 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)) { + 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 { @@ -1697,13 +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; - 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; - } + e1->ravi_type = RAVI_TANY; } else { luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ From c0122cd81613d1d4b698146a02a34006d0ec97fd Mon Sep 17 00:00:00 2001 From: XmiliaH Date: Fri, 19 Feb 2021 13:42:54 +0100 Subject: [PATCH 6/7] FIx tests --- tests/language/ravi_tests1.ravi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/language/ravi_tests1.ravi b/tests/language/ravi_tests1.ravi index 22f1e0e..3c9fc8b 100644 --- a/tests/language/ravi_tests1.ravi +++ b/tests/language/ravi_tests1.ravi @@ -1523,7 +1523,7 @@ print 'Test 58 OK' function x(s1: string, s2: string) return @string( s1 .. s2 ) end -check(x, 'TOSTRING', 'TOSTRING', 'MOVE', 'MOVE', 'CONCAT', 'RETURN', 'RETURN') +check(x, 'TOSTRING', 'TOSTRING', 'MOVE', 'MOVE', 'CONCAT', 'TOSTRING', 'RETURN', 'RETURN') assert(x('a', 'b') == 'ab') compile(x) assert(x('a', 'b') == 'ab') From 62ab59134387beed5d4a19fb4fde330df75eeaf4 Mon Sep 17 00:00:00 2001 From: XmiliaH Date: Fri, 19 Feb 2021 16:45:03 +0100 Subject: [PATCH 7/7] Fix concat --- src/lcode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lcode.c b/src/lcode.c index 0077128..7cd379b 100644 --- a/src/lcode.c +++ b/src/lcode.c @@ -1391,7 +1391,7 @@ static void codebinexpval (FuncState *fs, OpCode op, 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) || + 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; }