feature. See also
. The project being documented here (as the example) is the Zig library itself.
ast.renderFunc
fn renderFunc(c: *Context, node: Node) !NodeIndex
File
Code
fn renderFunc(c: *Context, node: Node) !NodeIndex {
const payload = node.castTag(.func).?.data;
if (payload.is_pub) _ = try c.addToken(.keyword_pub, "pub");
if (payload.is_extern) _ = try c.addToken(.keyword_extern, "extern");
if (payload.is_export) _ = try c.addToken(.keyword_export, "export");
if (payload.is_inline) _ = try c.addToken(.keyword_inline, "inline");
const fn_token = try c.addToken(.keyword_fn, "fn");
if (payload.name) |some| _ = try c.addIdentifier(some);
var params = try renderParams(c, payload.params, payload.is_var_args);
defer params.deinit(c.gpa);
var span: NodeSubRange = undefined;
if (params.items.len > 1) span = try c.listToSpan(params.items);
const align_expr_opt = if (payload.alignment) |some| blk: {
_ = try c.addToken(.keyword_align, "align");
_ = try c.addToken(.l_paren, "(");
const res = try c.addNode(.{
.tag = .number_literal,
.main_token = try c.addTokenFmt(.number_literal, "{d}", .{some}),
.data = undefined,
});
_ = try c.addToken(.r_paren, ")");
break :blk res;
} else null;
const section_expr_opt = if (payload.linksection_string) |some| blk: {
_ = try c.addToken(.keyword_linksection, "linksection");
_ = try c.addToken(.l_paren, "(");
const res = try c.addNode(.{
.tag = .string_literal,
.main_token = try c.addTokenFmt(.string_literal, "\"{f}\"", .{std.zig.fmtString(some)}),
.data = undefined,
});
_ = try c.addToken(.r_paren, ")");
break :blk res;
} else null;
const callconv_expr_opt = if (payload.explicit_callconv) |some| blk: {
_ = try c.addToken(.keyword_callconv, "callconv");
_ = try c.addToken(.l_paren, "(");
const cc_node = switch (some) {
.c => cc_node: {
_ = try c.addToken(.period, ".");
break :cc_node try c.addNode(.{
.tag = .enum_literal,
.main_token = try c.addToken(.identifier, "c"),
.data = undefined,
});
},
.x86_64_sysv,
.x86_64_win,
.x86_stdcall,
.x86_fastcall,
.x86_thiscall,
.x86_vectorcall,
.x86_regcall,
.aarch64_vfabi,
.aarch64_sve_pcs,
.arm_aapcs,
.arm_aapcs_vfp,
.m68k_rtd,
.riscv_vector,
=> cc_node: {
_ = try c.addToken(.period, ".");
const outer_lbrace = try c.addToken(.l_brace, "{");
_ = try c.addToken(.period, ".");
_ = try c.addToken(.identifier, @tagName(some));
_ = try c.addToken(.equal, "=");
_ = try c.addToken(.period, ".");
const inner_lbrace = try c.addToken(.l_brace, "{");
_ = try c.addToken(.r_brace, "}");
_ = try c.addToken(.r_brace, "}");
break :cc_node try c.addNode(.{
.tag = .struct_init_dot_two,
.main_token = outer_lbrace,
.data = .{ .opt_node_and_opt_node = .{
(try c.addNode(.{
.tag = .struct_init_dot_two,
.main_token = inner_lbrace,
.data = .{ .opt_node_and_opt_node = .{
.none, .none,
} },
})).toOptional(),
.none,
} },
});
},
};
_ = try c.addToken(.r_paren, ")");
break :blk cc_node;
} else null;
const return_type_expr = try renderNode(c, payload.return_type);
const fn_proto = try blk: {
if (align_expr_opt == null and section_expr_opt == null and callconv_expr_opt == null) {
if (params.items.len < 2)
break :blk c.addNode(.{
.tag = .fn_proto_simple,
.main_token = fn_token,
.data = .{ .opt_node_and_opt_node = .{
if (params.items.len == 1) params.items[0].toOptional() else .none,
return_type_expr.toOptional(),
} },
})
else
break :blk c.addNode(.{
.tag = .fn_proto_multi,
.main_token = fn_token,
.data = .{ .extra_and_opt_node = .{
try c.addExtra(span),
return_type_expr.toOptional(),
} },
});
}
if (params.items.len < 2)
break :blk c.addNode(.{
.tag = .fn_proto_one,
.main_token = fn_token,
.data = .{
.extra_and_opt_node = .{
try c.addExtra(std.zig.Ast.Node.FnProtoOne{
.param = if (params.items.len == 1) params.items[0].toOptional() else .none,
.align_expr = .fromOptional(align_expr_opt),
.addrspace_expr = .none,
.section_expr = .fromOptional(section_expr_opt),
.callconv_expr = .fromOptional(callconv_expr_opt),
}),
return_type_expr.toOptional(),
},
},
})
else
break :blk c.addNode(.{
.tag = .fn_proto,
.main_token = fn_token,
.data = .{
.extra_and_opt_node = .{
try c.addExtra(std.zig.Ast.Node.FnProto{
.params_start = span.start,
.params_end = span.end,
.align_expr = .fromOptional(align_expr_opt),
.addrspace_expr = .none,
.section_expr = .fromOptional(section_expr_opt),
.callconv_expr = .fromOptional(callconv_expr_opt),
}),
return_type_expr.toOptional(),
},
},
});
};
const payload_body = payload.body orelse {
if (payload.is_extern) {
_ = try c.addToken(.semicolon, ";");
}
return fn_proto;
};
const body = try renderNode(c, payload_body);
return c.addNode(.{
.tag = .fn_decl,
.main_token = fn_token,
.data = .{ .node_and_node = .{
fn_proto, body,
} },
});
}