Overview - Expressions
Expressions are the basis of Kipper, as every operation in a program is made up of single expressions that perform certain actions, like reading a value, calculating something, calling a function, comparing values…
A simple example for expressions can be a simple calculation, like this:
val1 + val2 * val3; // Mathematical/Arithmetic expression
Notice how in this case we are not assigning the result to anything? This is an important fact of expressions that they are usually independent and do a single task, meaning if we wanted to assign this result to a variable, we would have to use an assignment expression like this:
// Assign and arithmetic expression
var result: num = val1 + val2 * val3;
In this case, we also now created an expression statement (ends in ;
), which wraps an
expression and allows it to be used inside a program. Expression statements will be explained
further in the docs page Statements.
Kipper Operators and Expressions Precedence
The following table shows all valid operators and expressions in the Kipper language, with their respective precedence. The higher the precedence the higher the importance of the item, and the order of evaluation.
Precedence | Operator / Expression | Description | Associativity |
---|---|---|---|
19 | ( ... ) |
Tangled expression - Forced increased precedence | n/a |
18 |
... ( ... ) call ... ( ... ) ... [ ... ] ... [ ... : ... ] ... . ...
|
Prefix increment and decrement (Suffix) Function call Function call (Legacy) Computed member access Slice subscripting Dot-notation member access |
Left-To-Right |
17 |
... ++ ... -- |
Postfix increment Postfix decrement |
n/a |
16 |
+ ... - ... ! ... ~ ... ++ ... -- ... |
Unary plus Unary minus Logical NOT Bitwise NOT Prefix increment Prefix decrement |
|
15 |
... as ...
|
Type conversion | |
14 |
... ** ...
|
Exponentiation |
right-to-left |
13 |
... * ... ... / ... ... % ... |
Multiplication Division Modulus Exponentiation |
left-to-right |
12 |
... + ... ... - ...
|
Addition Subtraction |
left-to-right |
11 |
... << ... ... >> ... ... >>> ...
|
Bitwise shift left Bitwise shift right Bitwise shift right zero fill |
left-to-right |
10 |
... < ... ... <= ... ... > ... ... => ... |
More than More or Equal to Less than Less or Equal to |
left-to-right |
9 |
... == ... ... != ... |
Equal to Not Equal to |
left-to-right |
8 | ... & ... |
Bitwise AND |
left-to-right |
7 | ... ^ ... |
Bitwise XOR |
left-to-right |
6 | ... | ... |
Bitwise OR |
left-to-right |
5 | ... && ... |
Logical AND |
left-to-right |
4 | ... || ... |
Logical OR |
left-to-right |
3 | ... ? ... : ... |
Ternary expression |
Right-To-Left |
2 |
... = ... ... += ... ... -= ... ... *= ... ... /= ... ... %= ...
|
Assignment Incremental assignment Decremental assignment Multiplicative assignment Divisional assignment Modulo assignment |
|
1 | ... , ... |
Comma | Left-To-Right |
How does precedence of operators and expressions affect a program?
The order of precedence is a very vital concept in programming languages, as they define how expressions are going to be evaluated. This directly can affect how your code runs, as certain parts might be evaluated first before others and change the entire course of your program.
A simple example of this are arithmetic expressions + - * / %
, which have per
mathematical conventions their own order of precedence. For example, multiplication and division
signs always come first before plus and minus, unless you explicitly use brackets,
like these ( )
. The same can be done here in Kipper as well, where you can forcefully
increase the order of precedence using brackets:
15 + 4 * 6; // -> (15 + (4 * 6)) -> (15 + 24) -> 39
Forced higher precedence using brackets:
(15 + 4) * 6; // -> ((15 + 4) * 6) -> (19 * 6) -> 114
What does associativity mean?
As you should have already seen in the table above, there is an extra column defining the so-called
associativity. What does that mean? It's relatively simple and means whether the following (( )
meaning the expression is read first):
a OPR b OPR c
is evaluated as (left-associative - Reads from left to right):
(a OPR b) OPR c
or as (right-associative - reads from right to left):
a OPR (b OPR c)
This is especially important as it can change how certain things are evaluated, and also cause unwanted errors! For example the following would be interpreted as (left-associative):
32 / 4 / 4; // -> ((32 / 4) / 4) -> (8 / 4) -> 2