General Information
Tutorials
Reference Manuals
Libraries
Translation Tasks
Tools
Administration
|
Name analysis according to scope rulesScopes Being Properties of Objects
Language constructs like modules, classes, or record types have a body
that is a range. The set of bindings for the components defined
in that range constitutes its scope.
In an applied context of a module, class, or record identifier
its components may be selected, e.g. in
This specific task of consistent renaming for component identifiers is often
closely related to type analysis. If The following four modules extend the basic scope rule modules (see Basic Scope Rules) by facilities that support scope properties. How to select one of the modules is explained below.
The design of scope rules and their description needs careful consideration if the concept of scopes being properties is involved. We have to answer some questions on the described language before we can decide which of the library modules is to be used: It is easily decided that we need the facility of scope properties: Assume the language has named program objects, say modules, which consist of a range with definitions of components or members. Those members are accessible outside their defining range wherever the name of the module is accessible: module m { int i; float f (); {...} } m:f();In this example the module body is a range where the members i and
f are defined. The scope of the range contains bindings for
i and f . It is a property of the module m which is
set in the module definition. The construct m:f is a qualified name:
A binding for f is to be found in the scope property of the
qualifying module name m . The definitions valid in the context of
the qualified name are irrelevant for the binding of f .
The same application pattern occurs for example with types that have components, like record types, structure types, and union types. There a component selection is usually qualified with an expression having such a type rather than with the type identifier itself.
It is recommended to use the module m; m:f(); module m { int i; float f (); {...} }Even if it should be considered erroneous to use the qualified name f before its definition, it is recommended to specify
the binding in the described way, and to enforce that restriction by
a check of the related positions.
The same holds for bottom-up basic scope rules. One only has to be aware
that the binding of qualified names is determined after the
bottom-up computations.
There are a few specific reasons where the modules
If the basic scope rules are specified C-like using
If the basic scope rules are specified C-like using The general description of this set of module is given in the section see Scope Properties without left-to-right Restrictions, the deviations of its variants are described in see Scope Properties C-like, and see Scope Properties C-like Bottom-Up. Scope Properties without left-to-right Restrictions
This module The module is instantiated by $/Name/ScopeProp.gnrc+instance=NAME +referto=KEY :inst
It is required that a
basic scope rule module is instantiated with the same generic parameters
Each of the modules introduces a
The module provide
Computations of these modules also establish attributes
We demonstrate the use of these facilities by extending the language of our running example by module declarations and access of module components. (For a complete example see the Tutorial on Name Analysis.) The notation is specified by the following two concrete productions:
Declaration: 'module' DefIdent ModBlock ';'. ModBlock: Compound. Operand: ModUseIdent '::' QualIdent. ModUseIdent: Ident. QualIdent: Ident. The symbols inherit the roles provided by the scope property module as described above:
SYMBOL ModBlock INHERITS ExportRange END; RULE: Declaration ::= 'module' DefIdent ModBlock ';' COMPUTE ModBlock.ScopeKey = DefIdent.Key; END; In the context of the module declaration it is specified that the scope of the module body is to be associated to the key of the module identifier. In the context of a selection the scope is specified in which the selected component is to be bound. It is accessed from the key of the module identifier. Module computations establish dependences such that all scope properties are associated before they are accessed here:
SYMBOL ModUseIdent INHERITS IdUseEnv, ChkIdUse, IdentOcc END; SYMBOL QualIdent INHERITS QualIdUse, ChkQualIdUse, IdentOcc END; RULE: Expression ::= ModUseIdent '::' QualIdent COMPUTE QualIdent.ScopeKey = ModUseIdent.Key; END; In order to make sure that the it is really a module identifier to which the selection is applied we specify the following check
RULE: Expression ::= ModUseIdent '::' QualIdent COMPUTE IF (AND (NE (QualIdent.ScopeKey, NoKey), EQ (QualIdent.Scope, NoEnv)), message (FATAL, CatStrInd ("module identifier required: ", ModUseIdent.Sym), 0, COORDREF)); END; The message is only issued if the identifier is defined but does not have a scope property.
(The Scope Properties C-like
This module implements consistent renaming of identifiers
using scopes which are properties associated to object keys.
The module computations establish bindings, lookup names,
associate scope properties, and lookup qualified names
in left-to-right depth-first order.
It imposes the strong requirement that a
qualified name, for example the
It is recommended to use this module only if it is needed as
a companion of the module The module is instantiated by $/Name/CScopeProp.gnrc+instance=NAME +referto=KEY :inst
Using this module requires that the module
The module provides a All computations of this module follow strictly C-like scope rules, i.e. binding of identifier occurrences, association of scope properties, and access of scope properties are done in left-to-right depth-first order.
Calls of Scope Properties C-like Bottom-Up
This module implements consistent renaming of identifiers
using scopes which are properties associated to object keys.
The module computations ensure that scope properties are associated
and accessed in left-to-right depth-first order.
It imposes the strong requirement that a
qualified name, for example the
It is recommended to use this module only if qualified identifiers
have to be bound in the bottom-up phase, or if the module is needed as
a companion of the module The computations provided by this module are executed while reading the input. The module is instantiated by $/Name/BuScopeProp.gnrc+instance=NAME +referto=KEY :inst
Using this module requires that the module
The module provides a
Note: The role names of the module All computations of this module follow strictly C-like scope rules, i.e. binding of identifier occurrences, association of scope properties, and access of scope properties are done in left-to-right depth-first order.
As a consequence of bottom-up computation the value of a key can
not be propagated by an upper computation to the range symbol.
Hence, if the defining identifier occurrence precedes the range,
the scope has to be created by the role
The role that opens the range scope (
The range symbol has the role The module declaration of our example then reads: RULE: Declaration ::= 'module' ModDefIdent Block ';' END; SYMBOL ModDefIdent INHERITS CreateNewScope, OpenNewScope, IdSetScopeProp, IdDefScope, IdentOcc COMPUTE SYNT.OpenPrecond = SYNT.Key; END;
In component selections the scope property needs to be propagated
from the context that provides it to the selector context.
The module role Hence, in our running example the selection is specified as follows:
RULE: Expression ::= ModUseIdent '::' QualIdent END; SYMBOL ModUseIdent INHERITS GetScopeProp, IdUseEnv, ChkIdUse, IdentOcc COMPUTE SYNT.ScopeKey = THIS.Key; END; SYMBOL QualIdent INHERITS QualIdUse, ChkIdUse, IdentOcc END;
If we had a typed record expression instead of the module identifier
to select from, |