# Operators Unlike in high-level languages, operators in Millfork have limited applicability. Not every well-formed expression is actually compilable. Most expressions involving single bytes compile, but for larger types usually you need to use in-place modification operators. Further improvements to the compiler may increase the number of acceptable combinations. Certain expressions require the commandline flag `-fzp-register` (`.ini` equivalent: `zeropage_register`) to be enabled. They will be marked with (zpreg) next to them. The flag is enabled by default, but you can disable it if you need it. ## Precedence Millfork has different operator precedence compared to most other languages. From highest to lowest it goes: * `*`, `*'` * `+`, `+'`, `-`, `-'`, `|`, `&`, `^`, `>>`, `>>'`, `<<`, `<<'`, `>>>>`, `<<<<` * `:` * `==`, `!=`, `<`, `>`, `<=`, `>=` * `&&` * `||` * assignment and in-place modification operators You cannot use two different operators at the same precedence levels without using parentheses to disambiguate. It is to prevent confusion about whether `a + b & c << d` means `(a + b) & (c << d)` `((a + b) & c) << d` or something else. The only exceptions are `+` and `-`, and `+'` and `-'`. They are interpreted as expected: `5 - 3 + 2 == 4` and `5 -' 3 +' 2 == 4`. Note that you cannot mix `+'` and `-'` with `+` and `-`. ## Argument types In the descriptions below, arguments to the operators are explained as follows: * `byte` means any one-byte type * `word` means any two-byte type, or a byte expanded to a word * `long` means any type longer than two bytes, or a shorted type expanded to such length to match the other argument * `constant` means a compile-time constant * `simple` means either: a constant, a non-stack variable, a pointer indexed with a constant, a pointer indexed with a non-stack variable, an array indexed with a constant, an array indexed with a non-stack variable, an array indexed with a sum of a constant and a non-stack variable, or a split-word expression made of two simple expressions. Examples: `1`, `a`, `p[2]`, `p[i]`, `arr[2]`, `arr[i]`, `arr[i+2]`, `h:l`, `h[i]:l[i]` Such expressions have the property that the only register they may clobber is Y. * `mutable` means an expression than can be assigned to ## Split-word operator Expressions of the shape `h:l` where `h` and `l` are of type byte, are considered expressions of type word. If and only if both `h` and `l` are assignable expressions, then `h:l` is also an assignable expression. ## Binary arithmetic operators * `+`, `-`: `byte + byte` `constant word + constant word` `constant long + constant long` * `*`: multiplication; the size of the result is the same as the size of the arguments `byte * constant byte` `constant byte * byte` `constant word * constant word` `constant long * constant long` `byte * byte` (zpreg) There are no division, remainder or modulo operators. ## Bitwise operators * `|`, `^`, `&`: OR, EXOR and AND `byte | byte` `constant word | constant word` `constant long | constant long` * `<<`, `>>`: bit shifting; shifting pads the result with zeroes `byte << constant byte` `word << constant byte` (zpreg) `constant word << constant byte` `constant long << constant byte` * `>>>>`: shifting a 9-bit value and returning a byte; `a >>>> b` is equivalent to `(a & $1FF) >> b`, but the latter doesn't compile yet `word >>>> constant byte` * `>>>>`: shifting a byte and returning a 9-bit value; `a >>>> b` is equivalent to `(a << b) & 0x1ff` if there was no overflow, but the latter doesn't compile yet `byte <<<< constant byte` ## Decimal arithmetic operators These operators work using the decimal arithmetic and will not work on Ricoh CPU's. * `+'`, `-'`: decimal addition/subtraction `byte +' byte` `constant word +' constant word` `constant long +' constant long` * `*'`: decimal multiplication `constant *' constant` * `<<'`, `>>'`: decimal multiplication/division by power of two `byte <<' constant byte` ## Comparison operators These operators (except for `!=`) can accept more than 2 arguments. In such case, the result is true if each comparison in the group is true. Note you cannot mix those operators, so `a <= b < c` is not valid. Note that currently in cases like `a < f() < b`, `f()` will be evaluated twice! * `==`: equality `byte == byte` `word == word` `long == long` * `!=`: inequality `byte != byte` `word != word` `long != long` * `>`, `<`, `<=`, `>=`: inequality `byte > byte` `word > word` `long > long` Currently, `>`, `<`, `<=`, `>=` operators perform unsigned comparison if none of the types of their arguments is signed, and fail to compile otherwise. This will be changed in the future. ## Assignment and in-place modification operators * `=`: normal assignment `mutable byte = byte` `mutable word = word` `mutable long = long` * `+=`, `+'=`, `|=`, `^=`, `&=`: modification in place `mutable byte += byte` `mutable word += word` `mutable long += long` * `<<=`, `>>=`, `<<'=`, `>>'=`: shift in place `mutable byte <<= constant byte` `mutable word <<= constant byte` `mutable long <<= constant byte` * `-=`, `-'=`: subtraction in place `mutable byte -= byte` `mutable word -= simple word` `mutable long -= simple long` * `*=`: multiplication in place `mutable byte *= constant byte` `mutable byte *= byte` (zpreg) * `*'=`: decimal multiplication in place `mutable byte *'= constant byte` ## Indexing While Millfork does not consider indexing an operator, this is a place as good as any to discuss it. An expression of form `a[i]`, where `i` is an expression of type `byte`, is: * when `a` is an array: an access to the `i`-th element of the array `a` * when `a` is a pointer variable: an access to the byte in memory at address `a + i` Those expressions are of type `byte`. If `a` is any other kind of expression, `a[i]` is invalid.