First part for type maps

pull/213/head
XmiliaH 3 years ago
parent 871b76fea2
commit 6af3d804a4

@ -600,32 +600,35 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) {
freereg(fs, e->u.ind.t);
/* TODO we should do this for upvalues too */
/* table access - set specialized op codes if array types are detected */
if (e->ravi_type == RAVI_TARRAYFLT && e->u.ind.key_ravi_type == RAVI_TNUMINT)
op = OP_RAVI_FARRAY_GET;
else if (e->ravi_type == RAVI_TARRAYINT && e->u.ind.key_ravi_type == RAVI_TNUMINT)
op = OP_RAVI_IARRAY_GET;
/* Check that we have a short string constant */
else if (e->ravi_type == RAVI_TTABLE && e->u.ind.key_ravi_type == RAVI_TSTRING && isshortstr(fs, e->u.ind.idx))
op = OP_RAVI_TABLE_GETFIELD;
else if (e->u.ind.key_ravi_type == RAVI_TNUMINT)
op = OP_RAVI_GETI;
else if (e->u.ind.key_ravi_type == RAVI_TSTRING && isshortstr(fs, e->u.ind.idx))
op = OP_RAVI_GETFIELD;
else
if (e->u.ind.key_ravi_type_map == RAVI_TM_INTEGER) {
if (e->ravi_type_map == RAVI_TM_FLOAT_ARRAY) {
op = OP_RAVI_FARRAY_GET;
} else if (e->ravi_type_map == RAVI_TM_INTEGER_ARRAY) {
op = OP_RAVI_IARRAY_GET;
} else {
op = OP_RAVI_GETI;
}
} else if (e->u.ind.key_ravi_type_map == RAVI_TM_STRING && isshortstr(fs, e->u.ind.idx)) {
op = e->ravi_type_map == RAVI_TM_TABLE ? OP_RAVI_TABLE_GETFIELD : OP_RAVI_GETFIELD;
} else {
op = OP_GETTABLE;
}
}
else {
lua_assert(e->u.ind.vt == VUPVAL);
if (e->u.ind.key_ravi_type == RAVI_TSTRING && isshortstr(fs, e->u.ind.idx))
if (e->u.ind.key_ravi_type_map == RAVI_TM_STRING && isshortstr(fs, e->u.ind.idx))
op = OP_RAVI_GETTABUP_SK;
else
op = OP_GETTABUP; /* 't' is in an upvalue */
}
if (e->ravi_type == RAVI_TARRAYFLT || e->ravi_type == RAVI_TARRAYINT)
/* set the type of resulting expression */
e->ravi_type = e->ravi_type == RAVI_TARRAYFLT ? RAVI_TNUMFLT : RAVI_TNUMINT;
else
e->ravi_type = RAVI_TANY;
uint32_t result_type = 0;
if (e->ravi_type_map & (~(RAVI_TM_INTEGER_ARRAY | RAVI_TM_FLOAT_ARRAY))) {
result_type = RAVI_TM_ANY;
} else {
if (e->ravi_type_map & RAVI_TM_INTEGER_ARRAY) result_type |= RAVI_TM_INTEGER;
if (e->ravi_type_map & RAVI_TM_FLOAT_ARRAY) result_type |= RAVI_TM_FLOAT;
}
e->ravi_type_map = result_type;
e->u.info = luaK_codeABC(fs, op, 0, e->u.ind.t, e->u.ind.idx);
e->k = VRELOCABLE;
DEBUG_EXPR(raviY_printf(fs, "luaK_dischargevars (VINDEXED->VRELOCABLE) %e\n", e));
@ -859,23 +862,22 @@ int luaK_exp2RK (FuncState *fs, expdesc *e) {
}
static void check_valid_store(FuncState *fs, expdesc *var, expdesc *ex) {
lua_assert(var->ravi_type_map == RAVI_TM_ANY || (var->ravi_type_map != 0 && (var->ravi_type_map & (var->ravi_type_map - 1)) == 0));
/* VNONRELOC means we have fixed register and do we know the type? */
if (ex->k == VNONRELOC &&
(var->ravi_type == RAVI_TNUMFLT ||
var->ravi_type == RAVI_TNUMINT ||
var->ravi_type == RAVI_TARRAYFLT ||
var->ravi_type == RAVI_TARRAYINT ||
var->ravi_type == RAVI_TTABLE ||
var->ravi_type == RAVI_TSTRING ||
var->ravi_type == RAVI_TFUNCTION ||
var->ravi_type == RAVI_TUSERDATA)) {
(var->ravi_type_map == RAVI_TM_FLOAT ||
var->ravi_type_map == RAVI_TM_INTEGER ||
var->ravi_type_map == RAVI_TM_FLOAT_ARRAY ||
var->ravi_type_map == RAVI_TM_INTEGER_ARRAY ||
var->ravi_type_map == RAVI_TM_TABLE ||
var->ravi_type_map == (RAVI_TM_STRING | RAVI_TM_NIL) ||
var->ravi_type_map == (RAVI_TM_FUNCTION | RAVI_TM_NIL) ||
var->ravi_type_map == (RAVI_TM_USERDATA | RAVI_TM_NIL))) {
/* handled by MOVEI, MOVEF, MOVEIARRAY, MOVEFARRAY at runtime */
return;
}
if (var->ravi_type == RAVI_TNUMFLT) {
if (ex->ravi_type == RAVI_TNUMFLT)
return;
if (ex->k == VINDEXED && ex->ravi_type == RAVI_TARRAYFLT)
if (var->ravi_type_map == RAVI_TM_FLOAT) {
if (ex->ravi_type_map == RAVI_TM_FLOAT)
return;
luaX_syntaxerror(
fs->ls,
@ -883,33 +885,27 @@ static void check_valid_store(FuncState *fs, expdesc *var, expdesc *ex) {
fs->ls->L,
"Invalid assignment: number expected"));
}
else if (var->ravi_type == RAVI_TNUMINT) {
if (ex->ravi_type == RAVI_TNUMINT)
return;
if (ex->k == VINDEXED && ex->ravi_type == RAVI_TARRAYINT)
else if (var->ravi_type_map == RAVI_TM_INTEGER) {
if (ex->ravi_type_map == RAVI_TM_INTEGER)
return;
luaX_syntaxerror(
fs->ls,
luaO_pushfstring(
fs->ls->L,
"Invalid assignment: integer expected",
var->ravi_type,
ex->ravi_type));
"Invalid assignment: integer expected"));
}
else if (var->ravi_type == RAVI_TARRAYFLT ||
var->ravi_type == RAVI_TARRAYINT ||
var->ravi_type == RAVI_TTABLE) {
if (ex->ravi_type == var->ravi_type && ex->k != VINDEXED)
else if (var->ravi_type_map & (~(RAVI_TM_INTEGER_ARRAY | RAVI_TM_FLOAT_ARRAY | RAVI_TM_TABLE)) == 0) {
if (ex->ravi_type_map == var->ravi_type_map)
return;
luaX_syntaxerror(
fs->ls,
luaO_pushfstring(
fs->ls->L,
"Invalid assignment: %s expected",
var->ravi_type == RAVI_TTABLE ? "table" : (var->ravi_type == RAVI_TARRAYFLT ? "number[]" : "integer[]")));
var->ravi_type_map == RAVI_TM_TABLE ? "table" : (var->ravi_type_map == RAVI_TM_FLOAT_ARRAY ? "number[]" : "integer[]")));
}
else if (var->ravi_type == RAVI_TSTRING) {
if (ex->ravi_type == RAVI_TNIL || (ex->ravi_type == var->ravi_type && ex->k != VINDEXED))
else if (var->ravi_type_map == (RAVI_TM_STRING | RAVI_TM_NIL)) {
if ((ex->ravi_type_map & ~(RAVI_TM_STRING | RAVI_TM_NIL)) == 0)
return;
luaX_syntaxerror(
fs->ls,
@ -917,8 +913,8 @@ static void check_valid_store(FuncState *fs, expdesc *var, expdesc *ex) {
fs->ls->L,
"Invalid assignment: string expected"));
}
else if (var->ravi_type == RAVI_TFUNCTION) {
if (ex->ravi_type == RAVI_TNIL || (ex->ravi_type == var->ravi_type && ex->k != VINDEXED))
else if (var->ravi_type_map == (RAVI_TM_FUNCTION | RAVI_TM_NIL)) {
if ((ex->ravi_type_map & ~(RAVI_TM_FUNCTION | RAVI_TM_NIL)) == 0)
return;
luaX_syntaxerror(
fs->ls,
@ -926,9 +922,9 @@ static void check_valid_store(FuncState *fs, expdesc *var, expdesc *ex) {
fs->ls->L,
"Invalid assignment: function expected"));
}
else if (var->ravi_type == RAVI_TUSERDATA) {
if (ex->ravi_type == RAVI_TNIL ||
(ex->ravi_type == var->ravi_type && var->usertype && var->usertype == ex->usertype && ex->k != VINDEXED))
else if (var->ravi_type_map == (RAVI_TM_USERDATA | RAVI_TM_NIL)) {
if ((ex->ravi_type_map & ~(RAVI_TM_USERDATA | RAVI_TM_NIL)) == 0 &&
(!(ex->ravi_type_map & RAVI_TM_USERDATA) || (var->usertype && var->usertype == ex->usertype)))
return;
luaX_syntaxerror(
fs->ls,
@ -940,27 +936,28 @@ static void check_valid_store(FuncState *fs, expdesc *var, expdesc *ex) {
static OpCode check_valid_setupval(FuncState *fs, expdesc *var, expdesc *ex,
int reg) {
lua_assert(var->ravi_type_map == RAVI_TM_ANY || (var->ravi_type_map != 0 && (var->ravi_type_map & (var->ravi_type_map - 1)) == 0));
OpCode op = OP_SETUPVAL;
if ((var->ravi_type == RAVI_TNUMINT || var->ravi_type == RAVI_TNUMFLT ||
var->ravi_type == RAVI_TARRAYFLT || var->ravi_type == RAVI_TARRAYINT ||
var->ravi_type == RAVI_TTABLE || var->ravi_type == RAVI_TSTRING ||
var->ravi_type == RAVI_TFUNCTION || var->ravi_type == RAVI_TUSERDATA) &&
var->ravi_type != ex->ravi_type) {
if (var->ravi_type == RAVI_TNUMINT)
if ((var->ravi_type_map == RAVI_TM_INTEGER || var->ravi_type_map == RAVI_TM_FLOAT ||
var->ravi_type_map == RAVI_TM_INTEGER_ARRAY || var->ravi_type_map == RAVI_TM_FLOAT_ARRAY ||
var->ravi_type_map == RAVI_TM_TABLE || var->ravi_type_map == RAVI_TM_STRING | RAVI_TM_NIL ||
var->ravi_type_map == RAVI_TM_FUNCTION | RAVI_TM_NIL || var->ravi_type_map == RAVI_TM_USERDATA | RAVI_TM_NIL) &&
ex->ravi_type_map & ~var->ravi_type_map) {
if (var->ravi_type_map == RAVI_TM_INTEGER)
op = OP_RAVI_SETUPVALI;
else if (var->ravi_type == RAVI_TNUMFLT)
else if (var->ravi_type_map == RAVI_TM_FLOAT)
op = OP_RAVI_SETUPVALF;
else if (var->ravi_type == RAVI_TARRAYINT)
else if (var->ravi_type_map == RAVI_TM_INTEGER_ARRAY)
op = OP_RAVI_SETUPVAL_IARRAY;
else if (var->ravi_type == RAVI_TARRAYFLT)
else if (var->ravi_type_map == RAVI_TM_FLOAT_ARRAY)
op = OP_RAVI_SETUPVAL_FARRAY;
else if (var->ravi_type == RAVI_TTABLE)
else if (var->ravi_type_map == RAVI_TM_TABLE)
op = OP_RAVI_SETUPVALT;
else if (var->ravi_type == RAVI_TSTRING)
else if (var->ravi_type_map == RAVI_TM_STRING | RAVI_TM_NIL)
luaK_codeABC(fs, OP_RAVI_TOSTRING, reg, 0, 0);
else if (var->ravi_type == RAVI_TFUNCTION)
else if (var->ravi_type_map == RAVI_TM_FUNCTION | RAVI_TM_NIL)
luaK_codeABC(fs, OP_RAVI_TOCLOSURE, reg, 0, 0);
else if (var->ravi_type == RAVI_TUSERDATA) {
else if (var->ravi_type_map == RAVI_TM_USERDATA | RAVI_TM_NIL) {
TString *usertype = fs->f->upvalues[var->u.info].usertype;
luaK_codeABx(fs, OP_RAVI_TOTYPE, reg, luaK_stringK(fs, usertype));
}
@ -979,9 +976,9 @@ static OpCode check_valid_setupval(FuncState *fs, expdesc *var, expdesc *ex,
void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {
switch (var->k) {
case VLOCAL: {
check_valid_store(fs, var, ex);
freeexp(fs, ex);
exp2reg(fs, ex, var->u.info); /* compute 'ex' into proper place */
check_valid_store(fs, var, ex);
return;
}
case VUPVAL: {
@ -991,38 +988,26 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {
break;
}
case VINDEXED: {
OpCode op = (var->u.ind.vt == VLOCAL) ? OP_SETTABLE : OP_SETTABUP;
if (op == OP_SETTABLE) {
OpCode op;
int e = luaK_exp2RK(fs, ex);
if (var->u.ind.vt == VLOCAL) {
/* table value set - if array access then use specialized versions */
if (var->ravi_type == RAVI_TARRAYFLT &&
var->u.ind.key_ravi_type == RAVI_TNUMINT) {
if (!(ex->ravi_type == RAVI_TNUMFLT || (ex->k == VINDEXED && ex->ravi_type == RAVI_TARRAYFLT)))
/* input value may need conversion */
op = OP_RAVI_FARRAY_SET;
else
/* input value is known to be number */
op = OP_RAVI_FARRAY_SETF;
} else if (var->ravi_type == RAVI_TARRAYINT &&
var->u.ind.key_ravi_type == RAVI_TNUMINT) {
if (!(ex->ravi_type == RAVI_TNUMINT || (ex->k == VINDEXED && ex->ravi_type == RAVI_TARRAYINT)))
/* input value may need conversion */
op = OP_RAVI_IARRAY_SET;
else
/* input value is known to be integer */
op = OP_RAVI_IARRAY_SETI;
} else if (var->u.ind.key_ravi_type == RAVI_TNUMINT) {
/* index op with integer key, target may not be a table */
op = OP_RAVI_SETI;
} else if (var->ravi_type == RAVI_TTABLE && var->u.ind.key_ravi_type == RAVI_TSTRING && isshortstr(fs, var->u.ind.idx)) {
/* table with string key */
op = OP_RAVI_TABLE_SETFIELD;
}
else if (var->u.ind.key_ravi_type == RAVI_TSTRING && isshortstr(fs, var->u.ind.idx)) {
/* index op with string key, target may not be a table */
op = OP_RAVI_SETFIELD;
if (var->u.ind.key_ravi_type_map == RAVI_TM_INTEGER) {
if (var->ravi_type_map == RAVI_TM_FLOAT_ARRAY) {
op = ex->ravi_type_map == RAVI_TM_FLOAT ? OP_RAVI_FARRAY_SETF : OP_RAVI_FARRAY_SET;
} else if (var->ravi_type_map == RAVI_TM_INTEGER_ARRAY) {
op = ex->ravi_type_map == RAVI_TM_INTEGER ? OP_RAVI_IARRAY_SETI : OP_RAVI_IARRAY_SET;
} else {
op = OP_RAVI_SETI;
}
} else if (var->u.ind.key_ravi_type_map == RAVI_TM_STRING && isshortstr(fs, var->u.ind.idx)) {
op = var->ravi_type_map == RAVI_TM_TABLE ? OP_RAVI_TABLE_SETFIELD : OP_RAVI_SETFIELD;
} else {
op = OP_SETTABLE;
}
} else {
op = OP_SETTABUP;
}
int e = luaK_exp2RK(fs, ex);
luaK_codeABC(fs, op, var->u.ind.t, var->u.ind.idx, e);
break;
}
@ -1045,13 +1030,13 @@ void luaK_self (FuncState *fs, expdesc *e, expdesc *key) {
*/
int is_string_constant_key =
key->k == VK &&
key->ravi_type == RAVI_TSTRING &&
key->ravi_type_map == RAVI_TM_STRING &&
ttisshrstring(&fs->f->k[key->u.info]);
luaK_exp2anyreg(fs, e);
// The check below needs to be
// after exp2anyreg as this can modify e->ravi_type
int table_and_string =
e->ravi_type == RAVI_TTABLE &&
e->ravi_type_map == RAVI_TM_TABLE &&
is_string_constant_key;
ereg = e->u.info; /* register where 'e' was placed */
freeexp(fs, e);
@ -1115,7 +1100,7 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) {
break;
}
default: {
if (e->ravi_type == RAVI_TNIL || e->ravi_type == RAVI_TANY || e->ravi_type == RAVI_TBOOLEAN) {
if (e->ravi_type_map & RAVI_TM_FALSISH) {
pc = jumponcond(fs, e, 0); /* jump when false */
}
else {
@ -1146,11 +1131,11 @@ void luaK_goiffalse (FuncState *fs, expdesc *e) {
break;
}
default: {
if (e->ravi_type == RAVI_TNIL) {
pc = NO_JUMP; /* always false; do nothing */
if (e->ravi_type_map & RAVI_TM_TRUISH) {
pc = jumponcond(fs, e, 1); /* jump if true */
}
else {
pc = jumponcond(fs, e, 1); /* jump if true */
pc = NO_JUMP; /* always false; do nothing */
}
break;
}
@ -1169,14 +1154,17 @@ 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_map = RAVI_TM_TRUE;
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_map = RAVI_TM_FALSE;
break;
}
case VJMP: {
negatecondition(fs, e);
e->ravi_type_map = RAVI_TM_BOOLEAN;
break;
}
case VRELOCABLE:
@ -1185,11 +1173,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_map = RAVI_TM_BOOLEAN;
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 */
@ -1204,7 +1192,7 @@ static void codenot (FuncState *fs, expdesc *e) {
void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
lua_assert(!hasjumps(t) && (vkisinreg(t->k) || t->k == VUPVAL));
t->u.ind.t = t->u.info; /* register or upvalue index */
t->u.ind.key_ravi_type = k->ravi_type; /* RAVI record the key type */
t->u.ind.key_ravi_type_map = k->ravi_type_map; /* RAVI record the key type */
t->u.ind.usertype = k->usertype; /* RAVI record the key type */
t->u.ind.idx = luaK_exp2RK(fs, k); /* R/K index for key */
t->u.ind.vt = (t->k == VUPVAL) ? VUPVAL : VLOCAL;
@ -1244,7 +1232,7 @@ static int constfolding (FuncState *fs, int op, expdesc *e1,
if (ttisinteger(&res)) {
e1->k = VKINT;
e1->u.ival = ivalue(&res);
e1->ravi_type = RAVI_TNUMINT;
e1->ravi_type_map = RAVI_TM_INTEGER;
}
else { /* folds neither NaN nor 0.0 (to avoid problems with -0.0) */
lua_Number n = fltvalue(&res);
@ -1252,7 +1240,7 @@ static int constfolding (FuncState *fs, int op, expdesc *e1,
return 0;
e1->k = VKFLT;
e1->u.nval = n;
e1->ravi_type = RAVI_TNUMFLT;
e1->ravi_type_map = RAVI_TM_FLOAT;
}
return 1;
}
@ -1268,42 +1256,41 @@ static void codeunexpval (FuncState *fs, OpCode op, expdesc *e, int line) {
freeexp(fs, e);
switch (op) {
case OP_BNOT:
if (e->ravi_type == RAVI_TNUMINT) {
if (e->ravi_type_map == RAVI_TM_INTEGER) {
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;
e->ravi_type_map = e->ravi_type_map == RAVI_TM_FLOAT ? RAVI_TM_INTEGER : RAVI_TM_ANY;
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;
if ((e->ravi_type_map & (~(RAVI_TM_INTEGER_ARRAY | RAVI_TM_FLOAT_ARRAY | RAVI_TM_STRING))) == 0) {
e->ravi_type_map = RAVI_TM_INTEGER;
}
else if (e->ravi_type == RAVI_TTABLE) {
else if ((e->ravi_type_map & (~(RAVI_TM_INTEGER_ARRAY | RAVI_TM_FLOAT_ARRAY | RAVI_TM_STRING | RAVI_TM_TABLE))) == 0) {
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;
e->ravi_type_map = RAVI_TM_INTEGER;
luaK_fixline(fs, line);
return;
}
else {
e->ravi_type = RAVI_TANY;
e->ravi_type_map = RAVI_TM_ANY;
}
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;
if (e->ravi_type_map & ~RAVI_TM_NUMBER) {
e->ravi_type_map = RAVI_TM_ANY;
}
break;
default:
e->u.info = luaK_codeABC(fs, op, 0, r, 0);
e->ravi_type = RAVI_TANY;
e->ravi_type_map = RAVI_TM_ANY;
}
e->k = VRELOCABLE; /* all those operations are relocatable */
luaK_fixline(fs, line);
@ -1329,61 +1316,68 @@ static void codebinexpval (FuncState *fs, OpCode op,
#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; \
#define RAVI_GEN_ARITH(op, co, ii, t) \
case OP_##op: \
if (e1->ravi_type_map == RAVI_TM_FLOAT) { \
if (e2->ravi_type_map == RAVI_TM_FLOAT) { \
e1->u.info = luaK_codeABC(fs, t(op, FF), 0, rk1, rk2); \
break; \
} \
else if (e2->ravi_type_map == RAVI_TM_INTEGER) { \
e1->u.info = luaK_codeABC(fs, t(op, FI), 0, rk1, rk2); \
break; \
} \
} \
else if (e1->ravi_type_map == RAVI_TM_INTEGER) { \
if (e2->ravi_type_map == RAVI_TM_FLOAT) { \
e1->u.info = co(op, t); \
e1->ravi_type_map = RAVI_TM_FLOAT; \
break; \
} \
else if (e2->ravi_type_map == RAVI_TM_INTEGER) { \
e1->u.info = luaK_codeABC(fs, t(op, II), 0, rk1, rk2); \
e1->ravi_type_map = ii; \
break; \
} \
} \
e1->u.info = luaK_codeABC(fs, OP_##op, 0, rk1, rk2); \
if ((e1->ravi_type_map & (~(RAVI_TM_FLOAT | RAVI_TM_INTEGER))) == 0 && \
(e1->ravi_type_map & (~(RAVI_TM_FLOAT | RAVI_TM_INTEGER))) == 0) { \
if (e1->ravi_type_map & e2->ravi_type_map & RAVI_TM_INTEGER) { \
e1->ravi_type_map = RAVI_TM_FLOAT | RAVI_TM_INTEGER; \
} \
else { \
e1->ravi_type_map = RAVI_TM_FLOAT; \
} \
} \
else { \
e1->ravi_type_map = RAVI_TM_ANY; \
} \
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; \
} \
#define RAVI_GEN_INT_OP(op) \
case OP_##op: \
if (e1->ravi_type_map == RAVI_TM_INTEGER && e2->ravi_type_map == RAVI_TM_INTEGER) { \
e1->u.info = luaK_codeABC(fs, OP_RAVI_##op##_II, 0, rk1, rk2); \
} \
else if ((e1->ravi_type_map & (~RAVI_TM_NUMBER)) == 0 && (e2->ravi_type_map & (~RAVI_TM_NUMBER)) == 0) { \
e1->u.info = luaK_codeABC(fs, OP_##op, 0, rk1, rk2); \
e1->ravi_type_map = RAVI_TM_INTEGER; \
} \
else { \
e1->u.info = luaK_codeABC(fs, OP_##op, 0, rk1, rk2); \
e1->ravi_type_map = RAVI_TM_ANY; \
} \
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_ARITH(ADD, RAVI_COMMUTATIVE, RAVI_TM_INTEGER, RAVI_OPCODE_SPECIALIZED);
RAVI_GEN_ARITH(SUB, RAVI_NON_COMMUTATIVE, RAVI_TM_INTEGER, RAVI_OPCODE_SPECIALIZED);
RAVI_GEN_ARITH(MUL, RAVI_COMMUTATIVE, RAVI_TM_INTEGER, RAVI_OPCODE_SPECIALIZED);
RAVI_GEN_ARITH(DIV, RAVI_NON_COMMUTATIVE, RAVI_TM_FLOAT, RAVI_OPCODE_SPECIALIZED);
RAVI_GEN_ARITH(IDIV, RAVI_NON_COMMUTATIVE, RAVI_TM_INTEGER, RAVI_OPCODE_GENERIC);
RAVI_GEN_ARITH(MOD, RAVI_NON_COMMUTATIVE, RAVI_TM_INTEGER, RAVI_OPCODE_GENERIC);
RAVI_GEN_ARITH(POW, RAVI_NON_COMMUTATIVE, RAVI_TM_FLOAT, RAVI_OPCODE_GENERIC);
RAVI_GEN_INT_OP(BAND);
RAVI_GEN_INT_OP(BOR);
RAVI_GEN_INT_OP(BXOR);
@ -1391,17 +1385,17 @@ 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)) {
e1->ravi_type = RAVI_TSTRING;
if ((e1->ravi_type_map & (~(RAVI_TM_STRING | RAVI_TM_INTEGER | RAVI_TM_FLOAT))) == 0 ||
(e2->ravi_type_map & (~(RAVI_TM_STRING | RAVI_TM_INTEGER | RAVI_TM_FLOAT))) == 0) {
e1->ravi_type_map = RAVI_TM_STRING;
}
else {
e1->ravi_type = RAVI_TANY;
e1->ravi_type_map = RAVI_TM_ANY;
}
break;
default:
e1->u.info = luaK_codeABC(fs, op, 0, rk1, rk2);
e1->ravi_type = RAVI_TANY;
e1->ravi_type_map = RAVI_TM_ANY;
}
e1->k = VRELOCABLE; /* all those operations are relocatable */
@ -1409,23 +1403,23 @@ static void codebinexpval (FuncState *fs, OpCode op,
}
static OpCode get_type_specific_comp_op(OpCode op, ravitype_t o1_tt, ravitype_t o2_tt) {
static OpCode get_type_specific_comp_op(OpCode op, uint32_t o1_tm, uint32_t o2_tm) {
if (op == OP_EQ) {
if (o1_tt == RAVI_TNUMINT && o2_tt == RAVI_TNUMINT)
if (o1_tm == RAVI_TM_INTEGER && o2_tm == RAVI_TM_INTEGER)
op = OP_RAVI_EQ_II;
else if (o1_tt == RAVI_TNUMFLT && o2_tt == RAVI_TNUMFLT)
else if (o1_tm == RAVI_TM_FLOAT && o2_tm == RAVI_TM_FLOAT)
op = OP_RAVI_EQ_FF;
}
else if (op == OP_LT) {
if (o1_tt == RAVI_TNUMINT && o2_tt == RAVI_TNUMINT)
if (o1_tm == RAVI_TM_INTEGER && o2_tm == RAVI_TM_INTEGER)
op = OP_RAVI_LT_II;
else if (o1_tt == RAVI_TNUMFLT && o2_tt == RAVI_TNUMFLT)
else if (o1_tm == RAVI_TM_FLOAT && o2_tm == RAVI_TM_FLOAT)
op = OP_RAVI_LT_FF;
}
else if (op == OP_LE) {
if (o1_tt == RAVI_TNUMINT && o2_tt == RAVI_TNUMINT)
if (o1_tm == RAVI_TM_INTEGER && o2_tm == RAVI_TM_INTEGER)
op = OP_RAVI_LE_II;
else if (o1_tt == RAVI_TNUMFLT && o2_tt == RAVI_TNUMFLT)
else if (o1_tm == RAVI_TM_FLOAT && o2_tm == RAVI_TM_FLOAT)
op = OP_RAVI_LE_FF;
}
return op;
@ -1439,32 +1433,32 @@ static void codecomp (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) {
DEBUG_EXPR(raviY_printf(fs, "Comparison of %e and %e\n", e1, e2));
int rk1 = (e1->k == VK) ? RKASK(e1->u.info)
: check_exp(e1->k == VNONRELOC, e1->u.info);
ravitype_t rk1_tt = e1->ravi_type;
uint32_t rk1_tm = e1->ravi_type_map;
int rk2 = luaK_exp2RK(fs, e2);
ravitype_t rk2_tt = e2->ravi_type;
uint32_t rk2_tm = e2->ravi_type_map;
freeexps(fs, e1, e2);
switch (opr) {
case OPR_NE: { /* '(a ~= b)' ==> 'not (a == b)' */
OpCode op = get_type_specific_comp_op(OP_EQ, rk1_tt, rk2_tt);
OpCode op = get_type_specific_comp_op(OP_EQ, rk1_tm, rk2_tm);
e1->u.info = condjump(fs, op, 0, rk1, rk2);
break;
}
case OPR_GT: case OPR_GE: {
/* '(a > b)' ==> '(b < a)'; '(a >= b)' ==> '(b <= a)' */
OpCode op = cast(OpCode, (opr - OPR_NE) + OP_EQ);
op = get_type_specific_comp_op(op, rk2_tt, rk1_tt);
op = get_type_specific_comp_op(op, rk2_tm, rk1_tm);
e1->u.info = condjump(fs, op, 1, rk2, rk1); /* invert operands */
break;
}
default: { /* '==', '<', '<=' use their own opcodes */
OpCode op = cast(OpCode, (opr - OPR_EQ) + OP_EQ);
op = get_type_specific_comp_op(op, rk1_tt, rk2_tt);
op = get_type_specific_comp_op(op, rk1_tm, rk2_tm);
e1->u.info = condjump(fs, op, 1, rk1, rk2);
break;
}
}
e1->k = VJMP;
e1->ravi_type = RAVI_TBOOLEAN;
e1->ravi_type_map = RAVI_TM_BOOLEAN;
}
@ -1479,21 +1473,21 @@ static void code_type_assertion(FuncState *fs, UnOpr op, expdesc *e, TString *us
switch (e->k) {
case VKFLT: {
if (op == OPR_TO_NUMBER) {
e->ravi_type = RAVI_TNUMFLT; /* RAVI TODO*/
lua_assert(e->ravi_type_map == RAVI_TM_FLOAT);
return;
}
break;
}
case VKINT: {
if (op == OPR_TO_INTEGER) {
e->ravi_type = RAVI_TNUMINT; /* RAVI TODO*/
lua_assert(e->ravi_type_map == RAVI_TM_INTEGER);
return;
}
break;
}
case VK: {
if (op == OPR_TO_STRING) {
if (e->ravi_type == RAVI_TSTRING)
if (e->ravi_type_map == RAVI_TM_STRING)
return;
}
break;
@ -1502,56 +1496,56 @@ static void code_type_assertion(FuncState *fs, UnOpr op, expdesc *e, TString *us
case VNONRELOC: {
discharge2anyreg(fs, e);
OpCode opcode;
ravitype_t tt;
if (op == OPR_TO_NUMBER && e->ravi_type != RAVI_TNUMFLT) {
uint32_t tm;
if (op == OPR_TO_NUMBER && e->ravi_type_map != RAVI_TM_FLOAT) {
opcode = OP_RAVI_TOFLT;
tt = RAVI_TNUMFLT;
tm = RAVI_TM_FLOAT;
}
else if (op == OPR_TO_INTEGER && e->ravi_type != RAVI_TNUMINT) {
else if (op == OPR_TO_INTEGER && e->ravi_type_map != RAVI_TM_INTEGER) {
opcode = OP_RAVI_TOINT;
tt = RAVI_TNUMINT;
tm = RAVI_TM_INTEGER;
}
else if (op == OPR_TO_INTARRAY && e->ravi_type != RAVI_TARRAYINT) {
if (e->ravi_type == RAVI_TTABLE && e->pc >= 0) {
else if (op == OPR_TO_INTARRAY && e->ravi_type_map != RAVI_TM_INTEGER_ARRAY) {
if (e->ravi_type_map == RAVI_TM_TABLE && e->pc >= 0) {
Instruction *i = &fs->f->code[e->pc];
if (GET_OPCODE(*i) == OP_NEWTABLE) {
SET_OPCODE(*i, OP_RAVI_NEW_IARRAY);
e->ravi_type = RAVI_TARRAYINT;
e->ravi_type_map = RAVI_TM_INTEGER_ARRAY;
DEBUG_EXPR(raviY_printf(fs, "code_type_assertion (OP_NEWTABLE to OP_RAVI_NEW_IARRAY) %e\n", e));
}
return;
}
opcode = OP_RAVI_TOIARRAY;
tt = RAVI_TARRAYINT;
tm = RAVI_TM_INTEGER_ARRAY;
}
else if (op == OPR_TO_NUMARRAY && e->ravi_type != RAVI_TARRAYFLT) {
if (e->ravi_type == RAVI_TTABLE && e->pc >= 0) {
else if (op == OPR_TO_NUMARRAY && e->ravi_type_map != RAVI_TM_FLOAT_ARRAY) {
if (e->ravi_type_map == RAVI_TM_TABLE && e->pc >= 0) {
Instruction *i = &fs->f->code[e->pc];
if (GET_OPCODE(*i) == OP_NEWTABLE) {
SET_OPCODE(*i, OP_RAVI_NEW_FARRAY);
e->ravi_type = RAVI_TARRAYFLT;
e->ravi_type_map = RAVI_TM_FLOAT_ARRAY;
DEBUG_EXPR(raviY_printf(fs, "code_type_assertion (OP_NEWTABLE to OP_RAVI_NEW_IARRAY) %e\n", e));
}
return;
}
opcode = OP_RAVI_TOFARRAY;
tt = RAVI_TARRAYFLT;
tm = RAVI_TM_FLOAT_ARRAY;
}
else if (op == OPR_TO_TABLE && e->ravi_type != RAVI_TTABLE) {
else if (op == OPR_TO_TABLE && e->ravi_type_map != RAVI_TM_TABLE) {
opcode = OP_RAVI_TOTAB;
tt = RAVI_TTABLE;
tm = RAVI_TM_TABLE;
}
else if (op == OPR_TO_STRING && e->ravi_type != RAVI_TSTRING) {
else if (op == OPR_TO_STRING && e->ravi_type_map != RAVI_TM_STRING) {
opcode = OP_RAVI_TOSTRING;
tt = RAVI_TSTRING;
tm = RAVI_TM_STRING;
}
else if (op == OPR_TO_CLOSURE && e->ravi_type != RAVI_TFUNCTION) {
else if (op == OPR_TO_CLOSURE && e->ravi_type_map != RAVI_TM_FUNCTION) {
opcode = OP_RAVI_TOCLOSURE;
tt = RAVI_TFUNCTION;
tm = RAVI_TM_FUNCTION;
}
else if (op == OPR_TO_TYPE) {
opcode = OP_RAVI_TOTYPE;
tt = RAVI_TUSERDATA;
tm = RAVI_TM_USERDATA;
}
else {
/* nothing to do*/
@ -1563,7 +1557,7 @@ static void code_type_assertion(FuncState *fs, UnOpr op, expdesc *e, TString *us
}
else
luaK_codeABC(fs, opcode, e->u.info, 0, 0);
e->ravi_type = tt;
e->ravi_type_map = tm;
e->k = VNONRELOC;
if (opcode == OP_RAVI_TOTYPE)
e->usertype = usertype;
@ -1578,7 +1572,7 @@ static void code_type_assertion(FuncState *fs, UnOpr op, expdesc *e, TString *us
** Apply prefix operation 'op' to expression 'e'.
*/
void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line, TString *usertype) {
expdesc ef = {.ravi_type = RAVI_TANY,
expdesc ef = {.ravi_type_map = RAVI_TM_ANY,
.pc = -1,
.t = NO_JUMP,
.f = NO_JUMP,
@ -1652,19 +1646,7 @@ 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);
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. */
}
e2->ravi_type_map |= e1->ravi_type_map & RAVI_TM_FALSISH;
*e1 = *e2;
break;
}
@ -1672,19 +1654,11 @@ 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);
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;
if (e1->ravi_type_map & e2->ravi_type_map & RAVI_TM_USERDATA) {
if (e1->usertype != e2->usertype)
e2->usertype = NULL;
}
e2->ravi_type_map |= e1->ravi_type_map & RAVI_TM_TRUISH;
*e1 = *e2;
break;
}
@ -1697,12 +1671,12 @@ 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;
if (e2->ravi_type_map == RAVI_TM_STRING &&
(e1->ravi_type_map & (~(RAVI_TM_STRING | RAVI_TM_INTEGER | RAVI_TM_FLOAT))) == 0) {
e1->ravi_type_map = RAVI_TM_STRING;
}
else {
e1->ravi_type = RAVI_TANY;
e1->ravi_type_map = RAVI_TM_ANY;
}
}
else {

@ -68,6 +68,41 @@ typedef enum {
RAVI_TUSERDATA /* userdata or lightuserdata */
} ravitype_t;
typedef enum {
RAVI_TI_NIL,
RAVI_TI_FALSE,
RAVI_TI_TRUE,
RAVI_TI_INTEGER,
RAVI_TI_FLOAT,
RAVI_TI_INTEGER_ARRAY,
RAVI_TI_FLOAT_ARRAY,
RAVI_TI_TABLE,
RAVI_TI_STRING,
RAVI_TI_FUNCTION,
RAVI_TI_USERDATA,
RAVI_TI_OTHER
} ravi_type_index;
#define RAVI_TM_NIL (1<<RAVI_TI_NIL)
#define RAVI_TM_FALSE (1<<RAVI_TI_FALSE)
#define RAVI_TM_TRUE (1<<RAVI_TI_TRUE)
#define RAVI_TM_INTEGER (1<<RAVI_TI_INTEGER)
#define RAVI_TM_FLOAT (1<<RAVI_TI_FLOAT)
#define RAVI_TM_INTEGER_ARRAY (1<<RAVI_TI_INTEGER_ARRAY)
#define RAVI_TM_FLOAT_ARRAY (1<<RAVI_TI_FLOAT_ARRAY)
#define RAVI_TM_TABLE (1<<RAVI_TI_TABLE)
#define RAVI_TM_STRING (1<<RAVI_TI_STRING)
#define RAVI_TM_FUNCTION (1<<RAVI_TI_FUNCTION)
#define RAVI_TM_USERDATA (1<<RAVI_TI_USERDATA)
#define RAVI_TM_OTHER (1<<RAVI_TI_OTHER)
#define RAVI_TM_FALSISH (RAVI_TM_NIL | RAVI_TM_FALSE)
#define RAVI_TM_TRUISH (~RAVI_TM_FALSISH)
#define RAVI_TM_BOOLEAN (RAVI_TM_FALSE | RAVI_TM_TRUE)
#define RAVI_TM_NUMBER (RAVI_TM_INTEGER | RAVI_TM_FLOAT)
#define RAVI_TM_INDEXABLE (RAVI_TM_INTEGER_ARRAY | RAVI_TM_FLOAT_ARRAY | RAVI_TM_TABLE)
#define RAVI_TM_ANY (~0)
/*
** Tagged Values. This is the basic representation of values in Lua,
** an actual value plus a tag with its type.
@ -432,7 +467,7 @@ typedef union UUdata {
typedef struct Upvaldesc {
TString *name; /* upvalue name (for debug information) */
TString *usertype; /* RAVI extension: name of user type */
lu_byte ravi_type; /* RAVI type of upvalue */
uint16_t ravi_type_map; /* RAVI type of upvalue */
lu_byte instack; /* whether it is in stack (register) */
lu_byte idx; /* index of upvalue (in stack or in outer function's list) */
} Upvaldesc;
@ -447,7 +482,7 @@ typedef struct LocVar {
TString *usertype; /* RAVI extension: name of user type */
int startpc; /* first point where variable is active */
int endpc; /* first point where variable is dead */
lu_byte ravi_type; /* RAVI type of the variable - RAVI_TANY if unknown */
uint32_t ravi_type_map; /* RAVI type of the variable - RAVI_TANY if unknown */
} LocVar;
/** RAVI changes start */

@ -94,66 +94,130 @@ const char *raviY_typename(ravitype_t tt) {
}
}
static char* raviY_buf_append(char* buf, const char* what) {
char c;
while((c=*what++)) {
*buf++ = c;
}
return buf;
}
#define RAVI_TYPEMAP_MAX_LEN (sizeof("nil|boolean|integer|number|integer[]|number[]|table|string|function|userdata|?|"))
static void raviY_typemap_string(uint32_t tm, char* buf) {
if (tm == RAVI_TM_ANY) {
memcpy(buf, "any", 4);
return;
} else if (tm == 0) {
memcpy(buf, "?", 2);
return;
}
buf[0] = '|';
buf++;
if (tm & RAVI_TM_NIL) {
buf = raviY_buf_append(buf, "nil|");
}
if (tm & RAVI_TM_BOOLEAN) {
if ((tm & RAVI_TM_TRUE) == 0) {
buf = raviY_buf_append(buf, "false|");
} else if((tm & RAVI_TM_FALSE) == 0) {
buf = raviY_buf_append(buf, "true|");
} else {
buf = raviY_buf_append(buf, "boolean|");
}
}
if (tm & RAVI_TM_INTEGER) {
buf = raviY_buf_append(buf, "integer|");
}
if (tm & RAVI_TM_FLOAT) {
buf = raviY_buf_append(buf, "number|");
}
if (tm & RAVI_TM_INTEGER_ARRAY) {
buf = raviY_buf_append(buf, "integer[]|");
}
if (tm & RAVI_TM_FLOAT_ARRAY) {
buf = raviY_buf_append(buf, "number[]|");
}
if (tm & RAVI_TM_TABLE) {
buf = raviY_buf_append(buf, "table|");
}
if (tm & RAVI_TM_STRING) {
buf = raviY_buf_append(buf, "string|");
}
if (tm & RAVI_TM_FUNCTION) {
buf = raviY_buf_append(buf, "function|");
}
if (tm & RAVI_TM_USERDATA) {
buf = raviY_buf_append(buf, "userdata|");
}
if (tm & RAVI_TM_OTHER) {
buf = raviY_buf_append(buf, "?|");
}
buf[-1] = 0;
}
/* RAVI - prints a Lua expression node */
static void print_expdesc(FILE *fp, FuncState *fs, const expdesc *e) {
char buf[80] = {0};
static void v(FILE *fp, FuncState *fs, const expdesc *e) {
char buf[80] = {0v};
char type_map_str[RAVI_TYPEMAP_MAX_LEN];
raviY_typemap_string(e->ravi_type_map, type_map_str);
switch (e->k) {
case VVOID:
fprintf(fp, "{p=%p, k=VVOID, type=%s}", e, raviY_typename(e->ravi_type));
fprintf(fp, "{p=%p, k=VVOID, type=%s}", e, type_map_str);
break;
case VNIL:
fprintf(fp, "{p=%p, k=VNIL, type=%s}", e, raviY_typename(e->ravi_type));
fprintf(fp, "{p=%p, k=VNIL, type=%s}", e, type_map_str);
break;
case VTRUE:
fprintf(fp, "{p=%p, k=VTRUE, type=%s}", e, raviY_typename(e->ravi_type));
fprintf(fp, "{p=%p, k=VTRUE, type=%s}", e, type_map_str);
break;
case VFALSE:
fprintf(fp, "{p=%p, k=VFALSE, type=%s}", e, raviY_typename(e->ravi_type));
fprintf(fp, "{p=%p, k=VFALSE, type=%s}", e, type_map_str);
break;
case VK:
fprintf(fp, "{p=%p, k=VK, Kst=%d, type=%s}", e, e->u.info,
raviY_typename(e->ravi_type));
type_map_str);
break;
case VKFLT:
fprintf(fp, "{p=%p, k=VKFLT, n=%f, type=%s}", e, e->u.nval,
raviY_typename(e->ravi_type));
type_map_str);
break;
case VKINT:
fprintf(fp, "{p=%p, k=VKINT, n=%lld, type=%s}", e, (long long)e->u.ival,
raviY_typename(e->ravi_type));
type_map_str);
break;
case VNONRELOC:
fprintf(fp, "{p=%p, k=VNONRELOC, register=%d %s, type=%s, pc=%d}", e, e->u.info,
raviY_typename(raviY_get_register_typeinfo(fs, e->u.info, NULL)),
raviY_typename(e->ravi_type),
type_map_str,
e->pc);
break;
case VLOCAL:
fprintf(fp, "{p=%p, k=VLOCAL, register=%d, type=%s}", e, e->u.info,
raviY_typename(e->ravi_type));
type_map_str);
break;
case VUPVAL:
fprintf(fp, "{p=%p, k=VUPVAL, idx=%d, type=%s}", e, e->u.info,
raviY_typename(e->ravi_type));
type_map_str);
break;
case VINDEXED:
fprintf(fp,
"{p=%p, k=VINDEXED, tablereg=%d, indexreg=%d, vtype=%s, type=%s}",
e, e->u.ind.t, e->u.ind.idx,
(e->u.ind.vt == VLOCAL) ? "VLOCAL" : "VUPVAL",
raviY_typename(e->ravi_type));
type_map_str);
break;
case VJMP:
fprintf(fp, "{p=%p, k=VJMP, pc=%d, instruction=(%s), type=%s}", e,
e->u.info,
raviP_instruction_to_str(buf, sizeof buf, getinstruction(fs, e)),
raviY_typename(e->ravi_type));
type_map_str);
break;
case VRELOCABLE:
fprintf(fp, "{p=%p, k=VRELOCABLE, pc=%d, instruction=(%s), type=%s, pc=%d}", e,
e->u.info,
raviP_instruction_to_str(buf, sizeof buf, getinstruction(fs, e)),
raviY_typename(e->ravi_type),
type_map_str,
e->pc);
break;
case VCALL:
@ -161,13 +225,13 @@ static void print_expdesc(FILE *fp, FuncState *fs, const expdesc *e) {
fp, "{p=%p, k=VCALL, pc=%d, instruction=(%s %s), type=%s}", e,
e->u.info, raviP_instruction_to_str(buf, sizeof buf, getinstruction(fs, e)),
raviY_typename(raviY_get_register_typeinfo(fs, GETARG_A(getinstruction(fs, e)), NULL)),
raviY_typename(e->ravi_type));
type_map_str);
break;
case VVARARG:
fprintf(fp, "{p=%p, k=VVARARG, pc=%d, instruction=(%s), type=%s}", e,
e->u.info,
raviP_instruction_to_str(buf, sizeof buf, getinstruction(fs, e)),
raviY_typename(e->ravi_type));
type_map_str);
break;
}
}
@ -187,10 +251,12 @@ void raviY_printf(FuncState *fs, const char *format, ...) {
cp++;
} else if (cp[0] == '%' && cp[1] == 'v') {
LocVar *v;
char type_map_str[RAVI_TYPEMAP_MAX_LEN];
v = va_arg(ap, LocVar *);
const char *s = getstr(v->varname);
raviY_typemap_string(v->ravi_type_map, type_map_str);
printf("var={%s startpc=%d endpc=%d, type=%s}", s, v->startpc, v->endpc,
raviY_typename(v->ravi_type));
type_map_str);
cp++;
} else if (cp[0] == '%' && cp[1] == 'o') {
Instruction i;
@ -314,12 +380,12 @@ static TString *str_checkname (LexState *ls) {
* expression kind in e->k, e->u.info may have a register
* or bytecode
*/
static void init_exp (expdesc *e, expkind k, int info, ravitype_t tt, TString *usertype) {
static void init_exp (expdesc *e, expkind k, int info, uint32_t tt, TString *usertype) {
e->f = e->t = NO_JUMP;
e->k = k;
e->u.info = info;
/* RAVI change; added type */
e->ravi_type = tt;
e->ravi_type_map = tt;
e->usertype = usertype;
e->pc = -1;
e->u.ind.usertype = NULL; /* Just for safey */
@ -329,7 +395,7 @@ static void init_exp (expdesc *e, expkind k, int info, ravitype_t tt, TString *u
* e->u.info, e->ravi_type = RAVI_TSTRING, e->k = VK
*/
static void codestring (LexState *ls, expdesc *e, TString *s) {
init_exp(e, VK, luaK_stringK(ls->fs, s), RAVI_TSTRING, NULL);
init_exp(e, VK, luaK_stringK(ls->fs, s), RAVI_TM_STRING, NULL);
}
/* verify that current token is a string, create a string constant
@ -344,7 +410,7 @@ static void checkname (LexState *ls, expdesc *e) {
* variable's index in ls->f->locvars.
* RAVI change - added the type of the variable.
*/
static int registerlocalvar (LexState *ls, TString *varname, unsigned int ravi_type, TString *usertype) {
static int registerlocalvar (LexState *ls, TString *varname, uint32_t ravi_type_map, TString *usertype) {
FuncState *fs = ls->fs;
Proto *f = fs->f;
int oldsize = f->sizelocvars;
@ -354,28 +420,25 @@ static int registerlocalvar (LexState *ls, TString *varname, unsigned int ravi_t
/* RAVI change initialize */
f->locvars[oldsize].startpc = -1;
f->locvars[oldsize].endpc = -1;
f->locvars[oldsize].ravi_type = RAVI_TANY;
f->locvars[oldsize].ravi_type_map = RAVI_TM_ANY;
f->locvars[oldsize].usertype = NULL;
f->locvars[oldsize++].varname = NULL;
}
f->locvars[fs->nlocvars].varname = varname;
f->locvars[fs->nlocvars].ravi_type = ravi_type;
if (ravi_type == RAVI_TUSERDATA && usertype != NULL) {
// Store a reference to the usertype name
f->locvars[fs->nlocvars].usertype = usertype;
}
f->locvars[fs->nlocvars].ravi_type_map = ravi_type_map;
f->locvars[fs->nlocvars].usertype = usertype;
luaC_objbarrier(ls->L, f, varname);
return fs->nlocvars++;
}
/* create a new local variable in function scope, and set the
* variable type (RAVI - added type tt) */
static void new_localvar (LexState *ls, TString *name, ravitype_t tt, TString *usertype) {
static void new_localvar (LexState *ls, TString *name, uint32_t tm, TString *usertype) {
FuncState *fs = ls->fs;
Dyndata *dyd = ls->dyd;
/* register variable and get its index */
/* RAVI change - record type info for local variable */
int reg = registerlocalvar(ls, name, tt, usertype);
int reg = registerlocalvar(ls, name, tm, usertype);
checklimit(fs, dyd->actvar.n + 1 - fs->firstlocal,
MAXVARS, "local variables");
luaM_growvector(ls->L, dyd->actvar.arr, dyd->actvar.n + 1,
@ -391,7 +454,7 @@ static void new_localvar (LexState *ls, TString *name, ravitype_t tt, TString *u
*/
static void new_localvarliteral_ (LexState *ls, const char *name, size_t sz) {
/* RAVI change - add type */
new_localvar(ls, luaX_newstring(ls, name, sz), RAVI_TANY, NULL);
new_localvar(ls, luaX_newstring(ls, name, sz), RAVI_TM_ANY, NULL);
}
/* create a new local variable
@ -428,13 +491,13 @@ static int register_to_locvar_index(FuncState *fs, int reg) {
* return the type associated with the variable.
* This is a RAVI function
*/
ravitype_t raviY_get_register_typeinfo(FuncState *fs, int reg, TString **pusertype) {
uint32_t raviY_get_register_typeinfo(FuncState *fs, int reg, TString **pusertype) {
int idx;
LocVar *v;
/* Due to the way Lua parser works it is not safe to look beyond nactvar */
if (reg < 0 || reg >= fs->nactvar ||
(fs->firstlocal + reg) >= fs->ls->dyd->actvar.n) {
return RAVI_TANY;
return RAVI_TM_ANY;
}
/* Get the LocVar associated with the register */
idx = fs->ls->dyd->actvar.arr[fs->firstlocal + reg].idx;
@ -443,7 +506,7 @@ ravitype_t raviY_get_register_typeinfo(FuncState *fs, int reg, TString **puserty
if (pusertype != NULL)
*pusertype = v->usertype;
/* Variable in scope so return the type if we know it */
return v->ravi_type;
return v->ravi_type_map;
}
/* moves the active variable watermark (nactvar) to cover the
@ -497,7 +560,7 @@ static int newupvalue (FuncState *fs, TString *name, expdesc *v) {
f->upvalues[fs->nups].instack = (v->k == VLOCAL);
f->upvalues[fs->nups].idx = cast_byte(v->u.info);
f->upvalues[fs->nups].name = name;
f->upvalues[fs->nups].ravi_type = v->ravi_type;
f->upvalues[fs->nups].ravi_type_map = v->ravi_type_map;
f->upvalues[fs->nups].usertype = v->usertype;
luaC_objbarrier(fs->ls->L, f, name);
return fs->nups++;
@ -534,13 +597,13 @@ static void markupval (FuncState *fs, int level) {
*/
static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
if (fs == NULL) /* no more levels? */
init_exp(var, VVOID, 0, RAVI_TANY, NULL); /* default is global */
init_exp(var, VVOID, 0, RAVI_TM_ANY, NULL); /* default is global */
else {
int v = searchvar(fs, n); /* look up locals at current level */
if (v >= 0) { /* found? */
/* RAVI set type of local var / expr if possible */
TString *usertype = NULL;
ravitype_t tt = raviY_get_register_typeinfo(fs, v, &usertype);
uint32_t tt = raviY_get_register_typeinfo(fs, v, &usertype);
init_exp(var, VLOCAL, v, tt, usertype); /* variable is local, RAVI set type */
if (!base)
markupval(fs, v); /* local will be used as an upval */
@ -554,7 +617,7 @@ static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
/* else was LOCAL or UPVAL */
idx = newupvalue(fs, n, var); /* will be a new upvalue */
}
init_exp(var, VUPVAL, idx, fs->f->upvalues[idx].ravi_type, fs->f->upvalues[idx].usertype); /* RAVI : set upvalue type */
init_exp(var, VUPVAL, idx, fs->f->upvalues[idx].ravi_type_map, fs->f->upvalues[idx].usertype); /* RAVI : set upvalue type */
}
}
}
@ -568,7 +631,7 @@ static void singlevar (LexState *ls, expdesc *var) {
FuncState *fs = ls->fs;
singlevaraux(fs, varname, var, 1);
if (var->k == VVOID) { /* global name? */
expdesc key = {.ravi_type = RAVI_TANY, .pc = -1};
expdesc key = {.ravi_type_map = RAVI_TM_ANY, .pc = -1};
singlevaraux(fs, ls->envn, var, 1); /* get environment variable */
lua_assert(var->k != VVOID); /* this one must exist */
codestring(ls, &key, varname); /* key is variable name */
@ -578,29 +641,30 @@ static void singlevar (LexState *ls, expdesc *var) {
/* RAVI code an instruction to coerce the type, reg is the register,
and ravi_type is the type we want */
static void ravi_code_typecoersion(LexState *ls, int reg, ravitype_t ravi_type, TString *typename /* only if tt is USERDATA */) {
static void ravi_code_typecoersion(LexState *ls, int reg, uint32_t ravi_type_map, TString *typename /* only if tt is USERDATA */) {
/* do we need to convert ? */
if (ravi_type == RAVI_TNUMFLT || ravi_type == RAVI_TNUMINT)
if (ravi_type_map == RAVI_TM_FLOAT || ravi_type_map == RAVI_TM_INTEGER)
/* code an instruction to convert in place */
luaK_codeABC(ls->fs,
ravi_type == RAVI_TNUMFLT ? OP_RAVI_TOFLT : OP_RAVI_TOINT, reg,
ravi_type_map == RAVI_TM_FLOAT ? OP_RAVI_TOFLT : OP_RAVI_TOINT, reg,
0, 0);
else if (ravi_type == RAVI_TARRAYINT || ravi_type == RAVI_TARRAYFLT)
luaK_codeABC(ls->fs, ravi_type == RAVI_TARRAYINT ? OP_RAVI_TOIARRAY
else if (ravi_type_map == RAVI_TM_INTEGER_ARRAY || ravi_type_map == RAVI_TM_FLOAT_ARRAY)
luaK_codeABC(ls->fs, ravi_type_map == RAVI_TM_INTEGER_ARRAY ? OP_RAVI_TOIARRAY
: OP_RAVI_TOFARRAY,
reg, 0, 0);
else if (ravi_type == RAVI_TTABLE)
else if (ravi_type_map == RAVI_TM_TABLE)
luaK_codeABC(ls->fs, OP_RAVI_TOTAB,
reg, 0, 0);
else if (ravi_type == RAVI_TUSERDATA)
else if (ravi_type_map == (RAVI_TM_USERDATA | RAVI_TM_NIL))
luaK_codeABx(ls->fs, OP_RAVI_TOTYPE,
reg, luaK_stringK(ls->fs, typename));
else if (ravi_type == RAVI_TSTRING)
else if (ravi_type_map == (RAVI_TM_STRING | RAVI_TM_NIL))
luaK_codeABC(ls->fs, OP_RAVI_TOSTRING,
reg, 0, 0);
else if (ravi_type == RAVI_TFUNCTION)
else if (ravi_type_map == RAVI_TM_FUNCTION | RAVI_TM_NIL)
luaK_codeABC(ls->fs, OP_RAVI_TOCLOSURE,
reg, 0, 0);
// TODO coerse to boolean
}
/* RAVI code an instruction to initialize a scalar typed value
@ -609,14 +673,16 @@ static void ravi_code_typecoersion(LexState *ls, int reg, ravitype_t ravi_type,
*/
static void ravi_code_setzero(FuncState *fs, int reg, ravitype_t ravi_type, TString *usertype) {
(void) usertype;
if (ravi_type == RAVI_TNUMFLT || ravi_type == RAVI_TNUMINT)
if (ravi_type == RAVI_TM_FLOAT || ravi_type == RAVI_TM_INTEGER)
/* code an instruction to convert in place */
luaK_codeABC(fs, ravi_type == RAVI_TNUMFLT ? OP_RAVI_LOADFZ : OP_RAVI_LOADIZ, reg, 0, 0);
else if (ravi_type == RAVI_TARRAYFLT)
luaK_codeABC(fs, ravi_type == RAVI_TM_FLOAT ? OP_RAVI_LOADFZ : OP_RAVI_LOADIZ, reg, 0, 0);
else if (~(ravi_type & RAVI_TM_NIL))
luaX_syntaxerror(fs->ls, "uninitialized number[] in local variable"); // TODO
else if (ravi_type == RAVI_TM_FLOAT_ARRAY)
luaX_syntaxerror(fs->ls, "uninitialized number[] in local variable");
else if (ravi_type == RAVI_TARRAYINT)
else if (ravi_type == RAVI_TM_INTEGER_ARRAY)
luaX_syntaxerror(fs->ls, "uninitialized integer[] in local variable");
else if (ravi_type == RAVI_TTABLE)
else if (ravi_type == RAVI_TM_TABLE)
luaX_syntaxerror(fs->ls, "uninitialized table in local variable");
}
@ -647,10 +713,10 @@ static void ravi_coercetype(LexState *ls, expdesc *v, int n)
* first convert from local register to variable index.
*/
int idx = register_to_locvar_index(ls->fs, i);
ravitype_t ravi_type = ls->fs->f->locvars[idx].ravi_type; /* get variable's type */
uint32_t ravi_type_map = ls->fs->f->locvars[idx].ravi_type_map; /* get variable's type */
TString *usertype = ls->fs->f->locvars[idx].usertype;
/* do we need to convert ? */
ravi_code_typecoersion(ls, i, ravi_type, usertype);
ravi_code_typecoersion(ls, i, ravi_type_map, usertype);
}
}
@ -664,10 +730,10 @@ static void ravi_setzero(FuncState *fs, int from, int n) {
* first convert from local register to variable index.
*/
int idx = register_to_locvar_index(fs, i);
ravitype_t ravi_type = fs->f->locvars[idx].ravi_type; /* get variable's type */
uint32_t ravi_type_map = fs->f->locvars[idx].ravi_type_map; /* get variable's type */
TString *usertype = fs->f->locvars[idx].usertype;
/* do we need to convert ? */
ravi_code_setzero(fs, i, ravi_type, usertype);
ravi_code_setzero(fs, i, ravi_type_map, usertype);
}
}
@ -929,7 +995,7 @@ static void codeclosure (LexState *ls, expdesc *v, int deferred) {
if (deferred) {
pc = luaK_codeABC(fs, OP_RAVI_DEFER, 0, 0, 0);
}
init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np - 1), RAVI_TFUNCTION, NULL);
init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np - 1), RAVI_TM_FUNCTION, NULL);
luaK_exp2nextreg(fs, v); /* fix it at the last register */
if (deferred) {
SETARG_A(fs->f->code[pc], v->u.info);
@ -939,7 +1005,7 @@ static void codeclosure (LexState *ls, expdesc *v, int deferred) {
#else
static void codeclosure (LexState *ls, expdesc *v) {
FuncState *fs = ls->fs->prev;
init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np - 1), RAVI_TFUNCTION, NULL);
init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np - 1), RAVI_TM_FUNCTION, NULL);
luaK_exp2nextreg(fs, v); /* fix it at the last register */
DEBUG_VARS(raviY_printf(ls->fs, "codeclosure -> closure created %e\n", v));
}
@ -1032,7 +1098,7 @@ static void statlist (LexState *ls) {
static void fieldsel (LexState *ls, expdesc *v) {
/* fieldsel -> ['.' | ':'] NAME */
FuncState *fs = ls->fs;
expdesc key = {.ravi_type = RAVI_TANY, .pc = -1};
expdesc key = {.ravi_type_map = RAVI_TM_ANY, .pc = -1};
luaK_exp2anyregup(fs, v);
luaX_next(ls); /* skip the dot or colon */
checkname(ls, &key);
@ -1069,8 +1135,8 @@ static void recfield (LexState *ls, struct ConsControl *cc) {
/* recfield -> (NAME | '['exp1']') = exp1 */
FuncState *fs = ls->fs;
int reg = ls->fs->freereg;
expdesc key = {.ravi_type = RAVI_TANY, .pc = -1},
val = {.ravi_type = RAVI_TANY, .pc = -1};
expdesc key = {.ravi_type_map = RAVI_TM_ANY, .pc = -1},
val = {.ravi_type_map = RAVI_TM_ANY, .pc = -1};
int rkkey;
if (ls->t.token == TK_NAME) {
checklimit(fs, cc->nh, MAX_INT, "items in a constructor");
@ -1153,9 +1219,9 @@ static void constructor (LexState *ls, expdesc *t) {
struct ConsControl cc;
cc.na = cc.nh = cc.tostore = 0;
cc.t = t;
init_exp(t, VRELOCABLE, pc, RAVI_TTABLE, NULL); /* RAVI initial type may be modified */
init_exp(t, VRELOCABLE, pc, RAVI_TM_TABLE, NULL); /* RAVI initial type may be modified */
t->pc = pc; /* RAVI save pc of OP_NEWTABLE instruction so that the correct type can be set later */
init_exp(&cc.v, VVOID, 0, RAVI_TANY, NULL); /* no value (yet) */
init_exp(&cc.v, VVOID, 0, RAVI_TM_ANY, NULL); /* no value (yet) */
luaK_exp2nextreg(ls->fs, t); /* fix it at stack top */
checknext(ls, '{');
do {
@ -1217,7 +1283,7 @@ static ravitype_t declare_localvar(LexState *ls, TString **pusertype) {
/* RAVI change - add type */
TString *name = str_checkname(ls);
/* assume a dynamic type */
ravitype_t tt = RAVI_TANY;
ravitype_t tm = RAVI_TM_ANY;
/* if the variable name is followed by a colon then we have a type
* specifier
*/
@ -1229,36 +1295,36 @@ static ravitype_t declare_localvar(LexState *ls, TString **pusertype) {
* the lexer doesn't need to be changed
*/
if (strcmp(str, "integer") == 0)
tt = RAVI_TNUMINT;
tm = RAVI_TM_INTEGER;
else if (strcmp(str, "number") == 0)
tt = RAVI_TNUMFLT;
tm = RAVI_TM_FLOAT;
else if (strcmp(str, "closure") == 0)
tt = RAVI_TFUNCTION;
tm = RAVI_TM_FUNCTION | RAVI_TM_NIL;
else if (strcmp(str, "table") == 0)
tt = RAVI_TTABLE;
tm = RAVI_TM_TABLE;
else if (strcmp(str, "string") == 0)
tt = RAVI_TSTRING;
tm = RAVI_TM_STRING | RAVI_TM_NIL;
else if (strcmp(str, "boolean") == 0)
tt = RAVI_TBOOLEAN;
tm = RAVI_TM_BOOLEAN | RAVI_TM_NIL;
else if (strcmp(str, "any") == 0)
tt = RAVI_TANY;
tm = RAVI_TM_ANY;
else {
/* default is a userdata type */
tt = RAVI_TUSERDATA;
tm = RAVI_TM_USERDATA | RAVI_TM_NIL;
typename = user_defined_type_name(ls, typename);
str = getstr(typename);
*pusertype = typename;
}
if (tt == RAVI_TNUMFLT || tt == RAVI_TNUMINT) {
if (tm == RAVI_TM_FLOAT || tm == RAVI_TM_INTEGER) {
/* if we see [] then it is an array type */
if (testnext(ls, '[')) {
checknext(ls, ']');
tt = (tt == RAVI_TNUMFLT) ? RAVI_TARRAYFLT : RAVI_TARRAYINT;
tm = (tm == RAVI_TM_FLOAT) ? RAVI_TM_FLOAT_ARRAY : RAVI_TM_INTEGER_ARRAY;
}
}
}
new_localvar(ls, name, tt, *pusertype);
return tt;
new_localvar(ls, name, tm, *pusertype);
return tm;
}
static void parlist (LexState *ls) {
@ -1481,7 +1547,7 @@ static int localvar_explist(LexState *ls, expdesc *v, int *vars, TString** usert
/* parse function arguments */
static void funcargs (LexState *ls, expdesc *f, int line) {
FuncState *fs = ls->fs;
expdesc args = {.ravi_type = RAVI_TANY, .pc = -1};
expdesc args = {.ravi_type_map = RAVI_TM_ANY, .pc = -1};
int base, nparams;
switch (ls->t.token) {
case '(': { /* funcargs -> '(' [ explist ] ')' */
@ -1517,7 +1583,7 @@ static void funcargs (LexState *ls, expdesc *f, int line) {
luaK_exp2nextreg(fs, &args); /* close last argument */
nparams = fs->freereg - (base+1);
}
init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams + 1, 2), RAVI_TANY, NULL); /* RAVI TODO return value from function call not known */
init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams + 1, 2), RAVI_TM_ANY, NULL); /* RAVI TODO return value from function call not known */
luaK_fixline(fs, line);
fs->freereg = base+1; /* call remove function and arguments and leaves
(unless changed) one result */
@ -1568,14 +1634,14 @@ static void suffixedexp (LexState *ls, expdesc *v) {
break;
}
case '[': { /* '[' exp1 ']' */
expdesc key = {.ravi_type = RAVI_TANY, .pc = -1};
expdesc key = {.ravi_type_map = RAVI_TM_ANY, .pc = -1};
luaK_exp2anyregup(fs, v);
yindex(ls, &key);
luaK_indexed(fs, v, &key);
break;
}
case ':': { /* ':' NAME funcargs */
expdesc key = {.ravi_type = RAVI_TANY, .pc = -1};
expdesc key = {.ravi_type_map = RAVI_TM_ANY, .pc = -1};
luaX_next(ls);
checkname(ls, &key);
luaK_self(fs, v, &key);
@ -1598,12 +1664,12 @@ static void simpleexp (LexState *ls, expdesc *v) {
constructor | FUNCTION body | suffixedexp */
switch (ls->t.token) {
case TK_FLT: {
init_exp(v, VKFLT, 0, RAVI_TNUMFLT, NULL);
init_exp(v, VKFLT, 0, RAVI_TM_FLOAT, NULL);
v->u.nval = ls->t.seminfo.r;
break;
}
case TK_INT: {
init_exp(v, VKINT, 0, RAVI_TNUMINT, NULL);
init_exp(v, VKINT, 0, RAVI_TM_INTEGER, NULL);
v->u.ival = ls->t.seminfo.i;
break;
}
@ -1612,22 +1678,22 @@ static void simpleexp (LexState *ls, expdesc *v) {
break;
}
case TK_NIL: {
init_exp(v, VNIL, 0, RAVI_TNIL, NULL);
init_exp(v, VNIL, 0, RAVI_TM_NIL, NULL);
break;
}
case TK_TRUE: {
init_exp(v, VTRUE, 0, RAVI_TANY, NULL); /* RAVI TODO */
init_exp(v, VTRUE, 0, RAVI_TM_TRUE, NULL); /* RAVI TODO */
break;
}
case TK_FALSE: {
init_exp(v, VFALSE, 0, RAVI_TANY, NULL); /* RAVI TODO */
init_exp(v, VFALSE, 0, RAVI_TM_FALSE, NULL); /* RAVI TODO */
break;
}
case TK_DOTS: { /* vararg */
FuncState *fs = ls->fs;
check_condition(ls, fs->f->is_vararg,
"cannot use '...' outside a vararg function");
init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0), RAVI_TANY, NULL);
init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0), RAVI_TM_ANY, NULL);
break;
}
case '{': { /* constructor */
@ -1750,7 +1816,7 @@ static BinOpr subexpr (LexState *ls, expdesc *v, int limit) {
/* expand while operators have priorities higher than 'limit' */
op = getbinopr(ls->t.token);
while (op != OPR_NOBINOPR && priority[op].left > limit) {
expdesc v2 = {.ravi_type = RAVI_TANY, .pc = -1};
expdesc v2 = {.ravi_type_map = RAVI_TM_ANY, .pc = -1};
BinOpr nextop;
int line = ls->linenumber;
luaX_next(ls);
@ -1841,10 +1907,10 @@ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) {
* The final recursive call parses the rhs.
*/
static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
expdesc e = {.ravi_type = RAVI_TANY, .pc = -1};
expdesc e = {.ravi_type_map = RAVI_TM_ANY, .pc = -1};
check_condition(ls, vkisvar(lh->v.k), "syntax error");
if (testnext(ls, ',')) { /* assignment -> ',' suffixedexp assignment */
struct LHS_assign nv = { .v.ravi_type = RAVI_TANY, .v.pc = -1 };
struct LHS_assign nv = { .v.ravi_type_map = RAVI_TM_ANY, .v.pc = -1 };
//nv.v.ravi_type = RAVI_TANY;
//nv.v.pc = -1;
nv.prev = lh;
@ -1871,7 +1937,7 @@ static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
return; /* avoid default */
}
}
init_exp(&e, VNONRELOC, ls->fs->freereg-1, RAVI_TANY, NULL); /* default assignment */
init_exp(&e, VNONRELOC, ls->fs->freereg-1, RAVI_TM_ANY, NULL); /* default assignment */
luaK_storevar(ls->fs, &lh->v, &e);
DEBUG_EXPR(raviY_printf(ls->fs, "assignment lhs = %e, rhs = %e\n", &lh->v, &e));
}
@ -1881,7 +1947,7 @@ static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
*/
static int cond (LexState *ls) {
/* cond -> exp */
expdesc v = {.ravi_type = RAVI_TANY, .pc = -1};
expdesc v = {.ravi_type_map = RAVI_TM_ANY, .pc = -1};
expr(ls, &v); /* read condition */
if (v.k == VNIL) v.k = VFALSE; /* 'falses' are all equal here */
luaK_goiftrue(ls->fs, &v);
@ -1986,7 +2052,7 @@ static void repeatstat (LexState *ls, int line) {
}
typedef struct Fornuminfo {
ravitype_t type;
uint32_t type_map;
int is_constant;
int int_value;
} Fornuminfo;
@ -2000,7 +2066,7 @@ static int exp1 (LexState *ls, Fornuminfo *info) {
* type - also the loop is already optimised so no point trying to
* optimise the iteration variable
*/
expdesc e = {.ravi_type = RAVI_TANY, .pc = -1};
expdesc e = {.ravi_type_map = RAVI_TM_ANY, .pc = -1};
int reg;
int expect_int = 0;
if (ls->t.token == '#')
@ -2012,12 +2078,12 @@ static int exp1 (LexState *ls, Fornuminfo *info) {
luaK_exp2nextreg(ls->fs, &e);
lua_assert(e.k == VNONRELOC);
reg = e.u.info;
if (expect_int && e.ravi_type != RAVI_TNUMINT) {
if (expect_int && e.ravi_type_map != RAVI_TM_INTEGER) {
luaK_codeABC(ls->fs, OP_RAVI_TOINT, reg, 0, 0);
info->type = RAVI_TNUMINT;
info->type_map = RAVI_TM_INTEGER;
}
else {
info->type = e.ravi_type;
info->type_map = e.ravi_type_map;
}
return reg;
}
@ -2072,7 +2138,7 @@ static void fornum (LexState *ls, TString *varname, int line) {
new_localvarliteral(ls, "(for index)");
new_localvarliteral(ls, "(for limit)");
new_localvarliteral(ls, "(for step)");
new_localvar(ls, varname, RAVI_TANY, NULL);
new_localvar(ls, varname, RAVI_TM_ANY, NULL);
/* The fornum sets up its own variables as above.
These are expected to hold numeric values - but from Ravi's
point of view we need to know if the variable is an integer or
@ -2083,7 +2149,7 @@ static void fornum (LexState *ls, TString *varname, int line) {
int var_idx = fs->nlocvars - 4; /* note location of idx variable */
checknext(ls, '=');
/* get the type of each expression */
Fornuminfo tidx = { RAVI_TANY,0,0 }, tlimit = { RAVI_TANY,0,0 }, tstep = { RAVI_TNUMINT,0,0 };
Fornuminfo tidx = { RAVI_TM_ANY,0,0 }, tlimit = { RAVI_TM_ANY,0,0 }, tstep = { RAVI_TM_INTEGER,0,0 };
Fornuminfo *info = NULL;
exp1(ls, &tidx); /* initial value */
checknext(ls, ',');
@ -2096,10 +2162,10 @@ static void fornum (LexState *ls, TString *varname, int line) {
luaK_codek(fs, fs->freereg, luaK_intK(fs, 1));
luaK_reserveregs(fs, 1);
}
if (tidx.type == tlimit.type && tlimit.type == tstep.type &&
(tidx.type == RAVI_TNUMFLT || tidx.type == RAVI_TNUMINT)) {
if (tidx.type_map == tlimit.type_map && tlimit.type_map == tstep.type_map &&
(tidx.type_map == RAVI_TM_FLOAT || tidx.type_map == RAVI_TM_INTEGER)) {
LocVar *vidx, *vlimit, *vstep, *vvar;
if (tidx.type == RAVI_TNUMINT && tstep.is_constant)
if (tidx.type_map == RAVI_TM_INTEGER && tstep.is_constant)
info = &tstep;
/* Note that as locvars may be reallocated while creating variables
therefore we access the variables here */
@ -2108,7 +2174,7 @@ static void fornum (LexState *ls, TString *varname, int line) {
vstep = &fs->f->locvars[var_idx+2]; /* index variable - not yet active so get it from locvars*/
vvar = &fs->f->locvars[var_idx+3]; /* index variable - not yet active so get it from locvars*/
/* Ok so we have an integer or double */
vidx->ravi_type = vlimit->ravi_type = vstep->ravi_type = vvar->ravi_type = tidx.type;
vidx->ravi_type_map = vlimit->ravi_type_map = vstep->ravi_type_map = vvar->ravi_type_map = tidx.type_map;
DEBUG_VARS(raviY_printf(fs, "fornum -> setting type for index %v\n", vidx));
DEBUG_VARS(raviY_printf(fs, "fornum -> setting type for limit %v\n", vlimit));
DEBUG_VARS(raviY_printf(fs, "fornum -> setting type for step %v\n", vstep));
@ -2123,7 +2189,7 @@ static void fornum (LexState *ls, TString *varname, int line) {
static void forlist (LexState *ls, TString *indexname) {
/* forlist -> NAME {,NAME} IN explist forbody */
FuncState *fs = ls->fs;
expdesc e = {.ravi_type = RAVI_TANY, .pc = -1};
expdesc e = {.ravi_type_map = RAVI_TM_ANY, .pc = -1};
int nvars = 4; /* gen, state, control, plus at least one declared var */
int line;
int base = fs->freereg;
@ -2132,9 +2198,9 @@ static void forlist (LexState *ls, TString *indexname) {
new_localvarliteral(ls, "(for state)");
new_localvarliteral(ls, "(for control)");
/* create declared variables */
new_localvar(ls, indexname, RAVI_TANY, NULL); /* RAVI TODO for name:type syntax? */
new_localvar(ls, indexname, RAVI_TM_ANY, NULL); /* RAVI TODO for name:type syntax? */
while (testnext(ls, ',')) {
new_localvar(ls, str_checkname(ls), RAVI_TANY, NULL); /* RAVI change - add type */
new_localvar(ls, str_checkname(ls), RAVI_TM_ANY, NULL); /* RAVI change - add type */
nvars++;
}
checknext(ls, TK_IN);
@ -2169,7 +2235,7 @@ static void test_then_block (LexState *ls, int *escapelist) {
/* test_then_block -> [IF | ELSEIF] cond THEN block */
BlockCnt bl;
FuncState *fs = ls->fs;
expdesc v = {.ravi_type = RAVI_TANY, .pc = -1};
expdesc v = {.ravi_type_map = RAVI_TM_ANY, .pc = -1};
int jf; /* instruction to skip 'then' code (if condition is false) */
luaX_next(ls); /* skip IF or ELSEIF */
expr(ls, &v); /* read condition */
@ -2216,16 +2282,16 @@ static void ifstat (LexState *ls, int line) {
/* parse a local function statement - called from statement() */
#ifdef RAVI_DEFER_STATEMENT
static void localfunc (LexState *ls, int defer) {
expdesc b = {.ravi_type = RAVI_TANY, .pc = -1};
expdesc b = {.ravi_type_map = RAVI_TM_ANY, .pc = -1};
FuncState *fs = ls->fs;
if (defer) {
static const char funcname[] = "(deferred function)";
new_localvar(ls, luaX_newstring(ls, funcname, sizeof funcname-1), RAVI_TFUNCTION, NULL); /* new local variable */
new_localvar(ls, luaX_newstring(ls, funcname, sizeof funcname-1), RAVI_TM_FUNCTION, NULL); /* new local variable */
markupval(fs, fs->nactvar);
fs->bl->insidetbc = 1; /* in the scope of a defer closure variable */
} else {
/* RAVI change - add type */
new_localvar(ls, str_checkname(ls), RAVI_TFUNCTION, NULL); /* new local variable */
new_localvar(ls, str_checkname(ls), RAVI_TM_FUNCTION, NULL); /* new local variable */
}
adjustlocalvars(ls, 1); /* enter its scope */
body(ls, &b, 0, ls->linenumber, defer); /* function created in next register */
@ -2250,7 +2316,7 @@ static void localstat (LexState *ls) {
/* stat -> LOCAL NAME {',' NAME} ['=' explist] */
int nvars = 0;
int nexps;
expdesc e = { .ravi_type = RAVI_TANY,.pc = -1 };
expdesc e = { .ravi_type_map = RAVI_TM_ANY,.pc = -1 };
/* RAVI while declaring locals we need to gather the types
* so that we can check any assignments later on.
* TODO we may be able to use register_typeinfo() here
@ -2298,8 +2364,8 @@ static int funcname (LexState *ls, expdesc *v) {
static void funcstat (LexState *ls, int line) {
/* funcstat -> FUNCTION funcname body */
int ismethod;
expdesc v = {.ravi_type = RAVI_TANY, .pc = -1},
b = {.ravi_type = RAVI_TANY, .pc = -1};
expdesc v = {.ravi_type_map = RAVI_TM_ANY, .pc = -1},
b = {.ravi_type_map = RAVI_TM_ANY, .pc = -1};
luaX_next(ls); /* skip FUNCTION */
ismethod = funcname(ls, &v);
DEBUG_VARS(raviY_printf(ls->fs, "funcstat -> declaring function %e\n", &v));
@ -2317,7 +2383,7 @@ static void exprstat (LexState *ls) {
/* stat -> func | assignment */
FuncState *fs = ls->fs;
struct LHS_assign v;
v.v.ravi_type = RAVI_TANY;
v.v.ravi_type_map = RAVI_TM_ANY;
suffixedexp(ls, &v.v);
if (ls->t.token == '=' || ls->t.token == ',') { /* stat -> assignment ? */
v.prev = NULL;
@ -2333,7 +2399,7 @@ static void exprstat (LexState *ls) {
static void retstat (LexState *ls) {
/* stat -> RETURN [explist] [';'] */
FuncState *fs = ls->fs;
expdesc e = {.ravi_type = RAVI_TANY, .pc = -1};
expdesc e = {.ravi_type_map = RAVI_TM_ANY, .pc = -1};
int first, nret; /* registers with returned values */
if (block_follow(ls, 1) || ls->t.token == ';')
first = nret = 0; /* return no values */
@ -2451,10 +2517,10 @@ static void statement (LexState *ls) {
*/
static void mainfunc (LexState *ls, FuncState *fs) {
BlockCnt bl;
expdesc v = {.ravi_type = RAVI_TANY, .pc = -1};
expdesc v = {.ravi_type_map = RAVI_TM_ANY, .pc = -1};
open_func(ls, fs, &bl);
fs->f->is_vararg = 1; /* main function is always declared vararg */
init_exp(&v, VLOCAL, 0, RAVI_TANY, NULL); /* create and... - RAVI TODO var arg is unknown type */
init_exp(&v, VLOCAL, 0, RAVI_TM_ANY, NULL); /* create and... - RAVI TODO var arg is unknown type */
newupvalue(fs, ls->envn, &v); /* ...set environment upvalue */
luaC_objbarrier(ls->L, fs->f, ls->envn);
luaX_next(ls); /* read first token */

@ -66,13 +66,15 @@ typedef struct expdesc {
short idx; /* index (R/K) */
lu_byte t; /* table (register or upvalue) */
lu_byte vt; /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */
lu_byte key_ravi_type; /* RAVI change: key type */
uint32_t key_ravi_type_map; /* Map of possible types the key could have */
// lu_byte key_ravi_type; /* RAVI change: key type */
TString *usertype; /* RAVI change: usertype name */
} ind;
} u;
int t; /* patch list of 'exit when true' */
int f; /* patch list of 'exit when false' */
lu_byte ravi_type; /* RAVI change: type of the expression if known, else RAVI_TANY */
uint32_t ravi_type_map; /* Map of possible types this expression could have */
// lu_byte ravi_type; /* RAVI change: type of the expression if known, else RAVI_TANY */
TString *usertype; /* RAVI change: usertype name */
int pc; /* RAVI change: holds the program counter for OP_NEWTABLE instruction when a constructor expression is parsed */
} expdesc;

Loading…
Cancel
Save