no more `global' declarations

This commit is contained in:
Roberto Ierusalimschy 2002-05-14 14:52:22 -03:00
parent 58bf77bc7f
commit 1c328a191a
4 changed files with 53 additions and 161 deletions

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lcode.c,v 1.102 2002/05/10 19:22:11 roberto Exp roberto $ ** $Id: lcode.c,v 1.103 2002/05/13 13:07:48 roberto Exp roberto $
** Code generator for Lua ** Code generator for Lua
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -191,7 +191,7 @@ void luaK_reserveregs (FuncState *fs, int n) {
static void freereg (FuncState *fs, int reg) { static void freereg (FuncState *fs, int reg) {
if (reg >= fs->nactloc && reg < MAXSTACK) { if (reg >= fs->nactvar && reg < MAXSTACK) {
fs->freereg--; fs->freereg--;
lua_assert(reg == fs->freereg); lua_assert(reg == fs->freereg);
} }
@ -375,7 +375,7 @@ int luaK_exp2anyreg (FuncState *fs, expdesc *e) {
luaK_dischargevars(fs, e); luaK_dischargevars(fs, e);
if (e->k == VNONRELOC) { if (e->k == VNONRELOC) {
if (!hasjumps(e)) return e->info; /* exp is already in a register */ if (!hasjumps(e)) return e->info; /* exp is already in a register */
if (e->info >= fs->nactloc) { /* reg. is not a local? */ if (e->info >= fs->nactvar) { /* reg. is not a local? */
luaK_exp2reg(fs, e, e->info); /* put value on it */ luaK_exp2reg(fs, e, e->info); /* put value on it */
return e->info; return e->info;
} }

View File

@ -1,5 +1,5 @@
/* /*
** $Id: ldebug.c,v 1.113 2002/05/09 14:14:34 roberto Exp roberto $ ** $Id: ldebug.c,v 1.114 2002/05/13 13:09:00 roberto Exp roberto $
** Debug Interface ** Debug Interface
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -432,11 +432,6 @@ static const char *getobjname (lua_State *L, CallInfo *ci, int stackpos,
break; break;
} }
case OP_GETTABLE: { case OP_GETTABLE: {
*name = luaF_getlocalname(p, GETARG_B(i)+1, pc);
if (*name && *name[0] == '*') {
*name = kname(p, GETARG_C(i));
return "global";
}
*name = kname(p, GETARG_C(i)); *name = kname(p, GETARG_C(i));
return "field"; return "field";
break; break;

180
lparser.c
View File

@ -1,5 +1,5 @@
/* /*
** $Id: lparser.c,v 1.181 2002/05/10 19:22:11 roberto Exp roberto $ ** $Id: lparser.c,v 1.182 2002/05/13 13:09:00 roberto Exp roberto $
** Lua Parser ** Lua Parser
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -23,15 +23,18 @@
#define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]])
/* /*
** nodes for block list (list of active blocks) ** nodes for block list (list of active blocks)
*/ */
typedef struct BlockCnt { typedef struct BlockCnt {
struct BlockCnt *previous; /* chain */ struct BlockCnt *previous; /* chain */
int breaklist; /* list of jumps out of this loop */ int breaklist; /* list of jumps out of this loop */
int nactloc; /* # active local variables outside the breakable structure */ int nactvar; /* # active local variables outside the breakable structure */
int nactvar;
int defaultglob;
int upval; /* true if some variable in the block is an upvalue */ int upval; /* true if some variable in the block is an upvalue */
int isbreakable; /* true if `block' is a loop */ int isbreakable; /* true if `block' is a loop */
} BlockCnt; } BlockCnt;
@ -138,51 +141,26 @@ static int luaI_registerlocalvar (LexState *ls, TString *varname) {
} }
static vardesc *new_var (LexState *ls, int n) {
FuncState *fs = ls->fs;
luaX_checklimit(ls, fs->nactvar+n+1, MAXVARS, "variables");
return &fs->actvar[fs->nactvar+n];
}
static void new_localvar (LexState *ls, TString *name, int n) { static void new_localvar (LexState *ls, TString *name, int n) {
vardesc *v = new_var(ls, n); FuncState *fs = ls->fs;
v->k = VLOCAL; luaX_checklimit(ls, fs->nactvar+n+1, MAXVARS, "local variables");
v->i = luaI_registerlocalvar(ls, name); fs->actvar[fs->nactvar+n] = luaI_registerlocalvar(ls, name);
v->level = ls->fs->nactloc + n;
} }
static void adjustlocalvars (LexState *ls, int nvars) { static void adjustlocalvars (LexState *ls, int nvars) {
FuncState *fs = ls->fs; FuncState *fs = ls->fs;
while (nvars--) { fs->nactvar += nvars;
lua_assert(fs->actvar[fs->nactvar].k == VLOCAL); for (; nvars; nvars--) {
fs->f->locvars[fs->actvar[fs->nactvar].i].startpc = fs->pc; getlocvar(fs, fs->nactvar - nvars).startpc = fs->pc;
fs->nactvar++;
fs->nactloc++;
}
}
static void adjustglobalvars (LexState *ls, int nvars, int level) {
FuncState *fs = ls->fs;
while (nvars--) {
fs->actvar[fs->nactvar].k = VGLOBAL;
fs->actvar[fs->nactvar].level = level;
fs->nactvar++;
} }
} }
static void removevars (LexState *ls, int tolevel) { static void removevars (LexState *ls, int tolevel) {
FuncState *fs = ls->fs; FuncState *fs = ls->fs;
while (fs->nactvar > tolevel) { while (fs->nactvar > tolevel)
fs->nactvar--; getlocvar(fs, --fs->nactvar).endpc = fs->pc;
if (fs->actvar[fs->nactvar].k == VLOCAL) {
fs->nactloc--;
fs->f->locvars[fs->actvar[fs->nactvar].i].endpc = fs->pc;
}
}
} }
@ -210,80 +188,48 @@ static int indexupvalue (FuncState *fs, expdesc *v) {
} }
static vardesc *searchvar (FuncState *fs, TString *n) { static int searchvar (FuncState *fs, TString *n) {
int i; int i;
for (i=fs->nactvar-1; i >= 0; i--) { for (i=fs->nactvar-1; i >= 0; i--) {
vardesc *v = &fs->actvar[i]; if (n == getlocvar(fs, i).varname)
if (v->k == VLOCAL ? n == fs->f->locvars[v->i].varname return i;
: n == tsvalue(&fs->f->k[v->i]))
return v;
} }
return NULL; /* not found */ return -1; /* not found */
} }
static void markupval (FuncState *fs, int level) { static void markupval (FuncState *fs, int level) {
BlockCnt *bl = fs->bl; BlockCnt *bl = fs->bl;
while (bl && bl->nactloc > level) bl = bl->previous; while (bl && bl->nactvar > level) bl = bl->previous;
if (bl) bl->upval = 1; if (bl) bl->upval = 1;
} }
static int singlevar_aux (FuncState *fs, TString *n, expdesc *var, int nd) { static void singlevar (FuncState *fs, TString *n, expdesc *var, int base) {
if (fs == NULL) { /* no more levels? */ if (fs == NULL) /* no more levels? */
init_exp(var, VGLOBAL, NO_REG); /* default is free global */ init_exp(var, VGLOBAL, NO_REG); /* default is global variable */
return VNIL; /* not found */
}
else { else {
vardesc *v = searchvar(fs, n); /* look up at current level */ int v = searchvar(fs, n); /* look up at current level */
if (v) { if (v >= 0) {
if (v->level == NO_REG) { /* free global? */ init_exp(var, VLOCAL, v);
lua_assert(v->k == VGLOBAL); if (!base)
init_exp(var, VGLOBAL, NO_REG); markupval(fs, v); /* local will be used as an upval */
}
else
init_exp(var, VLOCAL, v->level);
return v->k;
} }
else { /* not found at current level; try upper one */ else { /* not found at current level; try upper one */
int k = singlevar_aux(fs->prev, n, var, nd && fs->defaultglob == NO_REG); singlevar(fs->prev, n, var, 0);
if (var->k == VGLOBAL) { if (var->k == VGLOBAL) {
if (k == VNIL && nd && fs->defaultglob != NO_REG) { if (base)
if (fs->defaultglob == NO_REG1) var->info = luaK_stringK(fs, n); /* info points to global name */
luaX_syntaxerror(fs->ls, "undeclared global");
init_exp(var, VLOCAL, fs->defaultglob);
k = VGLOBAL; /* now there is a declaration */
}
} }
else { /* LOCAL or UPVAL */ else { /* LOCAL or UPVAL */
if (var->k == VLOCAL)
markupval(fs->prev, var->info); /* local will be used as an upval */
var->info = indexupvalue(fs, var); var->info = indexupvalue(fs, var);
var->k = VUPVAL; /* upvalue in this level */ var->k = VUPVAL; /* upvalue in this level */
} }
return k;
} }
} }
} }
static void singlevar (FuncState *fs, TString *n, expdesc *var) {
int k = singlevar_aux(fs, n, var, 1);
if (k == VNIL || k == VGLOBAL) { /* global? */
if (var->k == VGLOBAL) /* free global? */
var->info = luaK_stringK(fs, n);
else { /* `indexed' global */
expdesc e;
codestring(fs->ls, &e, n);
luaK_exp2anyreg(fs, var);
var->aux = luaK_exp2RK(fs, &e);
var->k = VINDEXED;
}
}
}
static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) {
FuncState *fs = ls->fs; FuncState *fs = ls->fs;
int extra = nvars - nexps; int extra = nvars - nexps;
@ -308,24 +254,22 @@ static void code_params (LexState *ls, int nparams, int dots) {
FuncState *fs = ls->fs; FuncState *fs = ls->fs;
adjustlocalvars(ls, nparams); adjustlocalvars(ls, nparams);
luaX_checklimit(ls, fs->nactvar, MAXPARAMS, "parameters"); luaX_checklimit(ls, fs->nactvar, MAXPARAMS, "parameters");
fs->f->numparams = cast(lu_byte, fs->nactloc); fs->f->numparams = cast(lu_byte, fs->nactvar);
fs->f->is_vararg = cast(lu_byte, dots); fs->f->is_vararg = cast(lu_byte, dots);
if (dots) if (dots)
create_local(ls, "arg"); create_local(ls, "arg");
luaK_reserveregs(fs, fs->nactloc); /* reserve register for parameters */ luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */
} }
static void enterblock (FuncState *fs, BlockCnt *bl, int isbreakable) { static void enterblock (FuncState *fs, BlockCnt *bl, int isbreakable) {
bl->breaklist = NO_JUMP; bl->breaklist = NO_JUMP;
bl->isbreakable = isbreakable; bl->isbreakable = isbreakable;
bl->nactloc = fs->nactloc;
bl->nactvar = fs->nactvar; bl->nactvar = fs->nactvar;
bl->defaultglob = fs->defaultglob;
bl->upval = 0; bl->upval = 0;
bl->previous = fs->bl; bl->previous = fs->bl;
fs->bl = bl; fs->bl = bl;
lua_assert(fs->freereg == fs->nactloc); lua_assert(fs->freereg == fs->nactvar);
} }
@ -334,11 +278,9 @@ static void leaveblock (FuncState *fs) {
fs->bl = bl->previous; fs->bl = bl->previous;
removevars(fs->ls, bl->nactvar); removevars(fs->ls, bl->nactvar);
if (bl->upval) if (bl->upval)
luaK_codeABC(fs, OP_CLOSE, bl->nactloc, 0, 0); luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);
lua_assert(bl->nactloc == fs->nactloc);
lua_assert(bl->nactvar == fs->nactvar); lua_assert(bl->nactvar == fs->nactvar);
fs->freereg = fs->nactloc; /* free registers */ fs->freereg = fs->nactvar; /* free registers */
fs->defaultglob = bl->defaultglob;
luaK_patchtohere(fs, bl->breaklist); luaK_patchtohere(fs, bl->breaklist);
} }
@ -373,9 +315,7 @@ static void open_func (LexState *ls, FuncState *fs) {
fs->h = luaH_new(ls->L, 0, 0); fs->h = luaH_new(ls->L, 0, 0);
fs->np = 0; fs->np = 0;
fs->nlocvars = 0; fs->nlocvars = 0;
fs->nactloc = 0;
fs->nactvar = 0; fs->nactvar = 0;
fs->defaultglob = NO_REG; /* default is free globals */
fs->bl = NULL; fs->bl = NULL;
f->code = NULL; f->code = NULL;
f->source = ls->source; f->source = ls->source;
@ -658,13 +598,13 @@ static void prefixexp (LexState *ls, expdesc *v) {
return; return;
} }
case TK_NAME: { case TK_NAME: {
singlevar(ls->fs, str_checkname(ls), v); singlevar(ls->fs, str_checkname(ls), v, 1);
next(ls); next(ls);
return; return;
} }
case '%': { /* for compatibility only */ case '%': { /* for compatibility only */
next(ls); /* skip `%' */ next(ls); /* skip `%' */
singlevar(ls->fs, str_checkname(ls), v); singlevar(ls->fs, str_checkname(ls), v, 1);
check_condition(ls, v->k == VUPVAL, "global upvalues are obsolete"); check_condition(ls, v->k == VUPVAL, "global upvalues are obsolete");
next(ls); next(ls);
return; return;
@ -1173,38 +1113,10 @@ static void localstat (LexState *ls) {
} }
static void globalstat (LexState *ls) {
/* stat -> GLOBAL NAME {`,' NAME} [IN exp] | GLOBAL IN exp */
FuncState *fs = ls->fs;
int nvars = 0;
next(ls); /* skip GLOBAL */
if (ls->t.token == TK_NAME) {
do {
vardesc *v = new_var(ls, nvars++);
v->i = luaK_stringK(ls->fs, str_checkname(ls));
next(ls); /* skip name */
} while (optional(ls, ','));
}
if (!optional(ls, TK_IN)) { /* free globals? */
if (nvars == 0) /* default - free is invalid */
error_expected(ls, TK_IN);
adjustglobalvars(ls, nvars, NO_REG); /* mark globals as free */
}
else {
int baselocal = fs->freereg;
int k = exp1(ls);
if (nvars == 0)
fs->defaultglob = (k == VNIL) ? NO_REG1 : baselocal;
adjustglobalvars(ls, nvars, baselocal);
create_local(ls, "*");
}
}
static int funcname (LexState *ls, expdesc *v) { static int funcname (LexState *ls, expdesc *v) {
/* funcname -> NAME {field} [`:' NAME] */ /* funcname -> NAME {field} [`:' NAME] */
int needself = 0; int needself = 0;
singlevar(ls->fs, str_checkname(ls), v); singlevar(ls->fs, str_checkname(ls), v, 1);
next(ls); /* skip var name */ next(ls); /* skip var name */
while (ls->t.token == '.') { while (ls->t.token == '.') {
luaY_field(ls, v); luaY_field(ls, v);
@ -1259,7 +1171,7 @@ static void retstat (LexState *ls) {
return; return;
} }
luaK_setcallreturns(fs, &e, LUA_MULTRET); luaK_setcallreturns(fs, &e, LUA_MULTRET);
first = fs->nactloc; first = fs->nactvar;
nret = LUA_MULTRET; /* return all values */ nret = LUA_MULTRET; /* return all values */
} }
else { else {
@ -1267,7 +1179,7 @@ static void retstat (LexState *ls) {
first = luaK_exp2anyreg(fs, &e); first = luaK_exp2anyreg(fs, &e);
else { else {
luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */ luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */
first = fs->nactloc; /* return all `active' values */ first = fs->nactvar; /* return all `active' values */
lua_assert(nret == fs->freereg - first); lua_assert(nret == fs->freereg - first);
} }
} }
@ -1289,7 +1201,7 @@ static void breakstat (LexState *ls) {
if (!bl) if (!bl)
luaX_syntaxerror(ls, "no loop to break"); luaX_syntaxerror(ls, "no loop to break");
if (upval) if (upval)
luaK_codeABC(fs, OP_CLOSE, bl->nactloc, 0, 0); luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);
luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); luaK_concat(fs, &bl->breaklist, luaK_jump(fs));
} }
@ -1327,10 +1239,6 @@ static int statement (LexState *ls) {
localstat(ls); localstat(ls);
return 0; return 0;
} }
case TK_GLOBAL: { /* stat -> globalstat */
globalstat(ls);
return 0;
}
case TK_RETURN: { /* stat -> retstat */ case TK_RETURN: { /* stat -> retstat */
retstat(ls); retstat(ls);
return 1; /* must be last statement */ return 1; /* must be last statement */
@ -1391,8 +1299,8 @@ static void chunk (LexState *ls) {
while (!islast && !block_follow(ls->t.token)) { while (!islast && !block_follow(ls->t.token)) {
islast = statement(ls); islast = statement(ls);
optional(ls, ';'); optional(ls, ';');
lua_assert(ls->fs->freereg >= ls->fs->nactloc); lua_assert(ls->fs->freereg >= ls->fs->nactvar);
ls->fs->freereg = ls->fs->nactloc; /* free registers */ ls->fs->freereg = ls->fs->nactvar; /* free registers */
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lparser.h,v 1.42 2002/05/09 18:00:38 roberto Exp roberto $ ** $Id: lparser.h,v 1.43 2002/05/10 19:22:11 roberto Exp roberto $
** Lua Parser ** Lua Parser
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -41,18 +41,9 @@ typedef struct expdesc {
} expdesc; } expdesc;
/* describe declared variables */
typedef struct vardesc {
int i; /* if local, its index in `locvars';
if global, its name index in `k' */
lu_byte k;
lu_byte level; /* if local, stack level;
if global, corresponding local (NO_REG for free globals) */
} vardesc;
struct BlockCnt; /* defined in lparser.c */ struct BlockCnt; /* defined in lparser.c */
/* state needed to generate code for a given function */ /* state needed to generate code for a given function */
typedef struct FuncState { typedef struct FuncState {
Proto *f; /* current function header */ Proto *f; /* current function header */
@ -63,16 +54,14 @@ typedef struct FuncState {
struct BlockCnt *bl; /* chain of current blocks */ struct BlockCnt *bl; /* chain of current blocks */
int pc; /* next position to code (equivalent to `ncode') */ int pc; /* next position to code (equivalent to `ncode') */
int lasttarget; /* `pc' of last `jump target' */ int lasttarget; /* `pc' of last `jump target' */
int jpc; /* list of jumps to `pc' */ int jpc; /* list of pending jumps to `pc' */
int freereg; /* first free register */ int freereg; /* first free register */
int defaultglob; /* where to look for non-declared globals */
int nk; /* number of elements in `k' */ int nk; /* number of elements in `k' */
int np; /* number of elements in `p' */ int np; /* number of elements in `p' */
int nlocvars; /* number of elements in `locvars' */ int nlocvars; /* number of elements in `locvars' */
int nactloc; /* number of active local variables */ int nactvar; /* number of active local variables */
int nactvar; /* number of elements in array `actvar' */
expdesc upvalues[MAXUPVALUES]; /* upvalues */ expdesc upvalues[MAXUPVALUES]; /* upvalues */
vardesc actvar[MAXVARS]; /* declared-variable stack */ int actvar[MAXVARS]; /* declared-variable stack */
} FuncState; } FuncState;