Dependency loop in statically-linked array elements

this appears to work, in that i have a “circular list” with pointers being represented as indicies into my array:

const std = @import("std");

const Elem = struct {
    pub const NIL = ~@as(u16, 0);
    data: u32,
    next: u16 = NIL,
    pub fn getNext(self: @This()) ?*Elem {
        if (self.next == NIL) {
            return null;
        } else {
            return &elem_table[self.next];
        }
    }
};

var elem_table = [_]Elem{
    Elem{ .data = 10, .next = 1 },
    Elem{ .data = 20, .next = 2 },
    Elem{ .data = 30, .next = 0 },
};

var head = &elem_table[0];

pub fn main() void {
    var e = head;
    while (true) {
        std.log.debug("{d}", .{e.data});
        if (e.getNext() == null) break;
        e = e.getNext().?;
        if (e == head) break;
    }
}

the trick, of course, is to ensure getNext incurs little/no overhead… given that initial value of elem_table is known at comptime, you’d think there would be some way to perform another comptime transformation that executes getNext with a known set of .next values on an elem_table that’s known…

in my use-case, i will be GENERATING a file that contains these static initializations; and adding some additional (advanced) comptime initialization is not a problem for me…

the goal remains to minimize memory footprint on my MCU target – pushing as much work as possible to an upstream pass (which actually generates the aforementioned file) as well as any “exotic” initialization idioms…

2 Likes