-- output.lua
-- This table is what parseJsonFile() returned.
local gameData = {classes={"Warrior","Archer","Wizard"},stats={"Health","Mana"}}
function love.load()
initGame()
initLevelEditor() -- We got this line because DEV_MODE was true.
end

local pp = require("preprocess")
local info, err = pp.processFile{
pathIn = "game.lua2p", -- This is the file we want to process.
pathMeta = "game.meta.lua", -- Temporary output file for the metaprogram.
pathOut = "game.lua", -- The output path.
}
if not info then
error(err)
end
print("Lines of code processed: "..info.lineCount)

One benefit of all this is that certain tasks can be performed only once at build time instead of every time you run the program. For example, you may load and parse a bunch of data files only to finally convert the data to Lua tables or something. With preprocessing you can do that once at build time and enjoy a program that starts up and runs faster in the end.

Another benefit is that you can make choices in your metaprogram about what code the final program should have. For example, during development you may have a bunch of developer-only functionality that should be excluded from a public build. (Compare this to #if/#ifdef directives in C/C++.)

Yet another benefit is that some kinds of code are simply easier to write and look nicer if the code can run in multiple steps. Some boilerplate code can be reduced, for example.

After having published a couple of games on Steam and itch.io I knew that having a "build phase" when making games was very helpful. I could automate tasks and generally reduce a bunch of unpleasant repetitive work. A while ago I started experimenting with taking things a step further. I began to process all Lua files (and eventually images and shaders etc. too) before ever running the game, even locally. This allowed me to easily include or exclude functionality that only certain versions of the game should have/not have. For example, my game may have a developer version, a normal public version and a demo version. All I have to do now is to change a boolean and my build system spits out a different program, or set another boolean and the system spits out a Zip file for every platform and OS, ready to be published. I think any serious LÖVE game could benefit from this kind of workflow.

I'm also using a separate Lua installation to run this, though you could theoretically use LÖVE.

If you use the library as a command line program then the output folder is currently the same folder as where the specified files are (you send it a list of files as arguments). I should maybe add a way to specify an output path for each file if the library is used this way. The library won't be able to create any folders for the output though as that's impossible with just Lua's standard libraries and I don't want to add any external dependencies.