Arithmetic operations - Palamecia/mint GitHub Wiki
Operators are used to compute values from literals or variables and create expressions. Operators take one to three values and compute them with a grouping order and a priority level. Some operators can also be overridden in a user defined type.
Note
Some parts of an expression can be written between the (
and )
operators to take the topmost priority level. Those expressions can also contain recursively other expressions between those operators which take a higher level of priority.
Each operator has a priority level and a grouping order. It allows writing a full arithmetic expression and obtaining the expected result without describing the order of application of each operation.
Precedence | Operators | Associativity |
---|---|---|
1 (lowest) |
, , in
|
Left-to-right |
2 |
|| , or
|
Left-to-right |
3 |
&& , and
|
Left-to-right |
4 | | |
Left-to-right |
5 |
^ , xor
|
Left-to-right |
6 | & |
Left-to-right |
7 |
= , ?: , := , []= , += , -= , *= , /= , %= , <<= , >>= , &= , |= , ^=
|
Right-to-left |
8 |
.. , ...
|
Left-to-right |
9 |
== , != , is , =~ , !~ , === , !==
|
Left-to-right |
10 |
< , > , <= , >=
|
Left-to-right |
11 |
<< , >>
|
Left-to-right |
12 |
+ , -
|
Left-to-right |
13 |
* , / , %
|
Left-to-right |
14 |
! , not , ~ , defined , typeof , membersof
|
Right-to-left |
15 |
++ , -- , **
|
Left-to-right |
16 (highest) |
. , () , [] , {}
|
Left-to-right |
The move assignment operators assign a value to a variable. It is used to initialize a variable or to change its value. Those operators do not work with types and can therefore not be overridden.
Operator | Description | Override |
---|---|---|
= |
Move the value of the right part to the variable on the left part | No |
+= |
Move by sum: alias for a = a + b
|
No (uses + ) |
-= |
Move by difference: alias for a = a - b
|
No (uses - ) |
*= |
Move by product: alias for a = a * b
|
No (uses * ) |
/= |
Move by quotient: alias for a = a / b
|
No (uses / ) |
%= |
Move by remainder: alias for a = a % b
|
No (uses % ) |
<<= |
Move by bitwise left shift: alias for a = a << b
|
No (uses << ) |
>>= |
Move by bitwise right shift: alias for a = a >> b
|
No (uses >> ) |
&= |
Move by bitwise AND: alias for a = a & b
|
No (uses & ) |
|= |
Move by bitwise OR: alias for a = a | b
|
No (uses | ) |
^= |
Move by bitwise XOR: alias for a = a ^ b
|
No (uses ^ ) |
Those operators are not applicable to variables with a constant reference.
The copy assignment operator casts a value to the type of the value referenced by a variable and replaces the current value of the variable. Once replaced, any variables referencing this value will give the new value.
This operator can be overridden by user defined types to define how to cast the expression and change its value. If the type does not override this operator, it will only be applicable to values of the same type (because no cast method is defined) and will clone the value of each member of the object.
Operator | Description | Override |
---|---|---|
:= |
Copy the value of the right part to the value of the variable on the left part | Yes |
This operator is not applicable to the type package and to variables with a constant value.
The function call operator is mainly used to call functions. An expression list can be passed between the (
and )
operators. The number of expressions in the list will change the behavior of the operator and can eventually generate an error if the number is not handled. Many types can handle this operator and it can also be overridden by user defined types.
Operator | Description | Override |
---|---|---|
() |
Call the value with optional parameters | Yes |
This operator is applicable to the following types:
- number, boolean: Create a constant copy of the value (takes no parameters)
- function: Call the function with the parameters
- object: Call the operator overload or create a constant copy of the object if not overloaded
-
class: Create a new instance and call the
new
member with the parameters
Note
If the function call operator is used alongside the .
operator, the value on the left of this operator is added as the first parameter of the list unless the called value is global. The type and package of this value are also associated with the new context created by the operator.
The ...
or *
operator can be used as a unary operator in a parameter list passed to a function call operator to expand each element contained in the value as an individual parameter. This also applies to containers literals.
Example:
var list = [0, 1, 2]
sum(*list) // is equivalent to sum(0, 1, 2)
The unpack operator can also be used to expand each element to initialize an array or an iterator.
Example:
// with myIterator = (3, 4, 5)
var list = [0, 1, 2, *myIterator, 6, 7, 8] // gives [0, 1, 2, 3, 4, 5, 6, 7, 8]
Arithmetic operators are used to perform mathematical operations like addition, subtraction, multiplication, etc.
Operator | Description | Override |
---|---|---|
+ |
Add two operands or unary plus | Yes |
- |
Subtract right operand from the left or unary minus | Yes |
* |
Multiply two operands | Yes |
/ |
Divide left operand by the right one | Yes |
% |
Modulus - remainder of the division of left operand by the right | Yes |
** |
Exponent - left operand raised to the power of right | Yes |
Example:
15 + 4 // gives 19
15 - 4 // gives 11
15 * 4 // gives 60
15 / 4 // gives 3.75
15 % 4 // gives 3
15 ** 4 // gives 50625
Comparison operators are used to compare values. They return either true
or false
according to the condition. They are typically used by the control structures.
Operator | Description | Override |
---|---|---|
> |
Greater than - true if the left operand is greater than the right |
Yes |
< |
Less than - true if the left operand is less than the right |
Yes |
== |
Equal to - true if both operands are equal |
Yes |
!= |
Not equal to - true if the operands are not equal |
Yes |
>= |
Greater than or equal to - true if the left operand is greater than or equal to the right |
Yes |
<= |
Less than or equal to - true if the left operand is less than or equal to the right |
Yes |
is |
Address comparison - true if both operands are the same value |
No |
=== |
Strictly equal to - true if both operands are equal and the same type |
No (uses == ) |
!== |
Strictly equal to - true if both operands are not equal or not the same type |
No (uses != ) |
Example:
10 > 12 // gives false
10 < 12 // gives true
10 == 12 // gives false
10 != 12 // gives true
10 >= 12 // gives false
10 <= 12 // gives true
Logical operators are used to compare boolean values. They can also be overridden to apply the same behavior to user defined types.
Operator | Description | Override |
---|---|---|
&& , and
|
true if both operands are true
|
Yes |
|| , or
|
true if either of the operands is true
|
Yes |
! , not
|
true if the operand is false
|
Yes |
Example:
true and false // gives false
true or false // gives true
not true // gives false
Bitwise operators act on operands as if they were strings of binary digits. They operate bit by bit. They can also be overridden to apply the same behavior to user defined types.
Operator | Description | Override |
---|---|---|
& |
Bitwise AND | Yes |
| |
Bitwise OR | Yes |
~ |
Bitwise NOT | Yes |
^ , xor
|
Bitwise XOR | Yes |
>> |
Bitwise right shift | Yes |
<< |
Bitwise left shift | Yes |
Range operators create an iterator on a range of values. They can also be overridden to apply the same behavior to user defined types.
Operator | Description | Override |
---|---|---|
.. |
Create a range of values from the left operand to the right operand (included) | Yes |
... |
Create a range of values from the left operand to the right operand (excluded) | Yes |
Example:
0..5 // gives (0, 1, 2, 3, 4, 5)
0...5 // gives (0, 1, 2, 3, 4)
Subscript operators are used to access a sub-element of a value. Sub-elements can be accessed for reading or for writing. A different behavior can be defined in both cases. They can also be overridden to apply the same behavior to user defined types.
Operator | Description | Override |
---|---|---|
[] |
Access sub-element for reading | Yes |
[]= |
Access sub-element for writing | Yes |
Note
The []=
operator will be used instead of the []
operator in an expression like value[key] = item
.
Example:
a = ['a', 'b', 'c']
a[1] // gives 'b'
a[1] = 'z' // a gives now ['a', 'z', 'c']
Those operators are applicable to the following types:
- number: Access the digit at the given index
- function: Access the sub-function with the given number of parameters
- object: Access the sub-element associated with the given key/index
Search operators are used to search a sub-element of a value. This operator is meant to be used with conditional structures and its behavior can change depending on the kind of structure. To use this operator outside of a conditional structures, it must be used as a function. The in
operator can also be overridden to search over a user defined types.
Operator | Description | Override |
---|---|---|
in |
Search element in value | Yes |
!in , not in
|
Search element not in value | No |
If the in
operator is used in a for
structure, it will return an iterator on each sub-element of the value. Each sub-element will be moved to the left part of the expression one after the other on each loop turn. The !in
or not in
operator cannot be used in a for
structure.
If the in
operator is used in an if
or a while
structure, it will return a boolean indicating whether the sub-element was found or not in the value. The !in
or not in
operator will invert the result of the in
operator.
Example:
if 10 in 0..5 {
// will never be executed
}
for i in 0..5 {
// i gives 0 on the first turn, then 1, 2, 3, 4 and 5
}
(0..5).in(10) // gives false
(0..5).in() // gives (0, 1, 2, 3, 4, 5)
Match operators are commonly used to test a regex over an expression. They can also be overridden to apply the same behavior to user defined types.
Operator | Description | Override |
---|---|---|
=~ |
At least one match - true if at least one match was found in the right operand |
Yes |
!~ |
Does not match - false if at least one match was found in the right operand |
Yes |
Example:
/es/ =~ 'test' // gives true
/es/ !~ 'test' // gives false
Note
These operators are also applicable to the type string. In this case, the right operand is cast to a regex and the same operator is used with self
as the right operand.
The conditional operator evaluates an expression, returning one value if that expression gives true
and a different one if the expression gives false
.
Operator | Description | Override |
---|---|---|
?: |
Evaluate an expression and gives one result if true or the other if false
|
No |
Example:
defined a ? a : 0 // gives the value of a if a is defined; otherwise gives 0
Meta operators are used to get meta information on values.
Operator | Description | Override |
---|---|---|
defined |
Defined variable - true if the variable is fully defined |
No |
typeof |
Provide the type of the value | No |
membersof |
Provide the list of members of the value | No |
The defined
operator compares the value to none
to check if the variable is defined. It can also check a full path to a member variable with only one expression.
Example:
defined foo.bar.member // equivalent to :
// not (foo is none) and not (foo.bar is none) and not (foo.bar.member is none)
The typeof
operator provides the type of the value as a string.
Example:
typeof 0 // gives 'number'
typeof '' // gives 'string'
typeof System.File // gives 'System.File'
The membersof
operator provides the list of members of the value as an array of strings.
Example:
membersof () // gives [':=', 'each', 'isEmpty', 'next', 'value']