docs/operators.md

Summary

Maintainability
Test Coverage
# Operators

uGO uses same binary and unary operators with Go. uGO relies on Go's wrap-around
behavior if compiler does not catch any overflow. Floating point numbers may be
rounded due to conversions. It is a good practice to use [builtin conversion
functions](builtins.md) to resolve ambiguities. If optimizer is enabled in
compiler options, using conversion functions with constant values has no
overhead at runtime.

## Binary Operators

### Relational Operators

Relational operators yields bool values.

| Symbol | Operation             |
|:------:|-----------------------|
|   ==   | equal                 |
|   !=   | not equal             |
|    <   | less than             |
|    >   | greater than          |
|   <=   | less than or equal    |
|   >=   | greater than or equal |

All relational operators apply to int, uint, float, char, bool, string, bytes.
uGO's [Object](tutorial.md#interfaces) interface methods `Equal and BinaryOp`
evaluates these operations. A runtime error is thrown if types are not
comparable. Note that, bool values are converted to untyped 1 or 0 for true or
false to compare with numeric values.

Following is the conversion table to apply relational operators to different
numeric types. `p` is the left hand side (LHS) in the first column and `q` is
the right hand side (RHS) in the first row.

| Type      | int        | uint       | float          | char          |
|:----------|------------|------------|----------------|---------------|
| **int**   | -          | uint64(p)  | float64(p)     | rune(p)       |
| **uint**  | uint64(q)  | -          | float64(p)     | rune(p)       |
| **float** | float64(q) | float64(q) | -              | **TypeError** |
| **char**  | rune(q)    | rune(q)    | **TypeError**  | -             |

- For `map` values, `==` and `!=` operators are applicable if LHS and RHS
  operands are of `map` type

- For `array` values, `==` and `!=` operators are applicable if LHS and RHS
  operands are of `array` type

- For `string` and `bytes` values, all relational operators are applicable if
  LHS and RHS are of same type

### Binary Arithmetic Operators

| Symbol | Operation          | Supported Types                              |
|:------:|--------------------|----------------------------------------------|
|    +   | sum                | int, uint, float, char, string, bytes, array |
|    -   | difference         | int, uint, float, char                       |
|    *   | product            | int, uint, float                             |
|    /   | quotient           | int, uint, float                             |
|   %    | remainder          | int, uint                                    |
|   &    | bitwise AND        | int, uint                                    |
|   \|   | bitwise OR         | int, uint                                    |
|   ^    | bitwise XOR        | int, uint                                    |
|   &^   | bit clear (AND NOT)| int, uint                                    |
|   <<   | shift left         | int, uint                                    |
|   >>   | shift right        | int, uint                                    |

**Rules**

LHS: left hand side, RHS: right hand side

- `string` values only support `+` operator for string concatenation as LHS
  operand regardless of other operand's type. Result is always of `string` type
- `bytes` values only support `+` operator for byte concatenation if it is LHS
  operand and RHS is of `bytes` or `string` type
- `array` values only support `+` operator to append object if it is LHS operand
- `bool` values are treated as untyped 1 or 0 before arithmetic operation
- `char` values only support `+`, `-` operators with `char`, `int`, `uint`
  values
- `char` values support `*`, `/`, `%`, `|`, `^`, `&^`, `<<`, `>>` operators
  if both operands are of `char` type
- if LHS or RHS is of `char` type, other operand is converted to `char` value
- if LHS or RHS is of `float` type, other operand is converted to `float` value
- if LHS or RHS is unsigned integer, signed integer is converted to unsigned
  integer
- A runtime error `TypeError` is thrown if operand is not of expected type

## Unary Operators

| Symbol | Operation                  | Supported Types                |
|:------:|----------------------------|--------------------------------|
|    +   | positive `0 + x`           | int, uint, float, char, bool*  |
|    -   | negation `0 - x`           | int, uint, float, char, bool*  |
|    ^   | bitwise complement** `m^x` | int, uint, char, bool*         |
|    !   | logical negation NOT `!x`  | all types                      |
|   ++   | increment `x = x + 1`      | all types except map and error |
|   --   | decrement `x = x - 1`      | all types except map and error |

\* bool values are converted to int 1 or 0 to apply operation

\*\* with m = "all bits set to 1" for unsigned x and  m = -1 for signed x

## Logical Operators

Logical operators apply to all types and yield a result of the same type as the
operands. The right operand is evaluated conditionally.

| Symbol | Operation                                           |
|:------:|-----------------------------------------------------|
|   &&   | Logical AND  `p && q  is  "if p then q else false"` |
|   \|\| | Logical OR  `p \|\| q  is  "if p then true else q"` |

_See [builtins](builtins.md) for conversion and type checking functions_