From 6af3d804a4bc877d9acca737ef3b0d120a97b12a Mon Sep 17 00:00:00 2001 From: XmiliaH Date: Fri, 19 Feb 2021 13:36:15 +0100 Subject: [PATCH 1/6] First part for type maps --- src/lcode.c | 444 ++++++++++++++++++++++++-------------------------- src/lobject.h | 39 ++++- src/lparser.c | 300 +++++++++++++++++++++------------- src/lparser.h | 6 +- 4 files changed, 433 insertions(+), 356 deletions(-) diff --git a/src/lcode.c b/src/lcode.c index 2f88f9e..93438cd 100644 --- a/src/lcode.c +++ b/src/lcode.c @@ -600,32 +600,35 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) { freereg(fs, e->u.ind.t); /* TODO we should do this for upvalues too */ /* table access - set specialized op codes if array types are detected */ - if (e->ravi_type == RAVI_TARRAYFLT && e->u.ind.key_ravi_type == RAVI_TNUMINT) - op = OP_RAVI_FARRAY_GET; - else if (e->ravi_type == RAVI_TARRAYINT && e->u.ind.key_ravi_type == RAVI_TNUMINT) - op = OP_RAVI_IARRAY_GET; - /* Check that we have a short string constant */ - else if (e->ravi_type == RAVI_TTABLE && e->u.ind.key_ravi_type == RAVI_TSTRING && isshortstr(fs, e->u.ind.idx)) - op = OP_RAVI_TABLE_GETFIELD; - else if (e->u.ind.key_ravi_type == RAVI_TNUMINT) - op = OP_RAVI_GETI; - else if (e->u.ind.key_ravi_type == RAVI_TSTRING && isshortstr(fs, e->u.ind.idx)) - op = OP_RAVI_GETFIELD; - else + if (e->u.ind.key_ravi_type_map == RAVI_TM_INTEGER) { + if (e->ravi_type_map == RAVI_TM_FLOAT_ARRAY) { + op = OP_RAVI_FARRAY_GET; + } else if (e->ravi_type_map == RAVI_TM_INTEGER_ARRAY) { + op = OP_RAVI_IARRAY_GET; + } else { + op = OP_RAVI_GETI; + } + } else if (e->u.ind.key_ravi_type_map == RAVI_TM_STRING && isshortstr(fs, e->u.ind.idx)) { + op = e->ravi_type_map == RAVI_TM_TABLE ? OP_RAVI_TABLE_GETFIELD : OP_RAVI_GETFIELD; + } else { op = OP_GETTABLE; + } } else { lua_assert(e->u.ind.vt == VUPVAL); - if (e->u.ind.key_ravi_type == RAVI_TSTRING && isshortstr(fs, e->u.ind.idx)) + if (e->u.ind.key_ravi_type_map == RAVI_TM_STRING && isshortstr(fs, e->u.ind.idx)) op = OP_RAVI_GETTABUP_SK; else op = OP_GETTABUP; /* 't' is in an upvalue */ } - if (e->ravi_type == RAVI_TARRAYFLT || e->ravi_type == RAVI_TARRAYINT) - /* set the type of resulting expression */ - e->ravi_type = e->ravi_type == RAVI_TARRAYFLT ? RAVI_TNUMFLT : RAVI_TNUMINT; - else - e->ravi_type = RAVI_TANY; + uint32_t result_type = 0; + if (e->ravi_type_map & (~(RAVI_TM_INTEGER_ARRAY | RAVI_TM_FLOAT_ARRAY))) { + result_type = RAVI_TM_ANY; + } else { + if (e->ravi_type_map & RAVI_TM_INTEGER_ARRAY) result_type |= RAVI_TM_INTEGER; + if (e->ravi_type_map & RAVI_TM_FLOAT_ARRAY) result_type |= RAVI_TM_FLOAT; + } + e->ravi_type_map = result_type; e->u.info = luaK_codeABC(fs, op, 0, e->u.ind.t, e->u.ind.idx); e->k = VRELOCABLE; DEBUG_EXPR(raviY_printf(fs, "luaK_dischargevars (VINDEXED->VRELOCABLE) %e\n", e)); @@ -859,23 +862,22 @@ int luaK_exp2RK (FuncState *fs, expdesc *e) { } 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? */ if (ex->k == VNONRELOC && - (var->ravi_type == RAVI_TNUMFLT || - var->ravi_type == RAVI_TNUMINT || - var->ravi_type == RAVI_TARRAYFLT || - var->ravi_type == RAVI_TARRAYINT || - var->ravi_type == RAVI_TTABLE || - var->ravi_type == RAVI_TSTRING || - var->ravi_type == RAVI_TFUNCTION || - var->ravi_type == RAVI_TUSERDATA)) { + (var->ravi_type_map == RAVI_TM_FLOAT || + var->ravi_type_map == RAVI_TM_INTEGER || + var->ravi_type_map == RAVI_TM_FLOAT_ARRAY || + var->ravi_type_map == RAVI_TM_INTEGER_ARRAY || + 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))) { /* handled by MOVEI, MOVEF, MOVEIARRAY, MOVEFARRAY at runtime */ return; } - if (var->ravi_type == RAVI_TNUMFLT) { - if (ex->ravi_type == RAVI_TNUMFLT) - return; - if (ex->k == VINDEXED && ex->ravi_type == RAVI_TARRAYFLT) + if (var->ravi_type_map == RAVI_TM_FLOAT) { + if (ex->ravi_type_map == RAVI_TM_FLOAT) return; luaX_syntaxerror( fs->ls, @@ -883,33 +885,27 @@ static void check_valid_store(FuncState *fs, expdesc *var, expdesc *ex) { fs->ls->L, "Invalid assignment: number expected")); } - else if (var->ravi_type == RAVI_TNUMINT) { - if (ex->ravi_type == RAVI_TNUMINT) - return; - if (ex->k == VINDEXED && ex->ravi_type == RAVI_TARRAYINT) + else if (var->ravi_type_map == RAVI_TM_INTEGER) { + if (ex->ravi_type_map == RAVI_TM_INTEGER) return; luaX_syntaxerror( fs->ls, luaO_pushfstring( fs->ls->L, - "Invalid assignment: integer expected", - var->ravi_type, - ex->ravi_type)); + "Invalid assignment: integer expected")); } - else if (var->ravi_type == RAVI_TARRAYFLT || - var->ravi_type == RAVI_TARRAYINT || - var->ravi_type == RAVI_TTABLE) { - if (ex->ravi_type == var->ravi_type && ex->k != VINDEXED) + 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) return; luaX_syntaxerror( fs->ls, luaO_pushfstring( fs->ls->L, "Invalid assignment: %s expected", - var->ravi_type == RAVI_TTABLE ? "table" : (var->ravi_type == RAVI_TARRAYFLT ? "number[]" : "integer[]"))); + var->ravi_type_map == RAVI_TM_TABLE ? "table" : (var->ravi_type_map == RAVI_TM_FLOAT_ARRAY ? "number[]" : "integer[]"))); } - else if (var->ravi_type == RAVI_TSTRING) { - if (ex->ravi_type == RAVI_TNIL || (ex->ravi_type == var->ravi_type && ex->k != VINDEXED)) + else if (var->ravi_type_map == (RAVI_TM_STRING | RAVI_TM_NIL)) { + if ((ex->ravi_type_map & ~(RAVI_TM_STRING | RAVI_TM_NIL)) == 0) return; luaX_syntaxerror( fs->ls, @@ -917,8 +913,8 @@ static void check_valid_store(FuncState *fs, expdesc *var, expdesc *ex) { fs->ls->L, "Invalid assignment: string expected")); } - else if (var->ravi_type == RAVI_TFUNCTION) { - if (ex->ravi_type == RAVI_TNIL || (ex->ravi_type == var->ravi_type && ex->k != VINDEXED)) + else if (var->ravi_type_map == (RAVI_TM_FUNCTION | RAVI_TM_NIL)) { + if ((ex->ravi_type_map & ~(RAVI_TM_FUNCTION | RAVI_TM_NIL)) == 0) return; luaX_syntaxerror( fs->ls, @@ -926,9 +922,9 @@ static void check_valid_store(FuncState *fs, expdesc *var, expdesc *ex) { fs->ls->L, "Invalid assignment: function expected")); } - else if (var->ravi_type == RAVI_TUSERDATA) { - if (ex->ravi_type == RAVI_TNIL || - (ex->ravi_type == var->ravi_type && var->usertype && var->usertype == ex->usertype && ex->k != VINDEXED)) + else if (var->ravi_type_map == (RAVI_TM_USERDATA | RAVI_TM_NIL)) { + 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))) return; luaX_syntaxerror( fs->ls, @@ -940,27 +936,28 @@ static void check_valid_store(FuncState *fs, expdesc *var, expdesc *ex) { static OpCode check_valid_setupval(FuncState *fs, expdesc *var, expdesc *ex, 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; - if ((var->ravi_type == RAVI_TNUMINT || var->ravi_type == RAVI_TNUMFLT || - var->ravi_type == RAVI_TARRAYFLT || var->ravi_type == RAVI_TARRAYINT || - var->ravi_type == RAVI_TTABLE || var->ravi_type == RAVI_TSTRING || - var->ravi_type == RAVI_TFUNCTION || var->ravi_type == RAVI_TUSERDATA) && - var->ravi_type != ex->ravi_type) { - if (var->ravi_type == RAVI_TNUMINT) + 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_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) && + ex->ravi_type_map & ~var->ravi_type_map) { + if (var->ravi_type_map == RAVI_TM_INTEGER) op = OP_RAVI_SETUPVALI; - else if (var->ravi_type == RAVI_TNUMFLT) + else if (var->ravi_type_map == RAVI_TM_FLOAT) op = OP_RAVI_SETUPVALF; - else if (var->ravi_type == RAVI_TARRAYINT) + else if (var->ravi_type_map == RAVI_TM_INTEGER_ARRAY) op = OP_RAVI_SETUPVAL_IARRAY; - else if (var->ravi_type == RAVI_TARRAYFLT) + else if (var->ravi_type_map == RAVI_TM_FLOAT_ARRAY) op = OP_RAVI_SETUPVAL_FARRAY; - else if (var->ravi_type == RAVI_TTABLE) + else if (var->ravi_type_map == RAVI_TM_TABLE) op = OP_RAVI_SETUPVALT; - else if (var->ravi_type == RAVI_TSTRING) + else if (var->ravi_type_map == RAVI_TM_STRING | RAVI_TM_NIL) luaK_codeABC(fs, OP_RAVI_TOSTRING, reg, 0, 0); - else if (var->ravi_type == RAVI_TFUNCTION) + else if (var->ravi_type_map == RAVI_TM_FUNCTION | RAVI_TM_NIL) luaK_codeABC(fs, OP_RAVI_TOCLOSURE, reg, 0, 0); - else if (var->ravi_type == RAVI_TUSERDATA) { + else if (var->ravi_type_map == RAVI_TM_USERDATA | RAVI_TM_NIL) { TString *usertype = fs->f->upvalues[var->u.info].usertype; luaK_codeABx(fs, OP_RAVI_TOTYPE, reg, luaK_stringK(fs, usertype)); } @@ -979,9 +976,9 @@ static OpCode check_valid_setupval(FuncState *fs, expdesc *var, expdesc *ex, void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { switch (var->k) { case VLOCAL: { - check_valid_store(fs, var, ex); freeexp(fs, ex); exp2reg(fs, ex, var->u.info); /* compute 'ex' into proper place */ + check_valid_store(fs, var, ex); return; } case VUPVAL: { @@ -991,38 +988,26 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { break; } case VINDEXED: { - OpCode op = (var->u.ind.vt == VLOCAL) ? OP_SETTABLE : OP_SETTABUP; - if (op == OP_SETTABLE) { + OpCode op; + int e = luaK_exp2RK(fs, ex); + if (var->u.ind.vt == VLOCAL) { /* table value set - if array access then use specialized versions */ - if (var->ravi_type == RAVI_TARRAYFLT && - var->u.ind.key_ravi_type == RAVI_TNUMINT) { - if (!(ex->ravi_type == RAVI_TNUMFLT || (ex->k == VINDEXED && ex->ravi_type == RAVI_TARRAYFLT))) - /* input value may need conversion */ - op = OP_RAVI_FARRAY_SET; - else - /* input value is known to be number */ - op = OP_RAVI_FARRAY_SETF; - } else if (var->ravi_type == RAVI_TARRAYINT && - var->u.ind.key_ravi_type == RAVI_TNUMINT) { - if (!(ex->ravi_type == RAVI_TNUMINT || (ex->k == VINDEXED && ex->ravi_type == RAVI_TARRAYINT))) - /* input value may need conversion */ - op = OP_RAVI_IARRAY_SET; - else - /* input value is known to be integer */ - op = OP_RAVI_IARRAY_SETI; - } else if (var->u.ind.key_ravi_type == RAVI_TNUMINT) { - /* index op with integer key, target may not be a table */ - op = OP_RAVI_SETI; - } else if (var->ravi_type == RAVI_TTABLE && var->u.ind.key_ravi_type == RAVI_TSTRING && isshortstr(fs, var->u.ind.idx)) { - /* table with string key */ - op = OP_RAVI_TABLE_SETFIELD; - } - else if (var->u.ind.key_ravi_type == RAVI_TSTRING && isshortstr(fs, var->u.ind.idx)) { - /* index op with string key, target may not be a table */ - op = OP_RAVI_SETFIELD; + if (var->u.ind.key_ravi_type_map == RAVI_TM_INTEGER) { + if (var->ravi_type_map == RAVI_TM_FLOAT_ARRAY) { + op = ex->ravi_type_map == RAVI_TM_FLOAT ? OP_RAVI_FARRAY_SETF : OP_RAVI_FARRAY_SET; + } else if (var->ravi_type_map == RAVI_TM_INTEGER_ARRAY) { + op = ex->ravi_type_map == RAVI_TM_INTEGER ? OP_RAVI_IARRAY_SETI : OP_RAVI_IARRAY_SET; + } else { + op = OP_RAVI_SETI; + } + } else if (var->u.ind.key_ravi_type_map == RAVI_TM_STRING && isshortstr(fs, var->u.ind.idx)) { + op = var->ravi_type_map == RAVI_TM_TABLE ? OP_RAVI_TABLE_SETFIELD : OP_RAVI_SETFIELD; + } else { + op = OP_SETTABLE; } + } else { + op = OP_SETTABUP; } - int e = luaK_exp2RK(fs, ex); luaK_codeABC(fs, op, var->u.ind.t, var->u.ind.idx, e); break; } @@ -1045,13 +1030,13 @@ void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { */ int is_string_constant_key = key->k == VK && - key->ravi_type == RAVI_TSTRING && + key->ravi_type_map == RAVI_TM_STRING && ttisshrstring(&fs->f->k[key->u.info]); luaK_exp2anyreg(fs, e); // The check below needs to be // after exp2anyreg as this can modify e->ravi_type int table_and_string = - e->ravi_type == RAVI_TTABLE && + e->ravi_type_map == RAVI_TM_TABLE && is_string_constant_key; ereg = e->u.info; /* register where 'e' was placed */ freeexp(fs, e); @@ -1115,7 +1100,7 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) { break; } default: { - if (e->ravi_type == RAVI_TNIL || e->ravi_type == RAVI_TANY || e->ravi_type == RAVI_TBOOLEAN) { + if (e->ravi_type_map & RAVI_TM_FALSISH) { pc = jumponcond(fs, e, 0); /* jump when false */ } else { @@ -1146,11 +1131,11 @@ void luaK_goiffalse (FuncState *fs, expdesc *e) { break; } default: { - if (e->ravi_type == RAVI_TNIL) { - pc = NO_JUMP; /* always false; do nothing */ + if (e->ravi_type_map & RAVI_TM_TRUISH) { + pc = jumponcond(fs, e, 1); /* jump if true */ } else { - pc = jumponcond(fs, e, 1); /* jump if true */ + pc = NO_JUMP; /* always false; do nothing */ } break; } @@ -1169,14 +1154,17 @@ static void codenot (FuncState *fs, expdesc *e) { switch (e->k) { case VNIL: case VFALSE: { e->k = VTRUE; /* true == not nil == not false */ + e->ravi_type_map = RAVI_TM_TRUE; break; } case VK: case VKFLT: case VKINT: case VTRUE: { e->k = VFALSE; /* false == not "x" == not 0.5 == not 1 == not true */ + e->ravi_type_map = RAVI_TM_FALSE; break; } case VJMP: { negatecondition(fs, e); + e->ravi_type_map = RAVI_TM_BOOLEAN; break; } case VRELOCABLE: @@ -1185,11 +1173,11 @@ static void codenot (FuncState *fs, expdesc *e) { freeexp(fs, e); e->u.info = luaK_codeABC(fs, OP_NOT, 0, e->u.info, 0); e->k = VRELOCABLE; + e->ravi_type_map = RAVI_TM_BOOLEAN; break; } default: lua_assert(0); /* cannot happen */ } - e->ravi_type = RAVI_TBOOLEAN; /* interchange true and false lists */ { int temp = e->f; e->f = e->t; e->t = temp; } removevalues(fs, e->f); /* values are useless when negated */ @@ -1204,7 +1192,7 @@ static void codenot (FuncState *fs, expdesc *e) { void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { lua_assert(!hasjumps(t) && (vkisinreg(t->k) || t->k == VUPVAL)); t->u.ind.t = t->u.info; /* register or upvalue index */ - t->u.ind.key_ravi_type = k->ravi_type; /* RAVI record the key type */ + t->u.ind.key_ravi_type_map = k->ravi_type_map; /* RAVI record the key type */ t->u.ind.usertype = k->usertype; /* RAVI record the key type */ t->u.ind.idx = luaK_exp2RK(fs, k); /* R/K index for key */ t->u.ind.vt = (t->k == VUPVAL) ? VUPVAL : VLOCAL; @@ -1244,7 +1232,7 @@ static int constfolding (FuncState *fs, int op, expdesc *e1, if (ttisinteger(&res)) { e1->k = VKINT; e1->u.ival = ivalue(&res); - e1->ravi_type = RAVI_TNUMINT; + e1->ravi_type_map = RAVI_TM_INTEGER; } else { /* folds neither NaN nor 0.0 (to avoid problems with -0.0) */ lua_Number n = fltvalue(&res); @@ -1252,7 +1240,7 @@ static int constfolding (FuncState *fs, int op, expdesc *e1, return 0; e1->k = VKFLT; e1->u.nval = n; - e1->ravi_type = RAVI_TNUMFLT; + e1->ravi_type_map = RAVI_TM_FLOAT; } return 1; } @@ -1268,42 +1256,41 @@ static void codeunexpval (FuncState *fs, OpCode op, expdesc *e, int line) { freeexp(fs, e); switch (op) { case OP_BNOT: - if (e->ravi_type == RAVI_TNUMINT) { + if (e->ravi_type_map == RAVI_TM_INTEGER) { e->u.info = luaK_codeABC(fs, OP_RAVI_BNOT_I, 0, r, 0); - e->ravi_type = RAVI_TNUMINT; break; } e->u.info = luaK_codeABC(fs, OP_BNOT, 0, r, 0); - e->ravi_type = e->ravi_type == RAVI_TNUMFLT ? RAVI_TNUMINT : RAVI_TANY; + e->ravi_type_map = e->ravi_type_map == RAVI_TM_FLOAT ? RAVI_TM_INTEGER : RAVI_TM_ANY; break; case OP_LEN: e->u.info = luaK_codeABC(fs, OP_LEN, 0, r, 0); - if (e->ravi_type == RAVI_TARRAYINT || e->ravi_type == RAVI_TARRAYFLT || e->ravi_type == RAVI_TSTRING) { - e->ravi_type = RAVI_TNUMINT; + if ((e->ravi_type_map & (~(RAVI_TM_INTEGER_ARRAY | RAVI_TM_FLOAT_ARRAY | RAVI_TM_STRING))) == 0) { + e->ravi_type_map = RAVI_TM_INTEGER; } - else if (e->ravi_type == RAVI_TTABLE) { + else if ((e->ravi_type_map & (~(RAVI_TM_INTEGER_ARRAY | RAVI_TM_FLOAT_ARRAY | RAVI_TM_STRING | RAVI_TM_TABLE))) == 0) { e->k = VRELOCABLE; luaK_exp2anyreg(fs, e); /* This is not incompatible with lua since a type annotation is require to get here or the table trivially has * no metatable */ luaK_codeABC(fs, OP_RAVI_TOINT, e->u.info, 0, 0); - e->ravi_type = RAVI_TNUMINT; + e->ravi_type_map = RAVI_TM_INTEGER; luaK_fixline(fs, line); return; } else { - e->ravi_type = RAVI_TANY; + e->ravi_type_map = RAVI_TM_ANY; } break; case OP_UNM: e->u.info = luaK_codeABC(fs, OP_UNM, 0, r, 0); - if (e->ravi_type != RAVI_TNUMINT && e->ravi_type != RAVI_TNUMFLT) { - e->ravi_type = RAVI_TANY; + if (e->ravi_type_map & ~RAVI_TM_NUMBER) { + e->ravi_type_map = RAVI_TM_ANY; } break; default: e->u.info = luaK_codeABC(fs, op, 0, r, 0); - e->ravi_type = RAVI_TANY; + e->ravi_type_map = RAVI_TM_ANY; } e->k = VRELOCABLE; /* all those operations are relocatable */ luaK_fixline(fs, line); @@ -1329,61 +1316,68 @@ static void codebinexpval (FuncState *fs, OpCode op, #define RAVI_OPCODE_GENERIC(op, t) OP_##op #define RAVI_COMMUTATIVE(op, t) luaK_codeABC(fs, t(op, FI), 0, rk2, rk1) #define RAVI_NON_COMMUTATIVE(op, t) luaK_codeABC(fs, t(op, IF), 0, rk1, rk2) -#define RAVI_GEN_ARITH(op, co, ii, t) \ - case OP_##op: \ - if (e1->ravi_type == RAVI_TNUMFLT) { \ - if (e2->ravi_type == RAVI_TNUMFLT) { \ - e1->u.info = luaK_codeABC(fs, t(op, FF), 0, rk1, rk2); \ - e1->ravi_type = RAVI_TNUMFLT; \ - break; \ - } \ - else if (e2->ravi_type == RAVI_TNUMINT) { \ - e1->u.info = luaK_codeABC(fs, t(op, FI), 0, rk1, rk2); \ - e1->ravi_type = RAVI_TNUMFLT; \ - break; \ - } \ - } \ - else if (e1->ravi_type == RAVI_TNUMINT) { \ - if (e2->ravi_type == RAVI_TNUMFLT) { \ - e1->u.info = co(op, t); \ - e1->ravi_type = RAVI_TNUMFLT; \ - break; \ - } \ - else if (e2->ravi_type == RAVI_TNUMINT) { \ - e1->u.info = luaK_codeABC(fs, t(op, II), 0, rk1, rk2); \ - e1->ravi_type = ii; \ - break; \ - } \ - } \ - e1->u.info = luaK_codeABC(fs, OP_##op, 0, rk1, rk2); \ - e1->ravi_type = RAVI_TANY; \ +#define RAVI_GEN_ARITH(op, co, ii, t) \ + case OP_##op: \ + if (e1->ravi_type_map == RAVI_TM_FLOAT) { \ + if (e2->ravi_type_map == RAVI_TM_FLOAT) { \ + e1->u.info = luaK_codeABC(fs, t(op, FF), 0, rk1, rk2); \ + break; \ + } \ + else if (e2->ravi_type_map == RAVI_TM_INTEGER) { \ + e1->u.info = luaK_codeABC(fs, t(op, FI), 0, rk1, rk2); \ + break; \ + } \ + } \ + else if (e1->ravi_type_map == RAVI_TM_INTEGER) { \ + if (e2->ravi_type_map == RAVI_TM_FLOAT) { \ + e1->u.info = co(op, t); \ + e1->ravi_type_map = RAVI_TM_FLOAT; \ + break; \ + } \ + else if (e2->ravi_type_map == RAVI_TM_INTEGER) { \ + e1->u.info = luaK_codeABC(fs, t(op, II), 0, rk1, rk2); \ + e1->ravi_type_map = ii; \ + break; \ + } \ + } \ + e1->u.info = luaK_codeABC(fs, OP_##op, 0, rk1, rk2); \ + if ((e1->ravi_type_map & (~(RAVI_TM_FLOAT | RAVI_TM_INTEGER))) == 0 && \ + (e1->ravi_type_map & (~(RAVI_TM_FLOAT | RAVI_TM_INTEGER))) == 0) { \ + if (e1->ravi_type_map & e2->ravi_type_map & RAVI_TM_INTEGER) { \ + e1->ravi_type_map = RAVI_TM_FLOAT | RAVI_TM_INTEGER; \ + } \ + else { \ + e1->ravi_type_map = RAVI_TM_FLOAT; \ + } \ + } \ + else { \ + e1->ravi_type_map = RAVI_TM_ANY; \ + } \ break -#define RAVI_GEN_INT_OP(op) \ - case OP_##op: \ - if (e1->ravi_type == RAVI_TNUMINT && e2->ravi_type == RAVI_TNUMINT) { \ - e1->u.info = luaK_codeABC(fs, OP_RAVI_##op##_II, 0, rk1, rk2); \ - e1->ravi_type = RAVI_TNUMINT; \ - } \ - else if ((e1->ravi_type == RAVI_TNUMFLT || e1->ravi_type == RAVI_TNUMINT) && \ - (e2->ravi_type == RAVI_TNUMFLT || e2->ravi_type == RAVI_TNUMINT)) { \ - e1->u.info = luaK_codeABC(fs, OP_##op, 0, rk1, rk2); \ - e1->ravi_type = RAVI_TNUMINT; \ - } \ - else { \ - e1->u.info = luaK_codeABC(fs, OP_##op, 0, rk1, rk2); \ - e1->ravi_type = RAVI_TANY; \ - } \ +#define RAVI_GEN_INT_OP(op) \ + case OP_##op: \ + if (e1->ravi_type_map == RAVI_TM_INTEGER && e2->ravi_type_map == RAVI_TM_INTEGER) { \ + e1->u.info = luaK_codeABC(fs, OP_RAVI_##op##_II, 0, rk1, rk2); \ + } \ + else if ((e1->ravi_type_map & (~RAVI_TM_NUMBER)) == 0 && (e2->ravi_type_map & (~RAVI_TM_NUMBER)) == 0) { \ + e1->u.info = luaK_codeABC(fs, OP_##op, 0, rk1, rk2); \ + e1->ravi_type_map = RAVI_TM_INTEGER; \ + } \ + else { \ + e1->u.info = luaK_codeABC(fs, OP_##op, 0, rk1, rk2); \ + e1->ravi_type_map = RAVI_TM_ANY; \ + } \ break switch (op) { - RAVI_GEN_ARITH(ADD, RAVI_COMMUTATIVE, RAVI_TNUMINT, RAVI_OPCODE_SPECIALIZED); - RAVI_GEN_ARITH(SUB, RAVI_NON_COMMUTATIVE, RAVI_TNUMINT, RAVI_OPCODE_SPECIALIZED); - RAVI_GEN_ARITH(MUL, RAVI_COMMUTATIVE, RAVI_TNUMINT, RAVI_OPCODE_SPECIALIZED); - RAVI_GEN_ARITH(DIV, RAVI_NON_COMMUTATIVE, RAVI_TNUMFLT, RAVI_OPCODE_SPECIALIZED); - RAVI_GEN_ARITH(IDIV, RAVI_NON_COMMUTATIVE, RAVI_TNUMINT, RAVI_OPCODE_GENERIC); - RAVI_GEN_ARITH(MOD, RAVI_NON_COMMUTATIVE, RAVI_TNUMINT, RAVI_OPCODE_GENERIC); - RAVI_GEN_ARITH(POW, RAVI_NON_COMMUTATIVE, RAVI_TNUMFLT, RAVI_OPCODE_GENERIC); + RAVI_GEN_ARITH(ADD, RAVI_COMMUTATIVE, RAVI_TM_INTEGER, RAVI_OPCODE_SPECIALIZED); + RAVI_GEN_ARITH(SUB, RAVI_NON_COMMUTATIVE, RAVI_TM_INTEGER, RAVI_OPCODE_SPECIALIZED); + RAVI_GEN_ARITH(MUL, RAVI_COMMUTATIVE, RAVI_TM_INTEGER, RAVI_OPCODE_SPECIALIZED); + RAVI_GEN_ARITH(DIV, RAVI_NON_COMMUTATIVE, RAVI_TM_FLOAT, RAVI_OPCODE_SPECIALIZED); + RAVI_GEN_ARITH(IDIV, RAVI_NON_COMMUTATIVE, RAVI_TM_INTEGER, RAVI_OPCODE_GENERIC); + RAVI_GEN_ARITH(MOD, RAVI_NON_COMMUTATIVE, RAVI_TM_INTEGER, RAVI_OPCODE_GENERIC); + RAVI_GEN_ARITH(POW, RAVI_NON_COMMUTATIVE, RAVI_TM_FLOAT, RAVI_OPCODE_GENERIC); RAVI_GEN_INT_OP(BAND); RAVI_GEN_INT_OP(BOR); RAVI_GEN_INT_OP(BXOR); @@ -1391,17 +1385,17 @@ static void codebinexpval (FuncState *fs, OpCode op, RAVI_GEN_INT_OP(SHR); case OP_CONCAT: e1->u.info = luaK_codeABC(fs, op, 0, rk1, rk2); - if ((e1->ravi_type == RAVI_TSTRING || e1->ravi_type == RAVI_TNUMINT || e1->ravi_type == RAVI_TNUMFLT) || - (e2->ravi_type == RAVI_TSTRING || e2->ravi_type == RAVI_TNUMINT || e2->ravi_type == RAVI_TNUMFLT)) { - e1->ravi_type = RAVI_TSTRING; + if ((e1->ravi_type_map & (~(RAVI_TM_STRING | RAVI_TM_INTEGER | RAVI_TM_FLOAT))) == 0 || + (e2->ravi_type_map & (~(RAVI_TM_STRING | RAVI_TM_INTEGER | RAVI_TM_FLOAT))) == 0) { + e1->ravi_type_map = RAVI_TM_STRING; } else { - e1->ravi_type = RAVI_TANY; + e1->ravi_type_map = RAVI_TM_ANY; } break; default: e1->u.info = luaK_codeABC(fs, op, 0, rk1, rk2); - e1->ravi_type = RAVI_TANY; + e1->ravi_type_map = RAVI_TM_ANY; } e1->k = VRELOCABLE; /* all those operations are relocatable */ @@ -1409,23 +1403,23 @@ static void codebinexpval (FuncState *fs, OpCode op, } -static OpCode get_type_specific_comp_op(OpCode op, ravitype_t o1_tt, ravitype_t o2_tt) { +static OpCode get_type_specific_comp_op(OpCode op, uint32_t o1_tm, uint32_t o2_tm) { if (op == OP_EQ) { - if (o1_tt == RAVI_TNUMINT && o2_tt == RAVI_TNUMINT) + if (o1_tm == RAVI_TM_INTEGER && o2_tm == RAVI_TM_INTEGER) op = OP_RAVI_EQ_II; - else if (o1_tt == RAVI_TNUMFLT && o2_tt == RAVI_TNUMFLT) + else if (o1_tm == RAVI_TM_FLOAT && o2_tm == RAVI_TM_FLOAT) op = OP_RAVI_EQ_FF; } else if (op == OP_LT) { - if (o1_tt == RAVI_TNUMINT && o2_tt == RAVI_TNUMINT) + if (o1_tm == RAVI_TM_INTEGER && o2_tm == RAVI_TM_INTEGER) op = OP_RAVI_LT_II; - else if (o1_tt == RAVI_TNUMFLT && o2_tt == RAVI_TNUMFLT) + else if (o1_tm == RAVI_TM_FLOAT && o2_tm == RAVI_TM_FLOAT) op = OP_RAVI_LT_FF; } else if (op == OP_LE) { - if (o1_tt == RAVI_TNUMINT && o2_tt == RAVI_TNUMINT) + if (o1_tm == RAVI_TM_INTEGER && o2_tm == RAVI_TM_INTEGER) op = OP_RAVI_LE_II; - else if (o1_tt == RAVI_TNUMFLT && o2_tt == RAVI_TNUMFLT) + else if (o1_tm == RAVI_TM_FLOAT && o2_tm == RAVI_TM_FLOAT) op = OP_RAVI_LE_FF; } return op; @@ -1439,32 +1433,32 @@ static void codecomp (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) { DEBUG_EXPR(raviY_printf(fs, "Comparison of %e and %e\n", e1, e2)); int rk1 = (e1->k == VK) ? RKASK(e1->u.info) : check_exp(e1->k == VNONRELOC, e1->u.info); - ravitype_t rk1_tt = e1->ravi_type; + uint32_t rk1_tm = e1->ravi_type_map; int rk2 = luaK_exp2RK(fs, e2); - ravitype_t rk2_tt = e2->ravi_type; + uint32_t rk2_tm = e2->ravi_type_map; freeexps(fs, e1, e2); switch (opr) { case OPR_NE: { /* '(a ~= b)' ==> 'not (a == b)' */ - OpCode op = get_type_specific_comp_op(OP_EQ, rk1_tt, rk2_tt); + OpCode op = get_type_specific_comp_op(OP_EQ, rk1_tm, rk2_tm); e1->u.info = condjump(fs, op, 0, rk1, rk2); break; } case OPR_GT: case OPR_GE: { /* '(a > b)' ==> '(b < a)'; '(a >= b)' ==> '(b <= a)' */ OpCode op = cast(OpCode, (opr - OPR_NE) + OP_EQ); - op = get_type_specific_comp_op(op, rk2_tt, rk1_tt); + op = get_type_specific_comp_op(op, rk2_tm, rk1_tm); e1->u.info = condjump(fs, op, 1, rk2, rk1); /* invert operands */ break; } default: { /* '==', '<', '<=' use their own opcodes */ OpCode op = cast(OpCode, (opr - OPR_EQ) + OP_EQ); - op = get_type_specific_comp_op(op, rk1_tt, rk2_tt); + op = get_type_specific_comp_op(op, rk1_tm, rk2_tm); e1->u.info = condjump(fs, op, 1, rk1, rk2); break; } } e1->k = VJMP; - e1->ravi_type = RAVI_TBOOLEAN; + e1->ravi_type_map = RAVI_TM_BOOLEAN; } @@ -1479,21 +1473,21 @@ static void code_type_assertion(FuncState *fs, UnOpr op, expdesc *e, TString *us switch (e->k) { case VKFLT: { if (op == OPR_TO_NUMBER) { - e->ravi_type = RAVI_TNUMFLT; /* RAVI TODO*/ + lua_assert(e->ravi_type_map == RAVI_TM_FLOAT); return; } break; } case VKINT: { if (op == OPR_TO_INTEGER) { - e->ravi_type = RAVI_TNUMINT; /* RAVI TODO*/ + lua_assert(e->ravi_type_map == RAVI_TM_INTEGER); return; } break; } case VK: { if (op == OPR_TO_STRING) { - if (e->ravi_type == RAVI_TSTRING) + if (e->ravi_type_map == RAVI_TM_STRING) return; } break; @@ -1502,56 +1496,56 @@ static void code_type_assertion(FuncState *fs, UnOpr op, expdesc *e, TString *us case VNONRELOC: { discharge2anyreg(fs, e); OpCode opcode; - ravitype_t tt; - if (op == OPR_TO_NUMBER && e->ravi_type != RAVI_TNUMFLT) { + uint32_t tm; + if (op == OPR_TO_NUMBER && e->ravi_type_map != RAVI_TM_FLOAT) { opcode = OP_RAVI_TOFLT; - tt = RAVI_TNUMFLT; + tm = RAVI_TM_FLOAT; } - else if (op == OPR_TO_INTEGER && e->ravi_type != RAVI_TNUMINT) { + else if (op == OPR_TO_INTEGER && e->ravi_type_map != RAVI_TM_INTEGER) { opcode = OP_RAVI_TOINT; - tt = RAVI_TNUMINT; + tm = RAVI_TM_INTEGER; } - else if (op == OPR_TO_INTARRAY && e->ravi_type != RAVI_TARRAYINT) { - if (e->ravi_type == RAVI_TTABLE && e->pc >= 0) { + else if (op == OPR_TO_INTARRAY && e->ravi_type_map != RAVI_TM_INTEGER_ARRAY) { + if (e->ravi_type_map == RAVI_TM_TABLE && e->pc >= 0) { Instruction *i = &fs->f->code[e->pc]; if (GET_OPCODE(*i) == OP_NEWTABLE) { SET_OPCODE(*i, OP_RAVI_NEW_IARRAY); - e->ravi_type = RAVI_TARRAYINT; + e->ravi_type_map = RAVI_TM_INTEGER_ARRAY; DEBUG_EXPR(raviY_printf(fs, "code_type_assertion (OP_NEWTABLE to OP_RAVI_NEW_IARRAY) %e\n", e)); } return; } opcode = OP_RAVI_TOIARRAY; - tt = RAVI_TARRAYINT; + tm = RAVI_TM_INTEGER_ARRAY; } - else if (op == OPR_TO_NUMARRAY && e->ravi_type != RAVI_TARRAYFLT) { - if (e->ravi_type == RAVI_TTABLE && e->pc >= 0) { + else if (op == OPR_TO_NUMARRAY && e->ravi_type_map != RAVI_TM_FLOAT_ARRAY) { + if (e->ravi_type_map == RAVI_TM_TABLE && e->pc >= 0) { Instruction *i = &fs->f->code[e->pc]; if (GET_OPCODE(*i) == OP_NEWTABLE) { SET_OPCODE(*i, OP_RAVI_NEW_FARRAY); - e->ravi_type = RAVI_TARRAYFLT; + e->ravi_type_map = RAVI_TM_FLOAT_ARRAY; DEBUG_EXPR(raviY_printf(fs, "code_type_assertion (OP_NEWTABLE to OP_RAVI_NEW_IARRAY) %e\n", e)); } return; } opcode = OP_RAVI_TOFARRAY; - tt = RAVI_TARRAYFLT; + tm = RAVI_TM_FLOAT_ARRAY; } - else if (op == OPR_TO_TABLE && e->ravi_type != RAVI_TTABLE) { + else if (op == OPR_TO_TABLE && e->ravi_type_map != RAVI_TM_TABLE) { opcode = OP_RAVI_TOTAB; - tt = RAVI_TTABLE; + tm = RAVI_TM_TABLE; } - else if (op == OPR_TO_STRING && e->ravi_type != RAVI_TSTRING) { + else if (op == OPR_TO_STRING && e->ravi_type_map != RAVI_TM_STRING) { opcode = OP_RAVI_TOSTRING; - tt = RAVI_TSTRING; + tm = RAVI_TM_STRING; } - else if (op == OPR_TO_CLOSURE && e->ravi_type != RAVI_TFUNCTION) { + else if (op == OPR_TO_CLOSURE && e->ravi_type_map != RAVI_TM_FUNCTION) { opcode = OP_RAVI_TOCLOSURE; - tt = RAVI_TFUNCTION; + tm = RAVI_TM_FUNCTION; } else if (op == OPR_TO_TYPE) { opcode = OP_RAVI_TOTYPE; - tt = RAVI_TUSERDATA; + tm = RAVI_TM_USERDATA; } else { /* nothing to do*/ @@ -1563,7 +1557,7 @@ static void code_type_assertion(FuncState *fs, UnOpr op, expdesc *e, TString *us } else luaK_codeABC(fs, opcode, e->u.info, 0, 0); - e->ravi_type = tt; + e->ravi_type_map = tm; e->k = VNONRELOC; if (opcode == OP_RAVI_TOTYPE) e->usertype = usertype; @@ -1578,7 +1572,7 @@ static void code_type_assertion(FuncState *fs, UnOpr op, expdesc *e, TString *us ** Apply prefix operation 'op' to expression 'e'. */ void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line, TString *usertype) { - expdesc ef = {.ravi_type = RAVI_TANY, + expdesc ef = {.ravi_type_map = RAVI_TM_ANY, .pc = -1, .t = NO_JUMP, .f = NO_JUMP, @@ -1652,19 +1646,7 @@ void luaK_posfix (FuncState *fs, BinOpr op, lua_assert(e1->t == NO_JUMP); /* list closed by 'luK_infix' */ luaK_dischargevars(fs, e2); luaK_concat(fs, &e2->f, e1->f); - if (e1->ravi_type == RAVI_TNIL) { - /* nil and something is still nil. */ - e2->ravi_type = RAVI_TNIL; - } - else if (e1->ravi_type == RAVI_TBOOLEAN || e1->ravi_type == RAVI_TANY) { - /* In these cases the 'and' can go both ways. */ - if (e2->ravi_type != e1->ravi_type) - e2->ravi_type = RAVI_TANY; - } - else { - /* Nothing to do here, since the first arg is always truish and therefore the second arg will be used every - * time. */ - } + e2->ravi_type_map |= e1->ravi_type_map & RAVI_TM_FALSISH; *e1 = *e2; break; } @@ -1672,19 +1654,11 @@ void luaK_posfix (FuncState *fs, BinOpr op, lua_assert(e1->f == NO_JUMP); /* list closed by 'luK_infix' */ luaK_dischargevars(fs, e2); luaK_concat(fs, &e2->t, e1->t); - if (e1->ravi_type == RAVI_TNIL) { - /* Nothing to do here, since the first arg is always truish and therefore the second arg will be used every - * time. */ - } - else if (e1->ravi_type == RAVI_TBOOLEAN || e1->ravi_type == RAVI_TANY) { - /* In these cases the 'or' can go both ways. */ - if (e2->ravi_type != e1->ravi_type) - e2->ravi_type = RAVI_TANY; - } - else { - /* In this case the first argument is truish and will be the return from 'or' */ - e2->ravi_type = e1->ravi_type; + if (e1->ravi_type_map & e2->ravi_type_map & RAVI_TM_USERDATA) { + if (e1->usertype != e2->usertype) + e2->usertype = NULL; } + e2->ravi_type_map |= e1->ravi_type_map & RAVI_TM_TRUISH; *e1 = *e2; break; } @@ -1697,12 +1671,12 @@ void luaK_posfix (FuncState *fs, BinOpr op, SETARG_B(getinstruction(fs, e2), e1->u.info); DEBUG_CODEGEN(raviY_printf(fs, "[%d]* %o ; set A to %d\n", e2->u.info, getinstruction(fs,e2), e1->u.info)); e1->k = VRELOCABLE; e1->u.info = e2->u.info; - if (e2->ravi_type == RAVI_TSTRING && - (e1->ravi_type == RAVI_TSTRING || e1->ravi_type == RAVI_TNUMINT || e1->ravi_type == RAVI_TNUMFLT)) { - e1->ravi_type = RAVI_TSTRING; + if (e2->ravi_type_map == RAVI_TM_STRING && + (e1->ravi_type_map & (~(RAVI_TM_STRING | RAVI_TM_INTEGER | RAVI_TM_FLOAT))) == 0) { + e1->ravi_type_map = RAVI_TM_STRING; } else { - e1->ravi_type = RAVI_TANY; + e1->ravi_type_map = RAVI_TM_ANY; } } else { diff --git a/src/lobject.h b/src/lobject.h index dd3f102..ad5f12b 100644 --- a/src/lobject.h +++ b/src/lobject.h @@ -68,6 +68,41 @@ typedef enum { RAVI_TUSERDATA /* userdata or lightuserdata */ } ravitype_t; +typedef enum { + RAVI_TI_NIL, + RAVI_TI_FALSE, + RAVI_TI_TRUE, + RAVI_TI_INTEGER, + RAVI_TI_FLOAT, + RAVI_TI_INTEGER_ARRAY, + RAVI_TI_FLOAT_ARRAY, + RAVI_TI_TABLE, + RAVI_TI_STRING, + RAVI_TI_FUNCTION, + RAVI_TI_USERDATA, + RAVI_TI_OTHER +} ravi_type_index; + +#define RAVI_TM_NIL (1<ravi_type_map, type_map_str); switch (e->k) { case VVOID: - fprintf(fp, "{p=%p, k=VVOID, type=%s}", e, raviY_typename(e->ravi_type)); + fprintf(fp, "{p=%p, k=VVOID, type=%s}", e, type_map_str); break; case VNIL: - fprintf(fp, "{p=%p, k=VNIL, type=%s}", e, raviY_typename(e->ravi_type)); + fprintf(fp, "{p=%p, k=VNIL, type=%s}", e, type_map_str); break; case VTRUE: - fprintf(fp, "{p=%p, k=VTRUE, type=%s}", e, raviY_typename(e->ravi_type)); + fprintf(fp, "{p=%p, k=VTRUE, type=%s}", e, type_map_str); break; case VFALSE: - fprintf(fp, "{p=%p, k=VFALSE, type=%s}", e, raviY_typename(e->ravi_type)); + fprintf(fp, "{p=%p, k=VFALSE, type=%s}", e, type_map_str); break; case VK: fprintf(fp, "{p=%p, k=VK, Kst=%d, type=%s}", e, e->u.info, - raviY_typename(e->ravi_type)); + type_map_str); break; case VKFLT: fprintf(fp, "{p=%p, k=VKFLT, n=%f, type=%s}", e, e->u.nval, - raviY_typename(e->ravi_type)); + type_map_str); break; case VKINT: fprintf(fp, "{p=%p, k=VKINT, n=%lld, type=%s}", e, (long long)e->u.ival, - raviY_typename(e->ravi_type)); + type_map_str); break; case VNONRELOC: 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)), - raviY_typename(e->ravi_type), + type_map_str, e->pc); break; case VLOCAL: fprintf(fp, "{p=%p, k=VLOCAL, register=%d, type=%s}", e, e->u.info, - raviY_typename(e->ravi_type)); + type_map_str); break; case VUPVAL: fprintf(fp, "{p=%p, k=VUPVAL, idx=%d, type=%s}", e, e->u.info, - raviY_typename(e->ravi_type)); + type_map_str); break; case VINDEXED: fprintf(fp, "{p=%p, k=VINDEXED, tablereg=%d, indexreg=%d, vtype=%s, type=%s}", e, e->u.ind.t, e->u.ind.idx, (e->u.ind.vt == VLOCAL) ? "VLOCAL" : "VUPVAL", - raviY_typename(e->ravi_type)); + type_map_str); break; case VJMP: fprintf(fp, "{p=%p, k=VJMP, pc=%d, instruction=(%s), type=%s}", e, e->u.info, raviP_instruction_to_str(buf, sizeof buf, getinstruction(fs, e)), - raviY_typename(e->ravi_type)); + type_map_str); break; case VRELOCABLE: fprintf(fp, "{p=%p, k=VRELOCABLE, pc=%d, instruction=(%s), type=%s, pc=%d}", e, e->u.info, raviP_instruction_to_str(buf, sizeof buf, getinstruction(fs, e)), - raviY_typename(e->ravi_type), + type_map_str, e->pc); break; case VCALL: @@ -161,13 +225,13 @@ static void print_expdesc(FILE *fp, FuncState *fs, const expdesc *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)), raviY_typename(raviY_get_register_typeinfo(fs, GETARG_A(getinstruction(fs, e)), NULL)), - raviY_typename(e->ravi_type)); + type_map_str); break; case VVARARG: fprintf(fp, "{p=%p, k=VVARARG, pc=%d, instruction=(%s), type=%s}", e, e->u.info, raviP_instruction_to_str(buf, sizeof buf, getinstruction(fs, e)), - raviY_typename(e->ravi_type)); + type_map_str); break; } } @@ -187,10 +251,12 @@ void raviY_printf(FuncState *fs, const char *format, ...) { cp++; } else if (cp[0] == '%' && cp[1] == 'v') { LocVar *v; + char type_map_str[RAVI_TYPEMAP_MAX_LEN]; v = va_arg(ap, LocVar *); const char *s = getstr(v->varname); + raviY_typemap_string(v->ravi_type_map, type_map_str); printf("var={%s startpc=%d endpc=%d, type=%s}", s, v->startpc, v->endpc, - raviY_typename(v->ravi_type)); + type_map_str); cp++; } else if (cp[0] == '%' && cp[1] == 'o') { Instruction i; @@ -314,12 +380,12 @@ 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, ravitype_t tt, TString *usertype) { +static void init_exp (expdesc *e, expkind k, int info, uint32_t tt, TString *usertype) { e->f = e->t = NO_JUMP; e->k = k; e->u.info = info; /* RAVI change; added type */ - e->ravi_type = tt; + e->ravi_type_map = tt; e->usertype = usertype; e->pc = -1; e->u.ind.usertype = NULL; /* Just for safey */ @@ -329,7 +395,7 @@ static void init_exp (expdesc *e, expkind k, int info, ravitype_t tt, TString *u * e->u.info, e->ravi_type = RAVI_TSTRING, e->k = VK */ static void codestring (LexState *ls, expdesc *e, TString *s) { - init_exp(e, VK, luaK_stringK(ls->fs, s), RAVI_TSTRING, NULL); + init_exp(e, VK, luaK_stringK(ls->fs, s), RAVI_TM_STRING, NULL); } /* verify that current token is a string, create a string constant @@ -344,7 +410,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, unsigned int ravi_type, TString *usertype) { +static int registerlocalvar (LexState *ls, TString *varname, uint32_t ravi_type_map, TString *usertype) { FuncState *fs = ls->fs; Proto *f = fs->f; int oldsize = f->sizelocvars; @@ -354,28 +420,25 @@ static int registerlocalvar (LexState *ls, TString *varname, unsigned int ravi_t /* RAVI change initialize */ f->locvars[oldsize].startpc = -1; f->locvars[oldsize].endpc = -1; - f->locvars[oldsize].ravi_type = RAVI_TANY; + f->locvars[oldsize].ravi_type_map = RAVI_TM_ANY; f->locvars[oldsize].usertype = NULL; f->locvars[oldsize++].varname = NULL; } f->locvars[fs->nlocvars].varname = varname; - f->locvars[fs->nlocvars].ravi_type = ravi_type; - if (ravi_type == RAVI_TUSERDATA && usertype != NULL) { - // Store a reference to the usertype name - f->locvars[fs->nlocvars].usertype = usertype; - } + f->locvars[fs->nlocvars].ravi_type_map = ravi_type_map; + f->locvars[fs->nlocvars].usertype = usertype; luaC_objbarrier(ls->L, f, varname); return fs->nlocvars++; } /* create a new local variable in function scope, and set the * variable type (RAVI - added type tt) */ -static void new_localvar (LexState *ls, TString *name, ravitype_t tt, TString *usertype) { +static void new_localvar (LexState *ls, TString *name, uint32_t tm, TString *usertype) { FuncState *fs = ls->fs; Dyndata *dyd = ls->dyd; /* register variable and get its index */ /* RAVI change - record type info for local variable */ - int reg = registerlocalvar(ls, name, tt, usertype); + int reg = registerlocalvar(ls, name, tm, usertype); checklimit(fs, dyd->actvar.n + 1 - fs->firstlocal, MAXVARS, "local variables"); luaM_growvector(ls->L, dyd->actvar.arr, dyd->actvar.n + 1, @@ -391,7 +454,7 @@ static void new_localvar (LexState *ls, TString *name, ravitype_t tt, TString *u */ static void new_localvarliteral_ (LexState *ls, const char *name, size_t sz) { /* RAVI change - add type */ - new_localvar(ls, luaX_newstring(ls, name, sz), RAVI_TANY, NULL); + new_localvar(ls, luaX_newstring(ls, name, sz), RAVI_TM_ANY, NULL); } /* create a new local variable @@ -428,13 +491,13 @@ static int register_to_locvar_index(FuncState *fs, int reg) { * return the type associated with the variable. * This is a RAVI function */ -ravitype_t raviY_get_register_typeinfo(FuncState *fs, int reg, TString **pusertype) { +uint32_t raviY_get_register_typeinfo(FuncState *fs, int reg, TString **pusertype) { int idx; LocVar *v; /* Due to the way Lua parser works it is not safe to look beyond nactvar */ if (reg < 0 || reg >= fs->nactvar || (fs->firstlocal + reg) >= fs->ls->dyd->actvar.n) { - return RAVI_TANY; + return RAVI_TM_ANY; } /* Get the LocVar associated with the register */ idx = fs->ls->dyd->actvar.arr[fs->firstlocal + reg].idx; @@ -443,7 +506,7 @@ ravitype_t raviY_get_register_typeinfo(FuncState *fs, int reg, TString **puserty if (pusertype != NULL) *pusertype = v->usertype; /* Variable in scope so return the type if we know it */ - return v->ravi_type; + return v->ravi_type_map; } /* moves the active variable watermark (nactvar) to cover the @@ -497,7 +560,7 @@ static int newupvalue (FuncState *fs, TString *name, expdesc *v) { f->upvalues[fs->nups].instack = (v->k == VLOCAL); f->upvalues[fs->nups].idx = cast_byte(v->u.info); f->upvalues[fs->nups].name = name; - f->upvalues[fs->nups].ravi_type = v->ravi_type; + f->upvalues[fs->nups].ravi_type_map = v->ravi_type_map; f->upvalues[fs->nups].usertype = v->usertype; luaC_objbarrier(fs->ls->L, f, name); return fs->nups++; @@ -534,13 +597,13 @@ static void markupval (FuncState *fs, int level) { */ static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { if (fs == NULL) /* no more levels? */ - init_exp(var, VVOID, 0, RAVI_TANY, NULL); /* default is global */ + init_exp(var, VVOID, 0, RAVI_TM_ANY, NULL); /* default is global */ else { int v = searchvar(fs, n); /* look up locals at current level */ if (v >= 0) { /* found? */ /* RAVI set type of local var / expr if possible */ TString *usertype = NULL; - ravitype_t tt = raviY_get_register_typeinfo(fs, v, &usertype); + uint32_t tt = raviY_get_register_typeinfo(fs, v, &usertype); init_exp(var, VLOCAL, v, tt, usertype); /* variable is local, RAVI set type */ if (!base) markupval(fs, v); /* local will be used as an upval */ @@ -554,7 +617,7 @@ static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { /* else was LOCAL or UPVAL */ idx = newupvalue(fs, n, var); /* will be a new upvalue */ } - init_exp(var, VUPVAL, idx, fs->f->upvalues[idx].ravi_type, fs->f->upvalues[idx].usertype); /* RAVI : set upvalue type */ + init_exp(var, VUPVAL, idx, fs->f->upvalues[idx].ravi_type_map, fs->f->upvalues[idx].usertype); /* RAVI : set upvalue type */ } } } @@ -568,7 +631,7 @@ static void singlevar (LexState *ls, expdesc *var) { FuncState *fs = ls->fs; singlevaraux(fs, varname, var, 1); if (var->k == VVOID) { /* global name? */ - expdesc key = {.ravi_type = RAVI_TANY, .pc = -1}; + expdesc key = {.ravi_type_map = RAVI_TM_ANY, .pc = -1}; singlevaraux(fs, ls->envn, var, 1); /* get environment variable */ lua_assert(var->k != VVOID); /* this one must exist */ codestring(ls, &key, varname); /* key is variable name */ @@ -578,29 +641,30 @@ 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, TString *typename /* only if tt is USERDATA */) { +static void ravi_code_typecoersion(LexState *ls, int reg, uint32_t ravi_type_map, TString *typename /* only if tt is USERDATA */) { /* do we need to convert ? */ - if (ravi_type == RAVI_TNUMFLT || ravi_type == RAVI_TNUMINT) + if (ravi_type_map == RAVI_TM_FLOAT || ravi_type_map == RAVI_TM_INTEGER) /* code an instruction to convert in place */ luaK_codeABC(ls->fs, - ravi_type == RAVI_TNUMFLT ? OP_RAVI_TOFLT : OP_RAVI_TOINT, reg, + ravi_type_map == RAVI_TM_FLOAT ? OP_RAVI_TOFLT : OP_RAVI_TOINT, reg, 0, 0); - else if (ravi_type == RAVI_TARRAYINT || ravi_type == RAVI_TARRAYFLT) - luaK_codeABC(ls->fs, ravi_type == RAVI_TARRAYINT ? OP_RAVI_TOIARRAY + 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 == RAVI_TTABLE) + else if (ravi_type_map == RAVI_TM_TABLE) luaK_codeABC(ls->fs, OP_RAVI_TOTAB, reg, 0, 0); - else if (ravi_type == RAVI_TUSERDATA) + 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 == RAVI_TSTRING) + 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 == RAVI_TFUNCTION) + else if (ravi_type_map == RAVI_TM_FUNCTION | RAVI_TM_NIL) luaK_codeABC(ls->fs, OP_RAVI_TOCLOSURE, reg, 0, 0); + // TODO coerse to boolean } /* RAVI code an instruction to initialize a scalar typed value @@ -609,14 +673,16 @@ static void ravi_code_typecoersion(LexState *ls, int reg, ravitype_t ravi_type, */ static void ravi_code_setzero(FuncState *fs, int reg, ravitype_t ravi_type, TString *usertype) { (void) usertype; - if (ravi_type == RAVI_TNUMFLT || ravi_type == RAVI_TNUMINT) + if (ravi_type == RAVI_TM_FLOAT || ravi_type == RAVI_TM_INTEGER) /* code an instruction to convert in place */ - luaK_codeABC(fs, ravi_type == RAVI_TNUMFLT ? OP_RAVI_LOADFZ : OP_RAVI_LOADIZ, reg, 0, 0); - else if (ravi_type == RAVI_TARRAYFLT) + luaK_codeABC(fs, ravi_type == RAVI_TM_FLOAT ? OP_RAVI_LOADFZ : OP_RAVI_LOADIZ, reg, 0, 0); + else if (~(ravi_type & RAVI_TM_NIL)) + luaX_syntaxerror(fs->ls, "uninitialized number[] in local variable"); // TODO + else if (ravi_type == RAVI_TM_FLOAT_ARRAY) luaX_syntaxerror(fs->ls, "uninitialized number[] in local variable"); - else if (ravi_type == RAVI_TARRAYINT) + else if (ravi_type == RAVI_TM_INTEGER_ARRAY) luaX_syntaxerror(fs->ls, "uninitialized integer[] in local variable"); - else if (ravi_type == RAVI_TTABLE) + else if (ravi_type == RAVI_TM_TABLE) luaX_syntaxerror(fs->ls, "uninitialized table in local variable"); } @@ -647,10 +713,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); - ravitype_t ravi_type = ls->fs->f->locvars[idx].ravi_type; /* get variable's type */ + uint32_t ravi_type_map = 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, usertype); + ravi_code_typecoersion(ls, i, ravi_type_map, usertype); } } @@ -664,10 +730,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); - ravitype_t ravi_type = fs->f->locvars[idx].ravi_type; /* get variable's type */ + uint32_t ravi_type_map = 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, usertype); + ravi_code_setzero(fs, i, ravi_type_map, usertype); } } @@ -929,7 +995,7 @@ static void codeclosure (LexState *ls, expdesc *v, int deferred) { if (deferred) { pc = luaK_codeABC(fs, OP_RAVI_DEFER, 0, 0, 0); } - init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np - 1), RAVI_TFUNCTION, NULL); + init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np - 1), RAVI_TM_FUNCTION, NULL); luaK_exp2nextreg(fs, v); /* fix it at the last register */ if (deferred) { SETARG_A(fs->f->code[pc], v->u.info); @@ -939,7 +1005,7 @@ static void codeclosure (LexState *ls, expdesc *v, int deferred) { #else static void codeclosure (LexState *ls, expdesc *v) { FuncState *fs = ls->fs->prev; - init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np - 1), RAVI_TFUNCTION, NULL); + init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np - 1), RAVI_TM_FUNCTION, NULL); luaK_exp2nextreg(fs, v); /* fix it at the last register */ DEBUG_VARS(raviY_printf(ls->fs, "codeclosure -> closure created %e\n", v)); } @@ -1032,7 +1098,7 @@ static void statlist (LexState *ls) { static void fieldsel (LexState *ls, expdesc *v) { /* fieldsel -> ['.' | ':'] NAME */ FuncState *fs = ls->fs; - expdesc key = {.ravi_type = RAVI_TANY, .pc = -1}; + expdesc key = {.ravi_type_map = RAVI_TM_ANY, .pc = -1}; luaK_exp2anyregup(fs, v); luaX_next(ls); /* skip the dot or colon */ checkname(ls, &key); @@ -1069,8 +1135,8 @@ static void recfield (LexState *ls, struct ConsControl *cc) { /* recfield -> (NAME | '['exp1']') = exp1 */ FuncState *fs = ls->fs; int reg = ls->fs->freereg; - expdesc key = {.ravi_type = RAVI_TANY, .pc = -1}, - val = {.ravi_type = RAVI_TANY, .pc = -1}; + expdesc key = {.ravi_type_map = RAVI_TM_ANY, .pc = -1}, + val = {.ravi_type_map = RAVI_TM_ANY, .pc = -1}; int rkkey; if (ls->t.token == TK_NAME) { checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); @@ -1153,9 +1219,9 @@ static void constructor (LexState *ls, expdesc *t) { struct ConsControl cc; cc.na = cc.nh = cc.tostore = 0; cc.t = t; - init_exp(t, VRELOCABLE, pc, RAVI_TTABLE, NULL); /* RAVI initial type may be modified */ + init_exp(t, VRELOCABLE, pc, RAVI_TM_TABLE, NULL); /* RAVI initial type may be modified */ t->pc = pc; /* RAVI save pc of OP_NEWTABLE instruction so that the correct type can be set later */ - init_exp(&cc.v, VVOID, 0, RAVI_TANY, NULL); /* no value (yet) */ + init_exp(&cc.v, VVOID, 0, RAVI_TM_ANY, NULL); /* no value (yet) */ luaK_exp2nextreg(ls->fs, t); /* fix it at stack top */ checknext(ls, '{'); do { @@ -1217,7 +1283,7 @@ static ravitype_t declare_localvar(LexState *ls, TString **pusertype) { /* RAVI change - add type */ TString *name = str_checkname(ls); /* assume a dynamic type */ - ravitype_t tt = RAVI_TANY; + ravitype_t tm = RAVI_TM_ANY; /* if the variable name is followed by a colon then we have a type * specifier */ @@ -1229,36 +1295,36 @@ static ravitype_t declare_localvar(LexState *ls, TString **pusertype) { * the lexer doesn't need to be changed */ if (strcmp(str, "integer") == 0) - tt = RAVI_TNUMINT; + tm = RAVI_TM_INTEGER; else if (strcmp(str, "number") == 0) - tt = RAVI_TNUMFLT; + tm = RAVI_TM_FLOAT; else if (strcmp(str, "closure") == 0) - tt = RAVI_TFUNCTION; + tm = RAVI_TM_FUNCTION | RAVI_TM_NIL; else if (strcmp(str, "table") == 0) - tt = RAVI_TTABLE; + tm = RAVI_TM_TABLE; else if (strcmp(str, "string") == 0) - tt = RAVI_TSTRING; + tm = RAVI_TM_STRING | RAVI_TM_NIL; else if (strcmp(str, "boolean") == 0) - tt = RAVI_TBOOLEAN; + tm = RAVI_TM_BOOLEAN | RAVI_TM_NIL; else if (strcmp(str, "any") == 0) - tt = RAVI_TANY; + tm = RAVI_TM_ANY; else { /* default is a userdata type */ - tt = RAVI_TUSERDATA; + tm = RAVI_TM_USERDATA | RAVI_TM_NIL; typename = user_defined_type_name(ls, typename); str = getstr(typename); *pusertype = typename; } - if (tt == RAVI_TNUMFLT || tt == RAVI_TNUMINT) { + if (tm == RAVI_TM_FLOAT || tm == RAVI_TM_INTEGER) { /* if we see [] then it is an array type */ if (testnext(ls, '[')) { checknext(ls, ']'); - tt = (tt == RAVI_TNUMFLT) ? RAVI_TARRAYFLT : RAVI_TARRAYINT; + tm = (tm == RAVI_TM_FLOAT) ? RAVI_TM_FLOAT_ARRAY : RAVI_TM_INTEGER_ARRAY; } } } - new_localvar(ls, name, tt, *pusertype); - return tt; + new_localvar(ls, name, tm, *pusertype); + return tm; } static void parlist (LexState *ls) { @@ -1481,7 +1547,7 @@ static int localvar_explist(LexState *ls, expdesc *v, int *vars, TString** usert /* parse function arguments */ static void funcargs (LexState *ls, expdesc *f, int line) { FuncState *fs = ls->fs; - expdesc args = {.ravi_type = RAVI_TANY, .pc = -1}; + expdesc args = {.ravi_type_map = RAVI_TM_ANY, .pc = -1}; int base, nparams; switch (ls->t.token) { case '(': { /* funcargs -> '(' [ explist ] ')' */ @@ -1517,7 +1583,7 @@ static void funcargs (LexState *ls, expdesc *f, int line) { luaK_exp2nextreg(fs, &args); /* close last argument */ nparams = fs->freereg - (base+1); } - init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams + 1, 2), RAVI_TANY, NULL); /* RAVI TODO return value from function call not known */ + init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams + 1, 2), RAVI_TM_ANY, NULL); /* RAVI TODO return value from function call not known */ luaK_fixline(fs, line); fs->freereg = base+1; /* call remove function and arguments and leaves (unless changed) one result */ @@ -1568,14 +1634,14 @@ static void suffixedexp (LexState *ls, expdesc *v) { break; } case '[': { /* '[' exp1 ']' */ - expdesc key = {.ravi_type = RAVI_TANY, .pc = -1}; + expdesc key = {.ravi_type_map = RAVI_TM_ANY, .pc = -1}; luaK_exp2anyregup(fs, v); yindex(ls, &key); luaK_indexed(fs, v, &key); break; } case ':': { /* ':' NAME funcargs */ - expdesc key = {.ravi_type = RAVI_TANY, .pc = -1}; + expdesc key = {.ravi_type_map = RAVI_TM_ANY, .pc = -1}; luaX_next(ls); checkname(ls, &key); luaK_self(fs, v, &key); @@ -1598,12 +1664,12 @@ static void simpleexp (LexState *ls, expdesc *v) { constructor | FUNCTION body | suffixedexp */ switch (ls->t.token) { case TK_FLT: { - init_exp(v, VKFLT, 0, RAVI_TNUMFLT, NULL); + init_exp(v, VKFLT, 0, RAVI_TM_FLOAT, NULL); v->u.nval = ls->t.seminfo.r; break; } case TK_INT: { - init_exp(v, VKINT, 0, RAVI_TNUMINT, NULL); + init_exp(v, VKINT, 0, RAVI_TM_INTEGER, NULL); v->u.ival = ls->t.seminfo.i; break; } @@ -1612,22 +1678,22 @@ static void simpleexp (LexState *ls, expdesc *v) { break; } case TK_NIL: { - init_exp(v, VNIL, 0, RAVI_TNIL, NULL); + init_exp(v, VNIL, 0, RAVI_TM_NIL, NULL); break; } case TK_TRUE: { - init_exp(v, VTRUE, 0, RAVI_TANY, NULL); /* RAVI TODO */ + init_exp(v, VTRUE, 0, RAVI_TM_TRUE, NULL); /* RAVI TODO */ break; } case TK_FALSE: { - init_exp(v, VFALSE, 0, RAVI_TANY, NULL); /* RAVI TODO */ + init_exp(v, VFALSE, 0, RAVI_TM_FALSE, NULL); /* RAVI TODO */ break; } case TK_DOTS: { /* vararg */ FuncState *fs = ls->fs; check_condition(ls, fs->f->is_vararg, "cannot use '...' outside a vararg function"); - init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0), RAVI_TANY, NULL); + init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0), RAVI_TM_ANY, NULL); break; } case '{': { /* constructor */ @@ -1750,7 +1816,7 @@ static BinOpr subexpr (LexState *ls, expdesc *v, int limit) { /* expand while operators have priorities higher than 'limit' */ op = getbinopr(ls->t.token); while (op != OPR_NOBINOPR && priority[op].left > limit) { - expdesc v2 = {.ravi_type = RAVI_TANY, .pc = -1}; + expdesc v2 = {.ravi_type_map = RAVI_TM_ANY, .pc = -1}; BinOpr nextop; int line = ls->linenumber; luaX_next(ls); @@ -1841,10 +1907,10 @@ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { * The final recursive call parses the rhs. */ static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { - expdesc e = {.ravi_type = RAVI_TANY, .pc = -1}; + expdesc e = {.ravi_type_map = RAVI_TM_ANY, .pc = -1}; check_condition(ls, vkisvar(lh->v.k), "syntax error"); if (testnext(ls, ',')) { /* assignment -> ',' suffixedexp assignment */ - struct LHS_assign nv = { .v.ravi_type = RAVI_TANY, .v.pc = -1 }; + struct LHS_assign nv = { .v.ravi_type_map = RAVI_TM_ANY, .v.pc = -1 }; //nv.v.ravi_type = RAVI_TANY; //nv.v.pc = -1; nv.prev = lh; @@ -1871,7 +1937,7 @@ static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { return; /* avoid default */ } } - init_exp(&e, VNONRELOC, ls->fs->freereg-1, RAVI_TANY, NULL); /* default assignment */ + init_exp(&e, VNONRELOC, ls->fs->freereg-1, RAVI_TM_ANY, NULL); /* default assignment */ luaK_storevar(ls->fs, &lh->v, &e); DEBUG_EXPR(raviY_printf(ls->fs, "assignment lhs = %e, rhs = %e\n", &lh->v, &e)); } @@ -1881,7 +1947,7 @@ static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { */ static int cond (LexState *ls) { /* cond -> exp */ - expdesc v = {.ravi_type = RAVI_TANY, .pc = -1}; + expdesc v = {.ravi_type_map = RAVI_TM_ANY, .pc = -1}; expr(ls, &v); /* read condition */ if (v.k == VNIL) v.k = VFALSE; /* 'falses' are all equal here */ luaK_goiftrue(ls->fs, &v); @@ -1986,7 +2052,7 @@ static void repeatstat (LexState *ls, int line) { } typedef struct Fornuminfo { - ravitype_t type; + uint32_t type_map; int is_constant; int int_value; } Fornuminfo; @@ -2000,7 +2066,7 @@ static int exp1 (LexState *ls, Fornuminfo *info) { * type - also the loop is already optimised so no point trying to * optimise the iteration variable */ - expdesc e = {.ravi_type = RAVI_TANY, .pc = -1}; + expdesc e = {.ravi_type_map = RAVI_TM_ANY, .pc = -1}; int reg; int expect_int = 0; if (ls->t.token == '#') @@ -2012,12 +2078,12 @@ static int exp1 (LexState *ls, Fornuminfo *info) { luaK_exp2nextreg(ls->fs, &e); lua_assert(e.k == VNONRELOC); reg = e.u.info; - if (expect_int && e.ravi_type != RAVI_TNUMINT) { + if (expect_int && e.ravi_type_map != RAVI_TM_INTEGER) { luaK_codeABC(ls->fs, OP_RAVI_TOINT, reg, 0, 0); - info->type = RAVI_TNUMINT; + info->type_map = RAVI_TM_INTEGER; } else { - info->type = e.ravi_type; + info->type_map = e.ravi_type_map; } return reg; } @@ -2072,7 +2138,7 @@ static void fornum (LexState *ls, TString *varname, int line) { new_localvarliteral(ls, "(for index)"); new_localvarliteral(ls, "(for limit)"); new_localvarliteral(ls, "(for step)"); - new_localvar(ls, varname, RAVI_TANY, NULL); + new_localvar(ls, varname, RAVI_TM_ANY, NULL); /* The fornum sets up its own variables as above. These are expected to hold numeric values - but from Ravi's point of view we need to know if the variable is an integer or @@ -2083,7 +2149,7 @@ static void fornum (LexState *ls, TString *varname, int line) { int var_idx = fs->nlocvars - 4; /* note location of idx variable */ checknext(ls, '='); /* get the type of each expression */ - Fornuminfo tidx = { RAVI_TANY,0,0 }, tlimit = { RAVI_TANY,0,0 }, tstep = { RAVI_TNUMINT,0,0 }; + Fornuminfo tidx = { RAVI_TM_ANY,0,0 }, tlimit = { RAVI_TM_ANY,0,0 }, tstep = { RAVI_TM_INTEGER,0,0 }; Fornuminfo *info = NULL; exp1(ls, &tidx); /* initial value */ checknext(ls, ','); @@ -2096,10 +2162,10 @@ static void fornum (LexState *ls, TString *varname, int line) { luaK_codek(fs, fs->freereg, luaK_intK(fs, 1)); luaK_reserveregs(fs, 1); } - if (tidx.type == tlimit.type && tlimit.type == tstep.type && - (tidx.type == RAVI_TNUMFLT || tidx.type == RAVI_TNUMINT)) { + if (tidx.type_map == tlimit.type_map && tlimit.type_map == tstep.type_map && + (tidx.type_map == RAVI_TM_FLOAT || tidx.type_map == RAVI_TM_INTEGER)) { LocVar *vidx, *vlimit, *vstep, *vvar; - if (tidx.type == RAVI_TNUMINT && tstep.is_constant) + if (tidx.type_map == RAVI_TM_INTEGER && tstep.is_constant) info = &tstep; /* Note that as locvars may be reallocated while creating variables therefore we access the variables here */ @@ -2108,7 +2174,7 @@ static void fornum (LexState *ls, TString *varname, int line) { vstep = &fs->f->locvars[var_idx+2]; /* index variable - not yet active so get it from locvars*/ vvar = &fs->f->locvars[var_idx+3]; /* index variable - not yet active so get it from locvars*/ /* Ok so we have an integer or double */ - vidx->ravi_type = vlimit->ravi_type = vstep->ravi_type = vvar->ravi_type = tidx.type; + vidx->ravi_type_map = vlimit->ravi_type_map = vstep->ravi_type_map = vvar->ravi_type_map = tidx.type_map; DEBUG_VARS(raviY_printf(fs, "fornum -> setting type for index %v\n", vidx)); DEBUG_VARS(raviY_printf(fs, "fornum -> setting type for limit %v\n", vlimit)); DEBUG_VARS(raviY_printf(fs, "fornum -> setting type for step %v\n", vstep)); @@ -2123,7 +2189,7 @@ static void fornum (LexState *ls, TString *varname, int line) { static void forlist (LexState *ls, TString *indexname) { /* forlist -> NAME {,NAME} IN explist forbody */ FuncState *fs = ls->fs; - expdesc e = {.ravi_type = RAVI_TANY, .pc = -1}; + expdesc e = {.ravi_type_map = RAVI_TM_ANY, .pc = -1}; int nvars = 4; /* gen, state, control, plus at least one declared var */ int line; int base = fs->freereg; @@ -2132,9 +2198,9 @@ static void forlist (LexState *ls, TString *indexname) { new_localvarliteral(ls, "(for state)"); new_localvarliteral(ls, "(for control)"); /* create declared variables */ - new_localvar(ls, indexname, RAVI_TANY, NULL); /* RAVI TODO for name:type syntax? */ + new_localvar(ls, indexname, RAVI_TM_ANY, NULL); /* RAVI TODO for name:type syntax? */ while (testnext(ls, ',')) { - new_localvar(ls, str_checkname(ls), RAVI_TANY, NULL); /* RAVI change - add type */ + new_localvar(ls, str_checkname(ls), RAVI_TM_ANY, NULL); /* RAVI change - add type */ nvars++; } checknext(ls, TK_IN); @@ -2169,7 +2235,7 @@ static void test_then_block (LexState *ls, int *escapelist) { /* test_then_block -> [IF | ELSEIF] cond THEN block */ BlockCnt bl; FuncState *fs = ls->fs; - expdesc v = {.ravi_type = RAVI_TANY, .pc = -1}; + expdesc v = {.ravi_type_map = RAVI_TM_ANY, .pc = -1}; int jf; /* instruction to skip 'then' code (if condition is false) */ luaX_next(ls); /* skip IF or ELSEIF */ expr(ls, &v); /* read condition */ @@ -2216,16 +2282,16 @@ static void ifstat (LexState *ls, int line) { /* parse a local function statement - called from statement() */ #ifdef RAVI_DEFER_STATEMENT static void localfunc (LexState *ls, int defer) { - expdesc b = {.ravi_type = RAVI_TANY, .pc = -1}; + expdesc b = {.ravi_type_map = RAVI_TM_ANY, .pc = -1}; FuncState *fs = ls->fs; if (defer) { static const char funcname[] = "(deferred function)"; - new_localvar(ls, luaX_newstring(ls, funcname, sizeof funcname-1), RAVI_TFUNCTION, NULL); /* new local variable */ + new_localvar(ls, luaX_newstring(ls, funcname, sizeof funcname-1), RAVI_TM_FUNCTION, NULL); /* new local variable */ markupval(fs, fs->nactvar); fs->bl->insidetbc = 1; /* in the scope of a defer closure variable */ } else { /* RAVI change - add type */ - new_localvar(ls, str_checkname(ls), RAVI_TFUNCTION, NULL); /* new local variable */ + new_localvar(ls, str_checkname(ls), RAVI_TM_FUNCTION, NULL); /* new local variable */ } adjustlocalvars(ls, 1); /* enter its scope */ body(ls, &b, 0, ls->linenumber, defer); /* function created in next register */ @@ -2250,7 +2316,7 @@ static void localstat (LexState *ls) { /* stat -> LOCAL NAME {',' NAME} ['=' explist] */ int nvars = 0; int nexps; - expdesc e = { .ravi_type = RAVI_TANY,.pc = -1 }; + expdesc e = { .ravi_type_map = RAVI_TM_ANY,.pc = -1 }; /* RAVI while declaring locals we need to gather the types * so that we can check any assignments later on. * TODO we may be able to use register_typeinfo() here @@ -2298,8 +2364,8 @@ static int funcname (LexState *ls, expdesc *v) { static void funcstat (LexState *ls, int line) { /* funcstat -> FUNCTION funcname body */ int ismethod; - expdesc v = {.ravi_type = RAVI_TANY, .pc = -1}, - b = {.ravi_type = RAVI_TANY, .pc = -1}; + expdesc v = {.ravi_type_map = RAVI_TM_ANY, .pc = -1}, + b = {.ravi_type_map = RAVI_TM_ANY, .pc = -1}; luaX_next(ls); /* skip FUNCTION */ ismethod = funcname(ls, &v); DEBUG_VARS(raviY_printf(ls->fs, "funcstat -> declaring function %e\n", &v)); @@ -2317,7 +2383,7 @@ static void exprstat (LexState *ls) { /* stat -> func | assignment */ FuncState *fs = ls->fs; struct LHS_assign v; - v.v.ravi_type = RAVI_TANY; + v.v.ravi_type_map = RAVI_TM_ANY; suffixedexp(ls, &v.v); if (ls->t.token == '=' || ls->t.token == ',') { /* stat -> assignment ? */ v.prev = NULL; @@ -2333,7 +2399,7 @@ static void exprstat (LexState *ls) { static void retstat (LexState *ls) { /* stat -> RETURN [explist] [';'] */ FuncState *fs = ls->fs; - expdesc e = {.ravi_type = RAVI_TANY, .pc = -1}; + expdesc e = {.ravi_type_map = RAVI_TM_ANY, .pc = -1}; int first, nret; /* registers with returned values */ if (block_follow(ls, 1) || ls->t.token == ';') first = nret = 0; /* return no values */ @@ -2451,10 +2517,10 @@ static void statement (LexState *ls) { */ static void mainfunc (LexState *ls, FuncState *fs) { BlockCnt bl; - expdesc v = {.ravi_type = RAVI_TANY, .pc = -1}; + expdesc v = {.ravi_type_map = RAVI_TM_ANY, .pc = -1}; open_func(ls, fs, &bl); fs->f->is_vararg = 1; /* main function is always declared vararg */ - init_exp(&v, VLOCAL, 0, RAVI_TANY, NULL); /* create and... - RAVI TODO var arg is unknown type */ + init_exp(&v, VLOCAL, 0, RAVI_TM_ANY, NULL); /* create and... - RAVI TODO var arg is unknown type */ newupvalue(fs, ls->envn, &v); /* ...set environment upvalue */ luaC_objbarrier(ls->L, fs->f, ls->envn); luaX_next(ls); /* read first token */ diff --git a/src/lparser.h b/src/lparser.h index 19696af..018b367 100644 --- a/src/lparser.h +++ b/src/lparser.h @@ -66,13 +66,15 @@ 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) */ - lu_byte key_ravi_type; /* RAVI change: key type */ + uint32_t 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' */ - lu_byte ravi_type; /* RAVI change: type of the expression if known, else RAVI_TANY */ + uint32_t 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 */ } expdesc; From 7789f4f32db19c326cf8d5f2e0e0e991cb1681b2 Mon Sep 17 00:00:00 2001 From: XmiliaH Date: Fri, 19 Feb 2021 16:39:29 +0100 Subject: [PATCH 2/6] Finish type maps --- src/lapi.c | 38 ++++----- src/lcode.c | 94 +++++++++++++-------- src/ldebug.c | 21 ++--- src/ldump.c | 20 ++++- src/lfunc.c | 6 +- src/lfunc.h | 2 +- src/lobject.c | 16 ++++ src/lobject.h | 46 +++++----- src/lparser.c | 144 ++++++++++++++------------------ src/lparser.h | 6 +- src/ltable.c | 18 ++-- src/ltable.h | 2 +- src/ltests.c | 2 +- src/lundump.c | 21 ++++- src/lvm.c | 8 +- tests/language/ravi_tests1.ravi | 2 +- 16 files changed, 237 insertions(+), 209 deletions(-) diff --git a/src/lapi.c b/src/lapi.c index 9eac09a..e3b5027 100644 --- a/src/lapi.c +++ b/src/lapi.c @@ -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, - CClosure **owner, UpVal **uv, ravitype_t *type) { - *type = RAVI_TANY; + CClosure **owner, UpVal **uv, ravi_type_map *type) { + *type = RAVI_TM_ANY; switch (ttype(fi)) { case LUA_TCCL: { /* C closure */ 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; if (uv) *uv = f->upvals[n - 1]; 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); } 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) { const char *name; - ravitype_t type; + ravi_type_map type; TValue *val = NULL; /* to avoid warnings */ lua_lock(L); 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; } - LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { const char *name; TValue *val = NULL; /* to avoid warnings */ CClosure *owner = NULL; UpVal *uv = NULL; 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); fi = index2addr(L, funcindex); 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 ** 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; - int 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) - name = NULL; - } + + StkId input = L->top - 1; + int compatible = ravi_checktype(input, type); + + if (!compatible) + name = NULL; } if (name) { 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; StkId fi = index2addr(L, fidx); api_check(L, ttisLclosure(fi), "Lua function expected"); f = clLvalue(fi); 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; 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, int fidx2, int n2) { LClosure *f1; - ravitype_t t1, t2; + ravi_type_map t1, t2; UpVal **up1 = getupvalref(L, fidx1, n1, &f1, &t1); UpVal **up2 = getupvalref(L, fidx2, n2, NULL, &t2); if (t1 == t2 && *up1 != *up2) { diff --git a/src/lcode.c b/src/lcode.c index 93438cd..f7d02a5 100644 --- a/src/lcode.c +++ b/src/lcode.c @@ -621,7 +621,7 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) { else 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))) { result_type = RAVI_TM_ANY; } else { @@ -683,28 +683,28 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) { TString *usertype = NULL; int ravi_type = raviY_get_register_typeinfo(fs, reg, &usertype); switch (ravi_type) { - case RAVI_TNUMINT: + case RAVI_TM_INTEGER: luaK_codeABC(fs, OP_RAVI_MOVEI, reg, e->u.info, 0); break; - case RAVI_TNUMFLT: + case RAVI_TM_FLOAT: luaK_codeABC(fs, OP_RAVI_MOVEF, reg, e->u.info, 0); break; - case RAVI_TARRAYINT: + case RAVI_TM_INTEGER_ARRAY: luaK_codeABC(fs, OP_RAVI_MOVEIARRAY, reg, e->u.info, 0); break; - case RAVI_TARRAYFLT: + case RAVI_TM_FLOAT_ARRAY: luaK_codeABC(fs, OP_RAVI_MOVEFARRAY, reg, e->u.info, 0); break; - case RAVI_TTABLE: + case RAVI_TM_TABLE: luaK_codeABC(fs, OP_RAVI_MOVETAB, reg, e->u.info, 0); break; default: 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); - 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); - 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)); break; } @@ -862,7 +862,6 @@ int luaK_exp2RK (FuncState *fs, expdesc *e) { } 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? */ if (ex->k == VNONRELOC && (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 */ 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 (ex->ravi_type_map == RAVI_TM_FLOAT) + if (ex_ravi_type_map == RAVI_TM_FLOAT) return; luaX_syntaxerror( fs->ls, @@ -886,7 +895,7 @@ static void check_valid_store(FuncState *fs, expdesc *var, expdesc *ex) { "Invalid assignment: number expected")); } 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; luaX_syntaxerror( fs->ls, @@ -894,8 +903,8 @@ static void check_valid_store(FuncState *fs, expdesc *var, expdesc *ex) { fs->ls->L, "Invalid assignment: integer expected")); } - 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) + 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) return; luaX_syntaxerror( 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[]"))); } 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; luaX_syntaxerror( fs->ls, @@ -914,7 +923,7 @@ static void check_valid_store(FuncState *fs, expdesc *var, expdesc *ex) { "Invalid assignment: string expected")); } 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; luaX_syntaxerror( fs->ls, @@ -923,8 +932,8 @@ static void check_valid_store(FuncState *fs, expdesc *var, expdesc *ex) { "Invalid assignment: function expected")); } else if (var->ravi_type_map == (RAVI_TM_USERDATA | RAVI_TM_NIL)) { - 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))) + 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))) return; luaX_syntaxerror( 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, 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; 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_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_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)) && ex->ravi_type_map & ~var->ravi_type_map) { if (var->ravi_type_map == RAVI_TM_INTEGER) op = OP_RAVI_SETUPVALI; @@ -953,21 +961,27 @@ static OpCode check_valid_setupval(FuncState *fs, expdesc *var, expdesc *ex, op = OP_RAVI_SETUPVAL_FARRAY; else if (var->ravi_type_map == RAVI_TM_TABLE) 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); - 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); - 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; 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, "Invalid assignment of " "upvalue: upvalue type " "%s, expression type %s", - raviY_typename(var->ravi_type), - raviY_typename(ex->ravi_type))); + var_type_map_str, + ex_type_map_str)); + } } 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) { switch (var->k) { case VLOCAL: { + check_valid_store(fs, var, ex); freeexp(fs, ex); exp2reg(fs, ex, var->u.info); /* compute 'ex' into proper place */ - check_valid_store(fs, var, ex); return; } case VUPVAL: { @@ -1535,17 +1549,17 @@ static void code_type_assertion(FuncState *fs, UnOpr op, expdesc *e, TString *us opcode = OP_RAVI_TOTAB; 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; - 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; - tm = RAVI_TM_FUNCTION; + tm = RAVI_TM_FUNCTION | RAVI_TM_NIL; } else if (op == OPR_TO_TYPE) { - opcode = OP_RAVI_TOTYPE; - tm = RAVI_TM_USERDATA; + opcode = OP_RAVI_TOTYPE; + tm = RAVI_TM_USERDATA | RAVI_TM_NIL; } else { /* 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' */ luaK_dischargevars(fs, e2); 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; break; } @@ -1658,7 +1676,11 @@ void luaK_posfix (FuncState *fs, BinOpr op, if (e1->usertype != e2->usertype) 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; break; } diff --git a/src/ldebug.c b/src/ldebug.c index 13ba22b..6408a1f 100644 --- a/src/ldebug.c +++ b/src/ldebug.c @@ -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, - StkId *pos, ravitype_t *type) { + StkId *pos, ravi_type_map *type) { const char *name = NULL; StkId base; - *type = RAVI_TANY; + *type = RAVI_TM_ANY; if (isLua(ci)) { if (n < 0) /* access to vararg values? */ 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) { const char *name; - ravitype_t type; + ravi_type_map type; lua_lock(L); swapextra(L); 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) { StkId pos = NULL; /* to avoid warnings */ const char *name; - ravitype_t type; + ravi_type_map type; int compatible = 1; lua_lock(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 ** 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; - 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)) - ; - } + StkId input = L->top - 1; + int compatible = ravi_checktype(input, type); if (compatible) { setobjs2s(L, pos, L->top - 1); 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, const char **name) { int pc; - ravitype_t type; + ravi_type_map type; *name = luaF_getlocalname(p, reg + 1, lastpc, &type); if (*name) /* is a local? */ return "local"; diff --git a/src/ldump.c b/src/ldump.c index 32aa8ce..f6a57de 100644 --- a/src/ldump.c +++ b/src/ldump.c @@ -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) { int i, n; @@ -163,7 +179,7 @@ static void DumpDebug (const Proto *f, DumpState *D) { DumpString((D->strip) ? NULL : f->locvars[i].varname, D); DumpInt(f->locvars[i].startpc, 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); } /* n = (D->strip) ? 0 : f->sizeupvalues; */ @@ -171,7 +187,7 @@ static void DumpDebug (const Proto *f, DumpState *D) { DumpInt(n, D); for (i = 0; i < n; i++) { 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); } } diff --git a/src/lfunc.c b/src/lfunc.c index 09db3d9..e4bc138 100644 --- a/src/lfunc.c +++ b/src/lfunc.c @@ -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, ravitype_t *type) { +const char *luaF_getlocalname (const Proto *f, int local_number, int pc, ravi_type_map *type) { int i; for (i = 0; isizelocvars && f->locvars[i].startpc <= pc; i++) { 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 (f->locvars[i].varname == NULL) break; - *type = f->locvars[i].ravi_type; + *type = f->locvars[i].ravi_type_map; return getstr(f->locvars[i].varname); } } } - *type = RAVI_TANY; + *type = RAVI_TM_ANY; return NULL; /* not found */ } diff --git a/src/lfunc.h b/src/lfunc.h index 21f1aa2..a945b0a 100644 --- a/src/lfunc.h +++ b/src/lfunc.h @@ -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, ravitype_t* type); + int pc, ravi_type_map* type); #endif diff --git a/src/lobject.c b/src/lobject.c index 24a20a1..b8bf65b 100644 --- a/src/lobject.c +++ b/src/lobject.c @@ -33,6 +33,22 @@ 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 ** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if diff --git a/src/lobject.h b/src/lobject.h index ad5f12b..028d3d0 100644 --- a/src/lobject.h +++ b/src/lobject.h @@ -54,19 +54,6 @@ typedef uint16_t LuaType; ** we care about from a performance point of view - if 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 { RAVI_TI_NIL, @@ -83,18 +70,20 @@ typedef enum { RAVI_TI_OTHER } ravi_type_index; -#define RAVI_TM_NIL (1<ravi_type_map, type_map_str); switch (e->k) { @@ -187,10 +161,14 @@ static void v(FILE *fp, FuncState *fs, const expdesc *e) { type_map_str); break; 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, - raviY_typename(raviY_get_register_typeinfo(fs, e->u.info, NULL)), + var_type_map_str, type_map_str, e->pc); + } break; case VLOCAL: 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); break; 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( 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)), - raviY_typename(raviY_get_register_typeinfo(fs, GETARG_A(getinstruction(fs, e)), NULL)), + var_type_map_str, type_map_str); + } break; case VVARARG: 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); cp++; } else if (cp[0] == '%' && cp[1] == 't') { - ravitype_t i; - i = va_arg(ap, ravitype_t); - fputs(raviY_typename(i), stdout); + ravi_type_map i; + char type_map_str[RAVI_TYPEMAP_MAX_LEN]; + i = va_arg(ap, ravi_type_map); + raviY_typemap_string(i, type_map_str); + fputs(type_map_str, stdout); cp++; } else { fputc(*cp, stdout); @@ -410,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, 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; Proto *f = fs->f; 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 * 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; Dyndata *dyd = ls->dyd; /* 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. * 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; LocVar *v; /* 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? */ /* RAVI set type of local var / expr if possible */ 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 */ if (!base) 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, 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 ? */ if (ravi_type_map == RAVI_TM_FLOAT || ravi_type_map == RAVI_TM_INTEGER) /* 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)) luaK_codeABC(ls->fs, OP_RAVI_TOSTRING, 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, reg, 0, 0); // 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 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; if (ravi_type == RAVI_TM_FLOAT || ravi_type == RAVI_TM_INTEGER) /* code an instruction to convert in place */ luaK_codeABC(fs, ravi_type == RAVI_TM_FLOAT ? OP_RAVI_LOADFZ : OP_RAVI_LOADIZ, reg, 0, 0); - else if (~(ravi_type & RAVI_TM_NIL)) - luaX_syntaxerror(fs->ls, "uninitialized number[] in local variable"); // TODO - else if (ravi_type == RAVI_TM_FLOAT_ARRAY) - luaX_syntaxerror(fs->ls, "uninitialized number[] in local variable"); - else if (ravi_type == RAVI_TM_INTEGER_ARRAY) - 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"); + else if ((ravi_type & RAVI_TM_NIL) == 0) { + char type_map_str[RAVI_TYPEMAP_MAX_LEN]; + raviY_typemap_string(ravi_type, type_map_str); + + luaX_syntaxerror(fs->ls, luaO_pushfstring(fs->ls->L, "uninitialized %s in local variable", type_map_str)); + } } @@ -713,7 +695,7 @@ 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); - 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; /* do we need to convert ? */ 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. */ 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; /* do we need to convert ? */ 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[]', * '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 */ TString *name = str_checkname(ls); /* 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 * specifier */ @@ -1333,7 +1315,7 @@ static void parlist (LexState *ls) { Proto *f = fs->f; int nparams = 0; enum { N = MAXVARS + 10 }; - int vars[N] = { 0 }; + ravi_type_map vars[N] = { 0 }; TString *typenames[N] = { NULL }; f->is_vararg = 0; 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 */ for (int i = 0; i < f->numparams; i++) { TString *usertype = NULL; - ravitype_t tt = raviY_get_register_typeinfo(fs, i, &usertype); - lua_assert((i < nparams && vars[i] == (int)tt) || 1); + ravi_type_map tm = raviY_get_register_typeinfo(fs, i, &usertype); + lua_assert((i < nparams && vars[i] == tm) || 1); lua_assert((i < nparams && usertype == typenames[i]) || 1); 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, 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 * 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) { /* NOTE that 'v' may not have register assigned yet */ - ravitype_t vartype = var_types[n]; - if (n < nvars && vartype != RAVI_TANY && v->ravi_type != vartype) { - if (v->ravi_type != vartype && - (vartype == RAVI_TARRAYFLT || vartype == RAVI_TARRAYINT) && + 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 @@ -1458,7 +1439,7 @@ static void ravi_typecheck(LexState *ls, expdesc *v, int *var_types, int reg = GETARG_A(*pc); if (reg == 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; SET_OPCODE(*pc, op); /* modify opcode */ DEBUG_CODEGEN( @@ -1471,11 +1452,10 @@ static void ravi_typecheck(LexState *ls, expdesc *v, int *var_types, luaX_syntaxerror(ls, "expecting array initializer"); } /* if we are calling a function then convert return types */ - else if (v->ravi_type != vartype && - (vartype == RAVI_TNUMFLT || vartype == RAVI_TNUMINT || - vartype == RAVI_TARRAYFLT || vartype == RAVI_TARRAYINT || - vartype == RAVI_TTABLE || vartype == RAVI_TSTRING || - vartype == RAVI_TFUNCTION || vartype == RAVI_TUSERDATA) && + 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() @@ -1502,15 +1482,15 @@ static void ravi_typecheck(LexState *ls, expdesc *v, int *var_types, /* do we need to convert ? */ 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) { - if ((vartype == RAVI_TNUMFLT && v->ravi_type != RAVI_TARRAYFLT) || - (vartype == RAVI_TNUMINT && v->ravi_type != RAVI_TARRAYINT)) + 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_TSTRING && v->ravi_type != RAVI_TSTRING) || - (vartype == RAVI_TFUNCTION && v->ravi_type != RAVI_TFUNCTION) || - vartype == RAVI_TUSERDATA) { + 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 @@ -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 * 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 } */ int n = 1; /* at least one expression */ expr(ls, v); @@ -2323,7 +2303,7 @@ static void localstat (LexState *ls) { * instead. */ enum { N = MAXVARS + 10 }; - int vars[N] = { 0 }; + ravi_type_map vars[N] = { 0 }; TString *usertypes[N] = { NULL }; do { /* RAVI changes start */ diff --git a/src/lparser.h b/src/lparser.h index 018b367..6737962 100644 --- a/src/lparser.h +++ b/src/lparser.h @@ -243,7 +243,9 @@ LUAI_FUNC LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, Dyndata *dyd, const char *name, int firstchar); /** 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: * %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 * 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) \ if ((ravi_parser_debug & 1) != 0) { \ diff --git a/src/ltable.c b/src/ltable.c index 4bdd5fd..4fe8f7b 100644 --- a/src/ltable.c +++ b/src/ltable.c @@ -503,19 +503,19 @@ Table *luaH_new (lua_State *L) { return t; } -RaviArray *raviH_new(lua_State *L, ravitype_t tt, int is_slice) { - lua_assert(tt == RAVI_TARRAYFLT || tt == RAVI_TARRAYINT); - GCObject *o = luaC_newobj(L, tt == RAVI_TARRAYFLT ? RAVI_TFARRAY : RAVI_TIARRAY, sizeof(RaviArray)); +RaviArray *raviH_new(lua_State *L, ravi_type_map tm, int is_slice) { + lua_assert(tm == RAVI_TM_FLOAT_ARRAY || tm == RAVI_TM_INTEGER_ARRAY); + GCObject *o = luaC_newobj(L, tm == RAVI_TM_FLOAT_ARRAY ? RAVI_TFARRAY : RAVI_TIARRAY, sizeof(RaviArray)); RaviArray *t = gco2array(o); t->len = 0; t->size = RAVI_ARRAY_MAX_INLINE; /* Initially we use inline storage */ - t->flags = (tt == RAVI_TARRAYFLT) ? RAVI_ARRAY_ISFLOAT : 0; - t->data = (tt == RAVI_TARRAYFLT) ? (char *) &t->numarray : (char *) &t->intarray; /* data */ + t->flags = (tm == RAVI_TM_FLOAT_ARRAY) ? RAVI_ARRAY_ISFLOAT : 0; + t->data = (tm == RAVI_TM_FLOAT_ARRAY) ? (char *) &t->numarray : (char *) &t->intarray; /* data */ t->parent = NULL; t->metatable = NULL; if (!is_slice) { /* 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); } 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, 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 if (new_len < len) { // Wrapped? 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, 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 if (new_len < len) { // Wrapped? 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( L, "cannot create slice from dynamic integer[] or number[] array"); /* 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 so we do not need a write barrier */ t->parent = orig; diff --git a/src/ltable.h b/src/ltable.h index 5f90d38..d5a91cf 100644 --- a/src/ltable.h +++ b/src/ltable.h @@ -124,7 +124,7 @@ LUAI_FUNC lua_Unsigned luaH_getn (Table *t); /* Creates a specialized version of Lua Table to support Ravi's * 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 int raviH_next(lua_State* L, RaviArray* t, StkId key); diff --git a/src/ltests.c b/src/ltests.c index 174855e..b01e8d1 100644 --- a/src/ltests.c +++ b/src/ltests.c @@ -644,7 +644,7 @@ static int listlocals (lua_State *L) { int pc = cast_int(luaL_checkinteger(L, 2)) - 1; int i = 0; const char *name; - ravitype_t tt; + ravi_type_map tt; luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1, "Lua function expected"); p = getproto(obj_at(L, 1)); diff --git a/src/lundump.c b/src/lundump.c index 69509cb..0f9f068 100644 --- a/src/lundump.c +++ b/src/lundump.c @@ -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) { int i, n; @@ -201,13 +218,13 @@ static void LoadDebug (LoadState *S, Proto *f) { f->locvars[i].varname = LoadString(S); f->locvars[i].startpc = 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); } n = LoadInt(S); for (i = 0; i < n; i++) { 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); } } diff --git a/src/lvm.c b/src/lvm.c index 80e9894..eb96425 100644 --- a/src/lvm.c +++ b/src/lvm.c @@ -2188,7 +2188,7 @@ int luaV_execute (lua_State *L) { vmcase(OP_RAVI_NEW_IARRAY) { RaviArray *t; 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); checkGC(L, ra + 1); vmbreak; @@ -2196,7 +2196,7 @@ int luaV_execute (lua_State *L) { vmcase(OP_RAVI_NEW_FARRAY) { RaviArray *t; 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); checkGC(L, ra + 1); 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) { - RaviArray *t = raviH_new(L, RAVI_TARRAYINT, 0); + RaviArray *t = raviH_new(L, RAVI_TM_INTEGER_ARRAY, 0); setiarrayvalue(L, ra, t); checkGC_(L, ra + 1); } 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); checkGC_(L, ra + 1); } diff --git a/tests/language/ravi_tests1.ravi b/tests/language/ravi_tests1.ravi index 22f1e0e..3c9fc8b 100644 --- a/tests/language/ravi_tests1.ravi +++ b/tests/language/ravi_tests1.ravi @@ -1523,7 +1523,7 @@ print 'Test 58 OK' function x(s1: string, s2: string) return @string( s1 .. s2 ) 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') compile(x) assert(x('a', 'b') == 'ab') From f80e4d544231196775da87f4a500714dbc89de16 Mon Sep 17 00:00:00 2001 From: XmiliaH Date: Fri, 19 Feb 2021 16:44:42 +0100 Subject: [PATCH 3/6] Fix concat --- src/lcode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lcode.c b/src/lcode.c index f7d02a5..8d21452 100644 --- a/src/lcode.c +++ b/src/lcode.c @@ -1399,7 +1399,7 @@ static void codebinexpval (FuncState *fs, OpCode op, RAVI_GEN_INT_OP(SHR); case OP_CONCAT: e1->u.info = luaK_codeABC(fs, op, 0, rk1, rk2); - if ((e1->ravi_type_map & (~(RAVI_TM_STRING | RAVI_TM_INTEGER | RAVI_TM_FLOAT))) == 0 || + if ((e1->ravi_type_map & (~(RAVI_TM_STRING | RAVI_TM_INTEGER | RAVI_TM_FLOAT))) == 0 && (e2->ravi_type_map & (~(RAVI_TM_STRING | RAVI_TM_INTEGER | RAVI_TM_FLOAT))) == 0) { e1->ravi_type_map = RAVI_TM_STRING; } From 435480f4dbc62ec10830998cc2f710dce14cbcde Mon Sep 17 00:00:00 2001 From: XmiliaH Date: Fri, 19 Feb 2021 18:54:42 +0100 Subject: [PATCH 4/6] Better deduction for not --- src/lcode.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/lcode.c b/src/lcode.c index 8d21452..63bf720 100644 --- a/src/lcode.c +++ b/src/lcode.c @@ -1168,17 +1168,14 @@ static void codenot (FuncState *fs, expdesc *e) { switch (e->k) { case VNIL: case VFALSE: { e->k = VTRUE; /* true == not nil == not false */ - e->ravi_type_map = RAVI_TM_TRUE; break; } case VK: case VKFLT: case VKINT: case VTRUE: { e->k = VFALSE; /* false == not "x" == not 0.5 == not 1 == not true */ - e->ravi_type_map = RAVI_TM_FALSE; break; } case VJMP: { negatecondition(fs, e); - e->ravi_type_map = RAVI_TM_BOOLEAN; break; } case VRELOCABLE: @@ -1187,11 +1184,12 @@ static void codenot (FuncState *fs, expdesc *e) { freeexp(fs, e); e->u.info = luaK_codeABC(fs, OP_NOT, 0, e->u.info, 0); e->k = VRELOCABLE; - e->ravi_type_map = RAVI_TM_BOOLEAN; break; } default: lua_assert(0); /* cannot happen */ } + e->ravi_type_map = ((e->ravi_type_map & RAVI_TM_TRUISH) ? RAVI_TM_FALSE : 0) | + ((e->ravi_type_map & RAVI_TM_FALSISH) ? RAVI_TM_TRUE : 0); /* interchange true and false lists */ { int temp = e->f; e->f = e->t; e->t = temp; } removevalues(fs, e->f); /* values are useless when negated */ @@ -1358,7 +1356,7 @@ static void codebinexpval (FuncState *fs, OpCode op, if ((e1->ravi_type_map & (~(RAVI_TM_FLOAT | RAVI_TM_INTEGER))) == 0 && \ (e1->ravi_type_map & (~(RAVI_TM_FLOAT | RAVI_TM_INTEGER))) == 0) { \ if (e1->ravi_type_map & e2->ravi_type_map & RAVI_TM_INTEGER) { \ - e1->ravi_type_map = RAVI_TM_FLOAT | RAVI_TM_INTEGER; \ + e1->ravi_type_map = RAVI_TM_FLOAT | ii; \ } \ else { \ e1->ravi_type_map = RAVI_TM_FLOAT; \ From a9537957d53136b43fa0b51f456c79dd1b1bab25 Mon Sep 17 00:00:00 2001 From: XmiliaH Date: Fri, 19 Feb 2021 21:04:24 +0100 Subject: [PATCH 5/6] Remove old ravi_type_t from jit --- src/ravi_jitshared.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/ravi_jitshared.c b/src/ravi_jitshared.c index 9e88221..1a9e7d5 100644 --- a/src/ravi_jitshared.c +++ b/src/ravi_jitshared.c @@ -299,19 +299,6 @@ static const char Lua_header[] = " { TValue *io=(o); const Udata *iu = (u); \\\n" " io->value_ = iu->user_; settt_(io, iu->ttuv_); \\\n" " checkliveness(L,io); }\n" - "typedef enum {\n" - " RAVI_TANY = 0,\n" - " RAVI_TNUMINT = 1,\n" - " RAVI_TNUMFLT,\n" - " RAVI_TARRAYINT,\n" - " RAVI_TARRAYFLT,\n" - " RAVI_TFUNCTION,\n" - " RAVI_TTABLE,\n" - " RAVI_TSTRING,\n" - " RAVI_TNIL,\n" - " RAVI_TBOOLEAN,\n" - " RAVI_TUSERDATA\n" - "} ravitype_t;\n" "typedef struct Upvaldesc {\n" " TString *name;\n" " TString *usertype;\n" From b4359b93913d6876c697fd95bcab93d180be7ab9 Mon Sep 17 00:00:00 2001 From: XmiliaH Date: Fri, 19 Feb 2021 22:47:51 +0100 Subject: [PATCH 6/6] Cleanup and Fixes --- src/lapi.c | 12 ++- src/lcode.c | 8 +- src/ldebug.c | 20 +++-- src/lfunc.c | 4 +- src/lfunc.h | 2 +- src/lobject.c | 6 +- src/lobject.h | 26 +++--- src/lparser.c | 221 +++++++++++++++++++++++++------------------------- src/lparser.h | 6 +- src/ltests.c | 3 +- 10 files changed, 159 insertions(+), 149 deletions(-) diff --git a/src/lapi.c b/src/lapi.c index e3b5027..f55874a 100644 --- a/src/lapi.c +++ b/src/lapi.c @@ -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; diff --git a/src/lcode.c b/src/lcode.c index 63bf720..0a7f406 100644 --- a/src/lcode.c +++ b/src/lcode.c @@ -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; diff --git a/src/ldebug.c b/src/ldebug.c index 6408a1f..4d0c1ff 100644 --- a/src/ldebug.c +++ b/src/ldebug.c @@ -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"; diff --git a/src/lfunc.c b/src/lfunc.c index e4bc138..0864e19 100644 --- a/src/lfunc.c +++ b/src/lfunc.c @@ -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; isizelocvars && 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 */ } diff --git a/src/lfunc.h b/src/lfunc.h index a945b0a..7f7b50d 100644 --- a/src/lfunc.h +++ b/src/lfunc.h @@ -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 diff --git a/src/lobject.c b/src/lobject.c index b8bf65b..2b26be2 100644 --- a/src/lobject.c +++ b/src/lobject.c @@ -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; } diff --git a/src/lobject.h b/src/lobject.h index 028d3d0..34ce3b5 100644 --- a/src/lobject.h +++ b/src/lobject.h @@ -72,18 +72,18 @@ typedef enum { typedef uint32_t ravi_type_map; -#define RAVI_TM_NIL (((uint32_t)1)<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; diff --git a/src/lparser.h b/src/lparser.h index 6737962..2676766 100644 --- a/src/lparser.h +++ b/src/lparser.h @@ -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 * diff --git a/src/ltests.c b/src/ltests.c index b01e8d1..a88d527 100644 --- a/src/ltests.c +++ b/src/ltests.c @@ -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; }