[Date Prev][Date Next][Thread Prev][Thread Next]
- Subject: Re: Feature request: hiding upvalues
- From: Dirk Laurie <dirk.laurie@...>
- Date: Tue, 13 Nov 2018 15:23:15 +0200
Op Di., 13 Nov. 2018 om 14:04 het Philippe Verdy <email@example.com> geskryf:
>> I'm not too sure how one could implement hiding of upvalues at the
>> language level. (At the implementation level, it's obvious. Just skip
>> the phase that looks for them.)
> This is not so obvious because Lua highly depends on this; the "phrase" that looks for it is exactly the one that lookups variables in the environment using its "__index" meta-entry, which is where the environment is already stated: so the first level of lookup would be required (otherwise the function itself not would have itself access its own local variables) but you want to avoid the recursion of the lookup to the next level to look for upvalues.
> Note that this recursion is a trailing recursion (so Lua optimizes it natively as a loop: the "phrase" you want to hide would be a statement within that loop, and you want it to be used only on a specific loop number to break that loop by returning early a "nil" value so that an "undefined variable error" can be stated). The difficulty is that there's no loop number which is accessible. So all I see you can do is to set the "__index" meta entry specifically to your need.
I think we are talking at cross-purposes.
Whether a name is recognized as an upvalue happens at compile time. No
metatable is involved. It's a question of what is in scope.
Do 'luac -l' for my two examples. The one without "x=1" generates the
instruction GETTABLE 4 0 -1 ; "x"
but the one with "x=1" generates GETUPVAL 4 0 ; x
The scope of a name is lexical. That means there is a sequence of
local scopes with the entire chunk outermost, each containing a
smaller scope until we get to the innermost scope. The compiler does
this when one refers to 'x':
1. Is there a local variable named 'x' in the innermost scope? If so,
it does not need to be loaded: the VM instruction can access it
2. For each containing containing scope working outwards, the question
is asked again. If a local variable named 'x' is found in that scope,
a GETUPVAL instruction is generated to load the variable via the
upvalue list that sits in the function's closure.
3. If no containing scope has 'x', a GETTABLE instruction is issued to
load the value as a table access from _ENV.
The requested "blind" keyword would merely tell the compiler to treat
the current innermost scope, from that point onwards, as not having a
containing scope, so that step 2 is an empty loop.
Youmay have been thinking of what happens in case 3: the GETTABLE from
_ENV could trigger a whole chin of __index metamethods, depending on
what you have done with _ENV (in fact, since this idiom is used in an
object-oriented paradigm, your _ENV is an object which may well have a