issue #215 adapt fix by XmiliaH from pull request

pull/216/head
Dibyendu Majumdar 3 years ago
parent 8fd3a1bbab
commit 658f04c3d8

@ -1367,96 +1367,94 @@ 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) {
/* NOTE that 'v' may not have register assigned yet */
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) {
/* 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_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));
ok = 1;
}
}
}
if (!ok)
luaX_syntaxerror(ls, "expecting array initializer");
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;
}
/* 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) &&
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 (v_type == RAVI_TARRAYFLT) {
v_type = RAVI_TNUMFLT;
}
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) {
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 {
v_type = RAVI_TANY;
}
else if (vartype != v->ravi_type){
luaX_syntaxerror(ls, "Invalid local assignment");
}
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
* 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_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));
ok = 1;
}
}
}
if (!ok)
luaX_syntaxerror(ls, "expecting array initializer");
}
/* if we are calling a function then convert return types */
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.
* 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_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
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");
}
}

Loading…
Cancel
Save