lua-users home
lua-l archive

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


On Tue, May 20, 2014 at 12:40 AM, Hisham <h@hisham.hm> wrote:
On 20 May 2014 01:31, Marc Lepage <mlepage@antimeta.com> wrote:
> Hi, looking for some thoughts on loading DSL style data.
>
> I have it working but would like to swap out the environment when doing so,
> so it doesn't trample on the global environment.
>
> I have something like:
>
> function load(name)
>     local env = getfenv(0)
>     setfenv(0, dsl)
>     local data = ""> >     setfenv(0, env)
> end
>
> Where I get the thread's environment, set the dsl table (with all the DSL
> functions) as the environment, load the data (using require), then restore
> the environment (presumably the _G table). Of course I should really pcall
> the load instead of require, and return the data, but that's the idea.
>
> This is using Lua 5.1.5. I understand that Lua 5.2 changes the way
> environments are handled?
>
> If anyone could offer tips here or even better, point to a page which
> explains a lot of this in this context, that would be super great.

it might or might not be exactly what you're looking for but your
problem reminded me of this:

https://github.com/keplerproject/luarocks/blob/master/src/luarocks/persist.lua#L19-L58

Hope that helps!

-- Hisham


Thanks. My first kick at the can just set a metatable on _G during the load, to try to avoid setting some functions. All the DSL functions were global.

That was messy (as I knew) so the last couple hours I managed to clean it up as follows.

All DSL functions exist in a table dsl. When loading, an empty environment env is used (via setfenv(0)). The empty environment has a metatable which directs __index access to the DSL table. That is how DSL functions are found. In fact, only DSL functions can be found (since the environment is otherwise empty), I'm OK with that.

The DSL table has a metatable which directs __index to a proxy table. That also starts out empty.

The environment metatable has __newindex which filters out certain attempts to set globals, and does something special with them. The rest are stored into the proxy table.

This means I cannot overwrite my DSL functions. E.g. if dsl.foo is a function, and I set global foo, it goes into the proxy table, and any access of foo still returns dsl.foo.

The point of this is that later on, after loading the DSL, the environment will switch back and I will also dump the contents of proxy back into it. So, when done using the DSL, dsl.foo no longer exists, and that foo that was set as a global is now a global.

That's the idea, anyways. I've hit some sort of hitch with accesses to globals in my "global" foo function no longer working after all this. Maybe I need to learn more about function environments.

Anyways this is almost working as I desire, just some glitches to work out. Still interested in tips.

Marc