Colobot Wiki
Advertisement

Expressions are used for various calculations with many different variables, which return the desired result. What distinguishes them from standard instructions are operators, which are described below.

Specifically speaking, an expression is an ordered series of operations which yield a result. Operations consist of operators, which are special functions T f(t1 x1, t2 x2, ..., tn xn), where xi is a value of type ti, and T is the result type. For example, float +(float a, float b) returns a sum of values a and b. Note: Operators are a part of the CBOT language and they cannot be defined in program. Also, the operators cannot be used as usual functions, they need to be written using a special notation depending on the operator, for example a+b.

In nearly all operations, constants, variables, functions returning non-void type and also other operations can be used as values.

Binary operations[]

Assuming that a, b can be values of declared and initialized variables of types t1 and t2, the binary operations can be described as follows:

r = a op b

Where r is the result of the operation and op is a binary operator which works with values of types t1 and t2.

Order of operations[]

Let a op1 b op2 c be a legal expression, then the following rules apply:

  • If op1 == op2 or op1 is as strong as op2 or op1 is stronger than op2, first calculate a op1 b and store its result in a temporary variable r, then calculate r op2 c, which is the final result of the expression.
  • If op1 is weaker than op2, first calculate b op2 c and store its result in a temporary variable r, then calculate a op1 r, which is the final result of the expression.

Note: an operation can be made stronger by surrounding it in brackets, so for example assuming that op1 is weaker than op2, in an expression (a op1 b) op2 c the a op1 b operation will be executed first.

Tip: always use brackets if you are not sure about the order of operations, do not try to remember how strong are each of the operators. Generally it should be fairly obvious.

Here is a complicated example, which uses arithmetic operations described below, showing how expressions are calculated:

Assume a, b, c, d, x, y, z, e are all initialized variables of type float or int. Then the following expression should be calculated the following way:

a * b + c - d / x % (y * z) - e =
= r1 + c - d / x % (y * z) - e    = , r1 = a * b
= r2 - d / x % (y * z) - e        = , r2 = r1 + c
= r2 - r3 % (y * z) - e           = , r3 = d / x
= r2 - r3 % r4 - e                = , r4 = y * z
= r2 - r5 - e                     = , r5 = r3 % r4
= r6 - e                          = , r6 = r2 - r5
= r7                                , r7 = r6 - e

r7 is the final result of this expression.

Assignment operator[]

= is the assignment operator. It is used to store the result of an expression in a variable.

On the left side of this operator there must be so called l-value and on the right side - r-value. L-values are just variables, r-values are expressions or just usual values. This makes the assignment operator kind of special, because what is l-value is pretty restrictive (it cannot be an expression, constant and so on, only single variable). Also, the type of l-value must match the type of r-value (unless a conversion is possible, for example assigning a float to int).

Note: it may be not obvious at first, but notice that = is an *operator* not an instruction. This mean that it can be used in the middle of an other expression! The result of = is the value which was assigned to the l-value - the result of the expression on the right. Example:

float a;
float b = 2.0 * (a = 4.0); // b == 8.0

This example is actually really confusing, but this property is actually useful, because it lets doing something like this:

float a, b, c, d, e;
a = b = c = d = e = 1.0; // a == b == c == d == e == 1.0

Basic arithmetic operations[]

Binary operators below are working with fundamental number types (int, float).

List:[]

+  addition

-  subtraction

*  multiplication

/  division

%  remainder of the division (only for the type int)

Notes[]

o The *, /, % are all stronger than + and -.

o The result type is always float. If a or b are of type int, they are automatically converted to float. Note: this means that results of intermediate calculations tends to be as precise as possible, the precision is lost only during converting the final (float) result to int, for example by the assignment = operator.

Real life examples[]


