| 1 | pub const Error = error{ WriteFailed, OutOfMemory }; |
| 2 | |
| 3 | pub 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".field_types) |f_type| { |
| 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 | |
| 45 | const 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} = ", .{@backingInt(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 | |
| 112 | const std = @import("std"); |
| 113 | const assert = std.debug.assert; |
| 114 | const Allocator = std.mem.Allocator; |
| 115 | const Zoir = std.zig.Zoir; |
| 116 | const Writer = std.Io.Writer; |