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.
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 example1):
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
Normally, you cannot exit from a
GOSUB statement using a standard
GOTO. To avoid this limitation you can use the
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
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 y + x 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 y + x 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” (note the double equals!);
<>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”
There are also three special functions that can be called during the decision making process:
TRUEthat returns 255;
FALSEthat returns 0;
NOTthat returns the logical inverse of the given value.
In all the conditional operations such as
REPEAT…UNTIL, the value of not zero is used to represent
TRUE, and the value of 0 is used to represent
FALSE. A value of either 255 (
TRUE) or 0 (
FALSE) is produced every time a test is made to satisfy a condition. Instead,
NOT is used to swap over every digit in a binary number from a 0 to a 1, and vice versa. Since 255 (
TRUE) can be expressed in binary as %11111111, then
NOT TRUE must 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 WAIT 500 MS COLOR BORDER BLACK WAIT 500 MS LOOP
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 The border will never be green, REM and the secondo loop will be skiped 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 255 represents
TRUE, whereas a zero
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 (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.
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 = (8BIT) 10 WHILE x > 0 DEBUG x x = x - 1 WEND LOOP
WHILE marks the start of this loop, and the condition is checked for a value of 255 (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
NOT to qualify the conditions to be checked.
DO x = (8BIT) 10 REPEAT DEBUG 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 DEBUG i NEXT HALT
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 DEBUG i * j NEXT NEXT HALT
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.
GOSUB are examples of a “forced” 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: DEBUG 1 RETURN second: DEBUG 2 RETURN third: DEBUG 3 RETURN
ON 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.
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
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.