Merge pull request #213 from XmiliaH/type-maps

Change ravi_type to a Bitmap
pull/218/head
Dibyendu Majumdar 3 years ago committed by GitHub
commit 347ae985bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1568,8 +1568,8 @@ LUA_API void *lua_newuserdata (lua_State *L, size_t size) {
static const char *aux_upvalue (StkId fi, int n, TValue **val, static const char *aux_upvalue (StkId fi, int n, TValue **val,
CClosure **owner, UpVal **uv, ravitype_t *type, TString **usertype) { CClosure **owner, UpVal **uv, ravi_type_map *type, TString **usertype) {
*type = RAVI_TANY; *type = RAVI_TM_ANY;
*usertype = NULL; *usertype = NULL;
switch (ttype(fi)) { switch (ttype(fi)) {
case LUA_TCCL: { /* C closure */ case LUA_TCCL: { /* C closure */
@ -1587,7 +1587,7 @@ static const char *aux_upvalue (StkId fi, int n, TValue **val,
*val = f->upvals[n-1]->v; *val = f->upvals[n-1]->v;
if (uv) *uv = f->upvals[n - 1]; if (uv) *uv = f->upvals[n - 1];
name = p->upvalues[n-1].name; name = p->upvalues[n-1].name;
*type = p->upvalues[n - 1].ravi_type; *type = p->upvalues[n - 1].ravi_type_map;
*usertype = p->upvalues[n - 1].usertype; *usertype = p->upvalues[n - 1].usertype;
return (name == NULL) ? "(*no name)" : getstr(name); return (name == NULL) ? "(*no name)" : getstr(name);
} }
@ -1598,7 +1598,7 @@ static const char *aux_upvalue (StkId fi, int n, TValue **val,
LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) {
const char *name; const char *name;
ravitype_t type; ravi_type_map type;
TString *usertype; TString *usertype;
TValue *val = NULL; /* to avoid warnings */ TValue *val = NULL; /* to avoid warnings */
lua_lock(L); lua_lock(L);
@ -1611,14 +1611,13 @@ LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) {
return name; return name;
} }
LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {
const char *name; const char *name;
TValue *val = NULL; /* to avoid warnings */ TValue *val = NULL; /* to avoid warnings */
CClosure *owner = NULL; CClosure *owner = NULL;
UpVal *uv = NULL; UpVal *uv = NULL;
StkId fi; StkId fi;
ravitype_t type; /* RAVI upvalue type will be obtained if possible */ ravi_type_map type; /* RAVI upvalue type will be obtained if possible */
TString *usertype; TString *usertype;
lua_lock(L); lua_lock(L);
fi = index2addr(L, funcindex); fi = index2addr(L, funcindex);
@ -1647,13 +1646,13 @@ LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {
} }
static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf, ravitype_t *type) { static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf, ravi_type_map *type) {
LClosure *f; LClosure *f;
StkId fi = index2addr(L, fidx); StkId fi = index2addr(L, fidx);
api_check(L, ttisLclosure(fi), "Lua function expected"); api_check(L, ttisLclosure(fi), "Lua function expected");
f = clLvalue(fi); f = clLvalue(fi);
api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index"); api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index");
if (type) *type = f->p->upvalues[n - 1].ravi_type; if (type) *type = f->p->upvalues[n - 1].ravi_type_map;
if (pf) *pf = f; if (pf) *pf = f;
return &f->upvals[n - 1]; /* get its upvalue pointer */ return &f->upvals[n - 1]; /* get its upvalue pointer */
} }
@ -1681,7 +1680,7 @@ LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) {
LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1, LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1,
int fidx2, int n2) { int fidx2, int n2) {
LClosure *f1; LClosure *f1;
ravitype_t t1, t2; ravi_type_map t1, t2;
UpVal **up1 = getupvalref(L, fidx1, n1, &f1, &t1); UpVal **up1 = getupvalref(L, fidx1, n1, &f1, &t1);
UpVal **up2 = getupvalref(L, fidx2, n2, NULL, &t2); UpVal **up2 = getupvalref(L, fidx2, n2, NULL, &t2);
if (t1 == t2 && *up1 != *up2) { if (t1 == t2 && *up1 != *up2) {

@ -600,34 +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->u.ind.key_ravi_type == RAVI_TNUMINT) { if (e->u.ind.key_ravi_type_map == RAVI_TM_INTEGER) {
if (e->ravi_type == RAVI_TARRAYFLT) if (e->ravi_type_map == RAVI_TM_FLOAT_ARRAY) {
op = OP_RAVI_FARRAY_GET; op = OP_RAVI_FARRAY_GET;
else if (e->ravi_type == RAVI_TARRAYINT) } else if (e->ravi_type_map == RAVI_TM_INTEGER_ARRAY) {
op = OP_RAVI_IARRAY_GET; op = OP_RAVI_IARRAY_GET;
else } else {
op = OP_RAVI_GETI; op = OP_RAVI_GETI;
} }
/* Check that we have a short string constant */ } 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 = e->ravi_type == RAVI_TTABLE ? OP_RAVI_TABLE_GETFIELD : 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) ravi_type_map 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));
@ -682,28 +683,28 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
TString *usertype = NULL; TString *usertype = NULL;
int ravi_type = raviY_get_register_typeinfo(fs, reg, &usertype); int ravi_type = raviY_get_register_typeinfo(fs, reg, &usertype);
switch (ravi_type) { switch (ravi_type) {
case RAVI_TNUMINT: case RAVI_TM_INTEGER:
luaK_codeABC(fs, OP_RAVI_MOVEI, reg, e->u.info, 0); luaK_codeABC(fs, OP_RAVI_MOVEI, reg, e->u.info, 0);
break; break;
case RAVI_TNUMFLT: case RAVI_TM_FLOAT:
luaK_codeABC(fs, OP_RAVI_MOVEF, reg, e->u.info, 0); luaK_codeABC(fs, OP_RAVI_MOVEF, reg, e->u.info, 0);
break; break;
case RAVI_TARRAYINT: case RAVI_TM_INTEGER_ARRAY:
luaK_codeABC(fs, OP_RAVI_MOVEIARRAY, reg, e->u.info, 0); luaK_codeABC(fs, OP_RAVI_MOVEIARRAY, reg, e->u.info, 0);
break; break;
case RAVI_TARRAYFLT: case RAVI_TM_FLOAT_ARRAY:
luaK_codeABC(fs, OP_RAVI_MOVEFARRAY, reg, e->u.info, 0); luaK_codeABC(fs, OP_RAVI_MOVEFARRAY, reg, e->u.info, 0);
break; break;
case RAVI_TTABLE: case RAVI_TM_TABLE:
luaK_codeABC(fs, OP_RAVI_MOVETAB, reg, e->u.info, 0); luaK_codeABC(fs, OP_RAVI_MOVETAB, reg, e->u.info, 0);
break; break;
default: default:
luaK_codeABC(fs, OP_MOVE, reg, e->u.info, 0); luaK_codeABC(fs, OP_MOVE, reg, e->u.info, 0);
if (ravi_type == RAVI_TSTRING) if (ravi_type == (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 (ravi_type == RAVI_TFUNCTION) else if (ravi_type == (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 (ravi_type == RAVI_TUSERDATA && usertype) else if (ravi_type == (RAVI_TM_USERDATA | RAVI_TM_NIL) && usertype)
luaK_codeABx(fs, OP_RAVI_TOTYPE, reg, luaK_stringK(fs, usertype)); luaK_codeABx(fs, OP_RAVI_TOTYPE, reg, luaK_stringK(fs, usertype));
break; break;
} }
@ -863,31 +864,29 @@ 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) {
/* 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;
} }
ravitype_t ex_ravi_type = ex->ravi_type; ravi_type_map ex_ravi_type_map = ex->ravi_type_map;
if (ex->k == VINDEXED) { if (ex->k == VINDEXED) {
if (ex_ravi_type == RAVI_TARRAYINT) { if (ex_ravi_type_map == RAVI_TM_INTEGER_ARRAY) {
ex_ravi_type = RAVI_TNUMINT; ex_ravi_type_map = RAVI_TM_INTEGER;
} } else if (ex_ravi_type_map == RAVI_TM_FLOAT_ARRAY) {
else if (ex_ravi_type == RAVI_TARRAYFLT) { ex_ravi_type_map = RAVI_TM_FLOAT;
ex_ravi_type = RAVI_TNUMFLT; } else {
} ex_ravi_type_map = RAVI_TM_ANY;
else {
ex_ravi_type = RAVI_TANY;
} }
} }
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; return;
luaX_syntaxerror( luaX_syntaxerror(
fs->ls, fs->ls,
@ -895,8 +894,8 @@ 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; return;
luaX_syntaxerror( luaX_syntaxerror(
fs->ls, fs->ls,
@ -904,20 +903,18 @@ static void check_valid_store(FuncState *fs, expdesc *var, expdesc *ex) {
fs->ls->L, fs->ls->L,
"Invalid assignment: integer expected")); "Invalid assignment: integer expected"));
} }
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)
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 == RAVI_TSTRING) if ((ex_ravi_type_map & ~(RAVI_TM_STRING | RAVI_TM_NIL)) == 0)
return; return;
luaX_syntaxerror( luaX_syntaxerror(
fs->ls, fs->ls,
@ -925,8 +922,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 == RAVI_TFUNCTION) if ((ex_ravi_type_map & ~(RAVI_TM_FUNCTION | RAVI_TM_NIL)) == 0)
return; return;
luaX_syntaxerror( luaX_syntaxerror(
fs->ls, fs->ls,
@ -934,9 +931,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 == RAVI_TUSERDATA && var->usertype && var->usertype == ex->usertype)) (!(ex_ravi_type_map & RAVI_TM_USERDATA) || (var->usertype && var->usertype == ex->usertype)))
return; return;
luaX_syntaxerror( luaX_syntaxerror(
fs->ls, fs->ls,
@ -949,36 +946,42 @@ 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) {
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));
} }
else else {
char var_type_map_str[RAVI_TYPEMAP_MAX_LEN];
char ex_type_map_str[RAVI_TYPEMAP_MAX_LEN];
raviY_typemap_string(var->ravi_type_map, var_type_map_str);
raviY_typemap_string(ex->ravi_type_map, ex_type_map_str);
luaX_syntaxerror(fs->ls, luaO_pushfstring(fs->ls->L, luaX_syntaxerror(fs->ls, luaO_pushfstring(fs->ls->L,
"Invalid assignment of " "Invalid assignment of "
"upvalue: upvalue type " "upvalue: upvalue type "
"%s, expression type %s", "%s, expression type %s",
raviY_typename(var->ravi_type), var_type_map_str,
raviY_typename(ex->ravi_type))); ex_type_map_str));
}
} }
return op; return op;
} }
@ -1003,29 +1006,20 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {
int e = luaK_exp2RK(fs, ex); int e = luaK_exp2RK(fs, ex);
if (var->u.ind.vt == VLOCAL) { 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->u.ind.key_ravi_type == RAVI_TNUMINT) { if (var->u.ind.key_ravi_type_map == RAVI_TM_INTEGER) {
if (var->ravi_type == RAVI_TARRAYFLT) { if (var->ravi_type_map == RAVI_TM_FLOAT_ARRAY) {
op = ex->ravi_type == RAVI_TNUMFLT ? OP_RAVI_FARRAY_SETF : /* input value is known to be number */ op = ex->ravi_type_map == RAVI_TM_FLOAT ? OP_RAVI_FARRAY_SETF : OP_RAVI_FARRAY_SET;
OP_RAVI_FARRAY_SET; /* input value may need conversion */ } 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 if (var->ravi_type == RAVI_TARRAYINT) { } else {
op = ex->ravi_type == RAVI_TNUMINT ? OP_RAVI_IARRAY_SETI : /* input value is known to be integer */
OP_RAVI_IARRAY_SET; /* input value may need conversion */
}
else {
/* index op with integer key, target may not be a table */
op = OP_RAVI_SETI; op = OP_RAVI_SETI;
} }
} } else if (var->u.ind.key_ravi_type_map == RAVI_TM_STRING && isshortstr(fs, var->u.ind.idx)) {
else if (var->u.ind.key_ravi_type == RAVI_TSTRING && isshortstr(fs, var->u.ind.idx)) { op = var->ravi_type_map == RAVI_TM_TABLE ? OP_RAVI_TABLE_SETFIELD : OP_RAVI_SETFIELD;
op = var->ravi_type == RAVI_TTABLE ? OP_RAVI_TABLE_SETFIELD : /* table with string key */ } else {
OP_RAVI_SETFIELD; /* index op with string key, target may not be a table */
}
else {
op = OP_SETTABLE; op = OP_SETTABLE;
} }
} } else {
else {
op = OP_SETTABUP; op = OP_SETTABUP;
} }
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);
@ -1050,13 +1044,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);
@ -1120,7 +1114,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 {
@ -1151,11 +1145,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;
} }
@ -1194,7 +1188,8 @@ static void codenot (FuncState *fs, expdesc *e) {
} }
default: lua_assert(0); /* cannot happen */ default: lua_assert(0); /* cannot happen */
} }
e->ravi_type = RAVI_TBOOLEAN; e->ravi_type_map = ((e->ravi_type_map & RAVI_TM_TRUISH) ? RAVI_TM_FALSE : 0) |
((e->ravi_type_map & RAVI_TM_FALSISH) ? RAVI_TM_TRUE : 0);
/* 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 */
@ -1209,7 +1204,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;
@ -1249,7 +1244,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);
@ -1257,7 +1252,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;
} }
@ -1273,42 +1268,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) { 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);
@ -1334,61 +1328,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 | ii; \
} \
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);
@ -1396,17 +1397,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_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_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 */
@ -1414,23 +1415,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, ravi_type_map o1_tm, ravi_type_map 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;
@ -1444,32 +1445,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; ravi_type_map 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; ravi_type_map 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;
} }
@ -1484,21 +1485,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;
@ -1507,56 +1508,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; ravi_type_map 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 | RAVI_TM_NIL))) != 0) {
opcode = OP_RAVI_TOSTRING; opcode = OP_RAVI_TOSTRING;
tt = RAVI_TSTRING; tm = RAVI_TM_STRING | RAVI_TM_NIL;
} }
else if (op == OPR_TO_CLOSURE && e->ravi_type != RAVI_TFUNCTION) { else if (op == OPR_TO_CLOSURE && (e->ravi_type_map & (~(RAVI_TM_FUNCTION | RAVI_TM_NIL))) != 0) {
opcode = OP_RAVI_TOCLOSURE; opcode = OP_RAVI_TOCLOSURE;
tt = RAVI_TFUNCTION; tm = RAVI_TM_FUNCTION | RAVI_TM_NIL;
} }
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 | RAVI_TM_NIL;
} }
else { else {
/* nothing to do*/ /* nothing to do*/
@ -1568,7 +1569,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;
@ -1583,7 +1584,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,
@ -1657,18 +1658,10 @@ 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) { if (e1->ravi_type_map & RAVI_TM_TRUISH) {
/* nil and something is still nil. */ e2->ravi_type_map |= e1->ravi_type_map & RAVI_TM_FALSISH;
e2->ravi_type = RAVI_TNIL; } else {
} e2->ravi_type_map = e1->ravi_type_map & RAVI_TM_FALSISH;
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;
@ -1677,18 +1670,14 @@ 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) { if (e1->ravi_type_map & RAVI_TM_FALSISH) {
/* In these cases the 'or' can go both ways. */ e2->ravi_type_map |= e1->ravi_type_map & RAVI_TM_TRUISH;
if (e2->ravi_type != e1->ravi_type) } else {
e2->ravi_type = RAVI_TANY; e2->ravi_type_map = e1->ravi_type_map & RAVI_TM_TRUISH;
}
else {
/* In this case the first argument is truish and will be the return from 'or' */
e2->ravi_type = e1->ravi_type;
} }
*e1 = *e2; *e1 = *e2;
break; break;
@ -1702,7 +1691,13 @@ void luaK_posfix (FuncState *fs, BinOpr op,
SETARG_B(getinstruction(fs, e2), e1->u.info); SETARG_B(getinstruction(fs, e2), e1->u.info);
DEBUG_CODEGEN(raviY_printf(fs, "[%d]* %o ; set A to %d\n", e2->u.info, getinstruction(fs,e2), e1->u.info)); DEBUG_CODEGEN(raviY_printf(fs, "[%d]* %o ; set A to %d\n", e2->u.info, getinstruction(fs,e2), e1->u.info));
e1->k = VRELOCABLE; e1->u.info = e2->u.info; e1->k = VRELOCABLE; e1->u.info = e2->u.info;
e1->ravi_type = RAVI_TANY; 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_map = RAVI_TM_ANY;
}
} }
else { else {
luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */

@ -147,10 +147,10 @@ static const char *findvararg (CallInfo *ci, int n, StkId *pos) {
static const char *findlocal (lua_State *L, CallInfo *ci, int n, static const char *findlocal (lua_State *L, CallInfo *ci, int n,
StkId *pos, ravitype_t *type, TString** usertype) { StkId *pos, ravi_type_map *type, TString** usertype) {
const char *name = NULL; const char *name = NULL;
StkId base; StkId base;
*type = RAVI_TANY; *type = RAVI_TM_ANY;
*usertype = NULL; *usertype = NULL;
if (isLua(ci)) { if (isLua(ci)) {
if (n < 0) /* access to vararg values? */ if (n < 0) /* access to vararg values? */
@ -176,7 +176,7 @@ static const char *findlocal (lua_State *L, CallInfo *ci, int n,
LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {
const char *name; const char *name;
ravitype_t type; ravi_type_map type;
TString *usertype; TString *usertype;
lua_lock(L); lua_lock(L);
swapextra(L); swapextra(L);
@ -203,7 +203,7 @@ LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {
LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
StkId pos = NULL; /* to avoid warnings */ StkId pos = NULL; /* to avoid warnings */
const char *name; const char *name;
ravitype_t type; ravi_type_map type;
TString* usertype; TString* usertype;
int compatible = 1; int compatible = 1;
lua_lock(L); lua_lock(L);
@ -215,7 +215,7 @@ LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
** not subvert the types of local variables ** not subvert the types of local variables
*/ */
StkId input = L->top - 1; StkId input = L->top - 1;
int compatible = raviV_checktype(L, input, type, usertype); int compatible = ravi_checktype(L, input, type, usertype);
if (compatible) { if (compatible) {
setobjs2s(L, pos, L->top - 1); setobjs2s(L, pos, L->top - 1);
L->top--; /* pop value */ L->top--; /* pop value */
@ -452,7 +452,7 @@ static int findsetreg (Proto *p, int lastpc, int reg) {
static const char *getobjname (Proto *p, int lastpc, int reg, static const char *getobjname (Proto *p, int lastpc, int reg,
const char **name) { const char **name) {
int pc; int pc;
ravitype_t type; ravi_type_map type;
TString *usertype; TString *usertype;
*name = luaF_getlocalname(p, reg + 1, lastpc, &type, &usertype); *name = luaF_getlocalname(p, reg + 1, lastpc, &type, &usertype);
if (*name) /* is a local? */ if (*name) /* is a local? */

@ -150,6 +150,22 @@ static void DumpUpvalues (const Proto *f, DumpState *D) {
} }
} }
static lu_byte ravi_type_map_to_old_type(ravi_type_map type_map) {
switch (type_map) {
case RAVI_TM_ANY: return 0;
case RAVI_TM_INTEGER: return 1;
case RAVI_TM_FLOAT: return 2;
case RAVI_TM_INTEGER_ARRAY: return 3;
case RAVI_TM_FLOAT_ARRAY: return 4;
case RAVI_TM_FUNCTION | RAVI_TM_NIL: return 5;
case RAVI_TM_TABLE: return 6;
case RAVI_TM_STRING | RAVI_TM_NIL: return 7;
case RAVI_TM_NIL: return 8;
case RAVI_TM_BOOLEAN | RAVI_TM_NIL: return 9;
case RAVI_TM_USERDATA | RAVI_TM_NIL: return 10;
default: return 0;
}
}
static void DumpDebug (const Proto *f, DumpState *D) { static void DumpDebug (const Proto *f, DumpState *D) {
int i, n; int i, n;
@ -163,7 +179,7 @@ static void DumpDebug (const Proto *f, DumpState *D) {
DumpString((D->strip) ? NULL : f->locvars[i].varname, D); DumpString((D->strip) ? NULL : f->locvars[i].varname, D);
DumpInt(f->locvars[i].startpc, D); DumpInt(f->locvars[i].startpc, D);
DumpInt(f->locvars[i].endpc, D); DumpInt(f->locvars[i].endpc, D);
DumpByte(f->locvars[i].ravi_type, D); DumpByte(ravi_type_map_to_old_type(f->locvars[i].ravi_type_map), D);
DumpString(f->locvars[i].usertype, D); DumpString(f->locvars[i].usertype, D);
} }
/* n = (D->strip) ? 0 : f->sizeupvalues; */ /* n = (D->strip) ? 0 : f->sizeupvalues; */
@ -171,7 +187,7 @@ static void DumpDebug (const Proto *f, DumpState *D) {
DumpInt(n, D); DumpInt(n, D);
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
DumpString((D->strip) ? NULL : f->upvalues[i].name, D); DumpString((D->strip) ? NULL : f->upvalues[i].name, D);
DumpByte(f->upvalues[i].ravi_type, D); DumpByte(ravi_type_map_to_old_type(f->upvalues[i].ravi_type_map), D);
DumpString(f->upvalues[i].usertype, D); DumpString(f->upvalues[i].usertype, D);
} }
} }

@ -243,7 +243,7 @@ void luaF_freeproto (lua_State *L, Proto *f) {
** Returns NULL if not found. ** Returns NULL if not found.
** RAVI extension - also return the known type if any ** RAVI extension - also return the known type if any
*/ */
const char *luaF_getlocalname (const Proto *f, int local_number, int pc, ravitype_t *type, TString **usertype) { const char *luaF_getlocalname (const Proto *f, int local_number, int pc, ravi_type_map *type, TString **usertype) {
int i; int i;
for (i = 0; i<f->sizelocvars && f->locvars[i].startpc <= pc; i++) { for (i = 0; i<f->sizelocvars && f->locvars[i].startpc <= pc; i++) {
if (pc < f->locvars[i].endpc) { /* is variable active? */ if (pc < f->locvars[i].endpc) { /* is variable active? */
@ -251,13 +251,13 @@ const char *luaF_getlocalname (const Proto *f, int local_number, int pc, ravityp
if (local_number == 0) { if (local_number == 0) {
if (f->locvars[i].varname == NULL) if (f->locvars[i].varname == NULL)
break; break;
*type = f->locvars[i].ravi_type; *type = f->locvars[i].ravi_type_map;
*usertype = f->locvars[i].usertype; *usertype = f->locvars[i].usertype;
return getstr(f->locvars[i].varname); return getstr(f->locvars[i].varname);
} }
} }
} }
*type = RAVI_TANY; *type = RAVI_TM_ANY;
*usertype = NULL; *usertype = NULL;
return NULL; /* not found */ return NULL; /* not found */
} }

@ -57,7 +57,7 @@ LUAI_FUNC void luaF_close (lua_State *L, StkId level);
LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f);
/* The additional type argument is a Ravi extension */ /* The additional type argument is a Ravi extension */
LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number,
int pc, ravitype_t* type, TString **usertype); int pc, ravi_type_map* type, TString **usertype);
#endif #endif

@ -33,6 +33,24 @@
LUAI_DDEF const TValue luaO_nilobject_ = {NILCONSTANT}; LUAI_DDEF const TValue luaO_nilobject_ = {NILCONSTANT};
int ravi_checktype(lua_State *L, StkId input, ravi_type_map type, TString* usertype) {
if (type == RAVI_TM_ANY) return 1;
if (type & RAVI_TM_NIL && ttisnil(input)) return 1;
if (type & RAVI_TM_FALSE && ttisboolean(input) && l_isfalse(input)) return 1;
if (type & RAVI_TM_TRUE && ttisboolean(input) && !l_isfalse(input)) return 1;
if (type & RAVI_TM_INTEGER && ttisinteger(input)) return 1;
if (type & RAVI_TM_FLOAT && ttisfloat(input)) return 1;
if (type & RAVI_TM_INTEGER_ARRAY && ttisiarray(input)) return 1;
if (type & RAVI_TM_FLOAT_ARRAY && ttisfarray(input)) return 1;
if (type & RAVI_TM_TABLE && ttisLtable(input)) return 1;
if (type & RAVI_TM_STRING && ttisstring(input)) return 1;
if (type & RAVI_TM_FUNCTION && ttisclosure(input)) return 1;
if (type & RAVI_TM_USERDATA) {
if (raviV_check_usertype(L, usertype, input)) return 1;
}
return 0;
}
/* /*
** converts an integer to a "floating point byte", represented as ** converts an integer to a "floating point byte", represented as
** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if ** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if

@ -54,19 +54,43 @@ typedef uint16_t LuaType;
** we care about from a performance point of view - if any ** we care about from a performance point of view - if any
** other types appear then they are all treated as ANY ** other types appear then they are all treated as ANY
**/ **/
typedef enum { typedef enum {
RAVI_TANY = 0, /* Lua dynamic type */ RAVI_TI_NIL,
RAVI_TNUMINT = 1, /* integer number */ RAVI_TI_FALSE,
RAVI_TNUMFLT, /* floating point number */ RAVI_TI_TRUE,
RAVI_TARRAYINT, /* array of ints */ RAVI_TI_INTEGER,
RAVI_TARRAYFLT, /* array of doubles */ RAVI_TI_FLOAT,
RAVI_TFUNCTION, /* Lua or C Function */ RAVI_TI_INTEGER_ARRAY,
RAVI_TTABLE, /* Lua table */ RAVI_TI_FLOAT_ARRAY,
RAVI_TSTRING, /* string */ RAVI_TI_TABLE,
RAVI_TNIL, /* NIL */ RAVI_TI_STRING,
RAVI_TBOOLEAN, /* boolean */ RAVI_TI_FUNCTION,
RAVI_TUSERDATA /* userdata or lightuserdata */ RAVI_TI_USERDATA,
} ravitype_t; RAVI_TI_OTHER
} ravi_type_index;
typedef uint32_t ravi_type_map;
#define RAVI_TM_NIL (((ravi_type_map)1)<<RAVI_TI_NIL)
#define RAVI_TM_FALSE (((ravi_type_map)1)<<RAVI_TI_FALSE)
#define RAVI_TM_TRUE (((ravi_type_map)1)<<RAVI_TI_TRUE)
#define RAVI_TM_INTEGER (((ravi_type_map)1)<<RAVI_TI_INTEGER)
#define RAVI_TM_FLOAT (((ravi_type_map)1)<<RAVI_TI_FLOAT)
#define RAVI_TM_INTEGER_ARRAY (((ravi_type_map)1)<<RAVI_TI_INTEGER_ARRAY)
#define RAVI_TM_FLOAT_ARRAY (((ravi_type_map)1)<<RAVI_TI_FLOAT_ARRAY)
#define RAVI_TM_TABLE (((ravi_type_map)1)<<RAVI_TI_TABLE)
#define RAVI_TM_STRING (((ravi_type_map)1)<<RAVI_TI_STRING)
#define RAVI_TM_FUNCTION (((ravi_type_map)1)<<RAVI_TI_FUNCTION)
#define RAVI_TM_USERDATA (((ravi_type_map)1)<<RAVI_TI_USERDATA)
#define RAVI_TM_OTHER (((ravi_type_map)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,
@ -432,7 +456,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 */ ravi_type_map 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 +471,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 */ ravi_type_map ravi_type_map; /* RAVI type of the variable - RAVI_TANY if unknown */
} LocVar; } LocVar;
/** RAVI changes start */ /** RAVI changes start */
@ -835,5 +859,8 @@ LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);
LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t srclen); LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t srclen);
LUAI_FUNC int ravi_checktype(lua_State *L, StkId input, ravi_type_map type, TString* usertype);
#endif #endif

File diff suppressed because it is too large Load Diff

@ -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 */ ravi_type_map 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 */ ravi_type_map 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;
@ -241,7 +243,9 @@ LUAI_FUNC LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
Dyndata *dyd, const char *name, int firstchar); Dyndata *dyd, const char *name, int firstchar);
/** RAVI extensions **/ /** RAVI extensions **/
LUAI_FUNC const char *raviY_typename(ravitype_t tt); #define RAVI_TYPEMAP_MAX_LEN (sizeof("nil|boolean|integer|number|integer[]|number[]|table|string|function|userdata|?|"))
LUAI_FUNC void raviY_typemap_string(ravi_type_map tm, char* buf);
/* Special printf that recognises following conversions: /* Special printf that recognises following conversions:
* %e - expdesc * * %e - expdesc *
@ -259,7 +263,7 @@ LUAI_FUNC void raviY_printf(FuncState *fs, const char *format, ...);
* Else RAVI_TANY is returned. Note that this function only looks * Else RAVI_TANY is returned. Note that this function only looks
* at active local variables - see note on FuncState on what this means. * at active local variables - see note on FuncState on what this means.
*/ */
LUAI_FUNC ravitype_t raviY_get_register_typeinfo(FuncState *fs, int reg, TString **); LUAI_FUNC ravi_type_map raviY_get_register_typeinfo(FuncState *fs, int reg, TString **);
#define DEBUG_EXPR(p) \ #define DEBUG_EXPR(p) \
if ((ravi_parser_debug & 1) != 0) { \ if ((ravi_parser_debug & 1) != 0) { \

@ -503,19 +503,19 @@ Table *luaH_new (lua_State *L) {
return t; return t;
} }
RaviArray *raviH_new(lua_State *L, ravitype_t tt, int is_slice) { RaviArray *raviH_new(lua_State *L, ravi_type_map tm, int is_slice) {
lua_assert(tt == RAVI_TARRAYFLT || tt == RAVI_TARRAYINT); lua_assert(tm == RAVI_TM_FLOAT_ARRAY || tm == RAVI_TM_INTEGER_ARRAY);
GCObject *o = luaC_newobj(L, tt == RAVI_TARRAYFLT ? RAVI_TFARRAY : RAVI_TIARRAY, sizeof(RaviArray)); GCObject *o = luaC_newobj(L, tm == RAVI_TM_FLOAT_ARRAY ? RAVI_TFARRAY : RAVI_TIARRAY, sizeof(RaviArray));
RaviArray *t = gco2array(o); RaviArray *t = gco2array(o);
t->len = 0; t->len = 0;
t->size = RAVI_ARRAY_MAX_INLINE; /* Initially we use inline storage */ t->size = RAVI_ARRAY_MAX_INLINE; /* Initially we use inline storage */
t->flags = (tt == RAVI_TARRAYFLT) ? RAVI_ARRAY_ISFLOAT : 0; t->flags = (tm == RAVI_TM_FLOAT_ARRAY) ? RAVI_ARRAY_ISFLOAT : 0;
t->data = (tt == RAVI_TARRAYFLT) ? (char *) &t->numarray : (char *) &t->intarray; /* data */ t->data = (tm == RAVI_TM_FLOAT_ARRAY) ? (char *) &t->numarray : (char *) &t->intarray; /* data */
t->parent = NULL; t->parent = NULL;
t->metatable = NULL; t->metatable = NULL;
if (!is_slice) { if (!is_slice) {
/* Note following will set len to 1 */ /* Note following will set len to 1 */
if (tt == RAVI_TARRAYFLT) { if (tm == RAVI_TM_FLOAT_ARRAY) {
raviH_set_float_inline(L, t, 0, 0.0); raviH_set_float_inline(L, t, 0, 0.0);
} }
else { else {
@ -904,7 +904,7 @@ void raviH_set_float(lua_State *L, RaviArray *t, lua_Unsigned u1, lua_Number val
RaviArray *raviH_new_integer_array(lua_State *L, unsigned int len, RaviArray *raviH_new_integer_array(lua_State *L, unsigned int len,
lua_Integer init_value) { lua_Integer init_value) {
RaviArray *t = raviH_new(L, RAVI_TARRAYINT, 0); RaviArray *t = raviH_new(L, RAVI_TM_INTEGER_ARRAY, 0);
unsigned int new_len = len + 1; // Ravi arrays have an extra slot at offset 0 unsigned int new_len = len + 1; // Ravi arrays have an extra slot at offset 0
if (new_len < len) { // Wrapped? if (new_len < len) { // Wrapped?
luaG_runerror(L, "array length out of range"); luaG_runerror(L, "array length out of range");
@ -924,7 +924,7 @@ RaviArray *raviH_new_integer_array(lua_State *L, unsigned int len,
RaviArray *raviH_new_number_array(lua_State *L, unsigned int len, RaviArray *raviH_new_number_array(lua_State *L, unsigned int len,
lua_Number init_value) { lua_Number init_value) {
RaviArray *t = raviH_new(L, RAVI_TARRAYFLT, 0); RaviArray *t = raviH_new(L, RAVI_TM_FLOAT_ARRAY, 0);
unsigned int new_len = len + 1; // Ravi arrays have an extra slot at offset 0 unsigned int new_len = len + 1; // Ravi arrays have an extra slot at offset 0
if (new_len < len) { // Wrapped? if (new_len < len) { // Wrapped?
luaG_runerror(L, "array length out of range"); luaG_runerror(L, "array length out of range");
@ -975,7 +975,7 @@ RaviArray *raviH_new_slice(lua_State *L, TValue *parent, unsigned int start,
luaG_runerror( luaG_runerror(
L, "cannot create slice from dynamic integer[] or number[] array"); L, "cannot create slice from dynamic integer[] or number[] array");
/* Create the slice table */ /* Create the slice table */
RaviArray *t = raviH_new(L, (orig->flags & RAVI_ARRAY_ISFLOAT) ? RAVI_TARRAYFLT : RAVI_TARRAYINT, 1); RaviArray *t = raviH_new(L, (orig->flags & RAVI_ARRAY_ISFLOAT) ? RAVI_TM_FLOAT_ARRAY : RAVI_TM_INTEGER_ARRAY, 1);
/* Add a reference to the parent table. From GC perspective the slice is a white object /* Add a reference to the parent table. From GC perspective the slice is a white object
so we do not need a write barrier */ so we do not need a write barrier */
t->parent = orig; t->parent = orig;

@ -124,7 +124,7 @@ LUAI_FUNC lua_Unsigned luaH_getn (Table *t);
/* Creates a specialized version of Lua Table to support Ravi's /* Creates a specialized version of Lua Table to support Ravi's
* integer[] and number[] arrays. * integer[] and number[] arrays.
*/ */
LUAI_FUNC RaviArray *raviH_new(lua_State *L, ravitype_t array_type, int is_slice); LUAI_FUNC RaviArray *raviH_new(lua_State *L, ravi_type_map array_type, int is_slice);
LUAI_FUNC void raviH_free(lua_State* L, RaviArray* t); LUAI_FUNC void raviH_free(lua_State* L, RaviArray* t);
LUAI_FUNC int raviH_next(lua_State* L, RaviArray* t, StkId key); LUAI_FUNC int raviH_next(lua_State* L, RaviArray* t, StkId key);

@ -644,7 +644,7 @@ static int listlocals (lua_State *L) {
int pc = cast_int(luaL_checkinteger(L, 2)) - 1; int pc = cast_int(luaL_checkinteger(L, 2)) - 1;
int i = 0; int i = 0;
const char *name; const char *name;
ravitype_t tt; ravi_type_map tt;
TString *usertype; TString *usertype;
luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
1, "Lua function expected"); 1, "Lua function expected");

@ -183,6 +183,23 @@ static void LoadUpvalues (LoadState *S, Proto *f) {
} }
} }
static ravi_type_map ravi_old_type_to_type_map(lu_byte old) {
switch (old) {
case 0: return RAVI_TM_ANY;
case 1: return RAVI_TM_INTEGER;
case 2: return RAVI_TM_FLOAT;
case 3: return RAVI_TM_INTEGER_ARRAY;
case 4: return RAVI_TM_FLOAT_ARRAY;
case 5: return RAVI_TM_FUNCTION | RAVI_TM_NIL;
case 6: return RAVI_TM_TABLE;
case 7: return RAVI_TM_STRING | RAVI_TM_NIL;
case 8: return RAVI_TM_NIL;
case 9: return RAVI_TM_BOOLEAN | RAVI_TM_NIL;
case 10: return RAVI_TM_USERDATA | RAVI_TM_NIL;
default: return RAVI_TM_ANY;
}
}
static void LoadDebug (LoadState *S, Proto *f) { static void LoadDebug (LoadState *S, Proto *f) {
int i, n; int i, n;
@ -201,13 +218,13 @@ static void LoadDebug (LoadState *S, Proto *f) {
f->locvars[i].varname = LoadString(S); f->locvars[i].varname = LoadString(S);
f->locvars[i].startpc = LoadInt(S); f->locvars[i].startpc = LoadInt(S);
f->locvars[i].endpc = LoadInt(S); f->locvars[i].endpc = LoadInt(S);
f->locvars[i].ravi_type = LoadByte(S); f->locvars[i].ravi_type_map = ravi_old_type_to_type_map(LoadByte(S));
f->locvars[i].usertype = LoadString(S); f->locvars[i].usertype = LoadString(S);
} }
n = LoadInt(S); n = LoadInt(S);
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
f->upvalues[i].name = LoadString(S); f->upvalues[i].name = LoadString(S);
f->upvalues[i].ravi_type = LoadByte(S); f->upvalues[i].ravi_type_map = ravi_old_type_to_type_map(LoadByte(S));
f->upvalues[i].usertype = LoadString(S); f->upvalues[i].usertype = LoadString(S);
} }
} }

@ -2215,7 +2215,7 @@ int luaV_execute (lua_State *L) {
vmcase(OP_RAVI_NEW_IARRAY) { vmcase(OP_RAVI_NEW_IARRAY) {
RaviArray *t; RaviArray *t;
savepc(L); /* in case of allocation errors */ savepc(L); /* in case of allocation errors */
t = raviH_new(L, RAVI_TARRAYINT, 0); t = raviH_new(L, RAVI_TM_INTEGER_ARRAY, 0);
setiarrayvalue(L, ra, t); setiarrayvalue(L, ra, t);
checkGC(L, ra + 1); checkGC(L, ra + 1);
vmbreak; vmbreak;
@ -2223,7 +2223,7 @@ int luaV_execute (lua_State *L) {
vmcase(OP_RAVI_NEW_FARRAY) { vmcase(OP_RAVI_NEW_FARRAY) {
RaviArray *t; RaviArray *t;
savepc(L); /* in case of allocation errors */ savepc(L); /* in case of allocation errors */
t = raviH_new(L, RAVI_TARRAYFLT, 0); t = raviH_new(L, RAVI_TM_FLOAT_ARRAY, 0);
setfarrayvalue(L, ra, t); setfarrayvalue(L, ra, t);
checkGC(L, ra + 1); checkGC(L, ra + 1);
vmbreak; vmbreak;
@ -2795,13 +2795,13 @@ void raviV_debug_trace(lua_State *L, int opCode, int pc) {
} }
void raviV_op_newarrayint(lua_State *L, CallInfo *ci, TValue *ra) { void raviV_op_newarrayint(lua_State *L, CallInfo *ci, TValue *ra) {
RaviArray *t = raviH_new(L, RAVI_TARRAYINT, 0); RaviArray *t = raviH_new(L, RAVI_TM_INTEGER_ARRAY, 0);
setiarrayvalue(L, ra, t); setiarrayvalue(L, ra, t);
checkGC_(L, ra + 1); checkGC_(L, ra + 1);
} }
void raviV_op_newarrayfloat(lua_State *L, CallInfo *ci, TValue *ra) { void raviV_op_newarrayfloat(lua_State *L, CallInfo *ci, TValue *ra) {
RaviArray *t = raviH_new(L, RAVI_TARRAYFLT, 0); RaviArray *t = raviH_new(L, RAVI_TM_FLOAT_ARRAY, 0);
setfarrayvalue(L, ra, t); setfarrayvalue(L, ra, t);
checkGC_(L, ra + 1); checkGC_(L, ra + 1);
} }

@ -299,19 +299,6 @@ static const char Lua_header[] =
" { TValue *io=(o); const Udata *iu = (u); \\\n" " { TValue *io=(o); const Udata *iu = (u); \\\n"
" io->value_ = iu->user_; settt_(io, iu->ttuv_); \\\n" " io->value_ = iu->user_; settt_(io, iu->ttuv_); \\\n"
" checkliveness(L,io); }\n" " checkliveness(L,io); }\n"
"typedef enum {\n"
" RAVI_TANY = 0,\n"
" RAVI_TNUMINT = 1,\n"
" RAVI_TNUMFLT,\n"
" RAVI_TARRAYINT,\n"
" RAVI_TARRAYFLT,\n"
" RAVI_TFUNCTION,\n"
" RAVI_TTABLE,\n"
" RAVI_TSTRING,\n"
" RAVI_TNIL,\n"
" RAVI_TBOOLEAN,\n"
" RAVI_TUSERDATA\n"
"} ravitype_t;\n"
"typedef struct Upvaldesc {\n" "typedef struct Upvaldesc {\n"
" TString *name;\n" " TString *name;\n"
" TString *usertype;\n" " TString *usertype;\n"

Loading…
Cancel
Save