The Scope of Identifiers

1.   A variable which is accessible to a subprogram without having
     to be explicitly declared in that subprogram is called a
     GLOBAL variable with respect to the subprogram.  Variables
     declared within subprograms are called LOCAL variables with
     respect to the subprogram.

2.   A variable could be local to one module (the calling module)
     at the same time that it is global to another (the module
     being called).

3.   The scope of a variable (or more generally an identifier) is
     the extent to which it is available to various subprograms in
     a given program.

4.   RECOMMENDATION:  make all variables as local as possible.  If
     a subprogram needs to interact with a variable, then that
     variable should be passed to it as a parameter.

5.   The rule of determining the scope of an identifier is:

     The scope of an identifier extends from the program unit in
     which it is defined to all subunits which do not themselves
     redefine that identifier.

6.   The rule for procedure calls is:

     A procedure can be referenced only in blocks that CONTAIN the
     procedure.  Procedures within the same block may only
     reference those which physically precede it.

     --------------------------------------------------------
     |                                                      |
     |    MAIN PROGRAM                                      |
     |      Var   A, B, C, D, E, F, G, H, I                 |
     |                                                      |
     |    -----------------------------------------         |
     |    |    Subprogram #1                      |         |
     |    |      Var  A, C, E, X, Y, Z            |         |
     |    |                                       |         |
     |    |    --------------------------         |         |
     |    |    |  Subprogram #1a        |         |         |    
     |    |    |    Var    C, Y, U, V   |         |         |
     |    |    |                        |         |         |
     |    |    |         A := 5;        |         |         |
     |    |    --------------------------         |         |
     |    -----------------------------------------         |
     |                                                      |
     |    -----------------------------------------         |
     |    |    Subprogram #2                      |         |
     |    |      Var   A, B, D, X, V              |         |
     |    |                                       |         |
     |    -----------------------------------------         |
     |                                                      |
     |                                                      |    
     --------------------------------------------------------


In the previous program structure:

     MAIN can call subprograms 1 and 2
     MAIN cannot call subprogram 1a
     Subprogram 1 can call subprogram 1a
     Subprogram 2 cannot call subprogram 1a
     Subprogram 2 can call subprogram 1
     Subprogram 1 cannot call subprogram 2

7. VALUE PARAMETERS are used only for INPUT to procedures.

   VARIABLE PARAMETERS are used for both input to and output from
   procedures

8. When an identifier is used in a procedure, the Pascal compiler

   (a)  first looks to see if the identifier is local to the
        procedure

   (b)  THEN it looks to see if the identifier is a formal
        parameter

   (c)  FINALLY it looks to see if the identifier is known outside
        the procedure at some level containing the procedure; if
        so, the FIRST occurrence of the identifier is used.

9. A global variable can be redefined at each new procedure level,
   at which time it is local to that level.


SCOPE RULES DEMO PROGRAM

Program Scope_rules;

{ This program illustrates the various scope rules for identifiers
in Pascal.     Just what can be referenced within procedures and at
what levels? }

Uses
  Crt;

Var
  A, B, X, Y:  Integer;   { LOCAL TO MAIN CODE; GLOBAL TO ALL
                            PROCEDURES WHICH DO NOT REDEFINE THEM! }


{ ============== 1ST PROCEDURE ================================ }

  Procedure FIRST;

  Begin  { FIRST }
    Writeln('Writing from within procedure #1...');
    Writeln('A = ', A);
    Writeln('B = ', B);   { The main code variables }
    A := -6;
    B := 0;
    Writeln('Leaving procedure #1...')
  End;   { FIRST }


{ ============== 2ND PROCEDURE =============================== }

  Procedure SECOND;

  Var
    A, C: Integer;

  Begin
    Writeln('Writing from within procedure #2...');
    A := 15;
    B := -1;
    C := 10;
    Writeln('A = ', A);
    Writeln('B = ', B);
    Writeln('C = ', C);
    Writeln('Leaving procedure #2...')
  End; { SECOND }

{ ============== 3RD PROCEDURE =============================== }

  Procedure Third(Var X, Y: Integer);

  Begin
    Writeln('Writing from within procedure #3...');
    Writeln('X = ', X);
    Writeln('Y = ', Y);
    X := -25;  { X and the parameter referenced by it are the same }
    Y := 123   { Y and the parameter referenced by it are the same }
  End;  { THIRD }

