Expression statements
The most common type of statement is the expression statement—an expression followed by;
.
See the FunC expressions article for details on the allowed expressions.
return
statement
The return
statement ends function execution and specifies a value to be returned to the function caller.
Any statement after the return
statement is not executed.
In this example, the return
statement instructs the function to halt execution and produce x + 1
as a result.
return
executes:
Block statement
A block statement is used to group zero or more statements. The block is delimited by a pair of curly braces{ ... }
.
A block statement also defines a scope, in which variables defined in the block are accessible only in the block or in nested blocks.
For example:
Conditional statements
These statements control the flow of the code based on a condition.if...else
statement
When executing an if...else
statement, first, the specified condition is evaluated.
If the condition evaluates to an integer different from 0
(see absence of boolean type), the block after the condition is executed.
Otherwise, if the condition evaluates to 0
, the optional else
block is executed. If the else
block is missing, nothing happens, and execution continues further.
Examples:
{}
are required in each block of an if...else
statement.
For example, the following code will not compile:
else
block must have curly brackets:
elseif
keyword, to avoid the need to write
several nested curly brackets in the else
case:
elseif
keyword is useful for stating several alternative cases:
elseifnot
keyword, which allows the inclusion of ifnot
statements in the alternatives:
ifnot...else
statement
The ifnot...else
statement is equivalent to the if...else
statement but with the condition negated using the bitwise ~
operator.
More specifically:
ifnot
evaluates to 0
(see absence of boolean type), the block after the condition is executed.
Otherwise, if the condition evaluates to an integer different from 0
, the optional else
block is executed.
If the else
block is missing, nothing happens, and execution continues further.
Examples:
if...else
, it is possible to use the keyword elseifnot
to add several alternative cases:
elseif
keyword, which allows the inclusion of standard if
statements in the alternatives:
Loops
FunC supportsrepeat
, while
, and do { ... } until
loops. The for
loop is not supported.
repeat
loop
The repeat
loop executes a block of code a specified number of times.
The number of repetitions should be given as a positive 32-bit integer in the inclusive range from
1
to 2^31 - 1
(i.e., 2,147,483,647
). If the value is greater, an error with exit code 5, Integer out of expected range
, will be thrown.
0
or any negative number in the inclusive range from -2^256
to -1
, it is ignored,
and the code block is not executed at all.
while
loop
The while
loop continues executing the block of code as long as the given condition evaluates to an integer different from 0
.
See absence of boolean type.
do...until
loop
The do...until
loop is a post-test loop that executes the block of code at least once and then continues to execute it until the
given condition evaluates to an integer different from 0
. See absence of boolean type.
try...catch
statement
Available in FunC since v0.4.0
The try...catch
statement consists of a try
block and a catch
block.
The code in the try
block is executed first, and if it fails, all changes made within the try
block are rolled back,
and the catch
block is executed instead. The catch
block has two arguments, which are local to the catch
block:
- The exception parameter, which can be of any type. Used to provide extra information about the error.
- The error code, an integer, which identifies the kind of error.
try
block. These modifications include updates to
local and global variables and changes to control registers
(for example, c4
for storage, c5
for action/messages, c7
for context, etc.).
Any contract storage updates and outgoing messages are also reverted.
However, certain TVM state components are not rolled back, such as:
- Codepage settings
- Gas counters
I am not sure if “Codepage settings” and “gas counters” refer to some TVM state component in page ton/tvm#1-4-total-state-of-tvm-scccg
try
block is still accounted for, and any modifications carried out by operations
that change gas limits (e.g., accept_message
or set_gas_limit
) will remain in effect.
In this example,
x
is incremented to 1
inside the try
block, the modification is rolled back due to the exception produced by the throw
function.
Hence, x
has value 0
at the moment the catch
block starts execution. However, the gas consumed inside the try
block is not rolled back when the catch
block starts execution.
Here is an example which illustrates how to generate and use the exception parameter:
throw_arg(-1, 100)
produces an exception with error code 100
and exception parameter -1
.
However, since the exception parameter can be of any type, which may vary depending on the exception,
FunC cannot determine its type at compile time in the catch
block.
This requires the developer to manually cast the exception parameter. In the example, casting of the exception parameter is achieved with the
assembler and polymorphic
function cast_to_int
, which receives an argument of any type and returns the same argument as an integer by wrapping
the NOP
(no operation) TVM instruction: