| William.Waite@Colorado.edu |
Only the semantic analysis task (determining the properties of all entities appearing in a program and decorating the abstract syntax tree) is covered in this document. Modules specifying the lexical and syntactic analysis tasks are also available, and can be combined with this module to specify a processor that extracts symbol information from FORTRAN 77 programs. These specifications can also be used as the basis for processors that derive metrics characterizing FORTRAN 77 programs, convert FORTRAN 77 programs into programs in other languages, or implement extensions.
All of the computations described in this document are carried out on an abstract syntax tree having the form defined by the phrase structure definition module for FORTRAN 77. Eli can generate either a FORTRAN 77 or a FORTRAN 90 scanner/parser from that specification, depending upon the setting of a #define directive. The directive must be set for FORTRAN 77 if the generated scanner/parser is to be used with the symbol table constructor described here.
File Symbol/F77Symbols.fw contains the specification from which this document was generated. An implementation of the symbol table construction task will be produced if Symbol/Symbol.specs is named as one of the specification components. The total set of components must also include the phrase structure definition module (file Phrase/Phrase.specs) with the appropriate #define directive. Any arbitrary additional components may be supplied to describe other tasks.
Section 2 summarizes the information defined by this module that is likely
to be of interest to other specification modules.
Users of this module should therefore concentrate their attention on
Section 2.
2 FORTRAN Terms and Concepts
The basic concepts of FORTRAN are reflected in the grammar symbols
and their attributes, and the entities with their associated properties.
For this specification, only the following concepts are needed:
FORTRAN Terms and Concepts[1]==A grammar symbol characterizes a class of tree nodes, while an attribute characterizes a value associated with a specific node in the tree. Each tree node in the class characterized by a specific grammar symbol has the same set of attributes, but the values of these attributes may differ between nodes.This macro is invoked in definition 237.Syntactic Items[5] Program Units and Procedures[18]
The properties of an entity are values of arbitrary type stored in the
definition table and accessible via a DefTableKey value representing
the entity.
Any property may be associated with any entity.
When a property is queried, the query operation must provide a ``default''
value to be used in satisfying the query if the entity does not possess
the queried property.
2.1 Sequence
The elements of a list are ordered by a one-to-one correspondence with the
numbers 1, 2, through the length of the list.
SeqCount gives the number of elements in each list or sublist,
and SeqIndex gives the position of a specific element.
Sequence[2]==This macro is defined in definitions 2 and 4.ATTR SeqIndex, SeqCount: int;
This macro is invoked in definition 237.
Sequence the elements[3](¶1)==The statement function ambiguity gives rise to a complex situation on the left-hand side of an assignment. In that case the nature of the list may change partway along, and it may be impossible to group the components of a single element properly. This results in a general list of expressions:This macro is invoked in definitions 91, 183, 219, and 229.RULE: ¶1List ::= ¶1 COMPUTE ¶1List.SeqCount=1; ¶1.SeqIndex=1; END; RULE: ¶1List ::= ¶1List ',' ¶1 COMPUTE ¶1List[1].SeqCount=¶1.SeqIndex; ¶1.SeqIndex=ADD(¶1List[2].SeqCount,1); END;
Sequence[4]==This macro is defined in definitions 2 and 4.RULE: xExprList ::= xExpr COMPUTE xExprList.SeqCount=1; END; RULE: xExprList ::= ':' COMPUTE xExprList.SeqCount=1; END; RULE: xExprList ::= ':' xExpr COMPUTE xExprList.SeqCount=1; END; RULE: xExprList ::= xExpr ':' COMPUTE xExprList.SeqCount=1; END; RULE: xExprList ::= xExpr ':' xExpr COMPUTE xExprList.SeqCount=1; END; RULE: xExprList ::= xExprList ',' xSectionSubscript COMPUTE xExprList[1].SeqCount=xSectionSubscript.SeqIndex; xSectionSubscript.SeqIndex=ADD(xExprList[2].SeqCount,1); END; RULE: xExprList ::= xSFDummyArgNameList ',' xExpr COMPUTE xExprList.SeqCount=ADD(xSFDummyArgNameList.SeqCount,1); END; RULE: xExprList ::= xSFDummyArgNameList ',' ':' COMPUTE xExprList.SeqCount=ADD(xSFDummyArgNameList.SeqCount,1); END; RULE: xExprList ::= xSFDummyArgNameList ',' ':' xExpr COMPUTE xExprList.SeqCount=ADD(xSFDummyArgNameList.SeqCount,1); END; RULE: xExprList ::= xSFDummyArgNameList ',' xExpr ':' COMPUTE xExprList.SeqCount=ADD(xSFDummyArgNameList.SeqCount,1); END; RULE: xExprList ::= xSFDummyArgNameList ',' xExpr ':' xExpr COMPUTE xExprList.SeqCount=ADD(xSFDummyArgNameList.SeqCount,1); END;
This macro is invoked in definition 237.
Syntactic Items[5]==This macro is invoked in definition 1.Symbolic Name Characteristics[6] Statement Label Characteristics[15]
The following attributes of symbolic names are established by this specification. All of these attributes are attached to each individual occurrence of a symbolic name in the program:
Symbolic Name Characteristics[6]==Sym gives the index in the string table of the character sequence representing the symbolic name. The StringTable function exported by the Character Storage module of the Eli library returns a pointer to the actual character string. Sym is used in constructing reports, and in computations that need access to the characters making up the name.This macro is defined in definitions 6 and 14.SYMBOL SymbolicName: Sym: int, Coord: CoordPtr, ObjectKey: DefTableKey, UnitKey: DefTableKey;
This macro is invoked in definition 5.
Coord gives the position of this instance of the symbolic name in the original source text of the program. The type CoordPtr is exported by the Error module of the Eli library. Coord is used to attach reports to a particular instance of a symbolic name.
Symbolic names identify entities like variables, arrays, and functions. A particular identification holds over a region of the program called the scope of the identification. The value of the ObjectKey attribute of a specific occurrence of a symbolic name represents the entity identified by that occurrence. The type DefTableKey is exported by the Definition Table module of the Eli library. It allows access to any of the properties of the entity it represents.
Properties accessible via the ObjectKey attribute[7]==The Value property is associated with each symbolic constant; other entities do not have this property. It is the string table index of a denotation giving the value of the symbolic constant. Queries should be provided with the default value 0, the string table index of the null string.This macro is invoked in definition 236.Value: int; Intrinsic: int;
The Intrinsic property value 1 is associated with entities representing FORTRAN intrinsic functions; other entities do not have this property. Queries should be provided with the default value 0.
All of the entities identified by a given symbolic name within a program unit share certain properties. The value of the UnitKey attribute allows access to these shared properties.
Properties accessible via the UnitKey attribute[8]==The KindSet property specifies the classification of the symbolic name. It is a set because a particular symbolic name may legally be classified in several different ways within a program unit. The elements of a KindSet are members of an enumeration whose elements are roughly the classes of symbolic names given in Section 18 of the standard:This macro is defined in definitions 8, 16, and 19.KindSet: IntSet; Type: DefTableKey; Length: int; StorageUnits: int;
This macro is invoked in definition 236.
KindSet elements[9]==Two additional elements are needed to accumulate information during classification:This macro is defined in definitions 9 and 10.typedef enum { CommonBlock, ExternalFunction, Subroutine, MainProgram, BlockDataSubprogram, Array, Variable, Constant, StatementFunction, IntrinsicFunction, DummyProcedure,
This macro is invoked in definition 241.
KindSet elements[10]==The KindSet is implemented using an Eli library module:This macro is defined in definitions 9 and 10.InExternalStmt, DummyArgument, } KindSetElement;
This macro is invoked in definition 241.
Instantiate the integer set property module[11]==The usual query applied to the KindSet property of a symbolic name asks whether that name has a specific classification:This macro is invoked in definition 235.$/Prop/KindSet.gnrc :inst
Classified as[12](¶2)==NullIS() is an empty set, and InIS(e,s) returns nonzero if and only if element e is a member of set s.This macro is invoked in definitions 151, 206, 216, 219, 229, 231, 232, and 234.InIS(¶1,GetKindSet(¶2.UnitKey,NullIS()))
The Type property specifies the FORTRAN data type of the entity represented by the symbolic name. Not all symbolic names have a Type property. The following definition table keys are possible values of the Type property:
Data Types[13]==The Length property specifies the number of characters in an entity of character type. It is the string table index of a string whose apparent integer value is the number of characters. A string table index of 0 indicates the absence of a Length. Only symbolic names having the Type property with the CharacterType value have a Length property.This macro is invoked in definition 236.IntegerType; RealType; DoublePrecisionType; ComplexType; LogicalType; CharacterType; ErrorType;
The StorageUnits property specifies the number if storage units occupied by the entity.
Symbolic names appear in a wide variety of contexts, which reflect different views of those names and are therefore represented in the grammar by distinct nonterminals that may have distinct computations. Each of these contexts embodies the FORTRAN concept of a symbolic name, however, so it must inherit any computations performed for all symbolic names:
Symbolic Name Characteristics[14]==Any computation performed for all symbolic names may be overridden in a specific context by attaching a computation of the same value to the grammar symbol representing that context.This macro is defined in definitions 6 and 14.SYMBOL xBlockDataName INHERITS SymbolicName END; SYMBOL xCommonBlockName INHERITS SymbolicName END; SYMBOL xDummyArgName INHERITS SymbolicName END; SYMBOL xEntryName INHERITS SymbolicName END; SYMBOL xExternalName INHERITS SymbolicName END; SYMBOL xFunctionName INHERITS SymbolicName END; SYMBOL xImpliedDoVariable INHERITS SymbolicName END; SYMBOL xIntrinsicProcedureName INHERITS SymbolicName END; SYMBOL xName INHERITS SymbolicName END; SYMBOL xNamedConstant INHERITS SymbolicName END; SYMBOL xNamedConstantUse INHERITS SymbolicName END; SYMBOL xObjectName INHERITS SymbolicName END; SYMBOL xProgramName INHERITS SymbolicName END; SYMBOL xSFDummyArgName INHERITS SymbolicName END; SYMBOL xSFVarName INHERITS SymbolicName END; SYMBOL xSubroutineName INHERITS SymbolicName END; SYMBOL xSubroutineNameUse INHERITS SymbolicName END; SYMBOL xVariableName INHERITS SymbolicName END;
This macro is invoked in definition 5.
Any computation performed for all statement labels may be overridden in a specific context by attaching a computation of the same value to the grammar symbol representing that context.
The following attributes of statement labels are established by this specification. All of these attributes are attached to each individual occurrence of a statement label in the program:
Statement Label Characteristics[15]==Sym gives the index in the string table of the character sequence representing the statement label. The StringTable function exported by the Character Storage module of the Eli library of the Eli library returns a pointer to the actual character string. Sym is used in constructing reports, and in computations that need access to the characters making up the label.This macro is defined in definitions 15 and 17.SYMBOL Label: Sym: int, UnitKey: DefTableKey;
This macro is invoked in definition 5.
The value of the UnitKey attribute of a specific occurrence of a statement label allows access to any of the properties of that label. The type DefTableKey is exported by the Definition Table module of the Eli library. A UnitKey attribute value of NoKey indicates that the label has not been defined.
Properties accessible via the UnitKey attribute[16]==The Executable property value 1 is associated with labels of executable statements; 0 is associated with labels of nonexecutable statements.This macro is defined in definitions 8, 16, and 19.Executable: int;
This macro is invoked in definition 236.
Statement labels appear in two contexts, which reflect different views of those labels and are therefore represented in the grammar by distinct nonterminals that may have distinct computations. Each of these contexts embodies the FORTRAN concept of a statement label, however, so it must inherit any computations performed for all statement labels:
Statement Label Characteristics[17]==This macro is defined in definitions 15 and 17.SYMBOL xLblDef INHERITS Label END; SYMBOL xLblRef INHERITS Label END;
This macro is invoked in definition 5.
Program Units and Procedures[18]==The Kind attribute reflects what kind of program unit the xProgramUnit phrase represents. Its value is the classification of the symbolic name of the program unit. (If the program unit has no symbolic name then the value of the Kind attribute is MainProgram.)This macro is defined in definitions 18.SYMBOL xProgramUnit: Kind: KindSetElement, ClassificationDone: VOID, GotAllTypes: VOID, GotAllDims: VOID, GotAllExecs: VOID;
This macro is invoked in definition 1.
The ClassificationDone attribute is an assertion that the KindSet property of every entity is valid. Computations that query the KindSet property should depend on this attribute unless the KindSet property of the specific entity being tested is known to be valid on other grounds.
The GotAllTypes attribute is an assertion that the Type property of every entity is valid. Computations that query the Type property should depend on this attribute unless the Type property of the specific entity being tested is known to be valid on other grounds.
The GotAllDims attribute is an assertion that the NumberOfDims property of every array is valid. Computations that query the NumberOfDims property should depend on this attribute unless the NumberOfDims property of the specific entity being tested is known to be valid on other grounds.
The GotAllExecs attribute is an assertion that the Executable
property of every label is valid.Computations that query the Executable
property should depend on this attribute unless the Executable property
of the specific label being tested is known to be valid on other grounds.
2.4 Array
An array has a fixed number of dimensions:
Properties accessible via the UnitKey attribute[19]==This macro is defined in definitions 8, 16, and 19.NumberOfDims: int;
This macro is invoked in definition 236.
A procedure reference is the appearance of a procedure name in a statement in a context that requires the actions specified by the procedure to be executed during the execution of the executable program.
References are represented in this document by the computational role Reference.
Reference[20]==This macro is defined in definitions 20.CLASS SYMBOL Reference END;
This macro is invoked in definition 42.
Storage[21]==An integer, real, or logical datum has one numeric storage unit in a storage sequence. A double precision or complex datum has two numeric storage units in a storage sequence. A character datum has one character storage unit in a storage sequence for each character in the datum.This macro is defined in definitions 21, 22, and 23.NumericStorage; CharacterStorage; InvalidStorage;
This macro is invoked in definition 236.
Storage[22]==The storage requirements for entities must be computed using safe arithmetic, and therefore must be represented as string table indices. StorageUnits is the property used for this purpose.This macro is defined in definitions 21, 22, and 23.UnitsPerDatum: int; StorageUnitKind: DefTableKey; IntegerType -> UnitsPerDatum={1}, StorageUnitKind={NumericStorage}; RealType -> UnitsPerDatum={1}, StorageUnitKind={NumericStorage}; DoublePrecisionType -> UnitsPerDatum={2}, StorageUnitKind={NumericStorage}; ComplexType -> UnitsPerDatum={2}, StorageUnitKind={NumericStorage}; LogicalType -> UnitsPerDatum={1}, StorageUnitKind={NumericStorage}; CharacterType -> UnitsPerDatum={1}, StorageUnitKind={CharacterStorage}; ErrorType -> UnitsPerDatum={1}, StorageUnitKind={InvalidStorage};
This macro is invoked in definition 236.
Storage[23]==Computation of the number of storage units will always depend ultimately on the number of storage units occupied by the basic type of the object.This macro is defined in definitions 21, 22, and 23.StorageUnits: int;
This macro is invoked in definition 236.
Evaluation functions[24]==This macro is defined in definitions 24, 98, 111, 167, 174, 177, and 179.int #ifdef PROTO_OK SizeOfType(DefTableKey key) #else SizeOfType(key) DefTableKey key; #endif { int units = GetUnitsPerDatum(GetType(key, key), 0); return (units == 0 ? 0 : IdnNumb(0, units)); }
This macro is invoked in definition 240.
Evaluation function interfaces[25]==This macro is defined in definitions 25, 99, 110, 112, 175, 178, and 180.int SizeOfType ELI_ARG((DefTableKey));
This macro is invoked in definition 241.
Characters, Lines and Execution Sequence[26]==Most of the remaining subsections of the standard are implemented by the specification module defining the phrase structure.This macro is invoked in definition 237.Statement Labels[27] Order of Statements and Lines[36]
Here is a consistent renaming specification that associates a unique DefTableKey-valued attribute named UnitKey with every occurrence of a given label in a program unit. Occurrences of distinct labels, and occurrences of the same label in distinct program units, will be associated with distinct DefTableKey values:
Statement Labels[27]==The nonterminal xLblDef represents the context of a label definition, and the nonterminal xLblRef represents the context of a label use.This macro is defined in definitions 27, 29, 31, and 32.SYMBOL xSourceFile INHERITS UnitRootScope END; SYMBOL xProgramUnit INHERITS UnitRangeScope END; SYMBOL xLblDef INHERITS UnitIdDefScope END; SYMBOL xLblRef INHERITS UnitIdUseEnv END;
This macro is invoked in definition 26.
This consistent renaming specification uses the Eli library module implementing scopes that are the closest-containing range (these are the scope rules of ALGOL 60):
Instantiate the ALGOL 60 scope module[28]==The form of a statement label is a sequence of 1 to 5 digits, one of which must be nonzero. Moreover, blanks and leading zeros in this sequence are not significant in distinguishing between labels. This specification therefore recognizes a label as a decimal integer constant, identifying it as a label only by the context in which it appears:This macro is defined in definitions 28, 194, and 200.$/Name/AlgScope.gnrc +instance=Unit +referto=Unit :inst
This macro is invoked in definition 235.
Statement Labels[29]==The function IdnNumb generates a symbol consisting of the string indexed by its first argument and the number given by its second. Since the null string is indexed by 0, this invocation of IdnNumb produces a symbol whose string is the sequence of decimal digits (with no leading zeros or embedded blanks) representing the value of the label.This macro is defined in definitions 27, 29, 31, and 32.SYMBOL xLabel: Sym: int; RULE: xLabel ::= xIcon COMPUTE IF(EQ(xIcon,0), message(ERROR,"Zero is not a valid label",0,COORDREF)); IF(GT(xIcon,99999), message(ERROR,"Labels must be 1 to 5 digits",0,COORDREF)); xLabel.Sym=IdnNumb(0,xIcon); END;
This macro is invoked in definition 26.
IdnNumb is exported by the Eli MakeName library module, which must therefore be instantiated:
Instantiate the MakeName library module[30]==Here xIdent is the terminal symbol used in the grammar to represent an identifier. When the module creates a symbol, it creates that symbol as though it had been recognized as an instance of the terminal symbol xIdent.This macro is invoked in definition 235.$/Tech/MakeName.gnrc +instance=xIdent :inst
Statement Labels[31]==The restriction that the same statement label must not be given to more than one statement in a program unit is typical of a number of such restrictions involving multiple occurrences of symbolic names:This macro is defined in definitions 27, 29, 31, and 32.RULE: xLblDef ::= xLabel COMPUTE xLblDef.Sym=xLabel.Sym; END; RULE: xLblDef ::= COMPUTE xLblDef.Sym=0; xLblDef.UnitKey=NoKey; END; RULE: xLblRef ::= xLabel COMPUTE xLblRef.Sym=xLabel.Sym; END;
This macro is invoked in definition 26.
Statement Labels[32]==Such a restriction is enforced by setting a property of the entity to 1 the first time and to 2 any subsequent time that the entity appears in a given context, and then complaining if the property has the value 2. The attribute GotAppearance asserts that the property has been set at a specific occurrence, while xProgramUnit.GotAllAppearances asserts that all occurrences in the program unit have been seen. Since not all contexts containing symbolic names are relevant for detecting multiple occurrences, there will be some that have no explicit computation of the GotAppearance attribute. The last symbol computation above ensures that SymbolicName.GotAppearance will be defined everywhere; this computation is overridden by computations attached to specific nonterminals inheriting from SymbolicName, as well as by computations attached to rules.This macro is defined in definitions 27, 29, 31, and 32.SYMBOL xProgramUnit COMPUTE SYNT.GotAllAppearances= CONSTITUENTS (xLblDef.GotAppearance,SymbolicName.GotAppearance); END; Report multiple[33] (`xLblDef', `label') SYMBOL SymbolicName COMPUTE INH.GotAppearance=1; END;
This macro is invoked in definition 26.
Here is a macro that defines an overriding computation. The macro's first argument specifies the grammar symbol defining the occurrences to be checked, the second specifies the property to be updated:
Report multiple[33](¶2)==Report multiple counts every occurrence of the specified symbol. If only the occurrences in certain contexts should be counted, a rule computation must be added to the rules defining those contexts:This macro is invoked in definitions 32, 121, 136, 147, and 149.SYMBOL ¶1 COMPUTE INH.GotAppearance=Set¶2App(THIS.UnitKey,1,2); IF(EQ(Get¶2App(THIS.UnitKey,0),2), message(ERROR,"Multiply-defined ¶2",0,COORDREF)) <- INCLUDING xProgramUnit.GotAllAppearances; END;
Rule multiple[34](¶2)==The arguments of this macro are identical to those of Report multiple.This macro is invoked in definition 49.¶1.GotAppearance=Set¶2App(¶1.UnitKey,1,2); IF(EQ(Get¶2App(¶1.UnitKey,0),2), message(ERROR,"Multiply-defined ¶2",0,COORDREF)) <- INCLUDING xProgramUnit.GotAllAppearances;
In addition to the operations, a property must be defined for each test:
Properties supporting multiple definition reporting[35]==This macro is defined in definitions 35, 50, 122, 137, 148, and 150.labelApp: int;
This macro is invoked in definition 236.
The restrictions on PROGRAM, FUNCTION, SUBROUTINE and BLOCK DATA statements are enforced by the grammar. Conditions (1) through (5), as well as the restriction on IMPLICIT statements, are enforced by the specification described below. Proper relative ordering of IMPLICIT and PARAMETER statements is enforced by the specifications of those statements. The restriction on the END statement is enforced by the grammar.
Figure 1 from Section 3.5 of the standard shows that the program can be divided into six segments, with a certain set of statements allowed in each segment. Statements that may appear in more than one of these segments are always restricted to a contiguous subset.
This specification is implemented by defining an integer-valued chain, Order, which contains the current segment number at each statement.
Order of Statements and Lines[36]==The chain value leaving a statement is the larger of two values: the first segment number in which that statement could appear, and the current segment number. Thus a statement will advance the current segment if that statement cannot appear until a segment following the current one.This macro is defined in definitions 36, 38, 39, and 40.CHAIN Order: int; SYMBOL xProgramUnit COMPUTE CHAINSTART HEAD.Order=0; END;
This macro is invoked in definition 26.
A statement is out of order if the last segment in which it could appear is earlier than the current segment:
Seq[37](¶3)==In addition to verifying the correct statement sequence, Order is used to enforce text-order dependence in initial classification. The GotContext attribute of SymbolicName asserts that the initial classification of the symbol has been updated by this information. Thus, because of the <- clause, Order asserts that all initial classifications reflect all information available up to this point.This macro is invoked in definitions 38, 39, and 40.RULE: xStmt ::= xLblDef ¶1 xEOS COMPUTE xStmt.Order= LaterOf(¶2,xStmt.Order) <- CONSTITUENTS SymbolicName.GotContext; IF(LE(¶3,xStmt.Order), message(ERROR,"Position violates the standard, Section 3.5",0,COORDREF)); END;
Figure 1 of Section 3.5 of the standard is encoded by specifying, for every statement, the first segment in which that statement may appear and the first segment in which it may not appear. (The segment containing IMPLICIT statements is numbered 1; the segment containing the END statement is numbered 5.)
Comment lines are removed during scanning, and hence do not appear in this specification.
Order of Statements and Lines[38]==Statement functions are a special case, because what is recognized syntactically is a possible statement function definition. The check for an ordering error must be based on the classification of the symbolic name:This macro is defined in definitions 36, 38, 39, and 40.Seq[37] (`'format' '(' xFmtSpec ')' ', ` 1', ` 5') Seq[37] (`'entry' xEntryName xFormalParameterList ', ` 1', ` 5') Seq[37] (`'parameter' '(' xNamedConstantDefList ')' ', ` 1', ` 3') Seq[37] (`'data' xDatalist ', ` 3', ` 5') Seq[37] (`'implicit' xImplicitSpecList ', ` 1', ` 2') Seq[37] (`'common' xComlist ', ` 2', ` 3') Seq[37] (`'dimension' xArrayDeclaratorList ', ` 2', ` 3') Seq[37] (`'equivalence' xEquivalenceSetList ', ` 2', ` 3') Seq[37] (`'external' xExternalNameList ', ` 2', ` 3') Seq[37] (`'intrinsic' xIntrinsicList ', ` 2', ` 3') Seq[37] (`'save' ', ` 2', ` 3') Seq[37] (`'save' xSavedEntityList ', ` 2', ` 3') Seq[37] (`xTypeSpec xEntityDeclList ', ` 2', ` 3')
This macro is invoked in definition 26.
Order of Statements and Lines[39]==Logical IF statements are also a special case, because they contain two instances of xStmt and are not terminated by xEOS. Thus they do not quite fit the macro definition:This macro is defined in definitions 36, 38, 39, and 40.RULE: xStmt ::= xLblDef xName xStmtFunctionRange COMPUTE xStmt.Order= LaterOf( IF(This is a statement function statement[230],3,4), xStmt.Order) <- CONSTITUENTS SymbolicName.GotContext; IF(LE( IF(This is a statement function statement[230],4,5), xStmt.Order), message(ERROR,"Position violates the standard, Section 3.5",0,COORDREF)); END; Seq[37] (`'assign' xLblRef 'to' xVariableName ', ` 4', ` 5') Seq[37] (`'backspace' '(' xIoControlSpecList ')' ', ` 4', ` 5') Seq[37] (`'backspace' xUnitIdentifier ', ` 4', ` 5') Seq[37] (`'call' xSubroutineNameUse '(' xArgList ')' ', ` 4', ` 5') Seq[37] (`'call' xSubroutineNameUse ', ` 4', ` 5') Seq[37] (`'close' '(' xIoControlSpecList ')' ', ` 4', ` 5') Seq[37] (`'continue' ', ` 4', ` 5') Seq[37] (`'do' xLblRef xLoopControl ', ` 4', ` 5') Seq[37] (`'else' ', ` 4', ` 5') Seq[37] (`'elseif' '(' xExpr ')' 'then' ', ` 4', ` 5') Seq[37] (`'endfile' '(' xIoControlSpecList ')' ', ` 4', ` 5') Seq[37] (`'endfile' xUnitIdentifier ', ` 4', ` 5') Seq[37] (`'if' '(' xExpr ')' 'then' ', ` 4', ` 5') Seq[37] (`'if' '(' xExpr ')' xLblRef ',' xLblRef ',' xLblRef', ` 4', ` 5')
This macro is invoked in definition 26.
Order of Statements and Lines[40]==This macro is defined in definitions 36, 38, 39, and 40.RULE: xStmt ::= xLblDef 'if' '(' xExpr ')' xStmt COMPUTE xStmt[1].Order= LaterOf(4,xStmt[1].Order) <- CONSTITUENTS SymbolicName.GotContext; IF(LE(5,xStmt[1].Order), message(ERROR,"Position violates the standard, Section 3.5",0,COORDREF)); END; Seq[37] (`'inquire' '(' xIoControlSpecList ')' ', ` 4', ` 5') Seq[37] (`'open' '(' xIoControlSpecList ')' ', ` 4', ` 5') Seq[37] (`'pause' ', ` 4', ` 5') Seq[37] (`'pause' xIcon ', ` 4', ` 5') Seq[37] (`'pause' xScon ', ` 4', ` 5') Seq[37] (`'print' xFormatIdentifier ',' xOutputItemList ', ` 4', ` 5') Seq[37] (`'print' xFormatIdentifier ', ` 4', ` 5') Seq[37] (`'read' xFormatIdentifier ',' xInputItemList ', ` 4', ` 5') Seq[37] (`'read' xFormatIdentifier ', ` 4', ` 5') Seq[37] (`'read' xIoControlSpec ', ` 4', ` 5') Seq[37] (`'read' xIoControlSpec xInputItemList ', ` 4', ` 5') Seq[37] (`'return' ', ` 4', ` 5') Seq[37] (`'return' xExpr ', ` 4', ` 5') Seq[37] (`'rewind' '(' xIoControlSpecList ')' ', ` 4', ` 5') Seq[37] (`'rewind' xUnitIdentifier ', ` 4', ` 5') Seq[37] (`'stop' ', ` 4', ` 5') Seq[37] (`'stop' xIcon ', ` 4', ` 5') Seq[37] (`'stop' xScon ', ` 4', ` 5') Seq[37] (`'write' '(' xIoControlSpecList ')' ', ` 4', ` 5') Seq[37] (`'write' '(' xIoControlSpecList ')' xOutputItemList', ` 4', ` 5') Seq[37] (`GoToKw '(' xLblRefList ')' xExpr ', ` 4', ` 5') Seq[37] (`GoToKw xLblRef ', ` 4', ` 5') Seq[37] (`GoToKw xVariableName '(' xLblRefList ')' ', ` 4', ` 5') Seq[37] (`GoToKw xVariableName ', ` 4', ` 5') Seq[37] (`xName '(' xExprList ')' '=' xExpr ', ` 4', ` 5') Seq[37] (`xName '(' xExprList ')' xSubstringRange '=' xExpr ', ` 4', ` 5') Seq[37] (`xName '=' xExpr ', ` 4', ` 5')
This macro is invoked in definition 26.
Data Types and Constants[41]==This macro is invoked in definition 237.Data Type of a Name[42] Constants[46]
Data Type of a Name[42]==The contexts in which a symbolic name is given a type inherit the computational role TypeName; those in which usage of the name requires a type inherit the computational role Reference.This macro is invoked in definition 41.CLASS SYMBOL TypeName COMPUTE IF(EQ(GetType(THIS.UnitKey,NoKey),ErrorType), message(ERROR,"Defined with different types",0,COORDREF)) <- INCLUDING xProgramUnit.GotAllTypes; END; SYMBOL xObjectName INHERITS TypeName END; SYMBOL xFunctionName INHERITS TypeName END; CLASS SYMBOL Reference COMPUTE SYNT.Type= IF(GetIntrinsic(THIS.ObjectKey,0), GuaranteeType(THIS.UnitKey,GetType(THIS.ObjectKey,NoKey)), GuaranteeType(THIS.UnitKey,DefaultType(THIS.Sym))) <- INCLUDING xProgramUnit.GotAllTypeDefs; SYNT.Length= IF(NE(SYNT.Type,CharacterType),0, IF(GetIntrinsic(THIS.ObjectKey,0), GuaranteeLength(THIS.UnitKey,MakeName("1")), GuaranteeLength(THIS.UnitKey,DefaultLength(THIS.Sym)))) <- INCLUDING xProgramUnit.GotAllLengths; END; Reference[20] SYMBOL xVariableName INHERITS Reference END; SYMBOL xName INHERITS Reference END; SYMBOL xNamedConstantUse INHERITS Reference END; SYMBOL xSFVarName INHERITS Reference END;
Properties for type analysis[43]==This macro is defined in definitions 43 and 119.Type: DefTableKey [Guarantee]; Length: int [Guarantee]; TYPE Guarantee(DefTableKey key, TYPE val) { if (key == NoKey) return val; if (!ACCESS) VALUE = val; return VALUE; }
This macro is invoked in definition 236.
Return the default type associated with the first letter of a name[44]==A first letter of I, J, K, L, M, or N implies type integer and any other letter implies real, unless an IMPLICIT statement is used to change the default implied type.This macro is invoked in definition 239.#define DefaultType(Sym) (TypeFor[*(StringTable(Sym)) - 'a']) #define DefaultLength(Sym) (LengthOf[*(StringTable(Sym)) - 'a'])
Set default implicit types[45]==This macro is invoked in definition 134.{ int i; for (i = 0; i <= 'z'-'a'; i++) TypeFor[i] = RealType; for (i = 'i'-'a'; i <= 'n'-'a'; i++) TypeFor[i] = IntegerType; }
Constants[46]==This macro is invoked in definition 41.Arithmetic constant type[47] (`xIcon', `IntegerType') Arithmetic constant type[47] (`xRcon', `RealType') Arithmetic constant type[47] (`xDcon', `DoublePrecisionType') Arithmetic constant type[47] (`xComplexConst', `ComplexType')
Arithmetic constant type[47](¶2)==This macro is invoked in definition 46.RULE: xUnsignedArithmeticConstant ::= ¶1 COMPUTE xUnsignedArithmeticConstant.TypeCode=OilType¶2; END;
Arrays and Substrings[48]==This macro is invoked in definition 237.Array Declarator[49] Kinds and Occurrences of Array Declarators[54] Properties of an Array[57] Array Element Name[65] Subscript[67] Character Substring[74]
Only one array declarator for an array name is permitted in a program unit:
Array Declarator[49]==This macro is defined in definitions 49, 51, 52, and 53.ATTR UnitKey: DefTableKey; RULE: xArrayDeclarator ::= xVariableName '(' DimensionDeclarators ')' COMPUTE Rule multiple[34] (`xVariableName', `array') DimensionDeclarators.UnitKey=xVariableName.UnitKey; END; RULE: xEntityDecl ::= xObjectName '(' DimensionDeclarators ')' COMPUTE Rule multiple[34] (`xObjectName', `array') DimensionDeclarators.UnitKey=xObjectName.UnitKey; END; RULE: xEntityDecl ::= xObjectName '(' DimensionDeclarators ')' '*' xCharLength COMPUTE Rule multiple[34] (`xObjectName', `array') DimensionDeclarators.UnitKey=xObjectName.UnitKey; END;
This macro is invoked in definition 48.
Properties supporting multiple definition reporting[50]==The number of dimensions of the array is the number of dimension declarators in the array declarator. The minimum number of dimensions is one (guaranteed by the grammar) and the maximum is seven.This macro is defined in definitions 35, 50, 122, 137, 148, and 150.arrayApp: int;
This macro is invoked in definition 236.
Array Declarator[51]==The nonterminals xLowerBound and xUpperBound represent the appearance of an expression as a dimension bound. According to the rules of FORTRAN expression evaluation, all of the components of an expression must be of type integer if the value yielded by that expression is of type integer.This macro is defined in definitions 49, 51, 52, and 53.RULE: DimensionDeclarators ::= xArraySpec COMPUTE IF(GT(xArraySpec.Dims,7), message(ERROR,"Maximum number of dimensions is 7",0,COORDREF)); END;
This macro is invoked in definition 48.
Array Declarator[52]==The upper dimension bound of the last dimension may be an asterisk in assumed-size array declarators.This macro is defined in definitions 49, 51, 52, and 53.RULE: xLowerBound ::= xExpr COMPUTE IF(NE(xExpr.TypeCode,OilTypeIntegerType), message(ERROR,"Bound must be an integer",0,COORDREF)); xLowerBound.Value=xExpr.Value; END; RULE: xUpperBound ::= xExpr COMPUTE IF(NE(xExpr.TypeCode,OilTypeIntegerType), message(ERROR,"Bound must be an integer",0,COORDREF)); xUpperBound.Value=xExpr.Value; END;
This macro is invoked in definition 48.
Array Declarator[53]==This macro is defined in definitions 49, 51, 52, and 53.ATTR NotLast: int; RULE: DimensionDeclarators ::= xArraySpec COMPUTE xArraySpec.NotLast=0; END; SYMBOL xArraySpec COMPUTE INH.NotLast=1; IF(AND(THIS.NotLast,THIS.AssumedSize), message(ERROR,"Asterisk only in the last dimension",0,COORDREF)); END;
This macro is invoked in definition 48.
Kinds and Occurrences of Array Declarators[54]==An actual array declarator is an array declarator in which the array name is not a dummy argument. Each actual array declarator must be a constant array declarator.This macro is defined in definitions 54, 55, and 56.ATTR Constant, AssumedSize: int; SYMBOL xArraySpec COMPUTE SYNT.Constant=0; SYNT.AssumedSize=1; END; RULE: xArraySpec ::= xExplicitShapeSpec COMPUTE xArraySpec.Constant=NE(xExplicitShapeSpec.SizeValue,0); xArraySpec.AssumedSize=0; END; RULE: xArraySpec ::= xArraySpec ',' xExplicitShapeSpec COMPUTE xArraySpec[1].Constant= AND(xArraySpec[2].Constant,NE(xExplicitShapeSpec.SizeValue,0)); xArraySpec[1].AssumedSize=0; END;
This macro is invoked in definition 48.
Kinds and Occurrences of Array Declarators[55]==An actual array declarator is permitted in a DIMENSION statement, type-statement, or COMMON statement. A dummy array declarator is permitted in a DIMENSION statement or a type-statement, but not in a COMMON statement.This macro is defined in definitions 54, 55, and 56.ATTR IsDummyArg: int; RULE: DimensionDeclarators ::= xArraySpec COMPUTE DimensionDeclarators.IsDummyArg= InIS(DummyArgument,GetKindSet(DimensionDeclarators.UnitKey,NullIS())) <- INCLUDING xProgramUnit.ClassificationDone; IF(AND(NOT(DimensionDeclarators.IsDummyArg),NOT(xArraySpec.Constant)), message(ERROR,"Must be a constant array declarator",0,COORDREF)); END;
This macro is invoked in definition 48.
Kinds and Occurrences of Array Declarators[56]==This macro is defined in definitions 54, 55, and 56.ATTR InCommonBlock: int; RULE: xCommonBlockObject ::= xArrayDeclarator COMPUTE xArrayDeclarator.InCommonBlock=1; END; SYMBOL xArrayDeclarator COMPUTE INH.InCommonBlock=0; END; RULE: xArrayDeclarator ::= xVariableName '(' DimensionDeclarators ')' COMPUTE IF(AND(xArrayDeclarator.InCommonBlock,DimensionDeclarators.IsDummyArg), message( ERROR, "Dummy array declarator not allowed in a COMMON statement", 0, COORDREF)); END;
This macro is invoked in definition 48.
Properties of an Array[57]==This macro is invoked in definition 48.Data Type of an Array and an Array Element[58] Dimensions of an Array[59] Size of an Array[62] Array Storage Sequence[64]
Data Type of an Array and an Array Element[58]==This macro is invoked in definition 57.
Dimensions of an Array[59]==The number of dimensions of an array is equal to the number of dimension declarators in the array declarator.This macro is defined in definitions 59, 60, and 61.RULE: DimensionDeclarators ::= xArraySpec COMPUTE DimensionDeclarators.GotDim= ResetNumberOfDims(DimensionDeclarators.UnitKey,xArraySpec.Dims); END; SYMBOL xProgramUnit COMPUTE SYNT.GotAllDims=CONSTITUENTS DimensionDeclarators.GotDim; END;
This macro is invoked in definition 57.
Dimensions of an Array[60]==The size of a dimension is one larger than the difference between the upper and lower bounds:This macro is defined in definitions 59, 60, and 61.ATTR Dims: int; RULE: xArraySpec ::= '*' COMPUTE xArraySpec.Dims=1; END; RULE: xArraySpec ::= xLowerBound ':' '*' COMPUTE xArraySpec.Dims=1; END; RULE: xArraySpec ::= xExplicitShapeSpec COMPUTE xArraySpec.Dims=1; END; RULE: xArraySpec ::= xArraySpec ',' '*' COMPUTE xArraySpec[1].Dims=ADD(xArraySpec[2].Dims,1); END; RULE: xArraySpec ::= xArraySpec ',' xLowerBound ':' '*' COMPUTE xArraySpec[1].Dims=ADD(xArraySpec[2].Dims,1); END; RULE: xArraySpec ::= xArraySpec ',' xExplicitShapeSpec COMPUTE xArraySpec[1].Dims=ADD(xArraySpec[2].Dims,1); END;
This macro is invoked in definition 57.
Dimensions of an Array[61]==If either bound is not a constant expression, the computation of that bound will yield a null string. Thus the SizeValue of the xExplicitShapeSpec will be a null string if the dimension is adjustable.This macro is defined in definitions 59, 60, and 61.ATTR SizeValue: int; RULE: xExplicitShapeSpec ::= xLowerBound ':' xUpperBound COMPUTE xExplicitShapeSpec.SizeValue= MakeName( stradd( strsub( StringTable(xUpperBound.Value), StringTable(xLowerBound.Value), 10), "1", 10)); IF(AND( AND(xUpperBound.Value,xLowerBound.Value), NOT(xExplicitShapeSpec.SizeValue)), message(ERROR,"Error evaluating array size",0,COORDREF)); END; RULE: xExplicitShapeSpec ::= xUpperBound COMPUTE xExplicitShapeSpec.SizeValue=xUpperBound.Value; END;
This macro is invoked in definition 57.
Size of an Array[62]==If any dimension is not defined by a constant expression, the corresponding SizeValue will be a null string. This null string will propagate through the computation, and therefore the SizeValue of an adjustable array declarator will be the null string.This macro is defined in definitions 62 and 63.RULE: xArraySpec ::= xExplicitShapeSpec COMPUTE xArraySpec.SizeValue=xExplicitShapeSpec.SizeValue; END; RULE: xArraySpec ::= xArraySpec ',' xExplicitShapeSpec COMPUTE xArraySpec[1].SizeValue= MakeName( strmult( StringTable(xExplicitShapeSpec.SizeValue), StringTable(xArraySpec[2].SizeValue), 10)); IF(AND( AND(xExplicitShapeSpec.SizeValue,xArraySpec[2].SizeValue), NOT(xArraySpec[1].SizeValue)), message(ERROR,"Error evaluating array size",0,COORDREF)); END;
This macro is invoked in definition 57.
If the upper bound of the last dimension of the array is an asterisk, then neither of the rules above apply. In that case an assumed-size array is being declared, and the SizeValue should be a null string:
Size of an Array[63]==This macro is defined in definitions 62 and 63.SYMBOL xArraySpec COMPUTE SYNT.SizeValue=0; END;
This macro is invoked in definition 57.
Array Storage Sequence[64]==This macro is invoked in definition 57.RULE: DimensionDeclarators ::= xArraySpec COMPUTE DimensionDeclarators.GotStorageUnits= ResetStorageUnits( DimensionDeclarators.UnitKey, ApplyStrmath(strmult, xArraySpec.SizeValue, SizeOfType(DimensionDeclarators.UnitKey))); END; SYMBOL xProgramUnit COMPUTE SYNT.GotAllStorageUnits=CONSTITUENTS DimensionDeclarators.GotStorageUnits; END;
Array Element Name[65]==The syntactic form of an array name is not unique, and therefore it is necessary to verify that xName actually refers to an array:This macro is invoked in definition 48.RULE: xStmt ::= xLblDef xName '(' xExprList ')' '=' xExpr xEOS COMPUTE Verify dimensionality[66] (`xExprList') END; RULE: xStmt ::= xLblDef xName '(' xExprList ')' xSubstringRange '=' xExpr xEOS COMPUTE Verify dimensionality[66] (`xExprList') END; RULE: xComplexDataRef ::= xName '(' xSectionSubscriptList ')' COMPUTE Verify dimensionality[66] (`xSectionSubscriptList') END;
Verify dimensionality[66](¶1)==This macro is invoked in definition 65.IF( AND( InIS(Array,GetKindSet(xName.UnitKey,NullIS())), NE(GetNumberOfDims(xName.UnitKey,0),¶1.SeqCount)), message(ERROR,"Wrong number of dimensions",0,COORDREF)) <- ( INCLUDING xProgramUnit.ClassificationDone, INCLUDING xProgramUnit.GotAllDims);
Subscript[67]==This macro is invoked in definition 48.Subscript Expression[68] Subscript Value[69]
Within a program unit, the value of each subscript expression must be greater than or equal to the corresponding lower dimension bound in the array declarator for the array. The value of each subscript expression must not exceed the corresponding upper dimension bound declared for the array in the program unit.
Subscript Expression[68]==This macro is invoked in definition 67.SYMBOL xSubscript INHERITS BoundDeListElem END; SYMBOL Subscripts INHERITS BoundDeListRoot END; RULE: xVariable ::= xVariableName '(' Subscripts ')' COMPUTE Subscripts.BoundList= GetArrayBounds(xVariableName.UnitKey,NULLBoundList) <- INCLUDING xProgramUnit.GotAllBounds; END; RULE: xVariable ::= xVariableName '(' Subscripts ')' xSubstringRange COMPUTE Subscripts.BoundList= GetArrayBounds(xVariableName.UnitKey,NULLBoundList) <- INCLUDING xProgramUnit.GotAllBounds; END; RULE: Subscripts ::= xSubscriptList END; RULE: xSubscript ::= xExpr COMPUTE IF(NE(xExpr.TypeCode,OilTypeIntegerType), message(ERROR,"Subscript must be an integer",0,COORDREF), IF(NOT(xExpr.Value), message(ERROR,"Must be a constant expression",0,COORDREF), IF( OR( LessThan(xExpr.Value,LowerOf(xSubscript.BoundElem)), GreaterThan(xExpr.Value,UpperOf(xSubscript.BoundElem))), message(ERROR,"Subscript out of bounds",0,COORDREF)))); END;
Subscript Value[69]==This macro is defined in definitions 69.ATTR Index: int; CHAIN PartialIndex: int; SYMBOL Subscripts COMPUTE CHAINSTART HEAD.PartialIndex=MakeName("1"); SYNT.Index=TAIL.PartialIndex; END; RULE: xSubscript ::= xExpr COMPUTE xSubscript.PartialIndex= ApplyStrmath(stradd, xSubscript.PartialIndex, ApplyStrmath(strmult, ApplyStrmath(strsub,xExpr.Value,LowerOf(xSubscript.BoundElem)), StrideOf(xSubscript.BoundElem))); END; SYMBOL xArraySpec INHERITS BoundListElem COMPUTE THIS._cBoundListPtr= RefEndConsBoundList(TAIL._cBoundListPtr,THIS.BoundElem); END; SYMBOL DimensionDeclarators INHERITS BoundListRoot COMPUTE SYNT.GotBounds=ResetArrayBounds(THIS.UnitKey,THIS.BoundList); END; SYMBOL xProgramUnit COMPUTE SYNT.GotAllBounds=CONSTITUENTS DimensionDeclarators.GotBounds; END; RULE: xArraySpec ::= '*' COMPUTE xArraySpec.BoundElem=NewBound(MakeName("1"),0,MakeName("1")); END; RULE: xArraySpec ::= xLowerBound ':' '*' COMPUTE xArraySpec.BoundElem=NewBound(xLowerBound.Value,0,MakeName("1")); END; ATTR LowerValue, UpperValue: int; RULE: xArraySpec ::= xExplicitShapeSpec COMPUTE xArraySpec.BoundElem= NewBound( xExplicitShapeSpec.LowerValue, xExplicitShapeSpec.UpperValue, MakeName("1")); END; RULE: xArraySpec ::= xArraySpec ',' '*' COMPUTE xArraySpec[1].BoundElem=NewBound(MakeName("1"),0,xArraySpec[2].SizeValue); END; RULE: xArraySpec ::= xArraySpec ',' xLowerBound ':' '*' COMPUTE xArraySpec[1].BoundElem=NewBound(xLowerBound.Value,0,xArraySpec[2].SizeValue); END; RULE: xArraySpec ::= xArraySpec ',' xExplicitShapeSpec COMPUTE xArraySpec[1].BoundElem= NewBound( xExplicitShapeSpec.LowerValue, xExplicitShapeSpec.UpperValue, xArraySpec[2].SizeValue); END; RULE: xExplicitShapeSpec ::= xLowerBound ':' xUpperBound COMPUTE xExplicitShapeSpec.LowerValue=xLowerBound.Value; xExplicitShapeSpec.UpperValue=xUpperBound.Value; END; RULE: xExplicitShapeSpec ::= xUpperBound COMPUTE xExplicitShapeSpec.LowerValue=MakeName("1"); xExplicitShapeSpec.UpperValue=xUpperBound.Value; END;
This macro is invoked in definition 67.
Bound list property[70]==This macro is invoked in definition 236.ArrayBounds: BoundList; "BoundList.h"
Instantiate a list of bound specifications[71]==This macro is invoked in definition 235.$/Adt/LidoList.gnrc+instance=Bound +referto=f77semantics :inst
Bound information access[72]==This macro is invoked in definition 241.typedef struct { int lower, upper, stride; } Bound; #define LowerOf(x) ((x).lower) #define UpperOf(x) ((x).upper) #define StrideOf(x) ((x).stride) extern Bound NoBound; extern Bound NewBound ELI_ARG((int lower, int upper, int stride));
Bound information[73]==This macro is invoked in definition 240.Bound NoBound = {0, 0, 0}; Bound #ifdef PROTO_OK NewBound(int lower, int upper, int stride) #else NewBound(lower, upper, stride) int lower, upper, stride; #endif { Bound temp; temp.lower = lower; temp.upper = upper; temp.stride = stride; return temp; }
Character Substring[74]==This macro is invoked in definition 48.Substring Name[75] Substring Expression[76]
Substring Name[75]==This macro is invoked in definition 74.RULE: xSubscriptTriplet ::= ':' COMPUTE xSubscriptTriplet.Index=MakeName("1"); END; RULE: xSubscriptTriplet ::= ':' xExpr COMPUTE xSubscriptTriplet.Index=MakeName("1"); END; RULE: xSubscriptTriplet ::= xExpr ':' COMPUTE xSubscriptTriplet.Index=xExpr.Value; END; RULE: xSubscriptTriplet ::= xExpr ':' xExpr COMPUTE xSubscriptTriplet.Index=xExpr[1].Value; END;
Substring Expression[76]==This macro is invoked in definition 74.RULE: xSubscriptTriplet ::= ':' xExpr COMPUTE IF(NE(xExpr.TypeCode,OilTypeIntegerType), message(ERROR,"Must be an integer expression.",0,COORDREF)); END; RULE: xSubscriptTriplet ::= xExpr ':' COMPUTE IF(NE(xExpr.TypeCode,OilTypeIntegerType), message(ERROR,"Must be an integer expression.",0,COORDREF)); END; RULE: xSubscriptTriplet ::= xExpr ':' xExpr COMPUTE IF(OR( NE(xExpr[1].TypeCode, OilTypeIntegerType), NE(xExpr[2].TypeCode, OilTypeIntegerType)), message(ERROR,"Must both be integer expressions.",0,COORDREF)); END;
Expressions[77]==Each of the next four subsections deals with one kind of expression, defining the operators that can be used in the expression, the types for literal constant operands (if applicable), and the rules governing the type consistency of the expressions.This macro is defined in definitions 77 and 78.Arithmetic Expressions[80] Character Expressions[83] Relational Expressions[86] Logical Expressions[88] Evaluation of Expressions[91] Constant Expressions[95]
This macro is invoked in definition 237.
All of the rules governing type consistency are written in OIL, the Operator Identification Language. They define an operator identification process, in which each operator indication is identified as an instance of a specific operator. Operator identification is carried out by an attribute computation described in the fifth subsection of this section.
The attribute computation is based on encodings of operators and types exported by the operator identification library:
Expressions[78]==Operator encodings are associated with the external representations of the operators by computations at the operator nodes of the tree:This macro is defined in definitions 77 and 78.ATTR TypeCode: tOilType; ATTR Indication, Operator: tOilOp;
This macro is invoked in definition 237.
Operator indication[79](¶3)==Here the first parameter specifies the class of node (xUnOp or xBinOp), the second gives the representation of the operator in the source program, and the third is the name used to represent the operator's encoding.This macro is invoked in definitions 80, 83, 86, and 88.RULE: ¶1 ::= ¶2 COMPUTE ¶1.Indication=OilOp¶3; END;
Precedence of operators is not defined here; that is a part of the phrase structure specification.
An expression is a constant expression if a value can be computed, as
indicated in the sixth subsection.
6.1 Arithmetic Expressions
There are five arithmetic operators, two of which may be either monadic or
dyadic:
Arithmetic Expressions[80]==When the operator + or - operates on a single operand, the data typs of the resulting expression is the same as the dtate type of the operand:This macro is invoked in definition 77.Operator indication[79] (`xBinOp', `'**'', `Exponentiation') Operator indication[79] (`xBinOp', `'/'', `Division') Operator indication[79] (`xBinOp', `'*'', `Multiplication') Operator indication[79] (`xBinOp', `'-'', `Subtraction') Operator indication[79] (`xUnOp', `'-'', `Negation') Operator indication[79] (`xBinOp', `'+'', `Addition') Operator indication[79] (`xUnOp', `'+'', `Identity') RULE: xExpr ::= xIcon COMPUTE xExpr.TypeCode=OilTypeIntegerType; END; RULE: xExpr ::= xUnsignedArithmeticConstant COMPUTE xExpr.TypeCode=xUnsignedArithmeticConstant.TypeCode; END;
Monadic arithmetic operators[81]==When an arithmetic operator operates on a pair of operands, the data type of the resulting expression is given in Tables 2 and 3 of the standard:This macro is invoked in definition 238.INDICATION Identity: iIdn, rIdn, dIdn, cIdn; Negation: iNeg, rNeg, dNeg, cNeg; OPER iIdn,iNeg(IntegerType): IntegerType; rIdn,rNeg(RealType): RealType; dIdn,dNeg(DoublePrecisionType): DoublePrecisionType; cIdn,cNeg(ComplexType): ComplexType;
Table 2, including replications, and Table 3[82]==The prohibited combinations in Tables 2 and 3 are prohibited here by the facts that it is impossible to coerce a double to a complex or vice-versa, and that double and complex operations require identical operand data types.This macro is invoked in definition 238.INDICATION Addition: iAdd, rAdd, dAdd, cAdd; Subtraction: iSub, rSub, dSub, cSub; Multiplication: iMul, rMul, dMul, cMul; Division: iDiv, rDiv, dDiv, cDiv; Exponentiation: iExp, riExp, diExp, ciExp, rExp, dExp, cExp; OPER iAdd,iSub,iMul,iDiv,iExp(IntegerType,IntegerType): IntegerType; rAdd,rSub,rMul,rDiv,rExp(RealType,RealType): RealType; dAdd,dSub,dMul,dDiv,dExp (DoublePrecisionType,DoublePrecisionType): DoublePrecisionType; cAdd,cSub,cMul,cDiv,cExp(ComplexType,ComplexType): ComplexType; riExp(RealType,IntegerType): RealType; diExp(DoublePrecisionType,IntegerType): DoublePrecisionType; ciExp(ComplexType,IntegerType): ComplexType; COERCION cREAL(IntegerType): RealType; cDBLE(RealType): DoublePrecisionType; cCMPLX(RealType): ComplexType COST 2;
Character Expressions[83]==The data type of a string constant is always CharacterType:This macro is defined in definitions 83 and 84.Operator indication[79] (`xBinOp', `'/' '/'', `Concatenation')
This macro is invoked in definition 77.
Character Expressions[84]==Concatenation takes character data objects and returns the same type:This macro is defined in definitions 83 and 84.RULE: xExpr ::= xScon COMPUTE xExpr.TypeCode=OilTypeCharacterType; END; RULE: xFormatIdentifier ::= xExpr xBinOp xExpr COMPUTE xBinOp.Operator= OilIdOp2(xBinOp.Indication,xExpr[1].TypeCode,xExpr[2].TypeCode); END;
This macro is invoked in definition 77.
Concatenation[85]==This macro is invoked in definition 238.INDICATION Concatenation: Cnc; OPER Cnc(CharacterType,CharacterType): CharacterType;
Relational Expressions[86]==There are no relational constants.This macro is invoked in definition 77.Operator indication[79] (`xBinOp', `'.lt.'', `Less') Operator indication[79] (`xBinOp', `'.le.'', `LessOrEqual') Operator indication[79] (`xBinOp', `'.eq.'', `Equal') Operator indication[79] (`xBinOp', `'.ne.'', `NotEqual') Operator indication[79] (`xBinOp', `'.gt.'', `Greater') Operator indication[79] (`xBinOp', `'.ge.'', `GreaterOrEqual')
All relational operators demand operands of identical type and return a logical value. Relational operators cannot be applied to logical values:
Relational operators[87]==This macro is invoked in definition 238.INDICATION Less: iLss, rLss, dLss, cLss, sLss; INDICATION LessOrEqual: iLeq, rLeq, dLeq, cLeq, sLeq; INDICATION Equal: iEql, rEql, dEql, cEql, sEql; INDICATION NotEqual: iNeq, rNeq, dNeq, cNeq, sNeq; INDICATION Greater: iGtr, rGtr, dGtr, cGtr, sGtr; INDICATION GreaterOrEqual: iGeq, rGeq, dGeq, cGeq, sGeq; OPER iLss,iLeq,iEql,iNeq,iGeq,iGtr (IntegerType,IntegerType): LogicalType; OPER rLss,rLeq,rEql,rNeq,rGeq,rGtr (RealType,RealType): LogicalType; OPER dLss,dLeq,dEql,dNeq,dGeq,dGtr (DoublePrecisionType,DoublePrecisionType): LogicalType; OPER cLss,cLeq,cEql,cNeq,cGeq,cGtr (ComplexType,ComplexType): LogicalType; OPER sLss,sLeq,sEql,sNeq,sGeq,sGtr (CharacterType,CharacterType): LogicalType;
Logical Expressions[88]==The data type of a logical constant is always LogicalType:This macro is defined in definitions 88 and 89.Operator indication[79] (`xUnOp', `'.not.'', `LogicalNegation') Operator indication[79] (`xBinOp', `'.and.'', `LogicalConjunction') Operator indication[79] (`xBinOp', `'.or.'', `LogicalInclusiveDisjunction') Operator indication[79] (`xBinOp', `'.eqv.'', `LogicalEquivalence') Operator indication[79] (`xBinOp', `'.neqv.'', `LogicalNonEquivalence')
This macro is invoked in definition 77.
Logical Expressions[89]==Logical operators demand operands of type logical and produce a result of type logical:This macro is defined in definitions 88 and 89.RULE: xExpr ::= xLogicalConstant COMPUTE xExpr.TypeCode=OilTypeLogicalType; END;
This macro is invoked in definition 77.
Logical operators[90]==This macro is invoked in definition 238.INDICATION LogicalNegation: lNeg; LogicalConjunction: lAnd; LogicalInclusiveDisjunction: lOr; LogicalEquivalence: lEqv; LogicalNonEquivalence: lNeq; OPER lNeg(LogicalType): LogicalType; lAnd,lOr,lEqv,lNeq(LogicalType,LogicalType): LogicalType;
Evaluation of Expressions[91]==The data type of an expression containing one or more operands is determined from the types of the operands, and must be compatible with the operator indication:This macro is defined in definitions 91, 92, and 93.RULE: xExpr ::= xName COMPUTE xExpr.TypeCode=GetOilType(xName.Type,OilErrorType()); END; RULE: xExpr ::= xSFVarName COMPUTE xExpr.TypeCode=GetOilType(xSFVarName.Type,OilErrorType()); END; RULE: xExpr ::= xName '(' ')' COMPUTE xExpr.TypeCode=GetOilType(xName.Type,OilErrorType()); END; RULE: xExpr ::= xComplexDataRef COMPUTE xExpr.TypeCode= GetOilType( CONSTITUENT xName.Type SHIELD xSectionSubscriptList, OilErrorType()); END; Sequence the elements[3] (`xSectionSubscript') RULE: xSectionSubscript ::= xExpr COMPUTE xSectionSubscript.Type=OilTypeName(xExpr.TypeCode); END; SYMBOL xSectionSubscript COMPUTE SYNT.Type=NoKey; END;
This macro is invoked in definition 77.
Evaluation of Expressions[92]==These computations determine the operator on the basis of the operator indication and the types of the operands, and then uses the result type of the identified operator as the type of the expression. Errors are detected when an operator cannot be identified:This macro is defined in definitions 91, 92, and 93.RULE: xExpr ::= xUnOp xExpr COMPUTE xExpr[1].TypeCode=OilGetArgType(xUnOp.Operator,0); xUnOp.Operator=OilIdOp1(xUnOp.Indication,xExpr[2].TypeCode); END; RULE: xExpr ::= xExpr xBinOp xExpr COMPUTE xExpr[1].TypeCode=OilGetArgType(xBinOp.Operator,0); xBinOp.Operator= OilIdOp2(xBinOp.Indication,xExpr[2].TypeCode,xExpr[3].TypeCode); END;
This macro is invoked in definition 77.
Evaluation of Expressions[93]==This macro is defined in definitions 91, 92, and 93.SYMBOL OpNode COMPUTE IF(NOT(OilIsValidOp(THIS.Operator)), message(ERROR,"Operator does not agree with its operand(s)",0,COORDREF)); END; SYMBOL xUnOp INHERITS OpNode END; SYMBOL xBinOp INHERITS OpNode END;
This macro is invoked in definition 77.
Complete the type lattice[94]==This macro is invoked in definition 238.SET AllTypes = [IntegerType,RealType,DoublePrecisionType,ComplexType, CharacterType, LogicalType]; COERCION Bottom(ErrorType): AllTypes;
In each case the primaries of the expression may be constants, symbolic names of constants or constant expressions enclosed in parentheses. Variable, array element, and function references are not allowed.
In this specification, all values are represented by string table indices. The absence of a value is represented by the index 0, which indexes the null string in the table. (According to Section 4.8.1 of the standard, the null string is not a valid character constant. Since only the concatenation operator is permitted in character constant expressions, there is no possibility of ambiguity.) Arithmetic values are represented by strings that obey the rules for FORTRAN real constants, except that they have no embedded spaces. Character values are represented by strings with no delimiting apostrophes, and with embedded apostrophes not doubled. The logical value .true. is represented by the string 1 and .false. is represented by the string 0.
Constant Expressions[95]==Complex constant expressions are not allowed in this implementation.This macro is defined in definitions 95 and 96.ATTR Value: int; RULE: xUnsignedArithmeticConstant ::= xIcon COMPUTE xUnsignedArithmeticConstant.Value=IdnNumb(0,xIcon); END; RULE: xUnsignedArithmeticConstant ::= xRcon COMPUTE xUnsignedArithmeticConstant.Value=xRcon; END; RULE: xUnsignedArithmeticConstant ::= xDcon COMPUTE xUnsignedArithmeticConstant.Value=xDcon; END; RULE: xLogicalConstant ::= '.true.' COMPUTE xLogicalConstant.Value=IdnNumb(0,1); END; RULE: xLogicalConstant ::= '.false.' COMPUTE xLogicalConstant.Value=IdnNumb(0,0); END; SYMBOL xUnsignedArithmeticConstant COMPUTE SYNT.Value=0; END;
This macro is invoked in definition 77.
Constant Expressions[96]==This macro is defined in definitions 95 and 96.RULE: xExpr ::= xIcon COMPUTE xExpr.Value=IdnNumb(0,xIcon); END; RULE: xExpr ::= xUnsignedArithmeticConstant COMPUTE xExpr.Value=xUnsignedArithmeticConstant.Value; END; RULE: xExpr ::= xScon COMPUTE xExpr.Value=xScon; END; RULE: xExpr ::= xName COMPUTE xExpr.Value=GetValue(xName.ObjectKey,0) <- xExpr.SymConstEval; END; RULE: xExpr ::= xUnOp xExpr COMPUTE xExpr[1].Value= IF(xExpr[2].Value, MakeName( APPLY( GetUnOpExec(OilOpName(xUnOp.Operator),NoUnOpExec), StringTable(xExpr[2].Value))), 0); END; RULE: xExpr ::= xExpr xBinOp xExpr COMPUTE xExpr[1].Value= IF(AND(xExpr[2].Value,xExpr[3].Value), ApplyStrmath( GetBinOpExec(OilOpName(xBinOp.Operator),NoBinOpExec), xExpr[2].Value, xExpr[3].Value), 0); END; SYMBOL xExpr COMPUTE SYNT.Value=0; END;
This macro is invoked in definition 77.
Indication/Evaluation function correspondence[97]==This macro is invoked in definition 236.UnOpExec: ExecUnOpFn; BinOpExec: ExecBinOpFn; iNeg -> UnOpExec={strneg}; rNeg -> UnOpExec={strneg}; dNeg -> UnOpExec={strneg}; iAdd -> BinOpExec={stradd}; rAdd -> BinOpExec={stradd}; dAdd -> BinOpExec={stradd}; iSub -> BinOpExec={strsub}; rSub -> BinOpExec={strsub}; dSub -> BinOpExec={strsub}; iMul -> BinOpExec={strmult}; rMul -> BinOpExec={strmult}; dMul -> BinOpExec={strmult}; iDiv -> BinOpExec={strdivi}; rDiv -> BinOpExec={strdivf}; dDiv -> BinOpExec={strdivf}; iExp -> BinOpExec={strpow}; riExp -> BinOpExec={strpow}; diExp -> BinOpExec={strpow}; lNeg -> UnOpExec={strnot}; lAnd -> BinOpExec={strand}; lOr -> BinOpExec={strior}; lEqv -> BinOpExec={streqv}; lNeq -> BinOpExec={strneq};
Evaluation functions[98]==This macro is defined in definitions 24, 98, 111, 167, 174, 177, and 179.char * #ifdef PROTO_OK NoUnOpExec(char *v) #else NoUnOpExec(v) char *v; #endif { return ""; } char * #ifdef PROTO_OK strneg(char *v) #else strneg(v) char *v; #endif { return strsub("0", v, 10); } char * #ifdef PROTO_OK strnot(char *v) #else strnot(v) char *v; #endif { return (*v == '0' ? "1" : "0"); } char * #ifdef PROTO_OK NoBinOpExec(char *v1, char *v2, int radix) #else NoBinOpExec(v1, v2, radix) char *v1, *v2; int radix; #endif { return ""; } char * #ifdef PROTO_OK strand(char *v1, char *v2, int radix) #else strand(v1, v2, radix) char *v1, *v2; int radix; #endif { return (*v1 == '0' ? v1 : v2); } char * #ifdef PROTO_OK strior(char *v1, char *v2, int radix) #else strior(v1, v2, radix) char *v1, *v2; int radix; #endif { return (*v1 == '1' ? v1 : v2); } char * #ifdef PROTO_OK streqv(char *v1, char *v2, int radix) #else streqv(v1, v2, radix) char *v1, *v2; int radix; #endif { return (*v1 == *v2 ? "1" : "0"); } char * #ifdef PROTO_OK strneq(char *v1, char *v2, int radix) #else strneq(v1, v2, radix) char *v1, *v2; int radix; #endif { return (*v1 != *v2 ? "1" : "0"); } int #ifdef PROTO_OK ApplyStrmath(ExecBinOpFn op, int v1, int v2) #else ApplyStrmath(op, v1, v2) ExecBinOpFn op; int v1, v2; #endif { return MakeName(op(StringTable(v1), StringTable(v2), 10)); } int #ifdef PROTO_OK LessThan(int v1, int v2) #else LessThan(v1, v2) int v1, v2; #endif { char *temp = strsub(StringTable(v1), StringTable(v2), 10); return (temp == 0 ? 1 : *temp == '-' ? 1 : 0); } int #ifdef PROTO_OK GreaterThan(int v1, int v2) #else GreaterThan(v1, v2) int v1, v2; #endif { char *temp = strsub(StringTable(v2), StringTable(v1), 10); return (temp == 0 ? 1 : *temp == '-' ? 1 : 0); }
This macro is invoked in definition 240.
Evaluation function interfaces[99]==The exponent markers for FORTRAN are E and D. In the result of a computation, the exponent markers will all be E; if a number must be output with a type-dependent exponent marker, then that must be arranged at the time of output by invoking strnorm.This macro is defined in definitions 25, 99, 110, 112, 175, 178, and 180.typedef char *(*ExecUnOpFn) ELI_ARG((char *)); typedef char *(*ExecBinOpFn) ELI_ARG((char *, char *, int)); char *NoUnOpExec ELI_ARG((char *)); char *strneg ELI_ARG((char *)); char *strnot ELI_ARG((char *)); char *NoBinOpExec ELI_ARG((char *, char *, int)); char *stradd ELI_ARG((char *, char *, int)); char *strsub ELI_ARG((char *, char *, int)); char *strmult ELI_ARG((char *, char *, int)); char *strdivi ELI_ARG((char *, char *, int)); char *strdivf ELI_ARG((char *, char *, int)); char *strpow ELI_ARG((char *, char *, int)); char *strand ELI_ARG((char *, char *, int)); char *strior ELI_ARG((char *, char *, int)); char *streqv ELI_ARG((char *, char *, int)); char *strneq ELI_ARG((char *, char *, int)); int ApplyStrmath ELI_ARG((ExecBinOpFn op, int v1, int v2)); int LessThan ELI_ARG((int v1, int v2)); int GreaterThan ELI_ARG((int v1, int v2));
This macro is invoked in definition 241.
Initialization[100]==This macro is defined in definitions 100 and 181.strmath(STRM_EXP_SYMBOLS, "EeDd");
This macro is invoked in definition 242.
Executable and Nonexecutable Statement Classification[101]==The computation of Executable above will appear in all contexts where the statement is not executable; it will be overridden in the context of executable statements by the rule computations given below.This macro is defined in definitions 101, 104, and 105.SYMBOL xLblDef: Executable: int; SYMBOL xLblDef COMPUTE INH.Executable=0; SYNT.GotExec=ResetExecutable(THIS.UnitKey,THIS.Executable); END; SYMBOL xProgramUnit COMPUTE SYNT.GotAllExecs=CONSTITUENTS xLblDef.GotExec; END;
This macro is invoked in definition 237.
Most executable statements have one of the following two forms:
Executable[102](¶1)==This macro is invoked in definition 104.RULE: xStmt ::= xLblDef ¶1 xEOS COMPUTE xLblDef.Executable=1; END;
End statement[103](¶1)==The only exceptions are the logical IF, which has no xEOS, and the terminator for a block IF, which is like and End statement but uses the keyword endif.This macro is invoked in definition 104.RULE: ¶1 ::= xLblDef 'end' xEOS COMPUTE xLblDef.Executable=1; END;
The following classification follows the list given in Section 7.1 of the standard:
Executable and Nonexecutable Statement Classification[104]==Although the ELSE IF and ELSE statements are listed in Section 7.1 as being executable, Sections 11.7.2 and 11.8.2 state that their statement labels, if any, must not be referenced by any statement. Thus they are omitted from the list above.This macro is defined in definitions 101, 104, and 105.Executable[102] (`xName '=' xExpr') Executable[102] (`xName '(' xExprList ')' '=' xExpr') Executable[102] (`xName '(' xExprList ')' xSubstringRange '=' xExpr') Executable[102] (`'assign' xLblRef 'to' xVariableName') Executable[102] (`GoToKw '(' xLblRefList ')' xExpr') Executable[102] (`GoToKw xLblRef') Executable[102] (`GoToKw xVariableName '(' xLblRefList ')'') Executable[102] (`GoToKw xVariableName') Executable[102] (`'if' '(' xExpr ')' xLblRef ',' xLblRef ',' xLblRef') RULE: xStmt ::= xLblDef 'if' '(' xExpr ')' xStmt COMPUTE xLblDef.Executable=1; END; Executable[102] (`'if' '(' xExpr ')' 'then'') RULE: xEndIfStmt ::= xLblDef 'endif' xEOS COMPUTE xLblDef.Executable=1; END; Executable[102] (`'continue'') Executable[102] (`'stop'') Executable[102] (`'stop' xIcon') Executable[102] (`'stop' xScon') Executable[102] (`'pause'') Executable[102] (`'pause' xIcon') Executable[102] (`'pause' xScon') Executable[102] (`'do' xLblRef xLoopControl') Executable[102] (`'read' xFormatIdentifier ',' xInputItemList') Executable[102] (`'read' xFormatIdentifier') Executable[102] (`'read' xIoControlSpec') Executable[102] (`'read' xIoControlSpec xInputItemList') Executable[102] (`'write' '(' xIoControlSpecList ')'') Executable[102] (`'write' '(' xIoControlSpecList ')' xOutputItemList') Executable[102] (`'print' xFormatIdentifier ',' xOutputItemList') Executable[102] (`'print' xFormatIdentifier') Executable[102] (`'rewind' '(' xIoControlSpecList ')'') Executable[102] (`'rewind' xUnitIdentifier') Executable[102] (`'backspace' '(' xIoControlSpecList ')'') Executable[102] (`'backspace' xUnitIdentifier') Executable[102] (`'endfile' '(' xIoControlSpecList ')'') Executable[102] (`'endfile' xUnitIdentifier') Executable[102] (`'open' '(' xIoControlSpecList ')'') Executable[102] (`'close' '(' xIoControlSpecList ')'') Executable[102] (`'inquire' '(' xIoControlSpecList ')'') Executable[102] (`'call' xSubroutineNameUse '(' xArgList ')'') Executable[102] (`'call' xSubroutineNameUse') Executable[102] (`'return'') Executable[102] (`'return' xExpr') End statement[103] (`xEndBlockDataStmt') End statement[103] (`xEndSubroutineStmt') End statement[103] (`xEndFunctionStmt') End statement[103] (`xEndProgramStmt')
This macro is invoked in definition 237.
A statement that has the form of a statement function must be checked semantically:
Executable and Nonexecutable Statement Classification[105]==This macro is defined in definitions 101, 104, and 105.RULE: xStmt ::= xLblDef xName xStmtFunctionRange COMPUTE xLblDef.Executable=IF(xStmtFunctionRange.InStmtFunc,0,1); END;
This macro is invoked in definition 237.
Specification Statements[106]==This macro is invoked in definition 237.DIMENSION Statement[107] EQUIVALENCE Statement[108] COMMON Statement[114] Type-Statements[118] IMPLICIT Statement[130] PARAMETER Statement[136] EXTERNAL Statement[146] INTRINSIC Statement[149]
DIMENSION Statement[107]==No specific analysis of a DIMENSION Statement is required.This macro is invoked in definition 106.RULE: xStmt ::= xLblDef 'dimension' xArrayDeclaratorList xEOS END; RULE: xArrayDeclaratorList LISTOF xArrayDeclarator END;
EQUIVALENCE Statement[108]==This macro is invoked in definition 106.RULE: xStmt ::= xLblDef 'equivalence' xEquivalenceSetList xEOS END; RULE: xEquivalenceSetList LISTOF xEquivalenceSet END; ATTR Point: EquivPoint; RULE: xEquivalenceSet LISTOF xEquivalenceObject COMPUTE xEquivalenceSet.Point= CONSTITUENTS xEquivalenceObject.Point WITH (EquivPoint,MakeEquiv,IDENTICAL,NoEquivPoint); END; RULE: xEquivalenceObject ::= xVariable COMPUTE xEquivalenceObject.Point= NewEquivPoint(CONSTITUENT xVariableName.UnitKey,xVariable.Index,COORDREF) <- INCLUDING xProgramUnit.GotAllCommon; END; RULE: xVariable ::= xVariableName '(' Subscripts ')' COMPUTE xVariable.Index=Subscripts.Index; END; RULE: xVariable ::= xVariableName '(' Subscripts ')' xSubstringRange COMPUTE xVariable.Index= ApplyStrmath(stradd, Subscripts.Index, ApplyStrmath(strsub, xSubstringRange CONSTITUENT xSubscriptTriplet.Index SHIELD xSubscriptTriplet, MakeName("1"))); END; SYMBOL xVariable COMPUTE SYNT.Index=MakeName("1"); END;
Properties for equivalence analysis[109]==This macro is invoked in definition 236.Parent: DefTableKey; Offset: int;
Evaluation function interfaces[110]==This macro is defined in definitions 25, 99, 110, 112, 175, 178, and 180.typedef struct { DefTableKey var; int index; CoordPtr loc; } EquivPoint; #define NoEquivPoint() NewEquivPoint(NoKey,0,NoPosition)
This macro is invoked in definition 241.
Evaluation functions[111]==This macro is defined in definitions 24, 98, 111, 167, 174, 177, and 179.EquivPoint #ifdef PROTO_OK NewEquivPoint(DefTableKey var, int index, CoordPtr loc) #else NewEquivPoint(var, index, loc) DefTableKey var; int index; CoordPtr loc; #endif { EquivPoint temp; temp.var = var; temp.index = index; temp.loc = loc; if (var != NoKey && GetBlockIn(var,NoKey) == NoKey) { DefTableKey leader = NewKey(); ResetStorageUnits(leader,GetStorageUnits(var,0)); ResetBlockIn(var,leader); } return temp; } static void #ifdef PROTO_OK CompressEquivPath(DefTableKey var) #else CompressEquivPath(var) DefTableKey var; #endif { DefTableKey temp, leader; int offset = MakeName("0"); for (temp=GetBlockIn(var,NoKey); temp!=NoKey; temp=GetParent(temp,NoKey)) { EquivStackPush(var); var = temp; } leader = var; while (!EquivStackEmpty) { var = EquivStackPop; if (!EquivStackEmpty) ResetParent(var,leader); else ResetBlockIn(var,leader); offset = ApplyStrmath(stradd,offset,GetOffset(var,MakeName("0"))); ResetOffset(var,offset); } } EquivPoint #ifdef PROTO_OK MakeEquiv(EquivPoint p1, EquivPoint p2) #else MakeEquiv(p1, p2) EquivPoint p1, p2; #endif { int offset1, offset2, diff, p1size, p2size; DefTableKey temp, lead1, lead2; if (p1.var == NoKey) return p2; if (p2.var == NoKey) return p1; CompressEquivPath(p1.var); lead1 = GetBlockIn(p1.var,NoKey); offset1 = ApplyStrmath(stradd,p1.index,GetOffset(p1.var,MakeName("0"))); CompressEquivPath(p2.var); lead2 = GetBlockIn(p2.var,NoKey); offset2 = ApplyStrmath(stradd,p2.index,GetOffset(p2.var,MakeName("0"))); if (lead1 == lead2 && offset1 != offset2) { message(ERROR,"Inconsistent equivalence",0,p2.loc); return p1; } if (InIS(CommonBlock,GetKindSet(lead1,NullIS()))) { if (InIS(CommonBlock,GetKindSet(lead2,NullIS()))) { message(ERROR,"Equivalences different common blocks",0,p2.loc); return p1; } diff = ApplyStrmath(strsub,offset1,offset2); if ((StringTable(diff))[0] == '-') { message(ERROR,"Equivalence changes common origin",0,p2.loc); return p1; } } else if (InIS(CommonBlock,GetKindSet(lead2,NullIS()))) { DefTableKey td; int ti; diff = ApplyStrmath(strsub,offset2,offset1); if ((StringTable(diff))[0] == '-') { message(ERROR,"Equivalence changes common origin",0,p2.loc); return p1; } td = lead1; lead1 = lead2; lead2 = td; ti = offset1; offset1 = offset2; offset2 = ti; } else { DefTableKey td; int ti; diff = ApplyStrmath(strsub,offset1,offset2); if ((StringTable(diff))[0] == '-') { diff = MakeName(StringTable(diff)+1); td = lead1; lead1 = lead2; lead2 = td; ti = offset1; offset1 = offset2; offset2 = ti; } } ResetParent(lead2,lead1); ResetOffset(lead2,diff); p1size = GetStorageUnits(lead1,0); p2size = ApplyStrmath(stradd,diff,GetStorageUnits(lead2,0)); if (LessThan(p1size,p2size)) ResetStorageUnits(lead1,p2size); return p1; }
This macro is invoked in definition 240.
Evaluation function interfaces[112]==This macro is defined in definitions 25, 99, 110, 112, 175, 178, and 180.extern EquivPoint NewEquivPoint ELI_ARG((DefTableKey, int, CoordPtr)); extern EquivPoint MakeEquiv ELI_ARG((EquivPoint, EquivPoint));
This macro is invoked in definition 241.
Instantiate the equivalence stack module[113]==This macro is invoked in definition 235.$/Adt/Stack.gnrc +instance=Equiv +referto=DefTableKey :inst
COMMON Statement[114]==This macro is invoked in definition 106.Form of a COMMON Statement[115] Common Block Storage Sequence[116]
In each COMMON statement, the xCommonBlockObjects following a xCommonBlockName are declared to be in that common block. All xCommonBlockObjects preceding the first xCommonBlockName are declared to be in blank common.
Any xCommonBlockName or omitted xCommonBlockName for blank common may occur more than once in one or more COMMON statements in a program unit. The xCommonBlockObjects following each successive appearance of the same xCommonBlockName are treated as a continuation of the list for that common block name.
The chain CommonKey embodies these conditions.
Form of a COMMON Statement[115]==This macro is invoked in definition 114.SYMBOL xProgramUnit: BlankCommonKey: DefTableKey; CHAIN CommonKey: DefTableKey; SYMBOL xProgramUnit COMPUTE SYNT.BlankCommonKey=NewKey(); CHAINSTART HEAD.CommonKey=SYNT.BlankCommonKey; SYNT.GotAllCommon=TAIL.CommonKey; END; RULE: xStmt ::= xLblDef 'common' xComlist xEOS COMPUTE xComlist.CommonKey= INCLUDING xProgramUnit.BlankCommonKey <- xStmt.CommonKey; END; RULE: xComlist LISTOF xComblock | xCommonBlockObject END; RULE: xComblock ::= '/' '/' COMPUTE xComblock.CommonKey= INCLUDING xProgramUnit.BlankCommonKey <- xComblock.CommonKey; END; RULE: xComblock ::= '/' xCommonBlockName '/' COMPUTE xComblock.CommonKey=xCommonBlockName.UnitKey <- xComblock.CommonKey; END;
Common Block Storage Sequence[116]==This macro is invoked in definition 114.ATTR PreviousSize: int; SYMBOL xCommonBlockObject COMPUTE SYNT.PreviousSize=GetBlockSize(THIS.CommonKey,MakeName("0")); THIS.CommonKey= ORDER( ResetBlockIn(CONSTITUENT xVariableName.UnitKey,THIS.CommonKey), ResetOffset(CONSTITUENT xVariableName.UnitKey,SYNT.PreviousSize), ResetBlockSize( THIS.CommonKey, ApplyStrmath(stradd, SYNT.PreviousSize, GetStorageUnits( CONSTITUENT xVariableName.UnitKey, SizeOfType(CONSTITUENT xVariableName.Type)) <- INCLUDING xProgramUnit.GotAllStorageUnits)), THIS.CommonKey); END;
Properties for Common Block Storage Sequence[117]==This macro is invoked in definition 236.BlockIn: DefTableKey; BlockSize: int;
Type-Statements[118]==IsType is a library access function that will change the Type property of THIS.UnitKey if it differs from INCLUDING xEntityDeclList.Type. If no type property has been set for THIS.UnitKey, then IsType will set the value of that property to INCLUDING xEntityDeclList.Type.This macro is defined in definitions 118, 121, 123, and 124.ATTR Type: DefTableKey; RULE: xStmt ::= xLblDef xTypeSpec xEntityDeclList xEOS COMPUTE xEntityDeclList.Type=xTypeSpec.Type; END; RULE: xEntityDeclList LISTOF xEntityDecl END; Type specified in type-statement as[138] (`INCLUDING xEntityDeclList.Type') Arithmetic and LOGICAL Type Statements[125] CHARACTER Type Statements[126]
This macro is invoked in definition 106.
Properties for type analysis[119]==This macro is defined in definitions 43 and 119.Type: DefTableKey [Is];
This macro is invoked in definition 236.
Set xTypeSpec.Type[120](¶2)==Within a program unit, a name must not have its type explicitly specified more than once.This macro is invoked in definition 125.RULE: xTypeSpec ::= '¶1' COMPUTE xTypeSpec.Type=¶2; xTypeSpec.Length=0; END;
Type-Statements[121]==This macro is defined in definitions 118, 121, 123, and 124.Report multiple[33] (`xObjectName', `type')
This macro is invoked in definition 106.
Properties supporting multiple definition reporting[122]==Only a constant, variable, array, external function or statement function may appear in a type statement. (The name of a main program, subroutine, or block data subprogram is disallowed.)This macro is defined in definitions 35, 50, 122, 137, 148, and 150.typeApp: int;
This macro is invoked in definition 236.
Type-Statements[123]==A type statement may confirm the type of an intrinsic function, but not change it:This macro is defined in definitions 118, 121, 123, and 124.SYMBOL xObjectName COMPUTE IF( DisjIS( GetKindSet(THIS.UnitKey,SingleIS(Variable)), ConsIS(Constant, ConsIS(Variable, ConsIS(Array, ConsIS(ExternalFunction, ConsIS(IntrinsicFunction, ConsIS(StatementFunction,NullIS()))))))), message(ERROR,"This class of symbolic name cannot be typed",0,COORDREF)) <- INCLUDING xProgramUnit.ClassificationDone; END;
This macro is invoked in definition 106.
Type-Statements[124]==This macro is defined in definitions 118, 121, 123, and 124.SYMBOL xObjectName COMPUTE IF( AND( GetIntrinsic(THIS.ObjectKey,0), NE(GetType(THIS.UnitKey,NoKey),GetType(THIS.ObjectKey,NoKey))), message(ERROR,"Cannot change the type of an intrinsic function",0,COORDREF)) <- INCLUDING xProgramUnit.GotAllTypes; END;
This macro is invoked in definition 106.
Arithmetic and LOGICAL Type Statements[125]==This macro is defined in definitions 125.Set xTypeSpec.Type[120] (`integer', `IntegerType') Set xTypeSpec.Type[120] (`real', `RealType') Set xTypeSpec.Type[120] (`doubleprecision', `DoublePrecisionType') Set xTypeSpec.Type[120] (`complex', `ComplexType') Set xTypeSpec.Type[120] (`logical', `LogicalType')
This macro is invoked in definition 118.
CHARACTER Type Statements[126]==A xCharLength must be an unsigned, nonzero integer constant, an integer constant expression with a positive value, or and asterisk. Since a specific value must be positive, we use the value 0 to indicate an asterisk.This macro is defined in definitions 126, 127, 128, and 129.ATTR Length: int; RULE: xStmt ::= xLblDef xTypeSpec xEntityDeclList xEOS COMPUTE xEntityDeclList.Length=xTypeSpec.Length; END; RULE: xTypeSpec ::= 'character' COMPUTE xTypeSpec.Type=CharacterType; xTypeSpec.Length=MakeName("1"); END; RULE: xTypeSpec ::= 'character' xCharSelector COMPUTE xTypeSpec.Type=CharacterType; xTypeSpec.Length=xCharSelector.Length; END; RULE: xCharSelector ::= '*' xCharLength COMPUTE xCharSelector.Length=xCharLength.Length; END;
This macro is invoked in definition 118.
CHARACTER Type Statements[127]==A length immediately following the word CHARACTER is the length specification for each entity in the statement not having its own length specification. A length specification immediately following an entity is the length specification for only that entity.This macro is defined in definitions 126, 127, 128, and 129.RULE: xCharLength ::= xIcon COMPUTE xCharLength.Length=IdnNumb(0,xIcon); IF(EQ(xIcon,0), message(ERROR,"Positive length expected",0,COORDREF)); END; RULE: xCharLength ::= '(' xTypeParamValue ')' COMPUTE xCharLength.Length=xTypeParamValue.Value; IF(AND(xTypeParamValue.Value,LessThan(xCharLength.Length,MakeName("1"))), message(ERROR, "Positive length expected", 0, COORDREF)); END; RULE: xTypeParamValue ::= xExpr COMPUTE xTypeParamValue.Value=xExpr.Value; IF(NE(xExpr.TypeCode,OilTypeIntegerType), message(ERROR,"Length must be an integer",0,COORDREF)); IF(NOT(xExpr.Value), message(ERROR,"Length must be constant",0,COORDREF)); END; RULE: xTypeParamValue ::= '*' COMPUTE xTypeParamValue.Value=0; END;
This macro is invoked in definition 118.
CHARACTER Type Statements[128]==An entity declared in a CHARACTER statement must have a nonzero length unless that entity is an external function, a dummy argument of an external procedure, or a character constant that has a symbolic name.This macro is defined in definitions 126, 127, 128, and 129.RULE: xEntityDecl ::= xObjectName COMPUTE xEntityDecl.Length=INCLUDING xEntityDeclList.Length; xEntityDecl.GotLength=ResetLength(xObjectName.UnitKey,xEntityDecl.Length); END; RULE: xEntityDecl ::= xObjectName '(' DimensionDeclarators ')' COMPUTE xEntityDecl.Length=INCLUDING xEntityDeclList.Length; xEntityDecl.GotLength=ResetLength(xObjectName.UnitKey,xEntityDecl.Length); END; RULE: xEntityDecl ::= xObjectName '*' xCharLength COMPUTE xEntityDecl.Length=xCharLength.Length; xEntityDecl.GotLength=ResetLength(xObjectName.UnitKey,xEntityDecl.Length); END; RULE: xEntityDecl ::= xObjectName '(' DimensionDeclarators ')' '*' xCharLength COMPUTE xEntityDecl.Length=xCharLength.Length; xEntityDecl.GotLength=ResetLength(xObjectName.UnitKey,xEntityDecl.Length); END; SYMBOL xProgramUnit COMPUTE SYNT.GotAllLengths= CONSTITUENTS (xEntityDecl.GotLength,xImplicitSpec.GotLength); END;
This macro is invoked in definition 118.
CHARACTER Type Statements[129]==This macro is defined in definitions 126, 127, 128, and 129.ATTR Class: IntSet; RULE: xEntityDecl ::= xObjectName COMPUTE xEntityDecl.Class= GetKindSet(xObjectName.UnitKey,NullIS()) <- xEntityDecl.Order; END; RULE: xEntityDecl ::= xObjectName '(' DimensionDeclarators ')' COMPUTE xEntityDecl.Class= GetKindSet(xObjectName.UnitKey,NullIS()) <- xEntityDecl.Order; END; RULE: xEntityDecl ::= xObjectName '*' xCharLength COMPUTE xEntityDecl.Class= GetKindSet(xObjectName.UnitKey,NullIS()) <- xEntityDecl.Order; END; RULE: xEntityDecl ::= xObjectName '(' DimensionDeclarators ')' '*' xCharLength COMPUTE xEntityDecl.Class= GetKindSet(xObjectName.UnitKey,NullIS()) <- xEntityDecl.Order; END; SYMBOL xEntityDecl COMPUTE IF( AND( AND(EQ(INCLUDING xEntityDeclList.Type,CharacterType),EQ(THIS.Length,0)), EmptyIS( InterIS( THIS.Class, ConsIS(ExternalFunction, ConsIS(DummyArgument, ConsIS(Constant, NullIS())))))), message(ERROR,"A length must be specified",0,COORDREF)); END;
This macro is invoked in definition 118.
IMPLICIT Statement[130]==This macro is defined in definitionsRULE: xImplicitSpec ::= xTypeSpec xImpl COMPUTE xImplicitSpec.ImplicitTyping= ImplicitType(xTypeSpec.Type,xImpl,COORDREF) <- xImplicitSpec.ImplicitTyping; xImplicitSpec.GotLength=ImplicitLength(xTypeSpec.Length,xImpl); END;