lua-users home
lua-l archive

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


D Burgess wrote:
> lua_getfenv() and getfenv() need to handle the case when
> c.env == NULL
>
Also,  getcurrenv() in lapi.c needs a little thought.

I have attached another patch which i feel is a lot nicer in its implementation than the previous 5 minute job i threw together.

The lua_getfenv has been resolved to return nil should the function not have an environment. I have removed the lua_clearfenv()/clearfenv() functions in favour of using lua_setfenv/setfenv() with nil as the special value that indicates the environment should be the "dynamic environment". By that meaning use the environment of the current thread as opposed to the inherited environment at creation time.

With regards to the getcurrenv(), it does depend on what one wants really. My understanding, the lua implementors can correct me if i am wrong, but the environments are inherited from the enclosing closure, this is for both closures and userdata. If one considers this nil environment to be a dynamic environment then it would make sense that new objects inherit the dynamic environment, this is represented as no environment.

Naturally i cannot guarantee that this works and is bug free ;-)

Andrew



diff -r lua-5.1.1/src/lapi.c lua-5.1.1.patched/src/lapi.c
64c64
<       sethvalue(L, &L->env, func->c.env);
---
>       sethvalue(L, &L->env, func->c.env ? func->c.env : hvalue(gt(L)));
616a617
>   setnilvalue(L->top);
619c620,621
<       sethvalue(L, L->top, clvalue(o)->c.env);
---
>       if (clvalue(o)->c.env)
>         sethvalue(L, L->top, clvalue(o)->c.env);
622c624,625
<       sethvalue(L, L->top, uvalue(o)->env);
---
>       if (uvalue(o)->env)
>         sethvalue(L, L->top, uvalue(o)->env);
627,629d629
<     default:
<       setnilvalue(L->top);
<       break;
737d736
<   api_check(L, ttistable(L->top - 1));
740c739,740
<       clvalue(o)->c.env = hvalue(L->top - 1);
---
>       api_check(L, ttistable(L->top - 1) || ttisnil(L->top - 1));
>       clvalue(o)->c.env = ttisnil(L->top - 1) ? NULL : hvalue(L->top - 1);
742a743
>       api_check(L, ttistable(L->top - 1));
745a747
>       api_check(L, ttistable(L->top - 1));
diff -r lua-5.1.1/src/lbaselib.c lua-5.1.1.patched/src/lbaselib.c
144c144
<   luaL_checktype(L, 2, LUA_TTABLE);
---
>   int t = lua_type(L, 2);
145a146,150
>   if (lua_isfunction(L, -1))
>     luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
> 		      "nil or table expected");
>   else
>     luaL_checktype(L, 2, LUA_TTABLE);
diff -r lua-5.1.1/src/lgc.c lua-5.1.1.patched/src/lgc.c
225c225,226
<   markobject(g, cl->c.env);
---
>   if (cl->c.env)
>     markobject(g, cl->c.env);
diff -r lua-5.1.1/src/lvm.c lua-5.1.1.patched/src/lvm.c
433c433
<         Protect(luaV_gettable(L, &g, rb, ra));
---
>         Protect(luaV_gettable(L, cl->env ? &g : gt(L), rb, ra));
444c444
<         Protect(luaV_settable(L, &g, KBx(i), ra));
---
>         Protect(luaV_settable(L, cl->env ? &g : gt(L), KBx(i), ra));