Search Top Index
HELP FORM Allan Ramsay, October 1983 The library program LIB *FORM allows the use of forms, which provide a simple means for defining new syntax words. A form definition consists of a pattern, describing the situation in which the form is to be expanded, and a body which specifies how the expansion is to be done. A form pattern consists of key words and placeholders. A key word is simply a word which is used to punctuate the input text, in the way that THEN breaks up the input stream when it occurs while a conditional expression is being read. Placeholders prescribe the sort of construct which is expected at any given point, and provide a means of referring to that construct when the form is expanded. A form body is simply a skeleton fragment of code. When the pattern for a form is matched, all occurrences of the placeholders are replaced by the code which was read at the appropriate point, and the resulting list of items is spliced into the input stream. To see what is going on, consider the following definition: form repeat impseq:action till expr:test endrepeat; repeat action; if test then quitloop endif; endrepeat; endform; The first line is the pattern. It says that this form should be expanded if the input stream contains the word *REPEAT, followed by an imperative sequence, followed by the word *TILL, followed by an expression, followed by the word *ENDREPEAT. Thus if we now type in repeat list => list.tl -> list till list == nil endrepeat; the imperative sequence LIST => LIST.TL -> LIST will be read and associated with the placeholder ACTION, TILL will be read, the expression LIST == NIL will be read and associated with the placeholder TEST, and ENDREPEAT will be read. So the header of the form has been matched, and its body should be expanded. This is done by splicing in the code associated with the placeholders wherever they appear in the body. So in this case the expansion of the body produces the list [ repeat list => list.tl -> list; if list == nil then quitloop endif; endrepeat; ] This list is appended to the front of the input stream for the system to parse again. The form is again activated, since the first word in the input stream is REPEAT, but this time its pattern is not matched, so the system falls back on its normal meaning for REPEAT and runs the code using that. NOTE that 1) placeholders are specified in the patterns of forms by <category> : <name> At the time the form definition is read, there must already be a function called <category>READ which reads a list of items which make up an object of type <category>, e.g. in the example above we had two placeholders, introduced by IMPSEQ:ACTION and EXPR:TEST. These two would require there to be functions IMPSEQREAD and EXPRREAD, which read and return an imperative sequence and an expression respectively. LIB FORMS contains definitions of EXPRREAD, IMPREAD, IMPSEQREAD and VARREAD - if you want to use any others you will have to define them. The reading functions may return either a list or a single item. If they return a list, it is assumed to be a list of items to be spliced into the input stream. If you have declared a placeholder to be of type "list", you do NOT want the value to be appended to the input stream, as would happen if *LISTREAD were used to read it. The package specifically checks for placeholders which are of type "list", and uses a version of LISTREAD which wraps its result up inside another list to achieve the desired effect. 2) you can define any number of forms with the same name. The package has been defined to deal with variant forms with very little backtracking, so you needn't feel guilty about the amount of work required to deal with them. You can define forms to have the same names as existing syntax words (as in the example). These WILL cause your compilations to slow down, since the new versions will be tried out before the standard ones, and will thus cause cases where you want the standard version to be used to take longer than usual to compile. 3) if you want to use labels and *GOTO s in a form body, or if you want to use variables which are "local" to the form, they should be declared as FORMVARS immediately after the form pattern. Anything which is declared as a FORMVAR is substituted by a new unique identifier every time the form body is expanded. See SHOWLIB *FORM for the code used by LIB FORM. See also HELP *SYNTAX - for an alternative method of defining new syntax words *EXPRSTA - expressions and statements in POP-11 *POP - overview of documentation on POP-11 --- C.all/help/form ---------------------------------------------------- --- Copyright University of Sussex 1987. All rights reserved. ----------