master
  1pub const Error = error{ WriteFailed, OutOfMemory };
  2
  3pub fn renderToWriter(zoir: Zoir, arena: Allocator, w: *Writer) Error!void {
  4    assert(!zoir.hasCompileErrors());
  5
  6    const bytes_per_node = comptime n: {
  7        var n: usize = 0;
  8        for (@typeInfo(Zoir.Node.Repr).@"struct".fields) |f| {
  9            n += @sizeOf(f.type);
 10        }
 11        break :n n;
 12    };
 13
 14    const node_bytes = zoir.nodes.len * bytes_per_node;
 15    const extra_bytes = zoir.extra.len * @sizeOf(u32);
 16    const limb_bytes = zoir.limbs.len * @sizeOf(std.math.big.Limb);
 17    const string_bytes = zoir.string_bytes.len;
 18
 19    // zig fmt: off
 20    try w.print(
 21        \\# Nodes:              {} ({Bi})
 22        \\# Extra Data Items:   {} ({Bi})
 23        \\# BigInt Limbs:       {} ({Bi})
 24        \\# String Table Bytes: {Bi}
 25        \\# Total ZON Bytes:    {Bi}
 26        \\
 27    , .{
 28        zoir.nodes.len, node_bytes,
 29        zoir.extra.len, extra_bytes,
 30        zoir.limbs.len, limb_bytes,
 31        string_bytes,
 32        node_bytes + extra_bytes + limb_bytes + string_bytes,
 33    });
 34    // zig fmt: on
 35    var pz: PrintZon = .{
 36        .w = w,
 37        .arena = arena,
 38        .zoir = zoir,
 39        .indent = 0,
 40    };
 41
 42    return pz.renderRoot();
 43}
 44
 45const PrintZon = struct {
 46    w: *Writer,
 47    arena: Allocator,
 48    zoir: Zoir,
 49    indent: u32,
 50
 51    fn renderRoot(pz: *PrintZon) Error!void {
 52        try pz.renderNode(.root);
 53        try pz.w.writeByte('\n');
 54    }
 55
 56    fn renderNode(pz: *PrintZon, node: Zoir.Node.Index) Error!void {
 57        const zoir = pz.zoir;
 58        try pz.w.print("%{d} = ", .{@intFromEnum(node)});
 59        switch (node.get(zoir)) {
 60            .true => try pz.w.writeAll("true"),
 61            .false => try pz.w.writeAll("false"),
 62            .null => try pz.w.writeAll("null"),
 63            .pos_inf => try pz.w.writeAll("inf"),
 64            .neg_inf => try pz.w.writeAll("-inf"),
 65            .nan => try pz.w.writeAll("nan"),
 66            .int_literal => |storage| switch (storage) {
 67                .small => |x| try pz.w.print("int({d})", .{x}),
 68                .big => |x| {
 69                    const str = try x.toStringAlloc(pz.arena, 10, .lower);
 70                    try pz.w.print("int(big {s})", .{str});
 71                },
 72            },
 73            .float_literal => |x| try pz.w.print("float({d})", .{x}),
 74            .char_literal => |x| try pz.w.print("char({d})", .{x}),
 75            .enum_literal => |x| try pz.w.print("enum_literal({f})", .{std.zig.fmtIdP(x.get(zoir))}),
 76            .string_literal => |x| try pz.w.print("str(\"{f}\")", .{std.zig.fmtString(x)}),
 77            .empty_literal => try pz.w.writeAll("empty_literal(.{})"),
 78            .array_literal => |vals| {
 79                try pz.w.writeAll("array_literal({");
 80                pz.indent += 1;
 81                for (0..vals.len) |idx| {
 82                    try pz.newline();
 83                    try pz.renderNode(vals.at(@intCast(idx)));
 84                    try pz.w.writeByte(',');
 85                }
 86                pz.indent -= 1;
 87                try pz.newline();
 88                try pz.w.writeAll("})");
 89            },
 90            .struct_literal => |s| {
 91                try pz.w.writeAll("struct_literal({");
 92                pz.indent += 1;
 93                for (s.names, 0..s.vals.len) |name, idx| {
 94                    try pz.newline();
 95                    try pz.w.print("[{f}] ", .{std.zig.fmtIdP(name.get(zoir))});
 96                    try pz.renderNode(s.vals.at(@intCast(idx)));
 97                    try pz.w.writeByte(',');
 98                }
 99                pz.indent -= 1;
100                try pz.newline();
101                try pz.w.writeAll("})");
102            },
103        }
104    }
105
106    fn newline(pz: *PrintZon) !void {
107        try pz.w.writeByte('\n');
108        try pz.w.splatByteAll(' ', 2 * pz.indent);
109    }
110};
111
112const std = @import("std");
113const assert = std.debug.assert;
114const Allocator = std.mem.Allocator;
115const Zoir = std.zig.Zoir;
116const Writer = std.Io.Writer;