483 lines
165 KiB
Plaintext
483 lines
165 KiB
Plaintext
Copyright (c) 1986 Xerox Corporation. All rights reserved.
|
||
|
||
25.8.3 Read Macros
|
||
1
|
||
|
||
Read macros are user-defined syntax classes that can cause complex operations when certain characters are read. Read macro characters are defined by specifying as a syntax class an expression of the form:
|
||
(TYPE OPTION1 ... OPTIONN FN)
|
||
where TYPE is one of MACRO, SPLICE, or INFIX, and FN is the name of a function or a lambda expression. Whenever READ encounters a read macro character, it calls the associated function, giving it as arguments the input stream and read table being used for that call to READ. The interpretation of the value returned depends on the type of read macro:
|
||
MACRO This is the simplest type of read macro. The result returned from the macro is treated as the expression to be read, instead of the read macro character. Often the macro reads more input itself. For example, in order to cause ~EXPR to be read as (NOT EXPR), one could define ~ as the read macro:
|
||
[MACRO (LAMBDA (FL RDTBL)
|
||
(LIST 'NOT (READ FL RDTBL]
|
||
SPLICE The result (which should be a list or NIL) is spliced into the input using NCONC. For example, if $ is defined by the read macro:
|
||
(SPLICE (LAMBDA NIL (APPEND FOO)))
|
||
and the value of FOO is (A B C), then when the user inputs (X $ Y), the result will be (X A B C Y).
|
||
INFIX The associated function is called with a third argument, which is a list, in TCONC format (("TCONC" . Function)), of what has been read at the current level of list nesting. The function's value is taken as a new TCONC list which replaces the old one. For example, the infix operator + could be defined by the read macro:
|
||
(INFIX (LAMBDA (FL RDTBL Z)
|
||
(RPLACA (CDR Z)
|
||
(LIST (QUOTE IPLUS)
|
||
(CADR Z)
|
||
(READ FL RDTBL)))
|
||
Z))
|
||
If an INFIX read macro character is encountered not in a list, the third argument to its associated function is NIL. If the function returns NIL, the read macro character is essentially ignored and reading continues. Otherwise, if the function returns a TCONC list of one element, that element is the value of the READ. If it returns a TCONC list of more than one element, the list is the value of the READ.
|
||
The specification for a read macro character can be augmented to specify various options OPTION1 ... OPTIONN, e.g., (MACRO FIRST IMMEDIATE FN). The following three disjoint options specify when the read macro character is to be effective:
|
||
ALWAYS The default. The read macro character is always effective (except when preceded by the % character), and is a break character, i.e., a member of (GETSYNTAX 'BREAK RDTBL).
|
||
FIRST The character is interpreted as a read macro character only when it is the first character seen after a break or separator character; in all other situations, the character is treated as having class OTHER. The read macro character is not a break character. For example, the quote character is a FIRST read macro character, so that DON'T is read as the single atom DON'T, rather than as DON followed by (QUOTE T).
|
||
ALONE The read macro character is not a break character, and is interpreted as a read macro character only when the character would have been read as a separate atom if it were not a read macro character, i.e., when its immediate neighbors are both break or separator characters.
|
||
Making a FIRST or ALONE read macro character be a break character (with SETBRK) disables the read macro interpretation, i.e., converts it to syntax class BREAKCHAR. Making an ALWAYS read macro character be a break character is a no-op.
|
||
The following two disjoint options control whether the read macro character is to be protected by the ESCAPE character on output when a litatom containing the character is printed:
|
||
ESCQUOTE or ESC The default. When printed with PRIN2, the read macro character will be preceded by the output escape character (%) as needed to permit the atom containing it to be read correctly. Note that for FIRST macros, this means that the character need be quoted only when it is the first character of the atom.
|
||
NOESCQUOTE or NOESC The read macro character will always be printed without an escape. For example, the ? read macro in the T read table is a NOESCQUOTE character. Unless you are very careful what you are doing, read macro characters in FILERDTBL should never be NOESCQUOTE, since symbols that happen to contain the read macro character will not read back in correctly.
|
||
The following two disjoint options control when the macro's function is actually executed:
|
||
IMMEDIATE or IMMED The read macro character is immediately activated, i.e., the current line is terminated, as if an EOL had been typed, a carriage-return line-feed is printed, and the entire line (including the macro character) is passed to the input function.
|
||
IMMEDIATE read macro characters enable the user to specify a character that will take effect immediately, as soon as it is encountered in the input, rather than waiting for the line to be terminated. Note that this is not necessarily as soon as the character is typed. Characters that cause action as soon as they are typed are interrupt characters (see ("Interrupt Characters" . TERM)).
|
||
Note that since an IMMEDIATE macro causes any input before it to be sent to the reader, characters typed before an IMMEDIATE read macro character cannot be erased by control-A or control-Q once the IMMEDIATE character has been typed, since they have already passed through the line buffer. However, an INFIX read macro can still alter some of what has been typed earlier, via its third argument.
|
||
NONIMMEDIATE or NONIMMED The default. The read macro character is a normal character with respect to the line buffering, and so will not be activated until a carriage-return or matching right parenthesis or bracket is seen.
|
||
Making a read macro character be both ALONE and IMMEDIATE is a contradiction, since ALONE requires that the next character be input in order to see if it is a break or separator character. Thus, ALONE read macros are always NONIMMEDIATE, regardless of whether or not IMMEDIATE is specified.
|
||
Read macro characters can be "nested". For example, if = is defined by
|
||
(MACRO (LAMBDA (FL RDTBL)
|
||
(EVAL (READ FL RDTBL))))
|
||
and ! is defined by
|
||
(SPLICE (LAMBDA (FL RDTBL)
|
||
(READ FL RDTBL)))
|
||
then if the value of FOO is (A B C), and (X =FOO Y) is input, (X (A B C) Y) will be returned. If (X !=FOO Y) is input, (X A B C Y) will be returned.
|
||
Note: If a read macro's function calls READ, and the READ returns NIL, the function cannot distinguish the case where a RIGHTPAREN or RIGHTBRACKET followed the read macro character, (e.g. "(A B ')"), from the case where the atom NIL (or "()") actually appeared. In Interlisp-D, a READ inside of a read macro when the next input character is a RIGHTPAREN or RIGHTBRACKET reads the character and returns NIL, just as if the READ had not occurred inside a read macro.
|
||
If a call to READ from within a read macro encounters an unmatched RIGHTBRACKET within a list, the bracket is simply put back into the buffer to be read (again) at the higher level. Thus, inputting an expression such as (A B '(C D] works correctly.
|
||
(INREADMACROP) [Function]
|
||
1
|
||
|
||
Returns NIL if currently not under a read macro function, otherwise the number of unmatched left parentheses or brackets.
|
||
1
|
||
|
||
("BREAKRESETFORMS" . Variable)(READMACROS FLG RDTBL) [Function]
|
||
1
|
||
|
||
If FLG=NIL, turns off action of read macros in read table RDTBL. If FLG=T, turns them on. Returns previous setting.
|
||
1
|
||
|
||
The following read macros are standardly defined in Interlisp in the T and EDITRDTBL read tables:
|
||
' (single-quote) Returns the next expression, wrapped in a call to QUOTE; e.g., 'FOO reads as (QUOTE FOO). The macro is defined as a FIRST read macro, so that the quote character has no effect in the middle of a symbol. The macro is also ignored if the quote character is immediately followed by a separator character.
|
||
control-Y Defined in T and EDITRDTBL. Returns the result of evaluating the next expression. For example, if the value of FOO is (A B), then (LIST 1 control-YFOO 2) is read as (LIST 1 (A B) 2). Note that no structure is copied; the third element of that input expression is still EQ to the value of FOO. Control-Y can thus be used to read structures that ordinarily have no read syntax. For example, the value returned from reading (KEY1 control-Y(ARRAY 10)) has an array as its second element. Control-Y can be thought of as an "un-quote" character. The choice of character to perform this function is changeable with SETTERMCHARS (("SETTERMCHARS" . Function)).
|
||
` (backquote) Backquote makes it easier to write programs to construct complex data structures. Backquote is like quote, except that within the backquoted expression, forms can be evaluated. The general idea is that the backquoted expression is a "template" containing some constant parts (as with a quoted form) and some parts to be filled in by evaluating something. Unlike with control-Y, however, the evaluation occurs not at the time the form is read, but at the time the backquoted expression is evaluated. That is, the backquote macro returns an expression which, when evaluated, produces the desired structure.
|
||
Within the backquoted expression, the character "," (comma) introduces a form to be evaluated. The value of a form preceded by ",@" is to be spliced in, using APPEND. If it is permissible to destroy the list being spliced in (i.e., NCONC may be used in the translation), then ",." can be used instead of ",@".
|
||
For example, if the value of FOO is (1 2 3 4), then the form
|
||
`(A ,(CAR FOO) ,@(CDDR FOO) D E)
|
||
evaluates to (A 1 3 4 D E); it is logically equivalent to writing
|
||
(CONS 'A
|
||
(CONS (CAR FOO)
|
||
(APPEND (CDDR FOO) '(D E))))
|
||
.
|
||
Backquote is particularly useful for writing macros. For example, the body of a macro that refers to X as the macro's argument list might be
|
||
`(COND
|
||
((FIXP ,(CAR X))
|
||
,(CADR X))
|
||
(T .,(CDDR X)))
|
||
which is equivalent to writing
|
||
(LIST 'COND
|
||
(LIST (LIST 'FIXP (CAR X))
|
||
(CADR X))
|
||
(CONS 'T (CDDR X)))
|
||
Note that comma does not have any special meaning outside of a backquote context.
|
||
For users without a backquote character on their keyboards, backquote can also be written as |' (vertical-bar, quote).
|
||
? Implements the ?= command for on-line help regarding the function currently being "called" in the typein (see ("?=" . inTTYIN)).
|
||
| (vertical bar) When followed by an end of line, tab or space, | is ignored, i.e., treated as a separator character, enabling the editor's CHANGECHAR feature (("CHANGECHAR" . Variable)). Otherwise it is a "dispatching" read macro whose meaning depends on the character(s) following it. The following are currently defined:
|
||
' (quote) -- A synonym for backquote.
|
||
. (period) -- Returns the evaluation of the next expression, i.e., this is a synonym for control-Y.
|
||
, (comma) -- Returns the evaluation of the next expression at load time, i.e., the following expression is quoted in such a manner that the compiler treats it as a literal whose value is not determined until the compiled expression is loaded.
|
||
O or o (the letter O) -- Treats the next number as octal, i.e., reads it in radix 8. For example, |o12 = 10 (decimal).
|
||
B or b -- Treats the next number as binary, i.e., reads it in radix 2. For example, |b101 = 5 (decimal).
|
||
X or x -- Treats the next number as hexadecimal, i.e., reads it in radix 16. The upper-case letters A though F are used as the digits after 9. For example, |x1A = 26 (decimal).
|
||
R or r -- Reads the next number in the radix specified by the (decimal) number that appears between the | and the R. When inputting a number in a radix above ten, the upper-case letters A through Z can be used as the digits after 9 (but there is no digit above Z, so it is not possible to type all base-99 digits). For example, |3r120 reads 120 in radix 3, returning 15.
|
||
(, {, ^ -- Used internally by HPRINT and HREAD (("HPRINT" . Function))to print and read unusual expressions.
|
||
The dispatching characters that are letters can appear in either upper or lower case.
|
||
|