Operator Overloading
Djinn allows user-defined types to define custom behavior for built-in operators like +, ==, -, and others. Operators can be declared inside a struct body or in a separate impl block.
Syntax
An operator overload is declared with the operator keyword followed by the operator symbol, a parameter list, a return type, and a body:
operator +(Vec2 left, Vec2 right) -> Vec2 {
return { .x = left.x + right.x, .y = left.y + right.y };
}Operators Inside Struct Bodies
Operators can be defined directly inside the struct definition:
struct Vec2 {
i32 x;
i32 y;
operator +(Vec2 left, Vec2 right) -> Vec2 {
return { .x = left.x + right.x, .y = left.y + right.y };
}
}
i32 main() {
Vec2 a = { .x = 10, .y = 20 };
Vec2 b = { .x = 5, .y = 7 };
Vec2 c = a + b;
return c.x + c.y; // 42
}Operators in impl Blocks
Operators can also be defined in a separate impl block:
struct Vec2 {
i32 x;
i32 y;
}
impl Vec2 {
operator +(Vec2 left, Vec2 right) -> Vec2 {
return { .x = left.x + right.x, .y = left.y + right.y };
}
}Equality Operators
Define == to enable equality comparisons. The compiler automatically derives != from ==, so you only need to implement one:
struct Point {
i32 x;
i32 y;
}
impl Point {
operator ==(Point left, Point right) -> bool {
return left.x == right.x && left.y == right.y;
}
}
i32 main() {
Point a = { .x = 5, .y = 10 };
Point b = { .x = 5, .y = 10 };
Point c = { .x = 1, .y = 2 };
if (a == b) { /* true */ }
if (a != c) { /* true — derived automatically */ }
}Multiple Operators
A struct can define as many operators as needed:
struct Vec2 {
i32 x;
i32 y;
operator +(Vec2 left, Vec2 right) -> Vec2 {
return { .x = left.x + right.x, .y = left.y + right.y };
}
operator ==(Vec2 left, Vec2 right) -> bool {
return left.x == right.x && left.y == right.y;
}
}
i32 main() {
Vec2 a = { .x = 3, .y = 4 };
Vec2 b = { .x = 3, .y = 4 };
Vec2 c = { .x = 6, .y = 8 };
Vec2 sum = a + b;
if (sum == c) {
return 99;
}
return 0;
}Operators in Interfaces
Interfaces can declare operator signatures that implementing structs must provide:
interface IEquatable<T> {
operator ==(T left, T right) -> bool;
}Overloadable Operators
| Category | Operators |
|---|---|
| Arithmetic | +, -, *, /, % |
| Comparison | ==, !=, <, <=, >, >= |
| Bitwise | &, |, ^, ~, <<, >> |
Bitwise Operators on Primitives
Bitwise operators work on integer primitives without needing overloads:
i32 main() {
i32 a = 12; // 1100
i32 b = 10; // 1010
i32 and_result = a & b; // 1000 = 8
i32 or_result = a | b; // 1110 = 14
i32 xor_result = a ^ b; // 0110 = 6
i32 not_result = ~a;
i32 shl_result = 1 << 3; // 8
i32 shr_result = 16 >> 2; // 4
}Derived Operators
When you define ==, the compiler automatically provides != as its logical negation. You do not need to implement != separately.