Is there a way to call require
in a Lua file, and have the module set the environment of the file that calls it? For example, if I have a DSL (domain specific language) that defines the functions Root
and Sequence
defined in a table, can I have something like setfenv(1, dslEnv)
in the module that allows me to access those functions like global variables?
The goal I in mind is using this is a behavior tree DSL in a way that makes my definition file look like this (or as close it as possible):
require "behaviortrees"
return Root {
Sequence {
Leaf "leafname",
Leaf "leafname"
}
}
without having to specifically bring Root
, Sequence
, and Leaf
into scope explicitly or having to qualify names like behaviortrees.Sequence
.
In short, I'm trying to make the definition file as clean as possible, without any extraneous lines cluttering the tree definition.
Can I have something like
setfenv(1, dslEnv)
in the module that allows me to access those functions like global variables?Sure you can. You just have to figure out the correct stack level to use instead of the
1
in yoursetfenv
call. Usually you'd walk up the stack using a loop withdebug.getinfo
calls until you find therequire
function on the stack, and then you move some more until you find the next main chunk (just in case someone callsrequire
in a function). This is the stack level you'd have to use withsetfenv
. But may I suggest a ...Different Approach
require
in Lua is pluggable. You can add a function (called a searcher) to thepackage.loaders
array, andrequire
will call it when it tries to load a module. Let's suppose all your DSL files have a.bt
suffix instead of the usual.lua
. You'd then use a reimplementation of the normal Lua searcher with the differences that you'd look for.bt
files instead of.lua
files, and that you'd callsetfenv
on the functionreturn
ed byloadfile
. Something like this:If you put this in a module and
require
it once from your main program, you can thenrequire
your DSL files with the custom environment from.bt
files somewhere where you would put your.lua
files as well. And you don't even need therequire("behaviortrees")
in your DSL files. E.g.:File
xxx.bt
:File
main.lua
: