• Aucun résultat trouvé

Macro Arguments

Dans le document Syntax and Semantics (Page 152-156)

ABCDEFGH I JKLMNOP QRS TUVWXYZ abcdefghijklmnopqrstuvwxyz

12. Objmods, Intmods, Libraries, and Search Rules

13.6. Macro Arguments

Most macro arguments may consist of the intended text with no special delimiters. But if the macro argument is a text "fragment" (e.g., if it contains unmatched parentheses), then it must be enclosed in brackets. An argument with unmatched brackets is not allowed.

The text of each macro argument starts with the first character (other than the "white space"

characters space, tab, eol, or eop) following the previous tenninating comma (or the opening left parenthesis of the argument list).

If the first character of a macro argument is not a left bracket, then the text of the argument is terminated with the next comma (or the closing right parenthesis) except that nesting counts are kept of parentheses and brackets; the argument text does not terminate until each nesting count is zero. That is, each time a left parenthesis (bracket) is encountered, the parenthesis (bracket) nesting count is incremented by one and each time a right parenthesis (bracket) is encountered, the appropriate count is decremented by one. The macro argument scan does not terminate until both counts are zero and a comma or right parenthesis is encountered. Trailing characters such as space, tab, eol, and eop are removed from the argument text. Comments are discarded;

i.e., if "#" is encountered, the remainder of the line is removed from the argument text.

String constants are treated as a unit; i.e., when a double quote is found, the compiler

immediately scans for the end of the string constant (as described in Section 3.5). Parentheses, commas, or brackets that occur in the string constant are not specially processed.

Commas may appear within properly nested parentheses, brackets, or string constants.

