Contact us Heritage collections Image license terms
HOME ACL Associates Technology Literature Applications Society Software revisited
Further reading □ PrefaceContents1 Introduction2 The basic language3 Storage and block structure of programs4 Routines5 Data I/O6 Monitor printing and fault diagnosis7 Presentation of complete programs8 Complex arithmetic9 Store Mapping10 The use of machine instructions11 Permanent routines □ Appendices and indices □ A1 Phrase structure notationA2 Standard functions and permanent routinesA3 DelimitersA4 Monitored faultsA5 Numerical equivalents of symbols
ACD C&A INF CCD CISD Archives Contact us Heritage archives Image license terms

Search

   
ACLLiteratureAtlas manualsAtlas Autocode :: ATLAS AUTOCODE REFERENCE MANUAL
ACLLiteratureAtlas manualsAtlas Autocode :: ATLAS AUTOCODE REFERENCE MANUAL
ACL ACD C&A INF CCD CISD Archives
Further reading

Preface
Contents
1 Introduction
2 The basic language
3 Storage and block structure of programs
4 Routines
5 Data I/O
6 Monitor printing and fault diagnosis
7 Presentation of complete programs
8 Complex arithmetic
9 Store Mapping
10 The use of machine instructions
11 Permanent routines
Appendices and indices
A1 Phrase structure notation
A2 Standard functions and permanent routines
A3 Delimiters
A4 Monitored faults
A5 Numerical equivalents of symbols

4 Routines

4.1 Basic Concepts

A large program is usually made up of several routines each of which represents some characteristic part of the calculation. Such routines may be called in at several different points in the program, and their design and use is a fundamental feature of the language. The introductory example consisted of a main block only (delimited by begin and end of program) although it makes reference to the routines 'read', 'print', 'newline', which are permanently available in the machine. In exactly the same way however, the user may call in routines which he has written himself in Autocode language. Consider for example a routine to evaluate

y = a(m) + a(m+1)x+...........+ a(m+n)x↑n     (n ≥ 0)

where the coefficients are selected from some vector a.

 
routine poly(real name y, array name a, real x, integer m,n)
integer i
y = a(m+n) ; return if n = 0
cycle i = m+n-1,-1,m
y = x*y+a(i)
repeat 
return 
end
         

Given the values of x,m,n and the addresses of y and the array elements a(i), it evaluates the polynomial and sets y to this value.

The statement end is the formal or written end of the routine while return is the dynamic end, i.e. it is the instruction which returns control to the main routine. Where the formal end is also a dynamic end as in the present example the return instruction preceding end can be omitted; in this case end serves for both purposes.

NOTES

1: There can be any number of alternative exit points in a routine - i.e. return can occur more than once.

2: return is a member of the FORMAT CLASS[UI] - i.e. it can be made conditional, as above.

This routine can be embedded and used in a main routine as illustrated below.

 
begin 
real U, V, z, x ; integer m
array b(0:15), c(0:50)
routine spec poly (realname y, array name a, real x, integer m,n)
---
---
poly(U,b,z,0,m)
---
---
poly(V,c,x2,20,10)
---
---
stop 

routine poly(realname y, array name a, real x, integer m,n)
integer i
y = a(m+n); return if n = 0
cycle i = m+n-1,-1,m
y = x*y+a(i)
repeat 
return 
end 
          
end of program
         

The routine is called in by the main routine whenever the name 'poly' appears. The first reference to 'poly' would cause the poly routine to evaluate

U = b(0) + b(1)z + ... + b(m)z↑m

and the second would cause it to evaluate

V = c(20) + c(21)x2 + ... + c(30)x↑20

The parameters in the routine specification and routine heading are the formal parameters and the parameters in the call statements are the actual parameters (see next section).

The body of the routine may be considered as a block delimited by routine and end, and the concepts of storage allocation, local and non-local names etc. apply to routines in exactly the sane manner as for blocks. In fact a block may be considered as being an open routine without parameters.

Any number of routines may be embedded in a main routine in the above fashion and they are referred to as subroutines of the main routine. If the body of a subroutine occurs before any reference to it in the main routine, the routine specification may be omitted, but by convention it is usual to place all the subroutine specifications among the declarations at the head of the main routine and the bodies at the end.

4.2 Formal Parameters and Actual Parameters

The parameters of the routine are the items of information which specify the action of the routine whenever it is used. The formal parameters are the names by which this information is referred to inside the routine itself, and the actual parameters are the names or expressions which are substituted for the formal parameters whenever the routine is used in the main program. For each type of formal parameter there is a permissible form for the actual parameter, as shown in the following table:-

