pub const Error = error{ WriteFailed, OutOfMemory }; pub fn renderToWriter(zoir: Zoir, arena: Allocator, w: *Writer) Error!void { assert(!zoir.hasCompileErrors()); const bytes_per_node = comptime n: { var n: usize = 0; for (@typeInfo(Zoir.Node.Repr).@"struct".fields) |f| { n += @sizeOf(f.type); } break :n n; }; const node_bytes = zoir.nodes.len * bytes_per_node; const extra_bytes = zoir.extra.len * @sizeOf(u32); const limb_bytes = zoir.limbs.len * @sizeOf(std.math.big.Limb); const string_bytes = zoir.string_bytes.len; // zig fmt: off try w.print( \\# Nodes: {} ({Bi}) \\# Extra Data Items: {} ({Bi}) \\# BigInt Limbs: {} ({Bi}) \\# String Table Bytes: {Bi} \\# Total ZON Bytes: {Bi} \\ , .{ zoir.nodes.len, node_bytes, zoir.extra.len, extra_bytes, zoir.limbs.len, limb_bytes, string_bytes, node_bytes + extra_bytes + limb_bytes + string_bytes, }); // zig fmt: on var pz: PrintZon = .{ .w = w, .arena = arena, .zoir = zoir, .indent = 0, }; return pz.renderRoot(); } const PrintZon = struct { w: *Writer, arena: Allocator, zoir: Zoir, indent: u32, fn renderRoot(pz: *PrintZon) Error!void { try pz.renderNode(.root); try pz.w.writeByte('\n'); } fn renderNode(pz: *PrintZon, node: Zoir.Node.Index) Error!void { const zoir = pz.zoir; try pz.w.print("%{d} = ", .{@intFromEnum(node)}); switch (node.get(zoir)) { .true => try pz.w.writeAll("true"), .false => try pz.w.writeAll("false"), .null => try pz.w.writeAll("null"), .pos_inf => try pz.w.writeAll("inf"), .neg_inf => try pz.w.writeAll("-inf"), .nan => try pz.w.writeAll("nan"), .int_literal => |storage| switch (storage) { .small => |x| try pz.w.print("int({d})", .{x}), .big => |x| { const str = try x.toStringAlloc(pz.arena, 10, .lower); try pz.w.print("int(big {s})", .{str}); }, }, .float_literal => |x| try pz.w.print("float({d})", .{x}), .char_literal => |x| try pz.w.print("char({d})", .{x}), .enum_literal => |x| try pz.w.print("enum_literal({f})", .{std.zig.fmtIdP(x.get(zoir))}), .string_literal => |x| try pz.w.print("str(\"{f}\")", .{std.zig.fmtString(x)}), .empty_literal => try pz.w.writeAll("empty_literal(.{})"), .array_literal => |vals| { try pz.w.writeAll("array_literal({"); pz.indent += 1; for (0..vals.len) |idx| { try pz.newline(); try pz.renderNode(vals.at(@intCast(idx))); try pz.w.writeByte(','); } pz.indent -= 1; try pz.newline(); try pz.w.writeAll("})"); }, .struct_literal => |s| { try pz.w.writeAll("struct_literal({"); pz.indent += 1; for (s.names, 0..s.vals.len) |name, idx| { try pz.newline(); try pz.w.print("[{f}] ", .{std.zig.fmtIdP(name.get(zoir))}); try pz.renderNode(s.vals.at(@intCast(idx))); try pz.w.writeByte(','); } pz.indent -= 1; try pz.newline(); try pz.w.writeAll("})"); }, } } fn newline(pz: *PrintZon) !void { try pz.w.writeByte('\n'); try pz.w.splatByteAll(' ', 2 * pz.indent); } }; const std = @import("std"); const assert = std.debug.assert; const Allocator = std.mem.Allocator; const Zoir = std.zig.Zoir; const Writer = std.Io.Writer;