Operators combine, inspect, or update values. Parsing determines grouping; semantic checking determines whether the operand types support the requested operation.
Arithmetic
| Operator | Meaning |
|---|---|
+ |
Addition |
- |
Subtraction |
* |
Multiplication |
/ |
Division |
% |
Remainder |
prefix - |
Negation |
subtotal := price * quantity
remainder := total % page_size
offset := -positionInteger division and floating-point division retain their operand category.
The checker does not turn an integer expression into floating point merely
because / appears.
For non-primitive values, +, -, *, and / dispatch through the
Numeric contract. Prefix - dispatches through Neg. % is not supplied by
Numeric and should be treated as a primitive numeric operation unless a
future dedicated trait is added.
Comparison
| Operator | Meaning |
|---|---|
== |
Equal |
!= |
Not equal |
< |
Less than |
<= |
Less than or equal |
> |
Greater than |
>= |
Greater than or equal |
same := left == right
within := value >= minimum and value <= maximumEquality on non-primitive values uses Equatable. Ordering uses
Comparable[T]. Comparisons do not chain: write a < b and b < c, not
a < b < c.
Equality is a value contract. It is not a source-level pointer identity test.
A user-defined implementation must preserve the usual equality laws, and a
Hashable implementation must give equal values equal hash codes.
Logic
and and or are short-circuiting boolean operators. && and || are
accepted aliases. Prefix not and ! are aliases for logical negation.
if user.is_active() and user.can_edit(document) {
edit(document)
}The right operand of and is evaluated only when the left is true. The right
operand of or is evaluated only when the left is false.
ready := cached or initialize()Both operands must type-check as bool. Atoll does not apply truthiness to
numbers, strings, collections, or optional values.
For non-primitive values, prefix ! or not can dispatch through Not.
Bitwise
| Operator | Meaning |
|---|---|
& |
Bitwise AND |
| |
Bitwise OR |
^ |
Bitwise XOR |
~ |
Bitwise complement |
<< |
Left shift |
>> |
Right shift |
flags := 0b1010
mask := 0b1100
shared := flags & mask
combined := flags | mask
toggled := flags ^ mask
shifted := flags << 2Primitive integers lower directly. User-defined types can participate through
BitAnd, BitOr, BitXor, BitNot, Shl, and Shr.
Prefix & is contextually different from infix &: it takes a reference to
an expression.
view: &Packet = &packetReference rules are covered in References.
Assignment
= updates an existing mutable place. It does not declare a new inferred
binding; declarations use :=.
mut count := 0
count = count + 1Compound assignments read, operate, and write the same place.
| Operators |
|---|
+=, -=, *=, /=, %= |
&=, |=, ^=, <<=, >>= |
??= |
mut total := 0
total += price
mut cached: string? = None
cached ??= compute_name()The target must be assignable and mutable. This includes mutable locals, mutable fields reached through a mutable receiver, and supported indexed places.
Options
?? chooses the successful payload from its left side or evaluates its right
side as a fallback. It works with the current Option and Result
coalescing rules.
name := configured_name ?? "anonymous"The right side is lazy. ?. performs option-safe member access and preserves
absence through a chain.
city := account?.profile?.city??= stores the fallback only when the target lacks a successful payload.
Detailed typing and control flow are in Option and
Result.
Propagation
Postfix ? propagates failure or absence according to the enclosing function
contract.
user := load_user(id)?On Result, it extracts Ok and returns Err from a compatible fallible
function. On Option, it extracts Some and returns None from a compatible
optional function. See Propagation.
Ranges
start..end excludes the upper endpoint. start..=end includes it.
for index in 0..items.len() {
use(items[index])
}
match status {
200..=299 => success()
_ => failure()
}Ranges appear in iteration and patterns. They are not Python-style slice syntax; slices use their own indexing and range support as provided by the collection type.
Membership
value in collection asks whether the right operand contains the left.
allowed := role in permitted_rolesThe type must provide a supported membership operation. The same in token is
the separator in an iteration loop, where the parser recognizes the loop-head
context.
Casts
value as T requests an explicit conversion.
small := count as u16
whole := ratio as intThe semantic checker must know a valid primitive or representation conversion. Writing an unrelated target type does not make the conversion legal.
Atoll’s current expression AST does not implement the legacy value is Type
runtime type-test proposal. Use enum or union pattern matching to refine a
closed set of alternatives.
Pipeline
value |> function forwards the left value to the right call.
answer := input |> parse |> normalizeWhen the right side already has arguments, the piped value becomes the leading argument.
page := records |> take(20)Pipeline syntax changes call shape, not evaluation semantics. Each stage is still type-checked as an ordinary function call.
Precedence
From tightest to loosest, the current parser groups:
| Level | Forms |
|---|---|
| Postfix | member access, calls, indexing, casts, ?, catch |
| Prefix | -, !, not, ~, & |
| Coalescing | ?? |
| Multiplicative | *, /, % |
| Additive | +, - |
| Shifts | <<, >> |
| Bitwise AND | & |
| Bitwise XOR | ^ |
| Bitwise OR | | |
| Ranges | .., ..= |
| Comparison | equality, ordering, in |
| Logical AND | and, && |
| Logical OR | or, || |
| Pipeline | |> |
| Assignment | = and compound assignments |
Assignment is right-associative. Most binary operators are left-associative; comparison and range chains should be written explicitly. Parentheses are preferable whenever mixed operator families would make intent unclear.