home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / p / pascal-.zip / pascal- / specs / Type.fw < prev   
Text File  |  1993-01-05  |  40KB  |  1,118 lines

  1. @=~
  2.  
  3. ~A~<Type Analysis~>
  4.  
  5. The purpose of type analysis is to determine what kind of object is
  6. represented by each name and what type of value each expression yields,
  7. and to verify that these satisfy the context conditions of the source language.
  8. Errors of agreement, such as use of a type name as an expression operand or
  9. use of an integer value to control an if-statement, are detected and
  10. reported during type analysis.
  11.  
  12. Type analysis is an attribution process.
  13. Given the ~{Key~} attributes resulting from the consistent renaming,
  14. it establishes a ~{Kind~} property for each object and specific additional
  15. properties for each type.
  16. It also defines a ~{Type~} attribute for each tree node that describes a
  17. construct yielding a value.
  18.  
  19. ~B
  20.  
  21. A Pascal- object belongs to one of seven classes:
  22.  
  23. ~$~<Kinds of objects~>==~{
  24. #define Undefined    0
  25. #define Typex        1
  26. #define Procedurex    2
  27. #define Constantx    3
  28. #define Variable    4
  29. #define ValueParameter    5
  30. #define VarParameter    6
  31. ~}
  32.  
  33. This classification is useful because it distinguishes objects that have
  34. very different characteristics.
  35. Nothing is known about an ~{Undefined~} object, and therefore the compiler
  36. should assume whatever characteristics are necessary in the context in
  37. which it appears.
  38. ~{Typex~} and ~{Procedurex~} objects are allowed only in specific contexts
  39. defined by the grammar.
  40. The remaining objects are all valid in expression contexts, but the code
  41. that must be generated to implement them varies.
  42. By grouping them as shown, a simple test can determine whether the context
  43. conditions are satisfied.
  44.  
  45. Brinch-Hansen distinguishes eleven object classes, dividing the ~{Typex~}
  46. class into standard types, array types and record types, dividing the
  47. ~{Procedurex~} class into standard procedures and user-defined procedures,
  48. and adding a class for record fields.
  49. The reason he needs this finer classification is that he defines a
  50. variant record to store all of the necessary information about each object,
  51. and uses the object class to distinguish variants.
  52. As we shall see, the information needed to describe an array type is
  53. somewhat different from the information needed to describe a standard type
  54. or record type.
  55. Therefore these two variants must be distinguished, and Brinch-Hansen needs
  56. distinct classes to make that distinction.
  57.  
  58. An Eli-generated compiler stores information about objects in a
  59. ~{definition table~}, which is a global database accessed by keys
  60. associated with each object.
  61. Each item of information is stored as a named ~/property~/ of arbitrary
  62. type.
  63. The property name and type must be declared.
  64. Here is a declaration of the ~{Kind~} property, of type ~{int~}, that will
  65. be defined for every object:
  66.  
  67. ~$~<The object classification property~>==~{
  68. Kind: int;
  69. ~}
  70.  
  71. For every property name, Eli creates two definition table operations.
  72. One operation (~{Get~}) is used to query the definition table,
  73. the other (~{Set~}) to update it.
  74. Thus the declaration of the ~{Kind~} property causes Eli to create the
  75. query operation ~{GetKind~} and the update operation ~{SetKind~}.
  76. Both operations take the key of the object of interest as their first
  77. argument.
  78. The second argument of the query operation ~{GetKind~} is the so-called
  79. ~/default value~/ for this query: if the object of interest does not have
  80. the ~{Kind~} property set, then ~{GetKind~} returns the value
  81. of its second argument.
  82. ~{SetKind~} has two arguments in addition to the key.
  83. The first is the value to which the ~{Kind~} property should be set if the
  84. object of interest currently has no ~{Kind~} property set; the second is
  85. the value to which the ~{Kind~} property should be changed if the object of
  86. interest currently has a ~{Kind~} property set.
  87.  
  88. Because Pascal- requires definition before use, we can obtain all of the
  89. properties of declared objects in a single text-order traversal of the tree.
  90. For this purpose, we define a chain ~{Objects~} to represent the invariant
  91. ``all visible objects have their properties defined''.
  92. Since the standard names are visible everywhere, this invariant is
  93. initially true when all properties of the standard names have been set:
  94.  
  95. ~$~<Text-order traversal invariant~>==~{
  96. CHAIN Objects: VOID;
  97.  
  98. SYMBOL StandardBlock COMPUTE
  99.   CHAINSTART HEAD.Objects=StandardIdProperties() DEPENDS_ON THIS.Env;
  100. END;
  101. ~}
  102.  
  103. ~B
  104.  
  105. Every object that yields a value has a property that specifies the type of
  106. the value yielded.
  107. Since a type is itself an object, with properties of its own,
  108. it is represented by a definition table key:
  109.  
  110. ~$~<Types~>==~{
  111. Type: DefTableKey;
  112. ~}
  113.  
  114. Each of the standard types ~{boolean~} and ~{integer~} is represented by an
  115. object of kind ~{Typex~}.
  116. No properties other than the ~{Kind~} are required of standard types by the
  117. type analyzer.
  118. The ~{Kind~} property is set using the update operation ~{SetKind~} that
  119. was created by Eli in response to the property declaration.
  120. This operation must be invoked as a part of the implementation of
  121. the ~{StandardIdProperties~} operation introduced in the last section:
  122.  
  123. ~$~<Set properties of standard names~>+=~{
  124.   SetKind(IntegerKey,Typex,Undefined);
  125.   SetKind(BooleanKey,Typex,Undefined);
  126. ~}
  127.  
  128. ~C
  129.  
  130. New types can be defined by the user.
  131. A type definition constructs either a new array type or a new record type,
  132. but in each case provides a definition table key to represent the
  133. constructed type:
  134.  
  135. ~$~<Type declaration~>==~{
  136. SYMBOL NewType: Key: DefTableKey;
  137.  
  138. RULE UserType: TypeDefinition ::= TypeNameDef '=' NewType ';'
  139. COMPUTE
  140.   NewType.Key=TypeNameDef.Key;
  141.   NewType.Objects=
  142.     SetKind(TypeNameDef.Key,Typex,Undefined)
  143.     DEPENDS_ON TypeDefinition.Objects;
  144. END;
  145. ~}
  146.  
  147. The specific properties of the constructed type depend on whether it is an
  148. array or a record, and will be discussed below.
  149. These properties will be stored in the database under the key of the type
  150. name, which is made available as the ~{Key~} attribute of ~{NewType~}.
  151.  
  152. Recall that the ~{Objects~} attribute is a chain representing the
  153. assertion ``all visible objects have their properties defined''.
  154. Rule ~{UserType~} therefore asserts that all objects visible at the
  155. beginning of the ~{NewType~} phrase have their properties defined if
  156. that assertion holds before the type definition, and if the ~{Kind~} property
  157. of the type object itself has been set.
  158. In this case all of the ~/known~/ properties are set, but some of the
  159. properties are not known until after the ~{NewType~} phrase has been
  160. processed.
  161. Thus rule ~{UserType~} cannot guarantee the truth of the assertion
  162. to the right of the ~{TypeDefinition~} phrase.
  163.  
  164. ~C
  165.  
  166. The symbol ~{TypeNameUse~} represents a context in which a type name
  167. is required.
  168. The interesting information carried by that name is its type
  169. property, which is delivered to the context as the ~{Type~} attribute of
  170. the ~{TypeNameUse~} node.
  171.  
  172. ~$~<Type name use~>==~{
  173. SYMBOL TypeNameUse: Type: DefTableKey;
  174.  
  175. SYMBOL TypeNameUse COMPUTE
  176.   SYNT.Type=
  177.     IF(EQ(GetKind(THIS.Key,Undefined),Typex),THIS.Key,NoKey)
  178.     DEPENDS_ON THIS.VisibleTypeProperties;
  179.   IF(NE(GetKind(THIS.Key,Typex),Typex),
  180.     Message(FATAL,"Must be a type name"))
  181.     DEPENDS_ON THIS.VisibleTypeProperties;
  182. END;
  183. ~}
  184.  
  185. ~{VisibleTypeProperties~} asserts that all type names
  186. visible at this point have their properties defined.
  187. Note that ~{VisibleTypeProperties~} differs from ~{Objects~}, which asserts
  188. that ~/all~/ visible names (not merely type names)
  189. have their properties defined.
  190. To see the need for ~{VisibleTypeProperties~}, consider the Pascal-
  191. construct ~{var a, b, c: T;~}.
  192. The Pascal- compiler computes properties in textual order.
  193. But the type represented by ~{T~} is one of the properties of the names
  194. ~{a~}, ~{b~} and ~{c~}.
  195. Therefore the ~{TypeNameUse~} ~{T~} must have its ~{Type~} property set
  196. ~/before~/ all visible names (which include ~{a~}, ~{b~} and ~{c~}!)
  197. have their properties defined.
  198. Section 7.4.1 shows how the assertion ~{VisibleTypeProperties~} is
  199. established for the construct ~{var a, b, c: T;~}.
  200.  
  201. If the name appearing in this context is not a type name
  202. then the ~{Type~} attribute will get the value ~{NoKey~},
  203. used to represent an unknown type.
  204. ~{NoKey~} is a distinguished definition table key that can never have any
  205. properties.
  206. Definition table query operations applied to ~{NoKey~} always yield their
  207. default values, and definition table update operations applied to ~{NoKey~}
  208. have no effect.
  209.  
  210. The decisions in the ~{TypeNameUse~} symbol computation illustrate the
  211. utility of a distinct default value for each invocation of a query
  212. operation.
  213. When establishing the value of the ~{Type~} attribute, both an undefined
  214. name and an name of the wrong class should yield ~{NoKey~}
  215. because in either case the type is unknown.
  216. An error, on the other hand, should be reported only if the name is
  217. defined but has the wrong class.
  218. If the name is not defined, that was a violation of the scope rules
  219. and has already been reported.
  220. A report that the name must be a type name would be wrong
  221. because the compiler does not know that the name in question isn't a
  222. type name -- it simply has no information about that name's
  223. meaning.
  224.  
  225. ~B
  226.  
  227. A constant yields a value, and therefore has a ~{Type~} property in
  228. addition to the ~{Kind~} property common to all objects.
  229. Because one of the context conditions verified by type analysis is that the
  230. lower bound of an array does not exceed the upper bound,
  231. and because bounds can be specified by constant names,
  232. the actual value of a constant must also be provided as one of its properties:
  233.  
  234. ~$~<Constants~>==~{
  235. Value: int;
  236. ~}
  237.  
  238. There are two pre-defined constant names, ~{true~} and ~{false~}.
  239. Their properties must be set as a part of the implementation of
  240. the ~{StandardIdProperties~} operation:
  241.  
  242. ~$~<Set properties of standard names~>+=~{
  243.   SetKind(FalseKey,Constantx,Undefined);
  244.   SetType(FalseKey,BooleanKey,NoKey);
  245.   SetValue(FalseKey,0,0);
  246.   SetKind(TrueKey,Constantx,Undefined);
  247.   SetType(TrueKey,BooleanKey,NoKey);
  248.   SetValue(TrueKey,1,0);
  249. ~}
  250.  
  251. Notice that, although ~{false~} and ~{true~} are Boolean constants,
  252. they are given integer values.
  253. Integer values are needed because ~{false~} and ~{true~}
  254. are legal array bounds.
  255. Brinch-Hansen does not discuss the integer values to be provided, but in
  256. Figure 7.2 of his book he shows ~{false~} with the value ``0''.
  257. The complete compiler listing he gives in Appendix A.3 sets the values of
  258. the Boolean constants to their Pascal ordinal values, which are defined by
  259. the Pascal standard to be ``0'' for ~{false~} and ``1'' for ~{true~}, so
  260. those are the settings used here.
  261.  
  262. ~C
  263.  
  264. Constant objects are created by the user via a constant declaration:
  265.  
  266. ~$~<Constant declaration~>==~{
  267. RULE ConstDef: ConstantDefinition ::= ConstantNameDef '=' Constant ';'
  268. COMPUTE
  269.   ConstantDefinition.Objects=
  270.     ORDER(
  271.       SetKind(ConstantNameDef.Key,Constantx,Undefined),
  272.       SetType(ConstantNameDef.Key,Constant.Type,NoKey),
  273.       SetValue(ConstantNameDef.Key,Constant.Value,NoKey))
  274.     DEPENDS_ON ConstantDefinition.Objects;
  275. END;
  276. ~}
  277.  
  278. This rule asserts that all visible objects have their properties
  279. defined after the constant definition if that assertion holds before the
  280. constant definition, and if the ~{Kind~}, ~{Type~} and ~{Value~} properties
  281. of the constant definition itself have been set.
  282. The use of ~{ORDER~} is a slight overspecification because the
  283. property values do not have to be set in any particular order.
  284. ~{ORDER~} is being used here simply to group the update operations into a
  285. single action asserting that the properties of the constant object have
  286. been set.
  287.  
  288. ~C
  289.  
  290. When a constant is used, the type and value of that constant are determined
  291. from the constant's properties and delivered to the surrounding context as
  292. attribute values.
  293. If the constant is an integer denotation, then its type and value are
  294. computed directly; if it is a constant name they are obtained from
  295. that name's properties:
  296.  
  297. ~$~<Constant name use~>==~{
  298. ATTR Type: DefTableKey;
  299. ATTR Value: int;
  300.  
  301. RULE IntConst: Constant ::= Numeral
  302. COMPUTE
  303.   Constant.Type=IntegerKey;
  304.   Constant.Value=Numeral.Value;
  305. END;
  306.  
  307. RULE IdnConst: Constant ::= ConstantNameUse
  308. COMPUTE
  309.   Constant.Type=
  310.     GetType(ConstantNameUse.Key,NoKey) DEPENDS_ON Constant.Objects;
  311.   Constant.Value=
  312.     GetValue(ConstantNameUse.Key,0) DEPENDS_ON Constant.Objects;
  313.   IF(NE(GetKind(ConstantNameUse.Key,Constantx),Constantx),
  314.     Message(FATAL,"Constant name required"))
  315.     DEPENDS_ON Constant.Objects;
  316. END;
  317. ~}
  318.  
  319. Rule ~{IdnConst~} demonstrates that
  320. the assertion that all visible objects have their properties defined
  321. is a precondition for the process of accessing the properties
  322. of a named constant.
  323. Unless that assertion is true, there is no guarantee that the definition
  324. table contains valid property values for the object.
  325.  
  326. Brinch-Hansen's Algorithm 7.1 must verify that the name is a constant
  327. name before accessing the property values, in order to ensure that
  328. they are defined.
  329. If the name is ~/not~/ a constant, he then must establish appropriate
  330. attribute values with a completely separate set of assignments.
  331. Here the fact that the two query operations ~{GetType~} and ~{GetValue~}
  332. each provide a default value allow us to handle the possibility that the
  333. name is not a constant without any additional mechanism.
  334.  
  335. ~B
  336.  
  337. In Pascal- variables and parameters are very similar in their behavior.
  338. All yield values, and therefore have a ~{Type~} property in
  339. addition to the ~{Kind~} property common to all objects.
  340. They are defined in groups, with all names in a groups having the same
  341. kind and type properties.
  342. Finally, a ~{VariableNameUse~} could actually be a use of a constant name,
  343. a variable name or a parameter name.
  344.  
  345. ~$~<Variables~>==~{
  346. ATTR Kind: int;
  347. ATTR Type: DefTableKey;
  348.  
  349. ~<Variable definitions~>
  350. ~<Parameter definitions~>
  351. ~<Constant, variable or parameter use~>
  352. ~}
  353.  
  354. ~C
  355.  
  356. Type is a characteristic of each group of variable names,
  357. a fact indicated by attaching the attribute ~{Type~} to ~{VariableDefinition~}.
  358. A remote attribute access (~{INCLUDING~}) is used to make it available
  359. at each individual variable name definition.
  360. Notice that the remote attribute access abstracts from the details of the
  361. tree structure, requiring only that a ~{VariableNameDef~} node be a
  362. descendent of a ~{VariableDefinition~} node.
  363.  
  364. ~$~<Variable definitions~>==~{
  365. RULE VarType: VariableDefinition ::= VariableNameDefList ':' TypeNameUse ';'
  366. COMPUTE
  367.   VariableDefinition.Type=TypeNameUse.Type;
  368.   TypeNameUse.VisibleTypeProperties=VariableDefinition.Objects;
  369. END;
  370.  
  371. SYMBOL VariableNameDef COMPUTE
  372.   THIS.Objects=
  373.     ORDER(
  374.       SetKind(THIS.Key,Variable,Undefined),
  375.       SetType(THIS.Key,INCLUDING VariableDefinition.Type,NoKey))
  376.     DEPENDS_ON THIS.Objects;
  377. END;
  378. ~}
  379.  
  380. Recall from Section 7.2 that the ~{VisibleTypeProperties~} attribute of
  381. ~{TypeNameUse~} asserts that all type names
  382. visible at this point have their properties defined.
  383. That assertion is true if ~/all~/ names visible at the beginning of
  384. the ~{VariableDefinition~} phrase have their properties defined
  385. (~{VariableDefinition.Objects~}), because no new type names
  386. become visible within the ~{VariableNameDefList~} phrase.
  387.  
  388. ~C
  389.  
  390. Parameters are declared in much the same way as variables, except that the
  391. classification of the parameter (as well as its type) is characteristic
  392. of the group rather than being fixed.
  393. Two attributes, ~{Kind~} and ~{Type~}, are therefore attached to
  394. ~{ParameterDefinition~} and accessed remotely by the computations
  395. associated with ~{ParameterNameDef~} nodes.
  396.  
  397. ~$~<Parameter definitions~>==~{
  398. RULE ValParmDef:
  399.   ParameterDefinition ::= ParameterNameDefList ':' TypeNameUse
  400. COMPUTE
  401.   ParameterDefinition.Kind=ValueParameter;
  402.   ParameterDefinition.Type=TypeNameUse.Type;
  403.   TypeNameUse.VisibleTypeProperties=ParameterDefinition.Objects;
  404. END;
  405.  
  406. RULE VarParmDef:
  407.   ParameterDefinition ::= 'var' ParameterNameDefList ':' TypeNameUse
  408. COMPUTE
  409.   ParameterDefinition.Kind=VarParameter;
  410.   ParameterDefinition.Type=TypeNameUse.Type;
  411.   TypeNameUse.VisibleTypeProperties=ParameterDefinition.Objects;
  412. END;
  413.  
  414. SYMBOL ParameterNameDef COMPUTE
  415.   THIS.Objects=
  416.     ORDER(
  417.       SetKind(THIS.Key,INCLUDING ParameterDefinition.Kind,Undefined),
  418.       SetType(THIS.Key,INCLUDING ParameterDefinition.Type,NoKey))
  419.     DEPENDS_ON THIS.Objects;
  420. END;
  421. ~}
  422.  
  423. ~C
  424.  
  425. Variable and parameter names are used in the same context: the name
  426. component of a ~{VariableAccess~} phrase.
  427. (Constant names can also appear in this context, as well as in other
  428. contexts.)
  429. The integer values used in the object classification scheme are chosen so
  430. that a single test suffices to differentiate constants, variables and
  431. parameters from types and procedures.
  432.  
  433. Because a ~{VariableAccess~} phrase describes a construct that yields a
  434. value, it has a ~{Type~} attribute.
  435. It also has a ~{Kind~} attribute to permit the compiler to verify that (for
  436. example) a constant does not appear on the left-hand side of an
  437. assignment.
  438.  
  439. ~$~<Constant, variable or parameter use~>==~{
  440. RULE VarIdn: VariableAccess ::= VariableNameUse
  441. COMPUTE
  442.   VariableAccess.Kind=
  443.     GetKind(VariableNameUse.Key,Variable) DEPENDS_ON VariableAccess.Objects;
  444.   VariableAccess.Type=
  445.     GetType(VariableNameUse.Key,NoKey) DEPENDS_ON VariableAccess.Objects;
  446.   IF(LT(VariableAccess.Kind,Constantx),
  447.     Message(FATAL,"Constant, variable or parameter name required"));
  448. END;
  449. ~}
  450.  
  451. Note that the computations of the ~{Kind~} and ~{Type~} attribute of the
  452. ~{VariableAccess~} both depend on the assertion that all names
  453. visible at this point have their properties set.
  454. The need for this dependence is clear:
  455. Both attributes are properties of the name being used, and might be
  456. meaningless if the assertion were false.
  457.  
  458. Choice of ~{Variable~} as the default value of the ~{Kind~} attribute
  459. avoids a spurious error report if the name is undefined.
  460. Remember that scope analysis has already reported an error if the name is
  461. undefined.
  462. If ~{Undefined~} were chosen as the default value, the error "Constant,
  463. variable or parameter name required" would be reported here.
  464. That report is spurious, because the compiler does not ~/know~/ that the
  465. name in question is not a constant, variable or parameter name -- it has no
  466. information about the name.
  467.  
  468. ~B
  469.  
  470. An array type has four properties in addition to the normal properties of a
  471. type object:
  472.  
  473. ~$~<Arrays~>==~{
  474. IndexType, ElementType: DefTableKey;
  475. LowerBound, UpperBound: int;
  476. ~}
  477.  
  478. All of these properties are used in checking the context conditions
  479. for expressions.
  480.  
  481. ~C
  482.  
  483. Array types are declared by specifying the index range and the element
  484. type.
  485. Each new array type is distinct from all others, even though two array type
  486. declarations may look the same.
  487.  
  488. ~$~<Array type definition~>==~{
  489. RULE ArrayDef:
  490.   NewArrayType ::= 'array' '[' IndexRange ']' 'of' TypeNameUse
  491. COMPUTE
  492.   NewArrayType.Objects=
  493.     ORDER(
  494.       SetLowerBound(INCLUDING NewType.Key,IndexRange.LowerBound,0),
  495.       SetUpperBound(INCLUDING NewType.Key,IndexRange.UpperBound,0),
  496.       SetIndexType(INCLUDING NewType.Key,IndexRange.IndexType,NoKey),
  497.       SetElementType(INCLUDING NewType.Key,TypeNameUse.Type,NoKey))
  498.     DEPENDS_ON NewArrayType.Objects;
  499.   TypeNameUse.VisibleTypeProperties=NewArrayType.Objects;
  500. END;
  501.  
  502. SYMBOL IndexRange:
  503.   LowerBound, UpperBound: int,
  504.   IndexType: DefTableKey;
  505.  
  506. RULE Bounds: IndexRange ::= Constant '..' Constant
  507. COMPUTE
  508.   IndexRange.LowerBound=Constant[1].Value;
  509.   IndexRange.UpperBound=Constant[2].Value;
  510.   IndexRange.IndexType=
  511.     IF(EQ(Constant[1].Type,Constant[2].Type),
  512.       Constant[1].Type,
  513.       ORDER(
  514.         IF(AND(NE(Constant[1].Type,NoKey),NE(Constant[2].Type,NoKey)),
  515.           Message(FATAL,"Bounds must be of the same type")),
  516.         NoKey));
  517.   IF(GT(Constant[1].Value,Constant[2].Value),
  518.     Message(FATAL,"Lower bound may not exceed upper bound"));
  519. END;
  520. ~}
  521.  
  522. The assertion that ``all visible names have their properties set'' is true
  523. after the array type declaration if it is true before and if the array type
  524. name has its properties set.
  525.  
  526. ~C
  527.  
  528. An array variable can be accessed as a whole simply by stating the name of
  529. the variable.
  530. One element of an array can also be accessed as a variable by specifying a
  531. subscript expression that selects the desired element.
  532.  
  533. ~$~<Array element use~>==~{
  534. RULE Index: VariableAccess ::= VariableAccess '[' Expression ']'
  535. COMPUTE
  536.   VariableAccess[1].Kind=VariableAccess[2].Kind;
  537.   VariableAccess[1].Type=
  538.     GetElementType(VariableAccess[2].Type,NoKey)
  539.     DEPENDS_ON VariableAccess[1].Objects;
  540.   IF(EQ(VariableAccess[1].Type,NoKey),
  541.     Message(FATAL,"Indexed variable must be of array type"));
  542.   Expression.ExpectedType=GetIndexType(VariableAccess[2].Type,NoKey)
  543.     DEPENDS_ON VariableAccess[1].Objects;
  544. END;
  545. ~}
  546.  
  547. A constant cannot be of an array type because there is no way to describe
  548. an array denotation in Pascal-.
  549. Therefore a single test of the type yielded by the indexed object
  550. suffices to determine the legality of an indexed selector.
  551.  
  552. ~B~<Records~>
  553.  
  554. A record variable consists of some number of distinct ~/field variables~/.
  555. Field variable names do not follow the same scope rules as other names.
  556. If a field variable name is defined within a record of type ~{T~}, then the
  557. scope of that definition is the set of names following the ``~{.~}'' in all
  558. phrases ~{VariableAccess '.' FieldNameUse~} for which ~{VariableAccess~}
  559. yields an object of type ~{T~}.
  560.  
  561. Scope rules of this kind are common in programming languages, and they
  562. cannot be verified during scope analysis because they depend on type
  563. analysis.
  564. Eli provides a generic library module ~{$/Tool/lib/Name/Field.gnrc~}
  565. to implement consistent renaming according to this rule.
  566.  
  567. ~{Field.gnrc~} exports four symbols to embody the concepts involved:
  568. a ~{FieldScope~} is a phrase that contains definitions, a ~{FieldDef~} is a
  569. name definition, and a ~{FieldUse~} is a name use.
  570. ~{RootField~} is a phrase containing all of the ~{FieldScope~} phrases in
  571. the source program.
  572. Name definitions and uses are assumed to be represented by tree nodes
  573. having a ~{Sym~} attribute of type ~{int~} that specifies the corresponding
  574. name.
  575. The module will compute the value of a ~{Key~} attribute of type
  576. ~{DefTableKey~} at each tree node representing a name definition or use.
  577. ~{Key~} attribute values of associated definitions and uses will be
  578. identical.
  579. If a use is not associated with any definition, its ~{Key~} attribute will
  580. be the distinguished ~{DefTableKey~} value ``~{NoKey~}''.
  581.  
  582. ~C
  583.  
  584. Each ~{FieldScope~} must be provided with a ~{Key~} attribute of type
  585. ~{DefTableKey~} by some mechanism outside of the module.
  586. The same ~{DefTableKey~} value must be provided as the ~{ScopeKey~}
  587. attribute of each ~{FieldUse~}, again via a mechanism outside of the
  588. module.
  589. It is this ~{DefTableKey~} value that links the field with the record in
  590. which it is defined.
  591.  
  592. In Pascal-, the ~{DefTableKey~} value linking records and their field
  593. variables is the record's type.
  594. The ~{FieldScope~} concept is embodied in the ~{NewRecordType~} phrase,
  595. ~{FieldDef~} is embodied in ~{FieldNameDef~} and
  596. ~{FieldUse~} is embodied in ~{FieldNameUse~}.
  597. Since the field names must be unique within a record and every field
  598. variable must be defined, these symbols also inherit from the error
  599. reporting modules discussed in Section 6.2.
  600.  
  601. ~$~<Record type definition~>==~{
  602. SYMBOL Program INHERITS RootField END;
  603. SYMBOL NewRecordType INHERITS FieldScope, RangeUnique COMPUTE
  604.   INH.Key=INCLUDING NewType.Key;
  605. END;
  606.  
  607. RULE RecSect: RecordSection ::= FieldNameDefList ':' TypeNameUse
  608. COMPUTE
  609.   RecordSection.Type=TypeNameUse.Type;
  610.   TypeNameUse.VisibleTypeProperties=RecordSection.Objects;
  611. END;
  612.  
  613. ATTR ScopeKey: DefTableKey;
  614.  
  615. SYMBOL FieldNameDef INHERITS FieldDef, NameOccurrence, IdDefUnique COMPUTE
  616.   INH.ScopeKey=INCLUDING NewType.Key;
  617.   SYNT.Objects=
  618.     SetType(THIS.Key,INCLUDING RecordSection.Type,NoKey)
  619.     DEPENDS_ON THIS.Objects;
  620. END;
  621. ~}
  622.  
  623. The assertion that ``all visible names have their properties set'' is true
  624. after the field declaration if it is true before and if the field
  625. name has its properties set.
  626.  
  627. ~C
  628.  
  629. A record variable can be accessed as a whole simply by stating the name of
  630. the variable.
  631. One field of a record can also be accessed as a variable by specifying a
  632. name that selects the desired field.
  633.  
  634. ~$~<Field name use~>==~{
  635. SYMBOL FieldNameUse INHERITS FieldUse, NameOccurrence, NoKeyMsg END;
  636.  
  637. RULE Select: VariableAccess ::= VariableAccess '.' FieldNameUse
  638. COMPUTE
  639.   VariableAccess[1].Kind=VariableAccess[2].Kind;
  640.   VariableAccess[1].Type=GetType(FieldNameUse.Key,NoKey)
  641.     DEPENDS_ON VariableAccess[1].Objects;
  642.   FieldNameUse.ScopeKey=VariableAccess[2].Type;
  643. END;
  644. ~}
  645.  
  646. ~{VariableAccess[1].Type~} is set to a property of the field name being used,
  647. and might be meaningless unless all visible identifiers have their
  648. properties set.
  649. Hence its dependence on the assertion ~{VariableAccess[1].Objects~}.
  650.  
  651. A constant cannot be of a record type because there is no way to describe
  652. an record denotation in Pascal-.
  653. Therefore the test for an undefined field variable
  654. suffices to determine the legality of a field selector.
  655.  
  656. ~B
  657.  
  658. Type analysis of a Pascal- expression determines the type yielded by every
  659. expression and the type required by the context in which that expression
  660. appears.
  661. It then verifies that the yielded type is appropriate for the context:
  662.  
  663. ~$~<Expressions~>==~{
  664. ATTR Type, ExpectedType: DefTableKey;
  665.  
  666. SYMBOL Expression COMPUTE
  667.   IF(AND(
  668.     AND(NE(THIS.Type,THIS.ExpectedType),NE(THIS.Type,NoKey)),
  669.     NE(NoKey,THIS.ExpectedType)),
  670.     Message(FATAL,"Type yielded is not compatible with the context"));
  671. END;
  672.  
  673. ~<Expression contexts~>
  674. ~<Operator definitions~>
  675. ~}
  676.  
  677. Note that no error report is issued when nothing is known about the
  678. expression type (i.e. the type is ~{NoKey~}).
  679.  
  680. This computation should be applied at ~/all~/ nodes representing
  681. expressions.
  682. In the grammar, however, phrases that describe expressions were given
  683. different names in order to make operator precedence and association rules
  684. explicit.
  685. Operator precedence and association rules only affect the structure of the
  686. tree, however, not the meaning of the computation.
  687. Thus ~{A+B~} and ~{A*B~} are both dyadic expressions, in which two operands
  688. are combined by an operator according to certain rules to yield a single
  689. result, even though the first constitutes a ~{SimpleExpression~} and the
  690. second a ~{Term~}.
  691.  
  692. To avoid spurious distinctions among nodes,
  693. define ~/equivalence classes~/ of phrases:
  694.  
  695. ~$~<Equivalence classes of expression and operator phrases~>==~{
  696. Expression ::= SimpleExpression Term Factor.
  697. Binop ::= RelationalOperator AddingOperator MultiplyingOperator.
  698. Unop ::= SignOperator NotOperator.
  699. ~}
  700.  
  701. Each equivalence class is represented by the name of one of its member
  702. phrases, the one appearing to the left of ``~{::=~}''.
  703. The name used to represent the members of the equivalence class
  704. need not actually appear in the grammar (~{Expression~} is a phrase in the
  705. Pascal- grammar, but ~{Binop~} and ~{Unop~} are not).
  706. Every tree node corresponding to a member of an equivalence class must be
  707. referred to by the name used to represent that class.
  708.  
  709. ~C
  710.  
  711. The ~{Type~} and ~{ExpectedType~} attributes of every expression must be
  712. set in order to verify the context condition.
  713. ~{Type~} depends on the content of the expression itself, while
  714. ~{ExpectedType~} depends upon how the expression is used.
  715. In Pascal-, there are four distinct ways of forming an expression:
  716.  
  717. ~$~<Expression contexts~>==~{
  718. RULE VariableExpr: Expression ::= VariableAccess
  719. COMPUTE
  720.   Expression.Type=VariableAccess.Type;
  721. END;
  722.  
  723. RULE Denotation: Expression ::= Numeral
  724. COMPUTE
  725.   Expression.Type=IntegerKey;
  726. END;
  727.  
  728. ATTR Needs: DefTableKey;
  729.  
  730. RULE Monadic: Expression ::= Unop Expression
  731. COMPUTE
  732.   Expression[1].Type=Unop.Type;
  733.   Expression[2].ExpectedType=Unop.Needs;
  734. END;
  735.  
  736. ATTR Left: DefTableKey;
  737.  
  738. RULE Dyadic: Expression ::= Expression Binop Expression
  739. COMPUTE
  740.   Expression[1].Type=Binop.Type;
  741.   Expression[2].ExpectedType=Binop.Needs;
  742.   Binop.Left=Expression[2].Type;
  743.   Expression[3].ExpectedType=Binop.Needs;
  744. END;
  745. ~}
  746.  
  747. When an expression is formed using an operator, the type yielded by the
  748. resulting expression is completely determined by the operator.
  749. The ~{Type~} attribute of the operator specifies that type.
  750. The ~{Needs~} attribute of the operator specifies the type that must be
  751. yielded by the operand(s) (both operands of a dyadic operator must
  752. yield the same type in Pascal-).
  753. ~{Needs~} is completely determined by the operator in most cases, but
  754. depends on ~{Left~} for relational operators.
  755.  
  756. ~C
  757.  
  758. Every Pascal- operator is described by a phrase in the grammar, and
  759. therefore corresponds to a node of the tree.
  760. The computations associated with those nodes simply establish the values of
  761. the ~{Needs~} and ~{Type~} attributes of the operator.
  762. Each phrase needs a rule with a name, and the rule must give the name of
  763. the phrase (~{Binop~} or ~{Unop~}), and the operator indication (~{'+'~},
  764. ~{'div'~}, etc.)
  765. Here is a template that creates the necessary boilerplate:
  766.  
  767. ~$~<Operator type information~>~(~5~)~M==~{
  768. RULE r~1: ~2 ::= ~3
  769. COMPUTE
  770.   ~2.Needs=~4Key; ~2.Type=~5Key;
  771. END;
  772. ~}
  773.  
  774. Relational operators do not fit this model, because they are
  775. ~/overloaded~/:
  776. Their operands might be either integer values or Boolean values.
  777. Therefore the ~{Needs~} attribute of a relational operator depends upon the
  778. types of the operands actually provided to it, while the ~{Needs~}
  779. attributes of other operators are determined by the operators.
  780.  
  781. ~$~<Relational operator type information~>~(~2~)~M==~{
  782. RULE r~1: Binop ::= ~2
  783. COMPUTE
  784.   Binop.Needs=IF(EQ(Binop.Left,BooleanKey),BooleanKey,IntegerKey);
  785.   Binop.Type=BooleanKey;
  786. END;
  787. ~}
  788.  
  789. Given these templates, the characteristics of the operators are simply
  790. listed:
  791.  
  792. ~$~<Operator definitions~>==~{
  793. ~<Relational operator type information~>~(Lss~,'<'~)
  794. ~<Relational operator type information~>~(Leq~,'<='~)
  795. ~<Relational operator type information~>~(Gtr~,'>'~)
  796. ~<Relational operator type information~>~(Geq~,'>='~)
  797. ~<Relational operator type information~>~(Equ~,'='~)
  798. ~<Relational operator type information~>~(Neq~,'<>'~)
  799.  
  800. ~<Operator type information~>~(Add~,Binop~,'+'~,Integer~,Integer~)
  801. ~<Operator type information~>~(Sub~,Binop~,'-'~,Integer~,Integer~)
  802. ~<Operator type information~>~(Mul~,Binop~,'*'~,Integer~,Integer~)
  803. ~<Operator type information~>~(Div~,Binop~,'div'~,Integer~,Integer~)
  804. ~<Operator type information~>~(Mod~,Binop~,'mod'~,Integer~,Integer~)
  805.  
  806. ~<Operator type information~>~(Neg~,Unop~,'-'~,Integer~,Integer~)
  807. ~<Operator type information~>~(Nop~,Unop~,'+'~,Integer~,Integer~)
  808.  
  809. ~<Operator type information~>~(And~,Binop~,'and'~,Boolean~,Boolean~)
  810. ~<Operator type information~>~(Or~,Binop~,'or'~,Boolean~,Boolean~)
  811. ~<Operator type information~>~(Not~,Unop~,'not'~,Boolean~,Boolean~)
  812. ~}
  813.  
  814. ~B
  815.  
  816. As far as type analysis is concerned, the only effect of a statement is
  817. to establish a context for the expressions it contains:
  818.  
  819. ~$~<Statements~>==~{
  820. RULE Assign: Statement ::= VariableAccess ':=' Expression
  821. COMPUTE
  822.   Expression.ExpectedType=VariableAccess.Type;
  823. END;
  824.  
  825. RULE While: Statement ::= 'while' Expression 'do' Statement
  826. COMPUTE
  827.   Expression.ExpectedType=BooleanKey;
  828. END;
  829.  
  830. RULE OneSided: Statement ::= 'if' Expression 'then' Statement
  831. COMPUTE
  832.   Expression.ExpectedType=BooleanKey;
  833. END;
  834.  
  835. RULE TwoSided: Statement ::= 'if' Expression 'then' Statement 'else' Statement
  836. COMPUTE
  837.   Expression.ExpectedType=BooleanKey;
  838. END;
  839. ~}
  840.  
  841. Procedure statements are deferred to the next section.
  842.  
  843. Because there is no need to distinguish the different kinds of statement
  844. described in the grammar, they are all placed into an equivalence class:
  845.  
  846. ~$~<Equivalence classes of statement phrases~>==~{
  847. Statement ::= AssignmentStatement ProcedureStatement IfStatement WhileStatement.
  848. ~}
  849.  
  850. ~B
  851.  
  852. Type analysis of procedures verifies that the the arguments of a procedure
  853. call agree with the parameter specifications of the procedure called.
  854. Since the specification of a parameter is available via its definition
  855. table key, a procedure must have a property that specifies its parameters,
  856. in addition to the ~{Kind~} property common to all objects:
  857.  
  858. ~$~<Procedures~>==~{
  859. Formals: KeyArray;
  860. ~}
  861.  
  862. A ~{KeyArray~} is an abstract data type provided by the Eli library to
  863. represent fixed-sized, ordered collections of objects.
  864. ~{KeyArray~} exports four operations:
  865. ~{NewKeyArray(n)~} returns a new collection of size ~{n~} whose elements
  866. are indexed by the integers 0 through n-1 inclusive.
  867. Initially, all elements of the collection represented by ~{NewKeyArray(n)~}
  868. are the distinguished definition table key ~{NoKey~}.
  869. Element ~{i~} of collection ~{a~} is set to the value ~{k~} by the
  870. operation ~{StoreKeyInArray(a,i,k)~} and its value is obtained by the
  871. operation ~{FetchKeyFromArray(a,i)~}.
  872. ~{KeyArraySize(a)~} yields the number of elements in a collection, and
  873. ~{NoKeyArray~} is the empty collection.
  874.  
  875. ~{KeyArray~} is an abstract data type, not a generic module.
  876. Therefore it need not be instantiated, but
  877. its interface must be made available:
  878.  
  879. ~$~<Definition table key array module interface~>==~{
  880. #include "keyarray.h"
  881. ~}
  882.  
  883. The properties of the standard procedures are established as follows:
  884.  
  885. ~$~<Set properties of standard names~>+=~{
  886.   { KeyArray Formals; DefTableKey FormalKey;
  887.  
  888.     SetKind(ReadKey,Procedurex,NoKey);
  889.     Formals = NewKeyArray(1);
  890.     FormalKey = NewKey();
  891.     SetKind(FormalKey,VarParameter,Undefined);
  892.     SetType(FormalKey,IntegerKey,NoKey);
  893.     StoreKeyInArray(Formals,0,FormalKey);
  894.     SetFormals(ReadKey,Formals,NoKey);
  895.  
  896.     SetKind(WriteKey,Procedurex,NoKey);
  897.     Formals = NewKeyArray(1);
  898.     FormalKey = NewKey();
  899.     SetKind(FormalKey,ValueParameter,Undefined);
  900.     SetType(FormalKey,IntegerKey,NoKey);
  901.     StoreKeyInArray(Formals,0,FormalKey);
  902.     SetFormals(WriteKey,Formals,NoKey);
  903.   }
  904. ~}
  905.  
  906. ~C
  907.  
  908. The formal parameters of a procedure are characteristic of the
  909. ~{ProcedureBlock~} component of the procedure definition, so
  910. ~{ProcedureBlock~} is given a ~{Formals~} attribute.
  911. Its value is a key array large enough to hold the collection of parameters.
  912. A computation at each parameter stores the parameter's definition table key
  913. into the key array, and the presence of the key array is asserted when all
  914. parameter keys have been stored.
  915.  
  916. ~$~<Procedure definitions~>==~{
  917. ATTR Formals: KeyArray;
  918.  
  919. RULE ProcDef:
  920.   ProcedureDefinition ::= 'procedure' ProcedureNameDef ProcedureBlock ';'
  921. COMPUTE
  922.   ProcedureBlock.Objects=
  923.     ORDER(
  924.       SetKind(ProcedureNameDef.Key,Procedurex,Undefined),
  925.       SetFormals(ProcedureNameDef.Key,ProcedureBlock.Formals,NoKeyArray))
  926.     DEPENDS_ON ProcedureNameDef.Objects;
  927. END;
  928.  
  929. CHAIN Counter: int;
  930.  
  931. RULE ProcBlock: ProcedureBlock ::= FormalParameterList ';' BlockBody
  932. COMPUTE
  933.   CHAINSTART FormalParameterList.Counter=0;
  934.   FormalParameterList.Formals=NewKeyArray(FormalParameterList.Counter);
  935.   ProcedureBlock.Formals=
  936.     FormalParameterList.Formals
  937.     DEPENDS_ON FormalParameterList CONSTITUENTS ParameterNameDef.GotFormal;
  938. END;
  939.  
  940. SYMBOL ParameterNameDef COMPUTE
  941.   SYNT.GotFormal=
  942.     StoreKeyInArray(
  943.       INCLUDING FormalParameterList.Formals,
  944.       THIS.Counter,
  945.       THIS.Key);
  946.   THIS.Counter=ADD(THIS.Counter,1);
  947. END;
  948. ~}
  949.  
  950. ~C
  951.  
  952. The corresponding formal parameter list is characteristic of the argument
  953. list in a call, so ~{ActualParameterList~} is given a ~{Formals~}
  954. attribute.
  955. The key of the parameter corresponding to each argument is extracted from
  956. the key array by the computation at the ~{ActualParameter~} node.
  957. The argument type is the type required by the argument expression's
  958. context, and thus becomes the value of that expression's ~{ExpectedType~}
  959. attribute.
  960. If the parameter is a ~{var~} parameter, however, the corresponding
  961. argument must also be a variable.
  962. Two more attributes, ~{ExpectedVar~} and ~{IsVariable~}, associated with
  963. ~{Expression~} nodes verify this condition:
  964.  
  965. ~$~<Procedure calls~>==~{
  966. RULE Call: Statement ::= ProcedureNameUse ActualParameterList
  967. COMPUTE
  968.   CHAINSTART ActualParameterList.Counter=0;
  969.   ActualParameterList.Formals=
  970.     GetFormals(ProcedureNameUse.Key,NoKeyArray)
  971.     DEPENDS_ON Statement.Objects;
  972.   IF(NE(GetKind(ProcedureNameUse.Key,Undefined),Procedurex),
  973.     Message(FATAL,"Procedure name required here"),
  974.     IF(NE(
  975.         ActualParameterList.Counter,
  976.         KeyArraySize(ActualParameterList.Formals)),
  977.       Message(FATAL,"Number of arguments differs from number of parameters")))
  978.     DEPENDS_ON Statement.Objects;
  979. END;
  980.  
  981. RULE Argument: ActualParameter ::= Expression
  982. COMPUTE
  983.   ActualParameter.Key=
  984.     FetchKeyFromArray(
  985.       INCLUDING ActualParameterList.Formals,
  986.       ActualParameter.Counter);
  987.   ActualParameter.Counter=ADD(ActualParameter.Counter,1);
  988.   Expression.ExpectedType=GetType(ActualParameter.Key,NoKey);
  989.   Expression.ExpectedVar=EQ(GetKind(ActualParameter.Key,NoKey),VarParameter);
  990. END;
  991.  
  992. SYMBOL Expression: ExpectedVar, IsVariable: int;
  993.  
  994. SYMBOL Expression COMPUTE
  995.   INH.ExpectedVar=0;
  996.   SYNT.IsVariable=0;
  997.   IF(AND(THIS.ExpectedVar,NOT(THIS.IsVariable)),
  998.     Message(FATAL,"A variable is required here"));
  999. END;
  1000.  
  1001. RULE VariableExpr: Expression ::= VariableAccess
  1002. COMPUTE
  1003.   Expression.IsVariable=NE(VariableAccess.Kind,Constantx);
  1004. END;
  1005. ~}
  1006.  
  1007. ~{ExpectedVar~} and ~{IsVariable~} are both false for almost all
  1008. expressions.
  1009. The only case in which ~{ExpectedVar~} is true is when the ~{Expression~}
  1010. is an argument corresponding to a ~{var~} parameter, and the only case in
  1011. which ~{IsVariable~} is true is when the ~{Expression~} is a
  1012. ~{VariableAccess~} that is not a constant.
  1013. Computations in these two contexts override the normal computations
  1014. associated with each ~{Expression~} node.
  1015.  
  1016. ~B~<Specification files for type analysis~>
  1017.  
  1018. Most of the type analysis problem is characterized by attribute
  1019. computations.
  1020. These computations involve both attributes and properties, which must be
  1021. defined.
  1022. Properties of standard names are set by a C module.
  1023.  
  1024. ~C
  1025.  
  1026. Attribute computations are specified in a type-~{lido~} file.
  1027. Eli merges this file with all other type-~{lido~} files and uses the
  1028. resulting specification to create the attribute evaluator.
  1029.  
  1030. ~O~<type.lido~>~{
  1031. ~<Text-order traversal invariant~>
  1032. ~<Constant declaration~>
  1033. ~<Constant name use~>
  1034. ~<Type declaration~>
  1035. ~<Type name use~>
  1036. ~<Array type definition~>
  1037. ~<Array element use~>
  1038. ~<Record type definition~>
  1039. ~<Field name use~>
  1040. ~<Variables~>
  1041. ~<Expressions~>
  1042. ~<Statements~>
  1043. ~<Procedure definitions~>
  1044. ~<Procedure calls~>
  1045. ~}
  1046.  
  1047. ~C
  1048.  
  1049. Properties are declared in a type-~{pdl~} file.
  1050. Eli merges this file with all other type-~{pdl~} files and uses the
  1051. resulting specification to create the definition table module.
  1052.  
  1053. ~O~<type.pdl~>~{
  1054. "keyarray.h"
  1055. ~<The object classification property~>
  1056. ~<Constants~>
  1057. ~<Types~>
  1058. ~<Arrays~>
  1059. ~<Procedures~>
  1060. ~}
  1061.  
  1062. ~C
  1063.  
  1064. A type-~{sym~} file specifies equivalence classes of phrase names.
  1065. Eli merges this file with all other type-~{sym~} files and uses the
  1066. resulting specification to create the procedure calls that build the tree.
  1067.  
  1068. ~O~<pascal-.sym~>==~{
  1069. ~<Equivalence classes of expression and operator phrases~>
  1070. ~<Equivalence classes of statement phrases~>
  1071. ~}
  1072.  
  1073. ~C
  1074.  
  1075. A type-~{c~} file implements a module that characterizes a problem by
  1076. solution.
  1077. Eli does ~/not~/ merge type-~{c~} files, but compiles them individually.
  1078.  
  1079. ~O~<type.c~>~{
  1080. #include "scope.h"
  1081. #include "type.h"
  1082. #include "pdl_gen.h"
  1083. #include "keyarray.h"
  1084.  
  1085. void
  1086. StandardIdProperties()
  1087. {
  1088. ~<Set properties of standard names~>
  1089. }
  1090. ~}
  1091.  
  1092. ~C
  1093.  
  1094. A type-~{h~} file defines the interface of a C module.
  1095. Eli does not merge type-~{h~} files.
  1096.  
  1097. ~O~<type.h~>~{
  1098. #ifndef TYPE_H
  1099. #define TYPE_H
  1100. ~<Kinds of objects~>
  1101. extern void StandardIdProperties();
  1102. #endif
  1103. ~}
  1104.  
  1105. ~C
  1106.  
  1107. The interface of a C module is made available to the tree construction and
  1108. attribute evaluation modules by placing a C pre-processor ~{include~}
  1109. directive in a type-~{head~} file.
  1110. Eli merges the contents of all type-~{head~} files into a single file,
  1111. ~{HEAD.h~}, which is included by the tree construction and attribute
  1112. evaluation modules.
  1113.  
  1114. ~O~<type.head~>~{
  1115. ~<Definition table key array module interface~>
  1116. #include "type.h"
  1117. ~}
  1118.