8. Statements
The body of a behaviour is a block: a sequence of statements that run in order. A statement may contain others (a condition, a loop, a block). Statements that act on models and resources are edition actions (chapter 10); they are statements by position and are described there.
8.1 Syntax
block = "{" block_statement* "}"
block_statement = type variable_declarator ";" (* local variable *)
| statement
statement = block
| ";"
| statement_expression ";"
| "if" "(" expression ")" statement
| "if" "(" expression ")" statement_no_short_if "else" statement
| "while" "(" expression ")" statement
| "do" statement "while" "(" expression ")" ";"
| "for" "(" for_init? ";" expression? ";" statement_expression? ")" statement
| "for" "(" type lidentifier ":" ( expression | fml_action_exp ) ")" statement
| "return" ";"
| "return" ( expression | fml_action_exp ) ";"
for_init = statement_expression | type variable_declarator
statement_expression = assignment | pre_increment | pre_decrement | post_increment | post_decrement
| method_invocation | new_instance | fml_action_exp
variable_declarator = lidentifier | lidentifier "=" expression | lidentifier "=" fml_action_exp
statement_no_short_if is statement without an if lacking an else; it resolves the dangling else as in
Java: an else belongs to the nearest preceding if.
There is no break, no continue, no switch, no try/catch/throw, and no labelled statement. A
loop ends when its condition does, or with return.
8.2 Local variables
A local variable is declared with its type and optionally an initial value:
int total = 0;
String name;
List<Shelf> shelves = select Shelf from this;
The type is mandatory; there is no type inference in a declaration. A local variable lives in the block that
declares it, from its declaration to the closing brace, and hides a property of the same name: this.name still
reaches the property.
public int scoped() {
int x = 0;
if (true) {
int y = 5;
x = y;
}
return x;
}
A local variable that is not initialised holds null, as a property does (§4.2).
The initial value of a declaration may be an expression or an edition action (§10): a select, a match,
a technology action.
8.3 Assignment
assignment = left_hand_side assignment_operator ( expression | fml_action_exp )
left_hand_side = composite_ident | field_access
An assignment is a statement expression: x = x + 1;, container.last = "done";, shape = DIAGRAM::AddShape(…);.
The left-hand side is a dotted name or a field access. An assignment to a name that is not a local variable
is an assignment to the property of that name in the current scope (§9.6.3): touched = touched + 1;.
An assignment to a path (other.value = 3;) sets the property of the object the prefix designates. An
assignment to a property that is not settable (an expression property, a get-only property) is ignored without an
error (§6.8).
The assignment operators are =, +=, -=, *=, /=, %=, <<=, >>=, >>>=, &=, |=, ^=.
A compound assignment used as a statement ignores its operator: n += 2; on
n = 5 leaves n equal to 2, because it is executed as n = 2 (CORE-D-7). Write n = n + 2;. As an
expression nested in another one, += is supported by the expression grammar; avoid it.
8.4 Conditions
public String grade(int score) {
if (parameters.score >= 90) {
return "A";
}
else if (parameters.score >= 50) {
return "B";
}
else {
return "C";
}
}
The condition is an expression of type boolean. It is evaluated once; the then branch runs when it is true and
the else branch, if any, when it is false.
The evaluation of a condition has a rule of its own:
| The condition… | …is taken as |
|---|---|
evaluates to true / false | that value |
evaluates to null | false |
goes through a null value (null reference) | false |
| is not set, is invalid (an unresolved name), or raises any other error | true |
The last row is a defect (CORE-D-8): an if whose condition does not resolve runs the
then branch, and a while loops forever. Nothing is reported at run time; validate the unit (§13.8).
8.5 Loops
while
public int sumWhile(int n) {
int i = 0;
int total = 0;
while (i < parameters.n) {
i = i + 1;
total = total + i;
}
return total;
}
do … while
Accepted by the grammar:
A do … while executes its body once and drops the condition (CORE-D-6).
Use while.
for
public int sumFor(int n) {
int total = 0;
for (int i = 1; i <= parameters.n; i++) {
total = total + i;
}
return total;
}
A classic for has an initialisation (a declaration or a statement expression), a condition and an update, each
optional in the grammar. The update is a single statement expression. i++ is supported in the update.
A for without a condition (for (int i = 0; ; i++)) is accepted by the
grammar and silently not built: the behaviour that contains it disappears and a call to it is an unresolved
binding (CORE-D-9). Always write the condition; to loop until a return, write while (true).
Also, after the first ; of a for header the lexer is back in the normal state (§2.3.1).
enhanced for
public String joinWords() {
String all = "";
for (String w : words) {
all = all + w + ",";
}
return all;
}
public String chorus() {
String all = "";
for (Creature c : select Creature from this) {
all = all + c.sound() + ";";
}
return all;
}
for (T x : source) iterates over the elements of a list; the source is an expression or an edition action
(typically a select). The loop variable is a new local of type T, bound to each element in turn. The elements
are visited in the order of the list; for a select this is the order of creation of the instances (§10.2).
8.6 Increment and decrement
++ and -- are accepted as statements and as expressions.
n++;, ++n;, n--; and --n; used as statements make the behaviour return
null (CORE-D-18). They work in the update part of a for. Write n = n + 1;.
8.7 Expression statements
A method call, a new, or an edition action used for its effect is a statement:
words.add(parameters.word);
new Shelf("Fiction", 20);
log "text is " + parameters.text;
delete parameters.book;
fire new ShelfCreated(parameters.label);
The value of such a statement is discarded.
8.8 Return
return; ends the behaviour. return expression; ends it and gives the value. return fml_action_exp; returns the result of an edition action, as in
return select unique Article from (this) where (selected.name == parameters.name);.
A return inside a loop ends the behaviour:
public String firstLong(int size) {
for (String w : words) {
if (w.length() >= parameters.size) {
return w;
}
}
return null;
}
8.9 Blocks and sequencing
Statements of a block run in order; a block is a statement. The body of a behaviour is a block. Internally the platform represents a body as a control graph of sequences, conditionals, iterations and actions, with the assignment of every value to a variable or property being an edition action; the textual form above is the only form this specification defines.