mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
std.zig.Ast: add printNode
This change adds a function to print a visual AST representation.
This commit is contained in:
parent
459f3b7ede
commit
be8f27e26b
1 changed files with 622 additions and 0 deletions
|
|
@ -4142,3 +4142,625 @@ test {
|
||||||
_ = Parse;
|
_ = Parse;
|
||||||
_ = Render;
|
_ = Render;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// printNode prints a visual representation of the AST in a human-readable
|
||||||
|
/// format, starting at `node`.
|
||||||
|
///
|
||||||
|
/// This funciton is expected to be used for debugging purposes.
|
||||||
|
pub fn printNode(tree: *const Ast, w: *Writer, node: Node.Index) Writer.Error!void {
|
||||||
|
var p: Printer = .{
|
||||||
|
.tree = tree,
|
||||||
|
.w = w,
|
||||||
|
};
|
||||||
|
try p.printNode(node);
|
||||||
|
try p.w.writeByte('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
const Printer = struct {
|
||||||
|
tree: *const Ast,
|
||||||
|
w: *Writer,
|
||||||
|
|
||||||
|
depth: usize = 0,
|
||||||
|
|
||||||
|
fn printNamedOptionalToken(p: *Printer, name: []const u8, token: OptionalTokenIndex) Writer.Error!void {
|
||||||
|
if (token.unwrap()) |t| {
|
||||||
|
try p.printNamedToken(name, t);
|
||||||
|
} else {
|
||||||
|
try p.w.print("{s} = .none", .{name});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn printNamedOptionalNode(p: *Printer, name: []const u8, node: Node.OptionalIndex) Writer.Error!void {
|
||||||
|
if (node.unwrap()) |t| {
|
||||||
|
try p.printNamedNode(name, t);
|
||||||
|
} else {
|
||||||
|
try p.w.print("{s} = .none", .{name});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn printNamedToken(p: *Printer, name: []const u8, token: TokenIndex) Writer.Error!void {
|
||||||
|
const tok = p.tree.tokens.get(token);
|
||||||
|
const loc = p.tree.tokenLocation(0, token);
|
||||||
|
if (p.tree.tokenTag(token).lexeme() == null) {
|
||||||
|
try p.w.print("{s} = .{s} {s} ({}:{})", .{ name, @tagName(tok.tag), p.tree.tokenSlice(token), loc.line + 1, loc.column + 1 });
|
||||||
|
} else {
|
||||||
|
try p.w.print("{s} = .{s} ({}:{})", .{ name, @tagName(tok.tag), loc.line + 1, loc.column + 1 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn printNamedNode(p: *Printer, name: []const u8, node: Node.Index) Writer.Error!void {
|
||||||
|
try p.w.print("{s} = ", .{name});
|
||||||
|
try p.printNode(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn indent(p: *const Printer) Writer.Error!void {
|
||||||
|
const tab: []const u8 = "\n" ++ (". " ** 256);
|
||||||
|
try p.w.writeAll(tab[0 .. 1 + @min(p.depth * 3, tab.len - 1)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn printNode(p: *Printer, node: Node.Index) Writer.Error!void {
|
||||||
|
try p.w.print("%{} ", .{@intFromEnum(node)});
|
||||||
|
try p.w.writeByte('{');
|
||||||
|
|
||||||
|
p.depth += 1;
|
||||||
|
|
||||||
|
try p.indent();
|
||||||
|
try p.w.print("tag = .{s}", .{@tagName(p.tree.nodeTag(node))});
|
||||||
|
try p.indent();
|
||||||
|
try p.printNamedToken("main_token", p.tree.nodeMainToken(node));
|
||||||
|
|
||||||
|
switch (p.tree.nodeTag(node)) {
|
||||||
|
.error_value,
|
||||||
|
.anyframe_literal,
|
||||||
|
.char_literal,
|
||||||
|
.number_literal,
|
||||||
|
.unreachable_literal,
|
||||||
|
.identifier,
|
||||||
|
.enum_literal,
|
||||||
|
.string_literal,
|
||||||
|
=> {}, // data field unused.
|
||||||
|
else => {
|
||||||
|
try p.indent();
|
||||||
|
try p.w.writeAll("data.");
|
||||||
|
try p.printData(node);
|
||||||
|
try p.indent();
|
||||||
|
try p.w.writeByte('}');
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
p.depth -= 1;
|
||||||
|
try p.indent();
|
||||||
|
try p.w.writeByte('}');
|
||||||
|
}
|
||||||
|
|
||||||
|
fn printData(p: *Printer, node: Node.Index) Writer.Error!void {
|
||||||
|
switch (p.tree.nodeTag(node)) {
|
||||||
|
.error_value,
|
||||||
|
.anyframe_literal,
|
||||||
|
.char_literal,
|
||||||
|
.number_literal,
|
||||||
|
.unreachable_literal,
|
||||||
|
.identifier,
|
||||||
|
.enum_literal,
|
||||||
|
.string_literal,
|
||||||
|
=> unreachable, // data field unused.
|
||||||
|
|
||||||
|
.root,
|
||||||
|
.array_init_dot,
|
||||||
|
.struct_init_dot,
|
||||||
|
.block,
|
||||||
|
.container_decl,
|
||||||
|
.tagged_union,
|
||||||
|
.builtin_call,
|
||||||
|
.array_init_dot_comma,
|
||||||
|
.struct_init_dot_comma,
|
||||||
|
.block_semicolon,
|
||||||
|
.container_decl_trailing,
|
||||||
|
.tagged_union_trailing,
|
||||||
|
.builtin_call_comma,
|
||||||
|
=> {
|
||||||
|
try p.w.writeAll("extra_range = {");
|
||||||
|
|
||||||
|
p.depth += 1;
|
||||||
|
defer p.depth -= 1;
|
||||||
|
try p.indent();
|
||||||
|
|
||||||
|
try p.printExtraNodes(p.tree.extraDataSlice(p.tree.nodeData(node).extra_range, Node.Index));
|
||||||
|
},
|
||||||
|
|
||||||
|
.bool_not,
|
||||||
|
.negation,
|
||||||
|
.bit_not,
|
||||||
|
.negation_wrap,
|
||||||
|
.address_of,
|
||||||
|
.@"try",
|
||||||
|
.optional_type,
|
||||||
|
.@"suspend",
|
||||||
|
.@"resume",
|
||||||
|
.@"nosuspend",
|
||||||
|
.@"comptime",
|
||||||
|
.@"defer",
|
||||||
|
.deref,
|
||||||
|
=> {
|
||||||
|
try p.w.writeAll("node = {");
|
||||||
|
|
||||||
|
p.depth += 1;
|
||||||
|
defer p.depth -= 1;
|
||||||
|
try p.indent();
|
||||||
|
|
||||||
|
try p.printNamedNode("node", p.tree.nodeData(node).node);
|
||||||
|
},
|
||||||
|
|
||||||
|
.@"return" => {
|
||||||
|
try p.w.writeAll("opt_node = {");
|
||||||
|
|
||||||
|
p.depth += 1;
|
||||||
|
defer p.depth -= 1;
|
||||||
|
try p.indent();
|
||||||
|
|
||||||
|
try p.printNamedOptionalNode("opt_node", p.tree.nodeData(node).opt_node);
|
||||||
|
},
|
||||||
|
|
||||||
|
.@"catch",
|
||||||
|
.equal_equal,
|
||||||
|
.bang_equal,
|
||||||
|
.less_than,
|
||||||
|
.greater_than,
|
||||||
|
.less_or_equal,
|
||||||
|
.greater_or_equal,
|
||||||
|
.assign_mul,
|
||||||
|
.assign_div,
|
||||||
|
.assign_mod,
|
||||||
|
.assign_add,
|
||||||
|
.assign_sub,
|
||||||
|
.assign_shl,
|
||||||
|
.assign_shl_sat,
|
||||||
|
.assign_shr,
|
||||||
|
.assign_bit_and,
|
||||||
|
.assign_bit_xor,
|
||||||
|
.assign_bit_or,
|
||||||
|
.assign_mul_wrap,
|
||||||
|
.assign_add_wrap,
|
||||||
|
.assign_sub_wrap,
|
||||||
|
.assign_mul_sat,
|
||||||
|
.assign_add_sat,
|
||||||
|
.assign_sub_sat,
|
||||||
|
.assign,
|
||||||
|
.merge_error_sets,
|
||||||
|
.mul,
|
||||||
|
.div,
|
||||||
|
.mod,
|
||||||
|
.array_mult,
|
||||||
|
.mul_wrap,
|
||||||
|
.mul_sat,
|
||||||
|
.add,
|
||||||
|
.sub,
|
||||||
|
.array_cat,
|
||||||
|
.add_wrap,
|
||||||
|
.sub_wrap,
|
||||||
|
.add_sat,
|
||||||
|
.sub_sat,
|
||||||
|
.shl,
|
||||||
|
.shl_sat,
|
||||||
|
.shr,
|
||||||
|
.bit_and,
|
||||||
|
.bit_xor,
|
||||||
|
.bit_or,
|
||||||
|
.@"orelse",
|
||||||
|
.bool_and,
|
||||||
|
.bool_or,
|
||||||
|
.error_union,
|
||||||
|
.if_simple,
|
||||||
|
.while_simple,
|
||||||
|
.for_simple,
|
||||||
|
.fn_decl,
|
||||||
|
.array_type,
|
||||||
|
.switch_range,
|
||||||
|
.array_access,
|
||||||
|
.array_init_one,
|
||||||
|
.container_field_align,
|
||||||
|
.slice_open,
|
||||||
|
.array_init_one_comma,
|
||||||
|
=> {
|
||||||
|
try p.w.writeAll("node_and_node = {");
|
||||||
|
|
||||||
|
p.depth += 1;
|
||||||
|
defer p.depth -= 1;
|
||||||
|
try p.indent();
|
||||||
|
|
||||||
|
const n = p.tree.nodeData(node).node_and_node;
|
||||||
|
try p.printNamedNode("node", n[0]);
|
||||||
|
try p.indent();
|
||||||
|
try p.printNamedNode("node", n[1]);
|
||||||
|
},
|
||||||
|
|
||||||
|
.multiline_string_literal, .error_set_decl => {
|
||||||
|
try p.w.writeAll("token_and_token = {");
|
||||||
|
|
||||||
|
p.depth += 1;
|
||||||
|
defer p.depth -= 1;
|
||||||
|
try p.indent();
|
||||||
|
|
||||||
|
const n = p.tree.nodeData(node).token_and_token;
|
||||||
|
try p.printNamedToken("token", n[0]);
|
||||||
|
try p.indent();
|
||||||
|
try p.printNamedToken("token", n[1]);
|
||||||
|
},
|
||||||
|
|
||||||
|
.anyframe_type => {
|
||||||
|
try p.w.writeAll("token_and_node = {");
|
||||||
|
|
||||||
|
p.depth += 1;
|
||||||
|
defer p.depth -= 1;
|
||||||
|
try p.indent();
|
||||||
|
|
||||||
|
const n = p.tree.nodeData(node).token_and_node;
|
||||||
|
try p.printNamedToken("token", n[0]);
|
||||||
|
try p.indent();
|
||||||
|
try p.printNamedNode("node", n[1]);
|
||||||
|
},
|
||||||
|
|
||||||
|
.field_access,
|
||||||
|
.unwrap_optional,
|
||||||
|
.asm_simple,
|
||||||
|
.grouped_expression,
|
||||||
|
.asm_input,
|
||||||
|
=> {
|
||||||
|
try p.w.writeAll("node_and_token = {");
|
||||||
|
|
||||||
|
p.depth += 1;
|
||||||
|
defer p.depth -= 1;
|
||||||
|
try p.indent();
|
||||||
|
|
||||||
|
const n = p.tree.nodeData(node).node_and_token;
|
||||||
|
try p.printNamedNode("node", n[0]);
|
||||||
|
try p.indent();
|
||||||
|
try p.printNamedToken("token", n[1]);
|
||||||
|
},
|
||||||
|
|
||||||
|
.switch_case_one,
|
||||||
|
.switch_case_inline_one,
|
||||||
|
.ptr_type_aligned,
|
||||||
|
.ptr_type_sentinel,
|
||||||
|
=> {
|
||||||
|
try p.w.writeAll("opt_node_and_node");
|
||||||
|
|
||||||
|
p.depth += 1;
|
||||||
|
defer p.depth -= 1;
|
||||||
|
try p.indent();
|
||||||
|
|
||||||
|
const n = p.tree.nodeData(node).opt_node_and_node;
|
||||||
|
try p.printNamedOptionalNode("opt_node", n[0]);
|
||||||
|
try p.indent();
|
||||||
|
try p.printNamedNode("node", n[1]);
|
||||||
|
},
|
||||||
|
|
||||||
|
.test_decl,
|
||||||
|
.@"errdefer",
|
||||||
|
=> {
|
||||||
|
try p.w.writeAll("opt_token_and_node = {");
|
||||||
|
|
||||||
|
p.depth += 1;
|
||||||
|
defer p.depth -= 1;
|
||||||
|
try p.indent();
|
||||||
|
|
||||||
|
const n = p.tree.nodeData(node).opt_token_and_node;
|
||||||
|
try p.printNamedOptionalToken("opt_tok", n[0]);
|
||||||
|
try p.indent();
|
||||||
|
try p.printNamedNode("node", n[1]);
|
||||||
|
},
|
||||||
|
|
||||||
|
.@"continue", .@"break" => {
|
||||||
|
try p.w.writeAll("opt_token_and_opt_node = {");
|
||||||
|
|
||||||
|
p.depth += 1;
|
||||||
|
defer p.depth -= 1;
|
||||||
|
try p.indent();
|
||||||
|
|
||||||
|
const n = p.tree.nodeData(node).opt_token_and_opt_node;
|
||||||
|
try p.printNamedOptionalToken("opt_token", n[0]);
|
||||||
|
try p.indent();
|
||||||
|
try p.printNamedOptionalNode("opt_node", n[1]);
|
||||||
|
},
|
||||||
|
|
||||||
|
.for_range,
|
||||||
|
.call_one,
|
||||||
|
.aligned_var_decl,
|
||||||
|
.container_field_init,
|
||||||
|
.call_one_comma,
|
||||||
|
.struct_init_one_comma,
|
||||||
|
.struct_init_one,
|
||||||
|
=> {
|
||||||
|
try p.w.writeAll("node_and_opt_node = {");
|
||||||
|
|
||||||
|
p.depth += 1;
|
||||||
|
defer p.depth -= 1;
|
||||||
|
try p.indent();
|
||||||
|
|
||||||
|
const n = p.tree.nodeData(node).node_and_opt_node;
|
||||||
|
try p.printNamedNode("node", n[0]);
|
||||||
|
try p.indent();
|
||||||
|
try p.printNamedOptionalNode("opt_node", n[1]);
|
||||||
|
},
|
||||||
|
|
||||||
|
.tagged_union_two_trailing,
|
||||||
|
.container_decl_two_trailing,
|
||||||
|
.struct_init_dot_two_comma,
|
||||||
|
.block_two_semicolon,
|
||||||
|
.builtin_call_two_comma,
|
||||||
|
.array_init_dot_two_comma,
|
||||||
|
.container_decl_two,
|
||||||
|
.struct_init_dot_two,
|
||||||
|
.builtin_call_two,
|
||||||
|
.block_two,
|
||||||
|
.tagged_union_two,
|
||||||
|
.array_init_dot_two,
|
||||||
|
.simple_var_decl,
|
||||||
|
.fn_proto_simple,
|
||||||
|
=> {
|
||||||
|
try p.w.writeAll("opt_token_and_opt_node = {");
|
||||||
|
|
||||||
|
p.depth += 1;
|
||||||
|
defer p.depth -= 1;
|
||||||
|
try p.indent();
|
||||||
|
|
||||||
|
const n = p.tree.nodeData(node).opt_node_and_opt_node;
|
||||||
|
try p.printNamedOptionalNode("opt_node", n[0]);
|
||||||
|
try p.indent();
|
||||||
|
try p.printNamedOptionalNode("opt_node", n[1]);
|
||||||
|
},
|
||||||
|
|
||||||
|
.asm_output => {
|
||||||
|
try p.w.writeAll("opt_node_and_token = {");
|
||||||
|
|
||||||
|
p.depth += 1;
|
||||||
|
defer p.depth -= 1;
|
||||||
|
try p.indent();
|
||||||
|
|
||||||
|
const n = p.tree.nodeData(node).opt_node_and_token;
|
||||||
|
try p.printNamedOptionalNode("opt_node", n[0]);
|
||||||
|
try p.indent();
|
||||||
|
try p.printNamedToken("token", n[1]);
|
||||||
|
},
|
||||||
|
|
||||||
|
.switch_case,
|
||||||
|
.switch_case_inline,
|
||||||
|
=> {
|
||||||
|
try p.w.writeAll("extra_and_node = {");
|
||||||
|
|
||||||
|
p.depth += 1;
|
||||||
|
defer p.depth -= 1;
|
||||||
|
try p.indent();
|
||||||
|
|
||||||
|
const n = p.tree.nodeData(node).extra_and_node;
|
||||||
|
try p.printExtraNodes(p.tree.extraDataSlice(p.tree.extraData(n[0], Node.SubRange), Node.Index));
|
||||||
|
try p.indent();
|
||||||
|
try p.printNamedNode("node", n[1]);
|
||||||
|
},
|
||||||
|
|
||||||
|
.assign_destructure => {
|
||||||
|
try p.w.writeAll("extra_and_node = {");
|
||||||
|
|
||||||
|
p.depth += 1;
|
||||||
|
defer p.depth -= 1;
|
||||||
|
try p.indent();
|
||||||
|
|
||||||
|
const n = p.tree.nodeData(node).extra_and_node;
|
||||||
|
const variable_count = p.tree.extra_data[@intFromEnum(n[0])];
|
||||||
|
try p.printExtraNodes(p.tree.extraDataSliceWithLen(@enumFromInt(@intFromEnum(n[0]) + 1), variable_count, Node.Index));
|
||||||
|
try p.indent();
|
||||||
|
try p.printNamedNode("node", n[1]);
|
||||||
|
},
|
||||||
|
|
||||||
|
.ptr_type => {
|
||||||
|
try p.printExtraAndNode(node, Node.PtrType);
|
||||||
|
},
|
||||||
|
|
||||||
|
.ptr_type_bit_range => {
|
||||||
|
try p.printExtraAndNode(node, Node.PtrTypeBitRange);
|
||||||
|
},
|
||||||
|
|
||||||
|
.call,
|
||||||
|
.call_comma,
|
||||||
|
.tagged_union_enum_tag,
|
||||||
|
.tagged_union_enum_tag_trailing,
|
||||||
|
.@"switch",
|
||||||
|
.container_decl_arg,
|
||||||
|
.asm_legacy,
|
||||||
|
.@"asm",
|
||||||
|
.array_init,
|
||||||
|
.struct_init,
|
||||||
|
.array_init_comma,
|
||||||
|
.struct_init_comma,
|
||||||
|
.container_decl_arg_trailing,
|
||||||
|
.switch_comma,
|
||||||
|
=> {
|
||||||
|
try p.w.writeAll("node_and_extra = {");
|
||||||
|
|
||||||
|
p.depth += 1;
|
||||||
|
defer p.depth -= 1;
|
||||||
|
try p.indent();
|
||||||
|
|
||||||
|
const n = p.tree.nodeData(node).node_and_extra;
|
||||||
|
try p.printNode(n[0]);
|
||||||
|
try p.printExtraNodes(p.tree.extraDataSlice(p.tree.extraData(n[1], Node.SubRange), Node.Index));
|
||||||
|
},
|
||||||
|
.container_field => {
|
||||||
|
try p.printNodeAndExtra(node, Node.ContainerField);
|
||||||
|
},
|
||||||
|
.slice => {
|
||||||
|
try p.printNodeAndExtra(node, Node.Slice);
|
||||||
|
},
|
||||||
|
.slice_sentinel => {
|
||||||
|
try p.printNodeAndExtra(node, Node.SliceSentinel);
|
||||||
|
},
|
||||||
|
.while_cont => {
|
||||||
|
try p.printNodeAndExtra(node, Node.WhileCont);
|
||||||
|
},
|
||||||
|
.@"while" => {
|
||||||
|
try p.printNodeAndExtra(node, Node.While);
|
||||||
|
},
|
||||||
|
.@"if" => {
|
||||||
|
try p.printNodeAndExtra(node, Node.If);
|
||||||
|
},
|
||||||
|
.array_type_sentinel => {
|
||||||
|
try p.printNodeAndExtra(node, Node.ArrayTypeSentinel);
|
||||||
|
},
|
||||||
|
|
||||||
|
.fn_proto_multi => {
|
||||||
|
try p.w.writeAll("extra_and_opt_node = {");
|
||||||
|
|
||||||
|
p.depth += 1;
|
||||||
|
defer p.depth -= 1;
|
||||||
|
try p.indent();
|
||||||
|
|
||||||
|
const n = p.tree.nodeData(node).extra_and_opt_node;
|
||||||
|
try p.printExtraNodes(p.tree.extraDataSlice(p.tree.extraData(n[0], Node.SubRange), Node.Index));
|
||||||
|
try p.indent();
|
||||||
|
try p.printNamedOptionalNode("opt_node", n[1]);
|
||||||
|
},
|
||||||
|
|
||||||
|
.fn_proto => {
|
||||||
|
try p.w.writeAll("extra_and_opt_node = {");
|
||||||
|
|
||||||
|
p.depth += 1;
|
||||||
|
defer p.depth -= 1;
|
||||||
|
try p.indent();
|
||||||
|
|
||||||
|
const n = p.tree.nodeData(node).extra_and_opt_node;
|
||||||
|
|
||||||
|
try p.w.writeAll("extra = {");
|
||||||
|
p.depth += 1;
|
||||||
|
|
||||||
|
const d = p.tree.extraData(n[0], Node.FnProto);
|
||||||
|
const params = p.tree.extraDataSlice(.{ .start = d.params_start, .end = d.params_end }, Node.Index);
|
||||||
|
|
||||||
|
for (params, 0..) |ni, i| {
|
||||||
|
try p.indent();
|
||||||
|
try p.w.print("[{}] = ", .{i});
|
||||||
|
try p.printNode(ni);
|
||||||
|
}
|
||||||
|
|
||||||
|
try p.indent();
|
||||||
|
try p.printNamedOptionalNode("align_expr", d.align_expr);
|
||||||
|
try p.indent();
|
||||||
|
try p.printNamedOptionalNode("addrspace_expr", d.addrspace_expr);
|
||||||
|
try p.indent();
|
||||||
|
try p.printNamedOptionalNode("section_expr", d.section_expr);
|
||||||
|
try p.indent();
|
||||||
|
try p.printNamedOptionalNode("callconv_expr", d.callconv_expr);
|
||||||
|
|
||||||
|
p.depth -= 1;
|
||||||
|
try p.indent();
|
||||||
|
try p.w.writeByte('}');
|
||||||
|
|
||||||
|
try p.indent();
|
||||||
|
try p.printNamedOptionalNode("opt_node", n[1]);
|
||||||
|
},
|
||||||
|
|
||||||
|
.fn_proto_one => {
|
||||||
|
try p.printExtraAndOptNode(node, Node.FnProtoOne);
|
||||||
|
},
|
||||||
|
.global_var_decl => {
|
||||||
|
try p.printExtraAndOptNode(node, Node.GlobalVarDecl);
|
||||||
|
},
|
||||||
|
.local_var_decl => {
|
||||||
|
try p.printExtraAndOptNode(node, Node.LocalVarDecl);
|
||||||
|
},
|
||||||
|
|
||||||
|
.@"for" => {
|
||||||
|
try p.w.writeAll("for = {");
|
||||||
|
|
||||||
|
p.depth += 1;
|
||||||
|
defer p.depth -= 1;
|
||||||
|
try p.indent();
|
||||||
|
|
||||||
|
const n = p.tree.nodeData(node).@"for";
|
||||||
|
try p.printExtraNodes(p.tree.extraDataSliceWithLen(n[0], n[1].inputs, Node.Index));
|
||||||
|
const else_expr: Node.OptionalIndex = if (n[1].has_else) @enumFromInt(p.tree.extra_data[@intFromEnum(n[0]) + n[1].inputs + 1]) else .none;
|
||||||
|
try p.indent();
|
||||||
|
try p.printNamedOptionalNode("else_expr", else_expr);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn printExtraNodes(p: *Printer, nodes: []const Node.Index) Writer.Error!void {
|
||||||
|
try p.w.writeAll("extra = {");
|
||||||
|
|
||||||
|
p.depth += 1;
|
||||||
|
for (nodes, 0..) |ni, i| {
|
||||||
|
try p.indent();
|
||||||
|
try p.w.print("[{}] = ", .{i});
|
||||||
|
try p.printNode(ni);
|
||||||
|
}
|
||||||
|
p.depth -= 1;
|
||||||
|
|
||||||
|
try p.indent();
|
||||||
|
try p.w.writeByte('}');
|
||||||
|
}
|
||||||
|
|
||||||
|
fn printExtraAndNode(p: *Printer, node: Node.Index, comptime T: type) Writer.Error!void {
|
||||||
|
try p.w.writeAll("extra_and_node = {");
|
||||||
|
|
||||||
|
p.depth += 1;
|
||||||
|
defer p.depth -= 1;
|
||||||
|
try p.indent();
|
||||||
|
|
||||||
|
const n = p.tree.nodeData(node).extra_and_node;
|
||||||
|
try p.printExtraData(n[0], T);
|
||||||
|
try p.indent();
|
||||||
|
try p.printNamedNode("node", n[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn printExtraAndOptNode(p: *Printer, node: Node.Index, comptime T: type) Writer.Error!void {
|
||||||
|
try p.w.writeAll("extra_and_opt_node = {");
|
||||||
|
|
||||||
|
p.depth += 1;
|
||||||
|
defer p.depth -= 1;
|
||||||
|
try p.indent();
|
||||||
|
|
||||||
|
const n = p.tree.nodeData(node).extra_and_opt_node;
|
||||||
|
try p.printExtraData(n[0], T);
|
||||||
|
try p.indent();
|
||||||
|
try p.printNamedOptionalNode("opt_node", n[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn printNodeAndExtra(p: *Printer, node: Node.Index, comptime T: type) Writer.Error!void {
|
||||||
|
try p.w.writeAll("node_and_extra = {");
|
||||||
|
|
||||||
|
p.depth += 1;
|
||||||
|
defer p.depth -= 1;
|
||||||
|
try p.indent();
|
||||||
|
|
||||||
|
const n = p.tree.nodeData(node).node_and_extra;
|
||||||
|
try p.printNamedNode("node", n[0]);
|
||||||
|
try p.indent();
|
||||||
|
try p.printExtraData(n[1], T);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn printExtraData(p: *Printer, index: ExtraIndex, comptime T: type) Writer.Error!void {
|
||||||
|
try p.w.writeAll("extra = {");
|
||||||
|
|
||||||
|
p.depth += 1;
|
||||||
|
const d = p.tree.extraData(index, T);
|
||||||
|
inline for (std.meta.fields(T)) |field| {
|
||||||
|
const f = @field(d, field.name);
|
||||||
|
switch (field.type) {
|
||||||
|
Node.OptionalIndex => try p.printNamedOptionalNode(field.name, f),
|
||||||
|
TokenIndex => try p.printNamedToken(field.name, f),
|
||||||
|
OptionalTokenIndex => try p.printNamedOptionalToken(field.name, f),
|
||||||
|
Node.Index => try p.printNamedNode(field.name, f),
|
||||||
|
ExtraIndex => @compileError("unable to handle ExtraIndex"),
|
||||||
|
else => @compileError("unexpected field type: " ++ @typeName(field.type)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.depth -= 1;
|
||||||
|
|
||||||
|
try p.indent();
|
||||||
|
try p.w.writeByte('}');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
test {
|
||||||
|
_ = &printNode;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue