Interaction Trees in Zig and simple benchmarks

This commit is contained in:
2026-05-15 21:41:19 -05:00
parent e3dcf5edd7
commit 8d5e76db1c
17 changed files with 2179 additions and 81 deletions

View File

@@ -5,6 +5,7 @@ const reduce = @import("reduce.zig");
const codecs = @import("codecs.zig");
const kernel = @import("kernel.zig");
const bundle = @import("bundle.zig");
const io_driver = @import("io_driver.zig");
/// Opaque handle for the C API. Layout is not exposed to C.
/// Holds a persistent arena for user-built terms and the kernel.
@@ -59,6 +60,57 @@ export fn arb_app(ctx: *ArbCtx, func: u32, arg: u32) u32 {
return ctx.arena.alloc(.{ .app = .{ .func = func, .arg = arg } }) catch 0;
}
// ---------------------------------------------------------------------------
// Tree inspection (Layer 1 — for custom IO drivers and non-POSIX hosts)
// All return 1 on success / true, 0 on failure / false.
// ---------------------------------------------------------------------------
export fn arb_is_leaf(ctx: *ArbCtx, root: u32) c_int {
if (root >= ctx.arena.len()) return 0;
return if (ctx.arena.nodes.items[root] == .leaf) 1 else 0;
}
export fn arb_is_stem(ctx: *ArbCtx, root: u32) c_int {
if (root >= ctx.arena.len()) return 0;
return if (ctx.arena.nodes.items[root] == .stem) 1 else 0;
}
export fn arb_is_fork(ctx: *ArbCtx, root: u32) c_int {
if (root >= ctx.arena.len()) return 0;
return if (ctx.arena.nodes.items[root] == .fork) 1 else 0;
}
export fn arb_is_app(ctx: *ArbCtx, root: u32) c_int {
if (root >= ctx.arena.len()) return 0;
return if (ctx.arena.nodes.items[root] == .app) 1 else 0;
}
export fn arb_get_stem_child(ctx: *ArbCtx, root: u32, out: *u32) c_int {
if (root >= ctx.arena.len()) return 0;
const node = ctx.arena.nodes.items[root];
if (node != .stem) return 0;
out.* = node.stem.child;
return 1;
}
export fn arb_get_fork_children(ctx: *ArbCtx, root: u32, out_left: *u32, out_right: *u32) c_int {
if (root >= ctx.arena.len()) return 0;
const node = ctx.arena.nodes.items[root];
if (node != .fork) return 0;
out_left.* = node.fork.left;
out_right.* = node.fork.right;
return 1;
}
export fn arb_get_app_func_arg(ctx: *ArbCtx, root: u32, out_func: *u32, out_arg: *u32) c_int {
if (root >= ctx.arena.len()) return 0;
const node = ctx.arena.nodes.items[root];
if (node != .app) return 0;
out_func.* = node.app.func;
out_arg.* = node.app.arg;
return 1;
}
// ---------------------------------------------------------------------------
// Reduction
// ---------------------------------------------------------------------------
@@ -157,6 +209,23 @@ export fn arb_unwrap_host_value(ctx: *ArbCtx, root: u32, out_tag: *u64, out_payl
return 1;
}
// ---------------------------------------------------------------------------
// IO driver (Layer 2 — POSIX interaction-tree runtime)
// ---------------------------------------------------------------------------
pub const arb_io_perms_t = extern struct {
allow_read_all: c_int,
allow_write_all: c_int,
};
export fn arb_run_io(ctx: *ArbCtx, program: u32, perms: ?*const arb_io_perms_t) u32 {
const zig_perms = if (perms) |p| io_driver.IOPerms{
.allow_read_all = p.allow_read_all != 0,
.allow_write_all = p.allow_write_all != 0,
} else io_driver.IOPerms{};
return io_driver.runIO(ctx.gpa, &ctx.arena, program, zig_perms) catch 0;
}
// ---------------------------------------------------------------------------
// Kernel entrypoints
// ---------------------------------------------------------------------------