William.Waite@Colorado.edu |
The specification was originally developed in 1995 as a class project at the University of Colorado by J. Amundsen, B. D. Basham, S-C. Chiang, D. A. Ence, R. K. Hill, J. E. Kvamme, O. Lokkebo, H. Ma, R. S. Matthieu, M. T. Rupawalla and W. Wang. It was put into its present form while the author was a Visiting Fellow at Australian National University in 1996. A major rewrite in 2012 simplified the tree structure and updated the tree computations to make use of the Eli type analysis modules.
From this specification module, the Eli system can generate an executable program that checks its input to verify conformance to the rules of ALGOL 60. This specification module can also be combined with other specification modules to define additional analysis of the input program and/or translation of the algorithm embodied in that program to another language.
This specification defines a hardware language that differs from the reference language of the Revised Report in some of the symbols used to represent objects. These differences will be pointed out in the appropriate sections of this document.
We have also restricted the language in two ways: unsigned integers cannot be used as labels, and type specifications must be given for all procedure parameters. The former restriction avoids a known ambiguity, and the latter is necessary for compile-time determination of the types of expressions. Both are common in ALGOL 60 implementations (Randell, B., Russell, L. J. ``ALGOL 60 Implementation'').
One consequence of this quoting strategy is that spaces are not allowed within nonterminal names. In order to preserve the understandability of the nonterminal names used in the Revised Report, we have adopted the convention of running the words together and capitalizing the first letter of every word. Thus we render the Revised Report's nonterminal <simple variable> as SimpleVariable.
The Revised Report uses a combination of BNF and English to describe the complete syntax of the language. Because this is an executable specification, we follow standard compiler practice, using BNF to describe the phrase structure and using a combination of regular expressions and C code to describe the basic symbols and comments.
algol60.con[1]==This macro is attached to a product file.Logical Values[26] Numbers[46] Variables[54] Function Designators[59] Expressions[53] Compound Statements and Blocks[90] Assignment Statements[93] Go To Statements[100] Dummy Statements[103] Conditional Statements[105] For Statements[107] Procedure Statements[111] Declarations[125]
The regular expression defines a sequence of characters that identifies the particular basic symbol or comment in the text. If this character sequence does not constitute the complete basic symbol or comment, then an auxiliary scanner that obtains the complete sequence is specified. Finally, if additional actions are required after the sequence has been recognized, then a token processor is specified to carry out those actions. Auxiliary scanners and token processors for common situations can be found in the Eli library. Routines to handle special situations can be written in C or C++ and provided as part of the specification.
For example, consider an ALGOL 60 string. This basic symbol is identified by the opening string quote `. A single opening string quote does not constitute the complete string, and the nested structure defined in Section 2.6.1 of the Revised Report cannot be described by a regular expression. Therefore we have written a C-coded auxiliary scanner named Algol60String to obtain the complete sequence. After the string has been recognized, an internal representation must be created. The token processor mkidn from the Eli library can be used to carry out that task.
A type-gla file provides the definitions of the basic symbols and comments. Each definition consists of a regular expression and (if necessary) the names of an auxiliary scanner and/or a token processor.
algol60.gla[2]==A type-c file contains the code of the auxiliary scanners and token processors that are written to support the specification.This macro is attached to a product file.Delimiters[28] Unsigned Numbers[45] Identifiers[35] Strings[47] Parameter Delimiter Letter String[60] Code as Procedure Body[156]
algol60.c[3]==All auxiliary scanners obey the following interface specification:This macro is attached to a product file.#include <stdio.h> #include <string.h> #include <ctype.h> #include "err.h" #include "gla.h" #include "source.h" #include "tabsize.h" #include "litcode.h" Comment Scanner[31] Token processors for comment delimiters[29] String Scanner[48]
Define an Auxiliary Scanner[4](¶1)==All token processors obey the following interface specification:This macro is invoked in definitions 31 and 48.char * ¶1(char *start, int length) /* Standard interface for an auxiliary scanner * On entry- * start points to the first character of the scanned string * length=length of the scanned string * On exit- * The function returns a pointer to the first character * beyond the scanned string ***/
Define a token processor[5](¶1)==This macro is invoked in definitions 29 and 34.void ¶1(const char *start, int length, int *syncode, int *intrinsic) /* Token processor "Name" * On entry- * start points to the first character of the sequence being * classified * length=length of the sequence being classified * syncode points to a location containing the initial * classification * intrinsic points to a location to receive the value * On exit- * syncode points to a location containing the final * classification * intrinsic points to a location containing the value (if * relevant) ***/
algol60.map[6]==Our specifications of equivalence classes have replaced the examples of ALGOL 60 code that appear in the Revised Report. Where no equivalence classes are defined, we have inserted an empty section in order to keep the section numbering parallel to that of the Revised Report.This macro is attached to a product file.MAPSYM Equivalences[55]
Relationships among computations are embodied in attributes, which constitute pre- and post-conditions for computations. An attribute may have a value, and that value may be of any type. Types are often defined by external modules that export a set of appropriate operations for use in computation. The pre- and post-conditions may relate computations locally, or remotely along root-to-leaf or depth-first, left-to-right paths.
Eli's attribute grammar notation is LIDO. A LIDO specification consists of a set of symbol and rule computations, with additional definitions of the types of attributes. All computations must be expressed as function application. (Non-strict functions are available for dealing with conditional computation.) Computations may be associated with specific contexts in the tree (rule computations), or with every context in which a particular symbol appears (symbol computations).
algol60.lido[7]==This macro is attached to a product file.Internal representation of an identifier[36] Binding Identifier Uses to their Definitions[8] Scope Violation Rules[37] Semantics[51] Subscripts[57] Type Attributes[52] Establish operator indications for source symbols[73] Identify an operator from its context[14] Balance the operands of a conditional[15] Verify type consistency of a left-part list[97] Verify that an expression can be assigned to a left-part list[98] The for List Elements[110] Actual-Formal Correspondence[116] Restrictions[120] Values of Function Designators[149] Specifications[152] Lower upper bound expressions[137]
Binding Identifier Uses to their Definitions[8]==Identifiers are freely chosen by the programmer and given meaning through specific language constructs. The general strategy is to bind the definition of an identifier and all of its uses to the same definition table key. When processing a construct that gives meaning to an identifier, properties characterizing that meaning are associated with the definition table key to which the definition is bound, and when processing a construct that uses an identifier those properties are accessed.This macro is invoked in definition 7.ATTR Key: DefTableKey;
Eli provides modules for establishing these bindings. Each module implements a specific set of rules governing the binding process, and any number of copies of any of the available modules can be instantiated in a given specification.
Instantiate the ALGOL 60 consistent renaming module[9]==This macro is invoked in definition 19.$/Name/AlgScope.gnrc :inst
Instantiate the type analysis modules[10]==For each operator, three steps are required: an operator indication must be established for the operator's source language symbol, one or more operators must be associated with the indication, and the signatures of those operators must be defined.This macro is invoked in definition 19.$/Type/Typing.gnrc :inst $/Type/Expression.gnrc :inst
Operator indications are established for each operator's source language symbol by computations described in LIDO:
Set a monadic operator indication[11](¶2)==This macro is invoked in definitions 73 and 84.RULE: Uniop ::= '¶1' COMPUTE Uniop.Indic=¶2; END;
Set a dyadic operator indication[12](¶2)==Signatures for the operators are described, and operators associated with indications, by descriptions written in OIL:This macro is invoked in definitions 73, 75, 77, 84, and 86.RULE: Binop ::= '¶1' COMPUTE Binop.Indic=¶2; END;
algol60.oil[13]==OIL describes a set of constraints that the operators and expressions must satisfy. Those constraints must be verified by tree computations that use computational roles exported by the type analysis modules.This macro is attached to a product file.Define operators and associate them with indications[67] Define an operator to be applied when needed[131] Define operators to establish types without values[102]
Identify an operator from its context[14]==The constraint on a conditional expression is that the type of the result must not depend on the (run-time) outcome of the condition:This macro is invoked in definition 7.SYMBOL Expression INHERITS ExpressionSymbol END; SYMBOL Uniop INHERITS OperatorSymbol END; SYMBOL Binop INHERITS OperatorSymbol END; RULE: Expression ::= Uniop Expression COMPUTE MonadicContext(Expression[1],Uniop,Expression[2]); END; RULE: Expression ::= Expression Binop Expression COMPUTE DyadicContext(Expression[1],Binop,Expression[2],Expression[3]); END;
Balance the operands of a conditional[15]==This macro is invoked in definition 7.RULE: Expression ::= IfClause Expression 'else' Expression COMPUTE BalanceContext(Expression[1],Expression[2],Expression[3]); END;
algol60.pdl[16]==The declaration of a property specifies the type of value that property can hold. All C basic types, plus the type DefTableKey (the type of a definition table key) can be used without further specification; any other types must be specified by some type-h file whose name is given in the type-pdl file.This macro is attached to a product file.Property characterizing all quantities[50] Dimension property of an array[135] Properties characterizing function designators[150] Properties characterizing formal parameters[115] Formal parameter key list[147] Property to support Section 5.2.4.2 check[139] Property to support Section 4.7.5.2 check[121]
algol60.h[17]==Because type-h files may be included by several different specifications, they must be protected against multiple inclusion. Eli's convention is to use a symbol consisting of the file name rendered in upper case, with periods replaced by underscores.This macro is attached to a product file.#ifndef ALGOL60_H #define ALGOL60_H Kinds of quantities[49] Parameter identification[118] Monitoring interface[20] #endif
The definitions must be made available to the routines that implement the computations, by including them in a type-head file:
algol60.head[18]==This macro is attached to a product file.#include "algol60.h"
algol60.specs[19]==This macro is attached to a product file.Instantiate the ALGOL 60 consistent renaming module[9] Instantiate modules to pre-define identifiers[65] Instantiate the type analysis modules[10] Instantiate modules to support MultDefChk[38] Instantiate modules for list handling[117] Instantiate additional modules for uniqueness checks[153]
Monitoring interface[20]==In order to print the monitored values, we need some TCL code.This macro is invoked in definition 17.#ifdef MONITOR #define DAPTO_RESULTKindOfQuantity(k) DAPTO_RESULT_INT (k) #define DAPTO_RESULTParameter(k) DAPTO_RESULT_PTR (k) #define DAPTO_ARGParameter(k) DAPTO_ARG_PTR (k, Parameter) #endif
algol60.tcl[21]==KindOfQuantity is an enumerated type, and it is useful to print the identifiers of that type rather than simply the index.This macro is attached to a product file.Print KindOfQuantity values[22] Print Parameter values[23]
Print KindOfQuantity values[22]==A Parameter is a definition table key, so we can use the monitor print routines already available for type DefTableKey.This macro is invoked in definition 21.set n(KindOfQuantity,desc) "Kind of quantity represented" proc n_KindOfQuantity_say {i} { set l {UndefinedIdn VariableIdn ArrayIdn LabelIdn SwitchIdn ProcedureIdn} n_say "KindOfQuantity:[lindex $l $i]" }
Print Parameter values[23]==This macro is invoked in definition 21.set n(Parameter,desc) "Internal parameter name" proc n_Parameter_open {text key} { n_DefTableKey_open $text $key } proc n_Parameter_say {key} { n_DefTableKey_say $key }
Basic symbols are recognized by a finite-state machine, and therefore the definitions of the basic symbols are stated as regular expressions rather than productions of a context-free grammar. This means that all recursive definitions given in the Revised Report must be replaced by the equivalent iterative formulations. We have kept the regular expression notation as close to the form of the context-free grammar as possible to ease verification, except that we have replaced alternations with a more compact representation when describing sets of characters: [a-d] means a|b|c|d and [^;] means ``any character other than semicolon'', for example.
The scanner that recognizes basic symbols attaches source text coordinates (the line number and column number of the first character) to each basic symbol. This requires that the scanner keep track of the coordinates as it is scanning. Coordinate tracking is handled automatically for most basic symbols, but must be provided explicitly for basic symbols that may contain horizontal tab or newline characters. These cases are noted below when they occur.
letter[24]==Letters are used only as components of other basic symbols.This macro is invoked in definition 35.[a-zA-Z]
digit[25]==Digits are used only as components of other basic symbols.This macro is invoked in definitions 35 and 39.[0-9]
Logical Values[26]==The logical values are denoted by keywords of the language.This macro is invoked in definition 1.LogicalValue ::= 'true' / 'false' .
We still want to represent these delimiters as quoted literals in the grammar, but we need to specify that they must be processed specially:
algol60.delit[27]==This specification requires that we recognize each of the delimiters using appropriate scanners, and then use a token processor to set the syncode to Semi, begin, or end. The actual text of each delimiter is specified as usual, except that no symbol is associated with the scan because the symbol will be supplied by the token processor.This macro is attached to a product file.$; Semi $begin begin $end end
Delimiters[28]==(\040 must be used to represent a space within a regular expression because any white space terminates the expression.)This macro is defined in definitions 28 and 30.$;([\040\t\n]*comment[^;]*;)? (coordAdjust) [SemiCmt] $begin([\040\t\n]+comment[^;]*;)? (coordAdjust) [BeginCmt]
This macro is invoked in definition 2.
Token processors for comment delimiters[29]==Both Semi and begin are easy to define with regular expressions because they are self-delimiting. The regular expression accepts horizontal tabs and newlines, and therefore the auxiliary scanner coordAdjust must be used to adjust the coordinates appropriately.This macro is defined in definitions 29 and 34.Define a token processor[5](`SemiCmt') { *syncode = Semi; } Define a token processor[5](`BeginCmt') { *syncode = begin; }
This macro is invoked in definition 3.
Comments following end are much harder to deal with because they can not contain certain strings. It would be possible to write a regular expression that matched strings ending in end or ; or else, and then use an auxiliary scanner to accept everything up to but not including that symbol. The problem is that the scanner would then find the longest such string, and we need the shortest such string.
Thus we need to use an auxiliary scanner to pick up the comment string following an end:
Delimiters[30]==An auxiliary scanner is invoked after the associated regular expression has been accepted. In this case, Algol60Comment will be invoked after the normal scanner has accepted the symbol end.This macro is defined in definitions 28 and 30.$end (Algol60Comment) [EndCmt]
This macro is invoked in definition 2.
The auxiliary scanner is called with a pointer to the first character matched by the regular expression and the length of the string matching the regular expression; it should return a pointer to the first character that does not belong to the basic symbol being recognized. Thus start should point to the e of end, length should be 3, and Algol60Comment should return a pointer to the next end, ; or else.
The regular expression will match the characters e, n and d in that order. Since the scanner finds the longest match, the character following the d cannot be a letter or a digit. If it were, the scanner would combine it with the first three characters in searching for an identifier. The variable p is set to point to the character following the d, so after fetching that character to c and incrementing p the stated loop invariant holds:
Comment Scanner[31]==If c is ;, then the scan should be terminated and the position of the semicolon returned. Otherwise, any necessary adjustment of the coordinates to reflect a tab or newline character must be made.This macro is defined in definitions 31.Define an Auxiliary Scanner[4](`Algol60Comment') { char *p = start + length; char c = *p++; for (;;) { /* Invariant: * c is neither a letter nor a digit && * p points to the first unexamined character * Bound: Number of characters left in the file ***/ if (c == ';') return p - 1; Adjust coordinates if necessary[32](`') if (*p == 'e') { if (strncmp(p, "end", 3) == 0 && !isalnum(p[3]) || strncmp(p, "else", 4) == 0 && !isalnum(p[4])) return p; } while (isalnum(c = *p++)) ; } }
This macro is invoked in definition 3.
The first unexamined character, pointed to by p, could be anything. If it is an e, then the routine checks for the presence of one of the two keywords that can follow the comment. Each of the specified character sequences must be followed by a character other than a letter or digit if it is to be recognized as a keyword. When either of those keywords is found, the routine returns the position of that keyword. (Thus terminating the comment with the character preceding the keyword.)
Finally, the routine re-establishes the invariant of the outer loop.
The generated scanner keeps track of the line and column number of each basic symbol, so that the processor can report errors at the appropriate position in the source program. Tab and newline characters require special action to maintain these values:
Adjust coordinates if necessary[32](¶1)==Character position within a line is the difference between the current character index and the character index StartLine. A tab character occupies one character position, but it may represent a longer sequence, depending upon it's position in the line. This additional white space is taken into account by moving StartLine backwards.This macro is invoked in definitions 31 and 48.if (c == '\t') StartLine -= TABSIZE(p - StartLine); else if (c == '\n') { Refill the source buffer if necessary[33](`¶1') LineNum++; StartLine = p - 1; }
The coordinate adjustment code is needed for processing strings (Section 2.6) as well. These two cases differ in that it is an error for the file to end within a string, but no error if the file ends within a comment. If an end-of-file is an error, code to report that error must be introduced. That code is introduced through the parameter to the coordinate adjustment description.
Source text is stored as a sequence of characters in memory, and the last character of that sequence is guaranteed to be a newline. If the character following a newline is the ASCII NUL character, then there are no more characters in the sequence; otherwise, this newline is not the last newline of the sequence. Thus when the scanner reaches a newline, it must check whether that newline is the last of the sequence in memory:
Refill the source buffer if necessary[33](¶1)==Recall that p points to the character following the newline. If it is the ASCII NUL character, then there are no more characters of the file stored in memory. By calling refillBuf with start as an argument, the scanner extends the character sequence that begins at the location pointed to by start. Because of the way storage is allocated by the source text input module, it may be necessary to move the sequence to another location. Thus TokenStart (the starting location of the basic symbol), start, and p must all be adjusted. Finally, a check is made to see whether the character sequence was, in fact, extended. If it was not, then end-of-file has been reached, the comment string has ended, and the scanner terminates.This macro is invoked in definition 32.if (*p == '\0') { size_t pSave = p - start, sSave = p - StartLine; refillBuf(start); TokenStart = start = TEXTSTART; p = start + pSave; StartLine = start + sSave; if (*p == '\0') { ¶1 return p - 1; } }
Token processors for comment delimiters[34]==This macro is defined in definitions 29 and 34.Define a token processor[5](`EndCmt') { *syncode = end; }
This macro is invoked in definition 3.
Identifiers[35]==This regular expression is equivalent to the definition given in the Revised Report.This macro is invoked in definition 2.Identifier: $letter[24](letter[24]|digit[25])* [mkidn]
Distinct identifiers must be distinguishable from one another. The token processor mkidn assigns a unique integer value to each distinct identifier. This integer value can also be used to access the string representing the identifier, and is stored as the value of the Sym attribute of symbols representing identifier occurrences:
Internal representation of an identifier[36]==Identifiers have no inherent meaning, but serve for the identification of simple variables, arrays, labels, switches, and procedures.This macro is invoked in definition 7.ATTR Sym: int; CLASS SYMBOL IdentOcc COMPUTE SYNT.Sym = TERM; END;
The same identifier cannot be used to denote two different quantities except when these quantities have disjoint scopes as defined by the declarations of the program:
Scope Violation Rules[37]==Unique and CatStrInd are exported by Eli library modules.This macro is defined in definitions 37, 126, and 127.SYMBOL MultDefChk INHERITS Unique COMPUTE IF(NOT(THIS.Unique), message( ERROR, CatStrInd("Identifier is multiply defined: ", THIS.Sym), 0, COORDREF)); END;
This macro is invoked in definition 7.
Instantiate modules to support MultDefChk[38]==This macro is invoked in definition 19.$/Prop/Unique.gnrc :inst $/Tech/Strings.specs
unsigned integer[39]==This regular expression is equivalent to the definition given in the Revised Report.This macro is invoked in definitions 40, 41, 43, and 45.digit[25]+
integer[40]==The + must be escaped because it is a regular expression operator.This macro is invoked in definition 42.(unsigned integer[39]|\+unsigned integer[39]|-unsigned integer[39])
decimal fraction[41]==The . must be escaped because it is a regular expression operator.This macro is invoked in definition 43.\.unsigned integer[39]
Following standard practice, we represent the subscript 10 of the reference language by the letter E:
exponent part[42]==By requiring a decimal number to contain a decimal fraction, we obtain distinct representations for integer and real constants:This macro is invoked in definitions 44 and 45.(E|e)integer[40]
decimal number[43]==We cannot allow an unsigned number consisting of only an exponent part, because there would be no way for the scanner to distinguish it from an identifier (this is a consequence of our representing the subscript 10 of the reference language by the letter E):This macro is invoked in definition 44.(decimal fraction[41]|unsigned integer[39]decimal fraction[41])
unsigned number[44]==We express the distinction between integer and real constants by introducing the new basic symbol UnsignedReal, which does not appear in the Revised Report:This macro is invoked in definition 45.(decimal number[43]|decimal number[43]exponent part[42])
Unsigned Numbers[45]==The token processor mkidn assigns a unique integer value to each distinct numeric denotation. (Note that distinct denotations may represent the same numeric value: 001 has the same value as 1 and 1.23E1 has the same value as 12.3.) This integer value can be used to access the denoting string.This macro is invoked in definition 2.UnsignedInteger: $unsigned integer[39] [mkidn] UnsignedReal: $unsigned number[44]|unsigned integer[39]exponent part[42] [mkidn]
An unsigned integer followed by an exponent part is legal according to the Revised Report. Because of the need to exclude unsigned integer from the definition of decimal number, however, this case has to be treated specially.
Numbers[46]==The symbol number does not appear elsewhere in the Revised Report, so it is not defined here.This macro is invoked in definition 1.UnsignedNumber ::= UnsignedInteger / UnsignedReal .
Strings[47]==Algol60String will be invoked after the normal scanner has accepted the character `.This macro is invoked in definition 2.String: $` (Algol60String) [mkidn]
String Scanner[48]==This macro is invoked in definition 3.Define an Auxiliary Scanner[4](`Algol60String') { char *p = start + length; int counter = 1; /* Invariant: * counter = number of unmatched open quotes * p points to the first unexamined character * Bound: Number of characters left in the file ***/ while (counter) { char c = *p++; Adjust coordinates if necessary[32](`message(ERROR,"End-of-file in string",0,&curpos);') if (c == '\'') counter--; else if (c == '`') counter++; } return p; }
Kinds of quantities[49]==UndefinedIdn is used to distinguish identifiers that are used but not declared. Every declared quantity is represented internally by a definition table key under which the kind is stored as a property:This macro is invoked in definition 17.typedef enum { UndefinedIdn, VariableIdn, ArrayIdn, LabelIdn, SwitchIdn, ProcedureIdn } KindOfQuantity;
Property characterizing all quantities[50]==The kind of quantity may also be stored as an attribute of certain nodes, and a dependence must be used to guarantee that all quantities have their Kind properties set before any are queried:This macro is defined in definitions 50.Kind: KindOfQuantity; "algol60.h"
This macro is invoked in definition 16.
Semantics[51]==This macro is defined in definitions 51, 56, 63, 72, 82, 83, 89, 92, 95, 96, 109, 113, 114, 130, 133, 134, 136, 141, 145, 146, and 148.ATTR kind: KindOfQuantity;
This macro is invoked in definition 7.
The Revised Report does not consider that labels and strings have values, but this position is inconsistent with the fact that labels and strings can be passed as parameters. For uniformity, therefore, we specify operators for labels and strings as well as for integer, real and Boolean values. These specifications result in the values labelType and stringType, which we use to represent the ``types'' of labels and strings.
Some procedures do not yield values, but may have side effects on the state of the computation. Our specifications of the operators characterizing these procedures return a ``value'' of type voidType.
Type Attributes[52]==This macro is invoked in definition 7.ATTR Type: DefTableKey;
Because type information is required to distinguish arithmetic, Boolean and designational expressions, we have merged the grammars for these three kinds of expression. Wherever possible, however, we have retained the nonterminal symbols used in the Revised Report.
The Revised Report distinguishes various classes of identifier: variable identifier, array identifier, switch identifier and procedure identifier. Without information about how an identifier was declared, it is impossible to make this distinction in all contexts. We have therefore replaced some occurrences of the nonterminals variable identifier, array identifier, switch identifier and procedure identifier with the terminal Identifier.
Expressions[53]==This macro is invoked in definition 1.Arithmetic Expressions[70] Boolean Expressions[80] Designational Expressions[88]
Because the phrase structure cannot distinguish different types of expression, we replace <arithmetic expression> here with Expression. Similarly, <array identifier> is replaced with VarIdUse.
Variables[54]==This macro is invoked in definition 1.VarIdUse ::= Identifier . SimpleVariable ::= VarIdUse . SubscriptExpression ::= Expression . SubscriptList ::= SubscriptExpression / SubscriptList ',' SubscriptExpression . SubscriptedVariable ::= VarIdUse '[' SubscriptList ']' . Variable ::= SimpleVariable / SubscriptedVariable .
Equivalences[55]==This macro is defined in definitions 55, 71, 81, 91, 94, 101, 104, 106, 108, 112, and 129.Variable ::= SimpleVariable SubscriptedVariable .
This macro is invoked in definition 6.
VarIdUse denotes an identifier that has a type property declared at its defining occurrence, and therefore it plays the TypedUseId role in the tree computation that verifies types.
Semantics[56]==The Kind property of an identifier is guaranteed to be set if the Type property of that variable is set, hence the dependence in the next-to-last line.This macro is defined in definitions 51, 56, 63, 72, 82, 83, 89, 92, 95, 96, 109, 113, 114, 130, 133, 134, 136, 141, 145, 146, and 148.SYMBOL VarIdUse INHERITS TypedUseId END; SYMBOL Variable COMPUTE SYNT.Sym=CONSTITUENT VarIdUse.Sym SHIELD SubscriptExpression; SYNT.Type=CONSTITUENT VarIdUse.Type SHIELD SubscriptExpression; SYNT.Key=CONSTITUENT VarIdUse.Key SHIELD SubscriptExpression <- THIS.Type; SYNT.kind=GetKind(THIS.Key,UndefinedIdn); END;
This macro is invoked in definition 7.
This means that the identifier must denote an array or a switch, and the number of subscripts must equal the number of dimensions.
Subscripts[57]==Each subscript position acts like a variable of type integer and the evaluation of the subscript is understood to be equivalent to an assignment to this fictitious variable. Thus the subscript expression is considered a RootContext requiring an integer value and allowing all type conversions defined for assignment.This macro is defined in definitions 57 and 58.ATTR dim, sub: int; RULE: Variable ::= VarIdUse '[' SubscriptList ']' COMPUTE .kind=GetKind(VarIdUse.Key,UndefinedIdn) <- VarIdUse.Type; IF(AND(AND(NE(.kind,ArrayIdn),NE(.kind,UndefinedIdn)),NE(.kind,SwitchIdn)), message(ERROR,"Array or switch identifier required",0,COORDREF)); .dim=GetDim(VarIdUse.Key,0) <- VarIdUse.Type; .sub= CONSTITUENTS SubscriptExpression.sub SHIELD SubscriptExpression WITH (int, ADD, IDENTICAL, ZERO); IF(AND(NE(.dim,0),NE(.dim,.sub)), message(ERROR,"Number of indices differs from dimension",0,COORDREF)); END; RULE: SubscriptExpression ::= Expression COMPUTE SubscriptExpression.sub=1; END;
This macro is invoked in definition 7.
Subscripts[58]==This macro is defined in definitions 57 and 58.RULE: SubscriptExpression ::= Expression COMPUTE RootContext(integerType,,Expression); Indication(ColonEqual); END;
This macro is invoked in definition 7.
Function Designators[59]==The complex parameter delimiter must be treated as a basic symbol in order to distinguish the letter string it contains from an identifier:This macro is defined in definitions 59, 61, and 62.ProcIdUse ::= Identifier . ActualParameter ::= String / Expression . ParameterDelimiter ::= ',' / PDLetterString .
This macro is invoked in definition 1.
Parameter Delimiter Letter String[60]==This macro is invoked in definition 2.PDLetterString : $\)[a-zA-Z]+:\(
Function Designators[61]==A FunctionDesignator with an empty ActualParameterPart cannot be distinguished from a Variable in the absence of type information, so we cannot allow an empty ActualParameterPart in this context.This macro is defined in definitions 59, 61, and 62.ActualParameterList ::= ActualParameter / ActualParameterList ParameterDelimiter ActualParameter .
This macro is invoked in definition 1.
Function Designators[62]==This macro is defined in definitions 59, 61, and 62.ActualParameterPart ::= '(' ActualParameterList ')' . FunctionDesignator ::= ProcIdUse ActualParameterPart .
This macro is invoked in definition 1.
Semantics[63]==This macro is defined in definitions 51, 56, 63, 72, 82, 83, 89, 92, 95, 96, 109, 113, 114, 130, 133, 134, 136, 141, 145, 146, and 148.SYMBOL FunctionDesignator INHERITS ExpressionSymbol END; SYMBOL ProcIdUse INHERITS OperatorSymbol COMPUTE SYNT.Indic=THIS.Key <- INCLUDING RootType.GotAllOpers; END; SYMBOL ActualParameterPart INHERITS OpndExprListRoot END; SYMBOL ActualParameter INHERITS OpndExprListElem END; RULE: ActualParameter ::= String COMPUTE PrimaryContext(ActualParameter,stringType); END; RULE: ActualParameter ::= Expression COMPUTE TransferContext(ActualParameter,Expression); END; RULE: FunctionDesignator ::= ProcIdUse ActualParameterPart COMPUTE ListContext(FunctionDesignator,ProcIdUse,ActualParameterPart); END;
This macro is invoked in definition 7.
Standard Functions[64]==PreDefKey is exported by an Eli library module.This macro is invoked in definition 66.PreDefKey("abs", absKey) PreDefKey("sign", signKey) PreDefKey("sqrt", sqrtKey) PreDefKey("sin", sinKey) PreDefKey("cos", cosKey) PreDefKey("arctan",arctanKey) PreDefKey("ln", lnKey) PreDefKey("exp", expKey)
Instantiate modules to pre-define identifiers[65]==The predefinition module requires that the specifications of predefined identifiers be supplied in a file whose name is passed as the referto parameter of the module's instantiation. This file is defined above as the result of the Eli request ALGOL60.fw:fwGen/algol60.d:This macro is invoked in definition 19.$/Name/PreDefine.gnrc +referto=Identifier :inst $/Name/PreDefId.gnrc +referto=(algol60.d) :inst
algol60.d[66]==Eli attaches no particular significance to the d suffix. The file is also marked as a ``non-product'' file, which means that Eli will not attempt to process it further in any event. However, it is included in the collection of files available for reference and is therefore accessible via the referto parameter of the inst derivation.This macro is attached to a non-product file.Standard Functions[64] Transfer Functions[68]
The standard functions are understood to operate indifferently on arguments both of type real and integer. They will all yield values of type real, except for sign(E) which will have values of type integer.
Define operators and associate them with indications[67]==All of these operations are defined to apply to real operands. In Section 5.1.3 we shall show how an integer value can be accepted wherever the context requires a real value.This macro is defined in definitions 67, 69, 74, 76, 78, 79, 85, 87, and 99.OPER absKey(realType): realType; signKey(realType): integerType; sqrtKey, sinKey, cosKey, arctanKey, lnKey, expKey(realType): realType; INDICATION absKey: absKey; signKey: signKey; sqrtKey: sqrtKey; sinKey: sinKey; cosKey: cosKey; arctanKey: arctanKey; lnKey: lnKey; expKey: expKey;
This macro is invoked in definition 13.
Transfer Functions[68]==This macro is invoked in definition 66.PreDefKey("entier",entierKey)
Define operators and associate them with indications[69]==This macro is defined in definitions 67, 69, 74, 76, 78, 79, 85, 87, and 99.OPER entierKey(realType): integerType; INDICATION entierKey: entierKey;
This macro is invoked in definition 13.
Arithmetic Expressions[70]==The Revised Report makes no syntactic distinction between the monadic and dyadic versions of + and -. Because this distinction is important for the semantics of the language, we have made it by using literals for the monadic versions.This macro is defined in definitions 70.AddingOperator ::= '+' / '-' . MultiplyingOperator ::= '*' / '/' / 'div' . Primary ::= UnsignedNumber / Variable / FunctionDesignator / '(' Expression ')' . Factor ::= Primary / Factor '^' Primary . Term ::= Factor / Term MultiplyingOperator Factor . SimpleArithmeticExpression ::= Term / '+' Term / '-' Term / SimpleArithmeticExpression AddingOperator Term .
This macro is invoked in definition 53.
Equivalences[71]==This macro is defined in definitions 55, 71, 81, 91, 94, 101, 104, 106, 108, 112, and 129.Binop ::= AddingOperator MultiplyingOperator . Expression ::= SimpleArithmeticExpression Term Factor Primary UnsignedNumber .
This macro is invoked in definition 6.
Semantics[72]==This macro is defined in definitions 51, 56, 63, 72, 82, 83, 89, 92, 95, 96, 109, 113, 114, 130, 133, 134, 136, 141, 145, 146, and 148.RULE: Expression ::= UnsignedInteger COMPUTE PrimaryContext(Expression,integerType); END; RULE: Expression ::= UnsignedReal COMPUTE PrimaryContext(Expression,realType); END; RULE: Expression ::= Variable COMPUTE PrimaryContext(Expression,Variable.Type); END; RULE: Expression ::= FunctionDesignator COMPUTE TransferContext(Expression, FunctionDesignator); END;
This macro is invoked in definition 7.
The operators +, - and * have the conventional meaning (addition, subtraction and multiplication). The type of the expression will be integer if both of the operands are of integer type, otherwise real:
Establish operator indications for source symbols[73]==This macro is defined in definitions 73, 75, 77, 84, and 86.Set a monadic operator indication[11](`+', `Nop') Set a dyadic operator indication[12](`+', `Plus') Set a monadic operator indication[11](`-', `Neg') Set a dyadic operator indication[12](`-', `Minus') Set a dyadic operator indication[12](`*', `Star')
This macro is invoked in definition 7.
Define operators and associate them with indications[74]==It is unnecessary to provide operators for all combinations of integer and real operands because Section 5.1.3 implies that the compiler is allowed to convert an integer value to a real value in an arithmetic expression wherever the context requires it.This macro is defined in definitions 67, 69, 74, 76, 78, 79, 85, 87, and 99.OPER iNop, iNeg(integerType): integerType; iiAdd, iiSubtract, iiMultiply(integerType, integerType): integerType; rNop, rNeg(realType): realType; rrAdd, rrSubtract, rrMultiply(realType, realType): realType; INDICATION Nop: iNop, rNop; Plus: iiAdd, rrAdd; Neg: iNeg, rNeg; Minus: iiSubtract, rrSubtract; Star: iiMultiply, rrMultiply;
This macro is invoked in definition 13.
The source language operator symbols / and div both denote division, to be understood as a multiplication of the left operand by the reciprocal of the right operand.
/ is defined for all four combinations of types real and integer and will yield results of type real in any case. The operator div is defined only for two operands both of type integer and will yield a result of type integer:
Establish operator indications for source symbols[75]==This macro is defined in definitions 73, 75, 77, 84, and 86.Set a dyadic operator indication[12](`/', `Slash') Set a dyadic operator indication[12](`div', `Div')
This macro is invoked in definition 7.
Define operators and associate them with indications[76]==The source language operator symbols ^ denotes exponentiation:This macro is defined in definitions 67, 69, 74, 76, 78, 79, 85, 87, and 99.OPER rrDiv(realType, realType): realType; iiDiv(integerType, integerType): integerType; INDICATION Slash: rrDiv; Div: iiDiv;
This macro is invoked in definition 13.
Establish operator indications for source symbols[77]==The Report specifies that the result of raising an integer value to an integer power has type integer if the exponent is positive and has type real if the exponent is negative. The fact that the type of the result of an exponentiation depends on the value of one of the operands is a problem, because type is considered to be a static property of the program in this specification. We must therefore define a new type, arithType to handle this situation.This macro is defined in definitions 73, 75, 77, 84, and 86.Set a dyadic operator indication[12](`^', `UpArrow')
This macro is invoked in definition 7.
Define operators and associate them with indications[78]==A value of arithType type would have to be implemented by a structure consisting of either an integer value or a real value and a flag specifying the type of that value. When using a value of arithType type as an operand, a run-time check must be made to determine the actual type and select the appropriate code to carry out the specified operation.This macro is defined in definitions 67, 69, 74, 76, 78, 79, 85, 87, and 99.OPER iiExp(integerType, integerType): arithType; riExp(realType, integerType): realType; rrExp(realType, realType): realType; INDICATION UpArrow: iiExp, riExp, rrExp;
This macro is invoked in definition 13.
Applying a Uniop to a value of arithType type, or applying a Binop to two values of arithType type, will always yield a value of arithType type as a result. In other cases, the result may be guaranteed to be of type real. A value of arithType type can always be converted into a value of type real if the context requires it. If the context requires an integer value, then either a value of arithType type can be converted to an integer or a run-time error can be reported. All of the possibilities are enumerated here:
Define operators and associate them with indications[79]==This macro is defined in definitions 67, 69, 74, 76, 78, 79, 85, 87, and 99.OPER aNop, aNeg(arithType): arithType; aaAdd, aaSubtract, aaMultiply, aaExp(arithType, arithType): arithType; aiAdd, aiSubtract, aiMultiply, aiExp(arithType, integerType): arithType; iaAdd, iaSubtract, iaMultiply, iaExp(integerType, arithType): arithType; arAdd, arSubtract, arMultiply, arExp(arithType, realType): realType; raAdd, raSubtract, raMultiply, raExp(realType, arithType): realType; INDICATION Nop: aNop; Plus: aaAdd, aiAdd, iaAdd, arAdd, raAdd; Neg: aNeg; Minus: aaSubtract, aiSubtract, iaSubtract, arSubtract, raSubtract; Star: aaMultiply, aiMultiply, iaMultiply, arMultiply, raMultiply; UpArrow: aaExp, aiExp, iaExp, arExp, raExp; COERCION aiConvert(arithType): integerType; arConvert(arithType): realType;
This macro is invoked in definition 13.
We used obvious representations for the operators that are not available as ASCII characters:
Boolean Expressions[80]==This macro is invoked in definition 53.Primary ::= LogicalValue . RelationalOperator ::= '<' / '<=' / '=' / '>=' / '>' / '!=' . Relation ::= SimpleArithmeticExpression RelationalOperator SimpleArithmeticExpression . BooleanPrimary ::= SimpleArithmeticExpression / Relation . BooleanSecondary ::= BooleanPrimary / 'not' BooleanPrimary . BooleanFactor ::= BooleanSecondary / BooleanFactor 'and' BooleanSecondary . BooleanTerm ::= BooleanFactor / BooleanTerm 'or' BooleanFactor . Implication ::= BooleanTerm / Implication '->' BooleanTerm . SimpleBoolean ::= Implication / SimpleBoolean '==' Implication . IfClause ::= 'if' Expression 'then' . Expression ::= SimpleBoolean / IfClause SimpleBoolean 'else' Expression .
Equivalences[81]==This macro is defined in definitions 55, 71, 81, 91, 94, 101, 104, 106, 108, 112, and 129.Binop ::= RelationalOperator . Expression ::= SimpleBoolean Implication BooleanTerm BooleanFactor BooleanSecondary BooleanPrimary Relation LogicalValue.
This macro is invoked in definition 6.
Semantics[82]==This macro is defined in definitions 51, 56, 63, 72, 82, 83, 89, 92, 95, 96, 109, 113, 114, 130, 133, 134, 136, 141, 145, 146, and 148.RULE: Expression ::= 'true' COMPUTE PrimaryContext(Expression,BooleanType); END; RULE: Expression ::= 'false' COMPUTE PrimaryContext(Expression,BooleanType); END;
This macro is invoked in definition 7.
The Expression in an IfClause must yield a Boolean value.
Semantics[83]==This macro is defined in definitions 51, 56, 63, 72, 82, 83, 89, 92, 95, 96, 109, 113, 114, 130, 133, 134, 136, 141, 145, 146, and 148.RULE: IfClause ::= 'if' Expression 'then' COMPUTE Expression.Required=BooleanType; END;
This macro is invoked in definition 7.
Establish operator indications for source symbols[84]==This macro is defined in definitions 73, 75, 77, 84, and 86.Set a monadic operator indication[11](`not', `Not') Set a dyadic operator indication[12](`<', `Lt') Set a dyadic operator indication[12](`<=', `Le') Set a dyadic operator indication[12](`=', `Eq') Set a dyadic operator indication[12](`!=', `Ne') Set a dyadic operator indication[12](`>=', `Ge') Set a dyadic operator indication[12](`>', `Gt')
This macro is invoked in definition 7.
Define operators and associate them with indications[85]==The logical operators always take values of type Boolean as operands and yield values of type Boolean as results.This macro is defined in definitions 67, 69, 74, 76, 78, 79, 85, 87, and 99.OPER iiLT, iiLE, iiEQ, iiGE, iiGT, iiNE(integerType, integerType): BooleanType; rrLT, rrLE, rrEQ, rrGE, rrGT, rrNE(realType, realType): BooleanType; INDICATION Lt: iiLT, rrLT; Le: iiLE, rrLE; Eq: iiEQ, rrEQ; Ge: iiGE, rrGE; Gt: iiGT, rrGT; Ne: iiNE, rrNE;
This macro is invoked in definition 13.
Establish operator indications for source symbols[86]==This macro is defined in definitions 73, 75, 77, 84, and 86.Set a dyadic operator indication[12](`and', `And') Set a dyadic operator indication[12](`or', `Or') Set a dyadic operator indication[12](`->', `Implies') Set a dyadic operator indication[12](`==', `Equiv')
This macro is invoked in definition 7.
Define operators and associate them with indications[87]==This macro is defined in definitions 67, 69, 74, 76, 78, 79, 85, 87, and 99.OPER bNot(BooleanType): BooleanType; bAnd, bOr, bImplies, bEquiv(BooleanType, BooleanType): BooleanType; INDICATION Not: bNot; And: bAnd; Or: bOr; Implies: bImplies; Equiv: bEquiv;
This macro is invoked in definition 13.
Designational Expressions[88]==Designational expressions do not appear in the syntax here because their phrase structure is already covered by other forms of expression, and they cannot be distinguished without type information.This macro is invoked in definition 53.Label ::= Identifier .
Semantics[89]==This macro is defined in definitions 51, 56, 63, 72, 82, 83, 89, 92, 95, 96, 109, 113, 114, 130, 133, 134, 136, 141, 145, 146, and 148.RULE: DesignationalExpression ::= Expression COMPUTE Expression.Required=labelType; END;
This macro is invoked in definition 7.
Compound Statements and Blocks[90]==This macro is invoked in definition 1.UnlabelledBasicStatement ::= AssignmentStatement / GoToStatement / DummyStatement / ProcedureStatement . BasicStatement ::= UnlabelledBasicStatement / Label ':' BasicStatement. UnconditionalStatement ::= BasicStatement / CompoundStatement / Block . Statement ::= UnconditionalStatement / ConditionalStatement / ForStatement . CompoundTail ::= Statement 'end' / Statement ';' CompoundTail . BlockHead ::= 'begin' Declaration / BlockHead ';' Declaration . UnlabelledCompound ::= 'begin' CompoundTail . UnlabelledBlock ::= BlockHead ';' CompoundTail . CompoundStatement ::= UnlabelledCompound / Label ':' CompoundStatement . Block ::= UnlabelledBlock / Label ':' Block . Program ::= Block / CompoundStatement .
Equivalences[91]==This macro is defined in definitions 55, 71, 81, 91, 94, 101, 104, 106, 108, 112, and 129.Statement ::= UnlabelledBasicStatement BasicStatement UnlabelledCompound CompoundStatement UnconditionalStatement .
This macro is invoked in definition 6.
Semantics[92]==This macro is defined in definitions 51, 56, 63, 72, 82, 83, 89, 92, 95, 96, 109, 113, 114, 130, 133, 134, 136, 141, 145, 146, and 148.SYMBOL UnlabelledBlock INHERITS RangeScope END;
This macro is invoked in definition 7.
Assignment Statements[93]==This macro is invoked in definition 1.LeftPart ::= Variable ':=' . LeftPartList ::= LeftPart / LeftPartList LeftPart . AssignmentStatement ::= LeftPartList Expression .
Equivalences[94]==This macro is defined in definitions 55, 71, 81, 91, 94, 101, 104, 106, 108, 112, and 129.Statement ::= AssignmentStatement .
This macro is invoked in definition 6.
Semantics[95]==Assignments to a procedure identifier may only occur within the body of a procedure defining the value of a function designator. This is checked by defining an InBody property for each procedure identifier. InBody has the value 0 outside of the procedure body and a nonzero value within the body. The inBody chain is used to control the value of InBody.This macro is defined in definitions 51, 56, 63, 72, 82, 83, 89, 92, 95, 96, 109, 113, 114, 130, 133, 134, 136, 141, 145, 146, and 148.RULE: LeftPart ::= Variable ':=' COMPUTE IF(AND(AND(AND( NE(Variable.kind,VariableIdn), NE(Variable.kind,ArrayIdn)), NE(Variable.kind,ProcedureIdn)), NE(Variable.kind,UndefinedIdn)), message(ERROR,"Illegal target of assignment :=",0,COORDREF)); END;
This macro is invoked in definition 7.
Semantics[96]==This macro is defined in definitions 51, 56, 63, 72, 82, 83, 89, 92, 95, 96, 109, 113, 114, 130, 133, 134, 136, 141, 145, 146, and 148.RULE: LeftPart ::= Variable ':=' COMPUTE IF(AND( EQ(Variable.kind,ProcedureIdn), EQ(GetInBody(Variable.Key,0),0)<-LeftPart.inBody), message( ERROR, CatStrInd( "Assignment must be within the body of procedure ", Variable.Sym), 0, COORDREF)); END;
This macro is invoked in definition 7.
Verify type consistency of a left-part list[97]==If this type is Boolean, the expression must likewise be Boolean. If the type is real or integer, the expression must be arithmetic. If the type of the arithmetic expression differs from that associated with the variables and procedure identifiers, appropriate transfer functions are understood to be automatically invoked.This macro is invoked in definition 7.RULE: LeftPartList ::= LeftPart COMPUTE LeftPartList.Type=LeftPart.Type; END; RULE: LeftPartList ::= LeftPartList LeftPart COMPUTE LeftPartList[1].Type=LeftPart.Type; IF(NE(LeftPartList[2].Type,LeftPart.Type), message(ERROR,"Type does not agree with previous variable",0,COORDREF)); END; RULE: LeftPart ::= Variable ':=' COMPUTE LeftPart.Type=Variable.Type; END;
Verify that an expression can be assigned to a left-part list[98]==For transfer from real to integer type, the transfer function is understood to yield a result equivalent to entier(E+0.5) where E is the value of the expression.This macro is invoked in definition 7.RULE: Statement ::= LeftPartList Expression COMPUTE RootContext(LeftPartList.Type,,Expression); Indication(ColonEqual); END;
Define operators and associate them with indications[99]==This macro is defined in definitions 67, 69, 74, 76, 78, 79, 85, 87, and 99.OPER riRound(realType): integerType; INDICATION ColonEqual: riRound;
This macro is invoked in definition 13.
Go To Statements[100]==This macro is invoked in definition 1.GoToStatement ::= 'go' 'to' DesignationalExpression .
Equivalences[101]==This macro is defined in definitions 55, 71, 81, 91, 94, 101, 104, 106, 108, 112, and 129.Statement ::= GoToStatement .
This macro is invoked in definition 6.
The jump operator is never used. It serves merely to establish the labelType.
Define operators to establish types without values[102]==This macro is defined in definitions 102 and 119.OPER jump(labelType):voidType;
This macro is invoked in definition 13.
Dummy Statements[103]==This macro is invoked in definition 1.DummyStatement ::= /*Empty*/ .
Equivalences[104]==This macro is defined in definitions 55, 71, 81, 91, 94, 101, 104, 106, 108, 112, and 129.Statement ::= DummyStatement .
This macro is invoked in definition 6.
Conditional Statements[105]==This macro is invoked in definition 1.IfStatement ::= IfClause UnconditionalStatement . ConditionalStatement ::= IfStatement / IfStatement 'else' Statement / IfClause ForStatement / Label ':' ConditionalStatement .
Equivalences[106]==This macro is defined in definitions 55, 71, 81, 91, 94, 101, 104, 106, 108, 112, and 129.Statement ::= ConditionalStatement IfStatement .
This macro is invoked in definition 6.
For Statements[107]==This macro is invoked in definition 1.ArithmeticExpression ::= Expression . BooleanExpression ::= Expression . ForListElement ::= ArithmeticExpression / ArithmeticExpression 'step' ArithmeticExpression 'until' ArithmeticExpression / ArithmeticExpression 'while' BooleanExpression . ForList ::= ForListElement / ForList ',' ForListElement . ForClause ::= 'for' Variable ':=' ForList 'do' . ForStatement ::= ForClause Statement / Label ':' ForStatement .
Equivalences[108]==This macro is defined in definitions 55, 71, 81, 91, 94, 101, 104, 106, 108, 112, and 129.Statement ::= ForStatement .
This macro is invoked in definition 6.
Semantics[109]==This macro is defined in definitions 51, 56, 63, 72, 82, 83, 89, 92, 95, 96, 109, 113, 114, 130, 133, 134, 136, 141, 145, 146, and 148.RULE: ForClause ::= 'for' Variable ':=' ForList 'do' COMPUTE ForClause.Type=Variable.Type; IF(AND( NE(Variable.Type,integerType), NE(Variable.Type,realType)), message(ERROR,"Controlled variable must be arithmetic",0,COORDREF)); END;
This macro is invoked in definition 7.
The for List Elements[110]==This macro is invoked in definition 7.RULE: ArithmeticExpression ::= Expression COMPUTE RootContext(INCLUDING ForClause.Type,,Expression); Indication(ColonEqual); END; RULE: BooleanExpression ::= Expression COMPUTE Expression.Required=BooleanType; END;
The nonterminal NoArgs is used to represent an empty argument list.
Procedure Statements[111]==This macro is invoked in definition 1.ProcedureStatement ::= ProcIdUse NoArgs / ProcIdUse ActualParameterPart . NoArgs ::= .
Equivalences[112]==This macro is defined in definitions 55, 71, 81, 91, 94, 101, 104, 106, 108, 112, and 129.ActualParameterPart ::= NoArgs .
This macro is invoked in definition 6.
Semantics[113]==All formal parameters quoted in the value part of the procedure declaration heading are assigned the values of the corresponding actual parameters, these assignments being considered as being performed explicitly before entering the procedure body. The effect is as though an additional block embracing the procedure body were created with the formal parameters declared as variables local to this fictitious block.This macro is defined in definitions 51, 56, 63, 72, 82, 83, 89, 92, 95, 96, 109, 113, 114, 130, 133, 134, 136, 141, 145, 146, and 148.SYMBOL ProcedureStatement INHERITS ExpressionSymbol COMPUTE INH.Required=voidType; END;
This macro is invoked in definition 7.
Semantics[114]==This macro is defined in definitions 51, 56, 63, 72, 82, 83, 89, 92, 95, 96, 109, 113, 114, 130, 133, 134, 136, 141, 145, 146, and 148.SYMBOL ValueParameter COMPUTE SYNT.GotValue=ResetIsValue(THIS.Key, 1); END;
This macro is invoked in definition 7.
Properties characterizing formal parameters[115]==This macro is invoked in definition 16.IsValue: int;
Actual-Formal Correspondence[116]==This macro is defined in definitions 116.SYMBOL ActualParameterPart INHERITS ParameterDeListRoot END; SYMBOL ActualParameter INHERITS ParameterDeListElem END; RULE: FunctionDesignator ::= ProcIdUse ActualParameterPart COMPUTE ActualParameterPart.ParameterList= GetFormals(ProcIdUse.Key,NULLParameterList) <- INCLUDING RootType.GotAllOpers; END; RULE: ProcedureStatement ::= ProcIdUse ActualParameterPart COMPUTE ActualParameterPart.ParameterList= GetFormals(ProcIdUse.Key,NULLParameterList) <- INCLUDING RootType.GotAllOpers; END;
This macro is invoked in definition 7.
Instantiate modules for list handling[117]==A parameter in this list is really a definition table key, although we could make it a more complex value if necessary.This macro is invoked in definition 19.$/Adt/LidoList.gnrc +instance=Parameter +referto=algol60 :inst
Parameter identification[118]==The actual verification that the procedure is called with the right number of arguments of the correct type is carried out during type analysis.This macro is invoked in definition 17.#include "deftbl.h" #define NoParameter NoKey typedef DefTableKey Parameter;
Define operators to establish types without values[119]==A formal parameter which occurs as a left part variable in an assignment statement within the procedure body and which is not called by value can only correspond to an actual parameter which is a variable.This macro is defined in definitions 102 and 119.OPER pass(stringType):voidType;
This macro is invoked in definition 13.
Restrictions[120]==This macro is defined in definitions 120, 122, 123, and 124.ATTR IsAssigned, IsVariable: int; SYMBOL Variable COMPUTE INH.IsAssigned=0; END; RULE: LeftPart ::= Variable ':=' COMPUTE Variable.IsAssigned=1; END; SYMBOL Expression COMPUTE SYNT.IsVariable=0; END; RULE: Expression ::= Variable COMPUTE Expression.IsVariable=1; END; SYMBOL VarIdUse COMPUTE SYNT.GotAssign=ResetIsAssigned(THIS.Key,INCLUDING Variable.IsAssigned); END; SYMBOL ROOTCLASS COMPUTE SYNT.GotProperties=CONSTITUENTS (VarIdUse.GotAssign,ValueParameter.GotValue); END; RULE: ActualParameter ::= Expression COMPUTE IF(AND(AND( GetIsAssigned(ActualParameter.ParameterElem,0), NOT(GetIsValue(ActualParameter.ParameterElem,0))), NOT(Expression.IsVariable)), message(ERROR,"Argument must be a variable",0,COORDREF)) <- INCLUDING (ROOTCLASS.GotProperties); END;
This macro is invoked in definition 7.
Property to support Section 4.7.5.2 check[121]==A formal parameter which is used within the procedure body as an array identifier can only correspond to an actual parameter which is an array.This macro is invoked in definition 16.IsAssigned: int;
Restrictions[122]==A formal parameter which is called by value cannot in general correspond to a switch identifier or a string, because these do not possess values.This macro is defined in definitions 120, 122, 123, and 124.SYMBOL Expression COMPUTE SYNT.kind=UndefinedIdn; END; RULE: Expression ::= Variable COMPUTE Expression.kind=Variable.kind; END; RULE: ActualParameter ::= Expression COMPUTE IF(AND( EQ(GetKind(ActualParameter.ParameterElem,UndefinedIdn),ArrayIdn), NE(Expression.kind,ArrayIdn)), message(ERROR,"Argument must be an array",0,COORDREF)); END;
This macro is invoked in definition 7.
Restrictions[123]==All formal parameters have restrictions on the type of the corresponding actual parameter. (This is a change from the Revised Report, discussed in Section 1.)This macro is defined in definitions 120, 122, 123, and 124.SYMBOL ValueParameter INHERITS TypedUseId COMPUTE IF(EQ(GetKind(THIS.Key,UndefinedIdn),SwitchIdn) <- THIS.Type, message( ERROR, CatStrInd("Value parameter cannot be a switch identifier: ",THIS.Sym), 0, COORDREF)); IF(EQ(THIS.Type,stringType), message( ERROR, CatStrInd("Value parameter cannot be a string: ",THIS.Sym), 0, COORDREF)); END;
This macro is invoked in definition 7.
Restrictions[124]==This macro is defined in definitions 120, 122, 123, and 124.RULE: ProcedureStatement ::= ProcIdUse ActualParameterPart COMPUTE ListContext(ProcedureStatement,ProcIdUse,ActualParameterPart); END;
This macro is invoked in definition 7.
Declarations[125]==Dynamically this implies the following: at the time of an entry to the block (through the begin, since the labels inside are local and therefore inaccessible from outside) all identifiers declared for the block assume the significance implied by the nature of the declarations given. If these identifiers had already been defined by other declarations outside they are for the time being given a new significance. Identifiers which are not declared for the block, on the other hand, retain their old meaning.This macro is invoked in definition 1.Declaration ::= TypeDeclaration / ArrayDeclaration / SwitchDeclaration / ProcedureDeclaration . Type Declarations[128] Array Declarations[132] Switch Declarations[140] Procedure Declarations[142]
At the time of an exit from the block (through end or by a go to statement) all identifiers which are declared for the block lose their local significance.
Eli captures this behavior in the IdUseEnv computational role of the name analysis module. The ChkIdUse computational role emits an error report if the identifier has not been declared.
Scope Violation Rules[126]==Labels are implicitly declared by their appearance preceding a colon. All other identifiers of a program must be explicitly declared. No identifier may be declared more than once in any block head.This macro is defined in definitions 37, 126, and 127.SYMBOL VarIdUse INHERITS IdentOcc, IdUseEnv, ChkIdUse END; SYMBOL ProcIdUse INHERITS IdentOcc, IdUseEnv, ChkIdUse END;
This macro is invoked in definition 7.
The IdDefScope computational role of the name analysis module provides for identifier declaration. MultDefChk was defined in Section 2.4 to report any identifier that is defined more than once in a block head.
Scope Violation Rules[127]==This macro is defined in definitions 37, 126, and 127.SYMBOL VarIdDef INHERITS IdentOcc, IdDefScope, MultDefChk END; SYMBOL ArrayIdentifier INHERITS IdentOcc, IdDefScope, MultDefChk END; SYMBOL ProcedureIdentifier INHERITS IdentOcc, IdDefScope, MultDefChk END; SYMBOL Label INHERITS IdentOcc, IdDefScope, MultDefChk END; SYMBOL SwitchIdentifier INHERITS IdentOcc, IdDefScope, MultDefChk END;
This macro is invoked in definition 7.
Type Declarations[128]==This macro is invoked in definition 125.VarIdDef ::= Identifier . TypeList ::= VarIdDef / VarIdDef ',' TypeList . Type ::= 'real' / 'integer' / 'Boolean' . LocalOrOwnType ::= Type / 'own' Type . TypeDeclaration ::= LocalOrOwnType TypeList .
Equivalences[129]==This macro is defined in definitions 55, 71, 81, 91, 94, 101, 104, 106, 108, 112, and 129.Type ::= LocalOrOwnType .
This macro is invoked in definition 6.
The Type attribute of the symbol playing the TypedDefinition role must be set by a user computation to the definition table key of the type. No other user computations are needed.
Semantics[130]==In arithmetic expressions any position which can be occupied by a real declared variable may be occupied by an integer declared variable.This macro is defined in definitions 51, 56, 63, 72, 82, 83, 89, 92, 95, 96, 109, 113, 114, 130, 133, 134, 136, 141, 145, 146, and 148.SYMBOL TypeDeclaration INHERITS TypedDefinition END; SYMBOL VarIdDef INHERITS TypedDefId COMPUTE INH.GotProp=ResetKind(THIS.Key,VariableIdn); END; RULE: Type ::= 'real' COMPUTE Type.Type=realType; END; RULE: Type ::= 'integer' COMPUTE Type.Type=integerType; END; RULE: Type ::= 'Boolean' COMPUTE Type.Type=BooleanType; END; RULE: TypeDeclaration ::= Type TypeList COMPUTE TypeDeclaration.Type=Type.Type; END;
This macro is invoked in definition 7.
Define an operator to be applied when needed[131]==This macro is defined in definitions 131.COERCION irConvert(integerType): realType;
This macro is invoked in definition 13.
Array Declarations[132]==This macro is invoked in definition 125.LowerBound ::= Expression . UpperBound ::= Expression . BoundPair ::= LowerBound ':' UpperBound . BoundPairList ::= BoundPair / BoundPairList ',' BoundPair . ArrayIdentifier ::= Identifier . ArraySegment ::= ArrayIdentifier '[' BoundPairList ']' / ArrayIdentifier ',' ArraySegment . ArrayList ::= ArraySegment / ArrayList ',' ArraySegment . ArrayDeclaration ::= 'array' ArrayList / LocalOrOwnType 'array' ArrayList .
All arrays declared in one declaration are of the same quoted type. If not type declarator is given the type real is understood.
The Eli Typing module's TypedDefinition role is played by the ArrayDeclaration, the symbol that represents a definition of one or more subscripted variables. Each of those variables plays the TypedDefId role.
Semantics[133]==The dimensions are given as the number of entries in the bound pair list.This macro is defined in definitions 51, 56, 63, 72, 82, 83, 89, 92, 95, 96, 109, 113, 114, 130, 133, 134, 136, 141, 145, 146, and 148.SYMBOL ArrayDeclaration INHERITS TypedDefinition END; SYMBOL ArrayIdentifier INHERITS TypedDefId END; RULE: ArrayDeclaration ::= Type 'array' ArrayList COMPUTE ArrayDeclaration.Type=Type.Type; END; RULE: ArrayDeclaration ::= 'array' ArrayList COMPUTE ArrayDeclaration.Type=realType; END;
This macro is invoked in definition 7.
Semantics[134]==The declared dimensions are stored as the value of the Dim property of the ArrayIdentifier.This macro is defined in definitions 51, 56, 63, 72, 82, 83, 89, 92, 95, 96, 109, 113, 114, 130, 133, 134, 136, 141, 145, 146, and 148.SYMBOL BoundPair COMPUTE SYNT.dim=1; END; RULE: ArraySegment ::= ArrayIdentifier '[' BoundPairList ']' COMPUTE ArraySegment.dim= CONSTITUENTS BoundPair.dim WITH (int, ADD, IDENTICAL, ZERO); ArrayIdentifier.dim=ArraySegment.dim; END; RULE: ArraySegment ::= ArrayIdentifier ',' ArraySegment COMPUTE ArraySegment[1].dim=ArraySegment[2].dim; ArrayIdentifier.dim=ArraySegment[2].dim; END;
This macro is invoked in definition 7.
Dimension property of an array[135]==The Dim and Kind properties of the variable must be available whenever the type is available, which is guaranteed by making ArrayIdentifier.GotProp dependent upon setting them.This macro is invoked in definition 16.Dim: int;
Semantics[136]==This macro is defined in definitions 51, 56, 63, 72, 82, 83, 89, 92, 95, 96, 109, 113, 114, 130, 133, 134, 136, 141, 145, 146, and 148.SYMBOL ArrayIdentifier COMPUTE INH.GotProp= ORDER( ResetDim(THIS.Key,THIS.dim), ResetKind(THIS.Key,ArrayIdn)); END;
This macro is invoked in definition 7.
Lower upper bound expressions[137]==Bound expressions can only depend on variables and procedures which are nonlocal to the block for which the array declaration is valid.This macro is defined in definitions 137 and 138.RULE: LowerBound ::= Expression COMPUTE RootContext(integerType,,Expression); Indication(ColonEqual); END; RULE: UpperBound ::= Expression COMPUTE RootContext(integerType,,Expression); Indication(ColonEqual); END;
This macro is invoked in definition 7.
Lower upper bound expressions[138]==This macro is defined in definitions 137 and 138.ATTR InBoundExpr: int; SYMBOL ROOTCLASS COMPUTE SYNT.InBoundExpr=0; END; SYMBOL BoundPair COMPUTE SYNT.InBoundExpr=1; END; SYMBOL AnyScope COMPUTE SYNT.Key=NewKey(); END; SYMBOL Quantity COMPUTE SYNT.GotBlk=ResetBlock(THIS.Key,INCLUDING AnyScope.Key); END; SYMBOL VarIdDef INHERITS Quantity END; SYMBOL ArrayIdentifier INHERITS Quantity END; SYMBOL ProcedureIdentifier INHERITS Quantity END; SYMBOL ROOTCLASS COMPUTE SYNT.GotBlks=CONSTITUENTS Quantity.GotBlk; END; SYMBOL VarIdUse COMPUTE IF(AND(AND( NE(GetKind(THIS.Key,UndefinedIdn),UndefinedIdn), INCLUDING (ROOTCLASS.InBoundExpr, BoundPair.InBoundExpr)), EQ(GetBlock(THIS.Key,NoKey),INCLUDING AnyScope.Key)), message( ERROR, CatStrInd("Local quantity in a bound expression: ",THIS.Sym), 0, COORDREF)); END;
This macro is invoked in definition 7.
Property to support Section 5.2.4.2 check[139]==This macro is invoked in definition 16.Block: DefTableKey;
Switch Declarations[140]==This macro is invoked in definition 125.SwitchList ::= DesignationalExpression / SwitchList ',' DesignationalExpression . SwitchIdentifier ::= Identifier . SwitchDeclaration ::= 'switch' SwitchIdentifier ':=' SwitchList .
Semantics[141]==This macro is defined in definitions 51, 56, 63, 72, 82, 83, 89, 92, 95, 96, 109, 113, 114, 130, 133, 134, 136, 141, 145, 146, and 148.SYMBOL SwitchDeclaration INHERITS TypedDefinition COMPUTE SYNT.Type=labelType; END; SYMBOL SwitchIdentifier INHERITS TypedDefId COMPUTE INH.GotProp= ORDER( ResetKind(THIS.Key,SwitchIdn), ResetDim(THIS.Key,1)); END;
This macro is invoked in definition 7.
Procedure Declarations[142]==The syntax of SpecificationPart in the report is ambiguous. Also, we need to distinguish the role played by the identifiers in the specification part: they constitute the type definitions of the formal parameters.This macro is defined in definitions 142, 143, and 144.FormalParameter ::= Identifier . FormalParameterList ::= FormalParameter / FormalParameterList ParameterDelimiter FormalParameter . FormalParameterPart ::= / '(' FormalParameterList ')' . IdentifierList ::= ValueParameter / IdentifierList ',' ValueParameter . ValueParameter ::= Identifier . ValuePart ::= 'value' IdentifierList ';' / /*Empty*/ .
This macro is invoked in definition 125.
Procedure Declarations[143]==The grammar given in the Revised Report does not reflect the scope rules of the language: A procedure identifier is declared in the enclosing scope, and the formal parameters are declared in the procedure body, but the grammar places both in the <procedure heading> phrase. We have therefore moved the procedure identifier to the procedure declaration and defined a new nonterminal, ProcedureRange, that is exactly the scope of the formal parameters described by Section 5.4.3 of the Revised Report:This macro is defined in definitions 142, 143, and 144.Specifier ::= 'string' / Type / 'array' / Type 'array' / 'label' / 'switch' / 'procedure' / Type 'procedure' . SpecificationPart ::= FormalSpecification* . FormalSpecification ::= Specifier FormalIdList ';' . FormalIdList ::= FormalParamIdTypeDef / FormalIdList ',' FormalParamIdTypeDef . FormalParamIdTypeDef ::= Identifier .
This macro is invoked in definition 125.
Procedure Declarations[144]==This macro is defined in definitions 142, 143, and 144.ProcedureIdentifier ::= Identifier . ProcedureHeading ::= FormalParameterPart ';' ValuePart SpecificationPart . ProcedureBody ::= Statement / Code . ProcedureRange ::= ProcedureHeading ProcedureBody . ProcedureDeclaration ::= 'procedure' ProcedureIdentifier ProcedureRange / Type 'procedure' ProcedureIdentifier ProcedureRange .
This macro is invoked in definition 125.
Semantics[145]==We need to distinguish three roles that may be played in the heading by those identifiers.This macro is defined in definitions 51, 56, 63, 72, 82, 83, 89, 92, 95, 96, 109, 113, 114, 130, 133, 134, 136, 141, 145, 146, and 148.SYMBOL ProcedureRange INHERITS RangeScope END;
This macro is invoked in definition 7.
The FormalParamIdTypeDef is the defining occurrence of the formal parameter's identifier. As discussed earlier, we require that each formal parameter be given a type in order to be able to determine the type of any expression.
A FormalParameter is an applied occurrence in the FormalParameterPart. It is used to determine the type of argument that will appear in a specific position in the argument list of a call.
Finally, the ValueParameter is an applied occurrence in the value list. It allows the analyzer to set the value property of the corresponding formal parameter.
Semantics[146]==Formal parameters will, whenever the procedure is activated, be assigned the values of or be replaced by actual parameters. Thus the procedure plays the role of an operator with an operand list. We also need the definition table keys of the formal parameters in order to verify restrictions in Section 4.7.5.This macro is defined in definitions 51, 56, 63, 72, 82, 83, 89, 92, 95, 96, 109, 113, 114, 130, 133, 134, 136, 141, 145, 146, and 148.SYMBOL FormalParamIdTypeDef INHERITS IdentOcc, IdDefScope, MultDefChk END; SYMBOL FormalParameter INHERITS IdentOcc, IdUseScope, ChkIdUse END; SYMBOL ValueParameter INHERITS IdentOcc, IdUseScope, ChkIdUse END;
This macro is invoked in definition 7.
Formal parameter key list[147]==This macro is invoked in definition 16.Formals: ParameterList; "ParameterList.h"
Semantics[148]==This macro is defined in definitions 51, 56, 63, 72, 82, 83, 89, 92, 95, 96, 109, 113, 114, 130, 133, 134, 136, 141, 145, 146, and 148.SYMBOL ProcedureDeclaration INHERITS OperatorDefs END; SYMBOL FormalParameterPart INHERITS OpndTypeListRoot, ParameterListRoot END; SYMBOL FormalParameter INHERITS OpndTypeListElem, TypedUseId, ParameterListElem COMPUTE SYNT.ParameterElem=THIS.Key; END; RULE: ProcedureDeclaration ::= 'procedure' ProcedureIdentifier ProcedureRange COMPUTE ProcedureDeclaration.GotOper= ListOperator( ProcedureIdentifier.Key, NoOprName, CONSTITUENT FormalParameterPart.OpndTypeList, voidType); ProcedureIdentifier.GotProp= ORDER( ResetKind(ProcedureIdentifier.Key,ProcedureIdn), ResetFormals( ProcedureIdentifier.Key, CONSTITUENT FormalParameterPart.ParameterList)); END; RULE: ProcedureDeclaration ::= Type 'procedure' ProcedureIdentifier ProcedureRange COMPUTE ProcedureDeclaration.GotOper= ListOperator( ProcedureIdentifier.Key, NoOprName, CONSTITUENT FormalParameterPart.OpndTypeList, Type.Type); ProcedureIdentifier.GotProp= ORDER( ResetKind(ProcedureIdentifier.Key,ProcedureIdn), ResetFormals( ProcedureIdentifier.Key, CONSTITUENT FormalParameterPart.ParameterList)); END;
This macro is invoked in definition 7.
This is checked by defining an InBody property for each procedure identifier. InBody has the value 0 outside of the procedure body and a nonzero value within the body. The inBody chain is used to control the value of InBody.
Values of Function Designators[149]==This macro is defined in definitions 149 and 151.CHAIN inBody: VOID; ATTR InBody: int; SYMBOL ROOTCLASS COMPUTE CHAINSTART HEAD.inBody=0; END; RULE: ProcedureDeclaration ::= 'procedure' ProcedureIdentifier ProcedureRange COMPUTE ProcedureRange.inBody= ResetInBody(ProcedureIdentifier.Key,1) <- ProcedureDeclaration.inBody; ProcedureDeclaration.inBody= ResetInBody(ProcedureIdentifier.Key,0) <- ProcedureRange.inBody; END; RULE: ProcedureDeclaration ::= Type 'procedure' ProcedureIdentifier ProcedureRange COMPUTE ProcedureRange.inBody= ResetInBody(ProcedureIdentifier.Key,1) <- ProcedureDeclaration.inBody; ProcedureDeclaration.inBody= ORDER( IF(NE(GetInBody(ProcedureIdentifier.Key,1),2), message(ERROR,"No assignment to the function designator",0,COORDREF)), ResetInBody(ProcedureIdentifier.Key,0)) <- ProcedureRange.inBody; END; RULE: LeftPart ::= Variable ':=' COMPUTE LeftPart.inBody= IF(NE(GetInBody(Variable.Key,0),0), ResetInBody(Variable.Key,2)) <- LeftPart.inBody; END;
This macro is invoked in definition 7.
Properties characterizing function designators[150]==The type associated with the procedure identifier must be declared through the appearance of a type declarator as the very first symbol of the procedure declaration.This macro is invoked in definition 16.InBody: int;
Values of Function Designators[151]==This macro is defined in definitions 149 and 151.SYMBOL ProcedureDeclaration INHERITS TypedDefinition END; SYMBOL ProcedureIdentifier INHERITS TypedDefId END; RULE: ProcedureDeclaration ::= 'procedure' ProcedureIdentifier ProcedureRange COMPUTE ProcedureDeclaration.Type=voidType; END; RULE: ProcedureDeclaration ::= Type 'procedure' ProcedureIdentifier ProcedureRange COMPUTE ProcedureDeclaration.Type=Type.Type; END;
This macro is invoked in definition 7.
Specifications[152]==Neither the FormalParameterPart nor the ValuePart may contain repeated identifiers.This macro is defined in definitions 152, 154, and 155.SYMBOL FormalSpecification INHERITS TypedDefinition END; SYMBOL FormalParamIdTypeDef INHERITS TypedDefId COMPUTE INH.GotType=ResetKind(THIS.Key,INCLUDING FormalSpecification.kind); END; RULE: SpecificationPart LISTOF FormalSpecification END; RULE: FormalSpecification ::= Specifier FormalIdList ';' COMPUTE FormalSpecification.Type=Specifier.Type; FormalSpecification.kind=Specifier.kind; END; RULE: Specifier ::= 'string' COMPUTE Specifier.Type=stringType; Specifier.kind=VariableIdn; END; RULE: Specifier ::= Type COMPUTE Specifier.Type=Type.Type; Specifier.kind=VariableIdn; END; RULE: Specifier ::= 'array' COMPUTE Specifier.Type=realType; Specifier.kind=ArrayIdn; END; RULE: Specifier ::= Type 'array' COMPUTE Specifier.Type=Type.Type; Specifier.kind = ArrayIdn; END; RULE: Specifier ::= 'label' COMPUTE Specifier.Type=labelType; Specifier.kind=LabelIdn; END; RULE: Specifier ::= 'switch' COMPUTE Specifier.Type=labelType; Specifier.kind=SwitchIdn; END; RULE: Specifier ::= 'procedure' COMPUTE Specifier.Type=voidType; Specifier.kind=ProcedureIdn; END; RULE: Specifier ::= Type 'procedure' COMPUTE Specifier.Type=Type.Type; Specifier.kind = ProcedureIdn; END;
This macro is invoked in definition 7.
Instantiate additional modules for uniqueness checks[153]==This macro is invoked in definition 19.$/Prop/Unique.gnrc +instance=Formal :inst $/Prop/Unique.gnrc +instance=Value :inst
Specifications[154]==There must be a formal parameter for every specification.This macro is defined in definitions 152, 154, and 155.SYMBOL FormalParameter INHERITS FormalUnique COMPUTE IF(AND(NOT(THIS.FormalUnique),NE(THIS.Key,NoKey)), message( ERROR, CatStrInd("Repeated formal parameter: ",THIS.Sym), 0, COORDREF)); END; SYMBOL ValueParameter INHERITS ValueUnique COMPUTE IF(AND(NOT(THIS.ValueUnique),NE(THIS.Key,NoKey)), message( ERROR, CatStrInd("Repeated value parameter: ",THIS.Sym), 0, COORDREF)); END;
This macro is invoked in definition 7.
Specifications[155]==This macro is defined in definitions 152, 154, and 155.SYMBOL ProcedureHeading COMPUTE IF( NE( CONSTITUENTS FormalParameter.Sym WITH (int, ADD, ARGTOONE, ZERO), CONSTITUENTS FormalParamIdTypeDef.Sym WITH (int, ADD, ARGTOONE, ZERO)), message(ERROR,"Fewer formals than specifications",0,COORDREF)); END;
This macro is invoked in definition 7.
We have chosen to define Code as a body of text enclosed in braces, possibly with nested text of the same form. A C procedure body or compound statement takes this form, which is recognized by the Ctext auxiliary scanner from the Eli library:
Code as Procedure Body[156]==The { must be escaped because it is a regular expression operator.This macro is invoked in definition 2.Code: $\{ (Ctext) [mkstr]
The token processor mkstr assigns a unique integer value to each code body regardless of its content. This integer value can be used to access the code body.