Minilang provides some support for meta-programming using macros. During compilation, function calls which meet certain criteria are treated as macro expansions:

  1. The function being called must evaluate to a constant value at the compilation stage, and

  2. The constant value is a macro value.

In this situation, the compiler applies the macro with the specified arguments passed as expression values. The macro must then return another expression value which the compiler then compiles in place of the original function call.

This method of implementing macros is different to most other languages that support macros in that the substitution is performed during compilation rather than before.

macro is a normal Minilang type and macros can be defined using a constant declaration (either def name := macro(Callback) or the compact alternative macro: name(Callback)). For example:

1macro: log(; Expr) do
2   :{print('[{:$Source}:{:$Line}] {:$Expr}\n'), Expr is Expr, Source is macro::value(Expr:source), Line is macro::value(Expr:start)}
5log(1 + 1)
[<console>:1] 2