User Tools

Site Tools


ugbasic:user:control
Translations of this page:


ugBASIC User Manual

CONTROL STRUCTURES

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.

Unconditional jumps

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.

Returning from jumps

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.

Popping returning addresses

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.

Decision making

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 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:

  • TRUE that returns 255;
  • FALSE that returns 0;
  • NOT that returns the logical inverse of the given value.

In all the conditional operations such as IF…THEN and 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.

Loops and repetitions

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

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 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 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 (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 = (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 AND, OR and 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.

Controlled loops

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

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

Forced jumps by expression

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

Periodic calls

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.

POWERED BY

1)
More examples on official repository