ring with when filter

? Unknown Status unknown.

Code

// Test 914: Ring buffer consumer with WHEN clause filtering
//
// This demonstrates the FULL consumer pattern with all three primitives:
// - Labels for loops
// - Taps for observation
// - When clauses for filtering
//
// Only process EVEN numbers!

const std = @import("std");
~import "$std/taps"

// Generic ring buffer (Zig function returning type)
pub fn Ring(comptime T: type, comptime size: usize) type {
    return struct {
        const Self = @This();

        data: [size]T,
        head: usize,
        tail: usize,

        pub fn init() Self {
            return .{
                .data = undefined,
                .head = 0,
                .tail = 0,
            };
        }

        pub fn tryEnqueue(self: *Self, value: T) bool {
            if ((self.tail + 1) % size == self.head) {
                return false;
            }
            self.data[self.tail] = value;
            self.tail = (self.tail + 1) % size;
            return true;
        }

        pub fn tryDequeue(self: *Self) ?T {
            if (self.head == self.tail) {
                return null;
            }
            const value = self.data[self.head];
            self.head = (self.head + 1) % size;
            return value;
        }
    };
}

const MyRing = Ring(u32, 1024);

// Ring operations
~event ring.enqueue { ring: *Ring(u32, 1024), value: u32 }
| enqueued {}
| full {}

~proc ring.enqueue {
    if (ring.tryEnqueue(value)) {
        return .{ .enqueued = .{} };
    }
    return .{ .full = .{} };
}

~event ring.dequeue { ring: *Ring(u32, 1024) }
| value { data: u32 }
| empty {}

~proc ring.dequeue {
    if (ring.tryDequeue()) |data| {
        return .{ .value = .{ .data = data } };
    }
    return .{ .empty = .{} };
}

// Processing event - what we do with dequeued values
~event process { data: u32 }
| done {}

~proc process {
    std.debug.print("Processing: {}\n", .{data});
    return .{ .done = .{} };
}

// EVENT TAP with WHEN CLAUSE: Only process EVEN numbers!
// This is the filtered consumer - observe dequeue, but only act on evens
~tap(ring.dequeue -> *)
| value v when v.data % 2 == 0 |> process(data: v.data)
    | done |> _

// Producer: Fill the ring with values
~event produce { ring: *Ring(u32, 1024), count: u32 }
| done {}

~proc produce {
    var i: u32 = 0;
    while (i < count) : (i += 1) {
        _ = ring.tryEnqueue(i);
    }
    std.debug.print("Produced {} values\n", .{count});
    return .{ .done = .{} };
}

// Consumer loop using label + tap
// The tap fires automatically for each dequeued value!
~event start {}
| ready {}

~proc start {
    return .{ .ready = .{} };
}

var my_ring = MyRing.init();

~start()
| ready |> produce(ring: &my_ring, count: 6)
    | done |> #consume ring.dequeue(ring: &my_ring)
        | value |> @consume
        | empty |> _
input.kz

Expected Output

Produced 6 values
Processing: 0
Processing: 2
Processing: 4

Test Configuration

MUST_RUN