casestatement ::=CASE modifier OF statementlist CASEND statementlist ::=statement;|statementlist statement; ifstatement ::=IF logicalexpression THEN simplestatement ELSE statement| IF logicalexpression THEN statement statement ::=simplestatement|complexstatement simplestatement ::=assignment|cellassignment|functionstatement|nonplasydstatement| procedurestatement|casestatement|block|gotostatement|returnstatement| datastatement|obeystatement|NULL|label simplestatement complexstatement ::=ifstatement|forstatement|whilestatement|includestatement| label complexstatement assignment ::=xassignment|rassignment|xxassignntent|rrassignment cellassignment ::=xcellassignment|rcellassignment|xxcellassignment|rrcellassignment logicalexpression ::=andexpression|orexpression|condition andexpression ::=condition AND condition|andexpression AND condition orexpression ::=condition OR condition|orexpression OR condition condition ::=relationex|OVERFLOW|FOVERFLOW|CARRY|NOT OVERFLOW|NOT FOVERFLOW|NOT CARRY relationex ::=xrelationex|rrelationex|xxrelationex|rrrelationex αrelationex ::=αacc relation αprimary {α=r|xx|rr} xrelationex ::=xacc relation xprimary|xacc relation partaddress|xacc charel xprimary partaddress ::=£cellidentifier|$cellidentifier cellidentifier ::=upperidentifier|loweridentifier relation ::=<|>|≤|≥|NOT=|= charel ::=<CH|>CH|≤CH|≥CH forstatement ::=FOR xassignment STEP increment UNTIL xprimary DO statement increment ::=xprimary|-xprimary|CHAR whilestatement ::=WHILE logicalexpression DO statement|DO statement
This causes one only of a number of statements to be obeyed according to the value of a modifier. It is important that each of the statements generates only one machine instruction. For example:
CASE X1 OF A1:=A1+LRX; A1:=A1-LRX; A1:=A1*LRX; A1:=A1/LRX; GOTO LB; X1:=NEG LIX; LIX:=0; URX(X2):=A1; LIX:=LIX+X2; CASEND;
The effect of the statement is to cause the ith instruction of the sequence to be obeyed where the sequence is numbered starting at zero and i is the value of the modifier. In the example above, if X1 had the value 3 then the statement A1:=A1/LRX would be obeyed.
Unless the statement obeyed is a control jump of some kind, the next statement obeyed is the one following the CASEND. The modifier is destroyed by this instruction. For example, X1 will not still have the value 3 after the instruction above has been executed.
The CASE statement is implemented by storing the statements in storage, adding the base of these statements to the modifier and then executing an OBEY instruction with the modifier giving the instruction address.
Care should be taken that the- statements in the CASE only generate single machine code instructions. This does mean that any instruction containing a SMO index is not allowed. Some examples of statements generating a single instruction are:
If in doubt the SWITCH(0) facility will indicate which instructions have been generated.
If the modifier value specifies a non-existent instruction the effect is undefined.
The IF statement has basically two different formats similar to Algol. In the simple form:
IF logical expression THEN statement
the statement following the THEN is only obeyed if the logical expression has a value TRUE. Control is then passed to the statement following the IF statement assuming the one following the THEN is not some kind of control jump. In the more complex form:
IF logicalexpression THEN simplestatement ELSE statement
the simple statement following the THEN is executed if the logical expression has a value TRUE and the statement following ELSE is executed if the logical expression has a value FALSE. In either case, assuming the statements obeyed were not control jumps, control then passes to the statement following the IF statement. Thus one or other of the statements is obeyed but not both. Note that only the subclass of simple statements is allowed after the THEN. This is to remove the standard ambiguity of the dangling ELSE. For example in the statement:
IF X1=0 THEN IF X2=0 THEN GOTO L1 ELSE GOTO L2
the ELSE is associated with the second of the IF statements and could have been written:
IF X1=0 THEN BEGIN IF X2=0 THEN GOTO L1 ELSE GOTO L2; END;
The statement brackets, BEGIN and END, can always be introduced in this way to avoid ambiguity.
In its simplest form the logical expression is either a relation or one of the status conditions. The status conditions are set to true if:
OVERFLOW the overflow indicator is set (testing overflow clears it). FOVERFLOW the real (floating point) overflow indicator is set. CARRY the carry bit is set (if it is part of a multiple condition it should be the first item). NOT OVERFLOW the overflow indicator is not set. NOT FOVERFLOW the real overflow indicator is not set. NOT CARRY the carry bit is not set.
The simple relations compare some primary with the current value of an accumulator. These are quite self explanatory, being the standard set of comparisons. For example:
A1>0.0, A12<3.0L, X1=3, X2≥3, X12≤7B, X4 NOT=3
Two additional types of relation are permissible between integer accumulators and variables. The first of these:
xacc relation partaddress
allows comparisons to be made between the contents of an accumulator and the base or displacement of a call. For example:
X1>£LIX, X2=$UIA, X3≤£URA
The second relation:
xacc charel xprimary
allows special character comparisons to be made. The effect is to test the value of the integer accumulator considered as four six-bit characters against the primary similarly considered. CH comparisons are more efficient than normal relations. They can be used in place of arithmetic comparisons providing both operands are of the same sign. If they are of different signs, a negative number is unfortunately treated as larger than a positive one. The comparison is assumed to be a CH one if the primary is a character sequence used with a normal relation. Thus:
X1≥'ABCD'
is taken as identical to:
X1≥CH 'ABCD'
The CH is part of the comparison operator and should not therefore be separated by spaces from the remainder.
In its more complex form, the logical expression may consist of a number of relations all of which must be satisfied (andexpression), or only one need be satisfied (orexpression). For example:
X1>3 AND A1≥URX(X2) AND NOT OVERFLOW CARRY OR X1<CH LIX OR A1<URA(X1+3)
Note that AND's and OR's cannot be mixed so that to jump to label LB if X1 is zero and either X2 or X3 are also zero requires a statement of the form:
IF X1=0 THEN BEGIN IF X2=0 OR X3=0 THEN GOTO LB; END;
Although loops can be written using an IF statement and a GOTO statement, the FOR statement provides an easier method of causing a group of statements to be obeyed a specified number of times. For example:
FOR X1:=LIX STEP LIA UNTIL 10 DO LRX(X1):=0;
is equivalent to:
X1:=LIX; AG:LRX(X1):=0; IF X1=10 THEN GOTO ND; X1:=X1+LIA; GOTO AG; ND:NULL;
First the accumulator assignment is made followed by the execution of the statement. Then the value of the accumulator is checked for equality with the upper limit. If it does not equal it then the value of the accumulator is incremented and the statement executed again. The loop continues until the exact value of the limit is reached. Thus the statements:
FOR X1:=3 STEP 2 UNTIL 8 DO X7:=X7+3; FOR X1:=3 STEP 1 UNTIL 2 DO X7:=X7+3;
are both infinite loops. In any case where there is doubt that exact agreement will occur, a WHILE statement should be used.
The integer accumulator assignment initially can be any of the allowed forms (including address assignment). The increment can be any integer primary possibly preceded by a - sign. Some examples are:
FOR X1:=LIX(X2+2)+LIA(2) STEP #770 UNTIL UIA(X2) DO ............ FOR X1:=10+LIX STEP -1 UNTIL 0 DO............. FOR X1:=X1+$LRX STEP 1 UNTIL $LRA(4) DO..........
It is more efficient to have a limit of zero than any other primary.
The increment may also be the symbol CHAR. This will cause the value of the accumulator, treated as a character address, to be incremented by one character address at each iteration of the loop. Note that a BCHX order will be used to do the incrementing and consequently, if the compilation is in 15AM mode, the count position of the accumulator will be altered. The limit value must therefore take account of this.
The limit must be an integer primary so if the final value is a complicated expression, this should be calculated first and assigned to an accumulator or store location.
Some examples are:
FOR X3:=LIX STEP 1 UNTIL LIA(1) DO BEGIN UIA(X1+1):=X3; (X3):=1; END; X7:=£IUA+6+X1; LIX:=X7; FOR X2:=CHAR 1 OF £UIA STEP CHAR UNTIL LIX DO BEGIN X6:=CH UIA(X2); IF X6>'Z' THEN GOTO EXTRA; END;
This example only has meaning in 22AM mode.
This is similar in effect to a FOR statement in that it allows a statement to be executed repeatedly but in this case execution ceases when a condition specified by the programmer no longer holds. For example:
WHILE A1<LRX DO BEGIN A1:=A1+LRA(1); END;
This is equivalent to:
LBL:IF A1<LRX THEN BEGIN X1:=X1 +1; A1:=A1+LRA(1); GOTO LBL; END;
In the general form where the logical expression is present, the condition is tested first and if it is TRUE the statement is executed and the test repeated. If the condition no longer holds, control passes to the next statement in the sequence.
The WHILE statement is more flexible than the FOR statement as it can be used to construct loops without an exact end. Also the loop index can be a real accumulator. Thus:
FOR X1:=3 STEP 2 UNTIL 2 DO ...... and FOR X1:=3 STEP 2 UNTIL 10 DO ......
are both illegal FOR loops in that they will be repeated for ever.
However, similar WHILE loops will both terminate:
X1:=3; A1:=3.0; WHILE X1<2 DO BEGIN ..... X1:=X1+2; END; WHILE A1<10.0 DO BEGIN .. A1:=A1+2-0; END;
Conditions involving zero are more efficient than others.
There is a special form of WHILE statement for the repeated execution of a block from which there is some conditional exit. This has the simple form:
DO statement;
which is equivalent to
AG: statement; GOTO AG;
For example:
DO BEGIN X1:=X1+1; X7:=LIA(X1); LIA(X1-1):=X7; IF X1>9 THEN GOTO EXT; END;