Chapter
Nine
Program Flow Control Statements
Execution Control always processes the statement
in the Statement Table that follows the one it thinks it has just finished. This
means that statements in a BASIC program are usually processed in sequential order.
Several statements, however, can change that order: GOTO, IF, TRAP, FOR, NEXT, GOSUB,
RETURN, POP, and ON. They trick Execution Control by changing the parameters that
it maintains. Simple Flow Control Statements XGOTO ($BGA3) The simplest form of flow control transfer
is the GOTO statement, simulated by the XGOTO routine. Following the GOTO token in
the tokenized line is an expression representing the line number of the statement
that the user wishes to execute next. The first thing the XGOTO routine does is ask
Execute Expression to evaluate the expression and convert it to a positive integer.
XGOTO then calls the GETSTMT routine to find this line number in the Statement Table
and change Execution Control's line parameters to indicate this line. If the line
number does not exist, XGOTO restores the line parameters to indicate the line containing
the original GOTO, and transfers to the Error Handling Routine via the ERNOLN entry
point. The Error Handling Routine processes the error and jumps to the start of the
editor. If the line number was found, XGOTO jumps to the beginning of Execution Control
(EXECNL) rather than returning to the point in the routine from which it was called.
This leaves garbage on the 6502 CPU stack, so XGOTO first pulls the return address
off the stack. 75
Chapter
Nine
XIF($8778) The IF statement changes the statement flow based
on a condition. The simulatiQn routine, xw, begins by calling a subroutine of Execute
Expressionto evaluate the condition. Since this is a logical (rather than an arithmetic)
operation, we are only interested in whether the value is zero or non-zero. If the
expression was false (non-zero), XIF modifies Execution Control's line parameters
to indicate the end of this line and then returns. Execution Control moves to the
next line, skipping any remaining statements on the original IF statement line. If
the expression is true (zero), things get a little more complicated. Back during
syntaxing, when a statement of the form IF <expression> THEN <statement>
was encountered, the pre-compiler generated an end-of-statement token after THEN.
XIF now tests for this token. If we are at the end of the statement, XIF returns
to Execution Control, which processes what it thinks is the next statement in the
current line, but which is actually the THEN <statement> part of the IF statement.
If XIF does not find the end-of-statement token, then the statement must have had
the form IF <expression> THEN <line number>. XIF jumps to XGOTO, which
finishes processing by changing Execution Control's line parameters to indicate the
new line. XTRAP ($B7E1) The TRAP statement does not actually change the program
flow when it is executed. Instead, the XTRAP simulation routine calls a subroutine
of Execute Expression to evaluate the line number and then saves the result in TRAPLN
($BC). The program flow is changed only if there is an error. The Error Handling
Routine checks TRAPLN. If it contains a valid line number, the error routine does
some initial set-up and joins the XGOTO routine to transfer to the new line. Runtime
Stack Routines The rest of the Program Flow Control Statements use the Runtime
Stack. They put items on the stack, inspect them, and/or remove them from the stack.
Every item on the Runtime Stack contains a four-byte header. This header consists
of a one-byte type indication, a 76
Chapter
Nine
two-byte line number, and a one-byte displacement to the Statement
Name Token. (See pages 18-19.) The type byte is the last byte placed on the stack
for each entry. This means that the pointer to the top of the Runtime Stack (RUNSTK)
points to the type byte of the most recent entry on the stack. A zero type byte indicates
a GOSUB-type entry. Any non-zero type byte represents a FOR-type entry A GOSUB entry
consists solely of the four-byte header. A FOR entry contains twelve additional bytes:
a six-byte limit value and a six-byte step value. Several routines are used by more
than one of the statement simulation routines. PSHRSTK ($B683) This routine
expands the Runtime Stack by calling EXPLOW and then storing the type byte, line
number, and displacement of the Statement Name Token on the stack. POPRSTK ($B841)
This routine makes sure there really is an entry on the Runtime Stack. POPRSTK saves
the displacement to the statement name token in SVI)ISP, saves the line number in
TSLNUM, and puts the type/variable number in the 6502 accumulator. It then removes
the entry by calling the CONTLOW routine. :GETTOK ($B737) This routine first
sets up Execution Control's line parameters to point to the line whose number is
in the entry just pulled from the Runtime Stack. If the line was found, : GETTOK
updates the line parameters to indicate that the statement causing this entry is
now the current statement. Finally, it loads the 6502 accumulator with the statement
name token from the statement that created this entry and returns to its caller.
If the line number does not exist, : GETTOK restores the current statement address
and exits via the ERGFDEL entry point in the Error Handling Routine. Now let's look
at the simulation routines for the statements that utilize the Runtime Stack. XFOR
($B64B) XFOR is the name of the simulation routine which executes a FOR statement.
In the statement FOR 1=1 TO 10 STEP 2: I is the loop control variable
77
Chapter
Nine
1 is its initial value 10 is the limit value 2 is
the step value XFOR calls Execute Expression, which evaluates the initial
value and puts it in the loop control variable's entry in the Variable Value Table.
Then it calls a routine to remove any currently unwanted stack entries for example,
a previous FOR statement that used the same loop control variable as this one. XFOR
calls a subroutine of Execute Expression to evaluate the limit and step values. If
no step value was given, a value of 1 is assigned. It expands the Runtime Stack using
EXPLOW and puts the values on the stack. XFOR uses PSHRSTK to put the header entry
on the stack. It uses the variable number ofthe loop control variable (machine-language
ORed with $80) as the type byte. XFOR now returns to Execution Control, which processes
the statement following the FOR statement. The FOR statement does not change program
flow. It just sets up an entry on the Runtime Stack so that the NEXT statement can
change the flow. XNEXT ($B6CF) The XNEXT routine decides whether to alter
the program flow, depending on the top Runtime Stack entry. XNEXT calls the POPRSTK
routine repeatedly to remove four-byte header entries from the top of the stack until
an entry is found whose variable number (type) matches the NEXT statement's variable
token. If the top-of-stack or GOSUB-type entry is encountered, XNEXT transfers control
to an Error Handling Routine via the ERNOFOR entry point. To compute the new value
of the loop variable, XNEXT calls a subroutine of Execute Expression to retrieve
the loop control variable's current value from the Variable Value Table, then gets
the step value from the Runtime Stack, and finally adds the step value to the variable
value. XNEXT again calls an Execute Expression subroutine to update the variable's
value in the Variable Value Table. XNEXT gets the limit value from the stack to determine
if the variable's value is at or past the limit. If so, XNEXT returns to Execution
Control without changing the program flow, and the next sequential statement is processed.
78
Chapter
Nine
If the variable's value has not reached the limit, XNEXT returns
the entry to the Runtime Stack and changes the program flow. POPRSTK already saved
the line number of the FOR statement in TSLNUM and the displacement to the statement
name token in SVDISP. XNEXT calls the GETTOK routine to indicate the FOR statement
as the current statement. If the token at the saved displacement is not a FOR statement
name token, then the Error Handling Routine is given control at the ERGFDEL entry
point. Otherwise, XNEXT returns to Execution Control, which starts processing with
the statement following the FOR statement. XGOSUB ($BGA0) The GOSUB statement
causes an entry to be made on the Runtime Stack and also changes program flow. The
XGOSUB routine puts the GOSUB type indicator (zero) into the 6502 accumulator and
calls PSHRSTK to put a four-byte header entry on the Runtime Stack for later use
by the simulation routine for RETURN. XGOSUB then processes exactly like XGOTO. XRTN
($B719) The RETURN statement causes an entry to be removed from the Runtime Stack.
The XRTN routine uses the information in this entry to determine what statement should
be processed next. The XRTN first calls POPRSTK to remove a GOSUB-type entry from
the Runtime Stack. If there are no GOSUB entries on the stack, then the Error Handling
Routine is called at ERBRTN. Otherwise, XRTN calls GETTOK to indicate that the statement
which created the Runtime Stack entry is now the current statement. If the statement
name token at the saved displacement is not the correct type, then XRTN exits via
the Error Handling Routine's ERGFDEL entry point. Otherwise, control is returned
to the caller. When Execution Control was the caller, then GOSUB must have created
the stack entry, and processing will start at the statement following the GOSUB.
Several other statements put a GOSUB-type entry on the stack when they need to mark
their place in the program. They do not affect program flow and will be discussed
in later chapters. 79
Chapter
Nine
XPOP ($B841) The XPOP routine uses POPRSTK to remove an entry
from the Runtime Stack. A user might want to do this il he decided not to RETURN
from a GOSUB. XON ($B7ED) The ON statement comes in two versions: ON-GOTO
and ON— GOSUB. Only ON-GOSUB uses the Runtime Stack. The XON routine evaluates the
variable and converts it to an integer (MOD 256). If the value is zero, XON returns
to Execution Control without changing the program flow. If the value is non-zero
and this is an ON-GOSUB statement, XON puts a GOSUB-type entry on the Runtime Stack
for RETURN to use later. From this point, ON-GOSUB and ON-GOTO perform in exactly
the same manner. XON uses the integer value calculated earlier to index into the
tokenized statement line to the correct GOTO or GOSUB line number. If there is no
line number corresponding to the index, XON returns to Execution Control without
changing program flow. Otherwise, XON joins XGOTO to finish processing. 80
<-Chapter
08Chapter 10->