Skip to content

Loops

CKSP supports three types of loops: the while loop, which follows a syntax similar to vanilla KSP, the classic for loop with a counter, and the for-each loop, which is well-suited for iterating over arrays.


For-Each Loops

0.0.7

For-each loops provide a convenient syntax for iterating over arrays. The syntax is similar to other modern programming languages, making it easier to traverse arrays and enhancing code readability. Unlike classic for-loops, the iterators, in this case, the variables key and value, or just value, do not need to be declared beforehand.

Different types of for-each loops are available. You can iterate using only the value at each index position or use both the index and value as a pair in conjunction with the pairs() function. Additionally, you can easily iterate over multidimensional arrays without extra syntax or over specific dimensions of these arrays using wildcard notation.

Another efficient method is iterating over a range of numbers using the range(start, stop, step) function. If you need to iterate over a range with different steps, you can also use an initializer list directly.

Iterating Over Arrays

The following examples demonstrate the use of various for-each loop types with arrays.

1
2
3
4
declare array[5] := ["3", "4", "6", "8", "10"]
for val in array
    message(val)
end for
This example iterates over an array with 5 elements. val is the value of the current element in the array. For each iteration, the loop outputs the value of the element. The output is 3, 4, 6, 8, and 10.

1
2
3
4
declare array[5] := ["3", "4", "6", "8", "10"]
for key, val in pairs(array)
    message(key, val)
end for
In this example, the loop iterates over an array with 5 elements. key is the index of the current element in the array, and val is the value of the element. For each iteration, the loop outputs the index and the value of the element. The output is 0, 3, 1, 4, 2, 6, 3, 8, and 4, 10.

Iterating Over Multidimensional Arrays

As mentioned earlier, multidimensional arrays can also be iterated over. The wildcard notation can be used to iterate over specific dimensions.

1
2
3
4
declare ndarray[2, 3] := [[1, 2, 3], [4, 5, 6]]
for val in ndarray
    message(val)
end for
This example iterates over all elements of a two-dimensional array. val is the value of the current element. The output is the flattened array, which is 1, 2, 3, 4, 5, and 6.

1
2
3
for key, val in pairs(ndarray)
    message(key, val)
end for
This iteration can also be done using the pairs function as key-value pairs. In this case, the index of the element and the value of the element are output. The output is 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, and 5, 6.

1
2
3
4
declare ndarray[2, 3] := [[1, 2, 3], [4, 5, 6]]
for val in ndarray[0, *]
    message(val)
end for
To iterate only over the first dimension of the two-dimensional array, the wildcard notation can be used. In this case, only the first dimension of the array is iterated over. The output is 1, 2, and 3.
1
2
3
for idx, elem in pairs(ndarray[0, *])
    message(idx, elem)
end for
Here, the pairs function can also be used to output the index positions and the values of the elements. The output is 0, 1, 1, 2, and 2, 3.

1
2
3
4
declare ndarray[2, 3] := [[1, 2, 3], [4, 5, 6]]
for val in ndarray[*, *]
    message(val)
end for
This example shows the same result as the first, but here it is explicitly specified using wildcard notation that all dimensions of the array should be iterated over.

1
2
3
for i, elem in pairs(ndarray[*, *])
    message(i, elem)
end for
And of course, this example can also use the pairs function to output the index positions and the values of the elements. The output is 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, and 5, 6.

Iterating Over a Range of Numbers

To iterate over a range of numbers using for-each loops, the range(start, stop, step) function can be used. This function returns a list of numbers ranging from start to stop in steps of step. If the step parameter is not specified, it defaults to 1. Additionally, the start parameter is optional and defaults to 0. stop is always required and is treated as an exclusive value.

1
2
3
for num in range(10)
    message(num)
end for
When the range function is used without start and step parameters, it defaults to iterating from 0 to 10. The output is 0, 1, 2, 3, 4, 5, 6, 7, 8, and 9.

1
2
3
for idx, num in pairs(range(5, 10))
    message(idx, num)
end for
To get the indices of the numbers in the range, the pairs function can be used. In this case, it iterates from 5 to 10. The output is 0, 5, 1, 6, 2, 7, 3, 8, and 4, 9.

1
2
3
for num in range(10, 0, -1)
    message(num)
end for
To iterate in reverse order, the step parameter can be set to a negative value. In this case, it iterates from 10 to 0 in steps of -1. The output is 10, 9, 8, 7, 6, 5, 4, 3, 2, and 1.

1
2
3
for idx, num in pairs(range(10, 0, -1))
    message(idx, num)
end for
Here, the pairs function can also be used to get the indices of the numbers in the range. The output is 0, 10, 1, 9, 2, 8, 3, 7, 4, 6, 5, 5, 6, 4, 7, 3, 8, 2, and 9, 1.

Negative Step Value

To iterate in reverse order, the step parameter must be negative. It is not sufficient to set the start value greater than the stop value. In the latter case, the range would be empty, and no iteration would occur.

Iterating Over an Initializer List

