The error
❯ zig run ~/Downloads/walker.zig
/Users/joelr/Downloads/walker.zig:38:64: error: function type cannot have an inferred error set
const Walker = fn (alloc: Allocator, ctx: anytype, expr: Expr) !void;
The code only compiles if I type walker as anytype
.
const std = @import("std");
const mem = std.mem;
const Allocator = mem.Allocator;
pub const Error = Allocator.Error || error{};
pub const Expr = union(enum) {
binary: Binary,
paren: *Expr,
size: usize,
const Self = @This();
pub const Binary = struct {
op: BinaryOp,
lhs: *Expr,
rhs: *Expr,
};
pub const BinaryOp = enum {
@"||",
@"&&",
};
};
pub fn clone(alloc: Allocator, T: type, value: T) Error!*T {
const result = try alloc.create(T);
result.* = value;
return result;
}
pub fn cloneExpr(alloc: Allocator, expr: Expr) Error!*Expr {
return clone(alloc, Expr, expr);
}
const Walker = fn (alloc: Allocator, ctx: anytype, expr: Expr) !void;
pub fn walkExpr(T: type, walk: Walker) type {
return struct {
pub fn run(alloc: Allocator, context: *T, node: Expr) !void {
switch (node) {
.binary => |binary| {
try run(alloc, context, binary.lhs.*);
try run(alloc, context, binary.rhs.*);
},
.paren => |paren| try run(alloc, context, paren.*),
else => try walk(alloc, context, node),
}
}
};
}
pub fn main() !void {
const page_alloc = std.heap.page_allocator;
var arena = std.heap.ArenaAllocator.init(page_alloc);
defer arena.deinit();
const alloc = arena.allocator();
const sizeExpr = struct {
fn walk(_: Allocator, ctx: *usize, expr: Expr) Error!void {
switch (expr) {
.size => |size| ctx.* += size,
else => {},
}
}
}.walk;
const walker = walkExpr(usize, sizeExpr);
const one = Expr{ .size = 1 };
const two = Expr{ .size = 2 };
const three = Expr{ .size = 3 };
const binary = Expr{
.binary = .{
.op = .@"||",
.lhs = try cloneExpr(alloc, one),
.rhs = try cloneExpr(alloc, two),
},
};
const paren = Expr{
.paren = try cloneExpr(alloc, three),
};
const expr = Expr{
.binary = .{
.op = .@"&&",
.lhs = try cloneExpr(alloc, binary),
.rhs = try cloneExpr(alloc, paren),
},
};
var size: usize = 0;
try walker.run(alloc, &size, expr);
std.debug.print("size = {d}\n", .{size});
}