In order to manipulate syntax trees or provide annotations on source code, Slate provides another form of message-send called a macro-level message send. Sends of this sort have as their arguments the objects built for the expressions' shapes. Furthermore, the results of evaluation of macro-sends are placed in the syntax tree in the same location as the macro-send occupied.
Preceding any selector with a back-tick (`) will cause it to be sent as a macro. This means that the message sent will be dispatched on Slate's Syntax Node objects, which are produced by the parser and consumed by the compiler. Macros fit into the process of compiling in this order: the text is processed by the Lexer into a stream of tokens, which are consumed by the Parser to produce a (tree-)stream of Syntax Nodes. Before being passed to the compiler, the macroexpand method is recursively called on these syntax trees, which invokes every macro-level message-send and performs the mechanics of replacing the macro-send with the result of the method invoked. With this in mind, the Slate macro system is offered as a flexible communication system between the code-writer and the compiler or other tools or even other users, using parse trees as the medium.
As an example of the expressiveness of this system, we can express the type annotation and comment features of the Slate language in terms of macros:
Macros must be dispatched (if at all) upon the traits of expressions' syntactic representation. This introduces a few difficulties, in that some familiarity is needed with the parse node types in order to name them. However, only two things need to be remembered:
A fundamental application of the macro message-send system is the ability to obtain syntax trees for any expression at run-time. The most basic methods for this are `quote, which causes the surrounding expression to use its quoted value as the input for even normal methods, and `unquote results in an inversion of the action of `quote, so it can only be provided within quoted expressions. Lisp macro system users will note that this effectively makes `quote the same as quasi-quotation.
In experience with Lisp macros, nested quotation is often found necessary. In order to adequately control this, often the quotation prefix symbols have to be combined in non-intuitive ways to produce the correct code. Slate includes, as an alternative, two operations which set a label on a quotation and can unquote within that to the original quotation by means of referencing the label.
Most users need time to develop the understanding of the need for higher-order macros, and this relates to users who employ them. For reference, a Lisp book which covers the subject of higher-order macros better than any other is On Lisp[Graham 94]. However, it's also been said that Lisp's notation and the conceptual overhead required to manage the notation in higher-order macros keeps programmers from entering the field, so perhaps this new notation will help.
The operators are expr1 `quote: aLiteral and expr2 `unquote: aLiteral, and in order for this to work syntactically, the labels must be equal in value and must be literals. As well, the unquoting expression has to be a sub-expression of the quotation. The effect is that nesting an expression more deeply does not require altering the quotation operators to compensate, and it does indicate better what the unquoting is intended to do.
`with:as: is a proposed protocol for transparent substitution of temporary or locally-provided proxies for environment values and other system elements. This should provide an effective correspondent of the functionality of Lisp's "with-" style macros.
A future framework for expansion will involve accommodating the types of source-level pattern-matching used in tools for manipulating code for development, as in the Smalltalk Refactoring Browser.