Macros are used to generate complex code from simple expressions. Unlike C++ macros, Sexy macros operate
on the entire expression of an invocation, rather than individual token arguments. A macro has the full
power of the language to generate source code. Macros are expanded using Just-in-Time compilation - when
a function body containing a macro invocation is executed for the first time the macro code is
evaluated. Macros definitions are themselves compiled when an invocation is first expanded.
(macro <namespace>.<macro-name> <input-name> <output-name> <body> )
Where namespace is an existent Sexy namespace and macro-name is a sequence of characters that has
the same character sequence as a local variable (must begin with a lower-case letter and is followed by
an arbitrary alphanumeric sequence).
The input-name and output-name are local variable identifiers which are given type Sys.IExpression
and Sys.IExpressionBuilder respectively.
The body is a sequence of s-expressions that will generally use the output expression builder to
define what expression sequence is generated from the input argument. A macro is free use all available resources to generate source code, such as given by reflection, or the parents or descendants of the expression of the invocation. The input-name variable is initialized with a reference to the full calling invocation expression for the macro - this allows the macro to iterate through an arbitrary number of arguments so that macro invocations are all variadic.
Macro invocations have the syntax (#<macro-name> ...)
Example:
(macro Sys.Maths.square in out") (Sys.ValidateSubscriptRange in.ChildCount 2 2 "macro square supports one argument only") (IExpressionBuilder lhs = out.AddCompound) (lhs.Copy (in.Child 1)) (out.AddAtomic "*") (IExpressionBuilder rhs = out.AddCompound) (rhs.Copy (in.Child 1)) ) (function Main -> (Int32 result): (Int32 i = 7) (result = (#square i)) )