Documentation channel: current development main at compiler checkpoint 1d7e15e. The latest tagged release is v0.0.3; pages identify APIs that are not yet released.
Operators
Strut has a fixed, language-defined operator table. Packages may overload the enabled operators, but they cannot invent punctuation or change precedence. Overloads are free declarations, not methods, so operand order and symmetry are explicit.
Overload table
| Form | Operators | Overloadable | Declaration contract |
|---|---|---|---|
| Infix arithmetic | + - * / % | Yes | Two parameters; any declared return type. |
| Infix comparison | == != < <= > >= | Yes | Two parameters; return bool. |
| Infix logical/bitwise | || && | ^ & | Yes | Two parameters. Logical overloads return bool; bitwise overloads may return a domain type. |
| Infix shifts | << >> | Yes | Two parameters; return the shifted or stream type. |
| Prefix | + - ! ~ * ++ -- | Yes | One parameter; return type is explicit. |
| Postfix | ++ -- | Yes | One parameter followed by the compiler marker postfix. |
| Assignment | = := | Yes | Two parameters. The destination is first; use a reference destination for =. |
| Null coalescing | ?? | No | Language-defined nullable semantics. |
| Index and call | [] () | No | Reserved syntax; source overload declarations are not enabled yet. |
Certified examples for every enabled family
This single example declares and executes arithmetic, comparison, bitwise/logical-family, shift, prefix, initialization, and assignment overloads. It is compiled and run by the documentation suite, so every “Yes” row above has executable proof.
struct Number { int value; }
struct Config { int value; }
operator +(Number a, Number b) -> Number {
return Number { value: a.value + b.value };
}
operator ==(Number a, Number b) -> bool {
return a.value == b.value;
}
operator &(Number a, Number b) -> Number {
return Number { value: a.value & b.value };
}
operator <<(Number value, int amount) -> Number {
return Number { value: value.value << amount };
}
operator -(Number value) -> Number {
return Number { value: -value.value };
}
operator ++(Number& value) -> Number& {
value.value = value.value + 1;
return value;
}
operator ++(Number& value, postfix) -> Number {
previous := Number { value: value.value };
value.value = value.value + 1;
return previous;
}
operator :=(Number destination, Config source) -> void {
destination.value = source.value;
}
operator =(Number& destination, Config source) -> void {
destination.value = source.value;
}
function main() -> int {
one := Number { value: 1 };
two := Number { value: 2 };
sum := one + two;
same := sum == Number { value: 3 };
masked := sum & Number { value: 1 };
shifted := masked << 2;
negative := -shifted;
before := sum++;
updated := ++sum;
Number configured := Config { value: 7 };
configured = Config { value: 9 };
println(same);
println(negative.value);
println(before.value);
println(updated.value);
println(configured.value);
return 0;
}
Resolution rules
Binary overloads are ordered: operator +(Left, Right) does not imply operator +(Right, Left). Declare both when an operation is intentionally symmetric across different types. The declared return type controls the expression type and may differ from either operand.
Prefix and postfix increment/decrement are separate overload identities. ++value selects only operator ++(T& value), while value++ selects only operator ++(T& value, postfix). The postfix word is compile-time signature syntax: it is not a type, runtime argument, or body-visible parameter. Conventionally prefix returns the updated T& and postfix returns the previous T; return types do not determine which overload is selected.
= mutates existing storage and therefore normally takes T& as its first parameter. := constructs new storage and receives a destination value plus its source. These are dedicated language lowering points rather than native C++ assignment declarations.
Generic overloads
operator[T] +(Vector<T> a, Vector<T> b) -> Vector<T> {
return Vector<T> { x: a.x + b.x, y: a.y + b.y };
}
Callable-form declarations
operator<(Vector, Vector) -> Vector> + :=
(a, b) => Vector { x: a.x + b.x, y: a.y + b.y };
