issue #136 additional type assertions

gccjit-ravi534
Dibyendu Majumdar 7 years ago
parent 05963da39d
commit 5e03430d7d

@ -38,7 +38,7 @@ typedef enum BinOpr {
/** RAVI change */
typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_TO_INTEGER,
OPR_TO_NUMBER, OPR_TO_INTARRAY, OPR_TO_NUMARRAY, OPR_TO_TABLE, OPR_NOUNOPR } UnOpr;
OPR_TO_NUMBER, OPR_TO_INTARRAY, OPR_TO_NUMARRAY, OPR_TO_TABLE, OPR_TO_STRING, OPR_TO_CLOSURE, OPR_TO_TYPE, OPR_NOUNOPR } UnOpr;
/* get (pointer to) instruction of given 'expdesc' */
#define getinstruction(fs,e) ((fs)->f->code[(e)->u.info])
@ -78,7 +78,7 @@ LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list);
LUAI_FUNC void luaK_patchclose (FuncState *fs, int list, int level);
LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2);
LUAI_FUNC int luaK_getlabel (FuncState *fs);
LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v, int line);
LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v, int line, TString *);
LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v);
LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1,
expdesc *v2, int line);

@ -444,6 +444,7 @@ typedef struct LocVar {
int startpc; /* first point where variable is active */
int endpc; /* first point where variable is dead */
ravitype_t ravi_type; /* RAVI type of the variable - RAVI_TANY if unknown */
/* TODO add typename for userdata */
} LocVar;
/** RAVI changes start */

@ -264,6 +264,9 @@ OP_RAVI_TOFLT, /* A R(A) := tofloat(R(A)) */
OP_RAVI_TOARRAYI, /* A R(A) := to_arrayi(R(A)) */
OP_RAVI_TOARRAYF, /* A R(A) := to_arrayf(R(A)) */
OP_RAVI_TOTAB, /* A R(A) := to_table(R(A)) */
OP_RAVI_TOSTRING,
OP_RAVI_TOCLOSURE,
OP_RAVI_TOTYPE,
OP_RAVI_MOVEI, /* A B R(A) := R(B), check R(B) is int */
OP_RAVI_MOVEF, /* A B R(A) := R(B), check R(B) is float */

@ -401,7 +401,7 @@
** This macro is not on by default even in compatibility mode,
** because this is not really an incompatibility.
*/
/* #define LUA_COMPAT_FLOATSTRING */
#define LUA_COMPAT_FLOATSTRING
/* }================================================================== */