int    i = 12 + 3;      // i == 15
int    i = 2 - 5;       // i == -3
float  f = 3.01 * 10;   // f == 30.1
int    i = 5 / 3;       // i == 1 (automatic conversion to int)
float  f = 5 / 3;       // f == 1.67
float  f = 5 / 0;       // returns an error (division by zero)
int    i = 13 % 5;      // i == 3
int    i = -8 % 3;      // i == -2
float  f = sin(90) * i; // f == -2.0

Compound assignment operators[]

Besides the = operator for variable assignment there are several compound-assignment operators.

The compound-assignment operators combine the = assignment operator with another binary operator such as + or -. Compound-assignment operators perform the operation specified by the additional operator and then assign the result to the left operand. For example, a compound-assignment expression such as

lvalue += expression

is equivalent to:

lvalue = lvalue + expression

====
List: ==== +=  addition

-=  subtraction

*=  multiplication

/=  division

%=  remainder of the division (only for the type int)


String concatenation[]

If at least one of the values used with the + operator is a string, then the operation of concatenation is performed. The result of the operator is then a string, which is created by joining end-to-end the string and the other value. If the other value is not a string, then it is converted to string beforehand.

Examples:[]

string s = "a" + "bc";  // returns "abc"
string s = 1 + "bc";    // returns "1bc"
string s = 2.5 + "bc";  // returns "2.5bc"
string s = "a" + true;  // returns "atrue"

Tip: the properties of the concatenation + operator is useful with the message(); function, because it does not work with other types than string. An empty string can be used together with a value in order to create a string, which actually can be passed to the message(); function:

float pi = 3.14;
// message(pi); // does not work
message(""+pi);


Comparison operators[]

Comparison operators work with values of type float and they always return a bool. They are mainly used in conditions.

List:[]

a == b  a equals b

a != b  a is different from b

a <  b  a smaller than b

a <= b  a smaller than or equal to b

a >  b  a greater than b

a >= b  a greater than or equal to b

Examples:[]

12 == 12  returns true

45 != 47  returns true 

99 == 98  returns false

12 <  -1  returns false

12 >= 10  returns true 

12 >= 12  returns true 

Remark:[]

Be careful not to confuse the equality comparison == with the assignment of a variable =.

a == b is an expression that compares a with b.

a = b is an expression that copies the value of b into a.

Logical operators[]

Logical operators work with values of type bool and they always return a bool. They are mainly used in conditions.

List:[]

!a      not a
a && b  a and b
a || b  a or b

Examples:[]

!false        returns true
true && false returns false
true || false returns true

Ternary operator[]

The ternary operator is nothing more than a syntax sugar. It is also known as "inline if". It might be confusing at first, because its syntax is a little more complicated than other operators. It can be described as follows:

(condition) ? (result when true) : (result when false)

Brackets are not needed.

Firstly, the condition is valued and then the first result is returned if the condition is true, otherwise the second result is returned.

Example:[]

float c = ((3.0 > 2.0) ? 10.0 : -10.0); // c == 10.0

Bitwise operators[]

Bitwise operators are similar to the logical operator, because they are operating on bits (which can be only 0 or 1, conditions can have a value only of false or true). So in theory, they should be working with basically any type of variable, because each value in the computer must be stored as a sequence of bits.

List:[]

a & b  a AND b

a | b  a OR b

a ^ b  a XOR b

a >> b  shift bits of a to the right b times

a << b  shift bits of a to the left b times

Examples:[]

2 & 1         returns 0

2 | 1         returns 3

2 ^ 2         returns 0

2 >> 1        returns 1

2 << 1        returns 4

Prefix / postfix increment and decrement operators[]

The operators ++ and -- allow you to increment (++) or to decrement (--) a variable in very compact and efficient manner.

For example to increment the variable a you can write:

a++;

instead of:

a = a + 1;

The result of the operation a++ is the value of the variable a *before* the increment. If you use the prefix operator ++a the result of the operation is the value of the variable a *after* the increment. The same holds for the -- decrement operator.

Examples:[]

a = 2;
b = a++;
// now b contains 2 and a contains 3
a = 2;
b = ++a;
// now b contains 3 and a contains 3.
Advertisement