1. Scope Rules
A:{int x = 0;
void fie(){
x = 1;
}
B:{int x;
fie();
}
write(x);
}
Q: which value will be printed?
A: The result depends on the scope rule be used.
2. Static Scope
-- based on the text of the program
Definition 4.4:
(i) The declarations local to a block define the local environment of that block. The local declarations of a block include only those present in the block (usually at the start of the block itself) and not those possibly present in blocks nested inside the block in question.
(ii) If a name is used inside a block, the valid association for this name is the one present in the environment local to the block, if it exists. If no association for the name exists in the environment local to the block, the associations existing in the environment local to the block immediately containing the starting block are considered. If the association is found in this block, it is the valid one, otherwise the search continues with the blocks containing the one with which we started, from the nearest to the furthest. If, during this search, the outermost block is reached and it contains no association for the name, then this association must be looked up in the langage’s predefined environment. If no association exists here, there is an error.
(iii) A block can be assigned a name, in which case the name is part of the local environment of the block which immediately includes the block to which the name has been assigned. This is the case also for blocks associated with procedures.
{
int x = 0;
void fie(int n){
x = n+1;
}
fie(3);
write(x);
{
int x = 0;
fie(3);
write(x);
}
write(x);
}
This is a case of static scope, the first write(x) output the 4, because the fie(3) modify the x=n+1 and n=3 here. So the output 1 is 4. The second write(x) output 0, because fie(3) still use the x define the out-most block according the static scope, but not the nest-est definition of x, so the inner-est x is not be modified, still 0, so the second output is 0. And the last one is output 4, it is obviously.
3. Dynamic Scope
-- based on the flow of execution
{
const x = 0;
void fie(){
write(x);
}
void foo(){
const x =1;
fie();
}
foo();
}
This is a case of dynamic scope, the dynamic scope is based on the flow of execution, so the father block of a block is the one which call the block, but not where is the block in the file. So the foo() call the fie(), and the father block of fie block is foo, so the output x is the one which is defined in the foo, whose value is 1, the output is 1.
Exercise:
1. Consider the following program fragment written in a pseudo-language which uses static scope and where the primitive read(Y) allows the reading of the variable Y from standard input.
...
int X = 0;
int Y;
void fie(){
X++;
}
void foo(){
X++;
fie();
}
read(Y);
if Y > 0{
int X = 5; // line 12
foo();
}
else
foo();
write(X);
State what the printed values are.
Answer:
This is a case of static scope, the definition of static scope the father block is the one out of this block. In this case, the difference is where we call the foo(), actually the definition x=5 in line 12 doesn't influence the execution of foo(), so whatever the input of Y, the output is always 2 ( add 1 in the foo and then add 1 in the fie).
2. Consider the following program fragment written in a pseudo-language that
uses dynamic scope.
...
int X; // line 1
X = 1;
int Y;
void fie() {
foo();
X = 0;
}
void foo(){
int X;
X = 5;
}
read(Y);
if Y > 0{
int X; // line 14
X = 4;
fie();
}
else
fie();
write(X);
State which is (or are) the printed values.
Answer:
When Y greater than 0, the
int X;
X = 4;
fie();
will be executed, cause this is a case of dynamic scope, the father block is according the running environment, so the X in the father block of fie() here is defined in line 14, that means the fie execute and modify the value of X, but it's modify the inner-est X, but not the one defined in line 1, and the write(X) output the X defined in line 1, so the output is 1.
When Y less or equal than 0, the
fie()
will be executed, this case is simple, the output is 0.
3. Consider the following code fragment in which there are gaps indicated by (*) and (**). Provide code to insert in these positions in such a way that:
a. If the language being used employs static scope, the two calls to the procedure foo assign the same value to x.
b. If the language being used employs dynamic scope, the two calls to the procedure foo assign different values to x.
The function foo must be appropriately declared at (*).
{
int i;
(*)
for (i=0; i<=1; i++){
int x;
(**)
x= foo();
}
}
Answer:
There is no a standard answer for this question, the point here is the definition of function foo, which data will be return from the foo, it is obviously the foo will use a object inherent from father block, possibly modify it, and return a result according the object.
A example:
{
int i;
i = 0;
foo {
return i
}
for (i=0; i<=1; i++){
int x;
(blank)
x= foo();
}
}
In this example, the return of the foo depend on the value of i, in static scope case, the i is always 0, but in the dynamic case, the value of i is depend on the loop.