{ ============== 4TH PROCEDURE ================================== }

  Procedure Fourth(X, Y: Integer);

  Var
    A, F: Integer;

    { ============== 5TH PROCEDURE: NESTED WITHIN 4th ============ }
    Procedure Fifth(Var M, N: Integer);

      Var
        C, F: Integer;

      Begin  { FIFTH }
        Writeln;
        Writeln('Now inside FIFTH procedure declared within FOURTH...');
        A := 16;    { A is global to #4 }
        B := 976;   { B is the global variable in the main program }
        M := -65;   { M is linked to the parameter referenced by it }
        N := 100;   {     ditto for N    }
        F := -99;   { F is local to #5   }

        Writeln('A' :5, 'B' :5, 'F' :5, 'M' :5, 'N' :5, 'X' :5, 'Y' :5);
        Writeln(A :5, B :5, F :5, M :5, N :5, X :5, Y :5);

        Writeln('Leaving procedure FIFTH...');
        Writeln
      End;  { FIFTH }

    Begin  { FOURTH }
      Writeln;
      Writeln('Writing from within procedure #4...');
      Writeln('X = ', X);
      Writeln('Y = ', Y);
      X := -55;
      Y := 125;    { Both X and Y are local to Procedure #4 }
      A := 2500;   { A and F are local to procedure #4      }
      F := -512;
      Writeln('X = ', X);
      Writeln('Y = ', Y);
      Writeln('A = ', A);
      Writeln('F = ', F);
      FIFTH(X, Y);
      Writeln('Back in 4th again...');
      Writeln('A' :5, 'B' :5, 'F' :5, 'X' :5, 'Y' :5);
      Writeln(A :5, B :5, F :5, X :5, Y :5);
      Writeln('Leaving procedure #4...')
    End;

BEGIN  { MAIN }

  Clrscr;
  A := 1;
  B := 2;
  Writeln('In Main.');
  Writeln('A = ', A);
  Writeln('B = ', B);
  Writeln('Calling First Procedure');
  FIRST;
  Writeln('Returned from FIRST... now A = ', A, ' and  B = ', B);
  Readln;

  A := 1;
  B := 2;
  Writeln('In Main..');
  Writeln('A = ', A);
  Writeln('B = ', B);
  Writeln('Calling Second Procedure');
  SECOND;
  Writeln('Returned from SECOND... now A = ', A, ' and  B = ', B);
  Readln;

  A := 1;
  B := 2;
  X := 81;
  Y := -95;
  Writeln('In Main...');
  Writeln('Calling Third Procedure');
  THIRD(A, B);
  Writeln('Returned from THIRD... ');
  Writeln('now A = ', A, ' , B = ', B, ' , X = ', X, ' and Y = ', Y);
  Readln;

  A := 1;
  B := 2;
  Writeln('In Main....');
  Writeln('Calling Fourth Procedure');
  FOURTH(A, B);
  Writeln;
  Writeln('Returned from FOURTH... ');
  Writeln('now A = ', A, ' , B = ', B, ' , X = ', X, ' and Y = ', Y);
  Readln

END.

=====================================================================
PROGRAM RUN:
=====================================================================

In Main.
A = 1
B = 2
Calling First Procedure
Writing from within procedure #1...
A = 1
B = 2
Leaving procedure #1...
Returned from FIRST... now A = -6 and  B = 0


In Main..
A = 1
B = 2
Calling Second Procedure
Writing from within procedure #2...
A = 15
B = -1
C = 10
Leaving procedure #2...
Returned from SECOND... now A = 1 and  B = -1


In Main...
Calling Third Procedure
Writing from within procedure #3...
X = 1
Y = 2
Returned from THIRD...
now A = -25 , B = 123 , X = 81 and Y = -95


In Main....
Calling Fourth Procedure

Writing from within procedure #4...
X = 1
Y = 2
X = -55
Y = 125
A = 2500
F = -512

Now inside FIFTH procedure declared within FOURTH...
    A    B    F    M    N    X    Y
   16  976  -99  -65  100  -65  100
Leaving procedure FIFTH...

Back in 4th again...
    A    B    F    X    Y
   16  976 -512  -65  100
Leaving procedure #4...

Returned from FOURTH...
now A = 1 , B = 976 , X = 81 and Y = -95