Table of operators
Currently, all the unary and binary operators are integer operators. Logical operators are bitwise integer operators (cf. absence of boolean type).
Brief description | Operators |
---|---|
Parentheses | ( ) |
Unary bitwise NOT | ~ |
Multiplicative | * / ^/ ~/ % ^% ~% /% & |
Unary integer negation | - |
Additive | + - (integer subtraction) | ^ |
Shifts | >> << ^>> ~>> |
Comparison and Equality | > >= < <= <=> == != |
Ternary | ?: |
Assignment | = and all augmented assignment operators |
- Assignment operators (i.e., bottom row in the table), which are right-associative.
- Division-modulo operator
/%
, which is neither left associative nor right associative.
?:
is right-associative.
For example:
1 - 2 + 3
parses as(1 - 2) + 3
, producing2
as result.a = b += c = 10
parses as(a = (b += (c = 10)))
, producing the final valuesc = 10
,b = 11
, anda = 11
, under the assumption thatb
had value1
initially.0 ? a : 1 ? b : c
parses as0 ? a : (1 ? b : c)
, producingb
as a result.3 /% 5 /% 7
does not compile, neither(3 /% 5) /% 7
nor3 /% (5 /% 7)
.
In expressions, all operators should be separated from their arguments, otherwise the expression is interpreted as an identifier.For example:
- x
- Negates x.-x
- Interpreted as a single identifier, not an operation.x + y
- Addsx
andy
.x+y
- Interpreted as a single identifier, not an operation.
Precedence
Precedence is used to determine which operator should be considered in a particular situation. Whenever ambiguity arises, FunC prefers operators with higher precedence over those with lower precedence. For example, consider this expression:*
has higher precedence than the subtraction operator -
,
FunC will prefer to evaluate the multiplication first:
Neglecting precedence rules can often lead to confusing situations with operators.
The correct order of operations can be ensured by wrapping every operation in parentheses,
since parentheses have the highest precedence of all expressions and operators.
Parentheses
Parentheses (also called round brackets,()
) are more punctuation symbols than actual operators,
but their precedence is higher than the precedence of any other operator.
Use parentheses to override the order of operations:
Unary operators
Unary here means that they are applied only to one operand of the given expression. All unary operators are prefix operators, i.e., placed before the operand.Bitwise NOT, ~
The tilde (bitwise NOT) operator ~
inverts or flips each bit in the binary
representation of the expression, changing each 1
to 0
, and vice versa.
~
operator also behaves as expected on -1
and 0
, which are the emulated values for true
and false
:
~
can work as logical NOT when computing boolean conditions:
Negation, -
The minus sign (negation) operator -
reverses the sign of the expression.
Binary operators
Binary here means that they are applied to two operands of the given expression. All binary operators are infix operators, i.e., placed in the middle of the two operands.Multiplication, *
The asterisk (multiplication) operator *
is used for multiplication of two values.
Going beyond the range of the integer type will result in an error with exit code 4: Integer overflow
.
Division, /
The slash (division) operator /
is used for integer division of two values, which truncates toward zero if the result
is positive and away from zero if the result is negative. This is also called rounding down
or rounding toward negative infinity.
An attempt to divide by zero results in an error with exit code 4: Integer overflow
.
Ceiling division, ^/
The caret-slash (ceiling division) operator ^/
is used for integer division of two values, which truncates away from zero if the result
is positive and toward zero if the result is negative. This is also called rounding up
or rounding toward positive infinity.
An attempt to divide by zero results in an error with exit code 4: Integer overflow
.
Rounding division, ~/
The tilde-slash (rounding division) operator ~/
is used for integer division of two values, which truncates to the nearest integer but using the following
tie-breaking rule for half values: if the fractional part is 0.5
, it is truncated away from zero if the result is positive, and truncated toward zero
if the result is negative. This is also called rounding half up
or rounding half toward positive infinity.
An attempt to divide by zero results in an error with exit code 4: Integer overflow
.
Modulo, %
The percent sign (modulo) operator %
is used for obtaining the modulo of integer division, which is the remainder of dividing the operands with the /
operator.
Concretely, a % b
is defined as a - (b * (a / b))
, where /
is the division operator, *
is the multiplication operator,
and -
is the subtraction operator.
If b
in the expression a % b
is 0
, the result is an error with exit code 4: Integer overflow
.
%
always has the same sign as the divisor (i.e., b
is the divisor in the expression a % b
). This means that the modulo is not the same as the
remainder from Euclidean division, because in Euclidean division the remainder is always non-negative,
independently of the sign of the divisor. The modulo %
and the remainder from Euclidean division coincide when both operands are non-negative.
If you want to compute remainders as in Euclidean division by using the %
operator, the best way is to use only unsigned integers.
Alternatively, consider using the abs
function to ensure non-negative values:
Ceiling modulo, ^%
The caret-percent sign (ceiling modulo) operator ^%
is used for obtaining the ceiling modulo of integer ceiling division, which is the remainder of dividing the
operands with the ^/
operator.
Concretely, a ^% b
is defined as a - (b * (a ^/ b))
, where ^/
is the ceiling division operator,
*
is the multiplication operator, and -
is the subtraction operator.
If b
in the expression a ^% b
is 0
, the result is an error with exit code 4: Integer overflow
.
^%
always has the opposite sign of the divisor (i.e., b
is the divisor in the expression a ^% b
).
Rounding modulo, ~%
The tilde-percent sign (rounding modulo) operator ~%
is used for obtaining the rounding modulo of integer rounding division, which is the remainder of dividing the
operands with the ~/
operator.
Concretely, a ~% b
is defined as a - (b * (a ~/ b))
, where ~/
is the rounding division operator,
*
is the multiplication operator,
and -
is the subtraction operator.
If b
in the expression a ~% b
is 0
, the result is an error with exit code 4: Integer overflow
.
Division and modulo, /%
The slash-percent sign (division and modulo) operator /%
returns a two element tensor, where the first element is the result
of applying the division operator /
on the operands,
and the second element is the result of applying the modulo operator on the operands.
If b
in the expression a /% b
is 0
, the result is an error with exit code 4: Integer overflow
.
/%
is the only binary operator that does not associate to the right or to the left:
/%
is that it returns a 2-element tensor. This means that you must decompose the tensor before using the values.
See more about decomposition notation in the variable declaration section.
Bitwise AND, &
The ampersand (bitwise AND) operator &
applies a bitwise AND,
which performs the logical AND operation on each pair of corresponding bits of the operands.
This is useful when we want to clear selected bits of a number, where each bit represents an individual flag or a boolean state.
This makes it possible to “store” up to 257 boolean values per integer, as all integers in FunC are 257-bit signed.
&
operator also behaves as expected on -1
and 0
, which are the emulated values for true
and false
:
&
can work as logical AND when computing boolean conditions:
Addition, +
The plus (addition) operator +
is used for adding numbers together.
Going beyond the range of the integer type will result in an error with exit code 4: Integer overflow
.
Subtraction, -
The minus (subtraction) operator -
is used for subtracting numbers from each other.
Going beyond the range of the integer type will result in an error with exit code 4: Integer overflow
.
Bitwise OR, |
The bar (bitwise OR) operator |
applies a bitwise OR, which performs the
logical OR operation on each pair of corresponding bits of the operands.
This is useful when we want to apply a specific bitmask.
|
operator also behaves as expected on -1
and 0
, which are the emulated values for true
and false
:
|
can work as logical OR when computing boolean conditions:
Bitwise XOR, ^
The caret (bitwise XOR) operator ^
applies a bitwise XOR, performing the
logical exclusive OR operation on each pair of corresponding bits of the operands.
The result in each position is 1
if exactly one of the bits is 1
, or 0
if both bits are 0
or both bits are 1
.
Thus, it compares two bits, yielding 1
if the bits are different and 0
if they are the same.
It is useful for inverting selected bits of an operand (also called toggling or flipping), as any bit can be toggled by “XORing” it with 1
.
^
operator also behaves as expected on -1
and 0
, which are the emulated values for true
and false
:
Shift right, >>
The double greater than (shift right) operator >>
returns an integer whose binary representation is the left operand value
shifted by the right operand number of bits to the right.
Excess bits shifted off to the right are discarded, and copies of the leftmost bit are shifted in from the left.
This operation is also called “sign-propagating right shift” or “arithmetic right shift” because the sign of the resulting number
is the same as the sign of the left operand.
x >> n
is a more efficient way to divide x
by 2^n
, where the division truncation is done by flooring.
In other words, x >> n
is equivalent to floor(x / 2^n)
, where floor
is the floor function,
2^n
is exponentiation of 2
by n
, and /
is standard arithmetical division.
Shift left, <<
The double less-than (shift left) operator <<
returns an integer whose binary representation is the left operand value shifted to the left
by the number of bits specified by the right operand.
Excess bits shifted off from the left are discarded, and zero bits are shifted in from the right.
x << n
is a more efficient way to multiply x
by 2^n
.
In other words, x << n
is equivalent to x * 2^n
, where 2^n
is exponentiation of 2
by n
and *
is standard arithmetical multiplication.
Exceeding the range of the integer type will result in an error with exit code 4: Integer overflow
.
Ceiling shift right, ^>>
The caret-double greater than (ceiling shift right) operator computes an efficient way to divide the left operand by 2^n
, where n
is the right operand and
the division truncation is done by ceiling.
In other words, x ^>> n
is equivalent to ceil(x / 2^n)
, where ceil
is the ceil function,
2^n
is exponentiation of 2
by n
, and /
is standard arithmetical division.
Rounding shift right, ~>>
The tilde-double greater than (rounding shift right) operator computes an efficient way to divide the left operand by 2^n
, where n
is the right operand and
the division truncation is done by rounding half up.
In other words, x ~>> n
is equivalent to floor(x / 2^n + 0.5)
, where floor
is the floor function,
2^n
is exponentiation of 2
by n
, /
is standard arithmetical division, and +
is standard arithmetical addition.
Greater than, >
The greater than operator >
returns -1
if the left operand is greater than the right operand and 0
otherwise.
Greater than or equal, >=
The greater than or equal to operator >=
returns -1
if the left operand is greater than or equal to the right operand and 0
otherwise.
Less than, <
The less than operator <
returns -1
if the left operand is less than the right operand and 0
otherwise.
Less than or equal, <=
The less than or equal to operator <=
returns -1
if the left operand is less than or equal to the right operand and 0
otherwise.
Comparison, <=>
The less than or equal or greater than (comparison) operator <=>
, returns -1
if the left operand is less than the right operand,
0
if the left and right operands are equal, or 1
if the left operand is greater than the right operand.
Equality, ==
The equality operator ==
checks whether its two operands are equal, returning -1
if they are and 0
otherwise.
The ==
can only compare integers.
Inequality, !=
The inequality operator !=
checks whether its two operands are different, returning -1
if they are and 0
otherwise.
The !=
can only compare integers.
Ternary, ?:
The conditional (ternary) operator ?:
is the only operator that takes three operands: a condition followed by a question mark
(?
), then an expression to execute (the “consequent” expression) if the condition evaluates to an integer different from 0
, followed by a colon (:
),
and finally the expression to execute (the “alternative” expression) if the condition evaluates to 0
.
This operator is frequently used as an alternative to an if...else
statement.
Assignment, =
The assignment operator =
is used to assign the result of an expression to a variable. After execution, the =
operator returns the value assigned to the variable.
=
is right associative:
Augmented assignment operators
Augmented (or compound) assignment operators such as+=
combine an operation with an assignment.
Augmented assignments are semantically equivalent to regular assignments =
but include an operation:
*=
, which uses the multiplication operator*
./=
, which uses the division operator/
.^/=
, which uses the ceiling division operator^/
.~/=
, which uses the rounding division operator~/
.%=
, which uses the modulo operator%
.^%=
, which uses the ceiling modulo operator^%
.~%=
, which uses the rounding modulo operator~%
.&=
, which uses the bitwise AND operator&
.+=
, which uses the addition operator+
.-=
, which uses the subtraction operator-
.|=
, which uses the bitwise OR operator|
.^=
, which uses the bitwise XOR operator^
.>>=
, which uses the shift right operator>>
.<<=
, which uses the shift left operator<<
.^>>=
, which uses the ceiling shift right operator^>>
.~>>=
, which uses the rounding shift right operator~>>
.