Cleanup and Fixes

pull/213/head
XmiliaH 3 years ago
parent a9537957d5
commit b4359b9391

@ -1568,8 +1568,9 @@ 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, ravi_type_map *type) { CClosure **owner, UpVal **uv, ravi_type_map *type, TString **usertype) {
*type = RAVI_TM_ANY; *type = RAVI_TM_ANY;
*usertype = NULL;
switch (ttype(fi)) { switch (ttype(fi)) {
case LUA_TCCL: { /* C closure */ case LUA_TCCL: { /* C closure */
CClosure *f = clCvalue(fi); CClosure *f = clCvalue(fi);
@ -1587,6 +1588,7 @@ static const char *aux_upvalue (StkId fi, int n, TValue **val,
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_map; *type = p->upvalues[n - 1].ravi_type_map;
*usertype = p->upvalues[n - 1].usertype;
return (name == NULL) ? "(*no name)" : getstr(name); return (name == NULL) ? "(*no name)" : getstr(name);
} }
default: return NULL; /* not a closure */ default: return NULL; /* not a closure */
@ -1597,9 +1599,10 @@ 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;
ravi_type_map type; ravi_type_map type;
TString *usertype;
TValue *val = NULL; /* to avoid warnings */ TValue *val = NULL; /* to avoid warnings */
lua_lock(L); lua_lock(L);
name = aux_upvalue(index2addr(L, funcindex), n, &val, NULL, NULL, &type); name = aux_upvalue(index2addr(L, funcindex), n, &val, NULL, NULL, &type, &usertype);
if (name) { if (name) {
setobj2s(L, L->top, val); setobj2s(L, L->top, val);
api_incr_top(L); api_incr_top(L);
@ -1615,10 +1618,11 @@ LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {
UpVal *uv = NULL; UpVal *uv = NULL;
StkId fi; StkId fi;
ravi_type_map type; /* RAVI upvalue type will be obtained if possible */ ravi_type_map type; /* RAVI upvalue type will be obtained if possible */
TString *usertype;
lua_lock(L); lua_lock(L);
fi = index2addr(L, funcindex); fi = index2addr(L, funcindex);
api_checknelems(L, 1); api_checknelems(L, 1);
name = aux_upvalue(fi, n, &val, &owner, &uv, &type); name = aux_upvalue(fi, n, &val, &owner, &uv, &type, &usertype);
if (name) { if (name) {
/* RAVI extension /* RAVI extension
** We need to ensure that this function does ** We need to ensure that this function does
@ -1626,7 +1630,7 @@ LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {
*/ */
StkId input = L->top - 1; StkId input = L->top - 1;
int compatible = ravi_checktype(input, type); int compatible = ravi_checktype(L, input, type, usertype);
if (!compatible) if (!compatible)
name = NULL; name = NULL;

@ -1415,7 +1415,7 @@ static void codebinexpval (FuncState *fs, OpCode op,
} }
static OpCode get_type_specific_comp_op(OpCode op, uint32_t o1_tm, uint32_t o2_tm) { 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_tm == RAVI_TM_INTEGER && o2_tm == RAVI_TM_INTEGER) if (o1_tm == RAVI_TM_INTEGER && o2_tm == RAVI_TM_INTEGER)
op = OP_RAVI_EQ_II; op = OP_RAVI_EQ_II;
@ -1445,9 +1445,9 @@ 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);
uint32_t rk1_tm = e1->ravi_type_map; ravi_type_map rk1_tm = e1->ravi_type_map;
int rk2 = luaK_exp2RK(fs, e2); int rk2 = luaK_exp2RK(fs, e2);
uint32_t rk2_tm = e2->ravi_type_map; 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)' */
@ -1508,7 +1508,7 @@ 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;
uint32_t tm; ravi_type_map tm;
if (op == OPR_TO_NUMBER && e->ravi_type_map != RAVI_TM_FLOAT) { if (op == OPR_TO_NUMBER && e->ravi_type_map != RAVI_TM_FLOAT) {
opcode = OP_RAVI_TOFLT; opcode = OP_RAVI_TOFLT;
tm = RAVI_TM_FLOAT; tm = RAVI_TM_FLOAT;

@ -147,16 +147,17 @@ 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, ravi_type_map *type) { StkId *pos, ravi_type_map *type, TString** usertype) {
const char *name = NULL; const char *name = NULL;
StkId base; StkId base;
*type = RAVI_TM_ANY; *type = RAVI_TM_ANY;
*usertype = NULL;
if (isLua(ci)) { if (isLua(ci)) {
if (n < 0) /* access to vararg values? */ if (n < 0) /* access to vararg values? */
return findvararg(ci, -n, pos); return findvararg(ci, -n, pos);
else { else {
base = ci->u.l.base; base = ci->u.l.base;
name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci), type); name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci), type, usertype);
} }
} }
else else
@ -176,17 +177,18 @@ 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;
ravi_type_map type; ravi_type_map type;
TString *usertype;
lua_lock(L); lua_lock(L);
swapextra(L); swapextra(L);
if (ar == NULL) { /* information about non-active function? */ if (ar == NULL) { /* information about non-active function? */
if (!isLfunction(L->top - 1)) /* not a Lua function? */ if (!isLfunction(L->top - 1)) /* not a Lua function? */
name = NULL; name = NULL;
else /* consider live variables at function start (parameters) */ else /* consider live variables at function start (parameters) */
name = luaF_getlocalname(clLvalue(L->top - 1)->p, n, 0, &type); name = luaF_getlocalname(clLvalue(L->top - 1)->p, n, 0, &type, &usertype);
} }
else { /* active function; get information through 'ar' */ else { /* active function; get information through 'ar' */
StkId pos = NULL; /* to avoid warnings */ StkId pos = NULL; /* to avoid warnings */
name = findlocal(L, ar->i_ci, n, &pos, &type); name = findlocal(L, ar->i_ci, n, &pos, &type, &usertype);
if (name) { if (name) {
setobj2s(L, L->top, pos); setobj2s(L, L->top, pos);
api_incr_top(L); api_incr_top(L);
@ -202,17 +204,18 @@ 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;
ravi_type_map type; ravi_type_map type;
TString* usertype;
int compatible = 1; int compatible = 1;
lua_lock(L); lua_lock(L);
swapextra(L); swapextra(L);
name = findlocal(L, ar->i_ci, n, &pos, &type); name = findlocal(L, ar->i_ci, n, &pos, &type, &usertype);
if (name) { if (name) {
/* RAVI extension /* RAVI extension
** We need to ensure that this function does ** We need to ensure that this function does
** 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 = ravi_checktype(input, type); 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 */
@ -450,7 +453,8 @@ static const char *getobjname (Proto *p, int lastpc, int reg,
const char **name) { const char **name) {
int pc; int pc;
ravi_type_map type; ravi_type_map type;
*name = luaF_getlocalname(p, reg + 1, lastpc, &type); TString *usertype;
*name = luaF_getlocalname(p, reg + 1, lastpc, &type, &usertype);
if (*name) /* is a local? */ if (*name) /* is a local? */
return "local"; return "local";
/* else try symbolic execution */ /* else try symbolic execution */
@ -481,7 +485,7 @@ static const char *getobjname (Proto *p, int lastpc, int reg,
int k = GETARG_C(i); /* key index */ int k = GETARG_C(i); /* key index */
int t = GETARG_B(i); /* table index */ int t = GETARG_B(i); /* table index */
const char *vn = (op != OP_GETTABUP && op != OP_RAVI_GETTABUP_SK) /* name of indexed variable */ const char *vn = (op != OP_GETTABUP && op != OP_RAVI_GETTABUP_SK) /* name of indexed variable */
? luaF_getlocalname(p, t + 1, pc, &type) /* t+1 is the local variable number */ ? luaF_getlocalname(p, t + 1, pc, &type, &usertype) /* t+1 is the local variable number */
: upvalname(p, t); : upvalname(p, t);
kname(p, pc, k, name); kname(p, pc, k, name);
return (vn && strcmp(vn, LUA_ENV) == 0) ? "global" : "field"; return (vn && strcmp(vn, LUA_ENV) == 0) ? "global" : "field";

@ -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, ravi_type_map *type) { 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? */
@ -252,11 +252,13 @@ const char *luaF_getlocalname (const Proto *f, int local_number, int pc, ravi_ty
if (f->locvars[i].varname == NULL) if (f->locvars[i].varname == NULL)
break; break;
*type = f->locvars[i].ravi_type_map; *type = f->locvars[i].ravi_type_map;
*usertype = f->locvars[i].usertype;
return getstr(f->locvars[i].varname); return getstr(f->locvars[i].varname);
} }
} }
} }
*type = RAVI_TM_ANY; *type = RAVI_TM_ANY;
*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, ravi_type_map* type); int pc, ravi_type_map* type, TString **usertype);
#endif #endif

@ -33,7 +33,7 @@
LUAI_DDEF const TValue luaO_nilobject_ = {NILCONSTANT}; LUAI_DDEF const TValue luaO_nilobject_ = {NILCONSTANT};
int ravi_checktype(StkId input, ravi_type_map type) { 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_ANY) return 1;
if (type & RAVI_TM_NIL && ttisnil(input)) 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_FALSE && ttisboolean(input) && l_isfalse(input)) return 1;
@ -45,7 +45,9 @@ int ravi_checktype(StkId input, ravi_type_map type) {
if (type & RAVI_TM_TABLE && ttisLtable(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_STRING && ttisstring(input)) return 1;
if (type & RAVI_TM_FUNCTION && ttisclosure(input)) return 1; if (type & RAVI_TM_FUNCTION && ttisclosure(input)) return 1;
// TODO if (type & RAVI_TM_USERDATA && ) if (type & RAVI_TM_USERDATA) {
if (raviV_check_usertype(L, usertype, input)) return 1;
}
return 0; return 0;
} }

@ -72,18 +72,18 @@ typedef enum {
typedef uint32_t ravi_type_map; typedef uint32_t ravi_type_map;
#define RAVI_TM_NIL (((uint32_t)1)<<RAVI_TI_NIL) #define RAVI_TM_NIL (((ravi_type_map)1)<<RAVI_TI_NIL)
#define RAVI_TM_FALSE (((uint32_t)1)<<RAVI_TI_FALSE) #define RAVI_TM_FALSE (((ravi_type_map)1)<<RAVI_TI_FALSE)
#define RAVI_TM_TRUE (((uint32_t)1)<<RAVI_TI_TRUE) #define RAVI_TM_TRUE (((ravi_type_map)1)<<RAVI_TI_TRUE)
#define RAVI_TM_INTEGER (((uint32_t)1)<<RAVI_TI_INTEGER) #define RAVI_TM_INTEGER (((ravi_type_map)1)<<RAVI_TI_INTEGER)
#define RAVI_TM_FLOAT (((uint32_t)1)<<RAVI_TI_FLOAT) #define RAVI_TM_FLOAT (((ravi_type_map)1)<<RAVI_TI_FLOAT)
#define RAVI_TM_INTEGER_ARRAY (((uint32_t)1)<<RAVI_TI_INTEGER_ARRAY) #define RAVI_TM_INTEGER_ARRAY (((ravi_type_map)1)<<RAVI_TI_INTEGER_ARRAY)
#define RAVI_TM_FLOAT_ARRAY (((uint32_t)1)<<RAVI_TI_FLOAT_ARRAY) #define RAVI_TM_FLOAT_ARRAY (((ravi_type_map)1)<<RAVI_TI_FLOAT_ARRAY)
#define RAVI_TM_TABLE (((uint32_t)1)<<RAVI_TI_TABLE) #define RAVI_TM_TABLE (((ravi_type_map)1)<<RAVI_TI_TABLE)
#define RAVI_TM_STRING (((uint32_t)1)<<RAVI_TI_STRING) #define RAVI_TM_STRING (((ravi_type_map)1)<<RAVI_TI_STRING)
#define RAVI_TM_FUNCTION (((uint32_t)1)<<RAVI_TI_FUNCTION) #define RAVI_TM_FUNCTION (((ravi_type_map)1)<<RAVI_TI_FUNCTION)
#define RAVI_TM_USERDATA (((uint32_t)1)<<RAVI_TI_USERDATA) #define RAVI_TM_USERDATA (((ravi_type_map)1)<<RAVI_TI_USERDATA)
#define RAVI_TM_OTHER (((uint32_t)1)<<RAVI_TI_OTHER) #define RAVI_TM_OTHER (((ravi_type_map)1)<<RAVI_TI_OTHER)
#define RAVI_TM_FALSISH (RAVI_TM_NIL | RAVI_TM_FALSE) #define RAVI_TM_FALSISH (RAVI_TM_NIL | RAVI_TM_FALSE)
#define RAVI_TM_TRUISH (~RAVI_TM_FALSISH) #define RAVI_TM_TRUISH (~RAVI_TM_FALSISH)
@ -860,7 +860,7 @@ LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t srclen);
LUAI_FUNC int ravi_checktype(StkId input, ravi_type_map type); LUAI_FUNC int ravi_checktype(lua_State *L, StkId input, ravi_type_map type, TString* usertype);
#endif #endif

@ -75,7 +75,7 @@ static char* raviY_buf_append(char* buf, const char* what) {
return buf; return buf;
} }
void raviY_typemap_string(uint32_t tm, char* buf) { void raviY_typemap_string(ravi_type_map tm, char* buf) {
if (tm == RAVI_TM_ANY) { if (tm == RAVI_TM_ANY) {
memcpy(buf, "any", 4); memcpy(buf, "any", 4);
return; return;
@ -364,7 +364,7 @@ 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, uint32_t tt, TString *usertype) { static void init_exp (expdesc *e, expkind k, int info, ravi_type_map 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;
@ -394,7 +394,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, ravi_type_map ravi_type_map, TString *usertype) { static int registerlocalvar (LexState *ls, TString *varname, ravi_type_map tm, 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;
@ -409,7 +409,7 @@ static int registerlocalvar (LexState *ls, TString *varname, ravi_type_map ravi_
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_map = ravi_type_map; f->locvars[fs->nlocvars].ravi_type_map = tm;
f->locvars[fs->nlocvars].usertype = usertype; f->locvars[fs->nlocvars].usertype = usertype;
luaC_objbarrier(ls->L, f, varname); luaC_objbarrier(ls->L, f, varname);
return fs->nlocvars++; return fs->nlocvars++;
@ -625,29 +625,22 @@ 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, ravi_type_map ravi_type_map, TString *typename /* only if tt is USERDATA */) { static void ravi_code_typecoersion(LexState *ls, int reg, ravi_type_map tm,
TString *typename /* only if tt is USERDATA */) {
/* do we need to convert ? */ /* do we need to convert ? */
if (ravi_type_map == RAVI_TM_FLOAT || ravi_type_map == RAVI_TM_INTEGER) if (tm == RAVI_TM_FLOAT || tm == 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, tm == RAVI_TM_FLOAT ? OP_RAVI_TOFLT : OP_RAVI_TOINT, reg, 0, 0);
ravi_type_map == RAVI_TM_FLOAT ? OP_RAVI_TOFLT : OP_RAVI_TOINT, reg, else if (tm == RAVI_TM_INTEGER_ARRAY || tm == RAVI_TM_FLOAT_ARRAY)
0, 0); luaK_codeABC(ls->fs, tm == RAVI_TM_INTEGER_ARRAY ? OP_RAVI_TOIARRAY : OP_RAVI_TOFARRAY, reg, 0, 0);
else if (ravi_type_map == RAVI_TM_INTEGER_ARRAY || ravi_type_map == RAVI_TM_FLOAT_ARRAY) else if (tm == RAVI_TM_TABLE)
luaK_codeABC(ls->fs, ravi_type_map == RAVI_TM_INTEGER_ARRAY ? OP_RAVI_TOIARRAY luaK_codeABC(ls->fs, OP_RAVI_TOTAB, reg, 0, 0);
: OP_RAVI_TOFARRAY, else if (tm == (RAVI_TM_USERDATA | RAVI_TM_NIL))
reg, 0, 0); luaK_codeABx(ls->fs, OP_RAVI_TOTYPE, reg, luaK_stringK(ls->fs, typename));
else if (ravi_type_map == RAVI_TM_TABLE) else if (tm == (RAVI_TM_STRING | RAVI_TM_NIL))
luaK_codeABC(ls->fs, OP_RAVI_TOTAB, luaK_codeABC(ls->fs, OP_RAVI_TOSTRING, reg, 0, 0);
reg, 0, 0); else if (tm == (RAVI_TM_FUNCTION | RAVI_TM_NIL))
else if (ravi_type_map == (RAVI_TM_USERDATA | RAVI_TM_NIL)) luaK_codeABC(ls->fs, OP_RAVI_TOCLOSURE, reg, 0, 0);
luaK_codeABx(ls->fs, OP_RAVI_TOTYPE,
reg, luaK_stringK(ls->fs, typename));
else if (ravi_type_map == (RAVI_TM_STRING | RAVI_TM_NIL))
luaK_codeABC(ls->fs, OP_RAVI_TOSTRING,
reg, 0, 0);
else if (ravi_type_map == (RAVI_TM_FUNCTION | RAVI_TM_NIL))
luaK_codeABC(ls->fs, OP_RAVI_TOCLOSURE,
reg, 0, 0);
// TODO coerse to boolean // TODO coerse to boolean
} }
@ -695,10 +688,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);
ravi_type_map ravi_type_map = ls->fs->f->locvars[idx].ravi_type_map; /* get variable's type */ ravi_type_map tm = 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_map, usertype); ravi_code_typecoersion(ls, i, tm, usertype);
} }
} }
@ -712,10 +705,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);
ravi_type_map ravi_type_map = fs->f->locvars[idx].ravi_type_map; /* get variable's type */ ravi_type_map tm = 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_map, usertype); ravi_code_setzero(fs, i, tm, usertype);
} }
} }
@ -1417,92 +1410,96 @@ static int explist (LexState *ls, expdesc *v) {
*/ */
static void ravi_typecheck(LexState *ls, expdesc *v, ravi_type_map *var_types, static void ravi_typecheck(LexState *ls, expdesc *v, ravi_type_map *var_types,
TString **usertypes, int nvars, int n) { TString **usertypes, int nvars, int n) {
/* NOTE that 'v' may not have register assigned yet */ /* NOTE that 'v' may not have register assigned yet */
if (n >= nvars) return;
ravi_type_map vartype = var_types[n]; ravi_type_map vartype = var_types[n];
if (n < nvars && (v->ravi_type_map & ~vartype)) { ravi_type_map v_type_map = v->ravi_type_map;
if ((vartype == RAVI_TM_FLOAT_ARRAY || vartype == RAVI_TM_INTEGER_ARRAY) && if (v->k == VINDEXED) {
v->k == VNONRELOC) { if (v_type_map == RAVI_TM_INTEGER_ARRAY) {
/* as the bytecode for generating a table is already emitted by this stage v_type_map = RAVI_TM_INTEGER;
* we have to amend the generated byte code - not sure if there is a } else if (v_type_map == RAVI_TM_FLOAT_ARRAY) {
* better approach. The location of the OP_NEWTABLE instruction is in v_type_map = RAVI_TM_FLOAT;
* v->pc and we check that this has the same destination register as } else {
* v->u.info which is our variable */ v_type_map = RAVI_TM_ANY;
// local a:int[] = { 1 }
// ^ We are just past this
// and about to assign to a
int ok = 0;
if (v->pc >= 0) {
Instruction *pc =
&ls->fs->f->code[v->pc]; /* Get the OP_NEWTABLE instruction */
OpCode op = GET_OPCODE(*pc);
if (op == OP_NEWTABLE) { /* check before making changes */
int reg = GETARG_A(*pc);
if (reg ==
v->u.info) { /* double check that register is as expected */
op = (vartype == RAVI_TM_INTEGER_ARRAY) ? OP_RAVI_NEW_IARRAY
: OP_RAVI_NEW_FARRAY;
SET_OPCODE(*pc, op); /* modify opcode */
DEBUG_CODEGEN(
raviY_printf(ls->fs, "[%d]* %o ; modify opcode\n", v->pc, *pc));
ok = 1;
}
}
}
if (!ok)
luaX_syntaxerror(ls, "expecting array initializer");
} }
/* if we are calling a function then convert return types */ }
else if ((vartype == RAVI_TM_FLOAT || vartype == RAVI_TM_INTEGER || if ((v_type_map & ~vartype) == 0) return;
vartype == RAVI_TM_FLOAT_ARRAY || vartype == RAVI_TM_INTEGER_ARRAY || if ((vartype == RAVI_TM_FLOAT_ARRAY || vartype == RAVI_TM_INTEGER_ARRAY) &&
vartype == RAVI_TM_TABLE || vartype == (RAVI_TM_STRING | RAVI_TM_NIL) || v->k == VNONRELOC) {
vartype == (RAVI_TM_FUNCTION | RAVI_TM_NIL) || vartype == (RAVI_TM_USERDATA | RAVI_TM_NIL)) && /* as the bytecode for generating a table is already emitted by this stage
v->k == VCALL) { * we have to amend the generated byte code - not sure if there is a
/* For local variable declarations that call functions e.g. * better approach. The location of the OP_NEWTABLE instruction is in
* local i = func() * v->pc and we check that this has the same destination register as
* Lua ensures that the function returns values to register assigned to * v->u.info which is our variable */
* variable i and above so that no separate OP_MOVE instruction is // local a:int[] = { 1 }
* necessary. So that means that we need to coerce the return values // ^ We are just past this
* in situ. // and about to assign to a
*/ int ok = 0;
if (v->pc >= 0) {
Instruction *pc = Instruction *pc =
&getinstruction(ls->fs, v); /* Obtain the instruction for OP_CALL */ &ls->fs->f->code[v->pc]; /* Get the OP_NEWTABLE instruction */
lua_assert(GET_OPCODE(*pc) == OP_CALL); OpCode op = GET_OPCODE(*pc);
int a = GETARG_A(*pc); /* function return values will be placed from if (op == OP_NEWTABLE) { /* check before making changes */
register pointed by A and upwards */ int reg = GETARG_A(*pc);
int nrets = GETARG_C(*pc) - 1; if (reg ==
/* operand C contains number of return values expected */ v->u.info) { /* double check that register is as expected */
/* Note that at this stage nrets is always 1 - as Lua patches in the this op = (vartype == RAVI_TM_INTEGER_ARRAY) ? OP_RAVI_NEW_IARRAY
* value for the last function call in a : OP_RAVI_NEW_FARRAY;
* variable declaration statement in adjust_assign and SET_OPCODE(*pc, op); /* modify opcode */
* localvar_adjust_assign */ DEBUG_CODEGEN(
/* all return values that are going to be assigned to typed local vars raviY_printf(ls->fs, "[%d]* %o ; modify opcode\n", v->pc, *pc));
* must be converted to the correct type */ ok = 1;
int i; }
for (i = n; i < (n + nrets); i++) }
/* do we need to convert ? */
ravi_code_typecoersion(ls, a + (i - n), var_types[i], NULL);
}
else if ((vartype == RAVI_TM_FLOAT || vartype == RAVI_TM_INTEGER) &&
v->k == VINDEXED) {
if ((vartype == RAVI_TM_FLOAT && v->ravi_type_map != RAVI_TM_FLOAT_ARRAY) ||
(vartype == RAVI_TM_INTEGER && v->ravi_type_map != RAVI_TM_INTEGER_ARRAY))
luaX_syntaxerror(ls, "Invalid local assignment");
}
else if ((vartype == (RAVI_TM_STRING | RAVI_TM_NIL) && v->ravi_type_map != RAVI_TM_STRING) ||
(vartype == (RAVI_TM_FUNCTION | RAVI_TM_NIL) && v->ravi_type_map != RAVI_TM_FUNCTION) ||
vartype == (RAVI_TM_USERDATA | RAVI_TM_NIL)) { // TODO this is wrong since nil is ignored
TString *usertype = usertypes[n]; // NULL if var_types[n] is not userdata
/* we need to make sure that a register is assigned to 'v'
so that we can emit type assertion instructions. This would have
normally happened in the calling function but we do it early here -
possibly missing some optimization opportunity (i.e. avoiding register
assignment) */
luaK_exp2nextreg(ls->fs, v);
ravi_code_typecoersion(ls, v->u.info, vartype, usertype);
}
else {
luaX_syntaxerror(ls, "Invalid local assignment");
} }
if (!ok)
luaX_syntaxerror(ls, "expecting array initializer");
}
/* if we are calling a function then convert return types */
else if ((vartype == RAVI_TM_FLOAT || vartype == RAVI_TM_INTEGER ||
vartype == RAVI_TM_FLOAT_ARRAY || vartype == RAVI_TM_INTEGER_ARRAY ||
vartype == RAVI_TM_TABLE || vartype == (RAVI_TM_STRING | RAVI_TM_NIL) ||
vartype == (RAVI_TM_FUNCTION | RAVI_TM_NIL) || vartype == (RAVI_TM_USERDATA | RAVI_TM_NIL)) &&
v->k == VCALL) {
/* For local variable declarations that call functions e.g.
* local i = func()
* Lua ensures that the function returns values to register assigned to
* variable i and above so that no separate OP_MOVE instruction is
* necessary. So that means that we need to coerce the return values
* in situ.
*/
Instruction *pc =
&getinstruction(ls->fs, v); /* Obtain the instruction for OP_CALL */
lua_assert(GET_OPCODE(*pc) == OP_CALL);
int a = GETARG_A(*pc); /* function return values will be placed from
register pointed by A and upwards */
int nrets = GETARG_C(*pc) - 1;
/* operand C contains number of return values expected */
/* Note that at this stage nrets is always 1 - as Lua patches in the this
* value for the last function call in a
* variable declaration statement in adjust_assign and
* localvar_adjust_assign */
/* all return values that are going to be assigned to typed local vars
* must be converted to the correct type */
int i;
for (i = n; i < (n + nrets); i++)
/* do we need to convert ? */
ravi_code_typecoersion(ls, a + (i - n), var_types[i], NULL);
}
else if (vartype == (RAVI_TM_STRING | RAVI_TM_NIL) ||
vartype == (RAVI_TM_FUNCTION | RAVI_TM_NIL) ||
vartype == (RAVI_TM_USERDATA | RAVI_TM_NIL)) {
TString *usertype = usertypes[n]; // NULL if var_types[n] is not userdata
/* we need to make sure that a register is assigned to 'v'
so that we can emit type assertion instructions. This would have
normally happened in the calling function but we do it early here -
possibly missing some optimization opportunity (i.e. avoiding register
assignment) */
luaK_exp2nextreg(ls->fs, v);
ravi_code_typecoersion(ls, v->u.info, vartype, usertype);
}
else {
luaX_syntaxerror(ls, "Invalid local assignment");
} }
} }
@ -2032,7 +2029,7 @@ static void repeatstat (LexState *ls, int line) {
} }
typedef struct Fornuminfo { typedef struct Fornuminfo {
uint32_t type_map; ravi_type_map type_map;
int is_constant; int is_constant;
int int_value; int int_value;
} Fornuminfo; } Fornuminfo;