If the first character of a macro argument is a left bracket (" [It), then the argument is the sequence of characters up to the next matching right bracket (a nesting count, as described above, is kept for brackets, and the argument text terminates when the count is zero). This allows almost arbitrary text to be used as a macro argument; i.e., no attention is paid to parentheses, commas, string quotes, or comments within square brackets.

13.6.1. Repeatable Macro Parameters, $numArgs, $arg, and $sArg The last parameter of a macro may be declared repeatable:

DEFINE foo(a,b,REPEATABLE v)

= [ ... ];

In a call to such a macro, the arguments that correspond to the repeatable parameter are treated as if they had been enclosed in square brackets, i.e., as if they were a single argument

foo (i, j, k, l,m, n) => foo (i, j, [k, l,m, n])

Each occurrence of the repeatable parameter in the macro body is replaced by the bracketed text Thus, an occurrence of "v" in foo's body expands to "k,l,m,n".

Usually, however, it is desired to deal with one at a time of the arguments passed to the repeatable parameter, not with all of them at once.

Three special-purpose macros are provided for accessing the individual arguments of a repeatable parameter:

• "SnumArgs(v)" is the number of arguments passed to repeatable parameter v. For example, in the call to foo above, "$numArgs(v)" is 4 since [k,l,m,n] was passed to v.

• "Sarg(v,i)" is the ith argument passed to repeatable parameter v (the first argument is numbered one). For example, "Sarg(v,3)" above is m, since m was the third

argument in the [kJ,m,n] passed to v. If i is less than lor greater than the number of arguments passed to v, Sarg expands to no characters, i.e., D.

• "SsArg(v,i)" is like "$arg(v,i)" except that it expands to a string constant containing the text that "Sarg(v,i)" would have returned ([] is treated as '"'). For example,

"SsArg(v,3)" above would be the string constant "m".

SsArg is useful when the text of a macro is to be used as if it were a string constant. With a normal parameter, the effect can be obtained as follows:

DEFINE print(a)

=

[ttyWrite("a" & eol)];

Thus:

print (Hello)

causes "Hello<eol>" to be written. If the parameter a were made repeatable with the same macro body:

DEFINE print (REPEATABLE a)

=

[ttyWrite("a" & eol)];

the effect of "print(x,y,z)" is not the same as "print(x); print(y); print(z)" since the former writes

"x,y,z<eol>" while the latter writes "x<eol>y<eol>z<eol>". The following:

DEFINE print (REPEATABLE a)

=

[ttyWrite("$arg(a,i)" & eol)];

writes n$arg(x,y ,z,i)<eol>", since $arg is not recognized inside a string constant Use $sArg to get the desired behavior for print:

DEFINE print (REPEATABLE a)

=

[$FORC i

=

1 UPTO $numArgs(a) $DOC ttyWrite($sArg(a,i) & eol) ENDC];

In this form, "print(x,y,z)" writes "x<eol>y<eol>z<eol>".

In fact, $numArgs, $arg, and $sArg are implemented in a way that allows them to be used with non-repeatable parameters:

• $numArgs really just counts how many macro arguments it has. For example,

"$numArgs(a,b,c)" is 3.

• These macros see their arguments after any macro parameters of enclosing macros have been expanded. When used as above, "$numArgs(v)" expands to

n$numArgs(k,I,m,n)", since v is [k,l,m,n].

• $arg really just selects its ith argument, where i is its last argument; similarly for

$sArg. For example, "$arg(a,b,c,2)" is b. If i is less than 1 or greater than the number of preceding arguments, $arg expands to [] and $sArg expands to "". Thus

"$arg(a,b,c,O)" is [] and "$sArg(a,b,c,4)" the null string.

• If $arg (or $sArg) has just one argument, it behaves as if there were a second argument (the index) with value 1; i.e., the first (and only) argument is selected.

A repeatable macro argument is really just a convenience so the programmer does not have to enclose the repeated arguments in brackets. This allows the syntax of a macro to look like that of a procedure, so that the programmer need not know which is really being called. Defining fooas:

DEFINE foo(a,b,c) [

...

] ;

and then invoking it as:

foo (i, j, [k, l,m,n])

has the same effect as the above example using a repeatable parameter and no brackets in the call. In particular, $numArgs, $arg, and $sArg can be used to "look inside" any bracketed arguments, not just those declared repeatable.

For example:

MODULE xProcs

DEFINE defProc(t,p)

=

[t PROCEDURE p] & [Proc (t parm);];

$FORC j

=

1 UPTO 4 $DOC

) ;

expands to:

REDEFINE

x

=

$arg([INTEGER,i], [LONG INTEGER,li], [REAL,r], [LONG REAL,lr],j);

defProc($arg(x,1),$arg(x,2» ENDC

MODULE xProcs (

INTEGER PROCEDURE iProc (INTEGER parm);

LONG INTEGER PROCEDURE liProc (LONG INTEGER parm);

REAL PROCEDURE rProc (REAL parm);

LONG REAL PROCEDURE lrProc (LONG REAL parm);

) ;

The following is an example ofa "compiletime case expression":

DEFINE pdfChrs(a)

=

[cvli($arg(pdfBoChars,pdfiChars,pdfLiChars,pdfrChars, pdfLrChars,pdfbChars,pdfLbChars,

pdfiChars + length(a),pdfaChars,pdfcChars, MESSAGE "pdfChrs: unexpected type"; 0,

$TYPEOF(a»)];

Using a parameter a in string quotes ("a") fails if a's argument contains undoubled string quotes; $sArg provides a safe, general way to convert an ordinary macro argument into a string constant:

DEFINE foo(a,b) [ ... write(f,$sArg([a],l» . . . ];

is like:

DEFINE foo (a,b) = [ ••• write (f, "a") ... ];

except that the latter is incorrect if the argument to "a" contains undoubled suing quotes. The argument a was enclosed in brackets when used as the argument to $sArg because a alone could expand to what appears to be several macro arguments.

13.7. Determining Whether a Macro Argument Has Been Omitted

Dans le document Syntax and Semantics (Page 152-156)

Documents relatifs