lua-users home
lua-l archive

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


2010/12/12 Alexander Gladysh <agladysh@gmail.com>:
> Hi, list!
>
> I have some code, written in a Lua-based DSL, a lot of constructs like this:
>
> foo:bar "title"
> {
>  baz = "quo";
>
>  alpha:beta "gamma"
>  {
>    "delta";
>  };
> }
>
> This code is executed inside a custom global environment with
> pre-defined global objects foo and alpha (one can say these objects
> implement Builder pattern — things are a bit more complicated in my
> case, but that doesn't matter for this question).
>
> After the code is run, I inspect foo and alpha variables, and get the
> built data from them.
>
> Now I want to move this code to the Lua module — to make it reusable
> via require().
>
> Obviously, I can't just require() the file with DSL — the environment
> would be wrong.
>
> This means that I have to put my DSL into a function:
>
> local dsl_chunk = function()
>  return foo:bar "title"
>  {
>    baz = "quo";
>
>    alpha:beta "gamma"
>    {
>      "delta";
>    };
>  }
> end
>
> return
> {
>  dsl_chunk = dsl_chunk;
> }
>
> This works, but is less pretty. Also it affects the code that loads
> the DSL: I have to handle require-friendly DSL files differently.
>
> Perhaps there is some trick that I miss? I don't mind to add some
> boilreplate code to the "library" portions of my DSL code. But I'd
> like to keep that boilerplate to a bare minimum.

If you don't mind changing the extension for your DSL files (or have
any other way to distinguish them from regular Lua modules), a very
elegant solution (imho) would be to add a searcher function for your
files. A searcher is a function called by require, put in the
(misnamed) package.loaders table [1], that will look for for files
matching some path (the standard package.path or preferably some
custom package.dslpath), and try to load them using loadfile and
setfenv.

With that solution you can simply call require "foo" in your main
script, and that will load your files which contains only your bare
DSL code, the necessary boilerplate (the setfenv call and post-call
data extraction) being added by the searcher on the fly. I've
described extensively the search protocol in the Lua Programming Gems
book (last gem), and wrote some examples on the wiki [2][3][4], but I
can re-explain it here if you want.

[1] http://www.lua.org/manual/5.1/manual.html#pdf-package.loaders
[2] http://lua-users.org/wiki/LuaModulesLoader
[3] http://lua-users.org/wiki/BinaryModulesLoader
[4] http://lua-users.org/wiki/HashedModulesLoader