# 4. Control flow ## IF ... THEN ... ELSE ```basic 10 A# = 5 20 IF A# = 5 THEN PRINT "FIVE" ELSE PRINT "NOT FIVE" ``` ```output FIVE ``` The condition is a whole expression, so `AND`, `OR` and `NOT` all work in one: ```basic 10 A# = 5 20 IF A# > 0 AND A# < 10 THEN PRINT "IN RANGE" ``` ```output 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: ```basic 10 A# = 5 20 IF A# = 5 THEN BEGIN 30 PRINT "IN THE BLOCK" 40 PRINT "STILL IN IT" 50 BEND 60 PRINT "AFTER" ``` ```output IN THE BLOCK STILL IN IT AFTER ``` When the condition is false every line up to the `BEND` is skipped. ## FOR ... NEXT ```basic 10 FOR I# = 1 TO 5 20 PRINT I# 30 NEXT I# ``` ```output 1 2 3 4 5 ``` `STEP` sets the stride, and a negative one counts down: ```basic 10 FOR I# = 10 TO 0 STEP -2 20 PRINT I# 30 NEXT I# ``` ```output 10 8 6 4 2 0 ``` 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: ```basic 10 FOR I# = 1 TO 100 20 IF I# = 5 THEN EXIT 30 NEXT I# 40 PRINT "OUT" ``` ```output OUT ``` ## DO ... LOOP The condition can go on either end, or neither: ```basic 10 I# = 0 20 DO WHILE I# < 3 30 PRINT I# 40 I# = I# + 1 50 LOOP ``` ```output 0 1 2 ``` ```basic 10 I# = 0 20 DO 30 PRINT I# 40 I# = I# + 1 50 LOOP UNTIL I# = 3 ``` ```output 0 1 2 ``` 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 ```basic 10 GOSUB 100 20 PRINT "BACK" 30 END 100 PRINT "IN THE SUBROUTINE" 110 RETURN ``` ```output IN THE SUBROUTINE BACK ``` `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: ```basic 10 GOTO SETUP 20 PRINT "SKIPPED" 100 LABEL SETUP 110 PRINT "ARRIVED" ``` ```output 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. Follow that one step further and the numbers stop earning their keep at all. A program in a file can leave them out — see [Chapter 2](02-getting-started.md#a-program-in-a-file-does-not-need-them) — and then every branch it makes is by name: ```basic GOSUB GREET GOTO FINISH PRINT "NOT REACHED" LABEL GREET PRINT "HELLO" RETURN LABEL FINISH PRINT "DONE" ``` ```output HELLO DONE ``` Nothing in that program can be broken by inserting a line into it, which is the whole argument. ## ON `ON` picks the *n*th target from a list, counting from one: ```basic 10 CHOICE# = 2 20 ON CHOICE# GOTO 100, 200, 300 30 PRINT "CHOICE WAS OUT OF RANGE" 40 END 100 PRINT "FIRST" 110 END 200 PRINT "SECOND" 210 END 300 PRINT "THIRD" ``` ```output SECOND ``` 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: ```basic 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 ``` ```output CAUGHT Out Of Bounds ON LINE 30 CARRIED ON ``` 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. **[Chapter 15](15-error-codes.md) is the complete list** of what `ER#` can hold and what each code means. The short version is that the interpreter's own codes are 512 to 519 and are the only numbers worth comparing against; two codes render as the same `ERR()` text, so compare the number rather than the text. `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.