Control Flow

if/else, while loops, for/in iteration, break, and continue in Chasm.

if / else

Every branch is surrounded by do ... end. The else clause is optional:

if x > 0 do
  print("positive")
end

if x > 0 do
  print("positive")
else
  print("non-positive")
end

Chain multiple conditions with else if:

if x > 0 do
  print("positive")
else
  if x < 0 do
    print("negative")
  else
    print("zero")
  end
end

if is also an expression, both branches must produce a value of the same type:

label = if @score > 100 do "great" else "ok" end

while

Loops until the condition is false:

i = 0
while i < 10 do
  print(i)
  i = i + 1
end

No do..while:

Chasm does not have a do..while construct. Use a while true do ... break end pattern if you need it.

for / in

Range iteration

start..end iterates from start up to (but not including) end:

for i in 0..5 do
  print(i)   # 0, 1, 2, 3, 4
end

Array iteration

Iterate every element of an array:

names :: []string = array_new(3)
names.push("Alice")
names.push("Bob")
names.push("Carol")

for name in names do
  print(name)
end

The loop variable is a copy of each element. Structs are copied by value.

break and continue

break exits the nearest enclosing loop immediately:

for i in 0..100 do
  if i == 42 do
    break
  end
  print(i)
end

continue skips the rest of the current iteration and starts the next:

for i in 0..10 do
  if i == 3 do
    continue
  end
  print(i)   # prints 0 1 2 4 5 6 7 8 9
end

Both break and continue work in while loops too.

Practical Example

A game pattern, process active enemies and stop early:

@enemies :: script = array_fixed(32, Enemy{ x: 0.0, y: 0.0, hp: 0, active: 0 })

def on_tick(dt :: float) do
  i = 0
  while i < @enemies.len do
    e = @enemies.get(i)
    if e.active == 0 do
      i = i + 1
      continue
    end
    if e.hp <= 0 do
      @enemies.set(i, e with { active: 0 })
      i = i + 1
      continue
    end
    @enemies.set(i, e with { x: e.x + 1.0 * dt })
    i = i + 1
  end
end