@ -66,14 +66,14 @@ 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) */
uint32_t key_ravi_type_map; /* Map of possible types the key could have */ ravi_type_map key_ravi_type_map; /* Map of possible types the key could have */
// lu_byte key_ravi_type; /* RAVI change: key type */ // 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' */
uint32_t ravi_type_map; /* Map of possible types this expression could have */ 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 */ // 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 */
@ -245,7 +245,7 @@ LUAI_FUNC LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
/** RAVI extensions **/ /** RAVI extensions **/
#define RAVI_TYPEMAP_MAX_LEN (sizeof("nil|boolean|integer|number|integer[]|number[]|table|string|function|userdata|?|")) #define RAVI_TYPEMAP_MAX_LEN (sizeof("nil|boolean|integer|number|integer[]|number[]|table|string|function|userdata|?|"))
LUAI_FUNC void raviY_typemap_string(uint32_t tm, char* buf); 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 *

@ -645,10 +645,11 @@ static int listlocals (lua_State *L) {
int i = 0; int i = 0;
const char *name; const char *name;
ravi_type_map tt; ravi_type_map tt;
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");
p = getproto(obj_at(L, 1)); p = getproto(obj_at(L, 1));
while ((name = luaF_getlocalname(p, ++i, pc, &tt)) != NULL) while ((name = luaF_getlocalname(p, ++i, pc, &tt, &usertype)) != NULL)
lua_pushstring(L, name); lua_pushstring(L, name);
return i-1; return i-1;
} }

Loading…
Cancel
Save