struct Node [src]
Fields
tag: Tag
main_token: TokenIndex
data: Data
Members
- ArrayTypeSentinel (struct)
- Asm (struct)
- ContainerField (struct)
- Data (union)
- FnProto (struct)
- FnProtoOne (struct)
- For (struct)
- GlobalVarDecl (struct)
- If (struct)
- Index (enum)
- LocalVarDecl (struct)
- Offset (enum)
- OptionalIndex (enum)
- OptionalOffset (enum)
- PtrType (struct)
- PtrTypeBitRange (struct)
- Slice (struct)
- SliceSentinel (struct)
- SubRange (struct)
- Tag (enum)
- While (struct)
- WhileCont (struct)
Source
pub const Node = struct {
tag: Tag,
main_token: TokenIndex,
data: Data,
/// Index into `nodes`.
pub const Index = enum(u32) {
root = 0,
_,
pub fn toOptional(i: Index) OptionalIndex {
const result: OptionalIndex = @enumFromInt(@intFromEnum(i));
assert(result != .none);
return result;
}
pub fn toOffset(base: Index, destination: Index) Offset {
const base_i64: i64 = @intFromEnum(base);
const destination_i64: i64 = @intFromEnum(destination);
return @enumFromInt(destination_i64 - base_i64);
}
};
/// Index into `nodes`, or null.
pub const OptionalIndex = enum(u32) {
root = 0,
none = std.math.maxInt(u32),
_,
pub fn unwrap(oi: OptionalIndex) ?Index {
return if (oi == .none) null else @enumFromInt(@intFromEnum(oi));
}
pub fn fromOptional(oi: ?Index) OptionalIndex {
return if (oi) |i| i.toOptional() else .none;
}
};
/// A relative node index.
pub const Offset = enum(i32) {
zero = 0,
_,
pub fn toOptional(o: Offset) OptionalOffset {
const result: OptionalOffset = @enumFromInt(@intFromEnum(o));
assert(result != .none);
return result;
}
pub fn toAbsolute(offset: Offset, base: Index) Index {
return @enumFromInt(@as(i64, @intFromEnum(base)) + @intFromEnum(offset));
}
};
/// A relative node index, or null.
pub const OptionalOffset = enum(i32) {
none = std.math.maxInt(i32),
_,
pub fn unwrap(oo: OptionalOffset) ?Offset {
return if (oo == .none) null else @enumFromInt(@intFromEnum(oo));
}
};
comptime {
// Goal is to keep this under one byte for efficiency.
assert(@sizeOf(Tag) == 1);
if (!std.debug.runtime_safety) {
assert(@sizeOf(Data) == 8);
}
}
/// The FooComma/FooSemicolon variants exist to ease the implementation of
/// `Ast.lastToken()`
pub const Tag = enum {
/// The root node which is guaranteed to be at `Node.Index.root`.
/// The meaning of the `data` field depends on whether it is a `.zig` or
/// `.zon` file.
///
/// The `main_token` field is the first token for the source file.
root,
/// `usingnamespace expr;`.
///
/// The `data` field is a `.node` to expr.
///
/// The `main_token` field is the `usingnamespace` token.
@"usingnamespace",
/// `test {}`,
/// `test "name" {}`,
/// `test identifier {}`.
///
/// The `data` field is a `.opt_token_and_node`:
/// 1. a `OptionalTokenIndex` to the test name token (must be string literal or identifier), if any.
/// 2. a `Node.Index` to the block.
///
/// The `main_token` field is the `test` token.
test_decl,
/// The `data` field is a `.extra_and_opt_node`:
/// 1. a `ExtraIndex` to `GlobalVarDecl`.
/// 2. a `Node.OptionalIndex` to the initialization expression.
///
/// The `main_token` field is the `var` or `const` token.
///
/// The initialization expression can't be `.none` unless it is part of
/// a `assign_destructure` node or a parsing error occured.
global_var_decl,
/// `var a: b align(c) = d`.
/// `const main_token: type_node align(align_node) = init_expr`.
///
/// The `data` field is a `.extra_and_opt_node`:
/// 1. a `ExtraIndex` to `LocalVarDecl`.
/// 2. a `Node.OptionalIndex` to the initialization expression-
///
/// The `main_token` field is the `var` or `const` token.
///
/// The initialization expression can't be `.none` unless it is part of
/// a `assign_destructure` node or a parsing error occured.
local_var_decl,
/// `var a: b = c`.
/// `const name_token: type_expr = init_expr`.
/// Can be local or global.
///
/// The `data` field is a `.opt_node_and_opt_node`:
/// 1. a `Node.OptionalIndex` to the type expression, if any.
/// 2. a `Node.OptionalIndex` to the initialization expression.
///
/// The `main_token` field is the `var` or `const` token.
///
/// The initialization expression can't be `.none` unless it is part of
/// a `assign_destructure` node or a parsing error occured.
simple_var_decl,
/// `var a align(b) = c`.
/// `const name_token align(align_expr) = init_expr`.
/// Can be local or global.
///
/// The `data` field is a `.node_and_opt_node`:
/// 1. a `Node.Index` to the alignment expression.
/// 2. a `Node.OptionalIndex` to the initialization expression.
///
/// The `main_token` field is the `var` or `const` token.
///
/// The initialization expression can't be `.none` unless it is part of
/// a `assign_destructure` node or a parsing error occured.
aligned_var_decl,
/// `errdefer expr`,
/// `errdefer |payload| expr`.
///
/// The `data` field is a `.opt_token_and_node`:
/// 1. a `OptionalTokenIndex` to the payload identifier, if any.
/// 2. a `Node.Index` to the deferred expression.
///
/// The `main_token` field is the `errdefer` token.
@"errdefer",
/// `defer expr`.
///
/// The `data` field is a `.node` to the deferred expression.
///
/// The `main_token` field is the `defer`.
@"defer",
/// `lhs catch rhs`,
/// `lhs catch |err| rhs`.
///
/// The `main_token` field is the `catch` token.
///
/// The error payload is determined by looking at the next token after
/// the `catch` token.
@"catch",
/// `lhs.a`.
///
/// The `data` field is a `.node_and_token`:
/// 1. a `Node.Index` to the left side of the field access.
/// 2. a `TokenIndex` to the field name identifier.
///
/// The `main_token` field is the `.` token.
field_access,
/// `lhs.?`.
///
/// The `data` field is a `.node_and_token`:
/// 1. a `Node.Index` to the left side of the optional unwrap.
/// 2. a `TokenIndex` to the `?` token.
///
/// The `main_token` field is the `.` token.
unwrap_optional,
/// `lhs == rhs`. The `main_token` field is the `==` token.
equal_equal,
/// `lhs != rhs`. The `main_token` field is the `!=` token.
bang_equal,
/// `lhs < rhs`. The `main_token` field is the `<` token.
less_than,
/// `lhs > rhs`. The `main_token` field is the `>` token.
greater_than,
/// `lhs <= rhs`. The `main_token` field is the `<=` token.
less_or_equal,
/// `lhs >= rhs`. The `main_token` field is the `>=` token.
greater_or_equal,
/// `lhs *= rhs`. The `main_token` field is the `*=` token.
assign_mul,
/// `lhs /= rhs`. The `main_token` field is the `/=` token.
assign_div,
/// `lhs %= rhs`. The `main_token` field is the `%=` token.
assign_mod,
/// `lhs += rhs`. The `main_token` field is the `+=` token.
assign_add,
/// `lhs -= rhs`. The `main_token` field is the `-=` token.
assign_sub,
/// `lhs <<= rhs`. The `main_token` field is the `<<=` token.
assign_shl,
/// `lhs <<|= rhs`. The `main_token` field is the `<<|=` token.
assign_shl_sat,
/// `lhs >>= rhs`. The `main_token` field is the `>>=` token.
assign_shr,
/// `lhs &= rhs`. The `main_token` field is the `&=` token.
assign_bit_and,
/// `lhs ^= rhs`. The `main_token` field is the `^=` token.
assign_bit_xor,
/// `lhs |= rhs`. The `main_token` field is the `|=` token.
assign_bit_or,
/// `lhs *%= rhs`. The `main_token` field is the `*%=` token.
assign_mul_wrap,
/// `lhs +%= rhs`. The `main_token` field is the `+%=` token.
assign_add_wrap,
/// `lhs -%= rhs`. The `main_token` field is the `-%=` token.
assign_sub_wrap,
/// `lhs *|= rhs`. The `main_token` field is the `*%=` token.
assign_mul_sat,
/// `lhs +|= rhs`. The `main_token` field is the `+|=` token.
assign_add_sat,
/// `lhs -|= rhs`. The `main_token` field is the `-|=` token.
assign_sub_sat,
/// `lhs = rhs`. The `main_token` field is the `=` token.
assign,
/// `a, b, ... = rhs`.
///
/// The `data` field is a `.extra_and_node`:
/// 1. a `ExtraIndex`. Further explained below.
/// 2. a `Node.Index` to the initialization expression.
///
/// The `main_token` field is the `=` token.
///
/// The `ExtraIndex` stores the following data:
/// ```
/// elem_count: u32,
/// variables: [elem_count]Node.Index,
/// ```
///
/// Each node in `variables` has one of the following tags:
/// - `global_var_decl`
/// - `local_var_decl`
/// - `simple_var_decl`
/// - `aligned_var_decl`
/// - Any expression node
///
/// The first 4 tags correspond to a `var` or `const` lhs node (note
/// that their initialization expression is always `.none`).
/// An expression node corresponds to a standard assignment LHS (which
/// must be evaluated as an lvalue). There may be a preceding
/// `comptime` token, which does not create a corresponding `comptime`
/// node so must be manually detected.
assign_destructure,
/// `lhs || rhs`. The `main_token` field is the `||` token.
merge_error_sets,
/// `lhs * rhs`. The `main_token` field is the `*` token.
mul,
/// `lhs / rhs`. The `main_token` field is the `/` token.
div,
/// `lhs % rhs`. The `main_token` field is the `%` token.
mod,
/// `lhs ** rhs`. The `main_token` field is the `**` token.
array_mult,
/// `lhs *% rhs`. The `main_token` field is the `*%` token.
mul_wrap,
/// `lhs *| rhs`. The `main_token` field is the `*|` token.
mul_sat,
/// `lhs + rhs`. The `main_token` field is the `+` token.
add,
/// `lhs - rhs`. The `main_token` field is the `-` token.
sub,
/// `lhs ++ rhs`. The `main_token` field is the `++` token.
array_cat,
/// `lhs +% rhs`. The `main_token` field is the `+%` token.
add_wrap,
/// `lhs -% rhs`. The `main_token` field is the `-%` token.
sub_wrap,
/// `lhs +| rhs`. The `main_token` field is the `+|` token.
add_sat,
/// `lhs -| rhs`. The `main_token` field is the `-|` token.
sub_sat,
/// `lhs << rhs`. The `main_token` field is the `<<` token.
shl,
/// `lhs <<| rhs`. The `main_token` field is the `<<|` token.
shl_sat,
/// `lhs >> rhs`. The `main_token` field is the `>>` token.
shr,
/// `lhs & rhs`. The `main_token` field is the `&` token.
bit_and,
/// `lhs ^ rhs`. The `main_token` field is the `^` token.
bit_xor,
/// `lhs | rhs`. The `main_token` field is the `|` token.
bit_or,
/// `lhs orelse rhs`. The `main_token` field is the `orelse` token.
@"orelse",
/// `lhs and rhs`. The `main_token` field is the `and` token.
bool_and,
/// `lhs or rhs`. The `main_token` field is the `or` token.
bool_or,
/// `!expr`. The `main_token` field is the `!` token.
bool_not,
/// `-expr`. The `main_token` field is the `-` token.
negation,
/// `~expr`. The `main_token` field is the `~` token.
bit_not,
/// `-%expr`. The `main_token` field is the `-%` token.
negation_wrap,
/// `&expr`. The `main_token` field is the `&` token.
address_of,
/// `try expr`. The `main_token` field is the `try` token.
@"try",
/// `await expr`. The `main_token` field is the `await` token.
@"await",
/// `?expr`. The `main_token` field is the `?` token.
optional_type,
/// `[lhs]rhs`. The `main_token` field is the `[` token.
array_type,
/// `[lhs:a]b`.
///
/// The `data` field is a `.node_and_extra`:
/// 1. a `Node.Index` to the length expression.
/// 2. a `ExtraIndex` to `ArrayTypeSentinel`.
///
/// The `main_token` field is the `[` token.
array_type_sentinel,
/// `[*]align(lhs) rhs`,
/// `*align(lhs) rhs`,
/// `[]rhs`.
///
/// The `data` field is a `.opt_node_and_node`:
/// 1. a `Node.OptionalIndex` to the alignment expression, if any.
/// 2. a `Node.Index` to the element type expression.
///
/// The `main_token` is the asterisk if a single item pointer or the
/// lbracket if a slice, many-item pointer, or C-pointer.
/// The `main_token` might be a ** token, which is shared with a
/// parent/child pointer type and may require special handling.
ptr_type_aligned,
/// `[*:lhs]rhs`,
/// `*rhs`,
/// `[:lhs]rhs`.
///
/// The `data` field is a `.opt_node_and_node`:
/// 1. a `Node.OptionalIndex` to the sentinel expression, if any.
/// 2. a `Node.Index` to the element type expression.
///
/// The `main_token` is the asterisk if a single item pointer or the
/// lbracket if a slice, many-item pointer, or C-pointer.
/// The `main_token` might be a ** token, which is shared with a
/// parent/child pointer type and may require special handling.
ptr_type_sentinel,
/// The `data` field is a `.opt_node_and_node`:
/// 1. a `ExtraIndex` to `PtrType`.
/// 2. a `Node.Index` to the element type expression.
///
/// The `main_token` is the asterisk if a single item pointer or the
/// lbracket if a slice, many-item pointer, or C-pointer.
/// The `main_token` might be a ** token, which is shared with a
/// parent/child pointer type and may require special handling.
ptr_type,
/// The `data` field is a `.opt_node_and_node`:
/// 1. a `ExtraIndex` to `PtrTypeBitRange`.
/// 2. a `Node.Index` to the element type expression.
///
/// The `main_token` is the asterisk if a single item pointer or the
/// lbracket if a slice, many-item pointer, or C-pointer.
/// The `main_token` might be a ** token, which is shared with a
/// parent/child pointer type and may require special handling.
ptr_type_bit_range,
/// `lhs[rhs..]`
///
/// The `main_token` field is the `[` token.
slice_open,
/// `sliced[start..end]`.
///
/// The `data` field is a `.node_and_extra`:
/// 1. a `Node.Index` to the sliced expression.
/// 2. a `ExtraIndex` to `Slice`.
///
/// The `main_token` field is the `[` token.
slice,
/// `sliced[start..end :sentinel]`,
/// `sliced[start.. :sentinel]`.
///
/// The `data` field is a `.node_and_extra`:
/// 1. a `Node.Index` to the sliced expression.
/// 2. a `ExtraIndex` to `SliceSentinel`.
///
/// The `main_token` field is the `[` token.
slice_sentinel,
/// `expr.*`.
///
/// The `data` field is a `.node` to expr.
///
/// The `main_token` field is the `*` token.
deref,
/// `lhs[rhs]`.
///
/// The `main_token` field is the `[` token.
array_access,
/// `lhs{rhs}`.
///
/// The `main_token` field is the `{` token.
array_init_one,
/// Same as `array_init_one` except there is known to be a trailing
/// comma before the final rbrace.
array_init_one_comma,
/// `.{a}`,
/// `.{a, b}`.
///
/// The `data` field is a `.opt_node_and_opt_node`:
/// 1. a `Node.OptionalIndex` to the first element. Never `.none`
/// 2. a `Node.OptionalIndex` to the second element, if any.
///
/// The `main_token` field is the `{` token.
array_init_dot_two,
/// Same as `array_init_dot_two` except there is known to be a trailing
/// comma before the final rbrace.
array_init_dot_two_comma,
/// `.{a, b, c}`.
///
/// The `data` field is a `.extra_range` that stores a `Node.Index` for
/// each element.
///
/// The `main_token` field is the `{` token.
array_init_dot,
/// Same as `array_init_dot` except there is known to be a trailing
/// comma before the final rbrace.
array_init_dot_comma,
/// `a{b, c}`.
///
/// The `data` field is a `.node_and_extra`:
/// 1. a `Node.Index` to the type expression.
/// 2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
/// each element.
///
/// The `main_token` field is the `{` token.
array_init,
/// Same as `array_init` except there is known to be a trailing comma
/// before the final rbrace.
array_init_comma,
/// `a{.x = b}`, `a{}`.
///
/// The `data` field is a `.node_and_opt_node`:
/// 1. a `Node.Index` to the type expression.
/// 2. a `Node.OptionalIndex` to the first field initialization, if any.
///
/// The `main_token` field is the `{` token.
///
/// The field name is determined by looking at the tokens preceding the
/// field initialization.
struct_init_one,
/// Same as `struct_init_one` except there is known to be a trailing comma
/// before the final rbrace.
struct_init_one_comma,
/// `.{.x = a, .y = b}`.
///
/// The `data` field is a `.opt_node_and_opt_node`:
/// 1. a `Node.OptionalIndex` to the first field initialization. Never `.none`
/// 2. a `Node.OptionalIndex` to the second field initialization, if any.
///
/// The `main_token` field is the '{' token.
///
/// The field name is determined by looking at the tokens preceding the
/// field initialization.
struct_init_dot_two,
/// Same as `struct_init_dot_two` except there is known to be a trailing
/// comma before the final rbrace.
struct_init_dot_two_comma,
/// `.{.x = a, .y = b, .z = c}`.
///
/// The `data` field is a `.extra_range` that stores a `Node.Index` for
/// each field initialization.
///
/// The `main_token` field is the `{` token.
///
/// The field name is determined by looking at the tokens preceding the
/// field initialization.
struct_init_dot,
/// Same as `struct_init_dot` except there is known to be a trailing
/// comma before the final rbrace.
struct_init_dot_comma,
/// `a{.x = b, .y = c}`.
///
/// The `data` field is a `.node_and_extra`:
/// 1. a `Node.Index` to the type expression.
/// 2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
/// each field initialization.
///
/// The `main_token` field is the `{` token.
///
/// The field name is determined by looking at the tokens preceding the
/// field initialization.
struct_init,
/// Same as `struct_init` except there is known to be a trailing comma
/// before the final rbrace.
struct_init_comma,
/// `a(b)`, `a()`.
///
/// The `data` field is a `.node_and_opt_node`:
/// 1. a `Node.Index` to the function expression.
/// 2. a `Node.OptionalIndex` to the first argument, if any.
///
/// The `main_token` field is the `(` token.
call_one,
/// Same as `call_one` except there is known to be a trailing comma
/// before the final rparen.
call_one_comma,
/// `async a(b)`, `async a()`.
///
/// The `data` field is a `.node_and_opt_node`:
/// 1. a `Node.Index` to the function expression.
/// 2. a `Node.OptionalIndex` to the first argument, if any.
///
/// The `main_token` field is the `(` token.
async_call_one,
/// Same as `async_call_one` except there is known to be a trailing
/// comma before the final rparen.
async_call_one_comma,
/// `a(b, c, d)`.
///
/// The `data` field is a `.node_and_extra`:
/// 1. a `Node.Index` to the function expression.
/// 2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
/// each argument.
///
/// The `main_token` field is the `(` token.
call,
/// Same as `call` except there is known to be a trailing comma before
/// the final rparen.
call_comma,
/// `async a(b, c, d)`.
///
/// The `data` field is a `.node_and_extra`:
/// 1. a `Node.Index` to the function expression.
/// 2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
/// each argument.
///
/// The `main_token` field is the `(` token.
async_call,
/// Same as `async_call` except there is known to be a trailing comma
/// before the final rparen.
async_call_comma,
/// `switch(a) {}`.
///
/// The `data` field is a `.node_and_extra`:
/// 1. a `Node.Index` to the switch operand.
/// 2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
/// each switch case.
///
/// `The `main_token` field` is the identifier of a preceding label, if any; otherwise `switch`.
@"switch",
/// Same as `switch` except there is known to be a trailing comma before
/// the final rbrace.
switch_comma,
/// `a => b`,
/// `else => b`.
///
/// The `data` field is a `.opt_node_and_node`:
/// 1. a `Node.OptionalIndex` where `.none` means `else`.
/// 2. a `Node.Index` to the target expression.
///
/// The `main_token` field is the `=>` token.
switch_case_one,
/// Same as `switch_case_one` but the case is inline.
switch_case_inline_one,
/// `a, b, c => d`.
///
/// The `data` field is a `.extra_and_node`:
/// 1. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
/// each switch item.
/// 2. a `Node.Index` to the target expression.
///
/// The `main_token` field is the `=>` token.
switch_case,
/// Same as `switch_case` but the case is inline.
switch_case_inline,
/// `lhs...rhs`.
///
/// The `main_token` field is the `...` token.
switch_range,
/// `while (a) b`,
/// `while (a) |x| b`.
while_simple,
/// `while (a) : (b) c`,
/// `while (a) |x| : (b) c`.
while_cont,
/// `while (a) : (b) c else d`,
/// `while (a) |x| : (b) c else d`,
/// `while (a) |x| : (b) c else |y| d`.
/// The continue expression part `: (b)` may be omitted.
@"while",
/// `for (a) b`.
for_simple,
/// `for (lhs[0..inputs]) lhs[inputs + 1] else lhs[inputs + 2]`. `For[rhs]`.
@"for",
/// `lhs..rhs`, `lhs..`.
for_range,
/// `if (a) b`.
/// `if (b) |x| b`.
if_simple,
/// `if (a) b else c`.
/// `if (a) |x| b else c`.
/// `if (a) |x| b else |y| d`.
@"if",
/// `suspend expr`.
///
/// The `data` field is a `.node` to expr.
///
/// The `main_token` field is the `suspend` token.
@"suspend",
/// `resume expr`.
///
/// The `data` field is a `.node` to expr.
///
/// The `main_token` field is the `resume` token.
@"resume",
/// `continue :label expr`,
/// `continue expr`,
/// `continue :label`,
/// `continue`.
///
/// The `data` field is a `.opt_token_and_opt_node`:
/// 1. a `OptionalTokenIndex` to the label identifier, if any.
/// 2. a `Node.OptionalIndex` to the target expression, if any.
///
/// The `main_token` field is the `continue` token.
@"continue",
/// `break :label expr`,
/// `break expr`,
/// `break :label`,
/// `break`.
///
/// The `data` field is a `.opt_token_and_opt_node`:
/// 1. a `OptionalTokenIndex` to the label identifier, if any.
/// 2. a `Node.OptionalIndex` to the target expression, if any.
///
/// The `main_token` field is the `break` token.
@"break",
/// `return expr`, `return`.
///
/// The `data` field is a `.opt_node` to the return value, if any.
///
/// The `main_token` field is the `return` token.
@"return",
/// `fn (a: type_expr) return_type`.
///
/// The `data` field is a `.opt_node_and_opt_node`:
/// 1. a `Node.OptionalIndex` to the first parameter type expression, if any.
/// 2. a `Node.OptionalIndex` to the return type expression. Can't be
/// `.none` unless a parsing error occured.
///
/// The `main_token` field is the `fn` token.
///
/// `anytype` and `...` parameters are omitted from the AST tree.
/// Extern function declarations use this tag.
fn_proto_simple,
/// `fn (a: b, c: d) return_type`.
///
/// The `data` field is a `.extra_and_opt_node`:
/// 1. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
/// each parameter type expression.
/// 2. a `Node.OptionalIndex` to the return type expression. Can't be
/// `.none` unless a parsing error occured.
///
/// The `main_token` field is the `fn` token.
///
/// `anytype` and `...` parameters are omitted from the AST tree.
/// Extern function declarations use this tag.
fn_proto_multi,
/// `fn (a: b) addrspace(e) linksection(f) callconv(g) return_type`.
/// zero or one parameters.
///
/// The `data` field is a `.extra_and_opt_node`:
/// 1. a `Node.ExtraIndex` to `FnProtoOne`.
/// 2. a `Node.OptionalIndex` to the return type expression. Can't be
/// `.none` unless a parsing error occured.
///
/// The `main_token` field is the `fn` token.
///
/// `anytype` and `...` parameters are omitted from the AST tree.
/// Extern function declarations use this tag.
fn_proto_one,
/// `fn (a: b, c: d) addrspace(e) linksection(f) callconv(g) return_type`.
///
/// The `data` field is a `.extra_and_opt_node`:
/// 1. a `Node.ExtraIndex` to `FnProto`.
/// 2. a `Node.OptionalIndex` to the return type expression. Can't be
/// `.none` unless a parsing error occured.
///
/// The `main_token` field is the `fn` token.
///
/// `anytype` and `...` parameters are omitted from the AST tree.
/// Extern function declarations use this tag.
fn_proto,
/// Extern function declarations use the fn_proto tags rather than this one.
///
/// The `data` field is a `.node_and_node`:
/// 1. a `Node.Index` to `fn_proto_*`.
/// 2. a `Node.Index` to function body block.
///
/// The `main_token` field is the `fn` token.
fn_decl,
/// `anyframe->return_type`.
///
/// The `data` field is a `.token_and_node`:
/// 1. a `TokenIndex` to the `->` token.
/// 2. a `Node.Index` to the function frame return type expression.
///
/// The `main_token` field is the `anyframe` token.
anyframe_type,
/// The `data` field is unused.
anyframe_literal,
/// The `data` field is unused.
char_literal,
/// The `data` field is unused.
number_literal,
/// The `data` field is unused.
unreachable_literal,
/// The `data` field is unused.
///
/// Most identifiers will not have explicit AST nodes, however for
/// expressions which could be one of many different kinds of AST nodes,
/// there will be an identifier AST node for it.
identifier,
/// `.foo`.
///
/// The `data` field is unused.
///
/// The `main_token` field is the identifier.
enum_literal,
/// The `data` field is unused.
///
/// The `main_token` field is the string literal token.
string_literal,
/// The `data` field is a `.token_and_token`:
/// 1. a `TokenIndex` to the first `.multiline_string_literal_line` token.
/// 2. a `TokenIndex` to the last `.multiline_string_literal_line` token.
///
/// The `main_token` field is the first token index (redundant with `data`).
multiline_string_literal,
/// `(expr)`.
///
/// The `data` field is a `.node_and_token`:
/// 1. a `Node.Index` to the sub-expression
/// 2. a `TokenIndex` to the `)` token.
///
/// The `main_token` field is the `(` token.
grouped_expression,
/// `@a(b, c)`.
///
/// The `data` field is a `.opt_node_and_opt_node`:
/// 1. a `Node.OptionalIndex` to the first argument, if any.
/// 2. a `Node.OptionalIndex` to the second argument, if any.
///
/// The `main_token` field is the builtin token.
builtin_call_two,
/// Same as `builtin_call_two` except there is known to be a trailing comma
/// before the final rparen.
builtin_call_two_comma,
/// `@a(b, c, d)`.
///
/// The `data` field is a `.extra_range` that stores a `Node.Index` for
/// each argument.
///
/// The `main_token` field is the builtin token.
builtin_call,
/// Same as `builtin_call` except there is known to be a trailing comma
/// before the final rparen.
builtin_call_comma,
/// `error{a, b}`.
///
/// The `data` field is a `.token_and_token`:
/// 1. a `TokenIndex` to the `{` token.
/// 2. a `TokenIndex` to the `}` token.
///
/// The `main_token` field is the `error`.
error_set_decl,
/// `struct {}`, `union {}`, `opaque {}`, `enum {}`.
///
/// The `data` field is a `.extra_range` that stores a `Node.Index` for
/// each container member.
///
/// The `main_token` field is the `struct`, `union`, `opaque` or `enum` token.
container_decl,
/// Same as `container_decl` except there is known to be a trailing
/// comma before the final rbrace.
container_decl_trailing,
/// `struct {lhs, rhs}`, `union {lhs, rhs}`, `opaque {lhs, rhs}`, `enum {lhs, rhs}`.
///
/// The `data` field is a `.opt_node_and_opt_node`:
/// 1. a `Node.OptionalIndex` to the first container member, if any.
/// 2. a `Node.OptionalIndex` to the second container member, if any.
///
/// The `main_token` field is the `struct`, `union`, `opaque` or `enum` token.
container_decl_two,
/// Same as `container_decl_two` except there is known to be a trailing
/// comma before the final rbrace.
container_decl_two_trailing,
/// `struct(arg)`, `union(arg)`, `enum(arg)`.
///
/// The `data` field is a `.node_and_extra`:
/// 1. a `Node.Index` to arg.
/// 2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
/// each container member.
///
/// The `main_token` field is the `struct`, `union` or `enum` token.
container_decl_arg,
/// Same as `container_decl_arg` except there is known to be a trailing
/// comma before the final rbrace.
container_decl_arg_trailing,
/// `union(enum) {}`.
///
/// The `data` field is a `.extra_range` that stores a `Node.Index` for
/// each container member.
///
/// The `main_token` field is the `union` token.
///
/// A tagged union with explicitly provided enums will instead be
/// represented by `container_decl_arg`.
tagged_union,
/// Same as `tagged_union` except there is known to be a trailing comma
/// before the final rbrace.
tagged_union_trailing,
/// `union(enum) {lhs, rhs}`.
///
/// The `data` field is a `.opt_node_and_opt_node`:
/// 1. a `Node.OptionalIndex` to the first container member, if any.
/// 2. a `Node.OptionalIndex` to the second container member, if any.
///
/// The `main_token` field is the `union` token.
///
/// A tagged union with explicitly provided enums will instead be
/// represented by `container_decl_arg`.
tagged_union_two,
/// Same as `tagged_union_two` except there is known to be a trailing
/// comma before the final rbrace.
tagged_union_two_trailing,
/// `union(enum(arg)) {}`.
///
/// The `data` field is a `.node_and_extra`:
/// 1. a `Node.Index` to arg.
/// 2. a `ExtraIndex` to a `SubRange` that stores a `Node.Index` for
/// each container member.
///
/// The `main_token` field is the `union` token.
tagged_union_enum_tag,
/// Same as `tagged_union_enum_tag` except there is known to be a
/// trailing comma before the final rbrace.
tagged_union_enum_tag_trailing,
/// `a: lhs = rhs,`,
/// `a: lhs,`.
///
/// The `data` field is a `.node_and_opt_node`:
/// 1. a `Node.Index` to the field type expression.
/// 2. a `Node.OptionalIndex` to the default value expression, if any.
///
/// The `main_token` field is the field name identifier.
///
/// `lastToken()` does not include the possible trailing comma.
container_field_init,
/// `a: lhs align(rhs),`.
///
/// The `data` field is a `.node_and_node`:
/// 1. a `Node.Index` to the field type expression.
/// 2. a `Node.Index` to the alignment expression.
///
/// The `main_token` field is the field name identifier.
///
/// `lastToken()` does not include the possible trailing comma.
container_field_align,
/// `a: lhs align(c) = d,`.
///
/// The `data` field is a `.node_and_extra`:
/// 1. a `Node.Index` to the field type expression.
/// 2. a `ExtraIndex` to `ContainerField`.
///
/// The `main_token` field is the field name identifier.
///
/// `lastToken()` does not include the possible trailing comma.
container_field,
/// `comptime expr`.
///
/// The `data` field is a `.node` to expr.
///
/// The `main_token` field is the `comptime` token.
@"comptime",
/// `nosuspend expr`.
///
/// The `data` field is a `.node` to expr.
///
/// The `main_token` field is the `nosuspend` token.
@"nosuspend",
/// `{lhs rhs}`.
///
/// The `data` field is a `.opt_node_and_opt_node`:
/// 1. a `Node.OptionalIndex` to the first statement, if any.
/// 2. a `Node.OptionalIndex` to the second statement, if any.
///
/// The `main_token` field is the `{` token.
block_two,
/// Same as `block_two` except there is known to be a trailing
/// comma before the final rbrace.
block_two_semicolon,
/// `{a b}`.
///
/// The `data` field is a `.extra_range` that stores a `Node.Index` for
/// each statement.
///
/// The `main_token` field is the `{` token.
block,
/// Same as `block` except there is known to be a trailing comma before
/// the final rbrace.
block_semicolon,
/// `asm(lhs)`.
///
/// rhs is a `Token.Index` to the `)` token.
/// The `main_token` field is the `asm` token.
asm_simple,
/// `asm(lhs, a)`.
///
/// The `data` field is a `.node_and_extra`:
/// 1. a `Node.Index` to lhs.
/// 2. a `ExtraIndex` to `Asm`.
///
/// The `main_token` field is the `asm` token.
@"asm",
/// `[a] "b" (c)`.
/// `[a] "b" (-> lhs)`.
///
/// The `data` field is a `.opt_node_and_token`:
/// 1. a `Node.OptionalIndex` to lhs, if any.
/// 2. a `TokenIndex` to the `)` token.
///
/// The `main_token` field is `a`.
asm_output,
/// `[a] "b" (lhs)`.
///
/// The `data` field is a `.node_and_token`:
/// 1. a `Node.Index` to lhs.
/// 2. a `TokenIndex` to the `)` token.
///
/// The `main_token` field is `a`.
asm_input,
/// `error.a`.
///
/// The `data` field is unused.
///
/// The `main_token` field is `error` token.
error_value,
/// `lhs!rhs`.
///
/// The `main_token` field is the `!` token.
error_union,
pub fn isContainerField(tag: Tag) bool {
return switch (tag) {
.container_field_init,
.container_field_align,
.container_field,
=> true,
else => false,
};
}
};
pub const Data = union {
node: Index,
opt_node: OptionalIndex,
token: TokenIndex,
node_and_node: struct { Index, Index },
opt_node_and_opt_node: struct { OptionalIndex, OptionalIndex },
node_and_opt_node: struct { Index, OptionalIndex },
opt_node_and_node: struct { OptionalIndex, Index },
node_and_extra: struct { Index, ExtraIndex },
extra_and_node: struct { ExtraIndex, Index },
extra_and_opt_node: struct { ExtraIndex, OptionalIndex },
node_and_token: struct { Index, TokenIndex },
token_and_node: struct { TokenIndex, Index },
token_and_token: struct { TokenIndex, TokenIndex },
opt_node_and_token: struct { OptionalIndex, TokenIndex },
opt_token_and_node: struct { OptionalTokenIndex, Index },
opt_token_and_opt_node: struct { OptionalTokenIndex, OptionalIndex },
opt_token_and_opt_token: struct { OptionalTokenIndex, OptionalTokenIndex },
@"for": struct { ExtraIndex, For },
extra_range: SubRange,
};
pub const LocalVarDecl = struct {
type_node: Index,
align_node: Index,
};
pub const ArrayTypeSentinel = struct {
sentinel: Index,
elem_type: Index,
};
pub const PtrType = struct {
sentinel: OptionalIndex,
align_node: OptionalIndex,
addrspace_node: OptionalIndex,
};
pub const PtrTypeBitRange = struct {
sentinel: OptionalIndex,
align_node: Index,
addrspace_node: OptionalIndex,
bit_range_start: Index,
bit_range_end: Index,
};
pub const SubRange = struct {
/// Index into extra_data.
start: ExtraIndex,
/// Index into extra_data.
end: ExtraIndex,
};
pub const If = struct {
then_expr: Index,
else_expr: Index,
};
pub const ContainerField = struct {
align_expr: Index,
value_expr: Index,
};
pub const GlobalVarDecl = struct {
/// Populated if there is an explicit type ascription.
type_node: OptionalIndex,
/// Populated if align(A) is present.
align_node: OptionalIndex,
/// Populated if addrspace(A) is present.
addrspace_node: OptionalIndex,
/// Populated if linksection(A) is present.
section_node: OptionalIndex,
};
pub const Slice = struct {
start: Index,
end: Index,
};
pub const SliceSentinel = struct {
start: Index,
/// May be .none if the slice is "open"
end: OptionalIndex,
sentinel: Index,
};
pub const While = struct {
cont_expr: OptionalIndex,
then_expr: Index,
else_expr: Index,
};
pub const WhileCont = struct {
cont_expr: Index,
then_expr: Index,
};
pub const For = packed struct(u32) {
inputs: u31,
has_else: bool,
};
pub const FnProtoOne = struct {
/// Populated if there is exactly 1 parameter. Otherwise there are 0 parameters.
param: OptionalIndex,
/// Populated if align(A) is present.
align_expr: OptionalIndex,
/// Populated if addrspace(A) is present.
addrspace_expr: OptionalIndex,
/// Populated if linksection(A) is present.
section_expr: OptionalIndex,
/// Populated if callconv(A) is present.
callconv_expr: OptionalIndex,
};
pub const FnProto = struct {
params_start: ExtraIndex,
params_end: ExtraIndex,
/// Populated if align(A) is present.
align_expr: OptionalIndex,
/// Populated if addrspace(A) is present.
addrspace_expr: OptionalIndex,
/// Populated if linksection(A) is present.
section_expr: OptionalIndex,
/// Populated if callconv(A) is present.
callconv_expr: OptionalIndex,
};
pub const Asm = struct {
items_start: ExtraIndex,
items_end: ExtraIndex,
/// Needed to make lastToken() work.
rparen: TokenIndex,
};
}