• Subject: Re: Determining if _ENV is the first upvalue of a closure?
• From: "Soni L." <fakedme@...>
• Date: Fri, 13 Mar 2015 09:13:10 -0300

```

On 13/03/15 09:00 AM, Luiz Henrique de Figueiredo wrote:
```
```The compiler adds _ENV as the first upvalue for the main function of
a chunk. It never worries about that for other functions, and lets
lexical scoping do its work. The only rule the compiler uses is that it
transforms references to global variables v into references to _ENV.v.
Such references are not special in the bytecode. For instance, in the
code below f and g have exactly the same bytecode, except that f has an
upvalue named _ENV. If you strip the debug information, you can't tell
the two functions apart at all.

local t
local function f() print(t[1]) end
local G
local function g() G.print(t[1]) end

The GETTABUP instruction, which indexes upvalues, is used for both
global variables and fields of other upvalues, so for instance in

local math=math
local function f() print(math.sin(2)) end

both print and sin are resolved using GETTABUP, which is a good thing
for size and uniformity of the VM. I think that's the beauty of the
_ENV scheme for resolving global names.

Whether a function has _ENV as an upvalue depends on when and if it ever
refers to a global variable. If it never does, it does not have _ENV as
an upvalue. Even if it does, _ENV may not be the first upvalue.

For instance, consider this code:

local x
local function f() return x end
local function g() print(x) end
local function h() local y=2*x print(x) end

Then
- f has an upvalue x but not _ENV;
- g has both x and _ENV as upvalues, and _ENV is the first one;
- h has both x and _ENV as upvalues, but x is the first one.

But I'm sure you know all this and I'm not answering your question.

I think the only real solution is to avoid stripping debug information
and search the upvalue list for an upvalue named _ENV.

If you can change the app, then perhaps you can add a special entry
in environments (both the global one and custom ones) and look in
the list of upvalues to see if they are a table with that entry.
This would then work even after stripping debug information.

```
I wish Lua had "env stacks"[1] (_ENV with full support for setfenv()/getfenv())
```
```
[1]This is the only thing I could find even tho I'm sure I have a post on the mailing list about it... https://github.com/SoniEx2/sexlua/wiki/Changes-from-Rio-Lua#op_pushpopfenv-51-like-functionchunk-envs-but-more-powerful
```
--
Disclaimer: these emails are public and can be accessed from <TODO: get a non-DHCP IP and put it here>. If you do not agree with this, DO NOT REPLY.

```