====== 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 example((More examples on [[https://github.com/spotlessmind1975/ugbasic/tree/main/examples|official repository]])): 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 ===== [[ugbasic:user|{{ :ugbasic:user:logo-ugbasic.png?nolink&600 |}}]]