Skip to main content

Reserved keywords

FunC reserves the following symbols and words. These cannot be used as identifiers.

Symbols

+   -*/ %?:, ;()[ ]{}= _<>& |^~== !=<=>=<=> <<>>~>>^>> ~/^/~%^% /%+=-=*= /=~/=^/=%= ~%=^%=<<=>>= ~>>=^>>=&=|= ^=->

Words

returnvarrepeatdo whileuntiltrycatch ififnotthenelse elseifelseifnotintcell slicebuilderconttuple typeforallexternglobal asmimpureinlineinline_ref auto_applymethod_idoperatorinfix infixlinfixrconst#pragma #include

Built-ins

This section covers extra language constructs that are not part of the core but are still important for functionality. Although they could be implemented in stdlib.fc, keeping them as built-in features allows the FunC optimizer to work more efficiently. In addition, FunC does not allow the built-in names in this section to be used as identifiers. However, there is an exception: built-ins with non-symbolic names can be used as identifiers for local variables.

Built-ins with symbolic names

_+__-_-__*_ _/__~/__^/__%_ _~%__^%__/%__<<_ _>>__~>>__^>>__&_ _|__^_~_^_+=_ ^_-=_^_*=_^_/=_^_~/=_ ^_^/=_^_%=_^_~%=_^_^%=_ ^_<<=_^_>>=_^_~>>=_^_^>>=_ ^_&=_^_|=_^_^=__==_ _!=__<__>__<=_ _>=__<=>_ Each one of the above names is a function wrapping the corresponding operator. For example, _+_ can be understood as wrapping the + operator:
int _+_(int a, int b) { return a + b; }
These functions are useful when operators need to be passed as arguments to functions, or assigned to variables. For example, in the following snippet, function apply receives as argument a function f of type (int, int) -> int and applies it on the arguments 2 and 3:
int apply(((int, int) -> int) f) {
    return f(2, 3);
}
Then, it is possible to invoke apply by passing _+_:
apply(_+_);   ;; Returns 5
Attempting to pass the operator + directly does not compile:
apply(+);   ;; DOES NOT COMPILE

Built-ins with non-symbolic names

divmod~divmodmoddiv~moddiv muldivmuldivrmuldivcmuldivmod truefalsenilNil null?throwthrow_ifthrow_unless throw_argthrow_arg_ifthrow_arg_unlessload_int load_uintpreload_intpreload_uintstore_int store_uint~store_int~store_uintload_bits preload_bitsint_atcell_atslice_at tuple_atattouch~touch touch2~touch2~dump~strdump run_method0run_method1run_method2run_method3

divmod

(int, int) divmod(int dividend, int divisor)
divmod takes two integers as input and returns the quotient and remainder of their division dividend / divisor.

~divmod

Same as divmod, but allows using modifying notation. Example:
int a = 10;
int b = 2;

;; "mod" stores the modulo 10 % 2
;; and "a" gets updated with the quotient of 10 / 2
int mod = a~divmod(b);

;; Here, a has value 5
;; mod has value 0
;; b has value 2

moddiv

(int, int) moddiv(int dividend, int divisor)
moddiv takes two integers as input and returns the remainder and quotient of their division dividend / divisor.

~moddiv

Same as moddiv, but allows using modifying notation. Example:
int a = 10;
int b = 2;

;; "div" stores the quotient of 10 / 2
;; and "a" gets updated with the modulo 10 % 2
int div = a~moddiv(b);

;; Here, a has value 0
;; div has value 5
;; b has value 2

muldiv

int muldiv(int factor1, int factor2, int divisor)
muldiv performs a multiply-then-divide operation (factor1 * factor2) / divisor, where / is the division operator. It uses a 513-bit intermediate result to prevent overflow if the final result fits within 257 bits.

muldivr

int muldivr(int factor1, int factor2, int divisor)
muldivr performs a multiply-then-divide operation (factor1 * factor2) ~/ divisor, where ~/ is the rounding division operator. It uses a 513-bit intermediate result to prevent overflow if the final result fits within 257 bits.

muldivc

int muldivc(int factor1, int factor2, int divisor)
muldivc performs a multiply-then-divide operation (factor1 * factor2) ^/ divisor, where ^/ is the ceiling division operator. It uses a 513-bit intermediate result to prevent overflow if the final result fits within 257 bits.

muldivmod

(int, int) muldivmod(int factor1, int factor2, int divisor)
muldivmod performs a multiply-then-divide operation (factor1 * factor2) / divisor, where / is the division operator, and returns the quotient and remainder of such division. It uses a 513-bit intermediate result to prevent overflow if the final result fits within 257 bits.

true

true is an alias for -1.

false

false is an alias for 0.

nil

nil is an alias for the null value.

Nil

Nil is an alias for the empty tuple [].

null?

forall X -> int null?(X val)
null? checks if the given argument is null. Returns 0 if the argument is not null, and -1 otherwise. For more info, see null values.

throw

() throw(int error)
Triggers an exception, which interrupts the execution flow. throw takes only one argument, the error code. See TVM error codes for details about error codes.

