Some Design issues.
	1. Recursion or not
	     Recursion: makes subprograms more useful and elegant especial when the underlying algorithm
	                is recursively defined but makes it necessary to provide run-time
	                supporting system that must update the Referencing Environment
	2. Nesting or not (which has a lot to do with the Identifier Scope Rule)
	     Nesting: Static Scope rule is the norm
		      Makes program execution safer by protecting inner(nested subprograms) from
		      unauthorized accesses and
		      makes static analysis of the programs simpler and easier than otherwise.
	3. Parameter Passing mechanisms.
	4. Memory allocation for Local Names: 	
	   Deletion (automatic)
	   Retention (static)

   A.	Referencing Environment
	Idea: 
	To grasp all memory locations that the program in execution havs access 
	at any given point in time during the execution of a program as they constantly change
	each time a subprogram is called or returns.
	Equivalently, all visible names during a program execution.
	Conceptually it has two parts:
		Local R.E. and
		Nonlocal R.E.
	1. Deciding the Local R.E. is straightforward.
	   It is the set of all local names of the currently active
	   one subprogram in execution.
	2. Deciding the Nonlocal R.E. depends on the Scope rule being used:
		Static Scope and
		Dynamic Scope.
	--------------------------------------------
	Evaluation of Scope Rules

	Static Scope:			
	1. Natural choice for block-structured languages especially for
	   those languages that allow nested subprograms such as
	   Pascal, ADA, and P/L-1 as access is controlled and prohibited
	   depending upon the textual containments of subprograms.
	2. Local variables of a calling subprogram still get protection
	   from the called subprogram unless the called subprogram is the 
	   static descendant subprogram (like the case of A() calling C())
	3. Compile-time Static binding and static type checking are
	   possible.
	4. Faster memory access for nonlocal variables. 
	5. Relatively easy to read programs.
	6. More Extensive changes may be needed if scopes of names are to be
	   modified. 

	Dynamic Scope:
	1. Possible choice when subprograms are NOT to be nested and Blocks
	   are not present and furthermore, the language is highly dynamic
	   and local variables of a subprogram are intended to be
	   visible to all other subprograms (or most of them, anyway)
	   that are subsequently to be called.
	2. Binding a nonlocal, in general, must be delayed until
	   run-time, which is time-consuming.
	   As a result, no compile-time Static type checking.
	3. All local variables are accessible to called subprograms
	   unless they are hidden by Redeclarations of called subprograms,
	   which may be good or bad.
	4. Slower memory access and more difficult to read programs.
	5. Can save parameters.
	------------------------------------------------------

		proc main();
		  proc A();
		    proc C();
		    proc D();
		  proc B();
		    proc E();
	        
		main() can call A() and B() but not C(), D() or E()
		A() can call C(,) D(), or itself.
		B() can call A(), E(), or itself.
		C() can call A() or itself but not D(), nor B() nor E()  
		D() can call A(), C() or itself but nothing else.


	EX: Static Scope
	
	program Example;
	  var a, b: integer;
	  .....
	  procedure sub1;
	    var x, y: integer;
	    begin
	      // point-1: 
		 L.R.E.=[x(sub1), y(sub1)]
		 N.R.E.=[a(example), b(example)]
	    end; {sub1}
	  procedure sub2;
	    var b,x: integer;
	    .....
	    procedure sub3;
	      var x: integer;
	      .....
	      // point-2
		 L.R.E.=[x(sub3)]
		 N.L.E.=[a(example), b(sub2)]
	      end	{sub3}
	    begin	{sub2}
	    // point-3
		 L.R.E.=[x(sub2), b(sub2)]
		 N.R.E.=[a(example)]
	    end;	{sub2}			
	  begin		{example}
	    .....
	    // point-4
		 L.R.E.=[a(example), b(example)]
	  end		{example}
	------------------------------------------

	EX: Dynamic Scope

	Main called sub3 and sub3 called sub2 which called sub1.

	void sub1()
	{  int a,b;	L.R.E. = [a(sub1), b(sub1)]
			N.R.E. = [c(sub2), d(sub3), e(main)]
	   .....
	   point-1
	}	/* end of sub1
	void sub2()
	{  int b,c;
	   ....
	   point-2	L.R.E. = [b(sub2), c(sub2)]
			N.R.E. = [d(sub3), e(main)]
	   sub1();
	}	/* end of sub2
	void  sub3()
	{  int b,d;
	   .....
	   point-3	L.R.E. = [b(sub3), d(sub3)]
			N.R.E. = [c(main), e(main)]
	   sub2();
	}	/* end of sub3

	void main()
	{  int c,d,e;
	   .....
	   point-4	L.R.E. = [c(main), d(main), e(main)]
	   sub3();
	}	/* end of main()
	   
   B.	Parameter passing
	1. Three semantic modes
	   Regarding direction of passing between the Calling unit
	   and called unit.
	   a. In mode
	   b. Out mode
	   c. In-Out mode
	   Ada and Fortran90 allow programs to specify.
	   In mode:   Actual argument's value is passed and formal parameter
	              is not to be altered, namely NOT to be assigned.
	   Out mode:  Formal parameter's value is passed and formal parameters are NOT to be
	              referenced, only to be assigned.
	   In-Out mode: Both and no restrictions on either parameter.

	2. Actual passing mechanisms
	   Pass-by-Value
	   Pass-by-Result
	   Pass-by-Value-Result
	   Pass-by-Reference
	   Pass-by-Name

	a. Pass-by-Value
	   (1) The value of actual argument is used to initialize the
	       corresponding parameter which acts like a local variable.
	   (2) In-mode semantic is realized.
	   (3) 2 ways to implement
	       Actual data transfer (to new memory space)
		 safe, faster access by the called unit.
	         more memory space.
	       Access Path transfer (Pointer rather than actual value)		
	         More like pass-by-reference
	         Dangerous for "Write Protection"
	         Less memory space when the actual argument is large like
	         an array.
	   (4) Used by many languages including C, C++, Ada, Pascal, 
	       Java (for primitive data types), ALGOL60, Snobol

	b. Pass-by-Result
	   (1) The value of the formal parameter is transferred to become
	       the new value of the corresponding actual argument which
	       must be a variable.
	   (2) Implementing the Out-mode semantic.
	   (3) 2 ways to implement just like Pass-by-Value.
	       Same tradeoffs including the problem of insuring that the initial
	       value of the actual argument is NOT used in the called unit
	       when the access path is transferred.
	   (4) Two Additional problems: 
		 Actual argument collision.
	           Sub(P1, P1)
	             the final value of P1 is unpredictable at best.
	         Deciding the address of an actual argument
	           Sub(List[index])
	             when index is changed inside the called subprogram, Sub,
	             the address of List[index]) can be different depending on
	             when the address is decided, on call or on Return.
	   (5) Used by Ada for Out-mode parameters.

	c. Pass-by-Value-Result (Pass-by-Copy)
	   (1) Value is copied from actual argument to formal parameter and
	       in the opposite direction as well.
	   (2) Implementing Inout-mode semantic.
	   (3) Share problems of both Pass-by-Value and Pass-by-Result.
	   (4) Free from aliasing (unlike Pass-by-Reference)
	   (5) Used by Fortran90 and Ada.

	d. Pass-by-Reference
	   (1) Implementing Inout-mode semantic
	   (2) An adderss is passed to the called subprogram enabling
	       the called subprogram to share the actual argument with
	       the calling subprogram.
	   (3) Efficient both in time (Due to NO Copying needed) 
	       and space (NO Duplicate memory space for copying).
	       By and large, the simplest method.
	   (4) Used by many languages including FORTRAN77, Pascal, C++,
	       Java (class objects, arrays), FORTRAN90
	   (5) Disadvantages
	       Access to actual argument itself may be slower due to indirect
	       addressing.
	       Aliasing: Harmful to Readability and Reliability.
	       EX:  Subprogram Fun(First, Second)
	 
	       a.   Call Fun(X,X)	
	              // Inside subprogram fun, the two different names, 
	              // First and Second, represent the same memory address
	              // So, they become aliases.
	       b.   Call Fun(L[K], L[M])
	              // If K and M happen to the same, then same result as above.

	            Subprogram Fun2(First, Second)
	       c.   Call Fun2 (List[K], List)
		      // Inside the called subprogram, First and an element of
	                 the array Second become aliases.

	            Subprogram Fun3(Param1)
	       d.   Call Fun3 (NonLocal1)
	              // When inside the called subprogram, the given actual
	                 argument is a visible non-local, then Param1 and
	                 Nonlocal1 become aliases.

	e. Pass-by-Name
	   (1) Delaying the actual binding of formal parameters to a value
	       or to an address until they are actually referenced or
	       assigned, by essentially substituting text of the argument
	       for the corresponding parameter.
	   (2) Implementing Inout-mode semantic
	   (3) Used initially in Algol60 along with Pass-by-Value.
	       No other language followed except SIMULA67
	   (4) Very slow as it is usually implemented by a parameterless
	       procedure called Thunks.
	   (5) Different outcomes:
	       If Actual argument is a scalar var: Same as Pass-by-Reference
	       If It is a constant expression: Same as Pass-by-Value
	       If it is an array element like A[K] or an expression that contains
	       a variable like X+Y, it is different from
	       any other methods yielding different unique results.
	   (6) Flexibility: A subprogram doing many different things. 
	    
	   EX:	Jensen's Device (Algol procedure)
		Real Procedure SUM(Exp,Index,L,U);
		  value L,U;
		  begin
		    real temp:=0;
		    for Index := L step 1 Until U
		      do temp := temp+Exp;
		    SUM := temp;
		    end;

	   Example calls:
		SUM(A[i], i, 1, 100)	
		  // A[1]+A[2]+A[3]+...+A[100]
		SUM(A[K]*B[K], K, 1, 100)
		  // A[1]*B[1]+A[2]*B[2]+ ... +A[100]*B[100]
		SUM(C[K,2], K, -100, -100)		    
		  // C[-100,2]+C[-99,2]+C[-98,2]+ ... +C[100,2]

	   (7) Inadequacy: Certain procedures may not work in some cases.
		
		Subprogram Swap(A,B)
	        integer A,B,C
		C=A
		A=B
		B=C
		return
		end

		If above were implemented by Pass-by-Name, then following 
		call would not work:
		          Call Swap(K,List[K])
	        because this call will be turned into:
			C=K
			K=List[K]
			List[K]=C 
		unless List[K] and K are the same
		although "Call Swap(List[K],K)" may.

   C. Parameters that are Subprogram Names (Parameter Subprograms)
	(1) Idea: To have a procedure perform a variety of tasks
	          by calling a subprogram that is sent to it.
	    Some languages allow this:
		Pascal, Fortran77, Fortran90, Algol68, C, C++ (by way of
		function pointers only)
	(2) Problems:
	    Need for checking type consistency of parameters of this parameter subprogram.
	    For this, parameter types of this subprogram need to be passed as arguments of 
	    the subprogram call.
	    
	    EX:  Pascal
	    procedure integrate (function fun(X:real):real;
		lower, upper:real; var result: real);
		...
	        var val:real;
		val := fun(lower);
		...
		end;

	    In this example, the Pascal compiler is able to check the type
	    consistency of the actual argument of the function fun() to be
	    called from above procedure integrate

	(3) Issue: Deciding the referencing environment of the called subprogram. (Under Static Scope)
	    Three possibilities: 
		Shallow Binding (Not suitable for nested subprograms for Static Scope Rule)
		  The environment of the call statement that ENACTS
		  the passed subprogram. (more natural for dynamic scope)
		Deep Binding (Choice)
		  The environment in which the passed subprogram is defined, which is consistent with
	          the normal binding in case of the Static Scope Rule.
		Ad Hoc Binding (Not been used)
		  The environment of the call statement that passed the subprogram
		  as an actual argument, which can change depending upon where
		  (or in which subprogram) it happened.

	Example (JavaScript)

	function sub1()
	{  var x;
	   function sub2()
	   {  alert(x);  // creates a dialog box with the value of x
	   };
	   function sub3()
	   {  var x;
	      x = 3;
	      sub4(sub2);
	   };
	   function sub4(subx)
	   {  var x;
	      x = 4;
	      subx();	// calling the passed subprogram which is a parameter.
	   };
	   x = 1;
	   sub3();
	}; 

	In the above program, sub1 calls sub3 
	                     which calls sub4 by the call statement, sub4(sub2).
        So, sub4() subsequently calls sub2().
        The environment of the execution of sub2() in this case can be one of the following three:
	  1. that of sub4(): Shallow Binding.
	     x=4
	  2. that of sub1(): Deep Binding.
	     x=1
	  3. that of sub3(): Ad Hoc Binding.
             x=3.
	   
	REF: Text, Section 9.6(pages 408-409)