Formal parameter type Corresponding actual parameter
integer name name of an integer variable
real name name of a real variable
integer an integer [EXPR] (similar to an integer assignment)
real a general(i.e. real or integer)[EXPR] (similar to a real assignment)
integer array name name of an integer array
array name name of a (real) array
integer array name of an integer array
array name of a (real) array (the difference between these and the previous pair of parameters is explained below)
routine type i.e.
routine
real fn
integer fn
Sometimes it is required to pass on the name of a routine as a parameter. In this case the actual parameter is the name of a routine which must correspond in type and specification with the formal parameter, the specification of which will be found in the routine body

In the example of a routine to evaluate a polynomial described earlier, the formal parameter y is the name of the variable to which the result is assigned, and the corresponding actual parameter must be a name, in this case the name of a real variable. The formal parameter then is of type real name. A reference to y inside the routine is essentially a reference to the non-local variable named by the actual parameter. The same applies to the array name parameter a, a reference to a inside the routine being a reference to the non-local array whose name is substituted for a in the calling statement.

The formal parameter real x on the other hand can be replaced by a general arithmetic expression, which is evaluated and assigned to the local variable x which is specially created in addition to any local real variables declared in the routine, The same applies to the formal parameters integer m,n. These are essentially local quantities, and expressions are substituted in place of them are evaluated and the resultant values assigned to the local integer variables m and n, which are lost on exit from the routine. Consequently the routine should place the information it produces in variables which are called by NAME (such as x and a).

The formal parameters x, m, n are said to be called by value in so far as it is only the values of the corresponding actual parameters which are of interest. This is the essential difference between the formal parameter types array and array name (or integer array and integer array name). In the former case the array named by the actual parameter is copied into a specially created local array, and a reference to the name in the routine is taken as referring to this local array. As the copying process can be time-consuming and space-consuming arrays should be called by name if at all possible, especially if they are large. Another example of a routine is the following

 
routine matmult(arrayname A,B,C integer p,q,r)
integer i,j,k ; real c
cycle  i = 1,1,p
cycle j = 1,1,r
c = 0
cycle k = 1,1,q
c = c+A(i,k)*B(k,j)
repeat
C(i,j) = c
repeat 
repeat 
end
         

This forms the product of a p × q matrix A and a q × r matrix B. The result, a p × r matrix, is accumulated in C. The routine assumes that the first element of each matrix has the suffix (1,1). A typical call sequence might be

mat mult(N, x, y, 20, 20, 1)

where N, x, y had been declared by

 
array N(1:20,1:20), x,y(1:20,1:1)

4.3 Function Routines

When a routine has a single output value it may be written as a function routine and then used in an arithmetic expression in the same way as the permanent functions (cos, sin etc.). For example, the polynomial routine described earlier may be recast as a function routine as follows:-

 
real fn poly(arrayname a, real x, integer m,n)
integer i ; real y
y = a(m+n) ; if n = 0 then result = y
cycle i = m+n-1,-1,m
y = y*x+a(i)
repeat 
result = y
end
         
NOTES

1: In general, the exit from a routine is of the form : result = [EXPR] and this causes the EXPRESSION on the right hand side to be evaluated as the value of the function.

2: result = [EXPR] acts as the dynamic end of a function (i.e. it corresponds to return in a routine), and may appear any number of times within the function.

3: result = [EXPR] is a number of the FORMAT CLASS[UI] - i.e. it may be made conditional.

The specification of the above routine would be written

 
real fn spec poly(arrayname a, real x, integer m,n)

and the routine can be called in an arithmetic statement, for example

y = a*b + 2h*poly(c,1/x,0,16)

An example of an integer function is given next. It selects the index of the maximum element x(k) in a set of array elements x(m), x(m+1),....,x(n) (n≥ m)

 
   integer fn max(arrayname x, integer m,n)
   integer i,k
   k = m
   ->1 if n = m
   cycle i = m+1,1,n
   k = i if x(i) > x(k)
   repeat
1: result = k
   end
         

A call sequence for this function routine might be

y = 1 + x(max(x,1,100))

4.4 Scope of Names

In general all names are declared at the head of a routine either in the routine heading or by the declarations integer, real, array, etc., and the various routine specifications.

Therefore they are local to that routine and independent of any names occurring in other routines. However, if a name appears in a routine which has not been declared in one of the above ways, then it is looked for outside i.e. in the routine or block in which it is embedded. If it is not declared there it is looked for in the routine or block outside that and so on until the main block is reached.

