REPEAT

Command: Execute code block repetitively.

((PUBPRI))
  REPEAT < Count >
  -> Statement(s)


((PUBPRI))
  REPEAT Variable FROM Start TO Finish < STEP Delta >
  -> Statement(s)


((PUBPRI))
  REPEAT
(( UNTILWHILE )) Condition(s)
  -> Statement(s)


((PUBPRI))
  REPEAT

  -> Statement(s)

  ((UNTILWHILE)) Condition(s)

  • Count is an optional expression indicating the finite number of times to execute Statement(s). If Count is omitted, syntax 1 creates an infinite loop made up of Statement(s).
  • Statement(s) is an optional block of one or more lines of code to execute repeatedly. Omitting Statement(s) is rare, but may be useful in syntax 3 and 4 if Condition(s) achieves the needed effects. Indention is required for all statements in the block.
  • Variable is a variable, usually user-defined, that will be iterated from Start to Finish, optionally by Delta units per iteration. Variable can be used in Statement(s) to determine or utilize the iteration count.
  • Start is an expression that determines the starting value of Variable in syntax 2. If Start is less than Finish, Variable will be incremented each iteration; it will be decremented otherwise.
  • Finish is an expression that determines the ending value of Variable in syntax 2. If Finish is greater than Start, Variable will be incremented each iteration; it will be decremented otherwise.
  • Delta is an optional expression that determines the units in which to increment/decrement Variable each iteration (syntax 2). If omitted, Variable is incremented/decremented by 1 each iteration.
  • Condition(s) is one or more Boolean expression(s) used by syntax 3 and 4 to continue or terminate the loop. When preceded by UNTIL, Condition(s) terminates the loop when true. When preceded by WHILE, Conditions(s) terminates the loop when FALSE.

Explanation

REPEAT is the very flexible looping structure for Spin code. It can be used to create any type of loop, including: infinite, finite, with/without loop counter, and conditional zero-to-many/one-to-many loops.

Indention is Critical

IMPORTANT: Indention is critical. The Spin language relies on indention (of one space or more) on lines following conditional commands to determine if they belong to that command or not. To have the Propeller Tool indicate these logically grouped blocks of code on-screen, you can press Ctrl + I to turn on block-group indicators. Pressing Ctrl + I again will disable that feature. See the Propeller Tool Help for a complete list of shortcut keys.

Infinite Loops (Syntax 1)

Truthfully, any of the four forms of REPEAT can be made into infinite loops, but the form used most often for this purpose is syntax 1 without the Count field. For example:

repeat                           'Repeat endlessly
  !outa[25]                      'Toggle P25
  waitcnt(2_000 + cnt)           'Pause for 2,000 cycles 

This code repeats the !outa[25] and waitcnt(2_000 + cnt) lines endlessly. Both lines are indented from the REPEAT so they belong to the REPEAT loop.

Since Statement(s) is really an optional part of REPEAT, the REPEAT command by itself can be used as an endless loop that does nothing but keep the cog active. This can be intentional, but sometimes is unintentional due to improper indention. For example:

repeat                           'Repeat endlessly
!outa[25]                        'Toggle P25 <-- This is never run 

The above example is erroneous; the last line is never executed because the REPEAT above it is an endless loop that has no Statement(s); there is nothing indented immediately below it, so the cog simply sits in an endless loop at the REPEAT line that does nothing but keep the cog active and consuming power.

Simple Finite Loops (Syntax 1)

Most loops are finite in nature; they execute a limited number of iterations only. The simplest form is syntax 1 with the Count field included.

For example:

repeat 10                        'Repeat 10 times
  !outa[25]                      'Toggle P25
byte[$7000]++                    'Increment RAM location $7000

The above code toggles P25 ten times, then increments the value in RAM location $7000.

Note that the Count field may be any numeric expression but the expression is evaluated only once, the first time the loop is entered. This means that any changes to the expression's variables within the loop will not affect the number of iterations of the loop. The next example assumes the variable Index was created previously.

Index := 10                      'Set loop to repeat 10 times
repeat Index                     'Repeat Index times
  !outa[25]                      'Toggle P25
  Index := 20                    'Change Index to 20

In the above example, Index is 10 upon entering the REPEAT loop the first time. Each time through the loop, however, Index is set to 20, but the loop continues to execute only 10 times.

Counted Finite Loops (Syntax 2)

Quite often it is necessary to count the loop iterations so the loop's code can perform differently based on that count. The REPEAT command makes it easy to do this with syntax 2. The next example assumes the variable Index was created previously.

repeat Index from 0 to 9         'Repeat 10 times
  byte[$7000][Index]++           'Increment RAM locations $7000 to $7009 

Like the previous example, the code above loops 10 times, but each time it adjusts the variable Index. The first time through the loop, Index will be 0 (as indicated by the "from 0") and each iteration afterwards Index will be 1 higher than the previous (as indicated by the "to 9"): ..1, 2, 3…9. After the tenth iteration, Index will be incremented to 10 and the loop will terminate, causing the next code following the REPEAT loop structure to execute, if any exists. The code in the loop uses Index as an offset to affect memory, byte[$7000][Index]++; in this case it is incrementing each of the byte-sized values in RAM locations $7000 to $7009 by 1, one at a time.

The REPEAT command automatically determines whether the range suggested by Start and Finish is increasing or decreasing. Since the above example used 0 to 9, the range is an increasing range; adjusting Index by +1 every time. To get the count to go backwards, simply reverse the Start and Finish values, as in:

