= Statements in Nickle

== Simple statements

_expr_ `;` +
`;` `/* null statement */` +
`{` _statement_ ... `}`

The simplest statement is merely an expression terminated by a semicolon; the expression is evaluated.
A semicolon by itself is allowed but does nothing.
One or more statements may be grouped inside curly braces to form one compound statement; each is executed in order.
Any statements may compose the statement list, including control statements and other curly-bracketed lists. 

== Conditionals

`if (` _expr_ `)` _statement_
`else` _statement_

`if` is used to execute a section of code only under some condition:
If `expr` is true, `statement` is executed; otherwise control skips
over it.  For example:

----
if ( x == 0 )
        printf ( "x is zero.\n" );
----

In this case, the message will be printed only if `x` is zero. 

`else` allows for a choice if the condition fails.  It executes its
`statement` if the most recent `if` or `twixt` (see below) did not.
For example,

----
if ( x == 0 )
        printf ( "x is zero.\n" );
else
        printf ( "x is not zero.\n" );
----

More than one option may be presented by nesting further 'if's in
'else' statements like this:

----
if ( x == 0 )
        printf ( "x is zero.\n" );
else if ( x  0 )
        printf ( "x is negative.\n" );
else
        printf ( "x is positive.\n" );
----

== Twixt

`twixt (` _expr_ `;` _expr_ `)` _statement_

Ensures that the the first `expr` will always have been evaluated
whenever control flow passes into any part of `statement` and ensures
that the second `expr` will be evaluated anytime control flow passes
out of `statement`. _That order is guaranteed_.  If a `long_jmp`
target is inside `statement`, the first `expr` will be executed before
control passes to the target.  If `statement` throws an exception or
`long_jmp`s out of the `twixt`, the second `expr` will be evaluated.
Thus, `twixt` is useful in locked operations where the statement
should only be executed under a lock and that lock must be released
afterwards.

----
twixt ( get_lock ( ); release_lock ( ) )
        locked_operation ( );
----

== Switch

`switch (` _expr_ `) { case` _expr_ `:` _statement-list_ ... `default:` _statement-list_ `}`

Control jumps to the first `case` whose `expr` evaluates to the same
value as the `expr` at the top.  Unlike in C, these values do not have
to be integers, or even constant.  The optional case `default` matches
any value.  If nothing is matched and there is no `default`, control
skips the `switch` entirely.  This example prints out a number to the
screen, replacing it by a letter as though it were a poker card:

----
switch ( x ) {
        case 1:
                printf ( "A\n" );       /* ace */
                break;
        case 11:
                printf ( "J\n" );       /* jack */
                break;
        case 12:
                printf ( "Q\n" );       /* queen */
                break;
        case 13:
                printf ( "K\n" );       /* king */
                break;
        default:
                printf ( "%d\n", x );   /* numeric */
                break;
}
----

Notice the `break`s in the example.  Once control jumps to the
matching case, it continues normally: Upon exhausting that
`statement-list`, _it does not jump out of the `_switch_`_; it
continues through the subsequent statement lists.  Here is an example
of this 'falling through':

----
int x = 3;

switch ( sign ( x ) ) {
        case -1:
                printf ( "x is negative.\n" );
        case 1:
                printf ( "x is positive.\n" );
        default:
                printf ( "x is zero.\n" );
}
----

This prints: 

----
x is positive.
x is zero.
----

Falling through may be desirable if several cases are treated
similarly; however, it should be used sparingly and probably commented
so it is clear you are doing it on purpose.  This is a difficult error
to catch.

== Union switch
`union switch (` _union_ `) { case` _name_ `:` _statement-list_ ... `default:` _statement-list_ `}`

`union switch` is similar to `switch`.  It matches the `case` based on
what name currently applies to the union's value.  As always,
`default` matches everything.  The following example chooses the best
way to print the union:

----
union {
        int a;
        string b;
} u;

u.b = "hello";

union switch ( u ) {
        case a:
                printf ( "%d\n", u.a );
                break;
        case b:
                printf ( "%s\n", u.b );
                break;
}
----

In this case, it prints 'hello'. 

An additional name may follow that of a case; the union's value will be available inside the case by that name.
The switch above could have been written: 

----
union switch ( u ) {
        case a num:
                printf ( "%d\n", num );
                break;
        case b str:
                printf ( "%s\n", str );
                break;
}
----

== Loops

`while (` _expr_ `)` _statement_ +
`do` _statement_ `while (` _expr_ `)` +
`for (` _expr_ `;` _expr_ `;` _expr_ `)` _statement_

`while` executes `statement` repeatedly as long as `expr` is true.
Control continues outside the loop when `expression` becomes false.
For example: 

----
int x = 0;
while ( x  10 ) {
        printf ( "%d\n", x );
        ++x;
}
----

This prints the numbers from zero to nine. 

`do-while` is like `while`, but tests the condition after each iteration rather than before.
Thus, it is garaunteed to execute at least once.
It is often used in input while testing for end-of-file: 

----
file f = File::open ( "test", "r" );

do {
        printf ( "%s\n", File::fgets ( f ) );
} while ( ! end ( f ) );

close ( f );
----

`for` begins by evaluating the first `expr`, which often initializes a
counter variable; since declarations are expressions in Nickle, they
may be used here and the counter will be local to the loop.  Then it
executes `statement` as long as the second `expr` is true, like
`while`.  After each iteration, the third `expr` is evaluated, which
usually increments or decrements the counter variable.  The `while`
example above can also be written as the following `for` loop:

----
for ( int x = 0; x  10; ++x )
        printf ( "%d\n", x );
----

== Flow control

`continue` +
`break` +
`return` _expr_

`continue` restarts the nearest surrounding `do-while`, `while`, or
`for` loop by jumping directly to the conditional test.  The iterative
statement of a `for` loop will be evaluated first.

`break` leaves the nearest surrounding `do-while`, `while`, `for`, or
`switch` statement by jumping to its end.  The iterative statement of
a `for` loop will not be evaluated.

`return` returns from the nearest surrounding function with value
`expr`.