To iterate over specific numbers that cannot be represented by a range function, an initializer list can be useful. cksp already provides the ability to pass these arrays or multidimensional arrays as values in an assignment statement. Additionally, these initializer lists can be used directly in a for-each loop.

Iterating Over a List of Numbers
1
2
3
for key, value in pairs([0,5,3,1,5,67])
    message(key, value)
end for
Here, this random sequence of numbers along with an index value is output. The output is 0, 0, 1, 5, 2, 3, 3, 1, 4, 5, and 5, 67.

It is also useful to iterate over a specific number of string values without having to store them in an array.

Iterating Over a List of Strings
1
2
3
for key, value in pairs(["Attack", "Decay", "Sustain", "Release"])
    label[key] -> text := value
end for
Here, each label in a possible ui_control array is directly assigned a text using an initializer list.


For Loops

The classic for loop uses a counter that must be declared before the loop. The counter is incremented or decremented on each iteration until the end condition is met. You can also specify a step value and have the loop run either upwards or downwards.

A simple for loop is defined with a start and end value, and the counter is incremented by 1 in each iteration:

1
2
3
4
declare i: int
for i := 0 to 6
    message(i, "i is below 6")
end for

Similar to the earlier while loop example, this for loop starts with i := 0 and runs until i := 6. It iterates 7 times, printing the values from 0 to 6.

You can adjust the step value in a for loop using the step keyword. This defines how much the counter is incremented with each iteration.

1
2
3
4
declare i: int
for i := 0 to 6 step 2
    message(i)
end for

In this example, the loop starts at i = 0 and ends at i = 6, but the counter is increased by 2 in each iteration. The output will be 0, 2, 4, and 6. This skipping of intermediate values is useful when not every value is needed.

A loop can be defined to run in reverse using the downto keyword.

1
2
3
4
declare i: int
for i := 6 downto 0
    message(i)
end for

This loop prints the numbers from 6 down to 0 in descending order.


While Loops

Just like vanilla KSP, CKSP supports traditional while loops, which repeatedly execute a block of code as long as a condition remains true. The condition is checked before each iteration. This makes while loops particularly useful when the number of iterations is not known beforehand.

Simple While Loop
1
2
3
4
5
declare i := 0
while(i < 6)
    message(i, "i is below 6")
    inc(i)
end while

In the example above, the loop starts with i := 0 and continues as long as i < 6. During each iteration, the current value of i is printed along with the message "i is below 6". The function inc(i) increments the value of i by 1 after each iteration. The loop terminates once the condition i < 6 is no longer true, meaning when i reaches 6.


Breaking or Continuing Loops

0.0.6 7.3

To alter the control flow within while or for loops, the break or continue keywords can be used.

The break Statement

The break statement in CKSP allows you to exit a loop prematurely. This can be particularly useful when you want to terminate the loop based on a certain condition without waiting for the loop’s normal end condition to be met.

1
2
3
4
5
6
7
8
declare i := 0
while (i < 10)
    inc(i)
    if (i = 5)
        break
    end if
    message(i)
end while

In this example, the loop starts with i := 0 and continues as long as i < 10. However, when i reaches 5, the break statement is executed, causing the loop to terminate immediately. Therefore, only the values from 1 to 4 will be processed by the message function, and the loop exits without completing the rest of the iterations.

1
2
3
4
5
6
7
declare i := 0
for i := 0 to 10
    if (i = 7)
        break
    end if
    message(i)
end for

In this example, the loop would normally run from 0 to 10. However, the break statement causes the loop to exit when i equals 7. As a result, the loop will print the numbers 0 through 6 and then terminate.

The continue Statement

The continue statement is used to skip the rest of the code in the current loop iteration and proceed to the next iteration. This can be useful for cases where you want to bypass certain processing based on a condition but still continue looping. continue skips the remaining code for that specific iteration and does not exit the loop entirely, unlike break.

1
2
3
4
5
6
7
8
declare i := 0
while (i < 5)
    inc(i)
    if (i <= 3)
        continue  // Skip to the next iteration if i <= 3
    end if
    message(i, "Processed")
end while

Here, the loop increments i on each iteration. When i is 1, 2, or 3, the continue statement is executed, and the rest of the loop body (the message function) is skipped. Therefore, the message 'Processed' will only be printed for i := 4 and i := 5.

1
2
3
4
5
6
7
for i := 0 to 5
    if (i = 2)
        continue
    end if

    message(i)
end for

In this example, the loop will print all numbers from 0 to 5 except 2. When i equals 2, the continue statement skips the rest of the loop iteration, and the loop moves to i := 3.

Difference Between While and For Loops

Although continue behaves similarly in both loop types, there is an important distinction:

  • While Loop: continue jumps directly to the loop condition, re-evaluating it before starting the next iteration.
  • For Loop: continue first executes the loop’s update expression (e.g. incrementing the counter), and only then re-evaluates the condition.

This means that a for loop with continue will still advance its loop variable, while in a while loop this must be ensured manually.
When lowering for loops into while loops at compile time, CKSP automatically inserts the update expression before the continue to preserve the same semantics.