2018-01-10 12:08:24 +00:00
# Operators
Unlike in high-level languages, operators in Millfork have limited applicability.
Not every well-formed expression is actually compilable.
2018-01-10 12:17:09 +00:00
Most expressions involving single bytes compile,
but for larger types usually you need to use in-place modification operators.
2018-01-10 12:08:24 +00:00
Further improvements to the compiler may increase the number of acceptable combinations.
2018-03-05 11:05:37 +00:00
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.
2018-01-10 12:08:24 +00:00
## Precedence
Millfork has different operator precedence compared to most other languages. From highest to lowest it goes:
* `*` , `*'`
2018-02-01 21:39:38 +00:00
* `+` , `+'` , `-` , `-'` , `|` , `&` , `^` , `>>` , `>>'` , `<<` , `<<'` , `>>>>` , `<<<<`
2018-01-10 12:08:24 +00:00
* `:`
* `==` , `!=` , `<` , `>` , `<=` , `>=`
* `&&`
* `||`
* 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 `-'` .
2018-01-31 21:26:20 +00:00
They are interpreted as expected: `5 - 3 + 2 == 4` and `5 -' 3 +' 2 == 4` .
2018-01-10 12:08:24 +00:00
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
2018-01-18 21:35:25 +00:00
## 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.
2018-01-10 12:08:24 +00:00
## Binary arithmetic operators
* `+` , `-` :
`byte + byte`
2018-01-10 12:17:09 +00:00
`constant word + constant word`
`constant long + constant long`
2018-01-10 12:08:24 +00:00
2018-01-10 12:17:09 +00:00
* `*` : multiplication; the size of the result is the same as the size of the arguments
2018-01-10 12:08:24 +00:00
`byte * constant byte`
2018-01-10 12:17:09 +00:00
`constant byte * byte`
`constant word * constant word`
2018-03-05 11:05:37 +00:00
`constant long * constant long`
`byte * byte` (zpreg)
2018-01-10 12:08:24 +00:00
There are no division, remainder or modulo operators.
## Bitwise operators
* `|` , `^` , `&` : OR, EXOR and AND
2018-01-10 12:17:09 +00:00
`byte | byte`
`constant word | constant word`
`constant long | constant long`
2018-01-10 12:08:24 +00:00
2018-01-10 12:17:09 +00:00
* `<<` , `>>` : bit shifting; shifting pads the result with zeroes
`byte << constant byte`
2018-03-05 11:05:37 +00:00
`word << constant byte` (zpreg)
2018-01-10 12:17:09 +00:00
`constant word << constant byte`
`constant long << constant byte`
2018-01-10 12:08:24 +00:00
* `>>>>` : 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`
2018-02-01 21:39:38 +00:00
* `>>>>` : 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`
2018-01-10 12:08:24 +00:00
## Decimal arithmetic operators
These operators work using the decimal arithmetic and will not work on Ricoh CPU's.
* `+'` , `-'` : decimal addition/subtraction
`byte +' byte`
2018-01-10 12:17:09 +00:00
`constant word +' constant word`
`constant long +' constant long`
2018-01-10 12:08:24 +00:00
* `*'` : decimal multiplication
`constant *' constant`
* `<<'` , `>>'` : decimal multiplication/division by power of two
2018-01-10 12:09:38 +00:00
`byte <<' constant byte`
2018-01-10 12:08:24 +00:00
## 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.
2018-01-18 21:35:25 +00:00
Note that currently in cases like `a < f() < b` , `f()` will be evaluated twice!
2018-01-10 12:08:24 +00:00
* `==` : equality
`byte == byte`
`word == word`
`long == long`
* `!=` : inequality
2018-01-10 12:09:38 +00:00
`byte != byte`
`word != word`
`long != long`
2018-01-10 12:08:24 +00:00
* `>` , `<` , `<=` , `>=` : 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.
2018-01-10 12:17:09 +00:00
## Assignment and in-place modification operators
2018-01-10 12:08:24 +00:00
* `=` : 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
2018-03-06 15:59:18 +00:00
`mutable byte *= constant byte`
`mutable byte *= byte` (zpreg)
2018-01-10 12:08:24 +00:00
2018-01-31 21:26:20 +00:00
* `*'=` : decimal multiplication in place
`mutable byte *'= constant byte`
2018-01-10 12:17:09 +00:00
2018-01-18 21:35:25 +00:00
## 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`
2018-01-31 21:26:20 +00:00
Those expressions are of type `byte` . If `a` is any other kind of expression, `a[i]` is invalid.
2018-01-18 21:35:25 +00:00