Chapter 8
Control Flow
Overview
Conditions and loops are expressions like every other construct: an
if with both branches has a value, and a
repeat loop answers the operand of the
break that ends it. A condition needs no parentheses;
a body of one statement needs no braces, a longer one is a block in
braces that begins on a line of its own. if cond stmt
without an else runs the statement when the condition
is true, and control continues after it.
Conditions are written as and/or
chains. A null test proves its name for what follows it in the chain:
in p <> null and p.x = 7 the right side reads
p.x only where p is there.
If Expressions
If expressions evaluate a condition and return one of two values.
Basic If
The if expression takes a boolean condition and two branches.
| Input | Result |
|---|---|
if true : 1 else 2 | 1
|
if false : 1 else 2 | 2
|
if 5 > 3 : 10 else 20 | 10
|
If with Bindings
If expressions can use values from let bindings.
| Input | Result |
|---|---|
| 10
|
| 7
|
Else-If Chains without a Final Else
An if statement may chain an else if without a final else. Such a chain yields no value; when no condition holds, the statement falls through and any bindings keep their prior values. (Regression: the emitter used to merge the arms' values into a dead phi node that failed LLVM verification when the inner arm's value was computed inside its own branch.)
| Input | Result |
|---|---|
| 6107
|
While Loops
While loops repeat as long as a condition is true.
Basic While
A while loop evaluates its body repeatedly while the condition is true.
| Input | Result |
|---|---|
| 3
|
| 10
|
While with Accumulation
While loops can accumulate values across iterations.
| Input | Result |
|---|---|
| 6
|
| 120
|
For Loops
For loops iterate over a range of integers.
Basic For
A for loop iterates from 0 to n-1 where n is the range expression.
| Input | Result |
|---|---|
| 3
|
| 42
|
For with Accumulation
For loops can accumulate values using the loop variable.
| Input | Result |
|---|---|
| 10
|
| 24
|
Break and Continue
Break exits a loop early, continue skips to the next iteration.
Break Statements
Break exits the innermost enclosing loop.
| Input | Result |
|---|---|
| 3
|
| 5
|
Continue Statements
Continue skips the rest of the current iteration and continues with the next.
| Input | Result |
|---|---|
| 6
|
| 20
|
Nested Loops
By default break and continue affect only the innermost loop.
| Input | Result |
|---|---|
| 6
|
| 9
|
Labeled Break and Continue
A loop may carry a label written label NAME after its colon.
From within a nested loop, break loop NAME exits the named loop and
continue loop NAME jumps to its next iteration, rather than acting on
the innermost loop.
| Input | Result |
|---|---|
| 2
|
| 0
|
Repeat Loops
A repeat loop runs its body forever and exits only through break (or
return). Because break is the only way out, a break carrying a value
(break v) makes the repeat an expression that yields that value.
Repeat and Break Value
The value of a repeat expression is the operand of the break that exits it.
| Input | Result |
|---|---|
| 105
|
| 3
|
Mutable Variables
A binding introduced with var may be assigned a new value; one introduced with let may not. The assignment is written target := source, in the Algol tradition, and is a statement of its own: it introduces no name and is never part of a condition. The equals sign always compares.
Var and Assignment
Var creates a mutable variable, and := assigns it.
| Input | Result |
|---|---|
| 5
|
| 10
|
| 4
|
| 6
|
Match
match compares one value against a list of
case alternatives and takes the first that is equal;
one case may name several values, and else takes the
rest. It works on numbers, characters and strings, which it compares by
content:
function kind(n: int) returns int
match n
case 1: 10
case 2 case 3: 20
else 0
let word "b"
match word
case "a": print "A"
case "b": print "B"
else print "?"
A union is matched by its variants with choose,
described under Union Types.