This feature isn't yet fully specified.
In transition from version 0.7.9.5 to 0.7.9.6, the macro system has been replaced.
It now uses plain language semantics - there is no builtin language syntax extension for macro support anymore. Instead, macros are implemented by ordinary LITTLE classes, which act as transform operators on nested sequences as generated by the compiler.
A macro is a class, which extends the abstract base class
little.compiler.macro.Macro
, and provides
a concrete implementation of method replace()
.
The compiler recursively checks any compound expression - if it's first
component is a symbol matching a macro class, it applies instantiates that
class and applies it's replace()
method to
the compound, which is then replaced by the computed result.
As macros are ordinary classes, they must be made known to the compiler, before
they can be used. This is, as usually, achieved by the
using
form (you can either refer single macro classes,
or compiete packages).
They are also documented like ordinary classes, i.e. the doc
-form
works inside macro definitions as well. If used inside the macro
And, of course, they can use all features of inheritance, like all other classes.
Macro definitions may use macros, and macros may return macros - macro expansion is performed recursively by the compiler on either macro definitions and macro expansion results (if you insist on it, you can make the compiler bail out with a stack overflow exception by writing a recursive macro, which contains or returns itself).
Samples for macro syntaxes included in the current release are
(for (<var> <seq>) ...)
iterates over a sequence seq, using local variabe var(when <expr> ...)
executes a list of expressions, if expr is true(when <expr> ...)
executes a list of expressions, if expr is false
Writing a macro requires knowledge of the compiler's representation for LITTLE
code. It is, admittedly, not a completely trivial task at this point, but it
is immensely flexible. Macro writing is supported by a (growing) API of macros
provided by package little.compiler.macro
.
These macros wrap creation and manipulation of compiler data structures - goal is
to completely hide them and decouple the macro authoring API from compiler internals.
However, this is not yet achieved - at this point, it is strongly recommended to
read the package code, and also have a glance at package
little.lang.macro
as a starting point.
The macroquote syntax & <expr>
has been introduced
in release 0.7.9.7, to avoid a common pitfall - undesired macro expansion within hierarchies
of macro classes. The ordinary ancestor specification within a class declaration would expand
to a macro replacement, if the first/only ancestor is the name of a macro class (a class
derived from little.compiler.macro.Macro
. This can be avoided by preceding the
ancestor declaration clause by &
.
More documentation will follow.