Structs & OOP

Jda uses a struct + trait + impl model for object-oriented programming, similar to Rust. There are no classes — data (structs) and behavior (functions, traits, impls) are composed together.

Structs

Structs are value types with named fields:

struct Point {
    x: i64
    y: i64
}

fn main() -> i64 {
    let p = Point{}
    p.x = 10
    p.y = 20
    print_i64(p.x + p.y)    // prints 30
    ret 0
}

Struct Pointers

Pass structs by reference for efficiency:

fn move_point(p: &Point, dx: i64, dy: i64) {
    p.x = p.x + dx
    p.y = p.y + dy
}

fn main() -> i64 {
    let p = Point{}
    p.x = 5
    p.y = 10
    move_point(&p, 3, 4)
    print_i64(p.x)    // prints 8
    ret 0
}

Nested Structs

struct Rect {
    origin: Point
    width: i64
    height: i64
}

fn area(r: &Rect) -> i64 {
    ret r.width * r.height
}

Arrays in Structs

struct Buffer {
    data: i64[256]
    len: i64
}

Traits (Interfaces)

Traits define shared behavior:

trait Shape {
    fn area(self: &Self) -> i64
}

trait Printable {
    fn show(self: &Self)
}

Default Methods

Traits can have default implementations:

trait Describable {
    fn name(self: &Self) -> i64       // required
    fn describe(self: &Self) {         // default
        print("object")
    }
}

Impl (Implementation)

Implement traits for structs:

struct Circle { radius: i64 }

impl Shape for Circle {
    fn area(self: &Circle) -> i64 {
        ret self.radius * self.radius * 3
    }
}

impl Printable for Circle {
    fn show(self: &Circle) {
        print("Circle(r=")
        print_i64(self.radius)
        print(")")
    }
}

Derive Macros

Auto-generate common trait implementations:

derive(Debug, Eq, Clone, Hash, Zero, Ord)
struct Config {
    width: i64
    height: i64
    depth: i64
}
DeriveGenerates
DebugConfig_debug(&c) — print struct fields
EqConfig_eq(&a, &b) — field-by-field equality
CloneConfig_clone(&c) — deep copy
HashConfig_hash(&c) — hash of all fields
ZeroConfig_zero(&c) — zero all fields
OrdConfig_lt(&a, &b) — lexicographic ordering

Generic Structs

struct Pair<T> {
    first: T
    second: T
}

fn pair_swap<T>(p: &Pair<T>) {
    let tmp = p.first
    p.first = p.second
    p.second = tmp
}

OOP Patterns

Encapsulation

Group related functions with a naming convention:

struct Stack {
    data: i64[1024]
    top: i64
}

fn stack_new() -> Stack {
    let s = Stack{}
    s.top = 0
    ret s
}

fn stack_push(s: &Stack, val: i64) {
    s.data[s.top] = val
    s.top = s.top + 1
}

fn stack_pop(s: &Stack) -> i64 {
    s.top = s.top - 1
    ret s.data[s.top]
}

Operator Overloading

fn Point_add(a: &Point, b: &Point) -> Point {
    let r = Point{}
    r.x = a.x + b.x
    r.y = a.y + b.y
    ret r
}

Builder Pattern

fn config_builder() -> Config {
    let c = Config{}
    c.width = 800
    c.height = 600
    c.depth = 32
    ret c
}