# 4. Control flow ## IF ... THEN ... ELSE ``` 10 A# = 5 20 IF A# = 5 THEN PRINT "FIVE" ELSE PRINT "NOT FIVE" ``` The condition is a whole expression, so `AND`, `OR` and `NOT` all work in one: ``` 10 IF A# > 0 AND A# < 10 THEN PRINT "IN RANGE" ``` **Everything after `THEN` on the line belongs to the condition**, which matters as soon as you put several statements on a line: | Line | Condition | What runs | |---|---|---| | `IF C THEN A : B` | true | `A`, `B` | | `IF C THEN A : B` | false | nothing | | `IF C THEN A ELSE B : D` | true | `A` | | `IF C THEN A ELSE B : D` | false | `B`, `D` | The remainder always belongs to whichever arm was written *last*. ### Blocks `BEGIN` and `BEND` make an `IF` span lines: ``` 10 IF A# = 5 THEN BEGIN 20 PRINT "IN THE BLOCK" 30 PRINT "STILL IN IT" 40 BEND 50 PRINT "AFTER" ``` When the condition is false every line up to the `BEND` is skipped. ## FOR ... NEXT ``` 10 FOR I# = 1 TO 5 20 PRINT I# 30 NEXT I# ``` `STEP` sets the stride, and a negative one counts down: ``` 10 FOR I# = 10 TO 0 STEP -2 20 PRINT I# 30 NEXT I# ``` The counter is an ordinary variable and the body may assign to it. Two things to know: - **The counter does not survive the loop.** It lives in the loop's own scope, so reading it afterwards gives zero. On a C128 it keeps its final value. - **A step that overshoots runs the body one extra time.** `FOR I = 1 TO 9 STEP 3` runs with 1, 4, 7 *and 10*. Both are recorded as known defects; see Chapter 13. `EXIT` leaves the loop early: ``` 10 FOR I# = 1 TO 100 20 IF I# = 5 THEN EXIT 30 NEXT I# ``` ## DO ... LOOP The condition can go on either end, or neither: ``` 10 I# = 0 20 DO WHILE I# < 3 30 PRINT I# 40 I# = I# + 1 50 LOOP ``` ``` 10 I# = 0 20 DO 30 PRINT I# 40 I# = I# + 1 50 LOOP UNTIL I# = 3 ``` A condition on the `DO` is tested before the body, so the body may run zero times. A condition on the `LOOP` is tested after, so it runs at least once. `DO` with no condition at all loops forever until an `EXIT` or a `GOTO` leaves it. `EXIT` works here too. ## GOTO and GOSUB ``` 10 GOSUB 100 20 PRINT "BACK" 30 END 100 PRINT "IN THE SUBROUTINE" 110 RETURN ``` `RETURN` goes back to the line after the `GOSUB`. ## Labels A label is a name with no type suffix. It marks a line, and anything that takes a line number takes a label instead: ``` 10 GOTO SETUP 20 PRINT "SKIPPED" 100 LABEL SETUP 110 PRINT "ARRIVED" ``` **Labels are filed before the program runs**, so a forward `GOTO` works. This is worth using for its own sake: a program written with labels is immune to `RENUMBER`, because there is no number to rewrite. ## ON `ON` picks the *n*th target from a list, counting from one: ``` 10 ON CHOICE# GOTO 100, 200, 300 20 PRINT "CHOICE WAS OUT OF RANGE" ``` Out of range is not an error — it falls through to the next statement, which is what lets you write the check as the line after. `ON ... GOSUB` works the same way and returns. ## Trapping errors `TRAP` sends an error to a handler instead of stopping the program: ``` 10 TRAP HANDLER 20 DIM Q#(2) 30 PRINT Q#(9) 40 PRINT "CARRIED ON" 50 END 100 LABEL HANDLER 110 PRINT "CAUGHT " + ERR(ER#) + " ON LINE " + EL# 120 RESUME NEXT ``` Two variables are set when the trap fires: **`ER#`** is the error code and **`EL#`** is the line it happened on. `ERR(ER#)` gives the message text. On a C128 these are called `ER` and `EL` with no suffix; this dialect has no bare variable names. `RESUME` comes in three forms: | Form | Where it goes | |---|---| | `RESUME` | back to the line that failed, and tries again | | `RESUME NEXT` | on to the line after the one that failed | | `RESUME (line)` | to a line you name | Bare `RESUME` only terminates if the handler fixed whatever was wrong — that is what it is for. `TRAP` with no argument turns trapping off. An error *inside* a handler is reported normally rather than re-entering it, so a broken handler cannot loop forever. ## STOP, END and CONT `STOP` stops the program and returns to the prompt; `CONT` resumes from there. `END` stops it without arming `CONT`. `QUIT` ends the interpreter itself.