|
|
Referencing Environment of a Procedure: Static
Scope
The static ancestors of a
procedure p() are all the procedures in the program within which the
procedure p() is defined, i.e., the definition of the procedure p()
is nested. The definition of a procedure may be directly nested within
only one procedure, called its static parent procedure. However, this
static parent procedure may itself be nested within another procedure, and so
on up to the main() program. All these procedures are considered to be
static ancestors of the procedure p(). The static non-local referencing
environment of a procedure p() is the set of all the unique
variables declared in the static ancestors of p(), that have not been
re-declared in the procedure p(). When more than one static ancestor
of p() declares a variable not re-declared in p(), the variable
included in the non-local referencing environment of p() is the one
declared in the procedure closest to p() in the chain of static
ancestry. Just as in the case of static scope, the static referencing environment
of a procedure in a program can be determined by simply studying the text of
the program. Static referencing environment is not affected by the order in
which procedures are called during the execution of the program. What is the static non-local referencing
environment of the procedure transform() in the following program? program main var y: Real; procedure compute() var x : Integer; var z : Integer;
procedure initialize()
begin {initialize} ... end {initialize} procedure transform() var x: Real; begin {transform} ... end {transform}
begin {compute} ... end {compute} procedure print() var y : Integer;
begin {print} ... end {print} begin {main} ... end {main} Answer: The variable x declared in the
procedure transform() is part of its local, not non-local
referencing environment. The static ancestors of transform()
are the procedures compute() and main(). The procedure initialize()
is a sibling of transform(), not its static ancestor. The procedure print()
is a sibling of the static ancestor compute(), and not itself an
ancestor. The variable x declared in compute()
is not part of the static non-local referencing environment of transform()
since transform() re-declares x. However, the variable z
declared in compute() is indeed a part of the non-local
referencing environment of transform(), since transform() does
not re-declare it. Similarly, the variable y
declared in main() is a part of the non-local referencing
environment of transform(), since neither transform() nor any
of its static ancestors already considered (compute()) re-declares y.
In a statically scoped language, the
concept of referencing environment is essential to understanding programs. In
the above example, you would not be able to correctly answer the following
questions if you did not understand the concept of referencing environment: 1. Is the expression x + y + z legal in the procedure transform()? 2. Does the expression x + y + z produce the same result in compute()
as it does in initialize()? 3. If we introduce a new variable y in transform(),
how might that break the code in transform() that worked correctly
before its introduction? Can you answer these questions? Algorithms
to determine Static Referencing Environment: The structure of a Pascal program, in
particular, the order in which procedure definitions are nested in the
program can be graphically depicted as a tree. This tree is called the static
tree of the program. It is quite convenient to use the static tree of a
Pascal program to determine the static non-local referencing environment of a
procedure in the program. Algorithm to draw
the static tree of a Pascal program: 1. Draw the main() program as the root node of the tree. 2. Identify all the procedures/functions directly defined in main().
Draw them as child nodes of main() node. 3. Repeatedly carry out step 2 for all the leaf nodes of the tree,
until there are no more nested procedures in the program. In the Pascal program presented earlier,
the procedures compute() and print() are defined directly in main(),
and are its children. The procedures initialize() and transform()
are defined within compute() and are its children. The static tree of
the program is shown below.
Algorithm to
determine the static referencing environment of a procedure p() using the
static tree of the program: 1.
Highlight the path in the static
tree from p() up to the root of the tree, i.e., main(). On this
path lie all the static ancestors of p() in the program. 2.
Identify all the variables in the
static parent of p() which have not been re-declared in p(),
and include them in the non-local referencing environment of p(). 3. Repeat Step 2 for each static ancestor of p(), working
your way from the parent of p() up to main(). In each
ancestral procedure, identify all the variables declared in the procedure
that have not been re-declared either in p(), or in the static
ancestors of p() that you have already considered. Include these
variables in the non-local referencing environment of p(). Stop when
you have considered main() in this fashion. The static tree of the program is shown
again below. In the tree, the static ancestors of the procedure transform()
have been numbered in the order in which they would be considered by the
algorithm.
Test
your understanding - Instructions: In order to better
understand the concept of static referencing environment of a procedure,
solve problems using the accompanying problet. The problet will present you
with the outline of a Pascal program, and ask you to identify all the
variables that are in the non-local referencing environment of a selected
procedure, as well as the procedures where these variables were declared. You
may solve the problems in one of two ways: 1. You may study the program and answer the
problem. In order to help you read the program, the problet provides a Format
menu with options such as: a. Using different colors to indicate the
different levels of nesting in the program; b. Drawing boxes to delineate definitions of
procedures in the program; c. Changing the amount of indentation to set
off different procedure definitions in the program. 2. Alternatively, you may study the static
tree of the program and answer the problem. Choose the View menu to
display the static tree of the program. Follow these steps
to solve each problem (See Figure below): 1. Study either the Pascal program or its
static tree in the left panel. 2. Read the question posed in the top right
panel. 3. Indicate your answer in the mid-right
panel, and click on Check My Answer button. 4. Study the detailed feedback provided by the
problet in the bottom right panel. If your answer is incorrect, this panel
will explain why it is incorrect. 5. Click on Get Another Problem button
to generate another problem.
Are you ready?
Click here to launch the Static Referencing Environment Problet. |