Language2 min read

Loops

Iteration constructs in BWSL including range-based loops, eval unrolling, and skip.

Reading Time
2 min
Word Count
325
Sections
20
Try It Live

Pressure-test the syntax

Take the concept from this page into the playground and deliberately break a pass, binding, or type signature to see how the compiler responds.

Try a Live Edit

BWSL provides a variety of loop constructs designed for shader programming, from familiar C-style loops to GPU-friendly range and unrolled forms.

C-Style For Loop

The traditional for loop works as expected:

bwsl
for (int i = 0; i < 10; i++) {
doThing(i);
}

Range-Based Loops

Exclusive Range

Use .. for an exclusive end bound:

bwsl
for (i in 0..10) {
doThing(i);
}

Inclusive Range

Use ..= for an inclusive end bound:

bwsl
for (i in 0..=9) {
doThing(i);
}

Step Size with by

bwsl
for (i in 0..100 by 4) {
processVector(i);
}

Multi-Variable Iteration

Use foreach to iterate over multiple ranges simultaneously:

bwsl
foreach (x in 0..width, y in 0..height) {
processPixel(x, y);
}

This expands to nested iteration over all combinations.

Collection Iteration

Explicit Element Variable

bwsl
for (vertex in vertices) {
transform(vertex);
}

Implicit Iterator

When you omit the element variable, use the reserved it keyword:

bwsl
for (lights) {
skip if (it.intensity < EPSILON);
accumLight += calculateLight(it);
}

Simple Loop

When you don't need an index, use loop with a count:

bwsl
loop (8) {
result = hash(result);
}

Loop Until

For post-condition loops, use loop with until:

bwsl
loop {
marchRay();
steps++;
} until (steps >= MAX_STEPS);

The loop body executes at least once before the condition is checked.

Compile-Time Unrolling

Eval For

bwsl
eval for (i in 0..4) {
output[i] = input[i] * 2.0;
}

Eval Loop

bwsl
eval loop (8) {
result = hash(result);
}

Use eval loops when the iteration count is small and known at compile time. This removes loop overhead and enables further folding.

Inside Eval Blocks

for and loop can also be used inside eval { ... } blocks, where all control flow is compile-time. This allows mixing compile-time variables with loop-generated runtime statements:

bwsl
eval {
eval int total = 0;
for (i in 0..4) {
total = total + i;
sum += float(i);
}
sum += float(total);
}

See Eval Blocks for full details.

Conditional Loop Control

Skip

BWSL uses skip instead of continue:

bwsl
for (int i = 0; i < 10; i = i + 1) {
skip if (i % 2 == 0);
sum = sum + float(i);
}

Break If

break if is the matching conditional form for early loop exit:

bwsl
for (int i = 0; i < 100; i = i + 1) {
sum = sum + float(i);
break if (sum > limit);
}

Loop Summary

ConstructDescription
for (int i = 0; i < n; i++)C-style loop with explicit counter
for (i in 0..n)Range loop, exclusive end
for (i in 0..=n)Range loop, inclusive end
for (i in 0..n by k)Range loop with custom step
foreach (x in a..b, y in c..d)Multi-variable nested iteration
for (item in collection)Collection iteration
for (collection)Collection iteration with implicit it
loop (n)Simple counted loop
loop { } until (cond)Post-condition loop
skip if (cond)Skip current iteration
break if (cond)Exit the loop early
eval for / eval loopCompile-time unrolled loops
eval { for ... }Compile-time loops inside eval blocks

See Also

  • Eval — Compile-time evaluation, eval blocks, and code folding
  • Language Overview - BWSL syntax and concepts