lua-users home
lua-l archive

Re: The purpose of LUA_ENVIRONINDEX pseudo index

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


Wow!!!, thank you for the explanation now I have a new understanding about lua stack and its environments. Definitely the purpose of pseudo-indices is not very clear in the manual. I thought that objects at pseudo-indices were special objects that can be accessed but can not be changed because they are not really in the current stack. I was completely wrong. That means , for example, a function can change the global thread environment or even the registry with lua_replace(L, LUA_GLOBALSINDEX, ) or lua_replace(L, LUA_REGISTRYINDEX, ) , isn't it? Now I think about it, it seems quite reasonable.
Jose L.
PD: And please excuse my bad English :)
El 29/08/2006, a las 18:29, Luis Carvalho escribió:
On Tue, Aug 29, 2006 at 08:57:22AM +0200, Jose Luis Hidalgo Valiño wrote:
<snip>
LUA_ENVIRONINDEX seems a way to hold data locally to a set of
functions ( or only one ) but without loosing the possibility of
access the full global environment (the thread environment) through
LUA_GLOBALSINDEX.
I like to think of LUA_ENVIRONINDEX as a sort of "lua_upvalueindex (0)": it is like a shared upvalue among all C functions that have the same environment. If by locally you mean private, then a closure is more appropriate, as Mildred
stated. Check toy example below.
In lua 5.1 lua_setfenv "changes" the behavior of LUA_ENVIRONINDEX or
LUA_GLOBALSINDEX ? I'm not sure.
I don't understand what you mean, but since lua_setfenv changes the
environment of a function, thread or userdata, it affects LUA_ENVIRONINDEX for
C functions.
A simple example:
/* environ.c */
#include <lua.h>
#include <lauxlib.h>
static int environ_upv (lua_State *L) {
 lua_Number e, u;
 /* get environment data */
 lua_rawgeti(L, LUA_ENVIRONINDEX, 1);
 e = luaL_optnumber(L, -1, 0);
 /* update environment */
 lua_pushnumber(L, e+1);
 lua_rawseti(L, LUA_ENVIRONINDEX, 1);
 /* get closure data */
 u = luaL_optnumber(L, lua_upvalueindex(1), 0);
 /* update closure */
 lua_pushnumber(L, u+1);
 lua_replace(L, lua_upvalueindex(1));
 lua_pushnumber(L, e);
 lua_pushnumber(L, u);
 return 2;
}
int luaopen_environ (lua_State *L) {
 /* set current environment */
 lua_createtable(L, 1, 0); /* environ table */
 lua_pushnumber(L, 0);
 lua_rawseti(L, -2, 1); /* environ[1] = 0 */
 lua_replace(L, LUA_ENVIRONINDEX);
 /* push closures with default environment (above) */
 lua_pushnumber(L, 0);
 lua_pushcclosure(L, environ_upv, 1);
 lua_setfield(L, LUA_GLOBALSINDEX, "env1");
 lua_pushnumber(L, 0);
 lua_pushcclosure(L, environ_upv, 1);
 lua_setfield(L, LUA_GLOBALSINDEX, "env2");
 /* change environment using setfenv */
 lua_pushnumber(L, 0);
 lua_pushcclosure(L, environ_upv, 1);
 lua_createtable(L, 1, 0); /* new environ table */
 lua_pushnumber(L, 0);
 lua_rawseti(L, -2, 1); /* environ[1] = 0 */
 lua_setfenv(L, -2);
 lua_setfield(L, LUA_GLOBALSINDEX, "env3");
 return 0;
}
Lua 5.1 Copyright (C) 1994-2006 Lua.org, PUC-Rio
require'environ'
printupv = function(f) print(string.format('env: %d, upvalue: %d', f())) end
printupv(env1)
env: 0, upvalue: 0
printupv(env1)
env: 1, upvalue: 1
printupv(env2)
env: 2, upvalue: 0
printupv(env2)
env: 3, upvalue: 1
printupv(env3)
env: 0, upvalue: 0
printupv(env3)
env: 1, upvalue: 1
printupv(env1)
env: 4, upvalue: 2
printupv(env1)
env: 5, upvalue: 3
printupv(env2)
env: 6, upvalue: 2
printupv(env2)
env: 7, upvalue: 3
For more examples of LUA_ENVIRONINDEX, check liolib.c.
Cheers,
Luis.
--
A mathematician is a device for turning coffee into theorems.
 -- P. Erdos
--
Luis Carvalho
Applied Math PhD Student - Brown University
PGP Key: E820854A <carvalho@dam.brown.edu>

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