Now the main block is itself embedded in a permanent block at 'zero level' which contains the permanent material, so that if a name is not found in the main block it is looked for among these. The permanent names may in fact be redeclared locally at any level, but clearly it would be unwise to assign new meanings to such routines as 'log', 'print', etc. This outer block also contains supervisory material for controlling the entry to and exit from the main block. Very often, the only non-local names used in a routine will be the permanent names. The level at which a name is declared is sometimes referred to as its 'textual' level.

4.5 Permanent Routines

The permanent names include the standard functions, sin, log, int, etc. and the basic input/output routines read, print etc. These routines are used in a program without declaration and without the necessity of inserting the routine bodies, since these are permanently available at level zero. A full list of the permanent routines is given in Appendix 2.

[NOTE : the standard functions (and the same applies to 'read') are not strictly routines : THEIR NAMES CANNOT BE SUBSTITUTED AS ACTUAL PARAMETERS IN PLACE OF FORMAL PARAMETERS OF ROUTINE TYPE. they would first have to be redefined and renamed as formal routines.]

4.6 Functions and Routines as Parameters

This is illustrated by the following example involving an integration routine

 
routine spec integrate(real name y, real a,b,integer n, real fn f)

which integrates a function f(x) over the range (a, b) by evaluating

y = (f(0) + 4f(1) + 2f(2) + ... + 4f(2n-1) + f(2n))(b-a)/(6n)
where   
f(i) = f(a + ½i*(b-a)/n)

An auxiliary routine is required to evaluate f(x) and details of it must be passed on to the integration routine. This is done by means of the formal parameter type [RT] as defined earlier, and the body of the routine might then be:-

 
routine integrate  (real name y, real a, b, integer n, real fn f)
real fn spec f(real x)
real h;  integer i
h = ½(b-a)/n
y = 0
cycle i = 0,2,2n-2
y = y+2f(a+i*h)+4f(a+(i+1)h)
repeat
y = (y-f(a)+f(b))h/3
end
         

To enable instructions such as

y = y+2f(a+i*h)+4f(a+(i+1)h)

to be translated, a specification of the formal parameter f is required. In this case the delimiter real fn spec can be replaced by spec since the type of the function is given explicitly by the formal parameter itself. Now consider a programme to evaluate

z = exp(-y)cos(b*y)dy

for various values of b read from a data tape, the last value being followed by 1000, using for n the integer nearest to 10b.

 
   begin 
   routine spec integrate (real name y,real a,b,integer n,real fn f)
   real fn spec aux (real y)
   real z, b
   comment Simpson rule integration
1:read (b)
   if b = 1000 then stop
   integrate (z, 0, 1, int(10b), aux)
   newline
   print (b, 1, 2);spaces(2);print(z, 1, 4)
   -> 1
   real fn aux(real y)
   result = exp(-y) cos(b*y)
   end
    -----------------
   |routine integrate|  
    -----------------
end of program
         
NOTES

1: That the names given to the auxiliary routine and its parameters need not be the same in the integration routine as in the main program, but they must correspond in type.

2: Since the result of the integration is a single quantity, the routine could be recast as a real fn :-

 
real fn spec integrate (real a,b, integer n, real fn f)

and called by, for example:-

print(integrate(0,1,int(10b),aux),1,6)

4.7 Recursive Use of Routines

The name of a routine is local to the routine or block in which its specification appears, and so the body of the routine is within the scope of its own name. Hence it may call itself. It may also call itself indirectly by invoking other routines which make use of it. On each activation of the routine a fresh copy of the local working space is set up in the stack, so that there will be no confusion between variables on successive calls. (This does not apply however to own variables. See next section.) Some criterion within the body of the routine must eventually inhibit the calling statement and allow the process to unwind. Functions defined recursively, for example:-

n! = n(n-1)! ,    n > 1
   = 1       ,    n = 1
   

can be implemented in this way, but it is always more efficient to use recurrence rather than recursive techniques.

4.8 Own Variables

When a routine is left any information stored in variables corresponding to local declarations in that routine is lost, and no furthur reference may be made to it. In some cases it may be desirable to retain some of this information and be able to refer to it on a subsequent entry to the routine. This may be accomplished by prefixing the relevant declaration by own. For example

            own real a, b;  own array A (1:10)

The effect of own is to allocate storage space for the named variables in a part of the store which is not overwritten when other routines are called in and to set them to zero. This is done during the compiling of the program and hence does not have dynamic significance; as a consequence an own array declaration must have parameters which are integer constants.

⇑ Top of page
© Chilton Computing and UKRI Science and Technology Facilities Council webmaster@chilton-computing.org.uk
Our thanks to UKRI Science and Technology Facilities Council for hosting this site