# Binary Expressions

Binary expressions are made of exactly two expressions. They are used for common arithmetic operations.

## AssignExpression§

### Grammar§

``` AssignOperator ::= "=" | "/=" | "*=" | "%=" | "-=" | "+=" | "&=" | "^=" | "|=" | "<<=" | ">>=" | "~="; AssignExpression ::= ConditionalExpression | RangeExpression | InExpression (AssignOperator AssignExpression)? ; ```

## ConditionalExpression§

### Grammar§

``` ConditionalExpression ::= InExpression "?" AssignExpression ConditionalElsePart? ConditionalElsePart ::= "else" AssignExpression ```

### Semantics§

#### General§

The expression located before the question mark, the condition, must be or convertible to a CmpExpression. If the condition is verified then the expression gives, as a rvalue, the `else` LHS (the trueExpression) and otherwise its RHS (the falseExpression).

The type is determined as following:

• it is the type of the falseExpression if the trueExpression implictly converts to.
• it is the type of the trueExpression if the falseExpression implictly converts to.
• if both expressions are pointer to classes then it is the most derived common type.

#### Void special case§

If one of the expression has for type void then the conditional expression also takes the void type and it does not yield any value.

``````function f(){}
var s32 a = 0;
a ? f() else a = 1;``````

Such conditional expressions can only be used as the expression of a ExpressionStatement or as the expression of a ReturnStatement if located in a function without return.

#### Shorthand syntax§

When the optional ConditionalElsePart is not specified then the compiler rewrites the expression. The trueExpression becomes the falseExpression and the comparison LHS becomes the trueExpression.

``````const s32 a = 1 ? 2;
// is lowered to const s32 a = 1 != 0 ? 1 else 2;
assert(a == 1);``````

The trueExpression, contrary to what would happen with the standard syntax, is evaluated only once.

``````static function get(): s32
{
static var s32 result;
return result += 1;
}
// standard
var s32 a = get() ? get() else 3;
assert(a == 2);
// shorthand form
var s32 a = get() ? 3;
assert(a == 1);``````

## RangeExpression§

### Grammar§

``` RangeExpression ::= InExpression ".." AssignExpression ```

### Semantics§

The expression takes a dedicated and unconvertible TypeRange type so that it can only be used as ForeachStatement iterable and as expression in the OnMatchStatement.

The left hand side must be implicitly convertible to the right hand side type, or the opposite.

Nested ranges are always rejected.

Other semantics are detailed in the ForeachStatement and the SwitchStatement specifications.

## InExpression§

### Grammar§

``` InExpression ::= OrOrExpression ("!"? "in" InExpression)? ```

### Semantics§

The operator is uniquely available for operator overloading using `@operator(a in b)` and for the inclusion test of TypeEnumSet.

## OrOrExpression§

### Grammar§

``` OrOrExpression ::= AndAndExpression ("||" OrOrExpression)? ```

## AndAndExpression§

### Grammar§

``` AndAndExpression ::= OrExpression ("&&" AndAndExpression)? ```

## OrExpression§

### Grammar§

``` OrExpression ::= XorExpression ("|" OrExpression)? ```

## XorExpression§

### Grammar§

``` XorExpression ::= AndExpression ("^" XorExpression)? ```

## AndExpression§

### Grammar§

``` AndExpression ::= CmpExpression ("&" AndExpression)? ```

## CmpExpression§

### Grammar§

``` CmpOperator ::= "==" | ">" | ">=" | "<" | "<=" ; CmpExpression ::= RShiftExpression (CmpOperator RShiftExpression)? ```

### Semantics§

Compare the two operands and returns a `bool` rvalue. The operands must be both of a numeric type or both of a pointer type.

If two integer values of same size are compared and if only one is signed, the signed value gets promoted.

Comparisons of `union` types are only supported using operator overloads.

Comparisons of `struct`, `class`, dynamic array and static array types are only supported for `==` and `!=` on lvalues. The comparison consists of a simple `memcmp` so the operator overloads defined by the aggregate elements are ignored.

The other comparison operators are supported by `class` and `struct` when overloaded.

## RShiftExpression§

### Grammar§

``` RShiftExpression ::= LShiftExpression (">>" RShiftExpression)? ```

## LShiftExpression§

### Grammar§

``` LShiftExpression ::= TidExpression ("<<" LShiftExpression)? ```

## TidExpression§

### Grammar§

``` TidExpression ::= MinExpression ("~" TidExpression)? ```

### Semantics§

The TidExpression concatenates its two sides in a new, managed, dynamic array. The type of the dynamic array is determined this way:

• if one of the side is an array then the element type is selected as a first reference.
• if one of the side is a value then its type is taken as a second reference.
• the two types must be equal.

this allows to concatenate two arrays

``````var u64 a = [1,2];
var u64 b = [3,4];
var u64[]  c   =  a ~ b;``````

but also to create arrays from values

``var u64[] a  =  1 ~ 2 ~ 3 ~ 4;``

and obviously the two ways can be mixed

``````var u64[] b = get();
var auto a  =  [1, 2] ~ 3 ~ 4 ~ get();``````

## MinExpression§

### Grammar§

``` MinExpression ::= AddExpression ("-" MinExpression)? ```

### Grammar§

``` AddExpression ::= ModExpression ("+" AddExpression)? ```

## ModExpression§

### Grammar§

``` ModExpression ::= DivExpression ("%" ModExpression)? ```

## DivExpression§

### Grammar§

``` DivExpression ::= MulExpression ("/" DivExpression)? ```

## MulExpression§

### Grammar§

``` MulExpression ::= UnaryExpression ("*" MulExpression)? ```