Syntactic macros allow new language constructs to be created.
We could, for example, mimic VisualBasic's with statement.
Given the following code:
If we define a 'with' macro we could rewite it like this:
In boo, macros are CLI objects that implement the Boo.Lang.Compiler.IAstMacro interface. It is inetresting to note that there is nothing magic about these objects. They must simply implement the interface the compiler expects. This implies that boo macros can be written in any CLI language!
When an unknown syntactic structure is encountered at compile time, like the with statement above, the compiler will look for the correct IAstMacro class, create an instance, and ask that instance to expand the macro. The compiler identifies the class to use via a simple naming convention. The class name must start with the name of the macro and end with 'Macro'. Additionally the PascalCase naming convention must be used. So in this case the name must be 'WithMacro'.
Here's the code to implement our macro:
Some explanation is in order. The parsing stage of the compiler pipeline parses a source stream into an abstract syntax tree (AST). A subtree, corresponding to the macro, will be passed to the Expand() method. Expand() is responsible for building an AST that will replace the provided subtree.
The subtree corresponding to a macro statement is embodied by the MacroStatement parameter.
A MacroStatement has a collection of arguments and a block.
In this case we expect a single argument: a reference to an object. We then traverse the block looking for references whose name begins with the '_' character. Whenever we encounter one, we replace it with a reference to a member.
There are two classes related specifically to AST traversal: DepthFirstVisitor and DepthFirstTransformer. Both classes walk an AST invoking appropriate methods for each type of element in the tree. In this case, we subclassed DepthFirstTransformer as a convenient way to find and replace ReferenceExpression nodes in the macro's block.
You can find this plus other macro examples in the examples/macros directory.