Skip to content

Flow control

This page explains how a d/BASIC program decides what to do next: making choices with IF and SELECT CASE, repeating with FOR, WHILE and DO, jumping with the classic GOTO and GOSUB, leaving a block early, and ending a program. It also introduces what happens when the runtime cannot do what you asked. After reading it you will be able to shape the order of any program, whether you write it fresh or bring it over from an old listing.

Every program is a story about order. Structured blocks tell that story most clearly; line numbers and labels remain available for when the original algorithm genuinely thinks in lines.

IF

Block form

IF Temperature# < 0 THEN
  State$ = "ICE"
ELSEIF Temperature# < 100 THEN
  State$ = "WATER"
ELSE
  State$ = "STEAM"
END IF

Use as many ELSEIF arms as you need. ELSE is optional.

Single-line form

IF Lives% = 0 THEN PRINT "GAME OVER" ELSE Lives% = Lives% - 1

A single-line IF is good for a truly small choice. It becomes hard to read once either side has more than one idea in it.

The classic forms that jump to a line are accepted too:

IF Done% THEN 900
IF Failed% GOTO Recovery

SELECT CASE

SELECT CASE is the readable choice when one value picks among several outcomes:

SELECT CASE Score%
  CASE 100
    Rank$ = "PERFECT"
  CASE 80 TO 99
    Rank$ = "EXCELLENT"
  CASE IS >= 60
    Rank$ = "PASS"
  CASE 0, 1, 2
    Rank$ = "JUST STARTED"
  CASE ELSE
    Rank$ = "TRY AGAIN"
END SELECT

A CASE can list exact values separated by commas, a value TO value range (both ends included), or IS followed by a comparison.

FOR ... NEXT

Use FOR when a counter and a limit describe the repetition:

FOR I% = 1 TO 10
  PRINT I%; I% * I%
NEXT I%

STEP may be positive, negative, or worked out at run time:

FOR I% = 10 TO 0 STEP -2
  PRINT I%
NEXT I%

NEXT may repeat the counter's name. That is useful in nested loops:

FOR Row% = 0 TO 2
  FOR Column% = 0 TO 2
    PRINT Grid%(Row%, Column%);
  NEXT Column%
  PRINT
NEXT Row%

Leave a loop early with EXIT FOR.

WHILE ... WEND

WHILE tests the condition before each pass through the body:

WHILE Remaining% > 0
  Remaining% = Remaining% - 1
WEND

If the condition is false to begin with, the body never runs. EXIT WHILE leaves the loop early.

DO ... LOOP

DO can test at the top or at the bottom, with either WHILE or UNTIL:

DO WHILE Connected%
  CALL PumpOneMessage
LOOP
DO
  Attempts% = Attempts% + 1
LOOP UNTIL Ready% OR Attempts% = 3

A loop that tests at the bottom runs at least once. Use EXIT DO to leave early.

Labels, GOTO, and GOSUB

A jump target is a numbered line or a named label:

GOSUB DrawBanner
GOTO Continue

DrawBanner:
  PRINT "d/BASIC"
  RETURN

Continue:
  PRINT "READY"

GOSUB remembers where it came from; RETURN goes back there. Prefer a SUB when the routine needs parameters, its own local variables, a declared signature, or reuse from other modules. GOSUB remains excellent for keeping the shape of a small classic listing.

Computed branches

ON expression GOTO and ON expression GOSUB pick a target by position, counting from one:

ON Choice% GOTO RedRoom, GreenRoom, BlueRoom
ON MenuItem% GOSUB NewFile, OpenFile, SaveFile

This is compact for code brought over from an old machine. In new code, SELECT CASE is usually easier to extend without mistakes.

Procedure exits

The structured ways to leave a block early are:

EXIT FOR
EXIT DO
EXIT WHILE
EXIT SUB
EXIT FUNCTION

Each exit names the thing it leaves. There is no bare break whose meaning changes when the code is nested.

END and STOP

END finishes a console program with exit status 0:

PRINT "ALL DONE"
END

STOP is a deliberate interruption and finishes with exit status 3. It is useful while teaching, poking at a program, or marking a path that should stand out if it is ever reached:

IF Impossible% THEN STOP

Neither of these is an error. Separately from both, the runtime (the d/OS program that runs your compiled code) can decline an operation it cannot honestly perform; that is covered next.

When the runtime says no: ON REFUSAL

ON REFUSAL GOTO target names the place to jump to when the runtime declines an operation. RESUME NEXT carries on after the operation that was declined; RESUME target carries on at a place you name.

ON REFUSAL GOTO CouldNotProvide

CALL AskForOptionalCapability
PRINT "AVAILABLE"
GOTO Finished

CouldNotProvide:
  PRINT "UNAVAILABLE:"; ERR; " AT "; ERL
  RESUME Finished

Finished:
END

Use this for an operation that is genuinely optional, such as a capability the host may not have. Do not use it to paper over programming mistakes, and it cannot catch a problem found by the checks a program passes before it runs, because at that point the program has not started. Errors, Refusals & Diagnostics explains what can be caught, how to recover, and how to clean up; Compatibility, Migration & Refusals explains the permanent line around direct machine access.


Next: Procedures & Functions →