Loops

Iteration constructs for repeated execution.

Source: src/scripting/control_flow.f90:274-608, src/ast/evaluator_simple_real.f90:2020-2346

For Loops

Word List Form

Iterate over a list of words:

for var in word1 word2 word3; do
    echo "$var"
done

Source: control_flow.f90:359-491

Positional Parameters

When in list is omitted, iterates over $@:

for arg; do
    echo "Argument: $arg"
done

Glob Expansion

Patterns are expanded to matching files:

for file in *.txt; do
    echo "Processing $file"
done

# Multiple patterns
for file in *.txt *.md *.rst; do
    wc -l "$file"
done

If no files match, the pattern is used literally. To avoid this:

shopt -s nullglob
for file in *.txt; do
    echo "$file"
done

Brace Expansion

# Numeric range
for i in {1..5}; do
    echo $i
done
# Output: 1 2 3 4 5

# With step
for i in {0..10..2}; do
    echo $i
done
# Output: 0 2 4 6 8 10

# Character range
for c in {a..e}; do
    echo $c
done
# Output: a b c d e

# Comma-separated
for x in {red,green,blue}; do
    echo $x
done

C-Style Arithmetic Form

Source: control_flow.f90:493-608

for ((init; condition; increment)); do
    commands
done

All three parts are optional:

# Standard form
for ((i=0; i<10; i++)); do
    echo $i
done

# Multiple variables
for ((i=0, j=10; i<j; i++, j--)); do
    echo "$i $j"
done

# Infinite loop (all parts empty)
for ((;;)); do
    echo "forever"
    sleep 1
done

Arithmetic expressions are evaluated via arithmetic_expansion_shell(). The initialization runs once, condition is checked before each iteration (non-zero exits), and increment runs after each iteration body.

While Loops

Source: control_flow.f90:274-314

Execute while condition is true (exit status 0):

while condition; do
    commands
done

Examples

# Counter
count=0
while [[ $count -lt 5 ]]; do
    echo $count
    ((count++))
done

# Read lines
while IFS= read -r line; do
    echo "Line: $line"
done < file.txt

# Until command fails
while grep -q "busy" status.txt; do
    sleep 1
done

# Infinite loop
while true; do
    process_queue
    sleep 5
done

Condition Re-evaluation

The condition is stored as condition_cmd on the control stack and re-evaluated fresh at each iteration. This is important for conditions that change:

while [[ $(wc -l < queue.txt) -gt 0 ]]; do
    process_first_line
done

Until Loops

Source: control_flow.f90:316-357

Execute while condition is false (non-zero exit status):

until condition; do
    commands
done

Semantically opposite of while. The condition is inverted internally (line 348: .not. condition_result).

# Wait for file
until [[ -f /tmp/ready ]]; do
    sleep 1
done

# Equivalent while form
while [[ ! -f /tmp/ready ]]; do
    sleep 1
done

Loop Control

Break

Source: src/execution/builtins.f90:2406-2456

Exit the innermost loop:

for i in {1..10}; do
    if [[ $i -eq 5 ]]; then
        break
    fi
    echo $i
done
# Output: 1 2 3 4

Exit multiple levels:

for i in {1..3}; do
    for j in {1..3}; do
        if [[ $j -eq 2 ]]; then
            break 2  # Exit both loops
        fi
        echo "$i,$j"
    done
done
# Output: 1,1

Continue

Source: src/execution/builtins.f90:2458-2508

Skip to next iteration:

for i in {1..5}; do
    if [[ $((i % 2)) -eq 0 ]]; then
        continue
    fi
    echo $i
done
# Output: 1 3 5

Skip multiple levels:

for i in {1..3}; do
    for j in {1..3}; do
        if [[ $j -eq 2 ]]; then
            continue 2  # Skip to next i
        fi
        echo "$i,$j"
    done
done
# Output: 1,1 2,1 3,1

Outside Loop Context

Both break and continue silently succeed (exit status 0) when called outside a loop, per POSIX.

Exit Status

  • Loop returns exit status of last executed command
  • Returns 0 if loop body never executed

Common Patterns

Process All Arguments

for file in "$@"; do
    process "$file"
done

Read File Lines

while IFS= read -r line || [[ -n "$line" ]]; do
    echo "$line"
done < file.txt

The || [[ -n "$line" ]] handles files without trailing newline.

Counter with While

i=0
while [[ $i -lt 10 ]]; do
    echo $i
    ((i++))
done

Find and Process

while IFS= read -r -d '' file; do
    process "$file"
done < <(find . -name "*.txt" -print0)

Retry with Backoff

attempts=0
until curl -sf http://example.com/health; do
    ((attempts++))
    if [[ $attempts -ge 5 ]]; then
        echo "Failed after 5 attempts"
        exit 1
    fi
    sleep $((attempts * 2))
done

Menu Loop

while true; do
    echo "1) Option A"
    echo "2) Option B"
    echo "q) Quit"
    read -p "Choice: " choice
    case $choice in
        1) do_a ;;
        2) do_b ;;
        q) break ;;
        *) echo "Invalid" ;;
    esac
done

Nesting Limits

Control flow nesting is limited by MAX_CONTROL_DEPTH. Exceeding this limit produces: "Control flow nesting too deep" (control_flow.f90:489).