repeat Index from 9 to 0         'Repeat 10 times
  byte[$7000][Index]++           'Increment RAM $7009 down through $7000

This example also loops 10 times, but counts with Index from 9 down to 0; adjusting Index by -1 each time. The contents of the loop still increments the values in RAM, but from locations $7009 down to $7000.

After the tenth iteration, Index will equal -1.

Since the Start and Finish fields can be expressions, they can contain variables. The next example assumes that S and F are variables created previously.

S := 0
  F := 9
  repeat 2                       'Repeat twice
    repeat Index from S to F     'Repeat 10 times
      byte[$7000][Index]++       'Increment RAM locations 7000..$7009
    S := 9
    F := 0 

The above example uses a nested loop. The outer loop (the first one) repeats 2 times. The inner loop repeats with Index from S to F, which were previously set to 0 and 9, respectively. The inner loop increments the values in RAM locations $7000 to $7009, in that order, because the inner loop is counting iterations from 0 to 9. Then, the inner loop terminates (with Index being set to 10) and the last two lines set S to 9 and F to 0, effectively swapping the Start and Finish values. Since this is still inside the outer loop, the outer loop then executes its contents again (for the second time) causing the inner loop to repeat with Index from 9 down to 0. The inner loop increments the values in RAM locations $7009 to $7000, in that order (reverse of the previous time) and terminates with Index equaling -1. The last two lines set S and F again, but the outer loop does not repeat a third time.

REPEAT loops don't have to be limited to incrementing or decrementing by 1 either. If the REPEAT command uses the optional STEP Delta syntax, it will increment or decrement the Variable by the Delta amount. In the syntax 2 form, REPEAT is actually always using a Delta value, but when the "STEP Delta" component is omitted, it uses either +1 or -1 by default, depending on the range of Start and Finish.

The following example includes the optional Delta value to increment by 2.

repeat Index from 0 to 8 step 2  'Repeat 5 times
  byte[$7000][Index]++           'Increment even RAM $7000 to $7008 

Here, REPEAT loops five times, with Index set to 0, 2, 4, 6, and 8, respectively. This code effectively increments every other RAM location (the even numbered locations) from $7000 to $7008 and terminates with Index equaling 10.

The Delta field can be positive or negative, regardless of the natural ascending/descending range of the Start and Finish values, and can even be adjusted within the loop to achieve interesting effects. For example, assuming Index and D are previously defined variables, the following code sets Index to the following sequence: 5, 6, 6, 5, 3.

D := 2
  repeat Index from 5 to 10 step D 
  --D 

This loop started out with Index at 5 and a Delta (D) of +2. But each iteration of the loop decrements D by one, so at the end of iteration 1, Index = 5 and D = +1. Iteration 2 has Index = 6 and D = 0. Iteration 3 has Index = 6 and D = -1. Iteration 4 has Index = 5 and D = -2. Iteration 5 has Index = 3 and D = -3. The loop then terminates because Index plus Delta (3 + -3) is outside the range of Start to Finish (5 to 10).

Conditional Loops (Syntax 3 and 4)

The final forms of REPEAT, syntax 3 and 4, are finite loops with conditional exits and have flexible options allowing for the use of either positive or negative logic and the creation of zero-to-many or one-to-many iteration loops. These two forms of REPEAT are usually referred to as "repeat while" or "repeat until" loops.

Let's look at the REPEAT form described by syntax 3. It consists of the REPEAT command followed immediately by either WHILE or UNTIL then Condition(s) and finally, on the lines below it, optional Statement(s). Since this form tests Condition(s) at the start of every iteration, it creates a zero-to-many loop; the Statement(s) block will execute zero or more times, depending on the Condition(s). For example, assume that X is a variable created earlier:

X := 0
repeat while X < 10              'Repeat while X is less than 10
  byte[$7000][X] := 0            'Increment RAM value
  X++                            'Increment X 

This example first sets X to 0, then repeats the loop while X is less than 10. The code inside the loop clears RAM locations based on X (starting at location $7000) and increments X. After the 10th iteration of the loop, X equals 10, making the condition while X < 10 false and the loop terminates.

This loop is said to use "positive" logic because it continues "WHILE" a condition is true. It could also be written with "negative" logic using UNTIL, instead. Such as:

X := 0
  repeat until X > 9             'Repeat until X is greater than 9
  byte[$7000][X] := 0            'Increment RAM value
  X++                            'Increment X 

The above example performs the same way as the previous, but the REPEAT loop uses negative logic because it continues "UNTIL" a condition is true; i.e: it continues while a condition is false.
In either example, if X was equal to 10 or higher before the first iteration of the REPEAT loop, the condition would cause the loop to never execute at all, which is why we call it a zero-to-many loop.

The REPEAT form described by syntax 4 is very similar to syntax 3, but the condition is tested at the end of every iteration, making it a one-to-many loop. For example:

X := 0
  repeat 
    byte[$7000][X] := 0          'Increment RAM value
    X++                          'Increment X
  while X < 10                   'Repeat while X is less than 10 

This works the same as the previous examples, looping 10 times, except that the condition is not tested until the end of each iteration. However, unlike the previous examples, even if X was equal to 10 or higher before the first iteration, the loop would run once then terminate, which is why we call it a one-to-many loop.

Other REPEAT Options

There are two other commands that affect the behavior of REPEAT loops: NEXT and QUIT. See the NEXT and QUIT commands for more information.

Unless otherwise noted, content on this site is licensed under the
Creative Commons Attribution-ShareAlike 4.0 International License.