Statements
Statements and expressions in B3 are self-terminating, so there are no semi-colons.
Stmt ::=
| VarDecl
| Assign
| Reinit
| BlockStmt
| Call
// assertions
| Check
| Assume
| Reach
| Assert
| AForall
// control flow
| Choose
| If
| IfCase
| Loop
| LabeledStmt
| Exit
| Return
// error reporting
| Probe
Variable declarations
VarDecl ::=
( var | val ) Identifier [ ":" Type ] [ "autoinv" Expression ] [ ":=" Expression ]
A declaration using var introduces a mutable local variable, whereas val
introduces an immutable local variable. A mutable variable that is never updated
is semantically equivalent to an immutable variable. However, the body of a forall
statements is not allowed to declare mutable variables.
The variable declaration is allowed to omit one of : Type or := Expression,
but not both. If the type is omitted, it is determined from the given expression.
If the expression is omitted, the variable is initialized with an arbitrary value
of its type.
The variable remains in scope until the end of the enclosing block.
A variable is allowed to shadow previously declared variables with the same name.
Assignment statements
Assign ::=
Identifier ":=" Expression
The identifier must be a mutable variable.
Re-init statements
Reinit ::=
reinit Identifier*,
This statement sets each of the named variables to an arbitrary value, subject to the auto-invariants of the variables.
Block statements
BlockStmt ::=
"{" Stmt* "}"
Call statement
Call ::=
Identifier "(" CallArgument ")"
CallArgument ::=
| Expression
| ( "inout" | "out" ) Identifier
A call statement invokes a procedure. The argument mode (in, inout, or out) of each parameter
is explicitly repeated at the call site (where the absence of inout and out indicates an
in-argument).
The types of the actual arguments must be the same as for the corresponding formal parameters.
The variables given as inout- and out-arguments must be distinct mutable variables.
Check statements
Check ::=
check Expression
The statement check e describes the intention that every program trace that leads to
this statement finds e to evaluate true.
It is an error if control flow can reach a check statement whose expression can evaluate to false.
Assume statements
Assume ::=
assume Expression
The statement assume e declares that a program trace that leads to this statement is of interest
only if, in that trace, e to evaluate true. In other words, the assume statement says that
“what follows this statement is of interest only if e evaluates to true”.
Reach statements
Reach ::=
reach Expression
The statement reach e describes the intention that there exists a program trace that leads to
this statement and finds e to evaluate true.
Assert statements
Assert ::=
assert Expression
A statement assert E is equivalent to the statement sequence check E assume E.
Forall statements
AForall ::=
forall Identifier ":" Type
BlockStmt
TODO: description
Choose statements
Choose ::=
choose BlockStmt ( or BlockStmt )*
TODO: description
If statements
If ::=
if Expression BlockStmt [ else IfContinuation ]
IfContinuation ::=
| BlockStmt
| If
| IfCase
TODO: description
If-case statements
IfCase ::=
if Case+
Case ::=
case Expression BlockStmt
TODO: description
Loops
Loop ::=
loop Invariant* BlockStmt
Invariant ::=
invariant AExpression
TODO: description
Labeled statements
LabeledStmt ::=
Identifier ":" ( BlockStmt | Loop )
TODO: description
Exit statements
Exit ::=
exit [ Identifier ]
An exit statement terminates a statement abruptly, transferring control out of the enclosing statement labeled with the given label. If the label is omitted, the statement transfers control out of the enclosing loop (which need not be labeled).
Return statements
Return ::=
return
A return statement terminates a procedure body abruptly, transferring control out
of the enclosing procedure body. It is as if the procedure body were labeled and
the return statement performs an exit to that label.
Probe statements
Probe ::=
probe Expression
TODO: description