Safe replacement for _ENV

Aug 29, 2014 at 12:25 AM
Hello,

In my current project using NLua which reads a DSL-like Lua file (for compatibility with a native client application using the same DSL Lua files), I'm using _ENV to define a superset of _G containing the specific DSL directives (for instance 'client_script' to be invoked using Lua's parenthesis-less call syntax) in the _ENV table.

Can I, as there's no separate memory management between LuaGlobal/environments in C#, replace this by using a different LuaGlobal load my DSL script in, and is it possible to set a metatable (containing __index/__newindex, primarily) on the LuaGlobal returned from CreateEnvironment?

Thanks in advance,

NTAuthority
Coordinator
Aug 29, 2014 at 1:49 PM
Hello,

yea, that sounds complicated. I thing, I did not understand what you are trying to accomplish.

May be this helps you:
LuaGlobal is like a LuaTable. All what you can do with the LuaTable, you can also do with LuaGlobal. It is also possible to extend LuaTable/LuaGlobal to add more functionallity (like I did with the LuaMember pattern in LuaGlobal).

The variable _G is implemented as argument on the chunks:
LuaResult Chunk(LuaGlobal _G)
{
  // compiled script
}
So, this is possible:
local mt = { __index =  { add = function (a, b) return a + b; end; } };
_G.__metatable = mt;
print(add(1,2));
print(add(20,30));
Helpful?
Aug 29, 2014 at 5:24 PM
That seems helpful, however, my __index callback typically wants to fall back to global scope... however rawget doesn't seem to work as expected?

See the following NeoCmd result:
> _G.__metatable = nil
> local rg = rawget
> local pr = print
> local mt = {
>       __index = function(t, k)
>               pr(t)
>               local raw = rg(t, k)
>               if raw then return raw end
>               pr('dummy')
>               return nil
>       end
> }
> _G.__metatable = mt
> pr(type(rg))
>
Neo.IronLua.LuaGlobal
dummy
LuaRuntimeException: Can not call nil value.
 at line#8(LuaGlobal _G) line line:14:4
As shown, rawget (aliased as 'rg' locally - there also seemed to be a bug with aliasing a global to a local with the same name) returns nil for the global 'type' function, which seems to be incorrect behavior compared to what Lua itself would do. I also can't directly access _G like in C Lua, as that'd obviously result in a stack overflow. :)
Coordinator
Aug 29, 2014 at 8:08 PM
I see the problem. You try to get the function-pointer of e.g. type.

But I implemented the the basic functions via LuaMember. That means, if you call e.g. type, NeoLua does some like this:
(getMember("type") ?? CallOrGenerateMember("type");
The "CallOrGenerate" is a placeholder where to call to the type functions is generated on first call. So, RawGet will never return a function pointer. This differs from c-lua.

But, this is ok. Because, if rawget returns nil and you return nil, than the default will be call.
_G.__metatable = { __index = function (t,k) console.WriteLine(k); return nil; end; }
print(type(2));

-- returns
print
type
number
The bad news: I found an error. Because every lua-function returns a value (at least a empty LuaResult), the return value is never nil/null. In Version 0.8.20 this will be fixed.

The good news: You can fix this until the next version by set the return type explicit to object.
_G.__metatable = { __index = function (t,k) : object console.WriteLine(k); return nil; end; }
there also seemed to be a bug with aliasing a global to a local with the same name) returns nil for the global 'type' function, which seems to be incorrect behavior compared to what Lua itself would do. I also can't directly access _G like in C Lua, as that'd obviously result in a stack overflow.
please more specific. What exact is not correct?
local type = 2;
print(2);
-- prints the number 2
Aug 29, 2014 at 8:12 PM
NeoLithos wrote:
I see the problem. You try to get the function-pointer of e.g. type.

But I implemented the the basic functions via LuaMember. That means, if you call e.g. type, NeoLua does some like this:
(getMember("type") ?? CallOrGenerateMember("type");
The "CallOrGenerate" is a placeholder where to call to the type functions is generated on first call. So, RawGet will never return a function pointer. This differs from c-lua.

But, this is ok. Because, if rawget returns nil and you return nil, than the default will be call.
Okay, that behavior seems acceptable.
> there also seemed to be a bug with aliasing a global to a local with the same name) returns nil for the global 'type' function, which seems to be incorrect behavior compared to what Lua itself would do. I also can't directly access _G like in C Lua, as that'd obviously result in a stack overflow.

please more specific. What exact is not correct?
local type = 2;
print(2);
-- prints the number 2
```
> local type = type
> type("")
>
LuaRuntimeException: Can not call nil value.
 at line(LuaGlobal _G) line line:2:1
This technique is commonly used to speed up global lookups, which may not be necessary in NeoLua, but for compatibility it'd be useful to support this.
Coordinator
Aug 29, 2014 at 9:24 PM
Bug in the parser.
I register the variables to early. Is fixed in Changeset 31393.

I will release the version on next friday. If you need a test version early I can sent it by email?
Coordinator
Aug 30, 2014 at 5:41 AM
Do you see any other problems, how I handle the basic function set? May be, I should set the references like c-lua in the LuaTable during the initialization of the LuaGlobal?