UNTIL

From BeebWiki
Revision as of 17:04, 23 December 2020 by Regregex (talk | contribs) (Dynamic programming: line 170 unreachable)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

UNTIL is the BASIC statement that closes a REPEAT...UNTIL loop.

UNTIL
Availability Present in all original versions of BBC BASIC.
Syntax UNTIL <testable condition>
Token (hex) FD (statement)
Description Evaluates the <testable condition>. If equal to FALSE the interpreter continues execution from the statement after the most recently executed REPEAT statement.
Otherwise it forgets the most recent REPEAT statement and continues execution.
Associated keywords REPEAT, WHILE, ENDWHILE, IF, TRUE, FALSE

Description

UNTIL is an essential statement to vary the behaviour of a program in response to some condition derived from the user's input, the contents of a file or the system environment.

It is part of a structure called a REPEAT...UNTIL loop, inside which code may be run again and again in the same order, as long as a condition remains unfulfilled. The condition is specified as a Boolean expression that is freshly evaluated at each encounter.

Unlike a WHILE...ENDWHILE loop, which tests a condition on entry and executes a loop zero or more times, the body of a REPEAT...UNTIL loop is executed at least once, and the condition is tested at the end of each pass.

Notes

FALSE (zero) is the only false value of a <testable condition>; all others are assumed to be TRUE (whose actual value is −1.)

If the statement has been met outside a REPEAT...UNTIL loop, a No REPEAT error results.

Dynamic programming

Line numbers aside, BBC BASIC versions I-III are languages with dynamic scope: the interpreter does not analyse the program structure except by running it, statement by statement. This approach made them simple to implement, but made WHILE...ENDWHILE loops and multi-line IF statements impractical, as they require the interpreter to find the end of the structure without passing flow-of-control through it.

Therefore in these and compatible versions of BASIC, a REPEAT statement may have more than one associated UNTIL statement; whichever one is next reached by the flow-of-control restarts or ends the loop according to its <testable condition>. The program will be safe provided that, once one of these associated UNTIL statements has been passed through with a true condition, none of them can be reached.

When there is exactly one associated UNTIL for each REPEAT, the program approximates lexical form and the LISTO 4 option causes LIST to indent the program properly.

UNTIL accesses the REPEAT...UNTIL stack as follows:

if <testable condition> = FALSE then
peek and jump to top location on REPEAT...UNTIL stack
else
pop and discard top location from REPEAT...UNTIL stack
endif

UNTIL FALSE is a common idiom to jump back to the statement after the most recent REPEAT. It appears:–

  • at the end of a loop that runs forever, or from which the code inside breaks out;
  • in the middle of a loop (inside an IF statement) to loop back early (compare with continue in C).

UNTIL TRUE may appear:–

  • in a developing program, at the end of a loop that is no longer required;
  • in the middle of a loop (inside an IF statement) to break out of it; the programmer must then send the flow-of-control outside the body of the loop.

A complex example of dynamic programming is shown below. This program fragment asks the user for a string to add to a set of hard-coded file names, then calls PROCupdate on each updatable file that contains some magic number. When the user enters an empty suffix string, the program prints the number of files updated and stops.

Lines 110 and 120 conditionally skip to the next file; line 80 makes the program ask the user for another suffix when the list of file names is exhausted.

Notice that line 170 is unreachable and can be left out.

    10 updated%=0
    20 REPEAT
    30   INPUT "Suffix: " suffix$
    40   IF suffix$ = "" THEN UNTIL TRUE:GOTO 180
    50   RESTORE
    60   REPEAT
    70     READ filename$
    80     IF filename$="" THEN UNTIL TRUE:UNTIL FALSE
    90     filename$=filename$+suffix$
   100     handle%=OPENUP filename$
   110     IF handle%=0 THEN UNTIL FALSE
   120     IF FNmagic_number(handle%)<>magic_number% THEN CLOSE#handle%:UNTIL FALSE
   130     PROCupdate(handle%)
   140     CLOSE#handle%
   150     updated%=updated%+1
   160   UNTIL FALSE
   170 UNTIL FALSE
   180 PRINT ;updated%;" files updated"
   190 END
   ...
  1000 DATA O2791,O1770,CHALL,W1770,A1770,M1770,PG400,A1772,M1772,""

-- Regregex (talk) 15:58, 19 February 2019 (CET)