Skip to content

8. Statements and control flow

EBNF
statements = statement+ .
statement = conditional | loop | reaction | expression .
scoped_statements = ( (* not "end", "else:", or "elif:" *) statement )+ .

A statement is either a conditional, a loop, a reaction, or an expression. Statements appear in the bodies of action fields such as conditions, scratch, and effects, as well as in other constructs that accept statement blocks.

EBNF
conditional = conditional_branches [ "else:" alternative ] "end" .
conditional_branches = "if" conditional_branch { "elif" conditional_branch } .
conditional_branch = condition ":" consequent .
condition = expression .
consequent = scoped_statements .
alternative = scoped_statements .

A conditional is an if/elif/else/end construct that executes one of several statement blocks depending on which condition evaluates to a truthy value. The elif and else branches are optional.

if @person.mood > 50:
@person.status = "happy"
elif @person.mood > 25:
@person.status = "neutral"
else:
@person.status = "sad"
end

Conditions are evaluated in order. The first branch whose condition is truthy has its consequent executed; all remaining branches are skipped. If no condition is truthy and an else branch is present, its alternative is executed. If no condition is truthy and there is no else branch, execution continues past the end.

A conditional MUST be terminated by end:

// Illegal: missing 'end'
if @person.mood > 50:
@person.status = "happy"
// Legal
if @person.mood > 50:
@person.status = "happy"
end

Conditionals may be nested:

if @person.mood > 50:
if @person.boldness > 50:
@person.status = "confident"
end
end
EBNF
loop = "loop" unary_expression "as" local_variable ":" scoped_statements "end" .
local_variable = local_variable_sigil binding_type identifier .

A loop iterates over a collection, binding each element to a local variable in turn. The body is a block of statements terminated by end.

loop @person.friends as _@friend:
_@friend.trust += 5
end

The collection expression MUST evaluate to an iterable value. The local variable is scoped to the loop body and is not accessible outside of it.

Loops may be nested:

loop @person.friends as _@friend:
loop _@friend.items as _@item:
_@item.value += 1
end
end
EBNF
local_variable = local_variable_sigil binding_type identifier .

A local variable is a variable scoped to a single block, such as a loop body. Local variables are prefixed with the local sigil _, followed by a type sigil (@ or &) and an identifier:

_@friend
_&value

Local variables are introduced by loop statements using the as keyword. They are only accessible within the body of the construct that introduces them.