lua-users home
lua-l archive

Backport of Lua 5.2 "in" scoping (was Re: Lua registry, environment, and threads.)

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


Roberto Ierusalimschy wrote:
> Yes. The semantics is exactly as Mark explained:
> 
> in t do command end 
> 
> is translated to
> 
> do
> local _temp = t;
> <command>
> end
> 
> and all acesses to <global> inside command are changed to _temp.global.
Sadly we don't get development snapshots for Lua 5.2. So I've
created a backport patch against Lua 5.1.4 from the above
description. It's entirely unsupported of course.
The intention is to allow everyone to experiment with this
feature, evaluate it's usefulness and/or complain if it doesn't
match their expectations. ;-)
[But don't complain to me -- I didn't propose the feature.]
--Mike
--- lua-5.1.4/src/lparser.h	2007年12月27日 14:02:25 +0100
+++ lua-5.1.4-in1/src/lparser.h	2010年01月08日 16:20:00 +0100
@@ -70,6 +70,7 @@
 int np; /* number of elements in `p' */
 short nlocvars; /* number of elements in `locvars' */
 lu_byte nactvar; /* number of active local variables */
+ lu_byte globalvar; /* global scope variable or NO_REG */
 upvaldesc upvalues[LUAI_MAXUPVALUES]; /* upvalues */
 unsigned short actvar[LUAI_MAXVARS]; /* declared-variable stack */
 } FuncState;
--- lua-5.1.4/src/lparser.c	2007年12月28日 16:32:23 +0100
+++ lua-5.1.4-in1/src/lparser.c	2010年01月08日 16:20:00 +0100
@@ -248,8 +248,16 @@
 static void singlevar (LexState *ls, expdesc *var) {
 TString *varname = str_checkname(ls);
 FuncState *fs = ls->fs;
- if (singlevaraux(fs, varname, var, 1) == VGLOBAL)
- var->u.s.info = luaK_stringK(fs, varname); /* info points to global name */
+ if (singlevaraux(fs, varname, var, 1) == VGLOBAL) {
+ if (fs->globalvar == NO_REG)
+ var->u.s.info = luaK_stringK(fs, varname); /* info has global name */
+ else {
+ expdesc key;
+ var->u.s.info = fs->globalvar;
+ codestring(ls, &key, varname);
+ luaK_indexed(fs, var, &key);
+ }
+ }
 }
 
 
@@ -342,6 +350,7 @@
 fs->nlocvars = 0;
 fs->nactvar = 0;
 fs->bl = NULL;
+ fs->globalvar = NO_REG;
 f->source = ls->source;
 f->maxstacksize = 2; /* registers 0/1 are always valid */
 fs->h = luaH_new(L, 0, 0);
@@ -1268,6 +1277,24 @@
 }
 
 
+static void instat (LexState *ls, int line) {
+ /* stat -> IN exp1 DO block END */
+ FuncState *fs = ls->fs;
+ int oldglobal = fs->globalvar;
+ BlockCnt bl;
+ enterblock(fs, &bl, 0);
+ new_localvarliteral(ls, "(env)", 0);
+ exp1(ls);
+ fs->globalvar = fs->nactvar;
+ adjustlocalvars(ls, 1);
+ checknext(ls, TK_DO);
+ chunk(ls);
+ check_match(ls, TK_END, TK_DO, line);
+ leaveblock(fs);
+ fs->globalvar = oldglobal;
+}
+
+
 static int statement (LexState *ls) {
 int line = ls->linenumber; /* may be needed for error messages */
 switch (ls->t.token) {
@@ -1314,6 +1341,11 @@
 breakstat(ls);
 return 1; /* must be last statement */
 }
+ case TK_IN: { /* stat -> instat */
+ luaX_next(ls); /* skip IN */
+ instat(ls, line);
+ return 0;
+ }
 default: {
 exprstat(ls);
 return 0; /* to avoid warnings */
--- lua-5.1.4/src/loadlib.c	2008年08月06日 15:29:28 +0200
+++ lua-5.1.4-in1/src/loadlib.c	2010年01月08日 16:20:00 +0100
@@ -565,7 +565,7 @@
 lua_pushvalue(L, -1);
 setfenv(L);
 dooptions(L, loaded - 1);
- return 0;
+ return 1;
 }
 
 

AltStyle によって変換されたページ (->オリジナル) /