Files
akbasic/docs/04-control-flow.md

177 lines
4.0 KiB
Markdown
Raw Normal View History

# 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.