struct FnProto [src]

Fields

visib_token: ?TokenIndex
extern_export_inline_token: ?TokenIndex
lib_name: ?TokenIndex
name_token: ?TokenIndex
lparen: TokenIndex
ast: Components

Members

Source

pub const FnProto = struct { visib_token: ?TokenIndex, extern_export_inline_token: ?TokenIndex, lib_name: ?TokenIndex, name_token: ?TokenIndex, lparen: TokenIndex, ast: Components, pub const Components = struct { proto_node: Node.Index, fn_token: TokenIndex, return_type: Node.OptionalIndex, params: []const Node.Index, align_expr: Node.OptionalIndex, addrspace_expr: Node.OptionalIndex, section_expr: Node.OptionalIndex, callconv_expr: Node.OptionalIndex, }; pub const Param = struct { first_doc_comment: ?TokenIndex, name_token: ?TokenIndex, comptime_noalias: ?TokenIndex, anytype_ellipsis3: ?TokenIndex, type_expr: ?Node.Index, }; pub fn firstToken(fn_proto: FnProto) TokenIndex { return fn_proto.visib_token orelse fn_proto.extern_export_inline_token orelse fn_proto.ast.fn_token; } /// Abstracts over the fact that anytype and ... are not included /// in the params slice, since they are simple identifiers and /// not sub-expressions. pub const Iterator = struct { tree: *const Ast, fn_proto: *const FnProto, param_i: usize, tok_i: TokenIndex, tok_flag: bool, pub fn next(it: *Iterator) ?Param { const tree = it.tree; while (true) { var first_doc_comment: ?TokenIndex = null; var comptime_noalias: ?TokenIndex = null; var name_token: ?TokenIndex = null; if (!it.tok_flag) { if (it.param_i >= it.fn_proto.ast.params.len) { return null; } const param_type = it.fn_proto.ast.params[it.param_i]; var tok_i = tree.firstToken(param_type) - 1; while (true) : (tok_i -= 1) switch (tree.tokenTag(tok_i)) { .colon => continue, .identifier => name_token = tok_i, .doc_comment => first_doc_comment = tok_i, .keyword_comptime, .keyword_noalias => comptime_noalias = tok_i, else => break, }; it.param_i += 1; it.tok_i = tree.lastToken(param_type) + 1; // Look for anytype and ... params afterwards. if (tree.tokenTag(it.tok_i) == .comma) { it.tok_i += 1; } it.tok_flag = true; return Param{ .first_doc_comment = first_doc_comment, .comptime_noalias = comptime_noalias, .name_token = name_token, .anytype_ellipsis3 = null, .type_expr = param_type, }; } if (tree.tokenTag(it.tok_i) == .comma) { it.tok_i += 1; } if (tree.tokenTag(it.tok_i) == .r_paren) { return null; } if (tree.tokenTag(it.tok_i) == .doc_comment) { first_doc_comment = it.tok_i; while (tree.tokenTag(it.tok_i) == .doc_comment) { it.tok_i += 1; } } switch (tree.tokenTag(it.tok_i)) { .ellipsis3 => { it.tok_flag = false; // Next iteration should return null. return Param{ .first_doc_comment = first_doc_comment, .comptime_noalias = null, .name_token = null, .anytype_ellipsis3 = it.tok_i, .type_expr = null, }; }, .keyword_noalias, .keyword_comptime => { comptime_noalias = it.tok_i; it.tok_i += 1; }, else => {}, } if (tree.tokenTag(it.tok_i) == .identifier and tree.tokenTag(it.tok_i + 1) == .colon) { name_token = it.tok_i; it.tok_i += 2; } if (tree.tokenTag(it.tok_i) == .keyword_anytype) { it.tok_i += 1; return Param{ .first_doc_comment = first_doc_comment, .comptime_noalias = comptime_noalias, .name_token = name_token, .anytype_ellipsis3 = it.tok_i - 1, .type_expr = null, }; } it.tok_flag = false; } } }; pub fn iterate(fn_proto: *const FnProto, tree: *const Ast) Iterator { return .{ .tree = tree, .fn_proto = fn_proto, .param_i = 0, .tok_i = fn_proto.lparen + 1, .tok_flag = true, }; } }