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

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

@ -66,13 +66,15 @@ typedef struct expdesc {
short idx; /* index (R/K) */ short idx; /* index (R/K) */
lu_byte t; /* table (register or upvalue) */ lu_byte t; /* table (register or upvalue) */
lu_byte vt; /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */ 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 */ TString *usertype; /* RAVI change: usertype name */
} ind; } ind;
} u; } u;
int t; /* patch list of 'exit when true' */ int t; /* patch list of 'exit when true' */
int f; /* patch list of 'exit when false' */ 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 */ TString *usertype; /* RAVI change: usertype name */
int pc; /* RAVI change: holds the program counter for OP_NEWTABLE instruction when a constructor expression is parsed */ int pc; /* RAVI change: holds the program counter for OP_NEWTABLE instruction when a constructor expression is parsed */
} expdesc; } expdesc;

Loading…
Cancel
Save