throw_if

() throw_if(int error, int condition)
Triggers an exception only if the provided condition is true, i.e., if the condition is -1. It receives two arguments: the error code, which defines the exception type, and the condition. See TVM error codes for details about error codes.

throw_unless

() throw_unless(int error, int condition)
Triggers an exception only if the provided condition is false, i.e., if the condition is 0. It receives two arguments: the error code, which defines the exception type, and the condition. See TVM error codes for details about error codes.

throw_arg

forall X -> () throw_arg(X arg, int error)
Triggers an exception, which interrupts the execution flow. The first argument can be of any type, and it is used to pass extra information about the error. This extra information can be processed in try..catch statements. Refer to the try..catch statement page for an example on how to use the first argument. The second argument is the error code. See TVM error codes for details about error codes.

throw_arg_if

forall X -> () throw_arg_if(X arg, int error, int condition)
Triggers an exception only if the provided condition is true, i.e., if the condition is -1. Similarly to throw_arg, the first argument can be of any type, and it is used to pass extra information about the error. This extra information can be processed in try..catch statements, in the same way as with throw_arg. The second argument is the error code. See TVM error codes for details about error codes. The third argument is the condition to check.

throw_arg_unless

forall X -> () throw_arg_unless(X arg, int error, int condition)
Triggers an exception only if the provided condition is false, i.e., if the condition is 0. Similarly to throw_arg, the first argument can be of any type, and it is used to pass extra information about the error. This extra information can be processed in try..catch statements, in the same way as with throw_arg. The second argument is the error code. See TVM error codes for details about error codes. The third argument is the condition to check.

load_int

(slice, int) load_int(slice s, int len)
Reads a signed len-bit integer from slice s. Returns the modified slice and the obtained integer.

load_uint

(slice, int) load_uint(slice s, int len)
Reads an unsigned len-bit integer from slice s. Returns the modified slice and the obtained unsigned integer.

preload_int

int preload_int(slice s, int len)
Reads a signed len-bit integer from slice s. Returns the obtained integer. This method does not modify slice s.

preload_uint

int preload_uint(slice s, int len)
Reads an unsigned len-bit integer from slice s. Returns the obtained unsigned integer. This method does not modify slice s.

store_int

builder store_int(builder b, int x, int len)
Stores a signed len-bit integer x in builder b. Returns the modified builder.

store_uint

builder store_uint(builder b, int x, int len)
Stores an unsigned len-bit integer x in builder b. Returns the modified builder.

~store_int

(builder, ()) ~store_int(builder b, int x, int len)
Same as store_int, but adapted to use modifying notation.

~store_uint

(builder, ()) ~store_uint(builder b, int x, int len)
Same as store_uint, but adapted to use modifying notation.

load_bits

(slice, slice) load_bits(slice s, int len)
Loads the first len bits from slice s. It returns the modified slice and a slice containing the loaded bits.

preload_bits

slice preload_bits(slice s, int len)
Loads the first len bits from slice s. It returns a slice containing the loaded bits. This method does not modify slice s.

int_at

int int_at(tuple t, int index)
Returns the element at index index in tuple t, casted as an integer.
It is responsibility of the programmer to check that the returned element is actually an integer.

cell_at

cell cell_at(tuple t, int index)
Returns the element at index index in tuple t, casted as a cell.
It is responsibility of the programmer to check that the returned element is actually a cell.

slice_at

slice slice_at(tuple t, int index)
Returns the element at index index in tuple t, casted as a slice.
It is responsibility of the programmer to check that the returned element is actually a slice.

tuple_at

tuple tuple_at(tuple t, int index)
Returns the element at index index in tuple t, casted as a tuple.
It is responsibility of the programmer to check that the returned element is actually a tuple.

at

forall X -> X at(tuple t, int index)
Returns the element at index index in tuple t. The returned element can be of any type.

touch

forall X -> X touch(X v)
Moves v to the top of the stack. It returns the argument v.

~touch

forall X -> (X, ()) ~touch(X v)
~touch is identical to touch, but adapted to use modifying notation.

touch2

forall X, Y -> (X, Y) touch2((X, Y) t)
Moves the components of the tensor t to the top of the stack; first component with type X and then component with type Y. It returns the argument tensor t.

~touch2

forall X, Y -> ((X, Y), ()) ~touch2((X, Y) t)
~touch2 is identical to touch2, but adapted to use modifying notation.

~dump

forall X -> (X, ()) ~dump(X value)
Outputs value value to the debug log. It returns the argument value and the unit value (). Modifying notation can be used on this function. In case value is a slice containing ASCII characters, it is preferable to use ~strdump if the intention is to print the ASCII string in the debug log. Otherwise, ~dump will print the slice’s contents as bits.

~strdump

forall X -> (X, ()) ~strdump(X s)
Outputs to the debug log the ASCII string encoded in slice s. It returns the argument s and the unit value (). Modifying notation can be used on this function. If the argument s is not a slice containing ASCII characters, the debug log will show an error.