[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6. Primitives useful for writing macros

The Q macro system allows arbitrary program transformation by running user-defined "macro functions at compile time functions. However, most of the time one only needs simple textual replacement, perhaps with parameters, as suggested by experience with the C pre-processor. The parse primitive function provides this functionality.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.1 parse

The "parse" routine takes any number of strings and/or expressions. If there is only a single string argument, "parse" parses the string, and yields the resulting parse tree expression. If there are multiple arguments, `parse' effectively parses their concatenation: when it gets to the end of one argument, it continues with the next. If one of the arguments is an expression, it is substituted in place.

The "increment" macro incr is a simple example:
 
:(macro incr :Y) = parse Y ":=" Y "+1
The application:
 
incr X
is re-writtenat compile-time to:
 
X:=X+1


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.2 The quote macro

The primitive macro quote puts quotes around its operands. Unless there are unquote operators (using `$'), the result is constant. For example: For example:
 
quote ~/Q/mi/parse* 3+$a
becomes:
 
["~/Q/mi/parse*" "3+$a"]
which (if a is has the value "4-5") evaluates to the 2-element vector:
 
["~/Q/mi/parse*" "3+4-5"]

The quote macro is the primitive used by all commands that do not evaluate their arguments. For example, the command "cd" is defined as:
 
:(macro cd :x@)= parse "__cd (quote " x@ ")"

(The first `x@' means the list of all the remaining arguments. The second "splices" the list `x' into `quote''s argument list.)

The body of cd is the call: parse "__cd (quote " x@ ")". First, parse scans the string "__cd (quote ". It then inserts the result of x@ (which is a list of expressions, usually just one), and finishes with the final quote bracket. Thus:
 
cd ../foo
is macro-expanded into (the parse of):
 
__cd (quote ../foo)
which becomes:
 
__cd ["../foo"]
where __cd is a non-macro function that does the actual work of cd.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.3 Features of quote

Parentheses, quoted strings, and backquotes are included in the resulting strings. Hence:
 
quote (3+4) "is"\: 10
==> ["(3+4)" "\"is\"\\:" "10"]
This is so avoid losing essential quoting and grouping information.

Also not that quote works of vectors of strings, not individual strings. If there are multiple expressions in parentheses, the result is multiple strings:
 
quote (a b)
==> ["(a)" "(b)"]
Concatenation of string vectors yields a distributive "join":
 
quote /(a b)/(c d)/
==>
["/(a)/(c)/" "/(a)/(d)/" "/(b)/(c)/" "/(b)/(d)/"]
This mechanism subsumes the {...}-feature of csh. For example, csh's:
 
cc -o foo{,.c}  # csh, not Q!
could be expressed as:
 
cc -o foo("" .c)

The same distribution is done for the result of an expression in $. If a has the value ["" ".c"], then quote foo$a evaluates to ["foo" "foo.c"]. If a is only a simple string (such as "\n.c"), it is split at newlines (so we get the same result as before).


[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by Per Bothner on December, 4 2001 using texi2html