Operators

Expressions are composed of operators and operands. Operators come in three flavours: with 1, 2, or 3 operands. Each operand in turn is an expression.

Each operator has a priority. For instance, the priority of the ` *`
is higher than that of ` +`, causing ` 1 + 2 * 3` to be
interpreted as first multiplying ` 2` by ` 3` followed by the
addition of ` 1`. Parentheses can be used to impose a different
evaluation order: ` (1 + 2) * 3` will first add ` 1` and
` 2`, multiplying the result with ` 3`.

You can experiment with expressions by modifying the ` hello.t`
program to print something different from its familiar message. Here are
a few examples; remember to run ` make` to have the program rebuilt
after you have modified the source.

[[[stdio out] print 1 + 2 * 3] nl]; [[[stdio out] print (1 + 2) * 3] nl];

And a more daring example--notice how ` print` accepts more than one
thing, grouped by parentheses and separated by commas.

[[[stdio out] print ("0 F = ", 5.0 / 9.0 * (0.0 - 32.0), " C")] nl];

Table 2.3 lists all operators. Operators nearer to the top have a higher priority than those below it. In the same group, between horizontal lines, operators have the same priority.

operator | arity | associativity | description |

++, - |
1 | right | increment, decrement |

-, , ! |
1 | right | minus, inversion, not |

*, /, % |
2 | left | multiply, divide, modulo |

+, - |
2 | left | add, subtract |

<<, >> |
2 | left | arithmetic shift |

>>> |
2 | left | logic shift right |

& |
2 | left | bitwise and |

| |
2 | left | bitwise or |

^ |
2 | left | bitwise exclusive-or |

<, <=, >=, > |
2 | left | ordered comparison |

==, != |
2 | left | equality comparison |

&& |
2 | left | boolean and |

|| |
2 | left | boolean or |

-> |
2 | left | implies |

?: |
3 | right | if-then-else |

=, etc. |
2 | right | assignment (see text) |

The unary minus returns the negation of its numeric argument. Thus,
evaluating any of the expressions ` -1`, ` -(1)`, and ` -(2 -
1)` all return the value -1. Negation preserves the type of its
argument: negating an ` int` value results in another ` int`
value.

The bitwise inversion operator, ,
returns, given an integer
numeric argument, an integer numeric value of the same type, but with all
0 bits replaced by 1 bits, and vice versa. Thus, ` 0`
returns -1.

The boolean not operator, ` !`, returns ` FALSE` iff its operand
has the default value for its type, and ` TRUE` otherwise. For
example, the default value of numeric types is 0, so ` !0` will
return ` TRUE` and ` !456` will return FALSE.

The value returned by ` !` has the ` boolean` type. The only
values of this type are ` TRUE` and ` FALSE`, also known as
` YES` and ` NO`^{2.2}.
Apart from ` >>>` and ` ->` the binary operators perform the same
function as their C, and many other languages, equivalents. ` >>>`
shifts a signed number in the same way as ` >>` shifts an unsigned
number in C. The implication operator, ` ->`, performs the boolean
implication: ` a -> b` is equivalent to ` !a || b`.
Table 2.4 shows a few examples of their use.

The operators ` *`, ` /`, ` +`, ` -`, ` <`,
` <=`, ` >=`, and ` >` operate on any numeric type. The
` %`, ` <<`, ` >>`, ` >>>`, ` &`, ` |`, and
` ^ ` operate on integer numeric types. ` &&`, ` ||`,
and ` ->` operate on the ` boolean` type. Furthermore,
` ==` and ` !=` operate on any type, including those to be
introduced later on.

All binary operators are left associative, except the assignment
operator^{2.3},
` =`, which is right-associative. The order of evaluation of the
operands follows the associativity of the operator. Thus, ` 1 + 2 +
3` is interpreted as ` (1 + 2) + 3`, and the ` 3` is only
evaluated after the addition of ` 1` and ` 2`--not that it makes
any difference in this simple case. Furthermore, ` a = b = c` means
` a = (b = c)`. (We will return to the assignment operator later
on--they aren't much use when constants and operators are the only
building blocks at hand.)

The boolean operators are * short-circuited*. This means that if
enough information is known about the operands that the result of the
whole expression is known the evaluation of any remaining operands is
skipped. Thus, ` FALSE && x` returns ` FALSE` without ever
evaluating ` x`, since its value does not matter.
There is only one ternary operator, ` ?:`, also known as the
if-then-else operator. For example, to compute the maximum of ` a`
and ` b`, one could use `a > b ? a : b`

, meaning that if
`a`

is larger than `b`

, the second expression (in this case
`a`

) will be evaluated and returned as the result; otherwise the
result of the third expression (`b`

) is the result of the whole
expression.

In general, when used as `x ? y : z`

, the type of ` x` must be
` boolean`, and the type of ` y` must equal the type of
` z`. Furthermore, only one of ` y` and ` z` will be
evaluated.