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,
CClosure **owner, UpVal **uv, ravi_type_map *type) {
CClosure **owner, UpVal **uv, ravi_type_map *type, TString **usertype) {
*type = RAVI_TM_ANY;
*usertype = NULL;
switch (ttype(fi)) {
case LUA_TCCL: { /* C closure */
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];
name = p->upvalues[n-1].name;
*type = p->upvalues[n - 1].ravi_type_map;
*usertype = p->upvalues[n - 1].usertype;
return (name == NULL) ? "(*no name)" : getstr(name);
}
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) {
const char *name;
ravi_type_map type;
TString *usertype;
TValue *val = NULL; /* to avoid warnings */
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) {
setobj2s(L, L->top, val);
api_incr_top(L);
@ -1615,10 +1618,11 @@ LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {
UpVal *uv = NULL;
StkId fi;
ravi_type_map type; /* RAVI upvalue type will be obtained if possible */
TString *usertype;
lua_lock(L);
fi = index2addr(L, funcindex);
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) {
/* RAVI extension
** 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;
int compatible = ravi_checktype(input, type);
int compatible = ravi_checktype(L, input, type, usertype);
if (!compatible)
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 (o1_tm == RAVI_TM_INTEGER && o2_tm == RAVI_TM_INTEGER)
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));
int rk1 = (e1->k == VK) ? RKASK(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);
uint32_t rk2_tm = e2->ravi_type_map;
ravi_type_map rk2_tm = e2->ravi_type_map;
freeexps(fs, e1, e2);
switch (opr) {
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: {
discharge2anyreg(fs, e);
OpCode opcode;
uint32_t tm;
ravi_type_map tm;
if (op == OPR_TO_NUMBER && e->ravi_type_map != RAVI_TM_FLOAT) {
opcode = OP_RAVI_TOFLT;
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,
StkId *pos, ravi_type_map *type) {
StkId *pos, ravi_type_map *type, TString** usertype) {
const char *name = NULL;
StkId base;
*type = RAVI_TM_ANY;
*usertype = NULL;
if (isLua(ci)) {
if (n < 0) /* access to vararg values? */
return findvararg(ci, -n, pos);
else {
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
@ -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) {
const char *name;
ravi_type_map type;
TString *usertype;
lua_lock(L);
swapextra(L);
if (ar == NULL) { /* information about non-active function? */
if (!isLfunction(L->top - 1)) /* not a Lua function? */
name = NULL;
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' */
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) {
setobj2s(L, L->top, pos);
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 */
const char *name;
ravi_type_map type;
TString* usertype;
int compatible = 1;
lua_lock(L);
swapextra(L);
name = findlocal(L, ar->i_ci, n, &pos, &type);
name = findlocal(L, ar->i_ci, n, &pos, &type, &usertype);
if (name) {
/* RAVI extension
** We need to ensure that this function does
** not subvert the types of local variables
*/
StkId input = L->top - 1;
int compatible = ravi_checktype(input, type);
int compatible = ravi_checktype(L, input, type, usertype);
if (compatible) {
setobjs2s(L, pos, L->top - 1);
L->top--; /* pop value */
@ -450,7 +453,8 @@ static const char *getobjname (Proto *p, int lastpc, int reg,
const char **name) {
int pc;
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? */
return "local";
/* 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 t = GETARG_B(i); /* table index */
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);
kname(p, pc, k, name);
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.
** 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;
for (i = 0; i<f->sizelocvars && f->locvars[i].startpc <= pc; i++) {
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)
break;
*type = f->locvars[i].ravi_type_map;
*usertype = f->locvars[i].usertype;
return getstr(f->locvars[i].varname);
}
}
}
*type = RAVI_TM_ANY;
*usertype = NULL;
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);
/* The additional type argument is a Ravi extension */
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

@ -33,7 +33,7 @@
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_NIL && ttisnil(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_STRING && ttisstring(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;
}

@ -72,18 +72,18 @@ typedef enum {
typedef uint32_t ravi_type_map;
#define RAVI_TM_NIL (((uint32_t)1)<<RAVI_TI_NIL)
#define RAVI_TM_FALSE (((uint32_t)1)<<RAVI_TI_FALSE)
#define RAVI_TM_TRUE (((uint32_t)1)<<RAVI_TI_TRUE)
#define RAVI_TM_INTEGER (((uint32_t)1)<<RAVI_TI_INTEGER)
#define RAVI_TM_FLOAT (((uint32_t)1)<<RAVI_TI_FLOAT)
#define RAVI_TM_INTEGER_ARRAY (((uint32_t)1)<<RAVI_TI_INTEGER_ARRAY)
#define RAVI_TM_FLOAT_ARRAY (((uint32_t)1)<<RAVI_TI_FLOAT_ARRAY)
#define RAVI_TM_TABLE (((uint32_t)1)<<RAVI_TI_TABLE)
#define RAVI_TM_STRING (((uint32_t)1)<<RAVI_TI_STRING)
#define RAVI_TM_FUNCTION (((uint32_t)1)<<RAVI_TI_FUNCTION)
#define RAVI_TM_USERDATA (((uint32_t)1)<<RAVI_TI_USERDATA)
#define RAVI_TM_OTHER (((uint32_t)1)<<RAVI_TI_OTHER)
#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)
@ -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

@ -75,7 +75,7 @@ static char* raviY_buf_append(char* buf, const char* what) {
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) {
memcpy(buf, "any", 4);
return;
@ -364,7 +364,7 @@ static TString *str_checkname (LexState *ls) {
* expression kind in e->k, e->u.info may have a register
* or bytecode
*/
static void init_exp (expdesc *e, expkind k, int info, 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->k = k;
e->u.info = info;
@ -394,7 +394,7 @@ static void checkname (LexState *ls, expdesc *e) {
* variable's index in ls->f->locvars.
* RAVI change - added the type of the variable.
*/
static int registerlocalvar (LexState *ls, TString *varname, 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;
Proto *f = fs->f;
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[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;
luaC_objbarrier(ls->L, f, varname);
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,
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 ? */
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 */
luaK_codeABC(ls->fs,
ravi_type_map == RAVI_TM_FLOAT ? OP_RAVI_TOFLT : OP_RAVI_TOINT, reg,
0, 0);
else if (ravi_type_map == RAVI_TM_INTEGER_ARRAY || ravi_type_map == RAVI_TM_FLOAT_ARRAY)
luaK_codeABC(ls->fs, ravi_type_map == RAVI_TM_INTEGER_ARRAY ? OP_RAVI_TOIARRAY
: OP_RAVI_TOFARRAY,
reg, 0, 0);
else if (ravi_type_map == RAVI_TM_TABLE)
luaK_codeABC(ls->fs, OP_RAVI_TOTAB,
reg, 0, 0);
else if (ravi_type_map == (RAVI_TM_USERDATA | RAVI_TM_NIL))
luaK_codeABx(ls->fs, OP_RAVI_TOTYPE,
reg, luaK_stringK(ls->fs, typename));
else if (ravi_type_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);
luaK_codeABC(ls->fs, tm == RAVI_TM_FLOAT ? OP_RAVI_TOFLT : OP_RAVI_TOINT, reg, 0, 0);
else if (tm == RAVI_TM_INTEGER_ARRAY || tm == RAVI_TM_FLOAT_ARRAY)
luaK_codeABC(ls->fs, tm == RAVI_TM_INTEGER_ARRAY ? OP_RAVI_TOIARRAY : OP_RAVI_TOFARRAY, reg, 0, 0);
else if (tm == RAVI_TM_TABLE)
luaK_codeABC(ls->fs, OP_RAVI_TOTAB, reg, 0, 0);
else if (tm == (RAVI_TM_USERDATA | RAVI_TM_NIL))
luaK_codeABx(ls->fs, OP_RAVI_TOTYPE, reg, luaK_stringK(ls->fs, typename));
else if (tm == (RAVI_TM_STRING | RAVI_TM_NIL))
luaK_codeABC(ls->fs, OP_RAVI_TOSTRING, reg, 0, 0);
else if (tm == (RAVI_TM_FUNCTION | RAVI_TM_NIL))
luaK_codeABC(ls->fs, OP_RAVI_TOCLOSURE, reg, 0, 0);
// 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.
*/
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;
/* 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.
*/
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;
/* 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,
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];
if (n < nvars && (v->ravi_type_map & ~vartype)) {
if ((vartype == RAVI_TM_FLOAT_ARRAY || vartype == RAVI_TM_INTEGER_ARRAY) &&
v->k == VNONRELOC) {
/* as the bytecode for generating a table is already emitted by this stage
* we have to amend the generated byte code - not sure if there is a
* better approach. The location of the OP_NEWTABLE instruction is in
* v->pc and we check that this has the same destination register as
* v->u.info which is our variable */
// 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");
ravi_type_map v_type_map = v->ravi_type_map;
if (v->k == VINDEXED) {
if (v_type_map == RAVI_TM_INTEGER_ARRAY) {
v_type_map = RAVI_TM_INTEGER;
} else if (v_type_map == RAVI_TM_FLOAT_ARRAY) {
v_type_map = RAVI_TM_FLOAT;
} else {
v_type_map = RAVI_TM_ANY;
}
/* 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.
*/
}
if ((v_type_map & ~vartype) == 0) return;
if ((vartype == RAVI_TM_FLOAT_ARRAY || vartype == RAVI_TM_INTEGER_ARRAY) &&
v->k == VNONRELOC) {
/* as the bytecode for generating a table is already emitted by this stage
* we have to amend the generated byte code - not sure if there is a
* better approach. The location of the OP_NEWTABLE instruction is in
* v->pc and we check that this has the same destination register as
* v->u.info which is our variable */
// local a:int[] = { 1 }
// ^ We are just past this
// and about to assign to a
int ok = 0;
if (v->pc >= 0) {
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_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");
&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 ||
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 {
uint32_t type_map;
ravi_type_map type_map;
int is_constant;
int int_value;
} Fornuminfo;

@ -66,14 +66,14 @@ typedef struct expdesc {
short idx; /* index (R/K) */
lu_byte t; /* table (register or upvalue) */
lu_byte vt; /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */
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 */
TString *usertype; /* RAVI change: usertype name */
} ind;
} u;
int t; /* patch list of 'exit when true' */
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 */
TString *usertype; /* RAVI change: usertype name */
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 **/
#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:
* %e - expdesc *

@ -645,10 +645,11 @@ static int listlocals (lua_State *L) {
int i = 0;
const char *name;
ravi_type_map tt;
TString *usertype;
luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
1, "Lua function expected");
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);
return i-1;
}

Loading…
Cancel
Save