struct FnProto [src]
Fields
visib_token: ?TokenIndex
extern_export_inline_token: ?TokenIndex
lib_name: ?TokenIndex
name_token: ?TokenIndex
lparen: TokenIndex
ast: Components
Members
- Components (struct)
- firstToken (Function)
- iterate (Function)
- Iterator (struct)
- Param (struct)
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,
};
}
}