Statements
Statements largely work like in C, but with some additions.
Expression blocks
Expression blocks (delimited using {| |}
) are compound statements that opens their own function scope.
Jumps cannot be done into or out of a function block, and return
exits the block, rather than the function as a whole.
The function below prints World!
fn void test()
{
int a = 0;
{|
if (a) return;
io::printf("Hello ");
return;
|};
io::printf("World!\n");
}
Expression blocks may also return values:
fn void test(int x)
{
int a = {|
if (x > 0) return x * 2;
if (x == 0) return 100;
return -x;
|};
io::printfn("The result was %d", a);
}
Labelled break and continue
Labelled break
and continue
lets you break out of an outer scope. Labels can be put on if
,
switch
, while
and do
statements.
fn void test(int i)
{
if FOO: (i > 0)
{
while (1)
{
io::printfn("%d", i);
// Break out of the top if statement.
if (i++ > 10) break FOO;
}
}
}
Do-without-while
Do-while statements can skip the ending while
. In that case it acts as if the while
was while(0)
:
do
{
io::printn("FOO");
} while (0);
// Equivalent to the above.
do
{
io::printn("FOO");
};
Nextcase and labelled nextcase
The nextcase
statement is used in switch
and if-catch
to jump to the next statement:
switch (i)
{
case 1:
doSomething();
nextcase; // Jumps to case 2
case 2:
doSomethingElse();
}
It's also possible to use nextcase
with an expression, to jump to an arbitrary case:
switch (i)
{
case 1:
doSomething();
nextcase 3; // Jump to case 3
case 2:
doSomethingElse();
case 3:
nextcase rand(); // Jump to random case
default:
io::printn("Ended");
}
Which can be used as structured goto
when creating state machines.
Switch cases with runtime evaluation
It's possible to use switch
as an enhanced if-else chain:
switch (true)
{
case x < 0:
xless();
case x > 0:
xgreater();
default:
xequals();
}
The above would be equivalent to writing:
if (c < 0)
{
xless();
}
else if (x > 0)
{
xgreater();
}
else
{
xequals();
}
Note that because of this, the first match is always picked. Consider:
switch (true)
{
case x > 0:
foo();
case x > 2:
bar();
}
Because of the evaluation order, only foo()
will be invoked for x > 0, even when x is greater than 2.
It's also possible to omit the conditional after switch
. In that case it is implicitly assumed to be same as
writing (true)
switch
{
case foo() > 0:
bar();
case test() == 1:
baz();
}