#Interface implementation

1 messages · Page 1 of 1 (latest)

honest sparrow
#

As a exercise in comptime I tried implementing an interface, but my implementation is really flaky.
It works in Debug optimisation level, if line 51 is uncommented. It does not have to be print it can be an assignment like:

    const val = &series_interface.simple_series.a;
    _ = val;

I tested on both 0.14.1 and master compilers.

Here is the code:

const Series = struct {
    const Self = @This();
    nextFn: *const fn(interface: *Self) i32,

    fn next(self: *Self) i32 {
        return self.nextFn(self);
    }
};

const SimpleSeries = struct {
    const Self = @This();
    a: i32,

    fn init() Self {
        return .{
            .a = 0,
        };
    }

    fn next(self: *Self) i32 {
        self.a += 1;
        return self.a;
    }

    fn series(self: *Self) SeriesInterface{
        return .{
            .simple_series = self,
            .interface = .{
                .nextFn = SeriesInterface.next,
            },
        };
    }

    const SeriesInterface = struct {
        simple_series: *SimpleSeries,
        interface: Series,

        fn next(series_iter: *Series) i32 {
            const self: *SeriesInterface = @fieldParentPtr("interface", series_iter);
            return SimpleSeries.next(self.simple_series);
        }
    };
};

const print = @import("std").debug.print;

pub fn main() void {
    var simple_series = SimpleSeries.init();
    const series_interface = simple_series.series();

    // print("Pointer {}\n", .{&series_interface.simple_series.a});

    var series = series_interface.interface;

    print("First value {}\n", .{series.next()});
}
abstract bison
#
const Series = struct {
    const Self = @This();
    context: *anyopaque,
    nextFn: *const fn (interface: *anyopaque) i32,

    fn next(self: *Self) i32 {
        return self.nextFn(self.context);
    }
};

const SimpleSeries = struct {
    const Self = @This();
    a: i32,

    fn init() Self {
        return .{
            .a = 0,
        };
    }

    fn next(self: *Self) i32 {
        self.a += 1;
        return self.a;
    }

    fn series(self: *Self) Series {
        const Impl = struct {
            fn nextFn(context: *anyopaque) i32 {
                const ptr: *SimpleSeries = @alignCast(@ptrCast(context));

                return ptr.next();
            }
        };
        return .{
            .context = self,
            .nextFn = Impl.nextFn,
        };
    }
};

const print = @import("std").debug.print;

pub fn main() void {
    var simple_series = SimpleSeries.init();
    var series = simple_series.series();

    for (0..10) |i| {
        print("{}: {}\n", .{ i, series.next() });
    }
}
hidden cedar
honest sparrow
hidden cedar
#

as a side note, intrusive interfaces are usually meant to live inside the data rather than live outside and reference the data

honest sparrow