I'm pleased to announce the availability of Metalua 0.7.2:
Metalua is a compiler for a superset of the Lua language, which supports compile-time metaprogramming: a source file can extend the language with new syntaxes on-the-fly, while being compiled. Such syntaxes can be packaged into extension modules, for easy distribution and reuse.
It is also a Lua program manipulation library: it generates and manipulates Abstract Syntax Trees (AST), decorated with source code pointers, which allow high-level analysis and manipulation of Lua programs. Besides converting between source, AST and bytecode formats, it offers some libraries such as `metalua.treequery`, which allow to analyze and modify ASTs. For instance, the following program finds and returns the names of all global variables occurring in a source file:
function all_globals(filename)
local globals = { }
local log = function() globals[identifier[1]] = true end
local mlc = require 'metalua.compiler'.new() -- compiler
local Q = require 'metalua.treequery' -- AST queries
local ast = mlc :srcfile_to_ast (filename)
Q(ast) -- globals are...
:filter 'Id' -- ...nodes with tag 'Id'...
:filter_not (Q.is_binder) -- ...which are not local binders...
:filter_not (Q.get_binder) -- ...and aren't bound;
:foreach (log) -- log each of them in `globals`.
return globals
end
Metalua is used as a Lua code analysis tool in projects like
LuaDevelopmentTools (the Eclipse-based Lua IDE),
LuaDocumentor (an LDoc-like tool which retrieves information missing from comments through code analysis),
LuaInspect (back-end for SciTE and ZeroBrane) , etc.
Language extensions wise, Metalua comes with two substantial extension modules:
- `metalua.extension.comprehension` is a language extension which supports lists by comprehension:
-{ extension('comprehension', ...) }
even = { i for i=1, 100 if i%2==0 }
It also supports improved loops, by allowing to compose their headers:
for i=1, 10 for j=1,10 if i~=j until i+j>17 do print(i,j) end
In such loops, `break` statements are handled gracefully (and `continue` statements are accepted ;-))
- `metalua.extension.match` is a language extension which offers ML / Haskell style structural pattern matching, particularly useful for AST manipulations:
-{extension('match',...)}
match ast with
| `Function{ args, body } -> do_stuff_with(args, body)
| `Number{ 0 } -> print "this is a zero"
| `Do{ ... } -> print("block of "..select('#', ...).." statements)
| x -> print("Don't know what to do with a "..tostring(x.tag))
end
In contrast to previous versions of Metalua, this version requires no compilation nor bootstrapping step to be installed: put the `metalua/` directory in your `$LUA_PATH`, and it works.
Libraries written in Metalua can be loaded from plain Lua ones by first performing `require "metalua.loader"` (or passing option `-lmetalua.loader` to the Lua interpreter), which will extend `package.loaders`. They can also be precompiled into bytecode, to be loaded by the regular Lua loader.
For convenience, Metalua has been cut in two separate Lua rocks:
- metalua-parser is the AST generation part, and is 100% written in plain Lua; it should be easily portable to Lua 5.2 and LuaJIT;
- metalua-compiler supports language extensions, and features libraries such as TreeQuery which are written with those extensions. It still depends on Lua 5.1, as it only generates 5.1 bytecode.
--
Fabien.