-
Notifications
You must be signed in to change notification settings - Fork 89
Macro tips
Some quick notes about using macros and quotations. This should really be merged with macros' documentation page, but it will wait, because our parsetree structure is going to be changed soon and this will also impact quotations (simplyfiy them) a lot.
For best reference of how to write quotations, take a look at algorithm used to translate them in the sources. This code is quite self explaining (at least if you just need to know how to write quotations).
So first, why can't I write
<[ | Some (x) => x ]>
Unfortunately
| Some (x) => x
is a match case, not an expression, and standard quotation is used by default for expressions. To make a quoted match case, you must simply add the case:
target to the quotation. So it would finally look like
<[ case: | Some (x) => x ]>
Unfortunately parsetree is not yet unified enough to look very consistent and try
statement use different syntax for quotations. You write
<[ try $body catch { $exn : $exn_ty => $handler } ]>
This quotation allows only one handler in catch, but you can nest others in body of try block.
Macros are arbitrary functions and they can reference any external classes. It is sometimes also useful to use Nemerle compiler API from withing a macro. It is usually done using two methods
- Using static helper functions from Nemerle.Compiler namespace
- Using the instance of typer to make more advanced things, like typing some code fragment, asking for defined local variables in current scope, etc.
Consider following code:
macro PrintVisibleLocalVariables(msg)
{
def typer = Nemerle.Macros.ImplicitCTX();
when (typer.IsMainPass)
{
Message.Hint("");
Message.Hint($"Variables in $msg");
Message.Hint($"$(msg.Location)");
def locals = typer.LocalContext.GetLocals();
mutable count = 0;
foreach ((name : Nemerle.Compiler.Parsetree.Name, _value : Nemerle.Compiler.LocalValue) in locals)
{
Message.Hint($" Variable: '$(name.Id)'");
count++;
}
Message.Hint($"In this location $count variable(s) are visible.");
}
<[ () ]>
}
...
mutable x = 0;
PrintVisibleLocalVariables("some location");
Main.n(18,5):Warning: hint: Variables in "some location" Main.n(18,5):Warning: hint: Main.n:18:32:18:46: Main.n(18,5):Warning: hint: Variable: 'x' Main.n(18,5):Warning: hint: In this location 1 variable(s) are visible.
This is the way how you can get some compiler's internals for your own usage. Feel free to ask for new useful methods to be created in compiler if you need them.