WPC' 2B B R Z 2 UniversCourier"4|J~ ^CCd||CCC|CCCC||||||||||CCh|so8okv|xCCCddCkskskHss00k0ssssFdHsooo`YdY|9|||||C||||||d|x0kkkkkksksksksk80808080sssssssssoktssosvslklllkktlsksktlstssssss80808080`okl0lDk0lHl0ttstsHHFdddd|P|H|Hstsstsox`x`x`sk0sFd|HoossCddCCCWddddddddddddddddddddddddddddddddddddddddNd||Choo||~QQ|LLdd|LCCdd~JJ~~zzdddzzCddL"djd9 dCCvCd|o~dC~d~skzUvdYYCCCCo~kodks]zUsk80dhoo~UssvkvvY~]k`o]s00skkkoCC~~~~~~~ooooooooooooooooooo]]]]]]]ssssssssssssssssssss000000000000ssssssskkkkkkkkkkkkCss88kdYC\   pxtll\tll@\@\`LHP LaserJet 4Si(PCL)CL)HP4SI.PRSX~xP7\XP#|~ 2>t e Z^  11-23-92 12:20a Unit 6.3 Class  9ddddKdd@dddKdd@9Ҋ#X~xP7XP# 2~CC,X~xP7XP ?SS,xP7P<?xxx,0x6X@`7X@ ZL((,hLxP7hP d!T,,,STxP7P빋v~]_^XUP6D6B3D DNH++_a3r]>[vU[3ҋYt@Fg<r6gF[c_ea36@D D6B"4|J~ ^SS}SSSSSSSSSESSS}}SZ<<<X}Zxo}oHS}<E<E<E<E<F<E<E<E<x<U<Z<ZZX}}}}dZZxxx<X}ZS}}SSSWddddddddddddddddddddddddddddddddddddddddN}Sff__}}_SS}}]]}}}S}}_"}}H}SSS}}S}j}ooSSSS}tjE<}jotxt<<SSttttttt<<<<<<<<<<<<SEE}oSER1s''hhO"  @s  PsPs;;   x_2pD!'"m+O6^((xYJTWECYW!CP@lW[G]MMJWWxWRH(((<<(@E@E@+EE@gEEEE*<+ECgCC:5<5xJ"JJJJJ(JJJJJJCCJJtL11xxJ..<mCWCL3[EWEG@GG5L8R@bTW:`RY[C8EE@@[@C[RRX((LLLLLLLCCCCCCCCCCCCCCCCCCC8888888EEEEEEEEEEEEEEEEEEEEEEEEEEE@@@@@@@@@@@@[[[[[[[[[[[[[[[[[[[[(EYEW![RY!R@<5(xx}l7lTTlCHqqllllllF`RRqqAAleeeOejjObYYVT`jlllsqqqzn^}YsYllll7YvlFlllAAllllllllllllllllllllllxxxxxxxx&7&llllls7lllllllllllllllllllllllllllllll}}}}xxxxxxxxxx``llllllvvll^^^^lljjjjllbbb^^^^:.M^ll"m+O6^,,CSSe,,,S,,,,SSSSSSSSSS,,EcS^`MJc`%JYHx`eOhUUS```[P,,,CC,HMHMH0MM H sMMMM/C0MJsJJ@;C;S&SSSSS,SSSSSSCSP cHcHcHcHcHp^HMHMHMHMH% % % % `MeMeMeMeM`M`M`M`M[JcH`MeMeM[J`MOMcHcHcH]H]H^H^H`XMHMHMHMHcMcMcMcMcMcM`M`M% % % % l@JYHH H-H H0H `M`[`M`MeMeMyU0U0U/UCUCUCUCS5S0S0`M`M`M`M`M`Ms[JP@P@P@`MH `MU/UCS0[J[J`XeM`M,CC,,,WddddddddddddddddddddddddddddddddddddddddN```CSS,EJJSST66S33CCS3,,CCT11TTRReCC`C[{{QQ,CC3"``C`F``C充&C,,`O``````````,CcSJT`cC,T`CTM`hV``````````H``````mYQh`9O```````C```````;````;````````````````````````````````````````````,```,```,```,`````````````cJTHJCcHM>Q9`MeH% YCcEyJ`JT9eM`MOHOO;T>[Hm^`@j[ceJ>M MHHeHJe[[b,,TTTTTTTJJJJJJJJJJJJJJJJJJJ>>>>>>>MMMMMMMMMMMMMMMMMMMM MMMMMMMHHHHHHHHHHHHeeeeeeeeeeeeeeeeeeee,McM`%e[c%[HC;,x=x]]xKP}}xxxxxxMk[[}}HHxpppXpuuXmcc`]kuxxx}}}{hccxxxx=cxMxxxHHxxxxxxxxxxxxxxxxxxxxxx+=+xxxxx=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxkkxxxxxxxxhhhhxxuuuuxxmmmhhhh@3Uhxx Unit6.5 ?
We learned about how to write procedures and functions. We learned how to call procedures and functions.

We learned how to set up parameters and use procedures and functions that received and changed parameters.

It is also possible to declare variables inside procedures and functions. This is an additional place as in the var statement at the beginning of the program.. These are called local variables. That means they are only accessible to statements inside the procedure. By doing this, we can ensure that should one use a variable of the same name in the main program or another procedure, there is not conflict.

Thus, we can have two different boxes with the same name. Inside one or more procedures or functions, the name will refer to one box. Inside the main procedure and possibly other procedures or functions, that name will refer to a distinct totally different box.

In addition, we could put procedures inside other procedures. We can refer to the procedures as the "inner" procedure and the "outer" procedure. Where the "inner" procedure is defined in the "outer" procedure. The "inner" procedure can only be called inside the "outer" procedure, note the "main" procedure and not other outer procedures. The "inner" procedure can also access variables local to the "outer" procedure.

Before we look at a detailed example, let us a look at a practical example which shows why these concepts are important to the practicing progammer.

In this example we search an array A for the first element whose Nth power is greater than 1000. N is an integer read in. The main program will contain the logic to inspect each element of A. However, to raise a given value of the array to a given power, requires another loop. That loop is put in the routine power wich will take a number and multiply by itself N times, so as to raise it to a given power.

(0*0*0*ԌThe programmer or programmers both ended up using the variable "I" for their loops. I is a very commonly used variable for loop counters, so this kind of thing will often happen often with this particular variable name.

However, in the example, the programmer of the power routine used the same variable I for that loop as we used in the search logic. There is a conflict. The first program doesn't work. It generates an infinite loop when we set N to 3. As the loop in the main procedure tries to advance I past three, the procedure power, sets it back. Thus, the I in the outer loop will never get to the end of the array.

The second program only differs with declaring I and ANSWER local. There are two different boxes, both named "I." The function, POWER, uses one of them. The main procedure uses the other. Thus, they don't interfere with each otherand the program now works.



NonWorking Program
 U66.PAS

Working Program
 U66A.PAS

Now we look at the general form of this, so we can solve problems of the form "tell what this program does" when we have local variables, and even procedures within procedure.

The key idea in all the rules below is that every variable or procedurename has a "scope" in which it is known. That scope is the procedure in which the variable is declared. That may be the main program, or any internal procedure. The variable may be used only within that scope. The scope will include any procedures declared within the procedure in which it is definedas long as they do not declare a variable with the same name themselves.

We have a program whose name is gvien by programname. Zero or more variables will be declared in the usual place. These are the global variables. They will be available from all procedures. I will refer to these as g1, g2, ... gm.

Then there are r outer procedures. They can be called from anywhere, either inside another procedure or from the main program. I will refer to their names as o1, o2, ... or.

Each of these outer procedures will have mi parameters where i is the number of the outer procedure.

These will be referred to as opi,y where i is the number of of the outer(0*0*0*Ԍprocedure.

and y will be from 1 to mi designating the indivdidual parameter. Note that inside procedure oi, any reference to the name opi,y will be to this parameter and not to any global name that might happen to be the same name. We see that the name opi,y is local to the proecure oi

In addition, there will be local variables for procedure oi. Their names will be referred to by oloci,j where i tells which procedure the local variable declared. The second item ",j" simply gives the name. These will be numbered from 1 to ni. ni simply states how many local variables there are for outer procedure i.

Within the body of oi, any reference to a variable xxx will be to opi,1, opi,2, ... opi,m1 or oloci,1, oloci,2, .. oloci,ni if the name xxx matches the variable. By match means that the xxx is spelled precisely as the above variable name.

If there is no such match, then the machine will use gi if gi matches xxx. Otherwise, the compiler will fail with a syntax error that xxx is not "defined."

Note that inside such a subroutine, the computer will not use variables declared as parameters or locally to any other outer subroutine or to any inner subroutine.

Also, note that if the computer has two variables with the same name where one is delcared inside the outer procedure and the other is global, the computer will use the one in the outer procedure for statements occurring within the outer procedure.

If there is call to a procedure, ppp, within oi the computer will first see if any of the internal procedures, inneri,1, inneri,2, inneri,qi match the name. If so, that procedure will be used. Then the computer will check for the other outer procedures, o1, o2, ..., or to see if that name matches. If there is no such match, then the computer will report an undefined error.

Note that the computer will never use an inner procedure for any call, except within the outer procedure in which it was declared.

Now, we look at what happens when we call procedures or use variables inside inner procedures.

Let us assume that the reference occurs inside inneri,j.

(0*0*0*Ԍvariablenames, vvvv.

First the computer checks to see if vvv matches any of the parameters, ipi,j,1, ipi,j,2, ..., ipi,j,mij. If so, it will use this reference.

Then, the computer checks to see if vvv matches any of the local variables to the inner procedure, iloci,j,1, iloci,j,2, iloci,j,nij.

If none of these match, the computer will now check the local variables to the outer procedure containing this inner procedure.

So, then, the computer will check if vvv matches any of the parameters, opi,1, opi,2, ..., opi,m1. Then, the computer will check the local variables oloci,1, oloci,2, oloci,n1.

Lastly, the computer will check the global variables, g1, g2,...,gm.

procedurenames, pppp.

First the computer will check to see if ppp matches any of the procedures,

inneri,1, inneri,2, ..., inneri,qi.

If so, that will be the procedure called.

If it doesn't, the computer will check the outer procedures,

o1, o2, ... , or.

In the example below, we say that we have procedures nested two deep. We have the outer procedures nested one deep within the main program. Within the outer procedures, we have inner procedures which are nested two deep.

Note that it is possible that one could write a PASCAL program, where the nesting is arbitrarily deep. The concepts extend in the logical manner. I may include such problems in the homework to see if you can see the logical extension of the pattern.


program programname;

var  g1 : typeg1;(0*0*0*Ԍ     g2 : typeg2;
     .
     .
     .
     gm : typegn;

procedure o1(   {var} op1,1 :
typeop1,1;
               {var} op1,2 : typeop1,2;
                .
                .
                .
               {var} op1,m1 : typeop1,m1 
);
var  oloc1,1 : typeoloc1,1;
     oloc1,2 : typeoloc1,2;
      .
      .
      .
     oloc1,n1 : typeoloc1,n1;

procedure inner1,1 {var} ip1,1,1 :
typeip1,1,1;
               {var} ip1,1,2 :
typeip1,1,2;
                .
                .
                .
               {var} ip1,1,m11 :
typeip1,1,m11 
);
var  iloc1,1,1 : typeiloc1,1,1;
     iloc1,1,2 : typeiloc1,1,2;
      .
      .
      .
     iloc1,1,n11 : typeiloc1,1,n11; 
begin

body of inner1,1

end;  (0*0*0*Ԍ

procedure inner1,2 {var}
ip1,2,1 : typei1p1,2,1;
               {var} ip1,2,2 :
typei1p1,2,2;
                .
                .
                .
               {var} ip1,2,m11 :
typei1p1,m11 
);
var  iloc1,1,1 : typeiloc1,1,1;
     iloc1,1,2 : typeiloc1,1,2;
      .
      .
      .
     iloc1,1,n12 : typeiloc1,1,n12; 
begin

body of inner1,2

end;

.
.

.

procedure i1,q1 {var} ip1,q1,1 :
typei1p1,q1,1;
               {var} ip1,q1,2 :
typei1p1,q1,2;
                .
                .
                .
               {var} ip1,q1,m11 :
typei1pq1,m11 
);
var  iloc1,q1,1 : typeiloc1,q1,1;
     iloc1,q1,2 : typeiloc1,q1,2;
      .
      .
      .
     iloc1,q1,n1q1 : typeiloc1,q1,n1q1; 
(0*0*0*Ԍbegin

body of inner1,q1

end;

begin

body of o1

end;

procedure o2(   {var} op2,1
: typeop2,1;
               {var} op2,2 : typeop2,2;
                .
                .
                .
               {var} op2,m2 : typeop2,m2 
);
var  oloc2,1 : typeoloc2,1;
     oloc2,2 : typeoloc2,2;
      .
      .
      .
     oloc2,n2 : typeoloc2,n2;

procedure inner2,1 {var} ip2,1,1 :
typeip2,1,1;
               {var} ip2,1,2 :
typeip2,1,2;
                .
                .
                .
               {var} ip2,1,m11 :
typeip2,1,m11 
);
var  iloc2,1,1 : typeiloc2,1,1;
     iloc2,1,2 : typeiloc2,1,2;
      .
      .
      .
     iloc2,1,n21 : typeiloc2,1,n21; 
begin(0*0*0*Ԍ

body of inner2,1

end;

procedure inner2,2 {var}
ip2,2,1 : typei1p2,2,1;
               {var} ip2,2,2 :
typei1p2,2,2;
                .
                .
                .
               {var} ip2,2,m11 :
typei2p1,m11 
);
var  iloc2,2,1 : typeiloc2,2,1;
     iloc2,2,2 : typeiloc2,2,2;
      .
      .
      .
     iloc2,2,n22 : typeiloc2,2,n22; 
begin

body of inner2,2

end;

.
.

.

procedure i2,q2 {var} ip2,q2,1 :
typei1p2,q2,1;
               {var} ip2,q2,2 :
typei1p2,q2,2;
                .
                .
                .
               {var} ip2,q2,m11 :
typei2pq2,m11 
);
var  iloc2,q2,1 : typeiloc2,q2,1;(0*0*0*Ԍ     iloc2,q2,2 : typeiloc2,q2,2;
      .
      .
      .
     iloc2,q2,n2q2 : typeiloc2,q2,n2q2; 
begin

body of inner2,q2

end;

begin

body of o2

end;

procedure or(   {var} opr,1
: typeopr,1;
               {var} opr,2 : typeopr,2;
                .
                .
                .
               {var} opr,mr : typeopr,mr 
);
var  olocr,1 : typeolocr,1;
     olocr,2 : typeolocr,2;
      .
      .
      .
     olocr,nr : typeolocr,nr;

procedure innerr,1 {var} ipr,1,1 :
typeipr,1,1;
               {var} ipr,1,2 : typeipr,1,2;
                .
                .
                .
               {var} ipr,1,m11 :
typeipr,1,m11 
);
var  ilocr,1,1 : typeilocr,1,1;
     ilocr,1,2 : typeilocr,1,2;
      .(	0*0*0*Ԍ      .
      .
     ilocr,1,nr1 : typeilocr,1,nr1; 
begin

body of innerr,1

end;

procedure ir,2  {var} ipr,2,1
: typei1pr,2,1;
               {var} ipr,2,2 :
typei1pr,2,2;
                .
                .
                .
               {var} ipr,2,mr1 :
typeirp1,mr1 
);
var  ilocr,2,1 : typeilocr,2,1;
     ilocr,2,2 : typeilocr,2,2;
      .
      .
      .
     ilocr,1,nr2 : typeilocr,1,nr2; 
begin

body of inner2,2

end;

.
.

.

procedure innerr,qr {var} ipr,qr,1 :
typei1pr,qr,1;
               {var} ipr,qr,2 :
typei1pr,qr,2;
                .
                .
                .(
0*0*0*Ԍ               {var} ipr,qr,mrqr :
typeirpqr,mrqr 
);
var  ilocr,qr,1 : typeilocr,qr,1;
     ilocr,qr,2 : typeilocr,qr,2;
      .
      .
      .
     ilocr,qr,nr,qr : typeilocr,qr,nr,qr; 
begin

body of innerr,qr

end;

begin

body of or

end;

begin

body of main program

end;



Below, you will find an example that will illustrate these ideas.

The programname is given by demoscope.

There are six global variables given by the names

g1       sugar
g2       vinegar
g3       salt
g4       spice
g5       ketchup
g6       mustard 
There are two outer procedures, tin and bronze . O1 is "tin"

It has two parameters, ( 0*0*0*Ԍ

op1,1    pear
op1,2    apple 
It has two local variables to it. These are
i1,1     acetic
i1,2     nitric
i1,3     sulfuric
i1,4     spice 
"tin" has two internal procedures, "milk" i1,1 and "soda" i1,2.

"milk" has two parameters.

ip1,1,1   sulfuric
ip1,1,2   nitric 
And it has one local variable
iloc1,1,1   nitric 
The other inner procedure for the outer procedure tin is called soda, i1,2.

It has one parameter:

ip1,2,1   x 
It also has only one local variable.
iloc1,2,1   sulfuric 
The second procedure begins on line 59, bronze, o2.

It has two parameters.

op2,1    mustard
op2,2    ketchup 
and two local variables:
iloc2,2,1   sulfuric
iloc2,2,2   vinegar 
There is one procedures defined within it, tin, i2,1.( 0*0*0*Ԍ

It has one parameter.

ip2,1,1   salt 
and no local variable.

Now that we have identified our various global and local procedures and variables, it is time to determine precisely what our program will do.

In lines 8186, we set our six global variables, g1 g6 to initial values.

In line 87, we call tin. The value of ketchup is copied to pear and the value of mustard is copied to apple.

Then we go to line 41, which is the beginning of the code for tin.

In line 42, we copy pear to acetic. acetic is a variable local to "tin" iloc1,1.

Line 43 increments this and then it is printed out.

Then in line 45, the variable sugar is incremented. Note that since sugar is not declared in lines 11 to 14, we look in the list of global variables. and change it from 11 to 12.

Apple, the second parameter is also incremented to 67. In line 47, we display the new value of sugar in tin. This is 12.

We change spice to 15 in lines 48 to 49. This is one of the local variables so we increment the one declared in line 14. Note, that the variable declared in line 5 is not changed.

In line 50, soda is called. The value of spice declared in line 14 is passed to the x parameter specified in line 26. So 15 is copied to the x in soda.

The variable sulfuric in soda is incremented. This will be the one declared in line 27. Thus, you will be adding one to an undefined value.and the print out in line 30 will print some random garbage.

The variable "sugar" is set to trunc(x). The routine func is used to convert from floating point (x) to integer (sugar). That sets sugar to 15 which is printed out in line 32. Note that this sets the global variable sugar which was define din line 2.

Then in line 33, nitric is incremented by ten. This is the variable nitric defined in line( 0*0*0*Ԍ17 (local to tin) as there is no nitric declared local to soda.

Then nitric, sugar, pear and apple are all printed out giving 15, 55, 67.

Upon return, the value of x is returned to spice, but nothing has changed.

Now, sulfuric, sice and sugar are allprinted out. Sulfuric will be the original value and won't be effected by the actions of line 29. That is because line 29 modified the sulfuric defined in line 27. The variable sulfuric printed out in line 53 is the one defined in line 13.

In line 54, the routine milk is called. During, the call sugar is copied to sulfuric. However, the sulfuric copied to is a new sulfuric, one associated with line 16. This is a different box from the one in line 13. Likewise, the variable sulfuric in line 54 is copied to the variable sugar in line 16. Again, this sugar is a different box from the one defined in line 2.

In line 19, the sugar (defined in 16) is set to 6. Then, the sulfuric defined in line 16 is printed out which will cause 15 to be output. This box is now incremented to 115.

The variable salt is printed out. This will be the value 33, for the box defined in line 4.

Then, the procedure milk routines. The 115 in the sulfuric is copied back to the sugar used in line 54. Note that 115 is now copied to the sugar defined in 2.

Also, the six in the parameter sugar is copied back to sulfuric. changing the box, sulfuric defined in line 13.

Thus, 115 would be printed out by line 55 and 6 by line 56.

At this point the program returns from tin. The value of pear (55) is copied to ketchup. And the value of apple, which is now 67 is copied to mustard.

Then the global variables are printed out in lines 89 to 93.

Then bronze is called. Observe that again, the global variable ketchup is copied to the parameter mustard. And the global variable mustard is copied parameter ketchup. These parameters are the ones on line 59.

At this point, the statement in line 73 will execute. This is a call to the procedure "tin" Observe that we call i2,1 and not o1. That is we call the procedure tin on line 62.

The variable vintegar is copied to the value of salt. At this point "salt" is undefined as nothing was put in the vinegar defined on line 61.(0*0*0*Ԍ

Sulfuric is set to 77 on line 64. However, this is the variable sulfuric oloc2,1 on line 60.

Line 65 sets vinegar to mustard (now 55). That is the value of the parameter mustard (declared line 59) is copied to the variable vinegar (declared line 61).

Then line 66, will put 55+1 into ketchup. Lines 67 to 69 will output that sulfuric is 77, vinegar is 55 and ketchup is changed to 56. salt is changed to 4. This is the parameter defined on line 62.

When we return from the call in tin, salt will NOT be copied back to vinegar. Why? Salt is not a var parameter.

Lines 74 to 77 output the current values of sulfuric, vinegar, mustard, ketchup. These are 77, 55, 55, and 56.

At this point, the flow of control returns to main program where the global variables are again printed out in lines 95 to 100. Notice that the only one to have changed is mustard which is now 56.



 U66B.PAS