lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Hello !

While trying to change Lua-5.4.4 to LJS (https://github.com/mingodad/ljs) I found an intriguing change in behavior/bug between Lua-5.3.6 and Lua-5.4.4, in LJS I decided to forbid shadowing variables in the same scope and it works as intended in LJS from LjsJit, Lua-(5.1.5 .. 5.3.6) but applying a similar check to Lua-5.4.4 find a duplicated variable name where it shouldn't (see code shown bellow).

Somehow this line 'local res = loadstring("a=1")' brings the 'a' variable name to visibility for the parser in Lua-5.4.4 but not for previous Lua versions.

It seems like the parser is parsing the string passed to 'load' when parsing the script instead of at runtime, or something else that I'm not seeing through the code.

Can someone shed some light on this issue ?

====

if loadstring == null then
    loadstring = load;
end
function bug()
    do
      local a = 2;
    end
    print(a);
    local res = loadstring("a=1"); --somehow this brings 'a' visible internally
    --res();
    print(a);
    --Lua-5.4.4 find the next 'a' declaration as duplicated
    --local a = 3; -- but if we comment this line 'a' is printed as 'nil' bellow
    print(res, a);
end

print(a);
bug();
print(a);

====

====

/*
** Create a new local variable with the given 'name'. Return its index
** in the function.
*/
static int new_localvar (LexState *ls, TString *name) {
  lua_State *L = ls->L;
  FuncState *fs = ls->fs;
  Dyndata *dyd = ls->dyd;
  Vardesc *var;

  /* START Check for duplicated varibale names in local scope */
  int vidx, nactvar_n;
  vidx = fs->bl ? fs->bl->nactvar + fs->firstlocal : fs->firstlocal;
  //nactvar_n = dyd->actvar.n;
  nactvar_n = fs->nactvar;
  if(nactvar_n > fs->ndebugvars) nactvar_n = fs->ndebugvars;
  for (; vidx < nactvar_n; ++vidx) {
      Vardesc *vd = dyd->actvar.arr+vidx;
    LocVar *lv = &fs->f->locvars[vd->vd.ridx];
    if (lv && name == lv->varname) {
      /* allow '_' duplicates */
      const char *sname = getstr(name);
      if(tsslen(name) == 1 && sname[0] == '_') break;
      luaX_syntaxerror(ls, luaO_pushfstring(ls->L,
             "Name [%s] already declared", sname));
    }
  }
  /* END Check for duplicated varibale names in local scope */

  checklimit(fs, dyd->actvar.n + 1 - fs->firstlocal,
                 MAXVARS, "local variables");
  luaM_growvector(L, dyd->actvar.arr, dyd->actvar.n + 1,
                  dyd->actvar.size, Vardesc, USHRT_MAX, "local variables");
  var = &dyd->actvar.arr[dyd->actvar.n++];
  var->vd.kind = VDKREG;  /* default */
  var->vd.name = name;
  return dyd->actvar.n - 1 - fs->firstlocal;
}

====

Cheers !