@ -1398,7 +1398,7 @@ static void codecomp (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) {
** operator that takes one operand - a register location - and
** asserts that the register contains a value of the required type.
*/
static void code_type_assertion(FuncState *fs, UnOpr op, expdesc *e) {
static void code_type_assertion(FuncState *fs, UnOpr op, expdesc *e, TString *typename) {
luaK_dischargevars(fs, e);
switch (e->k) {
case VKFLT: {
@ -1454,16 +1454,32 @@ static void code_type_assertion(FuncState *fs, UnOpr op, expdesc *e) {
opcode = OP_RAVI_TOARRAYF;
tt = RAVI_TARRAYFLT;
}
else if (op == OPR_TO_TABLE && e->ravi_type != RAVI_TTABLE) {
else if (op == OPR_TO_TABLE && e->ravi_type != RAVI_TTABLE) {
opcode = OP_RAVI_TOTAB;
tt = RAVI_TTABLE;
}
else if (op == OPR_TO_STRING && e->ravi_type != RAVI_TSTRING) {
opcode = OP_RAVI_TOSTRING;
tt = RAVI_TSTRING;
}
else if (op == OPR_TO_CLOSURE && e->ravi_type != RAVI_TFUNCTION) {
opcode = OP_RAVI_TOCLOSURE;
tt = RAVI_TFUNCTION;
}
else if (op == OPR_TO_TYPE) {
opcode = OP_RAVI_TOTYPE;
tt = RAVI_TUSERDATA;
}
else {
/* nothing to do*/
return;
}
/* Must already be NONRELOC */
luaK_codeABC(fs, opcode, e->u.info, 0, 0);
if (opcode == OP_RAVI_TOTYPE) {
luaK_codeABx(fs, opcode, e->u.info, luaK_stringK(fs, typename));
}
else
luaK_codeABC(fs, opcode, e->u.info, 0, 0);
e->ravi_type = tt;
e->k = VNONRELOC;
return;
@ -1476,7 +1492,7 @@ static void code_type_assertion(FuncState *fs, UnOpr op, expdesc *e) {
/*
** Apply prefix operation 'op' to expression 'e'.
*/
void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) {
void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line, TString *typename) {
expdesc ef = {.ravi_type = RAVI_TANY,
.pc = -1,
.t = NO_JUMP,
@ -1492,8 +1508,10 @@ void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) {
codeunexpval(fs, cast(OpCode, op + OP_UNM), e, line);
break;
case OPR_TO_INTEGER: case OPR_TO_NUMBER: case OPR_TO_INTARRAY:
case OPR_TO_NUMARRAY: case OPR_TO_TABLE:
code_type_assertion(fs, op, e); break;
case OPR_TO_NUMARRAY: case OPR_TO_TABLE: case OPR_TO_STRING: case OPR_TO_CLOSURE:
code_type_assertion(fs, op, e, NULL); break;
case OPR_TO_TYPE:
code_type_assertion(fs, op, e, typename); break;
case OPR_NOT: codenot(fs, e); break;
default: lua_assert(0);
}

@ -460,7 +460,7 @@ static int casttoken(LexState *ls, SemInfo *seminfo) {
else if (strncmp(s, "@table", n) == 0)
tok = TK_TO_TABLE;
else {
seminfo->ts = luaX_newstring(ls, s, n);
seminfo->ts = luaX_newstring(ls, s+1, n-1); /* omit @ */
tok = '@';
}
luaZ_buffremove(ls->buff, n); /* rewind but buffer still holds the saved characters */

@ -110,6 +110,9 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = {
"TOARRAYI", /* A R(A) := to_arrayi(R(A)) */
"TOARRAYF", /* A R(A) := to_arrayf(R(A)) */
"TOTAB", /* A R(A) := to_table(R(A)) */
"TOSTRING",
"TOCLOSURE",
"TOTYPE",
"MOVEI", /* A B R(A) := R(B) */
"MOVEF", /* A B R(A) := R(B) */
@ -248,6 +251,9 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
,opmode(0, 1, OpArgN, OpArgN, iABC) /* OP_RAVI_TOARRAYI A R(A) := check_array_of_int(R(A)) */
,opmode(0, 1, OpArgN, OpArgN, iABC) /* OP_RAVI_TOARRAYF A R(A) := check_array_of_float(R(A)) */
,opmode(0, 1, OpArgN, OpArgN, iABC) /* OP_RAVI_TOTAB A R(A) := check_table(R(A)) */
,opmode(0, 1, OpArgN, OpArgN, iABC) /* OP_RAVI_TOSTRING */
,opmode(0, 1, OpArgN, OpArgN, iABC) /* OP_RAVI_TOCLOSURE */
,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_RAVI_TOTYPE */
,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_RAVI_MOVEI A B R(A) := tointeger(R(B)) */
,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_RAVI_MOVEF A B R(A) := tonumber(R(B)) */

@ -563,7 +563,7 @@ static void singlevar (LexState *ls, expdesc *var) {
/* RAVI code an instruction to coerce the type, reg is the register,
and ravi_type is the type we want */
static void ravi_code_typecoersion(LexState *ls, int reg, ravitype_t ravi_type) {
static void ravi_code_typecoersion(LexState *ls, int reg, ravitype_t ravi_type, TString *typename /* only if tt is USERDATA */) {
/* do we need to convert ? */
if (ravi_type == RAVI_TNUMFLT || ravi_type == RAVI_TNUMINT)
/* code an instruction to convert in place */
@ -577,7 +577,15 @@ static void ravi_code_typecoersion(LexState *ls, int reg, ravitype_t ravi_type)
else if (ravi_type == RAVI_TTABLE)
luaK_codeABC(ls->fs, OP_RAVI_TOTAB,
reg, 0, 0);
// TODO handle string, function, userdata, boolean types
else if (ravi_type == RAVI_TUSERDATA)
luaK_codeABx(ls->fs, OP_RAVI_TOTYPE,
reg, luaK_stringK(ls->fs, typename));
else if (ravi_type == RAVI_TSTRING)
luaK_codeABC(ls->fs, OP_RAVI_TOSTRING,
reg, 0, 0);
else if (ravi_type == RAVI_TFUNCTION)
luaK_codeABC(ls->fs, OP_RAVI_TOCLOSURE,
reg, 0, 0);
}
/* RAVI code an instruction to initialize a scalar typed value
@ -625,7 +633,7 @@ static void ravi_coercetype(LexState *ls, expdesc *v, int n)
int idx = register_to_locvar_index(ls->fs, i);
ravitype_t ravi_type = ls->fs->f->locvars[idx].ravi_type; /* get variable's type */
/* do we need to convert ? */
ravi_code_typecoersion(ls, i, ravi_type);
ravi_code_typecoersion(ls, i, ravi_type, NULL);
}
}
@ -1134,7 +1142,7 @@ static void constructor (LexState *ls, expdesc *t) {
* where type is 'integer', 'integer[]',
* 'number', 'number[]'
*/
static ravitype_t declare_localvar(LexState *ls) {
static ravitype_t declare_localvar(LexState *ls, TString **userdata_name) {
/* RAVI change - add type */
TString *name = str_checkname(ls);
/* assume a dynamic type */
@ -1154,14 +1162,19 @@ static ravitype_t declare_localvar(LexState *ls) {
tt = RAVI_TNUMFLT;
else if (strcmp(str, "closure") == 0)
tt = RAVI_TFUNCTION;
else if (strcmp(str, "userdata") == 0)
tt = RAVI_TUSERDATA;
else if (strcmp(str, "table") == 0)
tt = RAVI_TTABLE;
else if (strcmp(str, "string") == 0)
tt = RAVI_TSTRING;
else if (strcmp(str, "boolean") == 0)
tt = RAVI_TBOOLEAN;
else if (strcmp(str, "any") == 0)
tt = RAVI_TANY;
else {
/* default is a userdata type */
tt = RAVI_TUSERDATA;
*userdata_name = typename;
}
if (tt == RAVI_TNUMFLT || tt == RAVI_TNUMINT) {
/* if we see [] then it is an array type */
if (testnext(ls, '[')) {
@ -1179,13 +1192,16 @@ static void parlist (LexState *ls) {
FuncState *fs = ls->fs;
Proto *f = fs->f;
int nparams = 0;
enum { N = MAXVARS + 10 };
int vars[N] = { 0 };
TString *typenames[N] = { NULL };
f->is_vararg = 0;
if (ls->t.token != ')') { /* is 'parlist' not empty? */
do {
switch (ls->t.token) {
case TK_NAME: { /* param -> NAME */
/* RAVI change - add type */
declare_localvar(ls);
vars[nparams] = declare_localvar(ls, &typenames[nparams]);
nparams++;
break;
}
@ -1205,7 +1221,7 @@ static void parlist (LexState *ls) {
ravitype_t tt = raviY_get_register_typeinfo(fs, i);
DEBUG_VARS(raviY_printf(fs, "Parameter [%d] = %v\n", i + 1, getlocvar(fs, i)));
/* do we need to convert ? */
ravi_code_typecoersion(ls, i, tt);
ravi_code_typecoersion(ls, i, tt, i < nparams ? typenames[i] : NULL);
}
}
@ -1331,7 +1347,7 @@ static void ravi_typecheck(LexState *ls, expdesc *v, int *vars, int nvars,
int i;
for (i = n; i < (n + nrets); i++)
/* do we need to convert ? */
ravi_code_typecoersion(ls, a + (i - n), vars[i]);
ravi_code_typecoersion(ls, a + (i - n), vars[i], NULL);
} else if ((vartype == RAVI_TNUMFLT || vartype == RAVI_TNUMINT) &&
v->k == VINDEXED) {
if ((vartype == RAVI_TNUMFLT && v->ravi_type != RAVI_TARRAYFLT) ||
@ -1542,6 +1558,8 @@ static UnOpr getunopr (int op) {
case TK_TO_INTARRAY: return OPR_TO_INTARRAY;
case TK_TO_NUMARRAY: return OPR_TO_NUMARRAY;
case TK_TO_TABLE: return OPR_TO_TABLE;
case '@':
return OPR_TO_TYPE;
default: return OPR_NOUNOPR;
}
}
@ -1605,9 +1623,10 @@ static BinOpr subexpr (LexState *ls, expdesc *v, int limit) {
uop = getunopr(ls->t.token);
if (uop != OPR_NOUNOPR) {
int line = ls->linenumber;
TString *typename = uop == OPR_TO_TYPE ? ls->t.seminfo.ts : NULL;
luaX_next(ls);
subexpr(ls, v, UNARY_PRIORITY);
luaK_prefix(ls->fs, uop, v, line);
luaK_prefix(ls->fs, uop, v, line, typename);
}
else {
simpleexp(ls, v);
@ -2106,10 +2125,11 @@ static void localstat (LexState *ls) {
*/
enum { N = MAXVARS + 10 };
int vars[N] = { 0 };
TString *typenames[N] = { NULL };
do {
/* RAVI changes start */
/* local name : type = value */
vars[nvars] = declare_localvar(ls);
vars[nvars] = declare_localvar(ls, &typenames[nvars]);
/* RAVI changes end */
nvars++;
if (nvars >= N)

@ -2212,6 +2212,15 @@ int luaV_execute (lua_State *L) {
luaG_runerror(L, "number[] expected");
vmbreak;
}
vmcase(OP_RAVI_TOSTRING) {
vmbreak;
}
vmcase(OP_RAVI_TOCLOSURE) {
vmbreak;
}
vmcase(OP_RAVI_TOTYPE) {
vmbreak;
}
}
}
}

Loading…
Cancel
Save