A program is presented to the computer as a length of perforated paper tape, prepared on a Flexowriter keyboard machine, the keys of which are engraved with the following symbols:-
ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz α β π 0123456789 = > < | * : , ' & 2 / . + _ ½ ( ) [ ] ?
A back-spacing facility allows underlining and also the formation of compound characters. For example :-
cycle ≠ ≥ ≤ ; ↑
The last of these created on a Flexowriter consists of an asterisk superimposed on a vertical bar. It is usually referred to as a vertical arrow (and would be written as such in a manuscript) and is used to denote exponentiation, thus a↑(n-1) means a raised to the power (n-1). Such a notation is necessary because we have no means of effecting superscripts and subscripts with a Flexowriter; the format is essentially one dimensional. There is one exception, the superscript 2 for which there is a special symbol: it is equivalent to ↑2.
Since the handbook itself is prepared on a Flexowriter the same conventions for exponents will also be used in the text.
In this document the Flexowriter symbol has been replaced by the up arrow.
NOTE All spaces and underline spaces in a program are ignored when the program is read into the machine. Thus they may be used freely to assist legibility in the written form of the program.
These are used to identify the various operands, functions and routines which appear in the program. A name consists of one or more Roman letters, possibly followed by one or more decimal digits, and possibly terminated by one or more primes('). For example:-
X I Alpha a10 TEMP1 y'' b3'
Underlined names and mixed names such as RK2ST are not allowed.
There are certain names, e.g. log, sin, exp, print, read, etc. which have a standard meaning (the permanent routines) but all other names must be declared before any reference is made to them (see below). In future a general name will be denoted by [NAME].
Numerical (positive) constants are written in a straight forward notation. For example:-
2.538 1 .25 17.28α-1 1α7
The last two examples mean 1.728 and 10000000.
The numerical part can be written in any number of ways. For example:-
15 015 15. 15.000
are all equivalent. The exponent, where present, consists of α followed by an optional sign and decimal digits. The symbol ½ is equivalent to the two symbols .5. Thus 2.5 may be punched as 2½.
There is a further specialised type of constant consisting of a symbol (either basic or composite) enclosed in quotes. Its value is that of the internal equivalent of the symbol, a list of which is given in Appendix 5. Thus
'a' ≡ 33 'φ' ≡ 2063
Though this form of constant may be used whenever a constant is relevant it is most often used when reading symbols off a data tape (see Section 5).
These are a preassigned set of symbols and underlined words. For example:-
+ - * / ( , ) > ≥ -> ; π cycle repeat integer real if then caption comment
Note that ->; consists of two symbols, - followed by >
Unlike names whose meaning can be defined by the user, delimiters have fixed absolute meanings in the language.
Calculations are performed on two principal types of operand, real and integer (later on we shall introduce complex). Both are represented by floating point numbers (in the form a*8↑b where a is held to a precision of 40 binary digits and b is an 8-bit integer); but those of integer type are kept in an unstandardised form (so that the least significant 24 bits can be used directly for B-modification; the precise method of storage is described in the section on machine instructions).
The locations in the computer store holding numbers are distinguished by assigning names to them (see later), and reference to the number is made by giving the appropriate name. Both real and integer numbers referred to in this way are called variables and denoted by [VARIABLE].
Programs will consist mainly of operations on real operands, the use of integer operands being generally confined to counting and subscript arithmetic.
The names of variables used in a block are declared at the head of the block; For example:-
integer I, max, min real t, Temp, VOL 1, VOL 2
The effect of these declarations is to allocate storage positions (addresses) to the named variables, and any subsequent reference to one of the declared names will then be taken as referring to the number stored in the appropriate address. The format of these declarations is formally
[TYPE][NAME LIST] where [TYPE] = integer, real [NAME LIST] = [NAME][REST OF NAME LIST] [REST OF NAME LIST] = [,][NAME][REST OF NAME LIST],NIL
N.B. This means of defining a list consisting of phrases separated by commas is used throughout: See Appendix 1.
One dimensional arrays of elements may be declared by statements such as
array a,b(0:99), c(10:19)
which reserves space for three arrays of real variables a(i), b(i), c(i). In the first two the subscript runs from 0 to 99, and in the third from 10 to 19.
To refer to a particular element of an array one might write
a(50) b(j) b(2n+2j-1) c(10+i)
It is the computed value of the argument, which may be a general integer expression (see later), which determines the particular element.
Two dimensional arrays are declared in a similar way. For example:-
array A(1:20,1:20), B(0:9,0:49)
This defines and allocates storage for a 20 X 20 array A and a 10 X 50 array B. To refer to a particular element, one writes, tor example:-
A(1,1) A(i-1,j+1) B(9,2K+1)
Should an array of integer elements be required, the declaration is qualified by integer. For example:-
integer array Ka (1:50).
Arrays of more than 2 dimensions may also be declared. For example:-
array CUBE 1, CUBE 2 (1:10,1:10,1:10)
reserves 1000 locations for each of the two arrays CUBE 1, CUBE 2.
Storage allocated by all the above declarations has dynamic significance, i.e. they are implemented at run time and not at compiler time. Consequently, the arguments in array declarations need not be constants but may be general integer expressions. The significance of this will be explained in the sections on block structure and dynamic storage allocation (see later).
The format of an array declaration is
[TYPE'] array [ARRAY LIST] where [TYPE'] = integer , real , NIL [ARRAY LIST] = [NAME LIST] ([BOUND PAIR LIST])[REST OF ARRAY LIST] [BOUND PAIR] = [EXPR]:[EXPR]
Here the [EXPR]'S must be integer [EXPR]'S (see Section 2.10).
Functional dependence is indicated by writing the name of the function followed by the list of arguments in parentheses (in a similar fashion to array elements). For example:-
sin(2πx/a) arctan(x,y) TEMP(i) a(10,10)
Each argument can be an arithmetical expression (see below).
Within a block all names must be distinct, and it is not possible to have a function with the same name as a scalar. Thus a and a(i) or f and f(x) would NOT be allowed to appear in the same block.
Certain standard functions are available and may be used directly in arithmetic expressions (see next section) without formal declaration:
sin(x) cos(x) tan(x) log(x) exp(x) sqrt(x) arcsin(x) (-π/2 ≤ result ≤ π/2) arccos(x) (0 ≤ result ≤ π) arctan(x,y) (= arctan (y/x), -π ≤ result ≤ π) radius(x,y) (= sqrt (x2+y2) ) mod(x) (= |x|) fracpt(x) (= fractional part of x) intpt(x) (= integral part of x) int(x) (= nearest integer to x. i.e. intpt(x+.5)) parity(n) (= (-1)↑n)
The last three functions are of type integer (see later), the rest of type real. The arguments of all these functions may be general expressions, except that the argument of the last must be of type integer.
A complete list of standard functions is given in Appendix 2.
A general arithmetical expression is denoted by [EXPR] and consists of an alternating sequence of operands and operators possibly preceded by a sign symbol, thus
[±'] [OPERAND][OPERATOR][OPERAND][OPERATOR] .... [OPERAND]
Or, more strictly, (See Appendix 1.)
[EXPR] = [±'][EXPR'] [EXPR'] = [OPERAND][OP][EXPR'],[OPERAND] [OPERAND] = [NAME][APP],[CONST],([EXPR]),|[EXPR]| [±'] = +,-,NIL
An [OPERAND] is a [VARIABLE], [CONSTANT], ([EXPR]), |[EXPR]|, or [FUNCTION], and an [OPERATOR] is one of + - * / ↑ (the asterisk denoting multiplication).
An explicit multiplication sign is not required when ambiguity could not arise from its omission. For example:-
2.5a1b means 2.5*a1*b
NOTE: When the compiler looks for a name, it finds the longest possible name. Thus ab is taken as a name rather than a*b even if only a and b and not ab were declared. In this case a fault (NAME ab NOT SET) would be indicated. Examples of expressions are:-
A(i-1,j) + A(i+1,j) + A(i,j-1) + A(i,j+1) - 4A(i,j) Z + log(1 + cos(2π(x/a + y/b + z/c))) LENGTH * BREADTH * HEIGHT 1 + sqrt(x(i)2 + y(i)2 + z(i)2) a * b/c * d/e (x + y + z)/(a + b + c) 2.5x1b * (c + d)e e = |x-y| + .00001 (1+x)↑(n-3) * (1-x)↑3
An [EXPR] is an integer [EXPR] if all the [OPERAND]'s are scalars, array elements etc, declared to be of type integer, or are integer constants or integer functions (e.g. int, intpt, or parity). Thus if we assume that x is a real [VARIABLE] and i,n,j,k(1),k(2) are integer [VARIABLE]'s the following are integer [EXPR]'s.
m*(n-1)/2 i + j + k(2) + int(x) j ↑ k intpt(n*(n-1)/3)
The definition given above does not guarantee that an integer [EXPR] will always give an integral result, e.g., 10/3 and j↑(-1) are not integral. There is no guarantee either that expressions like n*(n-1)/2(which is integral) will always yield the exact answer (in this particular case it does). When the result of such an operation is in doubt it is preferable to use 'int' e.g., int(n*(n-1)/2) to give an exact integer result.
Except in certain special cases integer [EXPR]'s are evaluated by floating point arithmetic in exactly the same way as general (real) expressions, but are destandardised on assignment (explicit or implicit) to their integer destination. The definition of an integer [EXPR] is a basis for checking that such assignments are sensible. The special cases mentioned above refer to the subscript expressions in array elements. Such expressions, which should always be integer [EXPR]'s are usually simple linear forms which are dealt with more appropriately by B-modification. It is mainly to facilitate such operations (and the associated operation of counting) that integer's are used. Being destandardised quantities they can be transferred directly to B-registers without using the floating point accumulator.
The general arithmetic instruction is
[VARIABLE] = [EXPR]
Examples are:-
X(p,q) = 1+2cos(2π(x+y)) a = (b+c)/(d+e)+F i = i+1
The action of the general arithmetic assignment is to place the computed value of the [EXPR] in the location allocated to the l.h.s. [VARIABLE]. If the l.h.s. is a real [VARIABLE], the r.h.s. [EXPR] may be of type real or integer, but if the l.h.s. is integer then the r.h.s. must be an integer [EXPR]. For example, if y had been declared real and i integer then we could write y = i but not i = y even if we knew that y had an integral value.
Normally instructions are obeyed sequentially, but frequently it is required to transfer control to some instruction other than the next in the sequence, or to obey an instruction only if certain conditions are satisfied. The facilities provided are defined in the following sections.
Any instruction can be labelled by writing an integer [N] before it, separated by a colon. More than one label is permitted. Unconditional jump instructions are written as -> [N]
->10 --- 10: --- 4:5: --- ->4 --- ->5
These are used to provide for a multi-way switch.
switch A(1 : 3) --- --- A(1): --- --- A(3): --- --- --- ->A(i) --- --- A(2): --- ---
With reference to the accompanying diagram the instruction -> A(i) will jump to A(1), A(2) or A(3) according as i = 1, 2 or 3.
A fault is signalled if the value of i corresponds in any way to a label not set. The general form of the label is [NAME]([N]): The range must be declared at the head of the routine by a statement of the form switch [NAME]([±'][N]:[±'][N]) where the [±'] indicates that the integers may be preceded by a sign if necessary. For example:-
switch SEGMENT (-4:+4)
A list of switches can be given. For example:-
switch A,B,C(1:3),D(0:2)
The [NAME]'s must not conflict with those of other operands in the same block.
Another kind of multi-way switch is illustrated by the accompanying diagram.
test 4, 5, 6 --- --- 4 case x<1:--- --- 5 case 0≤x≤1:--- --- 6 case x>1:--- --- ---
Here the conditions at the places indicated are tested in turn and control passes to the instruction following the first to be successful. If none is satisfied a fault is signalled. The general form of the label is [N] case [COND]: where [COND] denotes the general condition defined in the next section. A simple label [N]: may be used in place of the last alternative(i.e. 6:) in which case control passes directly to the following instructions if it reaches that point.
NOTE All labels are local to the block containing them and jump instructions may only refer to labels within the block (see later).
A CONDITIONAL OPERATOR of the form
if [COND] then or unless [COND] then
may be written before any unconditional instruction. These form the FORMAT CLASS [UI] (see Appendix 1) and include arithmetic, jump and test instructions.
The [COND] phrase takes one of the forms:
[SC] and [SC] and [SC] --- and [SC] or [SC] or [SC] or [SC] --- or [SC] or just [SC]
or, more strictly, (see Appendix 1)
[COND] = [SC] and [AND-C], [SC] or [OR-C], [SC] [AND-C] = [SC] and [AND-C],[SC] [OR-C] = [SC] or [OR-C],[SC]
Here [SC] denotes one of the following simple conditions
[EXPR][φ][EXPR] or [EXPR][φ][EXPR][φ][EXPR] or [(COND])
where [φ] denotes one of the comparison symbols = ≠ > ≥ < ≤ If (or unless) the condition is satisfied the instruction is obeyed, otherwise it is skipped and control passes directly to the next instruction.
Examples of conditional instructions and conditional labels are
if x < 0 then x = mod(y) if 0 ≤ x ≤ 1 and 0 ≤ y ≤ 1 then -> 1 case (y > 1 or y < - 1) and x ≥ 0:
Alternatively, conditional operators may appear after unconditional instructions, in which case they are written
if [COND] or unless [COND]
for example
x = 0 if |x| < .0000001 -> 1 unless z > R or z = 0
These are pairs of statements which allow a group of instructions to be obeyed a fixed number of times. For example:-
cycle i = 0, 1, n-1 --- --- --- repeat
In the above example the instructions between cycle and repeat are traversed n times, with i successively taking the values 0,1, ...,n-1. After the final cycle, control goes to the statement following repeat. The l.h.s. must be an integer name, but the r.h.s. quantities may be general integer [EXPR]'s which are initially evaluated and stored. Thus within the innermost cycle of the example below, the values of p,q and r may be altered without affecting the number of times the cycle is traversed. The initial value, increment, and final value must be such that
(final value - initial value) / increment
must be a positive integer or zero otherwise a fault is indicated. For example:-
cycle i = 1,1,p cycle k = 1,1,r c(i,k) = 0 repeat cycle j = 1,1,q cycle k = 1,1,r c(i,k) = c(i,k) + a(i,j)*b(j,k) repeat repeat repeat
NOTE Statements such as cycle x = .2,.1,1 are not allowed,and should be replaced by an equivalent permissible form. For example:-
cycle i = 2,1,10 x = .1i
where i has keen declared integer and x real.
upper case delimitersand then writing all following delimiters in upper case without the underlining.
Thus the example above could then be written:-
CYCLE i = 1,1,p CYCLE k = 1,1,r c(i,k) = 0 REPEAT CYCLE j = 1,1,q CYCLE k = 1,1,r c(i,k) = c(i,k) + a(i,j)*b(j,k) REPEAT REPEAT REPEAT
The delimiter causes the compiler to replace each upper case letter by the equivalent underlined lower case letter, so that a mixture of normal and upper case delimiters can be used. If this is required only for certain parts of a program then the instruction
normal delimiters
can be used to return the compiler to its normal operation.