Skip to content

Define a PolyNode type

Description

Define a PolyNode type.

  • Message struct embeds a poly: PolyNode field.
  • PolyHelper(Message) gives tag identity, init, and toPoly.
  • init sets the tag on a stack value, no heap.
  • isIt checks the tag.
  • toPoly reaches the embedded PolyNode — the way in.
  • The node carries the tag and starts unlinked, ready to be placed.

Coming back the other way is fromPoly. It needs a node whose type is not known statically, so it is shown in 023-tag_dispatch.

Diagram

 stack: var msg: Message
 PolyHelper.init ──► msg.poly.tag set (no alloc)
 MessagePolyHelper.toPoly ──► *PolyNode (the way in)
 node carries the tag, not linked yet
 (stack-allocated — no free needed)

Source

pub fn define_a_polynode_type(allocator: std.mem.Allocator, io: std.Io) !void {
    _ = .{ allocator, io };

    // A Message on the stack. No allocator involved.
    var msg: Message = .{ .text = "hello", .priority = 1 };
    MessagePolyHelper.init(&msg);

    // The tag identifies the type at runtime.
    try helpers.expect(error.DefineTypeFailed, MessagePolyHelper.isIt(msg.poly.tag), "expected Message tag");
    try helpers.expect(error.DefineTypeFailed, !items.Event.EventPolyHelper.isIt(msg.poly.tag), "unexpected Event tag");

    // toPoly reaches the embedded PolyNode. Nothing else needs to know
    // the field is called poly.
    const handle: polynode.ItemHandle = MessagePolyHelper.toPoly(&msg);

    // The node travels with its tag, so a holder can identify it later.
    try helpers.expect(error.DefineTypeFailed, MessagePolyHelper.isIt(handle.*.tag), "node must carry the Message tag");

    // A fresh item sits in no list yet.
    try helpers.expect(error.DefineTypeFailed, !polynode.is_linked(handle), "new item must be unlinked");
}

pub const Message = struct {
    poly: polynode.PolyNode = .{},
    text: []const u8 = "",
    priority: u8 = 0,
};

pub const MessagePolyHelper = polynode.PolyHelper(Message);

const items = @import("../items/items.zig");
const helpers = @import("../helpers/helpers.zig");
const polynode = @import("matryoshka").polynode;
const std = @import("std");