Targets · Zig · Drivers

Drivers

The native drivers that provide the interface, console and network.

Contents

How a Program becomes Zig, in parts. Start with the introduction, then follow each part into the rendered output and the runtime it links against.

Defining a driver

A driver is a Zig struct with the driver's functions: it drains one context channel and reconciles the resources it owns. Here is a console driver — it drains the Console.Lines channel and prints each line that has changed since the last cycle.

const ConsoleDriver = struct {
    last_by_id: std.AutoHashMap(i64, []const u8),

    pub fn channel(_: *ConsoleDriver) []const u8 {
        return "Console.Lines";
    }
    pub fn kind(_: *ConsoleDriver) DriverKind {
        return .array;
    }
    pub fn init(_: *ConsoleDriver, add_updates: AddUpdates) void {
        _ = add_updates;
    }

    pub fn dispatch(self: *ConsoleDriver, emissions: []const Line) void {
        for (emissions) |line| {
            const prev = self.last_by_id.get(line.id);
            if (prev == null or !std.mem.eql(u8, prev.?, line.text)) {
                std.debug.print("{s}\n", .{line.text});
                self.last_by_id.put(line.id, line.text) catch {};
            }
        }
    }
};

Registering it

A program lists the drivers it uses; the runtime opens a channel for each and never hardcodes one.

pub fn main() !void {
    var console = ConsoleDriver{ .last_by_id = std.AutoHashMap(i64, []const u8).init(allocator) };
    Program.application(struct { pub fn run() void {
        Main();
    } }.run, &.{ console.driver() });
}

How the runtime runs it

Each cycle the runtime opens the driver's channel, runs the reactive program (which emits into it), drains it, and passes the slice to dispatch:

Context.openArray("Console.Lines");
program = Reactive.run(program, updates);
driver.dispatch(Context.drainArray("Console.Lines"));

A driver that produces events — a timer, a network reply — calls the add_updates it was given in init, which schedules the next cycle. The three shapes are the same as everywhere: a tree renderer (the terminal interface), a request set (network), and a shared ticker.