# Statements

# Overview

Statements are very close to those found in C or Java:

- Expression: expression statement
- Locals: declare a local variable
- Return: exit from a method
- If/Else: conditional branching
- While: conditional looping
- For: just like C `for` statement
- Foreach: array iteration
- Goto: unconditional branching
- Switch: jump tables
- Assert: used for unit testing

Unlike C or Java, statements are not required to be terminated with a semicolon. By convention they are terminated with a newline, although they can also be terminated with a semicolon or "}". All of these are valid statements:

    if (c)
    {
      doSomething()
      orAnother()
    }

    if (c)
    {
      doSomething();
      orAnother();
    }

    if (c) { doSomething(); orAnother() }

Note that Sedona's grammar is not always unambiguous when terminating a statement with a newline. So on occasion you might be required to use a semicolon. If you get a weird compiler error you don't understand try sticking in a semicolon. This might happen if you have a statement that starts with a parenthesis such as `((Type)x).something()`.

# Expression

The most common type of statements are stand alone expressions. The following expressions can be used as a statement:

- Assignment: `x = y, x++, x[i] = y, x.f += y`
- Method calls: `x()`

# Local Variables

Local variables are declared as follows:

    float f
    int i = 5
    Component c = doSomething()

Local variables are scoped within their block - they are not visible to parent blocks. A local variable must be definitely assigned before it is used or the compiler will generate an error. Sedona doesn't currently support declaring multiple local variables in one statement like C or Java.

# Return

The return statement is used to exit a method. If a return is used in a non-void method, then it must specify the expression to return:

    // void return
    return

    // non-void return
    return expr

# If/Else

Sedona supports C style if/else statements:

    // if, no else
    if (cond)
      block

    // if-else
    if (cond)
      block
    else
      block

    // if, if-else, else
    if (cond)
      block
    else if (cond)
      block
    else
      block

Like C/Java, each block may be a single statement, or a block of statements wrapped in "{ }" curly braces.

# Looping

Sedona supports the traditional while, do-while, and for loops of C like languages. Sedona also has a foreach statement for iterating arrays. In each case, the repeated code can be a single statement or a sequence of statements wrapped in "{ }" curly braces.

## While

The while statement is used to loop while a boolean expression evaluates to true:

    while (cond)
      block

## Do While

The do-while statement works just like the while loop, except the condition is evaluated at the end of the block. It is typically used when you wish to guarantee the loops executes at least once:

    do
      block
    while (cond)

## For

The for statement works like a while loop except it allows an initialization expression and an update expression that executes after each loop iteration:

    for (init; cond; update)
      block

    // example - prints 0 to 4
    for (int i=0; i<5; ++i)
      Sys.out.print("i = $i\n")

Any of the init, cond, or update expressions may be omitted. If the cond is omitted, then it defaults to true and the loop must be terminated with a break or return statement inside the block.

## Foreach

Sedona provides the foreach statement to iterate through an array. Using the foreach statement is more efficient than using a for loop because is compiles into a specialized instruction. The foreach statement takes a local variable declaration, an array to iterate, and an optional array length:

    foreach (type var : array)
      block

    foreach (type var : array, length)
      block

    // example - prints each kit name and version
    foreach (Kit kit : Sys.kits, Sys.kitsLen)
      Sys.out.print("$kit.name  $kit.version").nl()

The length may be omitted only if the compiler can infer the length of the array from its declaration.

## Break

The break statement is used to exit a loop. It may be used with any looping statement (while, do-while, for, and foreach):

    // prints 0 to 3, then breaks
    for (int i=0; i<10; ++i)
    {
      if (i == 4) break
      Sys.out.print("i=$i\n")
    }

If a break is used inside nested loops, it breaks from the inner-most loop. Labeled breaks are not supported.

## Continue

The continue statement causes the next iteration of the containing loop to begin. For a while and do-while, the loop condition is executed immediately. For a for or foreach loop, control is passed to the increment step.

    // prints 0, 1, 3 (skips 2)
    for (int i=0; i<4; ++i)
    {
      if (i == 2) continue
      Sys.out.print("i=$i\n")
    }

If a continue is used inside nested loops, it continues the inner-most loop. Labeled continues are not supported.

# Goto

The goto statement performs an unconditional jump to a labeled statement within the same method:

    // this method always returns "y"
    static Str f()
    {
      goto foo
      return "x"
      foo: return "y"
    }

# Switch

The switch statement works just like C and Java. It evaluates an integer expression and jumps to a cast label:

    Str s = null
    switch (i)
    {
      case 0:
      case 1:
        s = "0 or 1"
        break
      case 2:
        s =  "2"
        break
      default:
        s = "not 0, 1, or 2"
    }

Like C, case blocks fall through to the next case block - use a break statement to break out of the switch statement. The default block handles any value without an matching case label. The default block is optional; if omitted then unmatched values fall through to the next statement after the switch. However, if the default block exists, it must be the last label in the switch statement.

If the last case statement does not break and there is a default block, the last case statement will fall through into the default block.

    switch(i)
    {
      case 0:
        reset()
        break
      case 1:
        init() // fall through to default block
      default:
        work() // whenever i is not zero
    }

## Limits on Case Values

To reduce code size, case values must not be too widely spaced. For a difference `delta` between the minimum and maximum case values, and total number of case values `num`, at least one of the following must be true:

- `delta <= 30`
- `num*3 >= delta`

It is a compile time error if both conditions are false. If you get this compiler error, you should change your code to use the `if/else if/.../else` idiom.

# Assert

The assert statement is used for unit testing.

    assert(cond)

The condition must be a boolean expression. Failed assertions result in a call to the Sedona VM's `onAssertFailure` callback. On most platforms, this will print a message to stdout. See Porting for more details.