Expressions can be used anywhere a numeric parameter is expected. The syntax for expressions is very close to standard C-style syntax with full operator ordering and parentheses. There are a few operators missing (notably the trinary ? : operator), and a few new ones (memory accessors). The table below lists all the operators in their order, highest precedence operators first.
| Operator | Description |
|---|---|
| ( ) | standard parentheses |
| ++ – | postfix increment/decrement |
| ++ – ~ ! - + b@ w@ d@ q@ | prefix inc/dec, binary NOT, logical NOT, unary +/-, memory access |
| * / % | multiply, divide, modulus |
| + - | add, subtract |
| << >> | shift left/right |
| < <= > >= | less than, less than or equal, greater than, greater than or equal |
| == != | equal, not equal |
| & | binary AND |
| ^ | binary XOR |
| | | binary OR |
| && | logical AND |
| || | logical OR |
| = *= /= %= += -= «= »= &= |= ^= | assignment |
| , | separate terms, function parameters |
These are the differences from C behaviors. First, All math is performed on full 64-bit unsigned values, so things like a < 0 won't work as expected. Second, the logical operators && and || do not have short-circuit properties – both halves are always evaluated. Finally, the new memory operators work like this: b@<addr> refers to the byte read from <addr>. Similarly, w@ refers to a word in memory, d@ refers to a dword in memory, and q@ refers to a qword in memory. The memory operators can be used as both lvalues and rvalues, so you can write b@100 = ff to store a byte in memory. By default these operators read from the program memory space, but you can override that by prefixing them with a d or an i. So dw@300 refers to data memory word at address 300 and id@400 refers to an I/O memory dword at address 400.