There are two kinds of macros in ATS. One kind is C-like and the other kind is LISP-like, though they are much simpler as well as weaker than their counterparts in C and LISP, respectively.
The following two declarations bind the identifiers N1 and N2 to the abstract syntax trees (not strings) representing 1024 and N1 + N1, respectively:
#define N1 1024 #define N2 N1 + N1Suppose we have the following value declaration appearing in the scope of the above macro delarations:
val x = N1 * N2Then N1 * N2 first expands into 1024 * (N1 + N1), which further expands into 1024 * (1024 + 1024). Note that if this example is done in C, then N1 * N2 expands into 1024 * 1024 + 1024, which is different from what we have here. Also note that it makes no difference if we reverse the order of the previous macro definitions:
#define N2 N1 + N1 #define N1 1024If we declare a marco as follows:
#define LOOP (LOOP + 1)then an infinite loop is entered (or more precisely, some macro expansion depth is to be reached) when the identifier LOOP is expanded.
Macros in Long Form As a macro in short form can simply be considered a special kind of macro in long form, we first give some explanantion on the latter. A macro definition in long form is introduced via the use of the keyword macrodef. For instance, the following syntax introduces a macro name one that refers to some code, that is, abstract syntax tree (AST) representing the integer number 1.
macrodef one = `(1)The special syntax `(...), where no space is allowed between the backquote "`" and the left parenthsis "(", means to form an abstract syntax tree representing what is written inside the parentheses. This is often referred to as backquote-notation. Intuitively, one may think that a backquote-notation exerts an effect that "freezes" everything inside it. Let us now define another macro as follows:
macrodef one_plus_one = `(1 + 1)The defined macro name one_plus_one refers to some code (i.e., AST) representing 1 + 1. At this point, it is important to stress that the code representing 1 + 1 is different from the code representing 2. The macro name one_plus_one can also be defined as follows:
macrodef one_plus_one = `(,(one) + ,(one))The syntax ,(...), where no space is allowed between the comma "," and the left parenthesis "(", indicates the need to expand (or evaluate) whatever is written inside the parentheses. This is often referred to as comma-notation. A comma-notation is only allowed inside a backquote-notation. Intuitively, a comma-notation cancels out the "freezing" effect of the enclosing backquote-notation.
In addition to macro names, we can also define macro functions. For instance, the following syntax introduces a macro function square_mac:
macrodef square_mac (x) = `(,(x) * ,(x)) // [x] should refer to some codeHere are some examples that make use of square_mac:
fun square_fun (i: int): int = ,(square_mac `(i)) fun area_of_circle_fun (r: double): doubld = 3.1416 * ,(square_mac `(r))Macros in Short Form The previous macro function square_mac can also be defined as follows:
macdef square_mac (x) = ,(x) * ,(x) // [x] should refer to some codeThe keyword macdef introduces a macro definition in short form. The previous examples that make use of square_mac can now be written as follows:
fun square_fun (i: int): int = square_mac (i) fun area_of_circle_fun (r: double): doubld = 3.1416 * square_mac (r)In terms of syntax, a macro function in short form is just like an ordinary function. In general, if a unary macro function fmac in short form is defined as as follows:
macdef fmac (x) = $exp_defthen one may essentially think that a macro definition in long form is defined as follows:
macrodef fmac_long (x) = `($exp_def) // please note the backquoteand each occurrence of fmac($exp_arg) is automatically rewritten into ,(fmac_long(`($exp_arg))). Note that macro functions in short form with multiple arguments are handled in precisely the same fashion. The primary purpose for introducing macros in short form is to provide a form of syntax that seems more accessible. While macros in long form can be defined recursively (as is to be explained later), macros in short form cannot.
Recursive Macro Definitions (to be written later)
The code used for illustration is available here.