Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lua - Reseting the state of a script without reparsing it

I have an application that runs Lua scripts. Each Lua script is likely to run several times. Some scripts may even run every time a key is pressed.

I would like these scripts to be "reset" between each run. I.e if a user sets a variable Foo, then Foo should not exist in the script the next time it runs until the user defines it again.

The problem is that, if I want to have such a behaviour, I need to create a new lua_State everytime, then open the libraries into it every time, and then parse the script file everytime, which seems very unoptimized.

Loading the libraries may be a rather lightweight operation (I assume), but parsing the scripts is probably not.

Is there a way to reset the state of a Lua script (i.e clear user-code-defined variables) without creating a new lua_State and reparsing the whole Lua script file ? I would just like the script files to be parsed once on application startup since they are not modifed at run-time.

Thank you. :)

EDIT : I found this topic but it is not detailed about to do that : http://lua-users.org/lists/lua-l/2006-01/msg00493.html

EDIT : lua_setfenv seems to be related to that. I'll dig a bit more.

EDIT : It seems like there is no more lua_setfenv as of LUA 5.2. Since i'm using 5.3 I would have to set the environement (i.e a hidden table nammed _ENV where variables are stored) in order to do that, and thus reload everything, which is what I want not to do...

like image 928
Virus721 Avatar asked Oct 30 '22 09:10

Virus721


1 Answers

Last time I looked into this the answer was no, unfortunately.

You also need to remember that the Lua may call libraries, that may open files, malloc() memory etc., and that any 'reset' needs to deal with closing those files, freeing that memory, etc.

As an alternative to 'resetting' the Lua state, you could simply organise your code so that it did not need a reset; this obviously requires the Lua code to be written in a specific way. One way to do that would be to insist your Lua code was entirely (or almost entirely) contained within function(s) and call one or more functions for each action. The code outside the functions might (e.g.) return a Lua table consisting of references to call for particular entry points; this would only be called once. The function(s), when called, would clear up after itself, including clearing up any library allocated items, open files, etc. Global variables should be avoided (unless constant). We successfully use this approach to ensure Lua is only parsed once, the entry points determined once, but relative small functions can be called very rapidly with little overhead.

In the comments you suggested you could lexically wrap the Lua code in a function block. I think this is less flexible than the above approach, and has the following disadvantages:

  • You lose the opportunity to do a 'one time init' (e.g. for instance reading a fixed constant from disk)

  • You risk unpredictable things if a user inserts (e.g.) a mismatched end ... function B() in their code

  • You constrain yourself to one entry point per Lua state.

It does mean that the Lua code must be written in a different way (in essence the Lua coder is supplying the code in the form required). One possible way around this is to use a fixed framework to do this and require in the code to be called as libraries. I have not tried that approach.

like image 82
abligh Avatar answered Nov 15 '22 07:11

abligh