Finish type maps

pull/213/head
XmiliaH 3 years ago
parent 6af3d804a4
commit 7789f4f32d

@ -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) { CClosure **owner, UpVal **uv, ravi_type_map *type) {
*type = RAVI_TANY; *type = RAVI_TM_ANY;
switch (ttype(fi)) { switch (ttype(fi)) {
case LUA_TCCL: { /* C closure */ case LUA_TCCL: { /* C closure */
CClosure *f = clCvalue(fi); CClosure *f = clCvalue(fi);
@ -1586,7 +1586,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;
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 */
@ -1596,7 +1596,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;
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);
@ -1608,14 +1608,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 */
lua_lock(L); lua_lock(L);
fi = index2addr(L, funcindex); fi = index2addr(L, funcindex);
api_checknelems(L, 1); api_checknelems(L, 1);
@ -1625,21 +1624,12 @@ LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {
** 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
*/ */
if ( type == RAVI_TNUMFLT
|| type == RAVI_TNUMINT StkId input = L->top - 1;
|| type == RAVI_TARRAYFLT int compatible = ravi_checktype(input, type);
|| type == RAVI_TARRAYINT) {
StkId input = L->top - 1; if (!compatible)
int compatible = name = NULL;
(type == RAVI_TNUMFLT && ttisfloat(input))
|| (type == RAVI_TNUMINT && ttisinteger(input))
|| (type == RAVI_TARRAYFLT && ttisfarray(input))
|| (type == RAVI_TARRAYINT && ttisiarray(input))
|| (type == RAVI_TTABLE && ttisLtable(input))
;
if (!compatible)
name = NULL;
}
} }
if (name) { if (name) {
L->top--; L->top--;
@ -1652,13 +1642,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 */
} }
@ -1686,7 +1676,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) {

@ -621,7 +621,7 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) {
else else
op = OP_GETTABUP; /* 't' is in an upvalue */ op = OP_GETTABUP; /* 't' is in an upvalue */
} }
uint32_t result_type = 0; ravi_type_map result_type = 0;
if (e->ravi_type_map & (~(RAVI_TM_INTEGER_ARRAY | RAVI_TM_FLOAT_ARRAY))) { if (e->ravi_type_map & (~(RAVI_TM_INTEGER_ARRAY | RAVI_TM_FLOAT_ARRAY))) {
result_type = RAVI_TM_ANY; result_type = RAVI_TM_ANY;
} else { } else {
@ -683,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;
} }
@ -862,7 +862,6 @@ int luaK_exp2RK (FuncState *fs, expdesc *e) {
} }
static void check_valid_store(FuncState *fs, expdesc *var, expdesc *ex) { static void check_valid_store(FuncState *fs, expdesc *var, expdesc *ex) {
lua_assert(var->ravi_type_map == RAVI_TM_ANY || (var->ravi_type_map != 0 && (var->ravi_type_map & (var->ravi_type_map - 1)) == 0));
/* VNONRELOC means we have fixed register and do we know the type? */ /* VNONRELOC means we have fixed register and do we know the type? */
if (ex->k == VNONRELOC && if (ex->k == VNONRELOC &&
(var->ravi_type_map == RAVI_TM_FLOAT || (var->ravi_type_map == RAVI_TM_FLOAT ||
@ -876,8 +875,18 @@ static void check_valid_store(FuncState *fs, expdesc *var, expdesc *ex) {
/* handled by MOVEI, MOVEF, MOVEIARRAY, MOVEFARRAY at runtime */ /* handled by MOVEI, MOVEF, MOVEIARRAY, MOVEFARRAY at runtime */
return; return;
} }
ravi_type_map ex_ravi_type_map = ex->ravi_type_map;
if (ex->k == VINDEXED) {
if (ex_ravi_type_map == RAVI_TM_INTEGER_ARRAY) {
ex_ravi_type_map = RAVI_TM_INTEGER;
} else if (ex_ravi_type_map == RAVI_TM_FLOAT_ARRAY) {
ex_ravi_type_map = RAVI_TM_FLOAT;
} else {
ex_ravi_type_map = RAVI_TM_ANY;
}
}
if (var->ravi_type_map == RAVI_TM_FLOAT) { if (var->ravi_type_map == RAVI_TM_FLOAT) {
if (ex->ravi_type_map == RAVI_TM_FLOAT) if (ex_ravi_type_map == RAVI_TM_FLOAT)
return; return;
luaX_syntaxerror( luaX_syntaxerror(
fs->ls, fs->ls,
@ -886,7 +895,7 @@ static void check_valid_store(FuncState *fs, expdesc *var, expdesc *ex) {
"Invalid assignment: number expected")); "Invalid assignment: number expected"));
} }
else if (var->ravi_type_map == RAVI_TM_INTEGER) { else if (var->ravi_type_map == RAVI_TM_INTEGER) {
if (ex->ravi_type_map == RAVI_TM_INTEGER) if (ex_ravi_type_map == RAVI_TM_INTEGER)
return; return;
luaX_syntaxerror( luaX_syntaxerror(
fs->ls, fs->ls,
@ -894,8 +903,8 @@ 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_map & (~(RAVI_TM_INTEGER_ARRAY | RAVI_TM_FLOAT_ARRAY | RAVI_TM_TABLE)) == 0) { else if ((var->ravi_type_map & (~(RAVI_TM_INTEGER_ARRAY | RAVI_TM_FLOAT_ARRAY | RAVI_TM_TABLE))) == 0) {
if (ex->ravi_type_map == var->ravi_type_map) if (ex_ravi_type_map == var->ravi_type_map)
return; return;
luaX_syntaxerror( luaX_syntaxerror(
fs->ls, fs->ls,
@ -905,7 +914,7 @@ static void check_valid_store(FuncState *fs, expdesc *var, expdesc *ex) {
var->ravi_type_map == RAVI_TM_TABLE ? "table" : (var->ravi_type_map == RAVI_TM_FLOAT_ARRAY ? "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_map == (RAVI_TM_STRING | RAVI_TM_NIL)) { else if (var->ravi_type_map == (RAVI_TM_STRING | RAVI_TM_NIL)) {
if ((ex->ravi_type_map & ~(RAVI_TM_STRING | RAVI_TM_NIL)) == 0) if ((ex_ravi_type_map & ~(RAVI_TM_STRING | RAVI_TM_NIL)) == 0)
return; return;
luaX_syntaxerror( luaX_syntaxerror(
fs->ls, fs->ls,
@ -914,7 +923,7 @@ static void check_valid_store(FuncState *fs, expdesc *var, expdesc *ex) {
"Invalid assignment: string expected")); "Invalid assignment: string expected"));
} }
else if (var->ravi_type_map == (RAVI_TM_FUNCTION | RAVI_TM_NIL)) { else if (var->ravi_type_map == (RAVI_TM_FUNCTION | RAVI_TM_NIL)) {
if ((ex->ravi_type_map & ~(RAVI_TM_FUNCTION | RAVI_TM_NIL)) == 0) if ((ex_ravi_type_map & ~(RAVI_TM_FUNCTION | RAVI_TM_NIL)) == 0)
return; return;
luaX_syntaxerror( luaX_syntaxerror(
fs->ls, fs->ls,
@ -923,8 +932,8 @@ static void check_valid_store(FuncState *fs, expdesc *var, expdesc *ex) {
"Invalid assignment: function expected")); "Invalid assignment: function expected"));
} }
else if (var->ravi_type_map == (RAVI_TM_USERDATA | RAVI_TM_NIL)) { else if (var->ravi_type_map == (RAVI_TM_USERDATA | RAVI_TM_NIL)) {
if ((ex->ravi_type_map & ~(RAVI_TM_USERDATA | RAVI_TM_NIL)) == 0 && if ((ex_ravi_type_map & ~(RAVI_TM_USERDATA | RAVI_TM_NIL)) == 0 &&
(!(ex->ravi_type_map & RAVI_TM_USERDATA) || (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,
@ -936,12 +945,11 @@ static void check_valid_store(FuncState *fs, expdesc *var, expdesc *ex) {
static OpCode check_valid_setupval(FuncState *fs, expdesc *var, expdesc *ex, static OpCode check_valid_setupval(FuncState *fs, expdesc *var, expdesc *ex,
int reg) { int reg) {
lua_assert(var->ravi_type_map == RAVI_TM_ANY || (var->ravi_type_map != 0 && (var->ravi_type_map & (var->ravi_type_map - 1)) == 0));
OpCode op = OP_SETUPVAL; OpCode op = OP_SETUPVAL;
if ((var->ravi_type_map == RAVI_TM_INTEGER || var->ravi_type_map == RAVI_TM_FLOAT || if ((var->ravi_type_map == RAVI_TM_INTEGER || var->ravi_type_map == RAVI_TM_FLOAT ||
var->ravi_type_map == RAVI_TM_INTEGER_ARRAY || var->ravi_type_map == RAVI_TM_FLOAT_ARRAY || var->ravi_type_map == RAVI_TM_INTEGER_ARRAY || var->ravi_type_map == RAVI_TM_FLOAT_ARRAY ||
var->ravi_type_map == RAVI_TM_TABLE || var->ravi_type_map == RAVI_TM_STRING | RAVI_TM_NIL || var->ravi_type_map == RAVI_TM_TABLE || var->ravi_type_map == (RAVI_TM_STRING | RAVI_TM_NIL) ||
var->ravi_type_map == RAVI_TM_FUNCTION | RAVI_TM_NIL || var->ravi_type_map == RAVI_TM_USERDATA | RAVI_TM_NIL) && var->ravi_type_map == (RAVI_TM_FUNCTION | RAVI_TM_NIL) || var->ravi_type_map == (RAVI_TM_USERDATA | RAVI_TM_NIL)) &&
ex->ravi_type_map & ~var->ravi_type_map) { ex->ravi_type_map & ~var->ravi_type_map) {
if (var->ravi_type_map == RAVI_TM_INTEGER) if (var->ravi_type_map == RAVI_TM_INTEGER)
op = OP_RAVI_SETUPVALI; op = OP_RAVI_SETUPVALI;
@ -953,21 +961,27 @@ static OpCode check_valid_setupval(FuncState *fs, expdesc *var, expdesc *ex,
op = OP_RAVI_SETUPVAL_FARRAY; op = OP_RAVI_SETUPVAL_FARRAY;
else if (var->ravi_type_map == RAVI_TM_TABLE) else if (var->ravi_type_map == RAVI_TM_TABLE)
op = OP_RAVI_SETUPVALT; op = OP_RAVI_SETUPVALT;
else if (var->ravi_type_map == RAVI_TM_STRING | RAVI_TM_NIL) 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_map == RAVI_TM_FUNCTION | RAVI_TM_NIL) 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_map == RAVI_TM_USERDATA | RAVI_TM_NIL) { 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;
} }
@ -976,9 +990,9 @@ static OpCode check_valid_setupval(FuncState *fs, expdesc *var, expdesc *ex,
void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {
switch (var->k) { switch (var->k) {
case VLOCAL: { case VLOCAL: {
check_valid_store(fs, var, ex);
freeexp(fs, ex); freeexp(fs, ex);
exp2reg(fs, ex, var->u.info); /* compute 'ex' into proper place */ exp2reg(fs, ex, var->u.info); /* compute 'ex' into proper place */
check_valid_store(fs, var, ex);
return; return;
} }
case VUPVAL: { case VUPVAL: {
@ -1535,17 +1549,17 @@ static void code_type_assertion(FuncState *fs, UnOpr op, expdesc *e, TString *us
opcode = OP_RAVI_TOTAB; opcode = OP_RAVI_TOTAB;
tm = RAVI_TM_TABLE; tm = RAVI_TM_TABLE;
} }
else if (op == OPR_TO_STRING && e->ravi_type_map != RAVI_TM_STRING) { 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;
tm = RAVI_TM_STRING; tm = RAVI_TM_STRING | RAVI_TM_NIL;
} }
else if (op == OPR_TO_CLOSURE && e->ravi_type_map != RAVI_TM_FUNCTION) { 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;
tm = RAVI_TM_FUNCTION; 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;
tm = RAVI_TM_USERDATA; tm = RAVI_TM_USERDATA | RAVI_TM_NIL;
} }
else { else {
/* nothing to do*/ /* nothing to do*/
@ -1646,7 +1660,11 @@ 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);
e2->ravi_type_map |= e1->ravi_type_map & RAVI_TM_FALSISH; if (e1->ravi_type_map & RAVI_TM_TRUISH) {
e2->ravi_type_map |= e1->ravi_type_map & RAVI_TM_FALSISH;
} else {
e2->ravi_type_map = e1->ravi_type_map & RAVI_TM_FALSISH;
}
*e1 = *e2; *e1 = *e2;
break; break;
} }
@ -1658,7 +1676,11 @@ void luaK_posfix (FuncState *fs, BinOpr op,
if (e1->usertype != e2->usertype) if (e1->usertype != e2->usertype)
e2->usertype = NULL; e2->usertype = NULL;
} }
e2->ravi_type_map |= e1->ravi_type_map & RAVI_TM_TRUISH; if (e1->ravi_type_map & RAVI_TM_FALSISH) {
e2->ravi_type_map |= e1->ravi_type_map & RAVI_TM_TRUISH;
} else {
e2->ravi_type_map = e1->ravi_type_map & RAVI_TM_TRUISH;
}
*e1 = *e2; *e1 = *e2;
break; break;
} }

@ -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) { StkId *pos, ravi_type_map *type) {
const char *name = NULL; const char *name = NULL;
StkId base; StkId base;
*type = RAVI_TANY; *type = RAVI_TM_ANY;
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);
@ -175,7 +175,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;
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? */
@ -201,7 +201,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;
int compatible = 1; int compatible = 1;
lua_lock(L); lua_lock(L);
swapextra(L); swapextra(L);
@ -211,15 +211,8 @@ LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
** 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
*/ */
if (type == RAVI_TNUMFLT || type == RAVI_TNUMINT || type == RAVI_TARRAYFLT || type == RAVI_TARRAYINT) { StkId input = L->top - 1;
StkId input = L->top - 1; int compatible = ravi_checktype(input, type);
compatible = (type == RAVI_TNUMFLT && ttisfloat(input))
|| (type == RAVI_TNUMINT && ttisinteger(input))
|| (type == RAVI_TARRAYFLT && ttisfarray(input))
|| (type == RAVI_TARRAYINT && ttisiarray(input))
|| (type == RAVI_TTABLE && ttisLtable(input))
;
}
if (compatible) { if (compatible) {
setobjs2s(L, pos, L->top - 1); setobjs2s(L, pos, L->top - 1);
L->top--; /* pop value */ L->top--; /* pop value */
@ -456,7 +449,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;
*name = luaF_getlocalname(p, reg + 1, lastpc, &type); *name = luaF_getlocalname(p, reg + 1, lastpc, &type);
if (*name) /* is a local? */ if (*name) /* is a local? */
return "local"; return "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) { const char *luaF_getlocalname (const Proto *f, int local_number, int pc, ravi_type_map *type) {
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,12 +251,12 @@ 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;
return getstr(f->locvars[i].varname); return getstr(f->locvars[i].varname);
} }
} }
} }
*type = RAVI_TANY; *type = RAVI_TM_ANY;
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); int pc, ravi_type_map* type);
#endif #endif

@ -33,6 +33,22 @@
LUAI_DDEF const TValue luaO_nilobject_ = {NILCONSTANT}; LUAI_DDEF const TValue luaO_nilobject_ = {NILCONSTANT};
int ravi_checktype(StkId input, ravi_type_map type) {
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;
// TODO if (type & RAVI_TM_USERDATA && )
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,6 @@ 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 {
RAVI_TANY = 0, /* Lua dynamic type */
RAVI_TNUMINT = 1, /* integer number */
RAVI_TNUMFLT, /* floating point number */
RAVI_TARRAYINT, /* array of ints */
RAVI_TARRAYFLT, /* array of doubles */
RAVI_TFUNCTION, /* Lua or C Function */
RAVI_TTABLE, /* Lua table */
RAVI_TSTRING, /* string */
RAVI_TNIL, /* NIL */
RAVI_TBOOLEAN, /* boolean */
RAVI_TUSERDATA /* userdata or lightuserdata */
} ravitype_t;
typedef enum { typedef enum {
RAVI_TI_NIL, RAVI_TI_NIL,
@ -83,18 +70,20 @@ typedef enum {
RAVI_TI_OTHER RAVI_TI_OTHER
} ravi_type_index; } ravi_type_index;
#define RAVI_TM_NIL (1<<RAVI_TI_NIL) typedef uint32_t ravi_type_map;
#define RAVI_TM_FALSE (1<<RAVI_TI_FALSE)
#define RAVI_TM_TRUE (1<<RAVI_TI_TRUE) #define RAVI_TM_NIL (((uint32_t)1)<<RAVI_TI_NIL)
#define RAVI_TM_INTEGER (1<<RAVI_TI_INTEGER) #define RAVI_TM_FALSE (((uint32_t)1)<<RAVI_TI_FALSE)
#define RAVI_TM_FLOAT (1<<RAVI_TI_FLOAT) #define RAVI_TM_TRUE (((uint32_t)1)<<RAVI_TI_TRUE)
#define RAVI_TM_INTEGER_ARRAY (1<<RAVI_TI_INTEGER_ARRAY) #define RAVI_TM_INTEGER (((uint32_t)1)<<RAVI_TI_INTEGER)
#define RAVI_TM_FLOAT_ARRAY (1<<RAVI_TI_FLOAT_ARRAY) #define RAVI_TM_FLOAT (((uint32_t)1)<<RAVI_TI_FLOAT)
#define RAVI_TM_TABLE (1<<RAVI_TI_TABLE) #define RAVI_TM_INTEGER_ARRAY (((uint32_t)1)<<RAVI_TI_INTEGER_ARRAY)
#define RAVI_TM_STRING (1<<RAVI_TI_STRING) #define RAVI_TM_FLOAT_ARRAY (((uint32_t)1)<<RAVI_TI_FLOAT_ARRAY)
#define RAVI_TM_FUNCTION (1<<RAVI_TI_FUNCTION) #define RAVI_TM_TABLE (((uint32_t)1)<<RAVI_TI_TABLE)
#define RAVI_TM_USERDATA (1<<RAVI_TI_USERDATA) #define RAVI_TM_STRING (((uint32_t)1)<<RAVI_TI_STRING)
#define RAVI_TM_OTHER (1<<RAVI_TI_OTHER) #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_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)
@ -467,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 */
uint16_t ravi_type_map; /* 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;
@ -482,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 */
uint32_t ravi_type_map; /* 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 */
@ -870,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(StkId input, ravi_type_map type);
#endif #endif

@ -66,33 +66,6 @@ typedef struct BlockCnt {
/* RAVI set debug level */ /* RAVI set debug level */
void ravi_set_debuglevel(int level) { ravi_parser_debug = level; } void ravi_set_debuglevel(int level) { ravi_parser_debug = level; }
/* RAVI - return the type name */
const char *raviY_typename(ravitype_t tt) {
switch (tt) {
case RAVI_TNIL:
return "nil";
case RAVI_TBOOLEAN:
return "boolean";
case RAVI_TNUMFLT:
return "number";
case RAVI_TNUMINT:
return "integer";
case RAVI_TSTRING:
return "string";
case RAVI_TFUNCTION:
return "function";
case RAVI_TARRAYINT:
return "integer[]";
case RAVI_TARRAYFLT:
return "number[]";
case RAVI_TUSERDATA:
return "userdata";
case RAVI_TTABLE:
return "table";
default:
return "?";
}
}
static char* raviY_buf_append(char* buf, const char* what) { static char* raviY_buf_append(char* buf, const char* what) {
char c; char c;
@ -102,9 +75,7 @@ static char* raviY_buf_append(char* buf, const char* what) {
return buf; return buf;
} }
#define RAVI_TYPEMAP_MAX_LEN (sizeof("nil|boolean|integer|number|integer[]|number[]|table|string|function|userdata|?|")) void raviY_typemap_string(uint32_t tm, char* buf) {
static void raviY_typemap_string(uint32_t tm, char* buf) {
if (tm == RAVI_TM_ANY) { if (tm == RAVI_TM_ANY) {
memcpy(buf, "any", 4); memcpy(buf, "any", 4);
return; return;
@ -112,8 +83,7 @@ static void raviY_typemap_string(uint32_t tm, char* buf) {
memcpy(buf, "?", 2); memcpy(buf, "?", 2);
return; return;
} }
buf[0] = '|'; char* start = buf;
buf++;
if (tm & RAVI_TM_NIL) { if (tm & RAVI_TM_NIL) {
buf = raviY_buf_append(buf, "nil|"); buf = raviY_buf_append(buf, "nil|");
} }
@ -153,12 +123,16 @@ static void raviY_typemap_string(uint32_t tm, char* buf) {
if (tm & RAVI_TM_OTHER) { if (tm & RAVI_TM_OTHER) {
buf = raviY_buf_append(buf, "?|"); buf = raviY_buf_append(buf, "?|");
} }
buf[-1] = 0; if (start == buf) {
memcpy(buf, "?", 2);
} else {
buf[-1] = 0;
}
} }
/* RAVI - prints a Lua expression node */ /* RAVI - prints a Lua expression node */
static void v(FILE *fp, FuncState *fs, const expdesc *e) { static void print_expdesc(FILE *fp, FuncState *fs, const expdesc *e) {
char buf[80] = {0v}; char buf[80] = {0};
char type_map_str[RAVI_TYPEMAP_MAX_LEN]; char type_map_str[RAVI_TYPEMAP_MAX_LEN];
raviY_typemap_string(e->ravi_type_map, type_map_str); raviY_typemap_string(e->ravi_type_map, type_map_str);
switch (e->k) { switch (e->k) {
@ -187,10 +161,14 @@ static void v(FILE *fp, FuncState *fs, const expdesc *e) {
type_map_str); type_map_str);
break; break;
case VNONRELOC: case VNONRELOC:
{
char var_type_map_str[RAVI_TYPEMAP_MAX_LEN];
raviY_typemap_string(raviY_get_register_typeinfo(fs, e->u.info, NULL), var_type_map_str);
fprintf(fp, "{p=%p, k=VNONRELOC, register=%d %s, type=%s, pc=%d}", e, e->u.info, fprintf(fp, "{p=%p, k=VNONRELOC, register=%d %s, type=%s, pc=%d}", e, e->u.info,
raviY_typename(raviY_get_register_typeinfo(fs, e->u.info, NULL)), var_type_map_str,
type_map_str, type_map_str,
e->pc); e->pc);
}
break; break;
case VLOCAL: case VLOCAL:
fprintf(fp, "{p=%p, k=VLOCAL, register=%d, type=%s}", e, e->u.info, fprintf(fp, "{p=%p, k=VLOCAL, register=%d, type=%s}", e, e->u.info,
@ -221,11 +199,15 @@ static void v(FILE *fp, FuncState *fs, const expdesc *e) {
e->pc); e->pc);
break; break;
case VCALL: case VCALL:
{
char var_type_map_str[RAVI_TYPEMAP_MAX_LEN];
raviY_typemap_string(raviY_get_register_typeinfo(fs, GETARG_A(getinstruction(fs, e)), NULL), var_type_map_str);
fprintf( fprintf(
fp, "{p=%p, k=VCALL, pc=%d, instruction=(%s %s), type=%s}", e, fp, "{p=%p, k=VCALL, pc=%d, instruction=(%s %s), type=%s}", e,
e->u.info, raviP_instruction_to_str(buf, sizeof buf, getinstruction(fs, e)), e->u.info, raviP_instruction_to_str(buf, sizeof buf, getinstruction(fs, e)),
raviY_typename(raviY_get_register_typeinfo(fs, GETARG_A(getinstruction(fs, e)), NULL)), var_type_map_str,
type_map_str); type_map_str);
}
break; break;
case VVARARG: case VVARARG:
fprintf(fp, "{p=%p, k=VVARARG, pc=%d, instruction=(%s), type=%s}", e, fprintf(fp, "{p=%p, k=VVARARG, pc=%d, instruction=(%s), type=%s}", e,
@ -280,9 +262,11 @@ void raviY_printf(FuncState *fs, const char *format, ...) {
printf("%f", d); printf("%f", d);
cp++; cp++;
} else if (cp[0] == '%' && cp[1] == 't') { } else if (cp[0] == '%' && cp[1] == 't') {
ravitype_t i; ravi_type_map i;
i = va_arg(ap, ravitype_t); char type_map_str[RAVI_TYPEMAP_MAX_LEN];
fputs(raviY_typename(i), stdout); i = va_arg(ap, ravi_type_map);
raviY_typemap_string(i, type_map_str);
fputs(type_map_str, stdout);
cp++; cp++;
} else { } else {
fputc(*cp, stdout); fputc(*cp, stdout);
@ -410,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, uint32_t ravi_type_map, TString *usertype) { static int registerlocalvar (LexState *ls, TString *varname, ravi_type_map ravi_type_map, TString *usertype) {
FuncState *fs = ls->fs; FuncState *fs = ls->fs;
Proto *f = fs->f; Proto *f = fs->f;
int oldsize = f->sizelocvars; int oldsize = f->sizelocvars;
@ -433,7 +417,7 @@ static int registerlocalvar (LexState *ls, TString *varname, uint32_t ravi_type_
/* create a new local variable in function scope, and set the /* create a new local variable in function scope, and set the
* variable type (RAVI - added type tt) */ * variable type (RAVI - added type tt) */
static void new_localvar (LexState *ls, TString *name, uint32_t tm, TString *usertype) { static void new_localvar (LexState *ls, TString *name, ravi_type_map tm, TString *usertype) {
FuncState *fs = ls->fs; FuncState *fs = ls->fs;
Dyndata *dyd = ls->dyd; Dyndata *dyd = ls->dyd;
/* register variable and get its index */ /* register variable and get its index */
@ -491,7 +475,7 @@ static int register_to_locvar_index(FuncState *fs, int reg) {
* return the type associated with the variable. * return the type associated with the variable.
* This is a RAVI function * This is a RAVI function
*/ */
uint32_t raviY_get_register_typeinfo(FuncState *fs, int reg, TString **pusertype) { ravi_type_map raviY_get_register_typeinfo(FuncState *fs, int reg, TString **pusertype) {
int idx; int idx;
LocVar *v; LocVar *v;
/* Due to the way Lua parser works it is not safe to look beyond nactvar */ /* Due to the way Lua parser works it is not safe to look beyond nactvar */
@ -603,7 +587,7 @@ static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
if (v >= 0) { /* found? */ if (v >= 0) { /* found? */
/* RAVI set type of local var / expr if possible */ /* RAVI set type of local var / expr if possible */
TString *usertype = NULL; TString *usertype = NULL;
uint32_t tt = raviY_get_register_typeinfo(fs, v, &usertype); ravi_type_map tt = raviY_get_register_typeinfo(fs, v, &usertype);
init_exp(var, VLOCAL, v, tt, usertype); /* variable is local, RAVI set type */ init_exp(var, VLOCAL, v, tt, usertype); /* variable is local, RAVI set type */
if (!base) if (!base)
markupval(fs, v); /* local will be used as an upval */ markupval(fs, v); /* local will be used as an upval */
@ -641,7 +625,7 @@ 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, uint32_t ravi_type_map, TString *typename /* only if tt is USERDATA */) { static void ravi_code_typecoersion(LexState *ls, int reg, ravi_type_map ravi_type_map, 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 (ravi_type_map == RAVI_TM_FLOAT || ravi_type_map == RAVI_TM_INTEGER)
/* code an instruction to convert in place */ /* code an instruction to convert in place */
@ -661,7 +645,7 @@ static void ravi_code_typecoersion(LexState *ls, int reg, uint32_t ravi_type_map
else if (ravi_type_map == (RAVI_TM_STRING | RAVI_TM_NIL)) else if (ravi_type_map == (RAVI_TM_STRING | RAVI_TM_NIL))
luaK_codeABC(ls->fs, OP_RAVI_TOSTRING, luaK_codeABC(ls->fs, OP_RAVI_TOSTRING,
reg, 0, 0); reg, 0, 0);
else if (ravi_type_map == RAVI_TM_FUNCTION | RAVI_TM_NIL) else if (ravi_type_map == (RAVI_TM_FUNCTION | RAVI_TM_NIL))
luaK_codeABC(ls->fs, OP_RAVI_TOCLOSURE, luaK_codeABC(ls->fs, OP_RAVI_TOCLOSURE,
reg, 0, 0); reg, 0, 0);
// TODO coerse to boolean // TODO coerse to boolean
@ -671,19 +655,17 @@ static void ravi_code_typecoersion(LexState *ls, int reg, uint32_t ravi_type_map
For array and table types however raise an error as uninitialized value For array and table types however raise an error as uninitialized value
would cause a null pointer and therefore memory fault would cause a null pointer and therefore memory fault
*/ */
static void ravi_code_setzero(FuncState *fs, int reg, ravitype_t ravi_type, TString *usertype) { static void ravi_code_setzero(FuncState *fs, int reg, ravi_type_map ravi_type, TString *usertype) {
(void) usertype; (void) usertype;
if (ravi_type == RAVI_TM_FLOAT || ravi_type == RAVI_TM_INTEGER) if (ravi_type == RAVI_TM_FLOAT || ravi_type == RAVI_TM_INTEGER)
/* code an instruction to convert in place */ /* code an instruction to convert in place */
luaK_codeABC(fs, ravi_type == RAVI_TM_FLOAT ? OP_RAVI_LOADFZ : OP_RAVI_LOADIZ, reg, 0, 0); luaK_codeABC(fs, ravi_type == RAVI_TM_FLOAT ? OP_RAVI_LOADFZ : OP_RAVI_LOADIZ, reg, 0, 0);
else if (~(ravi_type & RAVI_TM_NIL)) else if ((ravi_type & RAVI_TM_NIL) == 0) {
luaX_syntaxerror(fs->ls, "uninitialized number[] in local variable"); // TODO char type_map_str[RAVI_TYPEMAP_MAX_LEN];
else if (ravi_type == RAVI_TM_FLOAT_ARRAY) raviY_typemap_string(ravi_type, type_map_str);
luaX_syntaxerror(fs->ls, "uninitialized number[] in local variable");
else if (ravi_type == RAVI_TM_INTEGER_ARRAY) luaX_syntaxerror(fs->ls, luaO_pushfstring(fs->ls->L, "uninitialized %s in local variable", type_map_str));
luaX_syntaxerror(fs->ls, "uninitialized integer[] in local variable"); }
else if (ravi_type == RAVI_TM_TABLE)
luaX_syntaxerror(fs->ls, "uninitialized table in local variable");
} }
@ -713,7 +695,7 @@ 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);
uint32_t ravi_type_map = ls->fs->f->locvars[idx].ravi_type_map; /* get variable's type */ ravi_type_map ravi_type_map = ls->fs->f->locvars[idx].ravi_type_map; /* get variable's type */
TString *usertype = ls->fs->f->locvars[idx].usertype; TString *usertype = ls->fs->f->locvars[idx].usertype;
/* do we need to convert ? */ /* do we need to convert ? */
ravi_code_typecoersion(ls, i, ravi_type_map, usertype); ravi_code_typecoersion(ls, i, ravi_type_map, usertype);
@ -730,7 +712,7 @@ 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);
uint32_t ravi_type_map = fs->f->locvars[idx].ravi_type_map; /* get variable's type */ ravi_type_map ravi_type_map = fs->f->locvars[idx].ravi_type_map; /* get variable's type */
TString *usertype = fs->f->locvars[idx].usertype; TString *usertype = fs->f->locvars[idx].usertype;
/* do we need to convert ? */ /* do we need to convert ? */
ravi_code_setzero(fs, i, ravi_type_map, usertype); ravi_code_setzero(fs, i, ravi_type_map, usertype);
@ -1279,11 +1261,11 @@ static TString *user_defined_type_name(LexState *ls, TString *typename) {
* where type is 'integer', 'integer[]', * where type is 'integer', 'integer[]',
* 'number', 'number[]' * 'number', 'number[]'
*/ */
static ravitype_t declare_localvar(LexState *ls, TString **pusertype) { static ravi_type_map declare_localvar(LexState *ls, TString **pusertype) {
/* RAVI change - add type */ /* RAVI change - add type */
TString *name = str_checkname(ls); TString *name = str_checkname(ls);
/* assume a dynamic type */ /* assume a dynamic type */
ravitype_t tm = RAVI_TM_ANY; ravi_type_map tm = RAVI_TM_ANY;
/* if the variable name is followed by a colon then we have a type /* if the variable name is followed by a colon then we have a type
* specifier * specifier
*/ */
@ -1333,7 +1315,7 @@ static void parlist (LexState *ls) {
Proto *f = fs->f; Proto *f = fs->f;
int nparams = 0; int nparams = 0;
enum { N = MAXVARS + 10 }; enum { N = MAXVARS + 10 };
int vars[N] = { 0 }; ravi_type_map vars[N] = { 0 };
TString *typenames[N] = { NULL }; TString *typenames[N] = { NULL };
f->is_vararg = 0; f->is_vararg = 0;
if (ls->t.token != ')') { /* is 'parlist' not empty? */ if (ls->t.token != ')') { /* is 'parlist' not empty? */
@ -1359,12 +1341,12 @@ static void parlist (LexState *ls) {
luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */
for (int i = 0; i < f->numparams; i++) { for (int i = 0; i < f->numparams; i++) {
TString *usertype = NULL; TString *usertype = NULL;
ravitype_t tt = raviY_get_register_typeinfo(fs, i, &usertype); ravi_type_map tm = raviY_get_register_typeinfo(fs, i, &usertype);
lua_assert((i < nparams && vars[i] == (int)tt) || 1); lua_assert((i < nparams && vars[i] == tm) || 1);
lua_assert((i < nparams && usertype == typenames[i]) || 1); lua_assert((i < nparams && usertype == typenames[i]) || 1);
DEBUG_VARS(raviY_printf(fs, "Parameter [%d] = %v\n", i + 1, getlocvar(fs, i))); DEBUG_VARS(raviY_printf(fs, "Parameter [%d] = %v\n", i + 1, getlocvar(fs, i)));
/* do we need to convert ? */ /* do we need to convert ? */
ravi_code_typecoersion(ls, i, tt, usertype); ravi_code_typecoersion(ls, i, tm, usertype);
} }
} }
@ -1433,13 +1415,12 @@ static int explist (LexState *ls, expdesc *v) {
* 'v' may be a function call returning multiple values, in which case * 'v' may be a function call returning multiple values, in which case
* we need to check all returned values against the expected types. * we need to check all returned values against the expected types.
*/ */
static void ravi_typecheck(LexState *ls, expdesc *v, int *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 */
ravitype_t vartype = var_types[n]; ravi_type_map vartype = var_types[n];
if (n < nvars && vartype != RAVI_TANY && v->ravi_type != vartype) { if (n < nvars && (v->ravi_type_map & ~vartype)) {
if (v->ravi_type != vartype && if ((vartype == RAVI_TM_FLOAT_ARRAY || vartype == RAVI_TM_INTEGER_ARRAY) &&
(vartype == RAVI_TARRAYFLT || vartype == RAVI_TARRAYINT) &&
v->k == VNONRELOC) { v->k == VNONRELOC) {
/* as the bytecode for generating a table is already emitted by this stage /* 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 * we have to amend the generated byte code - not sure if there is a
@ -1458,7 +1439,7 @@ static void ravi_typecheck(LexState *ls, expdesc *v, int *var_types,
int reg = GETARG_A(*pc); int reg = GETARG_A(*pc);
if (reg == if (reg ==
v->u.info) { /* double check that register is as expected */ v->u.info) { /* double check that register is as expected */
op = (vartype == RAVI_TARRAYINT) ? OP_RAVI_NEW_IARRAY op = (vartype == RAVI_TM_INTEGER_ARRAY) ? OP_RAVI_NEW_IARRAY
: OP_RAVI_NEW_FARRAY; : OP_RAVI_NEW_FARRAY;
SET_OPCODE(*pc, op); /* modify opcode */ SET_OPCODE(*pc, op); /* modify opcode */
DEBUG_CODEGEN( DEBUG_CODEGEN(
@ -1471,11 +1452,10 @@ static void ravi_typecheck(LexState *ls, expdesc *v, int *var_types,
luaX_syntaxerror(ls, "expecting array initializer"); luaX_syntaxerror(ls, "expecting array initializer");
} }
/* if we are calling a function then convert return types */ /* if we are calling a function then convert return types */
else if (v->ravi_type != vartype && else if ((vartype == RAVI_TM_FLOAT || vartype == RAVI_TM_INTEGER ||
(vartype == RAVI_TNUMFLT || vartype == RAVI_TNUMINT || vartype == RAVI_TM_FLOAT_ARRAY || vartype == RAVI_TM_INTEGER_ARRAY ||
vartype == RAVI_TARRAYFLT || vartype == RAVI_TARRAYINT || vartype == RAVI_TM_TABLE || vartype == (RAVI_TM_STRING | RAVI_TM_NIL) ||
vartype == RAVI_TTABLE || vartype == RAVI_TSTRING || vartype == (RAVI_TM_FUNCTION | RAVI_TM_NIL) || vartype == (RAVI_TM_USERDATA | RAVI_TM_NIL)) &&
vartype == RAVI_TFUNCTION || vartype == RAVI_TUSERDATA) &&
v->k == VCALL) { v->k == VCALL) {
/* For local variable declarations that call functions e.g. /* For local variable declarations that call functions e.g.
* local i = func() * local i = func()
@ -1502,15 +1482,15 @@ static void ravi_typecheck(LexState *ls, expdesc *v, int *var_types,
/* do we need to convert ? */ /* do we need to convert ? */
ravi_code_typecoersion(ls, a + (i - n), var_types[i], NULL); ravi_code_typecoersion(ls, a + (i - n), var_types[i], NULL);
} }
else if ((vartype == RAVI_TNUMFLT || vartype == RAVI_TNUMINT) && else if ((vartype == RAVI_TM_FLOAT || vartype == RAVI_TM_INTEGER) &&
v->k == VINDEXED) { v->k == VINDEXED) {
if ((vartype == RAVI_TNUMFLT && v->ravi_type != RAVI_TARRAYFLT) || if ((vartype == RAVI_TM_FLOAT && v->ravi_type_map != RAVI_TM_FLOAT_ARRAY) ||
(vartype == RAVI_TNUMINT && v->ravi_type != RAVI_TARRAYINT)) (vartype == RAVI_TM_INTEGER && v->ravi_type_map != RAVI_TM_INTEGER_ARRAY))
luaX_syntaxerror(ls, "Invalid local assignment"); luaX_syntaxerror(ls, "Invalid local assignment");
} }
else if ((vartype == RAVI_TSTRING && v->ravi_type != RAVI_TSTRING) || else if ((vartype == (RAVI_TM_STRING | RAVI_TM_NIL) && v->ravi_type_map != RAVI_TM_STRING) ||
(vartype == RAVI_TFUNCTION && v->ravi_type != RAVI_TFUNCTION) || (vartype == (RAVI_TM_FUNCTION | RAVI_TM_NIL) && v->ravi_type_map != RAVI_TM_FUNCTION) ||
vartype == RAVI_TUSERDATA) { 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 TString *usertype = usertypes[n]; // NULL if var_types[n] is not userdata
/* we need to make sure that a register is assigned to 'v' /* we need to make sure that a register is assigned to 'v'
so that we can emit type assertion instructions. This would have so that we can emit type assertion instructions. This would have
@ -1530,7 +1510,7 @@ static void ravi_typecheck(LexState *ls, expdesc *v, int *var_types,
* types provided in vars array. This is a modified version of explist() to be * types provided in vars array. This is a modified version of explist() to be
* used to local variable declaration statement only. * used to local variable declaration statement only.
*/ */
static int localvar_explist(LexState *ls, expdesc *v, int *vars, TString** usertypes, int nvars) { static int localvar_explist(LexState *ls, expdesc *v, ravi_type_map *vars, TString** usertypes, int nvars) {
/* explist -> expr { ',' expr } */ /* explist -> expr { ',' expr } */
int n = 1; /* at least one expression */ int n = 1; /* at least one expression */
expr(ls, v); expr(ls, v);
@ -2323,7 +2303,7 @@ static void localstat (LexState *ls) {
* instead. * instead.
*/ */
enum { N = MAXVARS + 10 }; enum { N = MAXVARS + 10 };
int vars[N] = { 0 }; ravi_type_map vars[N] = { 0 };
TString *usertypes[N] = { NULL }; TString *usertypes[N] = { NULL };
do { do {
/* RAVI changes start */ /* RAVI changes start */

@ -243,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(uint32_t tm, char* buf);
/* Special printf that recognises following conversions: /* Special printf that recognises following conversions:
* %e - expdesc * * %e - expdesc *
@ -261,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;
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));

@ -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);
} }
} }

@ -2188,7 +2188,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;
@ -2196,7 +2196,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;
@ -2768,13 +2768,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);
} }

@ -1523,7 +1523,7 @@ print 'Test 58 OK'
function x(s1: string, s2: string) function x(s1: string, s2: string)
return @string( s1 .. s2 ) return @string( s1 .. s2 )
end end
check(x, 'TOSTRING', 'TOSTRING', 'MOVE', 'MOVE', 'CONCAT', 'RETURN', 'RETURN') check(x, 'TOSTRING', 'TOSTRING', 'MOVE', 'MOVE', 'CONCAT', 'TOSTRING', 'RETURN', 'RETURN')
assert(x('a', 'b') == 'ab') assert(x('a', 'b') == 'ab')
compile(x) compile(x)
assert(x('a', 'b') == 'ab') assert(x('a', 'b') == 'ab')

Loading…
Cancel
Save