|
|
|
@ -1367,14 +1367,28 @@ 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,
|
|
|
|
|
TString **usertypes, int nvars, int n) {
|
|
|
|
|
static void ravi_typecheck(LexState *ls, expdesc *v, int *var_types, TString **usertypes, int nvars, int n) {
|
|
|
|
|
/* NOTE that 'v' may not have register assigned yet */
|
|
|
|
|
if (n >= nvars)
|
|
|
|
|
return;
|
|
|
|
|
ravitype_t vartype = var_types[n];
|
|
|
|
|
if (n < nvars && vartype != RAVI_TANY) {
|
|
|
|
|
if (v->ravi_type != vartype &&
|
|
|
|
|
(vartype == RAVI_TARRAYFLT || vartype == RAVI_TARRAYINT) &&
|
|
|
|
|
v->k == VNONRELOC) {
|
|
|
|
|
if (vartype == RAVI_TANY)
|
|
|
|
|
return;
|
|
|
|
|
ravitype_t v_type = v->ravi_type;
|
|
|
|
|
if (v->k == VINDEXED) {
|
|
|
|
|
if (v_type == RAVI_TARRAYINT) {
|
|
|
|
|
v_type = RAVI_TNUMINT;
|
|
|
|
|
}
|
|
|
|
|
else if (v_type == RAVI_TARRAYFLT) {
|
|
|
|
|
v_type = RAVI_TNUMFLT;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
v_type = RAVI_TANY;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (v_type == vartype)
|
|
|
|
|
return;
|
|
|
|
|
if ((vartype == RAVI_TARRAYFLT || vartype == RAVI_TARRAYINT) && 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
|
|
|
|
@ -1385,18 +1399,14 @@ static void ravi_typecheck(LexState *ls, expdesc *v, int *var_types,
|
|
|
|
|
// 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 */
|
|
|
|
|
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_TARRAYINT) ? OP_RAVI_NEW_IARRAY
|
|
|
|
|
: OP_RAVI_NEW_FARRAY;
|
|
|
|
|
if (reg == v->u.info) { /* double check that register is as expected */
|
|
|
|
|
op = (vartype == RAVI_TARRAYINT) ? 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));
|
|
|
|
|
DEBUG_CODEGEN(raviY_printf(ls->fs, "[%d]* %o ; modify opcode\n", v->pc, *pc));
|
|
|
|
|
ok = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1405,10 +1415,8 @@ 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 ||
|
|
|
|
|
else if ((vartype == RAVI_TNUMFLT || vartype == RAVI_TNUMINT || vartype == RAVI_TARRAYFLT ||
|
|
|
|
|
vartype == RAVI_TARRAYINT || vartype == RAVI_TTABLE || vartype == RAVI_TSTRING ||
|
|
|
|
|
vartype == RAVI_TFUNCTION || vartype == RAVI_TUSERDATA) &&
|
|
|
|
|
v->k == VCALL) {
|
|
|
|
|
/* For local variable declarations that call functions e.g.
|
|
|
|
@ -1418,8 +1426,7 @@ static void ravi_typecheck(LexState *ls, expdesc *v, int *var_types,
|
|
|
|
|
* 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 */
|
|
|
|
|
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 */
|
|
|
|
@ -1436,15 +1443,7 @@ 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) &&
|
|
|
|
|
v->k == VINDEXED) {
|
|
|
|
|
if ((vartype == RAVI_TNUMFLT && v->ravi_type != RAVI_TARRAYFLT) ||
|
|
|
|
|
(vartype == RAVI_TNUMINT && v->ravi_type != RAVI_TARRAYINT))
|
|
|
|
|
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_TSTRING || vartype == RAVI_TFUNCTION || vartype == RAVI_TUSERDATA) {
|
|
|
|
|
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
|
|
|
|
@ -1454,11 +1453,10 @@ static void ravi_typecheck(LexState *ls, expdesc *v, int *var_types,
|
|
|
|
|
luaK_exp2nextreg(ls->fs, v);
|
|
|
|
|
ravi_code_typecoersion(ls, v->u.info, vartype, usertype);
|
|
|
|
|
}
|
|
|
|
|
else if (vartype != v->ravi_type){
|
|
|
|
|
else {
|
|
|
|
|
luaX_syntaxerror(ls, "Invalid local assignment");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* parse expression list, and validate that the expressions match expected
|
|
|
|
|
* types provided in vars array. This is a modified version of explist() to be
|
|
|
|
|