Templet for Lua

Templet is a template preprocessor written in pure Lua that parses text templates with embedded Lua statements and expressions. Templet may be used to preprocess source files of any language, such as OpenCL C. Templet works with Lua 5.1, Lua 5.2, Lua 5.3, and LuaJIT.

Consider a system of non-interacting classical particles. We would like to generate C code that moves the particles by a given time step. This should work for both 2 and 3 dimensional systems, and constant parameters should be substituted along the way.

First, the template is parsed, e.g., from a multi-line Lua string:

local templet = require("templet")

local temp = templet.loadstring([[
for (int i = 0; i < ${nparticle}; ++i) {
  |for i = 1, #coord do
  r[i].${coord[i]} = r[i].${coord[i]} + v[i].${coord[i]} * ${timestep};
  |end
}
]])

The template is then rendered, given a set of parameters:

local env = {coord = {"x", "y", "z"}, nparticle = 5000, timestep = 0.001}
io.write(temp(env))

In the resulting output, the loop has been expanded, and constants substituted:

for (int i = 0; i < 5000; ++i) {
  r[i].x = r[i].x + v[i].x * 0.001;
  r[i].y = r[i].y + v[i].y * 0.001;
  r[i].z = r[i].z + v[i].z * 0.001;
}
local env = {coord = {"x", "y"}, nparticle = 1000, timestep = 0.002}
io.write(temp(env))

The same template can be rendered, e.g., for a 2-dimensional system:

for (int i = 0; i < 1000; ++i) {
  r[i].x = r[i].x + v[i].x * 0.002;
  r[i].y = r[i].y + v[i].y * 0.002;
}

The resulting C code could be passed to a just-in-time C compiler for immediate execution.

Acknowledgements

I would like to thank Rici Lake for writing the Slightly Less Simple Lua Preprocessor, which provided the basis of the Templet parser, as well as Michal Januszewski and the Sailfish contributors for providing a real-world example of dynamically compiled GPU code templates in a simulation code.