03-statements

Chapter 3: Statements

A statement is an imperative representation of a computation; executing a statement might raise one or more side effects, but does not yield a result value. Whereas expressions are primarily about reaching a result value, statements are primarily about orchestrating control flow or raising some other effect.

What happens after a statement executes depends on whether the statement finishes normally or abruptly. In general, the former means that the next statement in order will execute, and the latter means that it will not, and something else will happen next. At the extreme end, program execution itself can finish abruptly. In order to more finely control the execution of blocks, loops, and loop iterations, labels can be declared and used.

Statements are semicolon-terminated; in general, it is legal for any statement to end with a semicolon. However, the semicolon can be omitted for any statement which occurs last in its block or compilation unit. Also, a special provision is made for statements which end in a closing curly brace (}); if the curly brace is followed by (horizontal whitespace and) a newline, then the semicolon can be omitted. All these rules are captured in the nonterminal <semicolon>, which usually resolves to a semicolon, but sometimes resolves to block end, compilation unit end, or closing curly brace and newline.

<statement> ::= <empty-statement>
             |  <expression-statement>
             |  <if-statement>
             |  <while-statement>
             |  <for-statement>
             |  <next-statement>
             |  <last-statement>
             |  <return-statement>
             |  <throw-statement>
             |  <catch-phaser>
             |  <leave-phaser>
             |  <block-statement>
             |  <labeled-statement>

3.1 Empty statement

An empty statement does nothing, and finishes normally.

<empty-statement> ::= <semicolon>

3.2 Expression statement

An expression statement evaluates an expression, and finishes normally.

<expression-statement> ::= <expression> <semicolon>

3.3 if statement

An if statement evaluates a condition, and uses the result of the condition to decide whether to (in the truthy case) evaluate the first block, or (in the falsy case) evaluate the (optional) rest of the statement (which might be a single unconditional block, or a nested if statement).

<if-statement> ::= "if"
                   <expression>
                   <xblock>
                   (<empty> | <xblock> | <if-statement>)
                   <semicolon>

3.4 while statement

A while statement evaluates a condition; in case this condition evaluates to a truthy value, the corresponding block is run, and the while statement is re-executed; in case the condition evaluates to a falsy value, the while statement finishes normally.

<while-statement> ::= "while" <expression> <xblock> <semicolon>

3.5 for statement

A for statement evaluates an expression, expecting it to be an Array; if it is not, execution terminates abruptly with an error. If it is an array, the block is executed once for each element in the array, possibly passing in the element as an argument.

<for-statement> ::= "for" <expression> <xblock> <semicolon>

3.6 next statement

A next statement abruptly finishes a surrounding loop iteration, and begins the next one. This statement can only occur inside a loop block. A label, if provided, must resolve to the Label of a surrounding loop.

<next-statement> ::= "next" <label>? <semicolon>

3.7 last statement

A last statement abruptly finishes by successfully finishing the surrounding loop, meaning that execution continues immediately after the loop itself. This statement can only occur inside a loop block. A label, if provided, must resolve to the Label of a surrounding loop.

<last-statement> ::= "last" <label>? <semicolon>

3.8 return statement

A return statement abruptly finishes and returns a value out of the innermost surrounding function. Evaluation continues after the expression that called the function. This statement can only occur inside a routine. An expression, if provided, is used to determine the return value; if no expression is provided, the value none is returned.

<return-statement> ::= "return" <expression>? <semicolon>

3.9 throw statement

A throw statement evaluates an expression to a value (expected to be of type Exception), and abruptly finishes and proceeds up the dynamic call stack, looking for the first catch clause that matches the value. Execution continues at the catch clause's block. In case there is no such catch clause, program execution finishes abruptly with an error based on the value.

<throw-statement> ::= "throw" <expression> <semicolon>

3.10 CATCH phaser

A CATCH phaser does not run as part of the normal control flow. Instead, it triggers if an exception is thrown and unrolls to the dynamic scope of the surrounding block. The optional parameter to the CATCH block is the exception.

<catch-phaser> ::= "CATCH" <xblock> <semicolon>

At most one CATCH block per surrounding block is allowed.

3.11 LEAVE phaser

A LEAVE phaser does not run as part of the normal control flow. Instead, it triggers unconditionally on the surrounding block's exit, whether that exit is a normal exit through the bottom of the block, or an abrupt exit such as via last or return or throw.

<leave-phaser> ::= "LEAVE" <block> <semicolon>

Teardown logic that needs to run regardless of how the block exits should be put in a LEAVE phaser.

If several LEAVE phasers are in the same block, they will run in reverse textual order.

3.12 Block statement

A block statement runs a block, and finishes normally.

In case of a grammatical conflict between a { starting a block statement and a { starting an expression statement starting an object literal, it's resolved in favor of the block statement.

<block-statement> ::= <block>
                      <semicolon>

<block> ::= "{" (<statement> | <declaration>)* "}"

Blocks occur regularly inside other statement forms. There are also pointy blocks, which accept a parameter:

<pblock> ::= "->" <parameter> <block>

But pointy blocks are not usually used directly; instead, the option is usually given between plain blocks and pointy blocks:

<xblock> ::= <block> | <pblock>

3.13 Labeled statement

A labeled statement is a statement optionally preceded by a label and a colon. All statements are allowed to be labeled statements, although by default only loops and block statements make any use of having a label. A statement can have zero or more labels.

The label is an identifier, with the colon not being considered part of the label itself. The presence of a label in a labeled statement counts as a declaration, and the name of the label is bound in the lexical scope to a value of type Label.

<labeled-statement> ::= <label> ":" <statement>

<label> ::= <identifier>

The Camelia image is copyright 2009 by Larry Wall. "Raku" is trademark of the Yet Another Society. All rights reserved.