Optional initialization for global declarations
This commit is contained in:
81
lparser.c
81
lparser.c
@@ -30,7 +30,7 @@
|
||||
|
||||
|
||||
|
||||
/* maximum number of variable declarationss per function (must be
|
||||
/* maximum number of variable declarations per function (must be
|
||||
smaller than 250, due to the bytecode format) */
|
||||
#define MAXVARS 200
|
||||
|
||||
@@ -197,7 +197,7 @@ static int new_varkind (LexState *ls, TString *name, lu_byte kind) {
|
||||
Dyndata *dyd = ls->dyd;
|
||||
Vardesc *var;
|
||||
luaM_growvector(L, dyd->actvar.arr, dyd->actvar.n + 1,
|
||||
dyd->actvar.size, Vardesc, SHRT_MAX, "variable declarationss");
|
||||
dyd->actvar.size, Vardesc, SHRT_MAX, "variable declarations");
|
||||
var = &dyd->actvar.arr[dyd->actvar.n++];
|
||||
var->vd.kind = kind; /* default */
|
||||
var->vd.name = name;
|
||||
@@ -485,6 +485,20 @@ static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
|
||||
}
|
||||
|
||||
|
||||
static void buildglobal (LexState *ls, TString *varname, expdesc *var) {
|
||||
FuncState *fs = ls->fs;
|
||||
expdesc key;
|
||||
init_exp(var, VGLOBAL, -1); /* global by default */
|
||||
singlevaraux(fs, ls->envn, var, 1); /* get environment variable */
|
||||
if (var->k == VGLOBAL)
|
||||
luaK_semerror(ls, "_ENV is global when accessing variable '%s'",
|
||||
getstr(varname));
|
||||
luaK_exp2anyregup(fs, var); /* _ENV could be a constant */
|
||||
codestring(&key, varname); /* key is variable name */
|
||||
luaK_indexed(fs, var, &key); /* 'var' represents _ENV[varname] */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Find a variable with the given name 'n', handling global variables
|
||||
** too.
|
||||
@@ -494,18 +508,11 @@ static void buildvar (LexState *ls, TString *varname, expdesc *var) {
|
||||
init_exp(var, VGLOBAL, -1); /* global by default */
|
||||
singlevaraux(fs, varname, var, 1);
|
||||
if (var->k == VGLOBAL) { /* global name? */
|
||||
expdesc key;
|
||||
int info = var->u.info;
|
||||
/* global by default in the scope of a global declaration? */
|
||||
if (info == -2)
|
||||
luaK_semerror(ls, "variable '%s' not declared", getstr(varname));
|
||||
singlevaraux(fs, ls->envn, var, 1); /* get environment variable */
|
||||
if (var->k == VGLOBAL)
|
||||
luaK_semerror(ls, "_ENV is global when accessing variable '%s'",
|
||||
getstr(varname));
|
||||
luaK_exp2anyregup(fs, var); /* but could be a constant */
|
||||
codestring(&key, varname); /* key is variable name */
|
||||
luaK_indexed(fs, var, &key); /* env[varname] */
|
||||
buildglobal(ls, varname, var);
|
||||
if (info != -1 && ls->dyd->actvar.arr[info].vd.kind == GDKCONST)
|
||||
var->u.ind.ro = 1; /* mark variable as read-only */
|
||||
else /* anyway must be a global */
|
||||
@@ -665,7 +672,7 @@ static void createlabel (LexState *ls, TString *name, int line, int last) {
|
||||
|
||||
|
||||
/*
|
||||
** Traverse the pending goto's of the finishing block checking whether
|
||||
** Traverse the pending gotos of the finishing block checking whether
|
||||
** each match some label of that block. Those that do not match are
|
||||
** "exported" to the outer block, to be solved there. In particular,
|
||||
** its 'nactvar' is updated with the level of the inner block,
|
||||
@@ -1435,6 +1442,15 @@ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Create code to store the "top" register in 'var' */
|
||||
static void storevartop (FuncState *fs, expdesc *var) {
|
||||
expdesc e;
|
||||
init_exp(&e, VNONRELOC, fs->freereg - 1);
|
||||
luaK_storevar(fs, var, &e); /* will also free the top register */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Parse and compile a multiple assignment. The first "variable"
|
||||
** (a 'suffixedexp') was already read by the caller.
|
||||
@@ -1468,8 +1484,7 @@ static void restassign (LexState *ls, struct LHS_assign *lh, int nvars) {
|
||||
return; /* avoid default */
|
||||
}
|
||||
}
|
||||
init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */
|
||||
luaK_storevar(ls->fs, &lh->v, &e);
|
||||
storevartop(ls->fs, &lh->v); /* default assignment */
|
||||
}
|
||||
|
||||
|
||||
@@ -1821,25 +1836,45 @@ static lu_byte getglobalattribute (LexState *ls, lu_byte df) {
|
||||
}
|
||||
|
||||
|
||||
static void globalnames (LexState *ls, lu_byte defkind) {
|
||||
FuncState *fs = ls->fs;
|
||||
int nvars = 0;
|
||||
int lastidx; /* index of last registered variable */
|
||||
do { /* for each name */
|
||||
TString *vname = str_checkname(ls);
|
||||
lu_byte kind = getglobalattribute(ls, defkind);
|
||||
lastidx = new_varkind(ls, vname, kind);
|
||||
nvars++;
|
||||
} while (testnext(ls, ','));
|
||||
if (testnext(ls, '=')) { /* initialization? */
|
||||
expdesc e;
|
||||
int i;
|
||||
int nexps = explist(ls, &e); /* read list of expressions */
|
||||
adjust_assign(ls, nvars, nexps, &e);
|
||||
for (i = 0; i < nvars; i++) { /* for each variable */
|
||||
expdesc var;
|
||||
TString *varname = getlocalvardesc(fs, lastidx - i)->vd.name;
|
||||
buildglobal(ls, varname, &var); /* create global variable in 'var' */
|
||||
storevartop(fs, &var);
|
||||
}
|
||||
}
|
||||
fs->nactvar = cast_short(fs->nactvar + nvars); /* activate declaration */
|
||||
}
|
||||
|
||||
|
||||
static void globalstat (LexState *ls) {
|
||||
/* globalstat -> (GLOBAL) attrib '*'
|
||||
globalstat -> (GLOBAL) attrib NAME attrib {',' NAME attrib} */
|
||||
FuncState *fs = ls->fs;
|
||||
/* get prefixed attribute (if any); default is regular global variable */
|
||||
lu_byte defkind = getglobalattribute(ls, GDKREG);
|
||||
if (testnext(ls, '*')) {
|
||||
if (!testnext(ls, '*'))
|
||||
globalnames(ls, defkind);
|
||||
else {
|
||||
/* use NULL as name to represent '*' entries */
|
||||
new_varkind(ls, NULL, defkind);
|
||||
fs->nactvar++; /* activate declaration */
|
||||
}
|
||||
else {
|
||||
do { /* list of names */
|
||||
TString *vname = str_checkname(ls);
|
||||
lu_byte kind = getglobalattribute(ls, defkind);
|
||||
new_varkind(ls, vname, kind);
|
||||
fs->nactvar++; /* activate declaration */
|
||||
} while (testnext(ls, ','));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1850,7 +1885,7 @@ static void globalfunc (LexState *ls, int line) {
|
||||
TString *fname = str_checkname(ls);
|
||||
new_varkind(ls, fname, GDKREG); /* declare global variable */
|
||||
fs->nactvar++; /* enter its scope */
|
||||
buildvar(ls, fname, &var);
|
||||
buildglobal(ls, fname, &var);
|
||||
body(ls, &b, 0, ls->linenumber); /* compile and return closure in 'b' */
|
||||
luaK_storevar(fs, &var, &b);
|
||||
luaK_fixline(fs, line); /* definition "happens" in the first line */
|
||||
|
||||
Reference in New Issue
Block a user