Any programming language gives to the programmer a set of instructions
that allow computer programs to make decisions: they are called "control structures".
This section will give you a quick overview on the topic.
goto
gosub
pop
if
loop
controlled
calculated
periodic
One way of forcing programs to jump to a specified locations is
to use the GOTO
instruction, followed by a specific
target destination. In ugBASIC destinations can
be a literal label or a line number. Label markers can consist
of names that use any string of letters or numbers, as well as
the underscore character (_
), and they must be
ended with the colon character :
.
Take a look at this example:
label:
COLOR BORDER YELLOW
WAIT 100 MS
COLOR BORDER BLACK
WAIT 100 MS
GOTO label
Like any BASIC, also numbers may be used to identify specific
lines, and the program can be commanded to GOTO
one
of these optional markers, like this:
10 COLOR BORDER YELLOW
20 WAIT 100 MS
30 COLOR BORDER BLACK
40 WAIT 100 MS
50 GOTO 10
Note that line numbers could be different from identification numbers,
and labels are much easier to remember and to locate.
Routines can be packaged to perform a specific task, and such routines could be
split into smaller set of instructions as “sub-routines”. GOSUB
is another,
also if a bit antiquated, command used to perform a jump to a sub-routine. As with
GOTO
, there are two alternative targets for a GOSUB
instruction:
labels and line numbers. To make sub-routines easier to spot in your program listings,
it is good practice to place them at the end of the main.
start:
GOSUB yellowBorder
WAIT 1000 MS
GOSUB blackBorder
WAIT 1000 MS
GOTO start
yellowBorder:
COLOR BORDER YELLOW
RETURN
blackBorder:
COLOR BORDER BLACK
RETURN
When a program execute a GOSUB
instruction, it must be instructed
to RETURN to the main program after the subroutine has been executed.
A single GOSUB
statement can be linked to several RETURN
commands, allowing exits from any number of different points in the routine.
x = 0
start:
GOSUB incrementX
COLOR BORDER x
WAIT 500 MS
GOTO start
incrementX:
x = x + 1
IF x > 16 THEN : x = 0 : RETURN : ENDIF
RETURN
There is no fixed rule. After the RETURN
, a jump is made back to the
instruction immediately after the original GOSUB
.
Normally, you cannot exit from a GOSUB
statement using a standard
GOTO
. To avoid this limitation you can use the POP
command:
x = 0
y = 0
start:
x = x + 1
COLOR BORDER x + y
GOSUB incrementX
GOTO start
nextCycle:
y = y + 1
IF y > 7 THEN : y = 0 : ENDIF
GOTO start
incrementX:
IF x > 7 THEN : POP : x = 0 : GOTO nextCycle : ENDIF
RETURN
It removes the return address generated by a GOSUB
, allowing you to leave
the subroutine not using a RETURN
statement. In the above example, when
the color index in x
is greater than 7, y
is incremented
but outside the original subroutine.
The most used command to implement the decision making process is the
IF...THEN...ENDIF
structure. It allows simple decisions
to be made within a program, so IF
a condition is true
THEN
the computer decides to take a particular
course of action, up to reach ENDIF
. If the condition
is not true, the machine does something else. The list of condition in an
IF...THEN...ENDIF
structure can be any list of tests,
including the use of AND
and OR
keywords.
Another keyword understood is ELSE
. This is the "alternative"
choice. Remember that an IF...THEN...ELSE...ENDIF
statement is
not limited to a single line so you can build a "structured test".
x = 0
y = 0
start:
IF x > 16 THEN
y = 0
ENDIF
IF x = 0 THEN
y = 1
ENDIF
IF y = 1 THEN : x = x + 1 : ELSE : x = x - 1 : ENDIF
COLOR BORDER x + y
WAIT x * 50 MS
GOTO start
In a structured test, each test is set up with an IF
and a THEN
,
and ended with a matching ENDIF
. The statements in a structured test are
separated by colons on any particular line, as usual, but can extend over any number
of lines in your listing, as required.
x = 0
y = 0
start:
IF x > 16 THEN
y = 0
ELSE IF x = 0 THEN
y = 1
ELSE
REM does nothing!
ENDIF
IF y = 1 THEN : x = x + 1 : ELSE : x = x - 1 : ENDIF
COLOR BORDER x + y
WAIT x * 50 MS
GOTO start
Moreover, there is the capability to allow multiple tests to be performed. The
keyword is ELSE IF
, and it must be used within a normal
IF...ENDIF
statement, and the only rule to remember is that there
must be one ELSE
just before the ENDIF
. This sort of test
waits for an expression, and if the expression is true, then what comes after it
is executed.
About logical decisions, ugBASIC understands the following character symbols, which
are used as a form of short-hand function:
=
is used as "equal to" (it can also be written as ==
, as well);<>
is used as “not equal to”;>
is used as "greater than";<
is used as "less than";>=
is used as "greater than or equal to";<=
is used as "less than or equal to";TRUE
that returns 255;FALSE
that returns 0;NOT
that returns the logical inverse of the given value.IF...THEN
and
REPEAT...UNTIL
, the value of -1 is used to represent
TRUE
, and the value of 0 is used to represent FALSE
. NOT
is
used to swap over every digit in a binary number from a 0 to a 1, and vice versa. Since
255 (-1, TRUE
) can be expressed in binary as %11111111
, then
NOT TRUE
will be equal to FALSE
, and a logical NOT
operation is achieved.
ugBASIC offers all of the expected programming short-cuts
to allow sections of code to be repeated as often as necessary. These
repeated parts of programs are known as "loops". In particular, loops
can be defined using the pair DO...LOOP
, and it will loop
a list of statements forever, with DO
acting as the marker
position for the LOOP
to return to.
DO
COLOR BORDER YELLOW
COLOR BORDER BLACK
WAIT 500 MS
LOOP
The instruction EXIT
forces the program to leave a loop
immediately, and it can be used to escape from all the types of loop, such as
FOR...NEXT
, REPEAT...UNTIL
, WHILE...WEND
and DO...LOOP
.
DO
COLOR BORDER YELLOW
WAIT 500 MS
COLOR BORDER BLACK
WAIT 500 MS
DO
COLOR BORDER RED
WAIT 1000 MS
EXIT
REM The border will never be green!
COLOR BORDER GREEN
WAIT 1000 MS
LOOP
LOOP
You can nest any number of loops, and when used on its own, EXIT
will
“short-circuit” the innermost loop only. By including the number after EXIT
,
that number of nested loops will be taken into account before the EXIT
is made.
DO
COLOR BORDER YELLOW
WAIT 500 MS
COLOR BORDER BLACK
WAIT 500 MS
DO
COLOR BORDER RED
WAIT 1000 MS
COLOR BORDER GREEN
WAIT 1000 MS
DO
COLOR BORDER RED
WAIT 1000 MS
EXIT 2 : REM EXIT 2 = skip 1 more loop, because "EXIT" == "EXIT 1"!
REM and the second loop will be skipped
COLOR BORDER GREEN
WAIT 1000 MS
LOOP
LOOP
LOOP
In this way, the program will jump directly to the instruction immediately after the
relevant loop. If you need to leave a loop as a result of a specific set of conditions,
this can be made by using the EXIT IF
instruction. As explained above, in
conditional operations, the value -1 (255) represents TRUE
, whereas a zero
represents FALSE
. After using EXIT IF
, an expression is given
which consists of one or more tests. The EXIT
will only be performed
IF
the result is found to be 255 (-1, TRUE
). As with the
command EXIT
, an optional number can be given to specify the number of loops
to be jumped from, otherwise only the current loop will be aborted.
The WHILE...WEND
commands provides a convenient way of making the program
repeat a group of instructions all the time a particular condition is true.
For example, this program will show a decrement number from 10 to 1 and restart from 10 again:
DO
x = 10
WHILE x > 0
PRINT x
x = x - 1
WEND
LOOP
WHILE
marks the start of this loop, and the condition is checked
for a value of 255 (-1, TRUE
) from this starting position through
to the end position, which is marked by a WEND
. The condition is
then checked again at every turn of the loop, until it is no longer true. You
are, obviously, free to use AND
, OR
and NOT
to qualify the conditions to be checked.
DO
x = 10
REPEAT
PRINT x
x = x - 1
UNTIL x == 0
LOOP
Instead of checking if a condition is true or false at the start of a loop,
REPEAT...UNTIL
makes its check at the end of a loop. REPEAT
marks the start and UNTIL
the end of the loop to be checked. This means
that if a condition is false at the beginning of a WHILE...WEND
structure,
that loop will never be performed at all, but if it is true at the beginning of a
REPEAT...UNTIL
structure, the loop will be performed at least once.
Control can be made much more definite than relying on whether conditions are
true or false. In particular, when deciding how many times a loop is to be
repeated, you can use the FOR...NEXT
control structure. For
example, this sample program will print numbers from 1 to 100:
i = 0
FOR i = 1 TO 100
PRINT i
NEXT
Each FOR
statement must be matched by a single NEXT
,
and pairs of FOR...NEXT
loops can be nested inside one another. Each
loop repeats a list of instructions for a specific number of times, governed by
an index which counts the number of times the loop is repeated. Once inside the
loop, this index can be read by the program as if it is a normal variable.
i = 0 : j = 0
FOR i = 1 TO 100
FOR j = 1 TO 5
PRINT i * j
NEXT
NEXT
Normally, the index counter is increased by 1 unit at every turn of a
FOR...NEXT
loop. When the current value exceeds that of the last
number specified, the loop is terminated. STEP
is used to change
the size of increase in the index value.
Jumps can be made whenever a particular variable is recognised, in other words,
regardless of any other conditions. GOTO
and GOSUB
are examples
of a unconditional jump. ON
can be used to force the program to jump to
a pre-defined position when it recognises a specified variable and against a choice of
several positions, depending on what value is held by the variable at the time it is spotted.
For example, this program will print repeatly the sequence "1, 2, 3":
times = 1
start:
ON times GOSUB first, second, third
times = times + 1
IF times > 3 THEN
times = 1
ENDIF
GOTO start
first:
PRINT 1
second:
PRINT 2
third:
PRINT 3
The ON
instruction can force a unconditional jump (GOTO
) or with
returning (GOSUB
). To work properly, the expression must have a value from
1 up to the number of the highest possible destination. If the expression has a value of
0 or greater than the highest possibile destination, no jump will be performed.
Take this example:
IF level=1 THEN GOTO level1
IF level=2 THEN GOTO level2
IF level=2 THEN GOTO level3
Can be rewritten as:
ON level GOTO level1, level2, level3
The use of an ON GOSUB
structure is identical to
ON...GOTO
, except that it must employ a
RETURN
(or a POP
!) to jump back to the instruction
immediately after the ON...GOSUB
statement. Destinations may be
given as the name of a label, or the identification number of a line between
1 and the maximum number of possible destinations.
The EVERY
statement is used to call up a sub-routine or a procedure
at regular intervals, without interfering with the main program. By specifying
the length of time between every call, measured in TICKS
, you can
call a sub-routine.
colorIndex = 0
EVERY 50 TICKS GOSUB changeBorderColor
EVERY ON
HALT
changeBorderColor:
COLOR BORDER colorIndex
colorIndex = colorIndex + 1
IF colorIndex > 16 THEN
colorIndex = 0
ENDIF
EVERY ON
RETURN
Note that the sub execution time should be less than the interval time, or the
main program timings will be affected. After a sub-routine has been entered, the
EVERY
system is automatically disabled. This means that, in order to
call this feature continuously, an EVERY ON
command must be inserted
into a sub-routine before the final RETURN
statement.
So, EVERY ON
should be used before the relevant sub-routine has
finished executing, while EVERY OFF
is the default condition, and
is used to disable the automatic calling process altogether.
If you have found a problem, if you think there is a bug or, more
simply, you would like something to be improved, write a topic on the official forum, or open an issue on GitHub.
Thank you!