Static Scoping Rule vs. Dynamic Scoping Rule

public class HelloPrinter
{
   public static void main(String[] args)
   {
	int a = 3;
	int count = 1;

	while( a > 0)
	{
           ++count;
	   a--; 
 	   System.out.printf("%d\n", count);
	}
   }
}
_________________________________
a = 3
count = 1
while a>0:
    count += 1
    a -= 1
    print(count, end=", ")
print()
What is the output? 
public class HelloPrinter
{
   public static void main(String[] args)
   {
	int a = 3;

	while( a > 0)
	{
    	   int count = 1;
           ++count;
	   a--; 
 	   System.out.printf("%d\n", count);
	}
   }
}
___________________________________________________
a = 3
while a>0:
    count = 1
    count += 1
    a -= 1
    print(count, end=", ")
print()

What is the output?

 

 

Scope:
    Scope of a program variable is the range of statements in which the variable is visible or can be referenced in that statement.

local variables - where it is declared.  It is declared local to the program unit or block.
nonlocal variables - are visible but not declared in that block or program unit where it is referenced.

Example:

Static Scope:
    - can be determined prior to execution.  (That is, at compile time)
    - Where is a declaration of a variable used, when a reference to this variable is found?
            First, find from the current subprogram.
            If it is not found, go up to parent program.
            Keep up until it is found.  Otherwise, all subprograms and main can not find, give error message.

e.g.   Page 200
 
procedure big;
var x : integer;
    
  procedure sub1;
  begin {sub1}
       ...x....       <---- reference
  end; {sub1}    There is no declaration of x in sub1.
   procedure sub2;           So, go up to big to find it.
   begin {sub2}
     ........
   end; {sub2}
  begin   {big}
      ......
  end;   {big}

e.g.  Page 201
 
program main;
   var x : integer;       x is hidden here.
 
   procedure sub1;
    var x : integer;   The reference to x in sub1 is to sub1's declared x.
    begin   {sub1}
      ...x....
    end;   {sub1}
      begin   {main}
   ...
   end.   {main}

How to access hidden variable:
  Ada:   main.x
  C++:   :: (scope operator)

C++, C use global variables to pass declaration to subprograms.
Pascal has nested subprogram, but C++ does not.

Blocks:
    block is equivalent to program unit.
        begin
          ...
       end

       {
       ....
       }

    Variable declared in block is a stack dynamic variable.
    The storage is allocated when section is entered and deallocated when section is exited.

Read Section 5.8.3 and figures 5.1, 5.2, 5.3 and 5.4 to see some problems with static scope.

Dynamic Scope:

follow execution path (The scope is determined on run time.)
no way to protect local variables from access by another active subroutine
access to nonlocals is slower
            First, find from the current subprogram. (local declarations)
            If it is not found, go up to procedure's dynamic parent program.
            Keep up until it is found.  Otherwise, all subprograms and main can not find, give error message.
 
procedure big;
  var x : integer;  <----declare x in big.
  procedure sub1;
    begin {sub1}
       ...x....     <---- reference x
    end; {sub1}    There is no declaration of x in sub1.
  procedure sub2;
   var x : integer;  <---- declare x in sub2.
   begin {sub2}
       ........
   end; {sub2}
  begin   {big}
   ......
  end;   {big}
              Example 1.  If big call sub2 and sub2 call sub1, then x in sub1 is referenced in the declaration of sub2.
           Example 2.  If big call sub1, then x in sub1 is referenced in the declaration of big.

Scope and Lifetime:

When a procedure does not call other procedures, the scope and lifetime of a variable are similar.
When a procedure calls other procedures, the scope and lifetime of a variable are different. See the following example.
void printheader()               //Page 207
{
 ....
}  /* end of printheader */

void compute()
{
  int sum;
  ....
  printheader();
}  /* end of compute */

The scope of sum does not extend to the body of printheader().  It is only in compute().
The lifetime of sum extend over the execution time of printheader().  The storage bound until whole compute() completed.  It includes running printheader statement.
The referencing environment of a statement is the collection of all names that are visible in the statement

Referencing Environments of a statement:
       A collection of all names that are visible in that statement.
     see pages 235 and 237.

program example;           Referencing Environment
  var a, b : integer;
  ...
  procedure sub1;
   var x, y : integer;
   begin   ( sub1 )
    ....     <-------------  x,y of sub1, a,b of example
    end;    ( sub1 )
  procedure sub2;
   var x : integer;
     ....
    procedure sub3;
    var x : integer;
    begin   ( sub3 )
     ....    <------------ x of sub3, (x of sub2 is hidden), a,b of example
    end;    ( sub3 )     x,y of sub1 are not referenced since sub1 is not a static ancestor of sub3.
   begin   ( sub2 )
    ....      <------------ x of sub2, a,b of example
   end;    ( sub2 )
  begin   ( example )
  ....        <------------ a,b of example
  end;    ( example )
The following example main calls sub2, sub2 calls sub1.
void sub1()               Referencing Environment
{
  int a, b;
  ...        <------------ a,b of sub1, c of sub2, d of main,
}   /* end of sub1 */         (b of sub2, c of main are hidden)
void sub2()
{
  int b, c;
  ...        <------------ b,c of sub2, d of main, (c of main is hidden)
  sub1;
}   /* end of sub2 */
void main()
{
  int c, d;
  ...        <------------ c,d of main
  sub2;
}   /* end of main */