Previous
Home
Contents
Next
Chapter 12: Source macros
12.1 Macro definition
12.2 Macro expansion
12.3 Examples
12.4 Points of style
12.1 : Macro definition
Aldor provides a way to define abbreviations, or macros, to make programs easier to read.
A common use of macros is to abbreviate names or type expressions,
as in the example below.
The lines containing "==>" are macro definitions:
-- Abbreviations for frequently used types:
SI ==> SingleInteger;
L T ==> List T;
split(lsi: L SI): Record(first: SI, second: SI, rest: L SI) ==
[first lsi, first rest lsi, rest rest lsi];
-- Abbreviations for long package names:
MStudy ==> LongitudinalStudiesOfMitralValveReplacementPatients;
d0 := intakes()$MStudy;
d1 := examinations()$MStudy;
The left hand side of a macro definition may be either an identifier or an application. A definition of the form
Op Parms ==> Body
is equivalent to
Op ==> macro Parms +-> Body
and defines a parameterized macro. Any application syntax is permitted on the original left hand side: prefix, infix, or bracketed. The resulting right hand side is called a macro function.
This rule is applied until the left hand side is an identifier. Macros may consequently be defined to receive their arguments in groups, in a ``curried'' fashion. For example, when P1 and P2 are parameter sequences, the definition
Op (P1)(P2) ==> Body
is equivalent to
Op ==> macro (P1) +-> macro (P2) +-> Body
Macro functions may appear directly in the source program, and may be written with their parameters in groups:
macro (P1)(P2)...(Pn) +-> Body
is equivalent to
macro (P1) +-> macro (P2) +-> ... macro (Pn) +-> Body
12.2 : Macro expansion
The process or replacing the abbrevations with what they stand for is called macro expansion. Macro expansion works by making substitutions in the parsed form of programs. Because the substitution is on trees, it is not necessary to include extra parentheses in macro definitions.
Macro expansion transforms the source syntax trees with the following steps:
+->'', ``where'', ``add'' or ``with''
in which it occurs.
(macro Parms +-> Body) (Exprs)
by introducing new macro definitions for the formal parameters and replacing the application with the macro expanded body.
Once macro expansion is complete, the entire program should be
free of macro definitions and macro functions.
The process of macro expansion removes all macro definitions;
any remaining unreduced macro functions are reported as errors.
12.3 : Examples
Given the following definitions,
a ==> A1 - A2; b ==> B; c ==> C; d(e,f)(g,h) ==> (e+f)*(g+h); x + y ==> c(x,y); f(g,x,y) ==> g(x,y) / g(y,x);
the following expressions expand as shown:
a; --> A1 - A2 b; --> B a + b; --> C(A1 - A2, B) d(1,2)(3,4); --> C(1,2) * C(3,4) f(+,u,v); --> C(u,v) / C(v,u) f((macro (a,b) +-> a), u, v); --> u / v (macro (a,b)(c)(d) +-> [a,b,c,d])(3,4)(5)(6); --> [3, 4, 5, 6]
12.4 : Points of style
It is often convenient to use macros which are local to a function
or expression. Below, we show a macro "l1?" which is
local to the function "f".
f(li: List Integer, lp: List Pointer): () == {
l1? x0 ==> (not empty? x and empty? rest x) where x := x0;
if l1? li then ...
if l1? lp then ...
...
}
The purpose of "l1?" is to provide an inexpensive test
whether a list has length one.
This example illustrates two additional points:
l1?"
macro may be applied to different values of different types.
If the body of the macro is large, having a "where" at the end of
a long expression can make a program harder to read.
A convenient way to introduce local variables in this case is to make
the left-hand side of the "where" a local macro.
BigBurger(patty1, patty2) ==> BB where {
p1 := patty1;
p2 := patty2;
BB ==> {
if not allBeef? p1 or not allBeef? p2 then
error "Bad food";
b := burger();
b << bottomBun;
b << p1;
b << cheese;
b << lettuce;
b << onions;
b << sauce;
b << middleBun;
b << p2;
b << cheese;
b << lettuce;
b << onions;
b << sauce;
b << topBun;
b
}
}
Just as a macro function
macro Parms +-> Body
is analogous to a function "Parms +-> Body",
a macro definition
Lhs ==> Expr.
is analogous to a definition "Lhs == Expr".
For this reason, a macro definition may be written
in the equivalent form
macro Lhs == Expr.
Previous
Home
Contents
Next