Flow Control

Whenever BBC BASIC (Z80) comes across a FOR, REPEAT, WHILE, GOSUB, FN or PROC statement, it needs to remember where it is in the program so that it can loop back or return there when it encounters a line with NEXT, UNTIL, ENDWHILE or RETURN statement or when it reaches the end of a function or procedure. These 'return addresses' tell BBC BASIC (Z80) where it is in the structure of your program.

Every time BBC BASIC (Z80) encounters a FOR, REPEAT, WHILE, GOSUB, FN or PROC statement it 'pushes' the return address on to a 'stack' and every time it encounters a NEXT, UNTIL, ENDWHILE, RETURN statement or the end of a function or procedure it 'pops' the latest return address of the stack and goes back there.

BBC BASIC (Z80) uses a single control stack (the processor's hardware stack) for all looping and nesting operations. The main effects of this are discussed below.

Loop Operation Errors

Apart from memory size, there is no limit to the level of nesting of FORNEXT, REPEATUNTIL, WHILEENDWHILE and GOSUBRETURN operations. The untrappable error message No room will be issued if all the stack space is used up.

Program Structure Limitations

The use of a common stack has one disadvantage (if it is a disadvantage) in that it forces stricter adherence to proper program structure. It is not good practice to exit from a FORNEXT loop without passing through the NEXT statement. It makes the program more difficult to understand and the FOR address is left on the stack. Similarly, the loop or return address is left on the stack if a REPEATUNTIL loop, WHILEENDWHILE loop or a GOSUBRETURN structure is incorrectly exited. This means that if you leave a FORNEXT loop without executing the NEXT statement, and then subsequently encounter, for example, a RETURN statement, BBC BASIC (Z80) will report an error. (In this case, a No GOSUB error.) The example below would result in the error message 'No PROC at line 500'.

400 - - -
410 INPUT "What number should I stop at", num
420 PROC_error_demo
430 END
440 :
450 DEF PROC_error_demo
460 FOR i=1 TO 100
470   PRINT i;
480   IF i=num THEN 500
490 NEXT i
500 ENDPROC

BBC BASIC (Z80) is a little unusual in detecting this error, but it is always risky. It usually results in an inconsistent program structure.

Leaving Program Loops

There are a number of ways to leave a program loop which do not conflict with the need to write tidy program structures. These are discussed below.

EXIT

The easiest and safest way to simply leave a loop (or several nested loops of different types) is to use a suitable EXIT statement.

10 i=1
20 REPEAT
30   PRINT i
40   i=i+1
50   IF i=6 THEN EXIT REPEAT
60 UNTIL FALSE
70 PRINT "Done"

EXIT is not a standard feature of BBC BASIC (Z80) and so may not be available in other implementations. Even though the other methods for leaving a loop prematurely may not seem as practical as EXIT they have the advantage of increased compatibility as well as smaller code size and higher performance by being supported directly by the interpreter with dedicated tokens.

REPEAT…UNTIL Loops

The simplest way to overcome the problem of exiting a FORNEXT loop is to restructure it as a REPEATUNTIL loop. The example below performs the same function as the previous example, but exits the structure properly. It has the additional advantage of more clearly showing the conditions which will cause the loop to be terminated.

400 - - -
410 INPUT "What number should I stop at", num
420 PROC_error_demo
430 END
440 :
450 DEF PROC_error_demo
460 i=0
470 REPEAT
480   i=i+1
490   PRINT i;
500 UNTIL i=100 OR i=num
510 ENDPROC

Changing the Loop Variable

A simple way of forcing an exit from a FORNEXT loop is to set the loop variable to a value equal to the limit value and then GOTO to the NEXT statement. alternatively, you could set the loop variable to a value greater than the limit (assuming a positive step), but in this case the value on exit would be different depending on why the loop was terminated. (In some circumstances, this may be an advantage). The example below uses this method to exit from the loop. Notice, however, that the conditions which cause the loop to terminate are less clear since they do not appear together.

400 - - -
410 INPUT "What number should I stop at", num
420 PROC_error_demo
430 END
440 :
450 DEF PROC_error_demo
460 FOR i=1 TO 100
470   PRINT i;
480   IF i=num THEN i=500: GOTO 510
490   …
500   (More program here if necessary)
510 NEXT
520 ENDPROC

Popping the Inner Variable

A less satisfactory way of exiting a FORNEXT loop is to enclose the loop in a dummy outer loop and rely on BBC BASIC (Z80)'s ability to 'pop' inner control variables off the stack until they match. If you use this method you MUST include the variable name in the NEXT statement. This method, which is demonstrated below, is very artificial and the conditions which cause the loop to terminate are unclear.

400 - - -
410 INPUT "What number should I stop at", num
420 PROC_error_demo
430 END
440 :
450 DEF PROC_error_demo
460 FOR dummy=1 TO 1 :REM Loop once only
470 FOR i=1 TO 100
480   PRINT i;
490   IF i=num THEN 530 :REM Jump to outer NEXT
500   - - -
510   (More program here if necessary)
520 NEXT i
530 NEXT dummy
540 ENDPROC

Local Variables

Since local variables are also stored on the processor's stack, you cannot use a FORNEXT loop to make an array LOCAL. For example, the following program will give the the error message 'Not LOCAL at line 400'.

380 DEF PROC_error_demo
390 FOR i=1 TO 10
400   LOCAL data(i)
410 NEXT
420 ENDPROC

You can overcome this by fabricating the loop using an IFTHEN statement as shown below. This is probably the only occasion when the use of a single stack promotes poor program structure.

380 DEF PROC_error_demo
390 i=1
400 LOCAL data(i)
410 i=i+1
420 IF i<11 THEN 400
430 ENDPROC

Stack Pointer

The program stack is initialised to begin at HIMEM and, because of this, you cannot change the value of HIMEM when there is anything on the stack. As a result, you cannot change HIMEM from within a procedure, function, subroutine, FORNEXT loop, REPEATUNTIL loop or WHILEENDWHILE loop.