Dodo doc > Macros and Templates > Macro Function


Macro Function

Syntax

A macro function also uses "wrap". The function name as selector, the arguments and the continuations are captured using pattern matching. By default the argument list is empty which matches a constant or a function without arguments. By default there are two continuations, "return" and "throw".

Another captured item is the scope of the function declaration which is "instance" by default but can also be "type".

The macro block contains a substitution for the body of the function. The variable created by the selector pattern is a function that can be called in the substitute function body. The variable created by the arguments pattern is a record with members a1, a2... for each argument.
The arguments can be converted into a list with [$args] or passed directly to the function with f($args)

Examples:

wrap (selector: $f, arguments: $args):
   *counter = counter + 1
   return f($args)
.

wrap (selector: delete, arguments: _(a1: ?House))
{
   # delete(House): don't do anything
}

If the selector starts with a capital letter it matches a method or constructor. In that case the macro does not return a value but it can modify "self" which is returned to the caller. Arguments passed by reference can be modified in the arguments record. If the arguments are converted into a list, references lose their ability to be modified and active references become inactive.

Rationale: it is common to use macros that behave like functions and this syntax allows it. The selector can match an existing function to replace it or add logic ("wrap") around it.
Using "$" in front of the variable tells the compiler to do a substitution, it is as if the argument list was written where $args is.
The arguments passed to a function are like a tuple of values, which can be converted into a struct where each member has its own name, value and type. That is how they appear to the substitute function body.

Declaration and use

A macro function declaration follows the same rules as a function declaration. This includes polymorphism: a macro function can be overridden in a subtype. To replace the parent type macro function add the option "override: true" to the wrap parameters. By default, the selector in a subtype macro function calls the macro function defined in the parent type. With "override: true" it calls the wrapped function instead.

A macro function is used in the same way as a function. See chapter on functions.

Rationale: to work better as a wrapper for functions, macro functions must support overriding. It is a design goal to make macro function calls same as function calls.

^ 5.1. Simple Macro

v 5.3. Advanced Macro