From 6e57243a79b08f37b80122f0eb24d073d6e2e95c Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 20 Apr 2018 02:15:09 -0400 Subject: [PATCH] zig fmt: preserve comments in front of test blocks * refactor std.zig.parser * fix compiler crashing for some compile errors * take advantage of @field in std.zig.ast * move ast.NodeFoo to ast.Node.Foo * comment preservation is more explicit See #911 --- src/ir.cpp | 4 + std/zig/ast.zig | 3391 ++++++++++++++++++++++---------------------- std/zig/parser.zig | 975 +++++++------ 3 files changed, 2169 insertions(+), 2201 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index a34c990afe..865a6823be 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -6523,6 +6523,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop case NodeTypeFieldAccessExpr: { IrInstruction *ptr_instruction = ir_gen_field_access(irb, scope, node); + if (ptr_instruction == irb->codegen->invalid_instruction) + return ptr_instruction; if (lval.is_ptr) return ptr_instruction; @@ -15556,6 +15558,8 @@ static TypeTableEntry *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira, } ensure_complete_type(ira->codegen, container_type); + if (type_is_invalid(container_type)) + return ira->codegen->builtin_types.entry_invalid; TypeStructField *field = find_struct_type_field(container_type, field_name); if (field == nullptr) { diff --git a/std/zig/ast.zig b/std/zig/ast.zig index 17a19e6213..76977a979a 100644 --- a/std/zig/ast.zig +++ b/std/zig/ast.zig @@ -6,7 +6,6 @@ const mem = std.mem; pub const Node = struct { id: Id, - comment: ?&NodeLineComment, pub const Id = enum { // Top level @@ -74,1750 +73,1686 @@ pub const Node = struct { FieldInitializer, }; - const IdTypePair = struct { - id: Id, - Type: type, - }; - - // TODO: When @field exists, we could generate this by iterating over all members of `Id`, - // and making an array of `IdTypePair { .id = @field(Id, @memberName(Id, i)), .Type = @field(ast, "Node" ++ @memberName(Id, i)) }` - const idTypeTable = []IdTypePair { - IdTypePair { .id = Id.Root, .Type = NodeRoot }, - IdTypePair { .id = Id.Use, .Type = NodeUse }, - IdTypePair { .id = Id.TestDecl, .Type = NodeTestDecl }, - - IdTypePair { .id = Id.VarDecl, .Type = NodeVarDecl }, - IdTypePair { .id = Id.Defer, .Type = NodeDefer }, - - IdTypePair { .id = Id.InfixOp, .Type = NodeInfixOp }, - IdTypePair { .id = Id.PrefixOp, .Type = NodePrefixOp }, - IdTypePair { .id = Id.SuffixOp, .Type = NodeSuffixOp }, - - IdTypePair { .id = Id.Switch, .Type = NodeSwitch }, - IdTypePair { .id = Id.While, .Type = NodeWhile }, - IdTypePair { .id = Id.For, .Type = NodeFor }, - IdTypePair { .id = Id.If, .Type = NodeIf }, - IdTypePair { .id = Id.ControlFlowExpression, .Type = NodeControlFlowExpression }, - IdTypePair { .id = Id.Suspend, .Type = NodeSuspend }, - - IdTypePair { .id = Id.VarType, .Type = NodeVarType }, - IdTypePair { .id = Id.ErrorType, .Type = NodeErrorType }, - IdTypePair { .id = Id.FnProto, .Type = NodeFnProto }, - - IdTypePair { .id = Id.IntegerLiteral, .Type = NodeIntegerLiteral }, - IdTypePair { .id = Id.FloatLiteral, .Type = NodeFloatLiteral }, - IdTypePair { .id = Id.StringLiteral, .Type = NodeStringLiteral }, - IdTypePair { .id = Id.MultilineStringLiteral, .Type = NodeMultilineStringLiteral }, - IdTypePair { .id = Id.CharLiteral, .Type = NodeCharLiteral }, - IdTypePair { .id = Id.BoolLiteral, .Type = NodeBoolLiteral }, - IdTypePair { .id = Id.NullLiteral, .Type = NodeNullLiteral }, - IdTypePair { .id = Id.UndefinedLiteral, .Type = NodeUndefinedLiteral }, - IdTypePair { .id = Id.ThisLiteral, .Type = NodeThisLiteral }, - IdTypePair { .id = Id.Unreachable, .Type = NodeUnreachable }, - IdTypePair { .id = Id.Identifier, .Type = NodeIdentifier }, - IdTypePair { .id = Id.GroupedExpression, .Type = NodeGroupedExpression }, - IdTypePair { .id = Id.BuiltinCall, .Type = NodeBuiltinCall }, - IdTypePair { .id = Id.ErrorSetDecl, .Type = NodeErrorSetDecl }, - IdTypePair { .id = Id.ContainerDecl, .Type = NodeContainerDecl }, - IdTypePair { .id = Id.Asm, .Type = NodeAsm }, - IdTypePair { .id = Id.Comptime, .Type = NodeComptime }, - IdTypePair { .id = Id.Block, .Type = NodeBlock }, - - IdTypePair { .id = Id.LineComment, .Type = NodeLineComment }, - IdTypePair { .id = Id.SwitchCase, .Type = NodeSwitchCase }, - IdTypePair { .id = Id.SwitchElse, .Type = NodeSwitchElse }, - IdTypePair { .id = Id.Else, .Type = NodeElse }, - IdTypePair { .id = Id.Payload, .Type = NodePayload }, - IdTypePair { .id = Id.PointerPayload, .Type = NodePointerPayload }, - IdTypePair { .id = Id.PointerIndexPayload, .Type = NodePointerIndexPayload }, - IdTypePair { .id = Id.StructField, .Type = NodeStructField }, - IdTypePair { .id = Id.UnionTag, .Type = NodeUnionTag }, - IdTypePair { .id = Id.EnumTag, .Type = NodeEnumTag }, - IdTypePair { .id = Id.AsmInput, .Type = NodeAsmInput }, - IdTypePair { .id = Id.AsmOutput, .Type = NodeAsmOutput }, - IdTypePair { .id = Id.AsyncAttribute, .Type = NodeAsyncAttribute }, - IdTypePair { .id = Id.ParamDecl, .Type = NodeParamDecl }, - IdTypePair { .id = Id.FieldInitializer, .Type = NodeFieldInitializer }, - }; - - pub fn IdToType(comptime id: Id) type { - inline for (idTypeTable) |id_type_pair| { - if (id == id_type_pair.id) - return id_type_pair.Type; - } - - unreachable; - } - - pub fn typeToId(comptime T: type) Id { - inline for (idTypeTable) |id_type_pair| { - if (T == id_type_pair.Type) - return id_type_pair.id; - } - - unreachable; - } - pub fn iterate(base: &Node, index: usize) ?&Node { - inline for (idTypeTable) |id_type_pair| { - if (base.id == id_type_pair.id) - return @fieldParentPtr(id_type_pair.Type, "base", base).iterate(index); + comptime var i = 0; + inline while (i < @memberCount(Id)) : (i += 1) { + if (base.id == @field(Id, @memberName(Id, i))) { + const T = @field(Node, @memberName(Id, i)); + return @fieldParentPtr(T, "base", base).iterate(index); + } } - unreachable; } pub fn firstToken(base: &Node) Token { - inline for (idTypeTable) |id_type_pair| { - if (base.id == id_type_pair.id) - return @fieldParentPtr(id_type_pair.Type, "base", base).firstToken(); + comptime var i = 0; + inline while (i < @memberCount(Id)) : (i += 1) { + if (base.id == @field(Id, @memberName(Id, i))) { + const T = @field(Node, @memberName(Id, i)); + return @fieldParentPtr(T, "base", base).firstToken(); + } } - unreachable; } pub fn lastToken(base: &Node) Token { - inline for (idTypeTable) |id_type_pair| { - if (base.id == id_type_pair.id) - return @fieldParentPtr(id_type_pair.Type, "base", base).lastToken(); - } - - unreachable; - } -}; - -pub const NodeRoot = struct { - base: Node, - decls: ArrayList(&Node), - eof_token: Token, - - pub fn iterate(self: &NodeRoot, index: usize) ?&Node { - if (index < self.decls.len) { - return self.decls.items[self.decls.len - index - 1]; - } - return null; - } - - pub fn firstToken(self: &NodeRoot) Token { - return if (self.decls.len == 0) self.eof_token else self.decls.at(0).firstToken(); - } - - pub fn lastToken(self: &NodeRoot) Token { - return if (self.decls.len == 0) self.eof_token else self.decls.at(self.decls.len - 1).lastToken(); - } -}; - -pub const NodeVarDecl = struct { - base: Node, - visib_token: ?Token, - name_token: Token, - eq_token: Token, - mut_token: Token, - comptime_token: ?Token, - extern_export_token: ?Token, - lib_name: ?&Node, - type_node: ?&Node, - align_node: ?&Node, - init_node: ?&Node, - semicolon_token: Token, - - pub fn iterate(self: &NodeVarDecl, index: usize) ?&Node { - var i = index; - - if (self.type_node) |type_node| { - if (i < 1) return type_node; - i -= 1; - } - - if (self.align_node) |align_node| { - if (i < 1) return align_node; - i -= 1; - } - - if (self.init_node) |init_node| { - if (i < 1) return init_node; - i -= 1; - } - - return null; - } - - pub fn firstToken(self: &NodeVarDecl) Token { - if (self.visib_token) |visib_token| return visib_token; - if (self.comptime_token) |comptime_token| return comptime_token; - if (self.extern_export_token) |extern_export_token| return extern_export_token; - assert(self.lib_name == null); - return self.mut_token; - } - - pub fn lastToken(self: &NodeVarDecl) Token { - return self.semicolon_token; - } -}; - -pub const NodeUse = struct { - base: Node, - visib_token: ?Token, - expr: &Node, - semicolon_token: Token, - - pub fn iterate(self: &NodeUse, index: usize) ?&Node { - var i = index; - - if (i < 1) return self.expr; - i -= 1; - - return null; - } - - pub fn firstToken(self: &NodeUse) Token { - if (self.visib_token) |visib_token| return visib_token; - return self.expr.firstToken(); - } - - pub fn lastToken(self: &NodeUse) Token { - return self.semicolon_token; - } -}; - -pub const NodeErrorSetDecl = struct { - base: Node, - error_token: Token, - decls: ArrayList(&Node), - rbrace_token: Token, - - pub fn iterate(self: &NodeErrorSetDecl, index: usize) ?&Node { - var i = index; - - if (i < self.decls.len) return self.decls.at(i); - i -= self.decls.len; - - return null; - } - - pub fn firstToken(self: &NodeErrorSetDecl) Token { - return self.error_token; - } - - pub fn lastToken(self: &NodeErrorSetDecl) Token { - return self.rbrace_token; - } -}; - -pub const NodeContainerDecl = struct { - base: Node, - ltoken: Token, - layout: Layout, - kind: Kind, - init_arg_expr: InitArg, - fields_and_decls: ArrayList(&Node), - rbrace_token: Token, - - const Layout = enum { - Auto, - Extern, - Packed, - }; - - const Kind = enum { - Struct, - Enum, - Union, - }; - - const InitArg = union(enum) { - None, - Enum, - Type: &Node, - }; - - pub fn iterate(self: &NodeContainerDecl, index: usize) ?&Node { - var i = index; - - switch (self.init_arg_expr) { - InitArg.Type => |t| { - if (i < 1) return t; - i -= 1; - }, - InitArg.None, - InitArg.Enum => { } - } - - if (i < self.fields_and_decls.len) return self.fields_and_decls.at(i); - i -= self.fields_and_decls.len; - - return null; - } - - pub fn firstToken(self: &NodeContainerDecl) Token { - return self.ltoken; - } - - pub fn lastToken(self: &NodeContainerDecl) Token { - return self.rbrace_token; - } -}; - -pub const NodeStructField = struct { - base: Node, - visib_token: ?Token, - name_token: Token, - type_expr: &Node, - - pub fn iterate(self: &NodeStructField, index: usize) ?&Node { - var i = index; - - if (i < 1) return self.type_expr; - i -= 1; - - return null; - } - - pub fn firstToken(self: &NodeStructField) Token { - if (self.visib_token) |visib_token| return visib_token; - return self.name_token; - } - - pub fn lastToken(self: &NodeStructField) Token { - return self.type_expr.lastToken(); - } -}; - -pub const NodeUnionTag = struct { - base: Node, - name_token: Token, - type_expr: ?&Node, - - pub fn iterate(self: &NodeUnionTag, index: usize) ?&Node { - var i = index; - - if (self.type_expr) |type_expr| { - if (i < 1) return type_expr; - i -= 1; - } - - return null; - } - - pub fn firstToken(self: &NodeUnionTag) Token { - return self.name_token; - } - - pub fn lastToken(self: &NodeUnionTag) Token { - if (self.type_expr) |type_expr| { - return type_expr.lastToken(); - } - - return self.name_token; - } -}; - -pub const NodeEnumTag = struct { - base: Node, - name_token: Token, - value: ?&Node, - - pub fn iterate(self: &NodeEnumTag, index: usize) ?&Node { - var i = index; - - if (self.value) |value| { - if (i < 1) return value; - i -= 1; - } - - return null; - } - - pub fn firstToken(self: &NodeEnumTag) Token { - return self.name_token; - } - - pub fn lastToken(self: &NodeEnumTag) Token { - if (self.value) |value| { - return value.lastToken(); - } - - return self.name_token; - } -}; - -pub const NodeIdentifier = struct { - base: Node, - token: Token, - - pub fn iterate(self: &NodeIdentifier, index: usize) ?&Node { - return null; - } - - pub fn firstToken(self: &NodeIdentifier) Token { - return self.token; - } - - pub fn lastToken(self: &NodeIdentifier) Token { - return self.token; - } -}; - -pub const NodeAsyncAttribute = struct { - base: Node, - async_token: Token, - allocator_type: ?&Node, - rangle_bracket: ?Token, - - pub fn iterate(self: &NodeAsyncAttribute, index: usize) ?&Node { - var i = index; - - if (self.allocator_type) |allocator_type| { - if (i < 1) return allocator_type; - i -= 1; - } - - return null; - } - - pub fn firstToken(self: &NodeAsyncAttribute) Token { - return self.async_token; - } - - pub fn lastToken(self: &NodeAsyncAttribute) Token { - if (self.rangle_bracket) |rangle_bracket| { - return rangle_bracket; - } - - return self.async_token; - } -}; - -pub const NodeFnProto = struct { - base: Node, - visib_token: ?Token, - fn_token: Token, - name_token: ?Token, - params: ArrayList(&Node), - return_type: ReturnType, - var_args_token: ?Token, - extern_export_inline_token: ?Token, - cc_token: ?Token, - async_attr: ?&NodeAsyncAttribute, - body_node: ?&Node, - lib_name: ?&Node, // populated if this is an extern declaration - align_expr: ?&Node, // populated if align(A) is present - - pub const ReturnType = union(enum) { - Explicit: &Node, - InferErrorSet: &Node, - }; - - pub fn iterate(self: &NodeFnProto, index: usize) ?&Node { - var i = index; - - if (self.body_node) |body_node| { - if (i < 1) return body_node; - i -= 1; - } - - switch (self.return_type) { - // TODO allow this and next prong to share bodies since the types are the same - ReturnType.Explicit => |node| { - if (i < 1) return node; - i -= 1; - }, - ReturnType.InferErrorSet => |node| { - if (i < 1) return node; - i -= 1; - }, - } - - if (self.align_expr) |align_expr| { - if (i < 1) return align_expr; - i -= 1; - } - - if (i < self.params.len) return self.params.items[self.params.len - i - 1]; - i -= self.params.len; - - if (self.lib_name) |lib_name| { - if (i < 1) return lib_name; - i -= 1; - } - - return null; - } - - pub fn firstToken(self: &NodeFnProto) Token { - if (self.visib_token) |visib_token| return visib_token; - if (self.extern_export_inline_token) |extern_export_inline_token| return extern_export_inline_token; - assert(self.lib_name == null); - if (self.cc_token) |cc_token| return cc_token; - return self.fn_token; - } - - pub fn lastToken(self: &NodeFnProto) Token { - if (self.body_node) |body_node| return body_node.lastToken(); - switch (self.return_type) { - // TODO allow this and next prong to share bodies since the types are the same - ReturnType.Explicit => |node| return node.lastToken(), - ReturnType.InferErrorSet => |node| return node.lastToken(), - } - } -}; - -pub const NodeParamDecl = struct { - base: Node, - comptime_token: ?Token, - noalias_token: ?Token, - name_token: ?Token, - type_node: &Node, - var_args_token: ?Token, - - pub fn iterate(self: &NodeParamDecl, index: usize) ?&Node { - var i = index; - - if (i < 1) return self.type_node; - i -= 1; - - return null; - } - - pub fn firstToken(self: &NodeParamDecl) Token { - if (self.comptime_token) |comptime_token| return comptime_token; - if (self.noalias_token) |noalias_token| return noalias_token; - if (self.name_token) |name_token| return name_token; - return self.type_node.firstToken(); - } - - pub fn lastToken(self: &NodeParamDecl) Token { - if (self.var_args_token) |var_args_token| return var_args_token; - return self.type_node.lastToken(); - } -}; - -pub const NodeBlock = struct { - base: Node, - label: ?Token, - lbrace: Token, - statements: ArrayList(&Node), - rbrace: Token, - - pub fn iterate(self: &NodeBlock, index: usize) ?&Node { - var i = index; - - if (i < self.statements.len) return self.statements.items[i]; - i -= self.statements.len; - - return null; - } - - pub fn firstToken(self: &NodeBlock) Token { - if (self.label) |label| { - return label; - } - - return self.lbrace; - } - - pub fn lastToken(self: &NodeBlock) Token { - return self.rbrace; - } -}; - -pub const NodeDefer = struct { - base: Node, - defer_token: Token, - kind: Kind, - expr: &Node, - - const Kind = enum { - Error, - Unconditional, - }; - - pub fn iterate(self: &NodeDefer, index: usize) ?&Node { - var i = index; - - if (i < 1) return self.expr; - i -= 1; - - return null; - } - - pub fn firstToken(self: &NodeDefer) Token { - return self.defer_token; - } - - pub fn lastToken(self: &NodeDefer) Token { - return self.expr.lastToken(); - } -}; - -pub const NodeComptime = struct { - base: Node, - comptime_token: Token, - expr: &Node, - - pub fn iterate(self: &NodeComptime, index: usize) ?&Node { - var i = index; - - if (i < 1) return self.expr; - i -= 1; - - return null; - } - - pub fn firstToken(self: &NodeComptime) Token { - return self.comptime_token; - } - - pub fn lastToken(self: &NodeComptime) Token { - return self.expr.lastToken(); - } -}; - -pub const NodePayload = struct { - base: Node, - lpipe: Token, - error_symbol: &Node, - rpipe: Token, - - pub fn iterate(self: &NodePayload, index: usize) ?&Node { - var i = index; - - if (i < 1) return self.error_symbol; - i -= 1; - - return null; - } - - pub fn firstToken(self: &NodePayload) Token { - return self.lpipe; - } - - pub fn lastToken(self: &NodePayload) Token { - return self.rpipe; - } -}; - -pub const NodePointerPayload = struct { - base: Node, - lpipe: Token, - ptr_token: ?Token, - value_symbol: &Node, - rpipe: Token, - - pub fn iterate(self: &NodePointerPayload, index: usize) ?&Node { - var i = index; - - if (i < 1) return self.value_symbol; - i -= 1; - - return null; - } - - pub fn firstToken(self: &NodePointerPayload) Token { - return self.lpipe; - } - - pub fn lastToken(self: &NodePointerPayload) Token { - return self.rpipe; - } -}; - -pub const NodePointerIndexPayload = struct { - base: Node, - lpipe: Token, - ptr_token: ?Token, - value_symbol: &Node, - index_symbol: ?&Node, - rpipe: Token, - - pub fn iterate(self: &NodePointerIndexPayload, index: usize) ?&Node { - var i = index; - - if (i < 1) return self.value_symbol; - i -= 1; - - if (self.index_symbol) |index_symbol| { - if (i < 1) return index_symbol; - i -= 1; - } - - return null; - } - - pub fn firstToken(self: &NodePointerIndexPayload) Token { - return self.lpipe; - } - - pub fn lastToken(self: &NodePointerIndexPayload) Token { - return self.rpipe; - } -}; - -pub const NodeElse = struct { - base: Node, - else_token: Token, - payload: ?&Node, - body: &Node, - - pub fn iterate(self: &NodeElse, index: usize) ?&Node { - var i = index; - - if (self.payload) |payload| { - if (i < 1) return payload; - i -= 1; - } - - if (i < 1) return self.body; - i -= 1; - - return null; - } - - pub fn firstToken(self: &NodeElse) Token { - return self.else_token; - } - - pub fn lastToken(self: &NodeElse) Token { - return self.body.lastToken(); - } -}; - -pub const NodeSwitch = struct { - base: Node, - switch_token: Token, - expr: &Node, - cases: ArrayList(&NodeSwitchCase), - rbrace: Token, - - pub fn iterate(self: &NodeSwitch, index: usize) ?&Node { - var i = index; - - if (i < 1) return self.expr; - i -= 1; - - if (i < self.cases.len) return &self.cases.at(i).base; - i -= self.cases.len; - - return null; - } - - pub fn firstToken(self: &NodeSwitch) Token { - return self.switch_token; - } - - pub fn lastToken(self: &NodeSwitch) Token { - return self.rbrace; - } -}; - -pub const NodeSwitchCase = struct { - base: Node, - items: ArrayList(&Node), - payload: ?&Node, - expr: &Node, - - pub fn iterate(self: &NodeSwitchCase, index: usize) ?&Node { - var i = index; - - if (i < self.items.len) return self.items.at(i); - i -= self.items.len; - - if (self.payload) |payload| { - if (i < 1) return payload; - i -= 1; - } - - if (i < 1) return self.expr; - i -= 1; - - return null; - } - - pub fn firstToken(self: &NodeSwitchCase) Token { - return self.items.at(0).firstToken(); - } - - pub fn lastToken(self: &NodeSwitchCase) Token { - return self.expr.lastToken(); - } -}; - -pub const NodeSwitchElse = struct { - base: Node, - token: Token, - - pub fn iterate(self: &NodeSwitchElse, index: usize) ?&Node { - return null; - } - - pub fn firstToken(self: &NodeSwitchElse) Token { - return self.token; - } - - pub fn lastToken(self: &NodeSwitchElse) Token { - return self.token; - } -}; - -pub const NodeWhile = struct { - base: Node, - label: ?Token, - inline_token: ?Token, - while_token: Token, - condition: &Node, - payload: ?&Node, - continue_expr: ?&Node, - body: &Node, - @"else": ?&NodeElse, - - pub fn iterate(self: &NodeWhile, index: usize) ?&Node { - var i = index; - - if (i < 1) return self.condition; - i -= 1; - - if (self.payload) |payload| { - if (i < 1) return payload; - i -= 1; - } - - if (self.continue_expr) |continue_expr| { - if (i < 1) return continue_expr; - i -= 1; - } - - if (i < 1) return self.body; - i -= 1; - - if (self.@"else") |@"else"| { - if (i < 1) return &@"else".base; - i -= 1; - } - - return null; - } - - pub fn firstToken(self: &NodeWhile) Token { - if (self.label) |label| { - return label; - } - - if (self.inline_token) |inline_token| { - return inline_token; - } - - return self.while_token; - } - - pub fn lastToken(self: &NodeWhile) Token { - if (self.@"else") |@"else"| { - return @"else".body.lastToken(); - } - - return self.body.lastToken(); - } -}; - -pub const NodeFor = struct { - base: Node, - label: ?Token, - inline_token: ?Token, - for_token: Token, - array_expr: &Node, - payload: ?&Node, - body: &Node, - @"else": ?&NodeElse, - - pub fn iterate(self: &NodeFor, index: usize) ?&Node { - var i = index; - - if (i < 1) return self.array_expr; - i -= 1; - - if (self.payload) |payload| { - if (i < 1) return payload; - i -= 1; - } - - if (i < 1) return self.body; - i -= 1; - - if (self.@"else") |@"else"| { - if (i < 1) return &@"else".base; - i -= 1; - } - - return null; - } - - pub fn firstToken(self: &NodeFor) Token { - if (self.label) |label| { - return label; - } - - if (self.inline_token) |inline_token| { - return inline_token; - } - - return self.for_token; - } - - pub fn lastToken(self: &NodeFor) Token { - if (self.@"else") |@"else"| { - return @"else".body.lastToken(); - } - - return self.body.lastToken(); - } -}; - -pub const NodeIf = struct { - base: Node, - if_token: Token, - condition: &Node, - payload: ?&Node, - body: &Node, - @"else": ?&NodeElse, - - pub fn iterate(self: &NodeIf, index: usize) ?&Node { - var i = index; - - if (i < 1) return self.condition; - i -= 1; - - if (self.payload) |payload| { - if (i < 1) return payload; - i -= 1; - } - - if (i < 1) return self.body; - i -= 1; - - if (self.@"else") |@"else"| { - if (i < 1) return &@"else".base; - i -= 1; - } - - return null; - } - - pub fn firstToken(self: &NodeIf) Token { - return self.if_token; - } - - pub fn lastToken(self: &NodeIf) Token { - if (self.@"else") |@"else"| { - return @"else".body.lastToken(); - } - - return self.body.lastToken(); - } -}; - -pub const NodeInfixOp = struct { - base: Node, - op_token: Token, - lhs: &Node, - op: InfixOp, - rhs: &Node, - - const InfixOp = union(enum) { - Add, - AddWrap, - ArrayCat, - ArrayMult, - Assign, - AssignBitAnd, - AssignBitOr, - AssignBitShiftLeft, - AssignBitShiftRight, - AssignBitXor, - AssignDiv, - AssignMinus, - AssignMinusWrap, - AssignMod, - AssignPlus, - AssignPlusWrap, - AssignTimes, - AssignTimesWarp, - BangEqual, - BitAnd, - BitOr, - BitShiftLeft, - BitShiftRight, - BitXor, - BoolAnd, - BoolOr, - Catch: ?&Node, - Div, - EqualEqual, - ErrorUnion, - GreaterOrEqual, - GreaterThan, - LessOrEqual, - LessThan, - MergeErrorSets, - Mod, - Mult, - MultWrap, - Period, - Range, - Sub, - SubWrap, - UnwrapMaybe, - }; - - pub fn iterate(self: &NodeInfixOp, index: usize) ?&Node { - var i = index; - - if (i < 1) return self.lhs; - i -= 1; - - switch (self.op) { - InfixOp.Catch => |maybe_payload| { - if (maybe_payload) |payload| { - if (i < 1) return payload; - i -= 1; - } - }, - - InfixOp.Add, - InfixOp.AddWrap, - InfixOp.ArrayCat, - InfixOp.ArrayMult, - InfixOp.Assign, - InfixOp.AssignBitAnd, - InfixOp.AssignBitOr, - InfixOp.AssignBitShiftLeft, - InfixOp.AssignBitShiftRight, - InfixOp.AssignBitXor, - InfixOp.AssignDiv, - InfixOp.AssignMinus, - InfixOp.AssignMinusWrap, - InfixOp.AssignMod, - InfixOp.AssignPlus, - InfixOp.AssignPlusWrap, - InfixOp.AssignTimes, - InfixOp.AssignTimesWarp, - InfixOp.BangEqual, - InfixOp.BitAnd, - InfixOp.BitOr, - InfixOp.BitShiftLeft, - InfixOp.BitShiftRight, - InfixOp.BitXor, - InfixOp.BoolAnd, - InfixOp.BoolOr, - InfixOp.Div, - InfixOp.EqualEqual, - InfixOp.ErrorUnion, - InfixOp.GreaterOrEqual, - InfixOp.GreaterThan, - InfixOp.LessOrEqual, - InfixOp.LessThan, - InfixOp.MergeErrorSets, - InfixOp.Mod, - InfixOp.Mult, - InfixOp.MultWrap, - InfixOp.Period, - InfixOp.Range, - InfixOp.Sub, - InfixOp.SubWrap, - InfixOp.UnwrapMaybe => {}, - } - - if (i < 1) return self.rhs; - i -= 1; - - return null; - } - - pub fn firstToken(self: &NodeInfixOp) Token { - return self.lhs.firstToken(); - } - - pub fn lastToken(self: &NodeInfixOp) Token { - return self.rhs.lastToken(); - } -}; - -pub const NodePrefixOp = struct { - base: Node, - op_token: Token, - op: PrefixOp, - rhs: &Node, - - const PrefixOp = union(enum) { - AddrOf: AddrOfInfo, - ArrayType: &Node, - Await, - BitNot, - BoolNot, - Cancel, - Deref, - MaybeType, - Negation, - NegationWrap, - Resume, - SliceType: AddrOfInfo, - Try, - UnwrapMaybe, - }; - - const AddrOfInfo = struct { - align_expr: ?&Node, - bit_offset_start_token: ?Token, - bit_offset_end_token: ?Token, - const_token: ?Token, - volatile_token: ?Token, - }; - - pub fn iterate(self: &NodePrefixOp, index: usize) ?&Node { - var i = index; - - switch (self.op) { - PrefixOp.SliceType => |addr_of_info| { - if (addr_of_info.align_expr) |align_expr| { - if (i < 1) return align_expr; - i -= 1; - } - }, - PrefixOp.AddrOf => |addr_of_info| { - if (addr_of_info.align_expr) |align_expr| { - if (i < 1) return align_expr; - i -= 1; - } - }, - PrefixOp.ArrayType => |size_expr| { - if (i < 1) return size_expr; - i -= 1; - }, - PrefixOp.Await, - PrefixOp.BitNot, - PrefixOp.BoolNot, - PrefixOp.Cancel, - PrefixOp.Deref, - PrefixOp.MaybeType, - PrefixOp.Negation, - PrefixOp.NegationWrap, - PrefixOp.Try, - PrefixOp.Resume, - PrefixOp.UnwrapMaybe => {}, - } - - if (i < 1) return self.rhs; - i -= 1; - - return null; - } - - pub fn firstToken(self: &NodePrefixOp) Token { - return self.op_token; - } - - pub fn lastToken(self: &NodePrefixOp) Token { - return self.rhs.lastToken(); - } -}; - -pub const NodeFieldInitializer = struct { - base: Node, - period_token: Token, - name_token: Token, - expr: &Node, - - pub fn iterate(self: &NodeFieldInitializer, index: usize) ?&Node { - var i = index; - - if (i < 1) return self.expr; - i -= 1; - - return null; - } - - pub fn firstToken(self: &NodeFieldInitializer) Token { - return self.period_token; - } - - pub fn lastToken(self: &NodeFieldInitializer) Token { - return self.expr.lastToken(); - } -}; - -pub const NodeSuffixOp = struct { - base: Node, - lhs: &Node, - op: SuffixOp, - rtoken: Token, - - const SuffixOp = union(enum) { - Call: CallInfo, - ArrayAccess: &Node, - Slice: SliceRange, - ArrayInitializer: ArrayList(&Node), - StructInitializer: ArrayList(&NodeFieldInitializer), - }; - - const CallInfo = struct { - params: ArrayList(&Node), - async_attr: ?&NodeAsyncAttribute, - }; - - const SliceRange = struct { - start: &Node, - end: ?&Node, - }; - - pub fn iterate(self: &NodeSuffixOp, index: usize) ?&Node { - var i = index; - - if (i < 1) return self.lhs; - i -= 1; - - switch (self.op) { - SuffixOp.Call => |call_info| { - if (i < call_info.params.len) return call_info.params.at(i); - i -= call_info.params.len; - }, - SuffixOp.ArrayAccess => |index_expr| { - if (i < 1) return index_expr; - i -= 1; - }, - SuffixOp.Slice => |range| { - if (i < 1) return range.start; - i -= 1; - - if (range.end) |end| { - if (i < 1) return end; - i -= 1; - } - }, - SuffixOp.ArrayInitializer => |exprs| { - if (i < exprs.len) return exprs.at(i); - i -= exprs.len; - }, - SuffixOp.StructInitializer => |fields| { - if (i < fields.len) return &fields.at(i).base; - i -= fields.len; - }, - } - - return null; - } - - pub fn firstToken(self: &NodeSuffixOp) Token { - return self.lhs.firstToken(); - } - - pub fn lastToken(self: &NodeSuffixOp) Token { - return self.rtoken; - } -}; - -pub const NodeGroupedExpression = struct { - base: Node, - lparen: Token, - expr: &Node, - rparen: Token, - - pub fn iterate(self: &NodeGroupedExpression, index: usize) ?&Node { - var i = index; - - if (i < 1) return self.expr; - i -= 1; - - return null; - } - - pub fn firstToken(self: &NodeGroupedExpression) Token { - return self.lparen; - } - - pub fn lastToken(self: &NodeGroupedExpression) Token { - return self.rparen; - } -}; - -pub const NodeControlFlowExpression = struct { - base: Node, - ltoken: Token, - kind: Kind, - rhs: ?&Node, - - const Kind = union(enum) { - Break: ?&Node, - Continue: ?&Node, - Return, - }; - - pub fn iterate(self: &NodeControlFlowExpression, index: usize) ?&Node { - var i = index; - - switch (self.kind) { - Kind.Break => |maybe_label| { - if (maybe_label) |label| { - if (i < 1) return label; - i -= 1; - } - }, - Kind.Continue => |maybe_label| { - if (maybe_label) |label| { - if (i < 1) return label; - i -= 1; - } - }, - Kind.Return => {}, - } - - if (self.rhs) |rhs| { - if (i < 1) return rhs; - i -= 1; - } - - return null; - } - - pub fn firstToken(self: &NodeControlFlowExpression) Token { - return self.ltoken; - } - - pub fn lastToken(self: &NodeControlFlowExpression) Token { - if (self.rhs) |rhs| { - return rhs.lastToken(); - } - - switch (self.kind) { - Kind.Break => |maybe_label| { - if (maybe_label) |label| { - return label.lastToken(); - } - }, - Kind.Continue => |maybe_label| { - if (maybe_label) |label| { - return label.lastToken(); - } - }, - Kind.Return => return self.ltoken, - } - - return self.ltoken; - } -}; - -pub const NodeSuspend = struct { - base: Node, - suspend_token: Token, - payload: ?&Node, - body: ?&Node, - - pub fn iterate(self: &NodeSuspend, index: usize) ?&Node { - var i = index; - - if (self.payload) |payload| { - if (i < 1) return payload; - i -= 1; - } - - if (self.body) |body| { - if (i < 1) return body; - i -= 1; - } - - return null; - } - - pub fn firstToken(self: &NodeSuspend) Token { - return self.suspend_token; - } - - pub fn lastToken(self: &NodeSuspend) Token { - if (self.body) |body| { - return body.lastToken(); - } - - if (self.payload) |payload| { - return payload.lastToken(); - } - - return self.suspend_token; - } -}; - -pub const NodeIntegerLiteral = struct { - base: Node, - token: Token, - - pub fn iterate(self: &NodeIntegerLiteral, index: usize) ?&Node { - return null; - } - - pub fn firstToken(self: &NodeIntegerLiteral) Token { - return self.token; - } - - pub fn lastToken(self: &NodeIntegerLiteral) Token { - return self.token; - } -}; - -pub const NodeFloatLiteral = struct { - base: Node, - token: Token, - - pub fn iterate(self: &NodeFloatLiteral, index: usize) ?&Node { - return null; - } - - pub fn firstToken(self: &NodeFloatLiteral) Token { - return self.token; - } - - pub fn lastToken(self: &NodeFloatLiteral) Token { - return self.token; - } -}; - -pub const NodeBuiltinCall = struct { - base: Node, - builtin_token: Token, - params: ArrayList(&Node), - rparen_token: Token, - - pub fn iterate(self: &NodeBuiltinCall, index: usize) ?&Node { - var i = index; - - if (i < self.params.len) return self.params.at(i); - i -= self.params.len; - - return null; - } - - pub fn firstToken(self: &NodeBuiltinCall) Token { - return self.builtin_token; - } - - pub fn lastToken(self: &NodeBuiltinCall) Token { - return self.rparen_token; - } -}; - -pub const NodeStringLiteral = struct { - base: Node, - token: Token, - - pub fn iterate(self: &NodeStringLiteral, index: usize) ?&Node { - return null; - } - - pub fn firstToken(self: &NodeStringLiteral) Token { - return self.token; - } - - pub fn lastToken(self: &NodeStringLiteral) Token { - return self.token; - } -}; - -pub const NodeMultilineStringLiteral = struct { - base: Node, - tokens: ArrayList(Token), - - pub fn iterate(self: &NodeMultilineStringLiteral, index: usize) ?&Node { - return null; - } - - pub fn firstToken(self: &NodeMultilineStringLiteral) Token { - return self.tokens.at(0); - } - - pub fn lastToken(self: &NodeMultilineStringLiteral) Token { - return self.tokens.at(self.tokens.len - 1); - } -}; - -pub const NodeCharLiteral = struct { - base: Node, - token: Token, - - pub fn iterate(self: &NodeCharLiteral, index: usize) ?&Node { - return null; - } - - pub fn firstToken(self: &NodeCharLiteral) Token { - return self.token; - } - - pub fn lastToken(self: &NodeCharLiteral) Token { - return self.token; - } -}; - -pub const NodeBoolLiteral = struct { - base: Node, - token: Token, - - pub fn iterate(self: &NodeBoolLiteral, index: usize) ?&Node { - return null; - } - - pub fn firstToken(self: &NodeBoolLiteral) Token { - return self.token; - } - - pub fn lastToken(self: &NodeBoolLiteral) Token { - return self.token; - } -}; - -pub const NodeNullLiteral = struct { - base: Node, - token: Token, - - pub fn iterate(self: &NodeNullLiteral, index: usize) ?&Node { - return null; - } - - pub fn firstToken(self: &NodeNullLiteral) Token { - return self.token; - } - - pub fn lastToken(self: &NodeNullLiteral) Token { - return self.token; - } -}; - -pub const NodeUndefinedLiteral = struct { - base: Node, - token: Token, - - pub fn iterate(self: &NodeUndefinedLiteral, index: usize) ?&Node { - return null; - } - - pub fn firstToken(self: &NodeUndefinedLiteral) Token { - return self.token; - } - - pub fn lastToken(self: &NodeUndefinedLiteral) Token { - return self.token; - } -}; - -pub const NodeThisLiteral = struct { - base: Node, - token: Token, - - pub fn iterate(self: &NodeThisLiteral, index: usize) ?&Node { - return null; - } - - pub fn firstToken(self: &NodeThisLiteral) Token { - return self.token; - } - - pub fn lastToken(self: &NodeThisLiteral) Token { - return self.token; - } -}; - -pub const NodeAsmOutput = struct { - base: Node, - symbolic_name: &Node, - constraint: &Node, - kind: Kind, - - const Kind = union(enum) { - Variable: &NodeIdentifier, - Return: &Node - }; - - pub fn iterate(self: &NodeAsmOutput, index: usize) ?&Node { - var i = index; - - if (i < 1) return self.symbolic_name; - i -= 1; - - if (i < 1) return self.constraint; - i -= 1; - - switch (self.kind) { - Kind.Variable => |variable_name| { - if (i < 1) return &variable_name.base; - i -= 1; - }, - Kind.Return => |return_type| { - if (i < 1) return return_type; - i -= 1; + comptime var i = 0; + inline while (i < @memberCount(Id)) : (i += 1) { + if (base.id == @field(Id, @memberName(Id, i))) { + const T = @field(Node, @memberName(Id, i)); + return @fieldParentPtr(T, "base", base).lastToken(); } } - - return null; + unreachable; } - pub fn firstToken(self: &NodeAsmOutput) Token { - return self.symbolic_name.firstToken(); + pub fn typeToId(comptime T: type) Id { + comptime var i = 0; + inline while (i < @memberCount(Id)) : (i += 1) { + if (T == @field(Node, @memberName(Id, i))) { + return @field(Id, @memberName(Id, i)); + } + } + unreachable; } - pub fn lastToken(self: &NodeAsmOutput) Token { - return switch (self.kind) { - Kind.Variable => |variable_name| variable_name.lastToken(), - Kind.Return => |return_type| return_type.lastToken(), + pub const Root = struct { + base: Node, + decls: ArrayList(&Node), + eof_token: Token, + + pub fn iterate(self: &Root, index: usize) ?&Node { + if (index < self.decls.len) { + return self.decls.items[self.decls.len - index - 1]; + } + return null; + } + + pub fn firstToken(self: &Root) Token { + return if (self.decls.len == 0) self.eof_token else self.decls.at(0).firstToken(); + } + + pub fn lastToken(self: &Root) Token { + return if (self.decls.len == 0) self.eof_token else self.decls.at(self.decls.len - 1).lastToken(); + } + }; + + pub const VarDecl = struct { + base: Node, + comments: ?&LineComment, + visib_token: ?Token, + name_token: Token, + eq_token: Token, + mut_token: Token, + comptime_token: ?Token, + extern_export_token: ?Token, + lib_name: ?&Node, + type_node: ?&Node, + align_node: ?&Node, + init_node: ?&Node, + semicolon_token: Token, + + pub fn iterate(self: &VarDecl, index: usize) ?&Node { + var i = index; + + if (self.type_node) |type_node| { + if (i < 1) return type_node; + i -= 1; + } + + if (self.align_node) |align_node| { + if (i < 1) return align_node; + i -= 1; + } + + if (self.init_node) |init_node| { + if (i < 1) return init_node; + i -= 1; + } + + return null; + } + + pub fn firstToken(self: &VarDecl) Token { + if (self.visib_token) |visib_token| return visib_token; + if (self.comptime_token) |comptime_token| return comptime_token; + if (self.extern_export_token) |extern_export_token| return extern_export_token; + assert(self.lib_name == null); + return self.mut_token; + } + + pub fn lastToken(self: &VarDecl) Token { + return self.semicolon_token; + } + }; + + pub const Use = struct { + base: Node, + visib_token: ?Token, + expr: &Node, + semicolon_token: Token, + + pub fn iterate(self: &Use, index: usize) ?&Node { + var i = index; + + if (i < 1) return self.expr; + i -= 1; + + return null; + } + + pub fn firstToken(self: &Use) Token { + if (self.visib_token) |visib_token| return visib_token; + return self.expr.firstToken(); + } + + pub fn lastToken(self: &Use) Token { + return self.semicolon_token; + } + }; + + pub const ErrorSetDecl = struct { + base: Node, + error_token: Token, + decls: ArrayList(&Node), + rbrace_token: Token, + + pub fn iterate(self: &ErrorSetDecl, index: usize) ?&Node { + var i = index; + + if (i < self.decls.len) return self.decls.at(i); + i -= self.decls.len; + + return null; + } + + pub fn firstToken(self: &ErrorSetDecl) Token { + return self.error_token; + } + + pub fn lastToken(self: &ErrorSetDecl) Token { + return self.rbrace_token; + } + }; + + pub const ContainerDecl = struct { + base: Node, + ltoken: Token, + layout: Layout, + kind: Kind, + init_arg_expr: InitArg, + fields_and_decls: ArrayList(&Node), + rbrace_token: Token, + + const Layout = enum { + Auto, + Extern, + Packed, }; - } + + const Kind = enum { + Struct, + Enum, + Union, + }; + + const InitArg = union(enum) { + None, + Enum, + Type: &Node, + }; + + pub fn iterate(self: &ContainerDecl, index: usize) ?&Node { + var i = index; + + switch (self.init_arg_expr) { + InitArg.Type => |t| { + if (i < 1) return t; + i -= 1; + }, + InitArg.None, + InitArg.Enum => { } + } + + if (i < self.fields_and_decls.len) return self.fields_and_decls.at(i); + i -= self.fields_and_decls.len; + + return null; + } + + pub fn firstToken(self: &ContainerDecl) Token { + return self.ltoken; + } + + pub fn lastToken(self: &ContainerDecl) Token { + return self.rbrace_token; + } + }; + + pub const StructField = struct { + base: Node, + visib_token: ?Token, + name_token: Token, + type_expr: &Node, + + pub fn iterate(self: &StructField, index: usize) ?&Node { + var i = index; + + if (i < 1) return self.type_expr; + i -= 1; + + return null; + } + + pub fn firstToken(self: &StructField) Token { + if (self.visib_token) |visib_token| return visib_token; + return self.name_token; + } + + pub fn lastToken(self: &StructField) Token { + return self.type_expr.lastToken(); + } + }; + + pub const UnionTag = struct { + base: Node, + name_token: Token, + type_expr: ?&Node, + + pub fn iterate(self: &UnionTag, index: usize) ?&Node { + var i = index; + + if (self.type_expr) |type_expr| { + if (i < 1) return type_expr; + i -= 1; + } + + return null; + } + + pub fn firstToken(self: &UnionTag) Token { + return self.name_token; + } + + pub fn lastToken(self: &UnionTag) Token { + if (self.type_expr) |type_expr| { + return type_expr.lastToken(); + } + + return self.name_token; + } + }; + + pub const EnumTag = struct { + base: Node, + name_token: Token, + value: ?&Node, + + pub fn iterate(self: &EnumTag, index: usize) ?&Node { + var i = index; + + if (self.value) |value| { + if (i < 1) return value; + i -= 1; + } + + return null; + } + + pub fn firstToken(self: &EnumTag) Token { + return self.name_token; + } + + pub fn lastToken(self: &EnumTag) Token { + if (self.value) |value| { + return value.lastToken(); + } + + return self.name_token; + } + }; + + pub const Identifier = struct { + base: Node, + token: Token, + + pub fn iterate(self: &Identifier, index: usize) ?&Node { + return null; + } + + pub fn firstToken(self: &Identifier) Token { + return self.token; + } + + pub fn lastToken(self: &Identifier) Token { + return self.token; + } + }; + + pub const AsyncAttribute = struct { + base: Node, + async_token: Token, + allocator_type: ?&Node, + rangle_bracket: ?Token, + + pub fn iterate(self: &AsyncAttribute, index: usize) ?&Node { + var i = index; + + if (self.allocator_type) |allocator_type| { + if (i < 1) return allocator_type; + i -= 1; + } + + return null; + } + + pub fn firstToken(self: &AsyncAttribute) Token { + return self.async_token; + } + + pub fn lastToken(self: &AsyncAttribute) Token { + if (self.rangle_bracket) |rangle_bracket| { + return rangle_bracket; + } + + return self.async_token; + } + }; + + pub const FnProto = struct { + base: Node, + comments: ?&LineComment, + visib_token: ?Token, + fn_token: Token, + name_token: ?Token, + params: ArrayList(&Node), + return_type: ReturnType, + var_args_token: ?Token, + extern_export_inline_token: ?Token, + cc_token: ?Token, + async_attr: ?&AsyncAttribute, + body_node: ?&Node, + lib_name: ?&Node, // populated if this is an extern declaration + align_expr: ?&Node, // populated if align(A) is present + + pub const ReturnType = union(enum) { + Explicit: &Node, + InferErrorSet: &Node, + }; + + pub fn iterate(self: &FnProto, index: usize) ?&Node { + var i = index; + + if (self.body_node) |body_node| { + if (i < 1) return body_node; + i -= 1; + } + + switch (self.return_type) { + // TODO allow this and next prong to share bodies since the types are the same + ReturnType.Explicit => |node| { + if (i < 1) return node; + i -= 1; + }, + ReturnType.InferErrorSet => |node| { + if (i < 1) return node; + i -= 1; + }, + } + + if (self.align_expr) |align_expr| { + if (i < 1) return align_expr; + i -= 1; + } + + if (i < self.params.len) return self.params.items[self.params.len - i - 1]; + i -= self.params.len; + + if (self.lib_name) |lib_name| { + if (i < 1) return lib_name; + i -= 1; + } + + return null; + } + + pub fn firstToken(self: &FnProto) Token { + if (self.visib_token) |visib_token| return visib_token; + if (self.extern_export_inline_token) |extern_export_inline_token| return extern_export_inline_token; + assert(self.lib_name == null); + if (self.cc_token) |cc_token| return cc_token; + return self.fn_token; + } + + pub fn lastToken(self: &FnProto) Token { + if (self.body_node) |body_node| return body_node.lastToken(); + switch (self.return_type) { + // TODO allow this and next prong to share bodies since the types are the same + ReturnType.Explicit => |node| return node.lastToken(), + ReturnType.InferErrorSet => |node| return node.lastToken(), + } + } + }; + + pub const ParamDecl = struct { + base: Node, + comptime_token: ?Token, + noalias_token: ?Token, + name_token: ?Token, + type_node: &Node, + var_args_token: ?Token, + + pub fn iterate(self: &ParamDecl, index: usize) ?&Node { + var i = index; + + if (i < 1) return self.type_node; + i -= 1; + + return null; + } + + pub fn firstToken(self: &ParamDecl) Token { + if (self.comptime_token) |comptime_token| return comptime_token; + if (self.noalias_token) |noalias_token| return noalias_token; + if (self.name_token) |name_token| return name_token; + return self.type_node.firstToken(); + } + + pub fn lastToken(self: &ParamDecl) Token { + if (self.var_args_token) |var_args_token| return var_args_token; + return self.type_node.lastToken(); + } + }; + + pub const Block = struct { + base: Node, + label: ?Token, + lbrace: Token, + statements: ArrayList(&Node), + rbrace: Token, + + pub fn iterate(self: &Block, index: usize) ?&Node { + var i = index; + + if (i < self.statements.len) return self.statements.items[i]; + i -= self.statements.len; + + return null; + } + + pub fn firstToken(self: &Block) Token { + if (self.label) |label| { + return label; + } + + return self.lbrace; + } + + pub fn lastToken(self: &Block) Token { + return self.rbrace; + } + }; + + pub const Defer = struct { + base: Node, + defer_token: Token, + kind: Kind, + expr: &Node, + + const Kind = enum { + Error, + Unconditional, + }; + + pub fn iterate(self: &Defer, index: usize) ?&Node { + var i = index; + + if (i < 1) return self.expr; + i -= 1; + + return null; + } + + pub fn firstToken(self: &Defer) Token { + return self.defer_token; + } + + pub fn lastToken(self: &Defer) Token { + return self.expr.lastToken(); + } + }; + + pub const Comptime = struct { + base: Node, + comptime_token: Token, + expr: &Node, + + pub fn iterate(self: &Comptime, index: usize) ?&Node { + var i = index; + + if (i < 1) return self.expr; + i -= 1; + + return null; + } + + pub fn firstToken(self: &Comptime) Token { + return self.comptime_token; + } + + pub fn lastToken(self: &Comptime) Token { + return self.expr.lastToken(); + } + }; + + pub const Payload = struct { + base: Node, + lpipe: Token, + error_symbol: &Node, + rpipe: Token, + + pub fn iterate(self: &Payload, index: usize) ?&Node { + var i = index; + + if (i < 1) return self.error_symbol; + i -= 1; + + return null; + } + + pub fn firstToken(self: &Payload) Token { + return self.lpipe; + } + + pub fn lastToken(self: &Payload) Token { + return self.rpipe; + } + }; + + pub const PointerPayload = struct { + base: Node, + lpipe: Token, + ptr_token: ?Token, + value_symbol: &Node, + rpipe: Token, + + pub fn iterate(self: &PointerPayload, index: usize) ?&Node { + var i = index; + + if (i < 1) return self.value_symbol; + i -= 1; + + return null; + } + + pub fn firstToken(self: &PointerPayload) Token { + return self.lpipe; + } + + pub fn lastToken(self: &PointerPayload) Token { + return self.rpipe; + } + }; + + pub const PointerIndexPayload = struct { + base: Node, + lpipe: Token, + ptr_token: ?Token, + value_symbol: &Node, + index_symbol: ?&Node, + rpipe: Token, + + pub fn iterate(self: &PointerIndexPayload, index: usize) ?&Node { + var i = index; + + if (i < 1) return self.value_symbol; + i -= 1; + + if (self.index_symbol) |index_symbol| { + if (i < 1) return index_symbol; + i -= 1; + } + + return null; + } + + pub fn firstToken(self: &PointerIndexPayload) Token { + return self.lpipe; + } + + pub fn lastToken(self: &PointerIndexPayload) Token { + return self.rpipe; + } + }; + + pub const Else = struct { + base: Node, + else_token: Token, + payload: ?&Node, + body: &Node, + + pub fn iterate(self: &Else, index: usize) ?&Node { + var i = index; + + if (self.payload) |payload| { + if (i < 1) return payload; + i -= 1; + } + + if (i < 1) return self.body; + i -= 1; + + return null; + } + + pub fn firstToken(self: &Else) Token { + return self.else_token; + } + + pub fn lastToken(self: &Else) Token { + return self.body.lastToken(); + } + }; + + pub const Switch = struct { + base: Node, + switch_token: Token, + expr: &Node, + cases: ArrayList(&SwitchCase), + rbrace: Token, + + pub fn iterate(self: &Switch, index: usize) ?&Node { + var i = index; + + if (i < 1) return self.expr; + i -= 1; + + if (i < self.cases.len) return &self.cases.at(i).base; + i -= self.cases.len; + + return null; + } + + pub fn firstToken(self: &Switch) Token { + return self.switch_token; + } + + pub fn lastToken(self: &Switch) Token { + return self.rbrace; + } + }; + + pub const SwitchCase = struct { + base: Node, + items: ArrayList(&Node), + payload: ?&Node, + expr: &Node, + + pub fn iterate(self: &SwitchCase, index: usize) ?&Node { + var i = index; + + if (i < self.items.len) return self.items.at(i); + i -= self.items.len; + + if (self.payload) |payload| { + if (i < 1) return payload; + i -= 1; + } + + if (i < 1) return self.expr; + i -= 1; + + return null; + } + + pub fn firstToken(self: &SwitchCase) Token { + return self.items.at(0).firstToken(); + } + + pub fn lastToken(self: &SwitchCase) Token { + return self.expr.lastToken(); + } + }; + + pub const SwitchElse = struct { + base: Node, + token: Token, + + pub fn iterate(self: &SwitchElse, index: usize) ?&Node { + return null; + } + + pub fn firstToken(self: &SwitchElse) Token { + return self.token; + } + + pub fn lastToken(self: &SwitchElse) Token { + return self.token; + } + }; + + pub const While = struct { + base: Node, + label: ?Token, + inline_token: ?Token, + while_token: Token, + condition: &Node, + payload: ?&Node, + continue_expr: ?&Node, + body: &Node, + @"else": ?&Else, + + pub fn iterate(self: &While, index: usize) ?&Node { + var i = index; + + if (i < 1) return self.condition; + i -= 1; + + if (self.payload) |payload| { + if (i < 1) return payload; + i -= 1; + } + + if (self.continue_expr) |continue_expr| { + if (i < 1) return continue_expr; + i -= 1; + } + + if (i < 1) return self.body; + i -= 1; + + if (self.@"else") |@"else"| { + if (i < 1) return &@"else".base; + i -= 1; + } + + return null; + } + + pub fn firstToken(self: &While) Token { + if (self.label) |label| { + return label; + } + + if (self.inline_token) |inline_token| { + return inline_token; + } + + return self.while_token; + } + + pub fn lastToken(self: &While) Token { + if (self.@"else") |@"else"| { + return @"else".body.lastToken(); + } + + return self.body.lastToken(); + } + }; + + pub const For = struct { + base: Node, + label: ?Token, + inline_token: ?Token, + for_token: Token, + array_expr: &Node, + payload: ?&Node, + body: &Node, + @"else": ?&Else, + + pub fn iterate(self: &For, index: usize) ?&Node { + var i = index; + + if (i < 1) return self.array_expr; + i -= 1; + + if (self.payload) |payload| { + if (i < 1) return payload; + i -= 1; + } + + if (i < 1) return self.body; + i -= 1; + + if (self.@"else") |@"else"| { + if (i < 1) return &@"else".base; + i -= 1; + } + + return null; + } + + pub fn firstToken(self: &For) Token { + if (self.label) |label| { + return label; + } + + if (self.inline_token) |inline_token| { + return inline_token; + } + + return self.for_token; + } + + pub fn lastToken(self: &For) Token { + if (self.@"else") |@"else"| { + return @"else".body.lastToken(); + } + + return self.body.lastToken(); + } + }; + + pub const If = struct { + base: Node, + if_token: Token, + condition: &Node, + payload: ?&Node, + body: &Node, + @"else": ?&Else, + + pub fn iterate(self: &If, index: usize) ?&Node { + var i = index; + + if (i < 1) return self.condition; + i -= 1; + + if (self.payload) |payload| { + if (i < 1) return payload; + i -= 1; + } + + if (i < 1) return self.body; + i -= 1; + + if (self.@"else") |@"else"| { + if (i < 1) return &@"else".base; + i -= 1; + } + + return null; + } + + pub fn firstToken(self: &If) Token { + return self.if_token; + } + + pub fn lastToken(self: &If) Token { + if (self.@"else") |@"else"| { + return @"else".body.lastToken(); + } + + return self.body.lastToken(); + } + }; + + pub const InfixOp = struct { + base: Node, + op_token: Token, + lhs: &Node, + op: Op, + rhs: &Node, + + pub const Op = union(enum) { + Add, + AddWrap, + ArrayCat, + ArrayMult, + Assign, + AssignBitAnd, + AssignBitOr, + AssignBitShiftLeft, + AssignBitShiftRight, + AssignBitXor, + AssignDiv, + AssignMinus, + AssignMinusWrap, + AssignMod, + AssignPlus, + AssignPlusWrap, + AssignTimes, + AssignTimesWarp, + BangEqual, + BitAnd, + BitOr, + BitShiftLeft, + BitShiftRight, + BitXor, + BoolAnd, + BoolOr, + Catch: ?&Node, + Div, + EqualEqual, + ErrorUnion, + GreaterOrEqual, + GreaterThan, + LessOrEqual, + LessThan, + MergeErrorSets, + Mod, + Mult, + MultWrap, + Period, + Range, + Sub, + SubWrap, + UnwrapMaybe, + }; + + pub fn iterate(self: &InfixOp, index: usize) ?&Node { + var i = index; + + if (i < 1) return self.lhs; + i -= 1; + + switch (self.op) { + Op.Catch => |maybe_payload| { + if (maybe_payload) |payload| { + if (i < 1) return payload; + i -= 1; + } + }, + + Op.Add, + Op.AddWrap, + Op.ArrayCat, + Op.ArrayMult, + Op.Assign, + Op.AssignBitAnd, + Op.AssignBitOr, + Op.AssignBitShiftLeft, + Op.AssignBitShiftRight, + Op.AssignBitXor, + Op.AssignDiv, + Op.AssignMinus, + Op.AssignMinusWrap, + Op.AssignMod, + Op.AssignPlus, + Op.AssignPlusWrap, + Op.AssignTimes, + Op.AssignTimesWarp, + Op.BangEqual, + Op.BitAnd, + Op.BitOr, + Op.BitShiftLeft, + Op.BitShiftRight, + Op.BitXor, + Op.BoolAnd, + Op.BoolOr, + Op.Div, + Op.EqualEqual, + Op.ErrorUnion, + Op.GreaterOrEqual, + Op.GreaterThan, + Op.LessOrEqual, + Op.LessThan, + Op.MergeErrorSets, + Op.Mod, + Op.Mult, + Op.MultWrap, + Op.Period, + Op.Range, + Op.Sub, + Op.SubWrap, + Op.UnwrapMaybe => {}, + } + + if (i < 1) return self.rhs; + i -= 1; + + return null; + } + + pub fn firstToken(self: &InfixOp) Token { + return self.lhs.firstToken(); + } + + pub fn lastToken(self: &InfixOp) Token { + return self.rhs.lastToken(); + } + }; + + pub const PrefixOp = struct { + base: Node, + op_token: Token, + op: Op, + rhs: &Node, + + const Op = union(enum) { + AddrOf: AddrOfInfo, + ArrayType: &Node, + Await, + BitNot, + BoolNot, + Cancel, + Deref, + MaybeType, + Negation, + NegationWrap, + Resume, + SliceType: AddrOfInfo, + Try, + UnwrapMaybe, + }; + + const AddrOfInfo = struct { + align_expr: ?&Node, + bit_offset_start_token: ?Token, + bit_offset_end_token: ?Token, + const_token: ?Token, + volatile_token: ?Token, + }; + + pub fn iterate(self: &PrefixOp, index: usize) ?&Node { + var i = index; + + switch (self.op) { + Op.SliceType => |addr_of_info| { + if (addr_of_info.align_expr) |align_expr| { + if (i < 1) return align_expr; + i -= 1; + } + }, + Op.AddrOf => |addr_of_info| { + if (addr_of_info.align_expr) |align_expr| { + if (i < 1) return align_expr; + i -= 1; + } + }, + Op.ArrayType => |size_expr| { + if (i < 1) return size_expr; + i -= 1; + }, + Op.Await, + Op.BitNot, + Op.BoolNot, + Op.Cancel, + Op.Deref, + Op.MaybeType, + Op.Negation, + Op.NegationWrap, + Op.Try, + Op.Resume, + Op.UnwrapMaybe => {}, + } + + if (i < 1) return self.rhs; + i -= 1; + + return null; + } + + pub fn firstToken(self: &PrefixOp) Token { + return self.op_token; + } + + pub fn lastToken(self: &PrefixOp) Token { + return self.rhs.lastToken(); + } + }; + + pub const FieldInitializer = struct { + base: Node, + period_token: Token, + name_token: Token, + expr: &Node, + + pub fn iterate(self: &FieldInitializer, index: usize) ?&Node { + var i = index; + + if (i < 1) return self.expr; + i -= 1; + + return null; + } + + pub fn firstToken(self: &FieldInitializer) Token { + return self.period_token; + } + + pub fn lastToken(self: &FieldInitializer) Token { + return self.expr.lastToken(); + } + }; + + pub const SuffixOp = struct { + base: Node, + lhs: &Node, + op: Op, + rtoken: Token, + + const Op = union(enum) { + Call: CallInfo, + ArrayAccess: &Node, + Slice: SliceRange, + ArrayInitializer: ArrayList(&Node), + StructInitializer: ArrayList(&FieldInitializer), + }; + + const CallInfo = struct { + params: ArrayList(&Node), + async_attr: ?&AsyncAttribute, + }; + + const SliceRange = struct { + start: &Node, + end: ?&Node, + }; + + pub fn iterate(self: &SuffixOp, index: usize) ?&Node { + var i = index; + + if (i < 1) return self.lhs; + i -= 1; + + switch (self.op) { + Op.Call => |call_info| { + if (i < call_info.params.len) return call_info.params.at(i); + i -= call_info.params.len; + }, + Op.ArrayAccess => |index_expr| { + if (i < 1) return index_expr; + i -= 1; + }, + Op.Slice => |range| { + if (i < 1) return range.start; + i -= 1; + + if (range.end) |end| { + if (i < 1) return end; + i -= 1; + } + }, + Op.ArrayInitializer => |exprs| { + if (i < exprs.len) return exprs.at(i); + i -= exprs.len; + }, + Op.StructInitializer => |fields| { + if (i < fields.len) return &fields.at(i).base; + i -= fields.len; + }, + } + + return null; + } + + pub fn firstToken(self: &SuffixOp) Token { + return self.lhs.firstToken(); + } + + pub fn lastToken(self: &SuffixOp) Token { + return self.rtoken; + } + }; + + pub const GroupedExpression = struct { + base: Node, + lparen: Token, + expr: &Node, + rparen: Token, + + pub fn iterate(self: &GroupedExpression, index: usize) ?&Node { + var i = index; + + if (i < 1) return self.expr; + i -= 1; + + return null; + } + + pub fn firstToken(self: &GroupedExpression) Token { + return self.lparen; + } + + pub fn lastToken(self: &GroupedExpression) Token { + return self.rparen; + } + }; + + pub const ControlFlowExpression = struct { + base: Node, + ltoken: Token, + kind: Kind, + rhs: ?&Node, + + const Kind = union(enum) { + Break: ?&Node, + Continue: ?&Node, + Return, + }; + + pub fn iterate(self: &ControlFlowExpression, index: usize) ?&Node { + var i = index; + + switch (self.kind) { + Kind.Break => |maybe_label| { + if (maybe_label) |label| { + if (i < 1) return label; + i -= 1; + } + }, + Kind.Continue => |maybe_label| { + if (maybe_label) |label| { + if (i < 1) return label; + i -= 1; + } + }, + Kind.Return => {}, + } + + if (self.rhs) |rhs| { + if (i < 1) return rhs; + i -= 1; + } + + return null; + } + + pub fn firstToken(self: &ControlFlowExpression) Token { + return self.ltoken; + } + + pub fn lastToken(self: &ControlFlowExpression) Token { + if (self.rhs) |rhs| { + return rhs.lastToken(); + } + + switch (self.kind) { + Kind.Break => |maybe_label| { + if (maybe_label) |label| { + return label.lastToken(); + } + }, + Kind.Continue => |maybe_label| { + if (maybe_label) |label| { + return label.lastToken(); + } + }, + Kind.Return => return self.ltoken, + } + + return self.ltoken; + } + }; + + pub const Suspend = struct { + base: Node, + suspend_token: Token, + payload: ?&Node, + body: ?&Node, + + pub fn iterate(self: &Suspend, index: usize) ?&Node { + var i = index; + + if (self.payload) |payload| { + if (i < 1) return payload; + i -= 1; + } + + if (self.body) |body| { + if (i < 1) return body; + i -= 1; + } + + return null; + } + + pub fn firstToken(self: &Suspend) Token { + return self.suspend_token; + } + + pub fn lastToken(self: &Suspend) Token { + if (self.body) |body| { + return body.lastToken(); + } + + if (self.payload) |payload| { + return payload.lastToken(); + } + + return self.suspend_token; + } + }; + + pub const IntegerLiteral = struct { + base: Node, + token: Token, + + pub fn iterate(self: &IntegerLiteral, index: usize) ?&Node { + return null; + } + + pub fn firstToken(self: &IntegerLiteral) Token { + return self.token; + } + + pub fn lastToken(self: &IntegerLiteral) Token { + return self.token; + } + }; + + pub const FloatLiteral = struct { + base: Node, + token: Token, + + pub fn iterate(self: &FloatLiteral, index: usize) ?&Node { + return null; + } + + pub fn firstToken(self: &FloatLiteral) Token { + return self.token; + } + + pub fn lastToken(self: &FloatLiteral) Token { + return self.token; + } + }; + + pub const BuiltinCall = struct { + base: Node, + builtin_token: Token, + params: ArrayList(&Node), + rparen_token: Token, + + pub fn iterate(self: &BuiltinCall, index: usize) ?&Node { + var i = index; + + if (i < self.params.len) return self.params.at(i); + i -= self.params.len; + + return null; + } + + pub fn firstToken(self: &BuiltinCall) Token { + return self.builtin_token; + } + + pub fn lastToken(self: &BuiltinCall) Token { + return self.rparen_token; + } + }; + + pub const StringLiteral = struct { + base: Node, + token: Token, + + pub fn iterate(self: &StringLiteral, index: usize) ?&Node { + return null; + } + + pub fn firstToken(self: &StringLiteral) Token { + return self.token; + } + + pub fn lastToken(self: &StringLiteral) Token { + return self.token; + } + }; + + pub const MultilineStringLiteral = struct { + base: Node, + tokens: ArrayList(Token), + + pub fn iterate(self: &MultilineStringLiteral, index: usize) ?&Node { + return null; + } + + pub fn firstToken(self: &MultilineStringLiteral) Token { + return self.tokens.at(0); + } + + pub fn lastToken(self: &MultilineStringLiteral) Token { + return self.tokens.at(self.tokens.len - 1); + } + }; + + pub const CharLiteral = struct { + base: Node, + token: Token, + + pub fn iterate(self: &CharLiteral, index: usize) ?&Node { + return null; + } + + pub fn firstToken(self: &CharLiteral) Token { + return self.token; + } + + pub fn lastToken(self: &CharLiteral) Token { + return self.token; + } + }; + + pub const BoolLiteral = struct { + base: Node, + token: Token, + + pub fn iterate(self: &BoolLiteral, index: usize) ?&Node { + return null; + } + + pub fn firstToken(self: &BoolLiteral) Token { + return self.token; + } + + pub fn lastToken(self: &BoolLiteral) Token { + return self.token; + } + }; + + pub const NullLiteral = struct { + base: Node, + token: Token, + + pub fn iterate(self: &NullLiteral, index: usize) ?&Node { + return null; + } + + pub fn firstToken(self: &NullLiteral) Token { + return self.token; + } + + pub fn lastToken(self: &NullLiteral) Token { + return self.token; + } + }; + + pub const UndefinedLiteral = struct { + base: Node, + token: Token, + + pub fn iterate(self: &UndefinedLiteral, index: usize) ?&Node { + return null; + } + + pub fn firstToken(self: &UndefinedLiteral) Token { + return self.token; + } + + pub fn lastToken(self: &UndefinedLiteral) Token { + return self.token; + } + }; + + pub const ThisLiteral = struct { + base: Node, + token: Token, + + pub fn iterate(self: &ThisLiteral, index: usize) ?&Node { + return null; + } + + pub fn firstToken(self: &ThisLiteral) Token { + return self.token; + } + + pub fn lastToken(self: &ThisLiteral) Token { + return self.token; + } + }; + + pub const AsmOutput = struct { + base: Node, + symbolic_name: &Node, + constraint: &Node, + kind: Kind, + + const Kind = union(enum) { + Variable: &Identifier, + Return: &Node + }; + + pub fn iterate(self: &AsmOutput, index: usize) ?&Node { + var i = index; + + if (i < 1) return self.symbolic_name; + i -= 1; + + if (i < 1) return self.constraint; + i -= 1; + + switch (self.kind) { + Kind.Variable => |variable_name| { + if (i < 1) return &variable_name.base; + i -= 1; + }, + Kind.Return => |return_type| { + if (i < 1) return return_type; + i -= 1; + } + } + + return null; + } + + pub fn firstToken(self: &AsmOutput) Token { + return self.symbolic_name.firstToken(); + } + + pub fn lastToken(self: &AsmOutput) Token { + return switch (self.kind) { + Kind.Variable => |variable_name| variable_name.lastToken(), + Kind.Return => |return_type| return_type.lastToken(), + }; + } + }; + + pub const AsmInput = struct { + base: Node, + symbolic_name: &Node, + constraint: &Node, + expr: &Node, + + pub fn iterate(self: &AsmInput, index: usize) ?&Node { + var i = index; + + if (i < 1) return self.symbolic_name; + i -= 1; + + if (i < 1) return self.constraint; + i -= 1; + + if (i < 1) return self.expr; + i -= 1; + + return null; + } + + pub fn firstToken(self: &AsmInput) Token { + return self.symbolic_name.firstToken(); + } + + pub fn lastToken(self: &AsmInput) Token { + return self.expr.lastToken(); + } + }; + + pub const Asm = struct { + base: Node, + asm_token: Token, + volatile_token: ?Token, + template: &Node, + //tokens: ArrayList(AsmToken), + outputs: ArrayList(&AsmOutput), + inputs: ArrayList(&AsmInput), + cloppers: ArrayList(&Node), + rparen: Token, + + pub fn iterate(self: &Asm, index: usize) ?&Node { + var i = index; + + if (i < self.outputs.len) return &self.outputs.at(index).base; + i -= self.outputs.len; + + if (i < self.inputs.len) return &self.inputs.at(index).base; + i -= self.inputs.len; + + if (i < self.cloppers.len) return self.cloppers.at(index); + i -= self.cloppers.len; + + return null; + } + + pub fn firstToken(self: &Asm) Token { + return self.asm_token; + } + + pub fn lastToken(self: &Asm) Token { + return self.rparen; + } + }; + + pub const Unreachable = struct { + base: Node, + token: Token, + + pub fn iterate(self: &Unreachable, index: usize) ?&Node { + return null; + } + + pub fn firstToken(self: &Unreachable) Token { + return self.token; + } + + pub fn lastToken(self: &Unreachable) Token { + return self.token; + } + }; + + pub const ErrorType = struct { + base: Node, + token: Token, + + pub fn iterate(self: &ErrorType, index: usize) ?&Node { + return null; + } + + pub fn firstToken(self: &ErrorType) Token { + return self.token; + } + + pub fn lastToken(self: &ErrorType) Token { + return self.token; + } + }; + + pub const VarType = struct { + base: Node, + token: Token, + + pub fn iterate(self: &VarType, index: usize) ?&Node { + return null; + } + + pub fn firstToken(self: &VarType) Token { + return self.token; + } + + pub fn lastToken(self: &VarType) Token { + return self.token; + } + }; + + pub const LineComment = struct { + base: Node, + lines: ArrayList(Token), + + pub fn iterate(self: &LineComment, index: usize) ?&Node { + return null; + } + + pub fn firstToken(self: &LineComment) Token { + return self.lines.at(0); + } + + pub fn lastToken(self: &LineComment) Token { + return self.lines.at(self.lines.len - 1); + } + }; + + pub const TestDecl = struct { + base: Node, + comments: ?&LineComment, + test_token: Token, + name: &Node, + body_node: &Node, + + pub fn iterate(self: &TestDecl, index: usize) ?&Node { + var i = index; + + if (i < 1) return self.body_node; + i -= 1; + + return null; + } + + pub fn firstToken(self: &TestDecl) Token { + return self.test_token; + } + + pub fn lastToken(self: &TestDecl) Token { + return self.body_node.lastToken(); + } + }; }; -pub const NodeAsmInput = struct { - base: Node, - symbolic_name: &Node, - constraint: &Node, - expr: &Node, - - pub fn iterate(self: &NodeAsmInput, index: usize) ?&Node { - var i = index; - - if (i < 1) return self.symbolic_name; - i -= 1; - - if (i < 1) return self.constraint; - i -= 1; - - if (i < 1) return self.expr; - i -= 1; - - return null; - } - - pub fn firstToken(self: &NodeAsmInput) Token { - return self.symbolic_name.firstToken(); - } - - pub fn lastToken(self: &NodeAsmInput) Token { - return self.expr.lastToken(); - } -}; - -pub const NodeAsm = struct { - base: Node, - asm_token: Token, - volatile_token: ?Token, - template: &Node, - //tokens: ArrayList(AsmToken), - outputs: ArrayList(&NodeAsmOutput), - inputs: ArrayList(&NodeAsmInput), - cloppers: ArrayList(&Node), - rparen: Token, - - pub fn iterate(self: &NodeAsm, index: usize) ?&Node { - var i = index; - - if (i < self.outputs.len) return &self.outputs.at(index).base; - i -= self.outputs.len; - - if (i < self.inputs.len) return &self.inputs.at(index).base; - i -= self.inputs.len; - - if (i < self.cloppers.len) return self.cloppers.at(index); - i -= self.cloppers.len; - - return null; - } - - pub fn firstToken(self: &NodeAsm) Token { - return self.asm_token; - } - - pub fn lastToken(self: &NodeAsm) Token { - return self.rparen; - } -}; - -pub const NodeUnreachable = struct { - base: Node, - token: Token, - - pub fn iterate(self: &NodeUnreachable, index: usize) ?&Node { - return null; - } - - pub fn firstToken(self: &NodeUnreachable) Token { - return self.token; - } - - pub fn lastToken(self: &NodeUnreachable) Token { - return self.token; - } -}; - -pub const NodeErrorType = struct { - base: Node, - token: Token, - - pub fn iterate(self: &NodeErrorType, index: usize) ?&Node { - return null; - } - - pub fn firstToken(self: &NodeErrorType) Token { - return self.token; - } - - pub fn lastToken(self: &NodeErrorType) Token { - return self.token; - } -}; - -pub const NodeVarType = struct { - base: Node, - token: Token, - - pub fn iterate(self: &NodeVarType, index: usize) ?&Node { - return null; - } - - pub fn firstToken(self: &NodeVarType) Token { - return self.token; - } - - pub fn lastToken(self: &NodeVarType) Token { - return self.token; - } -}; - -pub const NodeLineComment = struct { - base: Node, - lines: ArrayList(Token), - - pub fn iterate(self: &NodeLineComment, index: usize) ?&Node { - return null; - } - - pub fn firstToken(self: &NodeLineComment) Token { - return self.lines.at(0); - } - - pub fn lastToken(self: &NodeLineComment) Token { - return self.lines.at(self.lines.len - 1); - } -}; - -pub const NodeTestDecl = struct { - base: Node, - test_token: Token, - name: &Node, - body_node: &Node, - - pub fn iterate(self: &NodeTestDecl, index: usize) ?&Node { - var i = index; - - if (i < 1) return self.body_node; - i -= 1; - - return null; - } - - pub fn firstToken(self: &NodeTestDecl) Token { - return self.test_token; - } - - pub fn lastToken(self: &NodeTestDecl) Token { - return self.body_node.lastToken(); - } -}; diff --git a/std/zig/parser.zig b/std/zig/parser.zig index c0708581ea..017d293491 100644 --- a/std/zig/parser.zig +++ b/std/zig/parser.zig @@ -18,10 +18,10 @@ pub const Parser = struct { put_back_tokens: [2]Token, put_back_count: usize, source_file_name: []const u8, - pending_line_comment_node: ?&ast.NodeLineComment, + pending_line_comment_node: ?&ast.Node.LineComment, pub const Tree = struct { - root_node: &ast.NodeRoot, + root_node: &ast.Node.Root, arena_allocator: std.heap.ArenaAllocator, pub fn deinit(self: &Tree) void { @@ -66,22 +66,24 @@ pub const Parser = struct { extern_export_token: ?Token, lib_name: ?&ast.Node, list: &ArrayList(&ast.Node), + comments: ?&ast.Node.LineComment, }; const TopLevelExternOrFieldCtx = struct { visib_token: Token, - container_decl: &ast.NodeContainerDecl, + container_decl: &ast.Node.ContainerDecl, }; const ExternTypeCtx = struct { opt_ctx: OptionalCtx, extern_token: Token, + comments: ?&ast.Node.LineComment, }; const ContainerKindCtx = struct { opt_ctx: OptionalCtx, ltoken: Token, - layout: ast.NodeContainerDecl.Layout, + layout: ast.Node.ContainerDecl.Layout, }; const ExpectTokenSave = struct { @@ -132,7 +134,7 @@ pub const Parser = struct { const AsyncEndCtx = struct { ctx: OptionalCtx, - attribute: &ast.NodeAsyncAttribute, + attribute: &ast.Node.AsyncAttribute, }; const ErrorTypeOrSetDeclCtx = struct { @@ -141,13 +143,13 @@ pub const Parser = struct { }; const ParamDeclEndCtx = struct { - fn_proto: &ast.NodeFnProto, - param_decl: &ast.NodeParamDecl, + fn_proto: &ast.Node.FnProto, + param_decl: &ast.Node.ParamDecl, }; const ComptimeStatementCtx = struct { comptime_token: Token, - block: &ast.NodeBlock, + block: &ast.Node.Block, }; const OptionalCtx = union(enum) { @@ -190,24 +192,24 @@ pub const Parser = struct { TopLevelExternOrField: TopLevelExternOrFieldCtx, ContainerKind: ContainerKindCtx, - ContainerInitArgStart: &ast.NodeContainerDecl, - ContainerInitArg: &ast.NodeContainerDecl, - ContainerDecl: &ast.NodeContainerDecl, + ContainerInitArgStart: &ast.Node.ContainerDecl, + ContainerInitArg: &ast.Node.ContainerDecl, + ContainerDecl: &ast.Node.ContainerDecl, VarDecl: VarDeclCtx, - VarDeclAlign: &ast.NodeVarDecl, - VarDeclEq: &ast.NodeVarDecl, + VarDeclAlign: &ast.Node.VarDecl, + VarDeclEq: &ast.Node.VarDecl, - FnDef: &ast.NodeFnProto, - FnProto: &ast.NodeFnProto, - FnProtoAlign: &ast.NodeFnProto, - FnProtoReturnType: &ast.NodeFnProto, + FnDef: &ast.Node.FnProto, + FnProto: &ast.Node.FnProto, + FnProtoAlign: &ast.Node.FnProto, + FnProtoReturnType: &ast.Node.FnProto, - ParamDecl: &ast.NodeFnProto, - ParamDeclAliasOrComptime: &ast.NodeParamDecl, - ParamDeclName: &ast.NodeParamDecl, + ParamDecl: &ast.Node.FnProto, + ParamDeclAliasOrComptime: &ast.Node.ParamDecl, + ParamDeclName: &ast.Node.ParamDecl, ParamDeclEnd: ParamDeclEndCtx, - ParamDeclComma: &ast.NodeFnProto, + ParamDeclComma: &ast.Node.FnProto, MaybeLabeledExpression: MaybeLabeledExpressionCtx, LabeledExpression: LabelCtx, @@ -215,39 +217,39 @@ pub const Parser = struct { While: LoopCtx, WhileContinueExpr: &?&ast.Node, For: LoopCtx, - Else: &?&ast.NodeElse, + Else: &?&ast.Node.Else, - Block: &ast.NodeBlock, - Statement: &ast.NodeBlock, + Block: &ast.Node.Block, + Statement: &ast.Node.Block, ComptimeStatement: ComptimeStatementCtx, Semicolon: &&ast.Node, - AsmOutputItems: &ArrayList(&ast.NodeAsmOutput), - AsmOutputReturnOrType: &ast.NodeAsmOutput, - AsmInputItems: &ArrayList(&ast.NodeAsmInput), + AsmOutputItems: &ArrayList(&ast.Node.AsmOutput), + AsmOutputReturnOrType: &ast.Node.AsmOutput, + AsmInputItems: &ArrayList(&ast.Node.AsmInput), AsmClopperItems: &ArrayList(&ast.Node), ExprListItemOrEnd: ExprListCtx, ExprListCommaOrEnd: ExprListCtx, - FieldInitListItemOrEnd: ListSave(&ast.NodeFieldInitializer), - FieldInitListCommaOrEnd: ListSave(&ast.NodeFieldInitializer), - FieldListCommaOrEnd: &ast.NodeContainerDecl, + FieldInitListItemOrEnd: ListSave(&ast.Node.FieldInitializer), + FieldInitListCommaOrEnd: ListSave(&ast.Node.FieldInitializer), + FieldListCommaOrEnd: &ast.Node.ContainerDecl, IdentifierListItemOrEnd: ListSave(&ast.Node), IdentifierListCommaOrEnd: ListSave(&ast.Node), - SwitchCaseOrEnd: ListSave(&ast.NodeSwitchCase), - SwitchCaseCommaOrEnd: ListSave(&ast.NodeSwitchCase), + SwitchCaseOrEnd: ListSave(&ast.Node.SwitchCase), + SwitchCaseCommaOrEnd: ListSave(&ast.Node.SwitchCase), SwitchCaseFirstItem: &ArrayList(&ast.Node), SwitchCaseItem: &ArrayList(&ast.Node), SwitchCaseItemCommaOrEnd: &ArrayList(&ast.Node), - SuspendBody: &ast.NodeSuspend, - AsyncAllocator: &ast.NodeAsyncAttribute, + SuspendBody: &ast.Node.Suspend, + AsyncAllocator: &ast.Node.AsyncAttribute, AsyncEnd: AsyncEndCtx, ExternType: ExternTypeCtx, - SliceOrArrayAccess: &ast.NodeSuffixOp, - SliceOrArrayType: &ast.NodePrefixOp, - AddrOfModifiers: &ast.NodePrefixOp.AddrOfInfo, + SliceOrArrayAccess: &ast.Node.SuffixOp, + SliceOrArrayType: &ast.Node.PrefixOp, + AddrOfModifiers: &ast.Node.PrefixOp.AddrOfInfo, Payload: OptionalCtx, PointerPayload: OptionalCtx, @@ -310,8 +312,8 @@ pub const Parser = struct { errdefer arena_allocator.deinit(); const arena = &arena_allocator.allocator; - const root_node = try self.createNode(arena, ast.NodeRoot, - ast.NodeRoot { + const root_node = try self.createNode(arena, ast.Node.Root, + ast.Node.Root { .base = undefined, .decls = ArrayList(&ast.Node).init(arena), // initialized when we get the eof token @@ -334,43 +336,19 @@ pub const Parser = struct { // warn("\n"); //} - // look for line comments - while (true) { - if (self.eatToken(Token.Id.LineComment)) |line_comment| { - const node = blk: { - if (self.pending_line_comment_node) |comment_node| { - break :blk comment_node; - } else { - const comment_node = try arena.create(ast.NodeLineComment); - *comment_node = ast.NodeLineComment { - .base = ast.Node { - .id = ast.Node.Id.LineComment, - .comment = null, - }, - .lines = ArrayList(Token).init(arena), - }; - self.pending_line_comment_node = comment_node; - break :blk comment_node; - } - }; - try node.lines.append(line_comment); - continue; - } - break; - } - // This gives us 1 free append that can't fail const state = stack.pop(); switch (state) { State.TopLevel => { + const comments = try self.eatComments(arena); const token = self.getNextToken(); switch (token.id) { Token.Id.Keyword_test => { stack.append(State.TopLevel) catch unreachable; - const block = try self.createNode(arena, ast.NodeBlock, - ast.NodeBlock { + const block = try self.createNode(arena, ast.Node.Block, + ast.Node.Block { .base = undefined, .label = null, .lbrace = undefined, @@ -378,9 +356,10 @@ pub const Parser = struct { .rbrace = undefined, } ); - const test_node = try self.createAttachNode(arena, &root_node.decls, ast.NodeTestDecl, - ast.NodeTestDecl { + const test_node = try self.createAttachNode(arena, &root_node.decls, ast.Node.TestDecl, + ast.Node.TestDecl { .base = undefined, + .comments = comments, .test_token = token, .name = undefined, .body_node = &block.base, @@ -413,8 +392,8 @@ pub const Parser = struct { continue; }, Token.Id.Keyword_comptime => { - const block = try self.createNode(arena, ast.NodeBlock, - ast.NodeBlock { + const block = try self.createNode(arena, ast.Node.Block, + ast.Node.Block { .base = undefined, .label = null, .lbrace = undefined, @@ -422,8 +401,8 @@ pub const Parser = struct { .rbrace = undefined, } ); - const node = try self.createAttachNode(arena, &root_node.decls, ast.NodeComptime, - ast.NodeComptime { + const node = try self.createAttachNode(arena, &root_node.decls, ast.Node.Comptime, + ast.Node.Comptime { .base = undefined, .comptime_token = token, .expr = &block.base, @@ -506,6 +485,7 @@ pub const Parser = struct { continue; }, State.TopLevelDecl => |ctx| { + const comments = try self.eatComments(arena); const token = self.getNextToken(); switch (token.id) { Token.Id.Keyword_use => { @@ -513,8 +493,8 @@ pub const Parser = struct { return self.parseError(token, "Invalid token {}", @tagName((??ctx.extern_export_inline_token).id)); } - const node = try self.createAttachNode(arena, ctx.decls, ast.NodeUse, - ast.NodeUse { + const node = try self.createAttachNode(arena, ctx.decls, ast.Node.Use, + ast.Node.Use { .base = undefined, .visib_token = ctx.visib_token, .expr = undefined, @@ -539,6 +519,7 @@ pub const Parser = struct { stack.append(State { .VarDecl = VarDeclCtx { + .comments = comments, .visib_token = ctx.visib_token, .lib_name = ctx.lib_name, .comptime_token = null, @@ -551,9 +532,10 @@ pub const Parser = struct { }, Token.Id.Keyword_fn, Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc, Token.Id.Keyword_async => { - const fn_proto = try self.createAttachNode(arena, ctx.decls, ast.NodeFnProto, - ast.NodeFnProto { + const fn_proto = try self.createAttachNode(arena, ctx.decls, ast.Node.FnProto, + ast.Node.FnProto { .base = undefined, + .comments = comments, .visib_token = ctx.visib_token, .name_token = null, .fn_token = undefined, @@ -583,8 +565,8 @@ pub const Parser = struct { continue; }, Token.Id.Keyword_async => { - const async_node = try self.createNode(arena, ast.NodeAsyncAttribute, - ast.NodeAsyncAttribute { + const async_node = try self.createNode(arena, ast.Node.AsyncAttribute, + ast.Node.AsyncAttribute { .base = undefined, .async_token = token, .allocator_type = null, @@ -616,9 +598,9 @@ pub const Parser = struct { }, State.TopLevelExternOrField => |ctx| { if (self.eatToken(Token.Id.Identifier)) |identifier| { - std.debug.assert(ctx.container_decl.kind == ast.NodeContainerDecl.Kind.Struct); - const node = try self.createAttachNode(arena, &ctx.container_decl.fields_and_decls, ast.NodeStructField, - ast.NodeStructField { + std.debug.assert(ctx.container_decl.kind == ast.Node.ContainerDecl.Kind.Struct); + const node = try self.createAttachNode(arena, &ctx.container_decl.fields_and_decls, ast.Node.StructField, + ast.Node.StructField { .base = undefined, .visib_token = ctx.visib_token, .name_token = identifier, @@ -647,15 +629,15 @@ pub const Parser = struct { State.ContainerKind => |ctx| { const token = self.getNextToken(); - const node = try self.createToCtxNode(arena, ctx.opt_ctx, ast.NodeContainerDecl, - ast.NodeContainerDecl { + const node = try self.createToCtxNode(arena, ctx.opt_ctx, ast.Node.ContainerDecl, + ast.Node.ContainerDecl { .base = undefined, .ltoken = ctx.ltoken, .layout = ctx.layout, .kind = switch (token.id) { - Token.Id.Keyword_struct => ast.NodeContainerDecl.Kind.Struct, - Token.Id.Keyword_union => ast.NodeContainerDecl.Kind.Union, - Token.Id.Keyword_enum => ast.NodeContainerDecl.Kind.Enum, + Token.Id.Keyword_struct => ast.Node.ContainerDecl.Kind.Struct, + Token.Id.Keyword_union => ast.Node.ContainerDecl.Kind.Union, + Token.Id.Keyword_enum => ast.Node.ContainerDecl.Kind.Enum, else => { return self.parseError(token, "expected {}, {} or {}, found {}", @tagName(Token.Id.Keyword_struct), @@ -664,7 +646,7 @@ pub const Parser = struct { @tagName(token.id)); }, }, - .init_arg_expr = ast.NodeContainerDecl.InitArg.None, + .init_arg_expr = ast.Node.ContainerDecl.InitArg.None, .fields_and_decls = ArrayList(&ast.Node).init(arena), .rbrace_token = undefined, } @@ -690,11 +672,11 @@ pub const Parser = struct { const init_arg_token = self.getNextToken(); switch (init_arg_token.id) { Token.Id.Keyword_enum => { - container_decl.init_arg_expr = ast.NodeContainerDecl.InitArg.Enum; + container_decl.init_arg_expr = ast.Node.ContainerDecl.InitArg.Enum; }, else => { self.putBackToken(init_arg_token); - container_decl.init_arg_expr = ast.NodeContainerDecl.InitArg { .Type = undefined }; + container_decl.init_arg_expr = ast.Node.ContainerDecl.InitArg { .Type = undefined }; stack.append(State { .Expression = OptionalCtx { .Required = &container_decl.init_arg_expr.Type } }) catch unreachable; }, } @@ -705,9 +687,9 @@ pub const Parser = struct { switch (token.id) { Token.Id.Identifier => { switch (container_decl.kind) { - ast.NodeContainerDecl.Kind.Struct => { - const node = try self.createAttachNode(arena, &container_decl.fields_and_decls, ast.NodeStructField, - ast.NodeStructField { + ast.Node.ContainerDecl.Kind.Struct => { + const node = try self.createAttachNode(arena, &container_decl.fields_and_decls, ast.Node.StructField, + ast.Node.StructField { .base = undefined, .visib_token = null, .name_token = token, @@ -720,9 +702,9 @@ pub const Parser = struct { try stack.append(State { .ExpectToken = Token.Id.Colon }); continue; }, - ast.NodeContainerDecl.Kind.Union => { - const node = try self.createAttachNode(arena, &container_decl.fields_and_decls, ast.NodeUnionTag, - ast.NodeUnionTag { + ast.Node.ContainerDecl.Kind.Union => { + const node = try self.createAttachNode(arena, &container_decl.fields_and_decls, ast.Node.UnionTag, + ast.Node.UnionTag { .base = undefined, .name_token = token, .type_expr = null, @@ -734,9 +716,9 @@ pub const Parser = struct { try stack.append(State { .IfToken = Token.Id.Colon }); continue; }, - ast.NodeContainerDecl.Kind.Enum => { - const node = try self.createAttachNode(arena, &container_decl.fields_and_decls, ast.NodeEnumTag, - ast.NodeEnumTag { + ast.Node.ContainerDecl.Kind.Enum => { + const node = try self.createAttachNode(arena, &container_decl.fields_and_decls, ast.Node.EnumTag, + ast.Node.EnumTag { .base = undefined, .name_token = token, .value = null, @@ -752,7 +734,7 @@ pub const Parser = struct { }, Token.Id.Keyword_pub => { switch (container_decl.kind) { - ast.NodeContainerDecl.Kind.Struct => { + ast.Node.ContainerDecl.Kind.Struct => { try stack.append(State { .TopLevelExternOrField = TopLevelExternOrFieldCtx { .visib_token = token, @@ -809,9 +791,10 @@ pub const Parser = struct { State.VarDecl => |ctx| { - const var_decl = try self.createAttachNode(arena, ctx.list, ast.NodeVarDecl, - ast.NodeVarDecl { + const var_decl = try self.createAttachNode(arena, ctx.list, ast.Node.VarDecl, + ast.Node.VarDecl { .base = undefined, + .comments = ctx.comments, .visib_token = ctx.visib_token, .mut_token = ctx.mut_token, .comptime_token = ctx.comptime_token, @@ -881,8 +864,8 @@ pub const Parser = struct { const token = self.getNextToken(); switch(token.id) { Token.Id.LBrace => { - const block = try self.createNode(arena, ast.NodeBlock, - ast.NodeBlock { + const block = try self.createNode(arena, ast.Node.Block, + ast.Node.Block { .base = undefined, .label = null, .lbrace = token, @@ -924,7 +907,7 @@ pub const Parser = struct { const token = self.getNextToken(); switch (token.id) { Token.Id.Bang => { - fn_proto.return_type = ast.NodeFnProto.ReturnType { .InferErrorSet = undefined }; + fn_proto.return_type = ast.Node.FnProto.ReturnType { .InferErrorSet = undefined }; stack.append(State { .TypeExprBegin = OptionalCtx { .Required = &fn_proto.return_type.InferErrorSet }, }) catch unreachable; @@ -934,15 +917,15 @@ pub const Parser = struct { // TODO: this is a special case. Remove this when #760 is fixed if (token.id == Token.Id.Keyword_error) { if (self.isPeekToken(Token.Id.LBrace)) { - fn_proto.return_type = ast.NodeFnProto.ReturnType { - .Explicit = &(try self.createLiteral(arena, ast.NodeErrorType, token)).base + fn_proto.return_type = ast.Node.FnProto.ReturnType { + .Explicit = &(try self.createLiteral(arena, ast.Node.ErrorType, token)).base }; continue; } } self.putBackToken(token); - fn_proto.return_type = ast.NodeFnProto.ReturnType { .Explicit = undefined }; + fn_proto.return_type = ast.Node.FnProto.ReturnType { .Explicit = undefined }; stack.append(State { .TypeExprBegin = OptionalCtx { .Required = &fn_proto.return_type.Explicit }, }) catch unreachable; continue; }, @@ -954,8 +937,8 @@ pub const Parser = struct { if (self.eatToken(Token.Id.RParen)) |_| { continue; } - const param_decl = try self.createAttachNode(arena, &fn_proto.params, ast.NodeParamDecl, - ast.NodeParamDecl { + const param_decl = try self.createAttachNode(arena, &fn_proto.params, ast.Node.ParamDecl, + ast.Node.ParamDecl { .base = undefined, .comptime_token = null, .noalias_token = null, @@ -1026,15 +1009,15 @@ pub const Parser = struct { continue; } - _ = try self.createToCtxLiteral(arena, ctx.opt_ctx, ast.NodeIdentifier, ctx.label); + _ = try self.createToCtxLiteral(arena, ctx.opt_ctx, ast.Node.Identifier, ctx.label); continue; }, State.LabeledExpression => |ctx| { const token = self.getNextToken(); switch (token.id) { Token.Id.LBrace => { - const block = try self.createToCtxNode(arena, ctx.opt_ctx, ast.NodeBlock, - ast.NodeBlock { + const block = try self.createToCtxNode(arena, ctx.opt_ctx, ast.Node.Block, + ast.Node.Block { .base = undefined, .label = ctx.label, .lbrace = token, @@ -1123,8 +1106,8 @@ pub const Parser = struct { } }, State.While => |ctx| { - const node = try self.createToCtxNode(arena, ctx.opt_ctx, ast.NodeWhile, - ast.NodeWhile { + const node = try self.createToCtxNode(arena, ctx.opt_ctx, ast.Node.While, + ast.Node.While { .base = undefined, .label = ctx.label, .inline_token = ctx.inline_token, @@ -1153,8 +1136,8 @@ pub const Parser = struct { continue; }, State.For => |ctx| { - const node = try self.createToCtxNode(arena, ctx.opt_ctx, ast.NodeFor, - ast.NodeFor { + const node = try self.createToCtxNode(arena, ctx.opt_ctx, ast.Node.For, + ast.Node.For { .base = undefined, .label = ctx.label, .inline_token = ctx.inline_token, @@ -1175,8 +1158,8 @@ pub const Parser = struct { }, State.Else => |dest| { if (self.eatToken(Token.Id.Keyword_else)) |else_token| { - const node = try self.createNode(arena, ast.NodeElse, - ast.NodeElse { + const node = try self.createNode(arena, ast.Node.Else, + ast.Node.Else { .base = undefined, .else_token = else_token, .payload = null, @@ -1210,6 +1193,7 @@ pub const Parser = struct { } }, State.Statement => |block| { + const comments = try self.eatComments(arena); const token = self.getNextToken(); switch (token.id) { Token.Id.Keyword_comptime => { @@ -1224,6 +1208,7 @@ pub const Parser = struct { Token.Id.Keyword_var, Token.Id.Keyword_const => { stack.append(State { .VarDecl = VarDeclCtx { + .comments = comments, .visib_token = null, .comptime_token = null, .extern_export_token = null, @@ -1235,13 +1220,13 @@ pub const Parser = struct { continue; }, Token.Id.Keyword_defer, Token.Id.Keyword_errdefer => { - const node = try self.createAttachNode(arena, &block.statements, ast.NodeDefer, - ast.NodeDefer { + const node = try self.createAttachNode(arena, &block.statements, ast.Node.Defer, + ast.Node.Defer { .base = undefined, .defer_token = token, .kind = switch (token.id) { - Token.Id.Keyword_defer => ast.NodeDefer.Kind.Unconditional, - Token.Id.Keyword_errdefer => ast.NodeDefer.Kind.Error, + Token.Id.Keyword_defer => ast.Node.Defer.Kind.Unconditional, + Token.Id.Keyword_errdefer => ast.Node.Defer.Kind.Error, else => unreachable, }, .expr = undefined, @@ -1252,8 +1237,8 @@ pub const Parser = struct { continue; }, Token.Id.LBrace => { - const inner_block = try self.createAttachNode(arena, &block.statements, ast.NodeBlock, - ast.NodeBlock { + const inner_block = try self.createAttachNode(arena, &block.statements, ast.Node.Block, + ast.Node.Block { .base = undefined, .label = null, .lbrace = token, @@ -1274,11 +1259,13 @@ pub const Parser = struct { } }, State.ComptimeStatement => |ctx| { + const comments = try self.eatComments(arena); const token = self.getNextToken(); switch (token.id) { Token.Id.Keyword_var, Token.Id.Keyword_const => { stack.append(State { .VarDecl = VarDeclCtx { + .comments = comments, .visib_token = null, .comptime_token = ctx.comptime_token, .extern_export_token = null, @@ -1316,8 +1303,8 @@ pub const Parser = struct { continue; } - const node = try self.createNode(arena, ast.NodeAsmOutput, - ast.NodeAsmOutput { + const node = try self.createNode(arena, ast.Node.AsmOutput, + ast.Node.AsmOutput { .base = undefined, .symbolic_name = undefined, .constraint = undefined, @@ -1340,11 +1327,11 @@ pub const Parser = struct { const token = self.getNextToken(); switch (token.id) { Token.Id.Identifier => { - node.kind = ast.NodeAsmOutput.Kind { .Variable = try self.createLiteral(arena, ast.NodeIdentifier, token) }; + node.kind = ast.Node.AsmOutput.Kind { .Variable = try self.createLiteral(arena, ast.Node.Identifier, token) }; continue; }, Token.Id.Arrow => { - node.kind = ast.NodeAsmOutput.Kind { .Return = undefined }; + node.kind = ast.Node.AsmOutput.Kind { .Return = undefined }; try stack.append(State { .TypeExprBegin = OptionalCtx { .Required = &node.kind.Return } }); continue; }, @@ -1362,8 +1349,8 @@ pub const Parser = struct { continue; } - const node = try self.createNode(arena, ast.NodeAsmInput, - ast.NodeAsmInput { + const node = try self.createNode(arena, ast.Node.AsmInput, + ast.Node.AsmInput { .base = undefined, .symbolic_name = undefined, .constraint = undefined, @@ -1415,8 +1402,8 @@ pub const Parser = struct { continue; } - const node = try self.createNode(arena, ast.NodeFieldInitializer, - ast.NodeFieldInitializer { + const node = try self.createNode(arena, ast.Node.FieldInitializer, + ast.Node.FieldInitializer { .base = undefined, .period_token = undefined, .name_token = undefined, @@ -1485,8 +1472,8 @@ pub const Parser = struct { continue; } - const node = try self.createNode(arena, ast.NodeSwitchCase, - ast.NodeSwitchCase { + const node = try self.createNode(arena, ast.Node.SwitchCase, + ast.Node.SwitchCase { .base = undefined, .items = ArrayList(&ast.Node).init(arena), .payload = null, @@ -1512,8 +1499,8 @@ pub const Parser = struct { State.SwitchCaseFirstItem => |case_items| { const token = self.getNextToken(); if (token.id == Token.Id.Keyword_else) { - const else_node = try self.createAttachNode(arena, case_items, ast.NodeSwitchElse, - ast.NodeSwitchElse { + const else_node = try self.createAttachNode(arena, case_items, ast.Node.SwitchElse, + ast.Node.SwitchElse { .base = undefined, .token = token, } @@ -1564,24 +1551,24 @@ pub const Parser = struct { switch (node.id) { ast.Node.Id.FnProto => { - const fn_proto = @fieldParentPtr(ast.NodeFnProto, "base", node); + const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", node); fn_proto.async_attr = ctx.attribute; continue; }, ast.Node.Id.SuffixOp => { - const suffix_op = @fieldParentPtr(ast.NodeSuffixOp, "base", node); - if (suffix_op.op == ast.NodeSuffixOp.SuffixOp.Call) { + const suffix_op = @fieldParentPtr(ast.Node.SuffixOp, "base", node); + if (suffix_op.op == ast.Node.SuffixOp.Op.Call) { suffix_op.op.Call.async_attr = ctx.attribute; continue; } return self.parseError(node.firstToken(), "expected {}, found {}.", - @tagName(ast.NodeSuffixOp.SuffixOp.Call), + @tagName(ast.Node.SuffixOp.Op.Call), @tagName(suffix_op.op)); }, else => { return self.parseError(node.firstToken(), "expected {} or {}, found {}.", - @tagName(ast.NodeSuffixOp.SuffixOp.Call), + @tagName(ast.Node.SuffixOp.Op.Call), @tagName(ast.Node.Id.FnProto), @tagName(node.id)); } @@ -1591,9 +1578,10 @@ pub const Parser = struct { State.ExternType => |ctx| { if (self.eatToken(Token.Id.Keyword_fn)) |fn_token| { - const fn_proto = try self.createToCtxNode(arena, ctx.opt_ctx, ast.NodeFnProto, - ast.NodeFnProto { + const fn_proto = try self.createToCtxNode(arena, ctx.opt_ctx, ast.Node.FnProto, + ast.Node.FnProto { .base = undefined, + .comments = ctx.comments, .visib_token = null, .name_token = null, .fn_token = fn_token, @@ -1616,7 +1604,7 @@ pub const Parser = struct { .ContainerKind = ContainerKindCtx { .opt_ctx = ctx.opt_ctx, .ltoken = ctx.extern_token, - .layout = ast.NodeContainerDecl.Layout.Extern, + .layout = ast.Node.ContainerDecl.Layout.Extern, }, }) catch unreachable; continue; @@ -1626,8 +1614,8 @@ pub const Parser = struct { switch (token.id) { Token.Id.Ellipsis2 => { const start = node.op.ArrayAccess; - node.op = ast.NodeSuffixOp.SuffixOp { - .Slice = ast.NodeSuffixOp.SliceRange { + node.op = ast.Node.SuffixOp.Op { + .Slice = ast.Node.SuffixOp.SliceRange { .start = start, .end = null, } @@ -1653,8 +1641,8 @@ pub const Parser = struct { }, State.SliceOrArrayType => |node| { if (self.eatToken(Token.Id.RBracket)) |_| { - node.op = ast.NodePrefixOp.PrefixOp { - .SliceType = ast.NodePrefixOp.AddrOfInfo { + node.op = ast.Node.PrefixOp.Op { + .SliceType = ast.Node.PrefixOp.AddrOfInfo { .align_expr = null, .bit_offset_start_token = null, .bit_offset_end_token = null, @@ -1667,7 +1655,7 @@ pub const Parser = struct { continue; } - node.op = ast.NodePrefixOp.PrefixOp { .ArrayType = undefined }; + node.op = ast.Node.PrefixOp.Op { .ArrayType = undefined }; stack.append(State { .TypeExprBegin = OptionalCtx { .Required = &node.rhs } }) catch unreachable; try stack.append(State { .ExpectToken = Token.Id.RBracket }); try stack.append(State { .Expression = OptionalCtx { .Required = &node.op.ArrayType } }); @@ -1723,8 +1711,8 @@ pub const Parser = struct { continue; } - const node = try self.createToCtxNode(arena, opt_ctx, ast.NodePayload, - ast.NodePayload { + const node = try self.createToCtxNode(arena, opt_ctx, ast.Node.Payload, + ast.Node.Payload { .base = undefined, .lpipe = token, .error_symbol = undefined, @@ -1754,8 +1742,8 @@ pub const Parser = struct { continue; } - const node = try self.createToCtxNode(arena, opt_ctx, ast.NodePointerPayload, - ast.NodePointerPayload { + const node = try self.createToCtxNode(arena, opt_ctx, ast.Node.PointerPayload, + ast.Node.PointerPayload { .base = undefined, .lpipe = token, .ptr_token = null, @@ -1792,8 +1780,8 @@ pub const Parser = struct { continue; } - const node = try self.createToCtxNode(arena, opt_ctx, ast.NodePointerIndexPayload, - ast.NodePointerIndexPayload { + const node = try self.createToCtxNode(arena, opt_ctx, ast.Node.PointerIndexPayload, + ast.Node.PointerIndexPayload { .base = undefined, .lpipe = token, .ptr_token = null, @@ -1826,8 +1814,8 @@ pub const Parser = struct { const token = self.getNextToken(); switch (token.id) { Token.Id.Keyword_return, Token.Id.Keyword_break, Token.Id.Keyword_continue => { - const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeControlFlowExpression, - ast.NodeControlFlowExpression { + const node = try self.createToCtxNode(arena, opt_ctx, ast.Node.ControlFlowExpression, + ast.Node.ControlFlowExpression { .base = undefined, .ltoken = token, .kind = undefined, @@ -1839,31 +1827,31 @@ pub const Parser = struct { switch (token.id) { Token.Id.Keyword_break => { - node.kind = ast.NodeControlFlowExpression.Kind { .Break = null }; + node.kind = ast.Node.ControlFlowExpression.Kind { .Break = null }; try stack.append(State { .Identifier = OptionalCtx { .RequiredNull = &node.kind.Break } }); try stack.append(State { .IfToken = Token.Id.Colon }); }, Token.Id.Keyword_continue => { - node.kind = ast.NodeControlFlowExpression.Kind { .Continue = null }; + node.kind = ast.Node.ControlFlowExpression.Kind { .Continue = null }; try stack.append(State { .Identifier = OptionalCtx { .RequiredNull = &node.kind.Continue } }); try stack.append(State { .IfToken = Token.Id.Colon }); }, Token.Id.Keyword_return => { - node.kind = ast.NodeControlFlowExpression.Kind.Return; + node.kind = ast.Node.ControlFlowExpression.Kind.Return; }, else => unreachable, } continue; }, Token.Id.Keyword_try, Token.Id.Keyword_cancel, Token.Id.Keyword_resume => { - const node = try self.createToCtxNode(arena, opt_ctx, ast.NodePrefixOp, - ast.NodePrefixOp { + const node = try self.createToCtxNode(arena, opt_ctx, ast.Node.PrefixOp, + ast.Node.PrefixOp { .base = undefined, .op_token = token, .op = switch (token.id) { - Token.Id.Keyword_try => ast.NodePrefixOp.PrefixOp { .Try = void{} }, - Token.Id.Keyword_cancel => ast.NodePrefixOp.PrefixOp { .Cancel = void{} }, - Token.Id.Keyword_resume => ast.NodePrefixOp.PrefixOp { .Resume = void{} }, + Token.Id.Keyword_try => ast.Node.PrefixOp.Op { .Try = void{} }, + Token.Id.Keyword_cancel => ast.Node.PrefixOp.Op { .Cancel = void{} }, + Token.Id.Keyword_resume => ast.Node.PrefixOp.Op { .Resume = void{} }, else => unreachable, }, .rhs = undefined, @@ -1891,12 +1879,12 @@ pub const Parser = struct { const lhs = opt_ctx.get() ?? continue; if (self.eatToken(Token.Id.Ellipsis3)) |ellipsis3| { - const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp, - ast.NodeInfixOp { + const node = try self.createToCtxNode(arena, opt_ctx, ast.Node.InfixOp, + ast.Node.InfixOp { .base = undefined, .lhs = lhs, .op_token = ellipsis3, - .op = ast.NodeInfixOp.InfixOp.Range, + .op = ast.Node.InfixOp.Op.Range, .rhs = undefined, } ); @@ -1915,8 +1903,8 @@ pub const Parser = struct { const token = self.getNextToken(); if (tokenIdToAssignment(token.id)) |ass_id| { - const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp, - ast.NodeInfixOp { + const node = try self.createToCtxNode(arena, opt_ctx, ast.Node.InfixOp, + ast.Node.InfixOp { .base = undefined, .lhs = lhs, .op_token = token, @@ -1944,8 +1932,8 @@ pub const Parser = struct { const token = self.getNextToken(); if (tokenIdToUnwrapExpr(token.id)) |unwrap_id| { - const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp, - ast.NodeInfixOp { + const node = try self.createToCtxNode(arena, opt_ctx, ast.Node.InfixOp, + ast.Node.InfixOp { .base = undefined, .lhs = lhs, .op_token = token, @@ -1957,7 +1945,7 @@ pub const Parser = struct { stack.append(State { .UnwrapExpressionEnd = opt_ctx.toRequired() }) catch unreachable; try stack.append(State { .Expression = OptionalCtx { .Required = &node.rhs } }); - if (node.op == ast.NodeInfixOp.InfixOp.Catch) { + if (node.op == ast.Node.InfixOp.Op.Catch) { try stack.append(State { .Payload = OptionalCtx { .Optional = &node.op.Catch } }); } continue; @@ -1977,12 +1965,12 @@ pub const Parser = struct { const lhs = opt_ctx.get() ?? continue; if (self.eatToken(Token.Id.Keyword_or)) |or_token| { - const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp, - ast.NodeInfixOp { + const node = try self.createToCtxNode(arena, opt_ctx, ast.Node.InfixOp, + ast.Node.InfixOp { .base = undefined, .lhs = lhs, .op_token = or_token, - .op = ast.NodeInfixOp.InfixOp.BoolOr, + .op = ast.Node.InfixOp.Op.BoolOr, .rhs = undefined, } ); @@ -2002,12 +1990,12 @@ pub const Parser = struct { const lhs = opt_ctx.get() ?? continue; if (self.eatToken(Token.Id.Keyword_and)) |and_token| { - const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp, - ast.NodeInfixOp { + const node = try self.createToCtxNode(arena, opt_ctx, ast.Node.InfixOp, + ast.Node.InfixOp { .base = undefined, .lhs = lhs, .op_token = and_token, - .op = ast.NodeInfixOp.InfixOp.BoolAnd, + .op = ast.Node.InfixOp.Op.BoolAnd, .rhs = undefined, } ); @@ -2028,8 +2016,8 @@ pub const Parser = struct { const token = self.getNextToken(); if (tokenIdToComparison(token.id)) |comp_id| { - const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp, - ast.NodeInfixOp { + const node = try self.createToCtxNode(arena, opt_ctx, ast.Node.InfixOp, + ast.Node.InfixOp { .base = undefined, .lhs = lhs, .op_token = token, @@ -2056,12 +2044,12 @@ pub const Parser = struct { const lhs = opt_ctx.get() ?? continue; if (self.eatToken(Token.Id.Pipe)) |pipe| { - const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp, - ast.NodeInfixOp { + const node = try self.createToCtxNode(arena, opt_ctx, ast.Node.InfixOp, + ast.Node.InfixOp { .base = undefined, .lhs = lhs, .op_token = pipe, - .op = ast.NodeInfixOp.InfixOp.BitOr, + .op = ast.Node.InfixOp.Op.BitOr, .rhs = undefined, } ); @@ -2081,12 +2069,12 @@ pub const Parser = struct { const lhs = opt_ctx.get() ?? continue; if (self.eatToken(Token.Id.Caret)) |caret| { - const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp, - ast.NodeInfixOp { + const node = try self.createToCtxNode(arena, opt_ctx, ast.Node.InfixOp, + ast.Node.InfixOp { .base = undefined, .lhs = lhs, .op_token = caret, - .op = ast.NodeInfixOp.InfixOp.BitXor, + .op = ast.Node.InfixOp.Op.BitXor, .rhs = undefined, } ); @@ -2106,12 +2094,12 @@ pub const Parser = struct { const lhs = opt_ctx.get() ?? continue; if (self.eatToken(Token.Id.Ampersand)) |ampersand| { - const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp, - ast.NodeInfixOp { + const node = try self.createToCtxNode(arena, opt_ctx, ast.Node.InfixOp, + ast.Node.InfixOp { .base = undefined, .lhs = lhs, .op_token = ampersand, - .op = ast.NodeInfixOp.InfixOp.BitAnd, + .op = ast.Node.InfixOp.Op.BitAnd, .rhs = undefined, } ); @@ -2132,8 +2120,8 @@ pub const Parser = struct { const token = self.getNextToken(); if (tokenIdToBitShift(token.id)) |bitshift_id| { - const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp, - ast.NodeInfixOp { + const node = try self.createToCtxNode(arena, opt_ctx, ast.Node.InfixOp, + ast.Node.InfixOp { .base = undefined, .lhs = lhs, .op_token = token, @@ -2161,8 +2149,8 @@ pub const Parser = struct { const token = self.getNextToken(); if (tokenIdToAddition(token.id)) |add_id| { - const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp, - ast.NodeInfixOp { + const node = try self.createToCtxNode(arena, opt_ctx, ast.Node.InfixOp, + ast.Node.InfixOp { .base = undefined, .lhs = lhs, .op_token = token, @@ -2190,8 +2178,8 @@ pub const Parser = struct { const token = self.getNextToken(); if (tokenIdToMultiply(token.id)) |mult_id| { - const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp, - ast.NodeInfixOp { + const node = try self.createToCtxNode(arena, opt_ctx, ast.Node.InfixOp, + ast.Node.InfixOp { .base = undefined, .lhs = lhs, .op_token = token, @@ -2219,12 +2207,12 @@ pub const Parser = struct { const lhs = opt_ctx.get() ?? continue; if (self.isPeekToken(Token.Id.Period)) { - const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeSuffixOp, - ast.NodeSuffixOp { + const node = try self.createToCtxNode(arena, opt_ctx, ast.Node.SuffixOp, + ast.Node.SuffixOp { .base = undefined, .lhs = lhs, - .op = ast.NodeSuffixOp.SuffixOp { - .StructInitializer = ArrayList(&ast.NodeFieldInitializer).init(arena), + .op = ast.Node.SuffixOp.Op { + .StructInitializer = ArrayList(&ast.Node.FieldInitializer).init(arena), }, .rtoken = undefined, } @@ -2232,7 +2220,7 @@ pub const Parser = struct { stack.append(State { .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable; try stack.append(State { .IfToken = Token.Id.LBrace }); try stack.append(State { - .FieldInitListItemOrEnd = ListSave(&ast.NodeFieldInitializer) { + .FieldInitListItemOrEnd = ListSave(&ast.Node.FieldInitializer) { .list = &node.op.StructInitializer, .ptr = &node.rtoken, } @@ -2240,11 +2228,11 @@ pub const Parser = struct { continue; } - const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeSuffixOp, - ast.NodeSuffixOp { + const node = try self.createToCtxNode(arena, opt_ctx, ast.Node.SuffixOp, + ast.Node.SuffixOp { .base = undefined, .lhs = lhs, - .op = ast.NodeSuffixOp.SuffixOp { + .op = ast.Node.SuffixOp.Op { .ArrayInitializer = ArrayList(&ast.Node).init(arena), }, .rtoken = undefined, @@ -2272,12 +2260,12 @@ pub const Parser = struct { const lhs = opt_ctx.get() ?? continue; if (self.eatToken(Token.Id.Bang)) |bang| { - const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp, - ast.NodeInfixOp { + const node = try self.createToCtxNode(arena, opt_ctx, ast.Node.InfixOp, + ast.Node.InfixOp { .base = undefined, .lhs = lhs, .op_token = bang, - .op = ast.NodeInfixOp.InfixOp.ErrorUnion, + .op = ast.Node.InfixOp.Op.ErrorUnion, .rhs = undefined, } ); @@ -2290,8 +2278,8 @@ pub const Parser = struct { State.PrefixOpExpression => |opt_ctx| { const token = self.getNextToken(); if (tokenIdToPrefixOp(token.id)) |prefix_id| { - var node = try self.createToCtxNode(arena, opt_ctx, ast.NodePrefixOp, - ast.NodePrefixOp { + var node = try self.createToCtxNode(arena, opt_ctx, ast.Node.PrefixOp, + ast.Node.PrefixOp { .base = undefined, .op_token = token, .op = prefix_id, @@ -2301,8 +2289,8 @@ pub const Parser = struct { // Treat '**' token as two derefs if (token.id == Token.Id.AsteriskAsterisk) { - const child = try self.createNode(arena, ast.NodePrefixOp, - ast.NodePrefixOp { + const child = try self.createNode(arena, ast.Node.PrefixOp, + ast.Node.PrefixOp { .base = undefined, .op_token = token, .op = prefix_id, @@ -2314,7 +2302,7 @@ pub const Parser = struct { } stack.append(State { .TypeExprBegin = OptionalCtx { .Required = &node.rhs } }) catch unreachable; - if (node.op == ast.NodePrefixOp.PrefixOp.AddrOf) { + if (node.op == ast.Node.PrefixOp.Op.AddrOf) { try stack.append(State { .AddrOfModifiers = &node.op.AddrOf }); } continue; @@ -2327,8 +2315,8 @@ pub const Parser = struct { State.SuffixOpExpressionBegin => |opt_ctx| { if (self.eatToken(Token.Id.Keyword_async)) |async_token| { - const async_node = try self.createNode(arena, ast.NodeAsyncAttribute, - ast.NodeAsyncAttribute { + const async_node = try self.createNode(arena, ast.Node.AsyncAttribute, + ast.Node.AsyncAttribute { .base = undefined, .async_token = async_token, .allocator_type = null, @@ -2358,12 +2346,12 @@ pub const Parser = struct { const token = self.getNextToken(); switch (token.id) { Token.Id.LParen => { - const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeSuffixOp, - ast.NodeSuffixOp { + const node = try self.createToCtxNode(arena, opt_ctx, ast.Node.SuffixOp, + ast.Node.SuffixOp { .base = undefined, .lhs = lhs, - .op = ast.NodeSuffixOp.SuffixOp { - .Call = ast.NodeSuffixOp.CallInfo { + .op = ast.Node.SuffixOp.Op { + .Call = ast.Node.SuffixOp.CallInfo { .params = ArrayList(&ast.Node).init(arena), .async_attr = null, } @@ -2382,11 +2370,11 @@ pub const Parser = struct { continue; }, Token.Id.LBracket => { - const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeSuffixOp, - ast.NodeSuffixOp { + const node = try self.createToCtxNode(arena, opt_ctx, ast.Node.SuffixOp, + ast.Node.SuffixOp { .base = undefined, .lhs = lhs, - .op = ast.NodeSuffixOp.SuffixOp { + .op = ast.Node.SuffixOp.Op { .ArrayAccess = undefined, }, .rtoken = undefined @@ -2398,12 +2386,12 @@ pub const Parser = struct { continue; }, Token.Id.Period => { - const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeInfixOp, - ast.NodeInfixOp { + const node = try self.createToCtxNode(arena, opt_ctx, ast.Node.InfixOp, + ast.Node.InfixOp { .base = undefined, .lhs = lhs, .op_token = token, - .op = ast.NodeInfixOp.InfixOp.Period, + .op = ast.Node.InfixOp.Op.Period, .rhs = undefined, } ); @@ -2422,39 +2410,39 @@ pub const Parser = struct { const token = self.getNextToken(); switch (token.id) { Token.Id.IntegerLiteral => { - _ = try self.createToCtxLiteral(arena, opt_ctx, ast.NodeStringLiteral, token); + _ = try self.createToCtxLiteral(arena, opt_ctx, ast.Node.StringLiteral, token); continue; }, Token.Id.FloatLiteral => { - _ = try self.createToCtxLiteral(arena, opt_ctx, ast.NodeFloatLiteral, token); + _ = try self.createToCtxLiteral(arena, opt_ctx, ast.Node.FloatLiteral, token); continue; }, Token.Id.CharLiteral => { - _ = try self.createToCtxLiteral(arena, opt_ctx, ast.NodeCharLiteral, token); + _ = try self.createToCtxLiteral(arena, opt_ctx, ast.Node.CharLiteral, token); continue; }, Token.Id.Keyword_undefined => { - _ = try self.createToCtxLiteral(arena, opt_ctx, ast.NodeUndefinedLiteral, token); + _ = try self.createToCtxLiteral(arena, opt_ctx, ast.Node.UndefinedLiteral, token); continue; }, Token.Id.Keyword_true, Token.Id.Keyword_false => { - _ = try self.createToCtxLiteral(arena, opt_ctx, ast.NodeBoolLiteral, token); + _ = try self.createToCtxLiteral(arena, opt_ctx, ast.Node.BoolLiteral, token); continue; }, Token.Id.Keyword_null => { - _ = try self.createToCtxLiteral(arena, opt_ctx, ast.NodeNullLiteral, token); + _ = try self.createToCtxLiteral(arena, opt_ctx, ast.Node.NullLiteral, token); continue; }, Token.Id.Keyword_this => { - _ = try self.createToCtxLiteral(arena, opt_ctx, ast.NodeThisLiteral, token); + _ = try self.createToCtxLiteral(arena, opt_ctx, ast.Node.ThisLiteral, token); continue; }, Token.Id.Keyword_var => { - _ = try self.createToCtxLiteral(arena, opt_ctx, ast.NodeVarType, token); + _ = try self.createToCtxLiteral(arena, opt_ctx, ast.Node.VarType, token); continue; }, Token.Id.Keyword_unreachable => { - _ = try self.createToCtxLiteral(arena, opt_ctx, ast.NodeUnreachable, token); + _ = try self.createToCtxLiteral(arena, opt_ctx, ast.Node.Unreachable, token); continue; }, Token.Id.StringLiteral, Token.Id.MultilineStringLiteralLine => { @@ -2462,8 +2450,8 @@ pub const Parser = struct { continue; }, Token.Id.LParen => { - const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeGroupedExpression, - ast.NodeGroupedExpression { + const node = try self.createToCtxNode(arena, opt_ctx, ast.Node.GroupedExpression, + ast.Node.GroupedExpression { .base = undefined, .lparen = token, .expr = undefined, @@ -2480,8 +2468,8 @@ pub const Parser = struct { continue; }, Token.Id.Builtin => { - const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeBuiltinCall, - ast.NodeBuiltinCall { + const node = try self.createToCtxNode(arena, opt_ctx, ast.Node.BuiltinCall, + ast.Node.BuiltinCall { .base = undefined, .builtin_token = token, .params = ArrayList(&ast.Node).init(arena), @@ -2499,8 +2487,8 @@ pub const Parser = struct { continue; }, Token.Id.LBracket => { - const node = try self.createToCtxNode(arena, opt_ctx, ast.NodePrefixOp, - ast.NodePrefixOp { + const node = try self.createToCtxNode(arena, opt_ctx, ast.Node.PrefixOp, + ast.Node.PrefixOp { .base = undefined, .op_token = token, .op = undefined, @@ -2524,7 +2512,7 @@ pub const Parser = struct { .ContainerKind = ContainerKindCtx { .opt_ctx = opt_ctx, .ltoken = token, - .layout = ast.NodeContainerDecl.Layout.Packed, + .layout = ast.Node.ContainerDecl.Layout.Packed, }, }) catch unreachable; continue; @@ -2534,6 +2522,7 @@ pub const Parser = struct { .ExternType = ExternTypeCtx { .opt_ctx = opt_ctx, .extern_token = token, + .comments = null, }, }) catch unreachable; continue; @@ -2544,7 +2533,7 @@ pub const Parser = struct { .ContainerKind = ContainerKindCtx { .opt_ctx = opt_ctx, .ltoken = token, - .layout = ast.NodeContainerDecl.Layout.Auto, + .layout = ast.Node.ContainerDecl.Layout.Auto, }, }) catch unreachable; continue; @@ -2559,9 +2548,10 @@ pub const Parser = struct { continue; }, Token.Id.Keyword_fn => { - const fn_proto = try self.createToCtxNode(arena, opt_ctx, ast.NodeFnProto, - ast.NodeFnProto { + const fn_proto = try self.createToCtxNode(arena, opt_ctx, ast.Node.FnProto, + ast.Node.FnProto { .base = undefined, + .comments = null, .visib_token = null, .name_token = null, .fn_token = token, @@ -2580,9 +2570,10 @@ pub const Parser = struct { continue; }, Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => { - const fn_proto = try self.createToCtxNode(arena, opt_ctx, ast.NodeFnProto, - ast.NodeFnProto { + const fn_proto = try self.createToCtxNode(arena, opt_ctx, ast.Node.FnProto, + ast.Node.FnProto { .base = undefined, + .comments = null, .visib_token = null, .name_token = null, .fn_token = undefined, @@ -2607,15 +2598,15 @@ pub const Parser = struct { continue; }, Token.Id.Keyword_asm => { - const node = try self.createToCtxNode(arena, opt_ctx, ast.NodeAsm, - ast.NodeAsm { + const node = try self.createToCtxNode(arena, opt_ctx, ast.Node.Asm, + ast.Node.Asm { .base = undefined, .asm_token = token, .volatile_token = null, .template = undefined, - //.tokens = ArrayList(ast.NodeAsm.AsmToken).init(arena), - .outputs = ArrayList(&ast.NodeAsmOutput).init(arena), - .inputs = ArrayList(&ast.NodeAsmInput).init(arena), + //.tokens = ArrayList(ast.Node.Asm.AsmToken).init(arena), + .outputs = ArrayList(&ast.Node.AsmOutput).init(arena), + .inputs = ArrayList(&ast.Node.AsmInput).init(arena), .cloppers = ArrayList(&ast.Node).init(arena), .rparen = undefined, } @@ -2666,12 +2657,12 @@ pub const Parser = struct { State.ErrorTypeOrSetDecl => |ctx| { if (self.eatToken(Token.Id.LBrace) == null) { - _ = try self.createToCtxLiteral(arena, ctx.opt_ctx, ast.NodeErrorType, ctx.error_token); + _ = try self.createToCtxLiteral(arena, ctx.opt_ctx, ast.Node.ErrorType, ctx.error_token); continue; } - const node = try self.createToCtxNode(arena, ctx.opt_ctx, ast.NodeErrorSetDecl, - ast.NodeErrorSetDecl { + const node = try self.createToCtxNode(arena, ctx.opt_ctx, ast.Node.ErrorSetDecl, + ast.Node.ErrorSetDecl { .base = undefined, .error_token = ctx.error_token, .decls = ArrayList(&ast.Node).init(arena), @@ -2702,7 +2693,7 @@ pub const Parser = struct { }, State.Identifier => |opt_ctx| { if (self.eatToken(Token.Id.Identifier)) |ident_token| { - _ = try self.createToCtxLiteral(arena, opt_ctx, ast.NodeIdentifier, ident_token); + _ = try self.createToCtxLiteral(arena, opt_ctx, ast.Node.Identifier, ident_token); continue; } @@ -2750,6 +2741,33 @@ pub const Parser = struct { } } + fn eatComments(self: &Parser, arena: &mem.Allocator) !?&ast.Node.LineComment { + var result: ?&ast.Node.LineComment = null; + while (true) { + if (self.eatToken(Token.Id.LineComment)) |line_comment| { + const node = blk: { + if (result) |comment_node| { + break :blk comment_node; + } else { + const comment_node = try arena.create(ast.Node.LineComment); + *comment_node = ast.Node.LineComment { + .base = ast.Node { + .id = ast.Node.Id.LineComment, + }, + .lines = ArrayList(Token).init(arena), + }; + result = comment_node; + break :blk comment_node; + } + }; + try node.lines.append(line_comment); + continue; + } + break; + } + return result; + } + fn requireSemiColon(node: &const ast.Node) bool { var n = node; while (true) { @@ -2770,7 +2788,7 @@ pub const Parser = struct { ast.Node.Id.LineComment, ast.Node.Id.TestDecl => return false, ast.Node.Id.While => { - const while_node = @fieldParentPtr(ast.NodeWhile, "base", n); + const while_node = @fieldParentPtr(ast.Node.While, "base", n); if (while_node.@"else") |@"else"| { n = @"else".base; continue; @@ -2779,7 +2797,7 @@ pub const Parser = struct { return while_node.body.id != ast.Node.Id.Block; }, ast.Node.Id.For => { - const for_node = @fieldParentPtr(ast.NodeFor, "base", n); + const for_node = @fieldParentPtr(ast.Node.For, "base", n); if (for_node.@"else") |@"else"| { n = @"else".base; continue; @@ -2788,7 +2806,7 @@ pub const Parser = struct { return for_node.body.id != ast.Node.Id.Block; }, ast.Node.Id.If => { - const if_node = @fieldParentPtr(ast.NodeIf, "base", n); + const if_node = @fieldParentPtr(ast.Node.If, "base", n); if (if_node.@"else") |@"else"| { n = @"else".base; continue; @@ -2797,20 +2815,20 @@ pub const Parser = struct { return if_node.body.id != ast.Node.Id.Block; }, ast.Node.Id.Else => { - const else_node = @fieldParentPtr(ast.NodeElse, "base", n); + const else_node = @fieldParentPtr(ast.Node.Else, "base", n); n = else_node.body; continue; }, ast.Node.Id.Defer => { - const defer_node = @fieldParentPtr(ast.NodeDefer, "base", n); + const defer_node = @fieldParentPtr(ast.Node.Defer, "base", n); return defer_node.expr.id != ast.Node.Id.Block; }, ast.Node.Id.Comptime => { - const comptime_node = @fieldParentPtr(ast.NodeComptime, "base", n); + const comptime_node = @fieldParentPtr(ast.Node.Comptime, "base", n); return comptime_node.expr.id != ast.Node.Id.Block; }, ast.Node.Id.Suspend => { - const suspend_node = @fieldParentPtr(ast.NodeSuspend, "base", n); + const suspend_node = @fieldParentPtr(ast.Node.Suspend, "base", n); if (suspend_node.body) |body| { return body.id != ast.Node.Id.Block; } @@ -2825,11 +2843,11 @@ pub const Parser = struct { fn parseStringLiteral(self: &Parser, arena: &mem.Allocator, token: &const Token) !?&ast.Node { switch (token.id) { Token.Id.StringLiteral => { - return &(try self.createLiteral(arena, ast.NodeStringLiteral, token)).base; + return &(try self.createLiteral(arena, ast.Node.StringLiteral, token)).base; }, Token.Id.MultilineStringLiteralLine => { - const node = try self.createNode(arena, ast.NodeMultilineStringLiteral, - ast.NodeMultilineStringLiteral { + const node = try self.createNode(arena, ast.Node.MultilineStringLiteral, + ast.Node.MultilineStringLiteral { .base = undefined, .tokens = ArrayList(Token).init(arena), } @@ -2856,8 +2874,8 @@ pub const Parser = struct { fn parseBlockExpr(self: &Parser, stack: &ArrayList(State), arena: &mem.Allocator, ctx: &const OptionalCtx, token: &const Token) !bool { switch (token.id) { Token.Id.Keyword_suspend => { - const node = try self.createToCtxNode(arena, ctx, ast.NodeSuspend, - ast.NodeSuspend { + const node = try self.createToCtxNode(arena, ctx, ast.Node.Suspend, + ast.Node.Suspend { .base = undefined, .suspend_token = *token, .payload = null, @@ -2870,8 +2888,8 @@ pub const Parser = struct { return true; }, Token.Id.Keyword_if => { - const node = try self.createToCtxNode(arena, ctx, ast.NodeIf, - ast.NodeIf { + const node = try self.createToCtxNode(arena, ctx, ast.Node.If, + ast.Node.If { .base = undefined, .if_token = *token, .condition = undefined, @@ -2912,18 +2930,18 @@ pub const Parser = struct { return true; }, Token.Id.Keyword_switch => { - const node = try self.createToCtxNode(arena, ctx, ast.NodeSwitch, - ast.NodeSwitch { + const node = try self.createToCtxNode(arena, ctx, ast.Node.Switch, + ast.Node.Switch { .base = undefined, .switch_token = *token, .expr = undefined, - .cases = ArrayList(&ast.NodeSwitchCase).init(arena), + .cases = ArrayList(&ast.Node.SwitchCase).init(arena), .rbrace = undefined, } ); stack.append(State { - .SwitchCaseOrEnd = ListSave(&ast.NodeSwitchCase) { + .SwitchCaseOrEnd = ListSave(&ast.Node.SwitchCase) { .list = &node.cases, .ptr = &node.rbrace, }, @@ -2935,8 +2953,8 @@ pub const Parser = struct { return true; }, Token.Id.Keyword_comptime => { - const node = try self.createToCtxNode(arena, ctx, ast.NodeComptime, - ast.NodeComptime { + const node = try self.createToCtxNode(arena, ctx, ast.Node.Comptime, + ast.Node.Comptime { .base = undefined, .comptime_token = *token, .expr = undefined, @@ -2946,8 +2964,8 @@ pub const Parser = struct { return true; }, Token.Id.LBrace => { - const block = try self.createToCtxNode(arena, ctx, ast.NodeBlock, - ast.NodeBlock { + const block = try self.createToCtxNode(arena, ctx, ast.Node.Block, + ast.Node.Block { .base = undefined, .label = null, .lbrace = *token, @@ -2978,88 +2996,88 @@ pub const Parser = struct { } } - fn tokenIdToAssignment(id: &const Token.Id) ?ast.NodeInfixOp.InfixOp { + fn tokenIdToAssignment(id: &const Token.Id) ?ast.Node.InfixOp.Op { // TODO: We have to cast all cases because of this: // error: expected type '?InfixOp', found '?@TagType(InfixOp)' return switch (*id) { - Token.Id.AmpersandEqual => ast.NodeInfixOp.InfixOp { .AssignBitAnd = void{} }, - Token.Id.AngleBracketAngleBracketLeftEqual => ast.NodeInfixOp.InfixOp { .AssignBitShiftLeft = void{} }, - Token.Id.AngleBracketAngleBracketRightEqual => ast.NodeInfixOp.InfixOp { .AssignBitShiftRight = void{} }, - Token.Id.AsteriskEqual => ast.NodeInfixOp.InfixOp { .AssignTimes = void{} }, - Token.Id.AsteriskPercentEqual => ast.NodeInfixOp.InfixOp { .AssignTimesWarp = void{} }, - Token.Id.CaretEqual => ast.NodeInfixOp.InfixOp { .AssignBitXor = void{} }, - Token.Id.Equal => ast.NodeInfixOp.InfixOp { .Assign = void{} }, - Token.Id.MinusEqual => ast.NodeInfixOp.InfixOp { .AssignMinus = void{} }, - Token.Id.MinusPercentEqual => ast.NodeInfixOp.InfixOp { .AssignMinusWrap = void{} }, - Token.Id.PercentEqual => ast.NodeInfixOp.InfixOp { .AssignMod = void{} }, - Token.Id.PipeEqual => ast.NodeInfixOp.InfixOp { .AssignBitOr = void{} }, - Token.Id.PlusEqual => ast.NodeInfixOp.InfixOp { .AssignPlus = void{} }, - Token.Id.PlusPercentEqual => ast.NodeInfixOp.InfixOp { .AssignPlusWrap = void{} }, - Token.Id.SlashEqual => ast.NodeInfixOp.InfixOp { .AssignDiv = void{} }, + Token.Id.AmpersandEqual => ast.Node.InfixOp.Op { .AssignBitAnd = void{} }, + Token.Id.AngleBracketAngleBracketLeftEqual => ast.Node.InfixOp.Op { .AssignBitShiftLeft = void{} }, + Token.Id.AngleBracketAngleBracketRightEqual => ast.Node.InfixOp.Op { .AssignBitShiftRight = void{} }, + Token.Id.AsteriskEqual => ast.Node.InfixOp.Op { .AssignTimes = void{} }, + Token.Id.AsteriskPercentEqual => ast.Node.InfixOp.Op { .AssignTimesWarp = void{} }, + Token.Id.CaretEqual => ast.Node.InfixOp.Op { .AssignBitXor = void{} }, + Token.Id.Equal => ast.Node.InfixOp.Op { .Assign = void{} }, + Token.Id.MinusEqual => ast.Node.InfixOp.Op { .AssignMinus = void{} }, + Token.Id.MinusPercentEqual => ast.Node.InfixOp.Op { .AssignMinusWrap = void{} }, + Token.Id.PercentEqual => ast.Node.InfixOp.Op { .AssignMod = void{} }, + Token.Id.PipeEqual => ast.Node.InfixOp.Op { .AssignBitOr = void{} }, + Token.Id.PlusEqual => ast.Node.InfixOp.Op { .AssignPlus = void{} }, + Token.Id.PlusPercentEqual => ast.Node.InfixOp.Op { .AssignPlusWrap = void{} }, + Token.Id.SlashEqual => ast.Node.InfixOp.Op { .AssignDiv = void{} }, else => null, }; } - fn tokenIdToUnwrapExpr(id: @TagType(Token.Id)) ?ast.NodeInfixOp.InfixOp { + fn tokenIdToUnwrapExpr(id: @TagType(Token.Id)) ?ast.Node.InfixOp.Op { return switch (id) { - Token.Id.Keyword_catch => ast.NodeInfixOp.InfixOp { .Catch = null }, - Token.Id.QuestionMarkQuestionMark => ast.NodeInfixOp.InfixOp { .UnwrapMaybe = void{} }, + Token.Id.Keyword_catch => ast.Node.InfixOp.Op { .Catch = null }, + Token.Id.QuestionMarkQuestionMark => ast.Node.InfixOp.Op { .UnwrapMaybe = void{} }, else => null, }; } - fn tokenIdToComparison(id: @TagType(Token.Id)) ?ast.NodeInfixOp.InfixOp { + fn tokenIdToComparison(id: @TagType(Token.Id)) ?ast.Node.InfixOp.Op { return switch (id) { - Token.Id.BangEqual => ast.NodeInfixOp.InfixOp { .BangEqual = void{} }, - Token.Id.EqualEqual => ast.NodeInfixOp.InfixOp { .EqualEqual = void{} }, - Token.Id.AngleBracketLeft => ast.NodeInfixOp.InfixOp { .LessThan = void{} }, - Token.Id.AngleBracketLeftEqual => ast.NodeInfixOp.InfixOp { .LessOrEqual = void{} }, - Token.Id.AngleBracketRight => ast.NodeInfixOp.InfixOp { .GreaterThan = void{} }, - Token.Id.AngleBracketRightEqual => ast.NodeInfixOp.InfixOp { .GreaterOrEqual = void{} }, + Token.Id.BangEqual => ast.Node.InfixOp.Op { .BangEqual = void{} }, + Token.Id.EqualEqual => ast.Node.InfixOp.Op { .EqualEqual = void{} }, + Token.Id.AngleBracketLeft => ast.Node.InfixOp.Op { .LessThan = void{} }, + Token.Id.AngleBracketLeftEqual => ast.Node.InfixOp.Op { .LessOrEqual = void{} }, + Token.Id.AngleBracketRight => ast.Node.InfixOp.Op { .GreaterThan = void{} }, + Token.Id.AngleBracketRightEqual => ast.Node.InfixOp.Op { .GreaterOrEqual = void{} }, else => null, }; } - fn tokenIdToBitShift(id: @TagType(Token.Id)) ?ast.NodeInfixOp.InfixOp { + fn tokenIdToBitShift(id: @TagType(Token.Id)) ?ast.Node.InfixOp.Op { return switch (id) { - Token.Id.AngleBracketAngleBracketLeft => ast.NodeInfixOp.InfixOp { .BitShiftLeft = void{} }, - Token.Id.AngleBracketAngleBracketRight => ast.NodeInfixOp.InfixOp { .BitShiftRight = void{} }, + Token.Id.AngleBracketAngleBracketLeft => ast.Node.InfixOp.Op { .BitShiftLeft = void{} }, + Token.Id.AngleBracketAngleBracketRight => ast.Node.InfixOp.Op { .BitShiftRight = void{} }, else => null, }; } - fn tokenIdToAddition(id: @TagType(Token.Id)) ?ast.NodeInfixOp.InfixOp { + fn tokenIdToAddition(id: @TagType(Token.Id)) ?ast.Node.InfixOp.Op { return switch (id) { - Token.Id.Minus => ast.NodeInfixOp.InfixOp { .Sub = void{} }, - Token.Id.MinusPercent => ast.NodeInfixOp.InfixOp { .SubWrap = void{} }, - Token.Id.Plus => ast.NodeInfixOp.InfixOp { .Add = void{} }, - Token.Id.PlusPercent => ast.NodeInfixOp.InfixOp { .AddWrap = void{} }, - Token.Id.PlusPlus => ast.NodeInfixOp.InfixOp { .ArrayCat = void{} }, + Token.Id.Minus => ast.Node.InfixOp.Op { .Sub = void{} }, + Token.Id.MinusPercent => ast.Node.InfixOp.Op { .SubWrap = void{} }, + Token.Id.Plus => ast.Node.InfixOp.Op { .Add = void{} }, + Token.Id.PlusPercent => ast.Node.InfixOp.Op { .AddWrap = void{} }, + Token.Id.PlusPlus => ast.Node.InfixOp.Op { .ArrayCat = void{} }, else => null, }; } - fn tokenIdToMultiply(id: @TagType(Token.Id)) ?ast.NodeInfixOp.InfixOp { + fn tokenIdToMultiply(id: @TagType(Token.Id)) ?ast.Node.InfixOp.Op { return switch (id) { - Token.Id.Slash => ast.NodeInfixOp.InfixOp { .Div = void{} }, - Token.Id.Asterisk => ast.NodeInfixOp.InfixOp { .Mult = void{} }, - Token.Id.AsteriskAsterisk => ast.NodeInfixOp.InfixOp { .ArrayMult = void{} }, - Token.Id.AsteriskPercent => ast.NodeInfixOp.InfixOp { .MultWrap = void{} }, - Token.Id.Percent => ast.NodeInfixOp.InfixOp { .Mod = void{} }, - Token.Id.PipePipe => ast.NodeInfixOp.InfixOp { .MergeErrorSets = void{} }, + Token.Id.Slash => ast.Node.InfixOp.Op { .Div = void{} }, + Token.Id.Asterisk => ast.Node.InfixOp.Op { .Mult = void{} }, + Token.Id.AsteriskAsterisk => ast.Node.InfixOp.Op { .ArrayMult = void{} }, + Token.Id.AsteriskPercent => ast.Node.InfixOp.Op { .MultWrap = void{} }, + Token.Id.Percent => ast.Node.InfixOp.Op { .Mod = void{} }, + Token.Id.PipePipe => ast.Node.InfixOp.Op { .MergeErrorSets = void{} }, else => null, }; } - fn tokenIdToPrefixOp(id: @TagType(Token.Id)) ?ast.NodePrefixOp.PrefixOp { + fn tokenIdToPrefixOp(id: @TagType(Token.Id)) ?ast.Node.PrefixOp.Op { return switch (id) { - Token.Id.Bang => ast.NodePrefixOp.PrefixOp { .BoolNot = void{} }, - Token.Id.Tilde => ast.NodePrefixOp.PrefixOp { .BitNot = void{} }, - Token.Id.Minus => ast.NodePrefixOp.PrefixOp { .Negation = void{} }, - Token.Id.MinusPercent => ast.NodePrefixOp.PrefixOp { .NegationWrap = void{} }, - Token.Id.Asterisk, Token.Id.AsteriskAsterisk => ast.NodePrefixOp.PrefixOp { .Deref = void{} }, - Token.Id.Ampersand => ast.NodePrefixOp.PrefixOp { - .AddrOf = ast.NodePrefixOp.AddrOfInfo { + Token.Id.Bang => ast.Node.PrefixOp.Op { .BoolNot = void{} }, + Token.Id.Tilde => ast.Node.PrefixOp.Op { .BitNot = void{} }, + Token.Id.Minus => ast.Node.PrefixOp.Op { .Negation = void{} }, + Token.Id.MinusPercent => ast.Node.PrefixOp.Op { .NegationWrap = void{} }, + Token.Id.Asterisk, Token.Id.AsteriskAsterisk => ast.Node.PrefixOp.Op { .Deref = void{} }, + Token.Id.Ampersand => ast.Node.PrefixOp.Op { + .AddrOf = ast.Node.PrefixOp.AddrOfInfo { .align_expr = null, .bit_offset_start_token = null, .bit_offset_end_token = null, @@ -3067,10 +3085,10 @@ pub const Parser = struct { .volatile_token = null, }, }, - Token.Id.QuestionMark => ast.NodePrefixOp.PrefixOp { .MaybeType = void{} }, - Token.Id.QuestionMarkQuestionMark => ast.NodePrefixOp.PrefixOp { .UnwrapMaybe = void{} }, - Token.Id.Keyword_await => ast.NodePrefixOp.PrefixOp { .Await = void{} }, - Token.Id.Keyword_try => ast.NodePrefixOp.PrefixOp { .Try = void{ } }, + Token.Id.QuestionMark => ast.Node.PrefixOp.Op { .MaybeType = void{} }, + Token.Id.QuestionMarkQuestionMark => ast.Node.PrefixOp.Op { .UnwrapMaybe = void{} }, + Token.Id.Keyword_await => ast.Node.PrefixOp.Op { .Await = void{} }, + Token.Id.Keyword_try => ast.Node.PrefixOp.Op { .Try = void{ } }, else => null, }; } @@ -3080,11 +3098,7 @@ pub const Parser = struct { *node = *init_to; node.base = blk: { const id = ast.Node.typeToId(T); - if (self.pending_line_comment_node) |comment_node| { - self.pending_line_comment_node = null; - break :blk ast.Node {.id = id, .comment = comment_node}; - } - break :blk ast.Node {.id = id, .comment = null }; + break :blk ast.Node {.id = id}; }; return node; @@ -3183,7 +3197,7 @@ pub const Parser = struct { indent: usize, }; - pub fn renderAst(self: &Parser, stream: var, root_node: &ast.NodeRoot) !void { + pub fn renderAst(self: &Parser, stream: var, root_node: &ast.Node.Root) !void { var stack = self.initUtilityArrayList(RenderAstFrame); defer self.deinitUtilityArrayList(stack); @@ -3215,14 +3229,14 @@ pub const Parser = struct { ParamDecl: &ast.Node, Text: []const u8, Expression: &ast.Node, - VarDecl: &ast.NodeVarDecl, + VarDecl: &ast.Node.VarDecl, Statement: &ast.Node, - FieldInitializer: &ast.NodeFieldInitializer, + FieldInitializer: &ast.Node.FieldInitializer, PrintIndent, Indent: usize, }; - pub fn renderSource(self: &Parser, stream: var, root_node: &ast.NodeRoot) !void { + pub fn renderSource(self: &Parser, stream: var, root_node: &ast.Node.Root) !void { var stack = self.initUtilityArrayList(RenderState); defer self.deinitUtilityArrayList(stack); @@ -3256,7 +3270,8 @@ pub const Parser = struct { RenderState.TopLevelDecl => |decl| { switch (decl.id) { ast.Node.Id.FnProto => { - const fn_proto = @fieldParentPtr(ast.NodeFnProto, "base", decl); + const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl); + try self.renderComments(stream, fn_proto, indent); if (fn_proto.body_node) |body_node| { stack.append(RenderState { .Expression = body_node}) catch unreachable; @@ -3268,7 +3283,7 @@ pub const Parser = struct { try stack.append(RenderState { .Expression = decl }); }, ast.Node.Id.Use => { - const use_decl = @fieldParentPtr(ast.NodeUse, "base", decl); + const use_decl = @fieldParentPtr(ast.Node.Use, "base", decl); if (use_decl.visib_token) |visib_token| { try stream.print("{} ", self.tokenizer.getTokenSlice(visib_token)); } @@ -3277,18 +3292,19 @@ pub const Parser = struct { try stack.append(RenderState { .Expression = use_decl.expr }); }, ast.Node.Id.VarDecl => { - const var_decl = @fieldParentPtr(ast.NodeVarDecl, "base", decl); + const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", decl); try stack.append(RenderState { .VarDecl = var_decl}); }, ast.Node.Id.TestDecl => { - const test_decl = @fieldParentPtr(ast.NodeTestDecl, "base", decl); + const test_decl = @fieldParentPtr(ast.Node.TestDecl, "base", decl); + try self.renderComments(stream, test_decl, indent); try stream.print("test "); try stack.append(RenderState { .Expression = test_decl.body_node }); try stack.append(RenderState { .Text = " " }); try stack.append(RenderState { .Expression = test_decl.name }); }, ast.Node.Id.StructField => { - const field = @fieldParentPtr(ast.NodeStructField, "base", decl); + const field = @fieldParentPtr(ast.Node.StructField, "base", decl); if (field.visib_token) |visib_token| { try stream.print("{} ", self.tokenizer.getTokenSlice(visib_token)); } @@ -3296,7 +3312,7 @@ pub const Parser = struct { try stack.append(RenderState { .Expression = field.type_expr}); }, ast.Node.Id.UnionTag => { - const tag = @fieldParentPtr(ast.NodeUnionTag, "base", decl); + const tag = @fieldParentPtr(ast.Node.UnionTag, "base", decl); try stream.print("{}", self.tokenizer.getTokenSlice(tag.name_token)); if (tag.type_expr) |type_expr| { @@ -3305,7 +3321,7 @@ pub const Parser = struct { } }, ast.Node.Id.EnumTag => { - const tag = @fieldParentPtr(ast.NodeEnumTag, "base", decl); + const tag = @fieldParentPtr(ast.Node.EnumTag, "base", decl); try stream.print("{}", self.tokenizer.getTokenSlice(tag.name_token)); if (tag.value) |value| { @@ -3324,6 +3340,7 @@ pub const Parser = struct { }, RenderState.FieldInitializer => |field_init| { + //TODO try self.renderComments(stream, field_init, indent); try stream.print(".{}", self.tokenizer.getTokenSlice(field_init.name_token)); try stream.print(" = "); try stack.append(RenderState { .Expression = field_init.expr }); @@ -3369,7 +3386,8 @@ pub const Parser = struct { }, RenderState.ParamDecl => |base| { - const param_decl = @fieldParentPtr(ast.NodeParamDecl, "base", base); + const param_decl = @fieldParentPtr(ast.Node.ParamDecl, "base", base); + // TODO try self.renderComments(stream, param_decl, indent); if (param_decl.comptime_token) |comptime_token| { try stream.print("{} ", self.tokenizer.getTokenSlice(comptime_token)); } @@ -3390,11 +3408,11 @@ pub const Parser = struct { }, RenderState.Expression => |base| switch (base.id) { ast.Node.Id.Identifier => { - const identifier = @fieldParentPtr(ast.NodeIdentifier, "base", base); + const identifier = @fieldParentPtr(ast.Node.Identifier, "base", base); try stream.print("{}", self.tokenizer.getTokenSlice(identifier.token)); }, ast.Node.Id.Block => { - const block = @fieldParentPtr(ast.NodeBlock, "base", base); + const block = @fieldParentPtr(ast.Node.Block, "base", base); if (block.label) |label| { try stream.print("{}: ", self.tokenizer.getTokenSlice(label)); } @@ -3430,17 +3448,17 @@ pub const Parser = struct { } }, ast.Node.Id.Defer => { - const defer_node = @fieldParentPtr(ast.NodeDefer, "base", base); + const defer_node = @fieldParentPtr(ast.Node.Defer, "base", base); try stream.print("{} ", self.tokenizer.getTokenSlice(defer_node.defer_token)); try stack.append(RenderState { .Expression = defer_node.expr }); }, ast.Node.Id.Comptime => { - const comptime_node = @fieldParentPtr(ast.NodeComptime, "base", base); + const comptime_node = @fieldParentPtr(ast.Node.Comptime, "base", base); try stream.print("{} ", self.tokenizer.getTokenSlice(comptime_node.comptime_token)); try stack.append(RenderState { .Expression = comptime_node.expr }); }, ast.Node.Id.AsyncAttribute => { - const async_attr = @fieldParentPtr(ast.NodeAsyncAttribute, "base", base); + const async_attr = @fieldParentPtr(ast.Node.AsyncAttribute, "base", base); try stream.print("{}", self.tokenizer.getTokenSlice(async_attr.async_token)); if (async_attr.allocator_type) |allocator_type| { @@ -3450,7 +3468,7 @@ pub const Parser = struct { } }, ast.Node.Id.Suspend => { - const suspend_node = @fieldParentPtr(ast.NodeSuspend, "base", base); + const suspend_node = @fieldParentPtr(ast.Node.Suspend, "base", base); try stream.print("{}", self.tokenizer.getTokenSlice(suspend_node.suspend_token)); if (suspend_node.body) |body| { @@ -3464,10 +3482,10 @@ pub const Parser = struct { } }, ast.Node.Id.InfixOp => { - const prefix_op_node = @fieldParentPtr(ast.NodeInfixOp, "base", base); + const prefix_op_node = @fieldParentPtr(ast.Node.InfixOp, "base", base); try stack.append(RenderState { .Expression = prefix_op_node.rhs }); - if (prefix_op_node.op == ast.NodeInfixOp.InfixOp.Catch) { + if (prefix_op_node.op == ast.Node.InfixOp.Op.Catch) { if (prefix_op_node.op.Catch) |payload| { try stack.append(RenderState { .Text = " " }); try stack.append(RenderState { .Expression = payload }); @@ -3475,49 +3493,49 @@ pub const Parser = struct { try stack.append(RenderState { .Text = " catch " }); } else { const text = switch (prefix_op_node.op) { - ast.NodeInfixOp.InfixOp.Add => " + ", - ast.NodeInfixOp.InfixOp.AddWrap => " +% ", - ast.NodeInfixOp.InfixOp.ArrayCat => " ++ ", - ast.NodeInfixOp.InfixOp.ArrayMult => " ** ", - ast.NodeInfixOp.InfixOp.Assign => " = ", - ast.NodeInfixOp.InfixOp.AssignBitAnd => " &= ", - ast.NodeInfixOp.InfixOp.AssignBitOr => " |= ", - ast.NodeInfixOp.InfixOp.AssignBitShiftLeft => " <<= ", - ast.NodeInfixOp.InfixOp.AssignBitShiftRight => " >>= ", - ast.NodeInfixOp.InfixOp.AssignBitXor => " ^= ", - ast.NodeInfixOp.InfixOp.AssignDiv => " /= ", - ast.NodeInfixOp.InfixOp.AssignMinus => " -= ", - ast.NodeInfixOp.InfixOp.AssignMinusWrap => " -%= ", - ast.NodeInfixOp.InfixOp.AssignMod => " %= ", - ast.NodeInfixOp.InfixOp.AssignPlus => " += ", - ast.NodeInfixOp.InfixOp.AssignPlusWrap => " +%= ", - ast.NodeInfixOp.InfixOp.AssignTimes => " *= ", - ast.NodeInfixOp.InfixOp.AssignTimesWarp => " *%= ", - ast.NodeInfixOp.InfixOp.BangEqual => " != ", - ast.NodeInfixOp.InfixOp.BitAnd => " & ", - ast.NodeInfixOp.InfixOp.BitOr => " | ", - ast.NodeInfixOp.InfixOp.BitShiftLeft => " << ", - ast.NodeInfixOp.InfixOp.BitShiftRight => " >> ", - ast.NodeInfixOp.InfixOp.BitXor => " ^ ", - ast.NodeInfixOp.InfixOp.BoolAnd => " and ", - ast.NodeInfixOp.InfixOp.BoolOr => " or ", - ast.NodeInfixOp.InfixOp.Div => " / ", - ast.NodeInfixOp.InfixOp.EqualEqual => " == ", - ast.NodeInfixOp.InfixOp.ErrorUnion => "!", - ast.NodeInfixOp.InfixOp.GreaterOrEqual => " >= ", - ast.NodeInfixOp.InfixOp.GreaterThan => " > ", - ast.NodeInfixOp.InfixOp.LessOrEqual => " <= ", - ast.NodeInfixOp.InfixOp.LessThan => " < ", - ast.NodeInfixOp.InfixOp.MergeErrorSets => " || ", - ast.NodeInfixOp.InfixOp.Mod => " % ", - ast.NodeInfixOp.InfixOp.Mult => " * ", - ast.NodeInfixOp.InfixOp.MultWrap => " *% ", - ast.NodeInfixOp.InfixOp.Period => ".", - ast.NodeInfixOp.InfixOp.Sub => " - ", - ast.NodeInfixOp.InfixOp.SubWrap => " -% ", - ast.NodeInfixOp.InfixOp.UnwrapMaybe => " ?? ", - ast.NodeInfixOp.InfixOp.Range => " ... ", - ast.NodeInfixOp.InfixOp.Catch => unreachable, + ast.Node.InfixOp.Op.Add => " + ", + ast.Node.InfixOp.Op.AddWrap => " +% ", + ast.Node.InfixOp.Op.ArrayCat => " ++ ", + ast.Node.InfixOp.Op.ArrayMult => " ** ", + ast.Node.InfixOp.Op.Assign => " = ", + ast.Node.InfixOp.Op.AssignBitAnd => " &= ", + ast.Node.InfixOp.Op.AssignBitOr => " |= ", + ast.Node.InfixOp.Op.AssignBitShiftLeft => " <<= ", + ast.Node.InfixOp.Op.AssignBitShiftRight => " >>= ", + ast.Node.InfixOp.Op.AssignBitXor => " ^= ", + ast.Node.InfixOp.Op.AssignDiv => " /= ", + ast.Node.InfixOp.Op.AssignMinus => " -= ", + ast.Node.InfixOp.Op.AssignMinusWrap => " -%= ", + ast.Node.InfixOp.Op.AssignMod => " %= ", + ast.Node.InfixOp.Op.AssignPlus => " += ", + ast.Node.InfixOp.Op.AssignPlusWrap => " +%= ", + ast.Node.InfixOp.Op.AssignTimes => " *= ", + ast.Node.InfixOp.Op.AssignTimesWarp => " *%= ", + ast.Node.InfixOp.Op.BangEqual => " != ", + ast.Node.InfixOp.Op.BitAnd => " & ", + ast.Node.InfixOp.Op.BitOr => " | ", + ast.Node.InfixOp.Op.BitShiftLeft => " << ", + ast.Node.InfixOp.Op.BitShiftRight => " >> ", + ast.Node.InfixOp.Op.BitXor => " ^ ", + ast.Node.InfixOp.Op.BoolAnd => " and ", + ast.Node.InfixOp.Op.BoolOr => " or ", + ast.Node.InfixOp.Op.Div => " / ", + ast.Node.InfixOp.Op.EqualEqual => " == ", + ast.Node.InfixOp.Op.ErrorUnion => "!", + ast.Node.InfixOp.Op.GreaterOrEqual => " >= ", + ast.Node.InfixOp.Op.GreaterThan => " > ", + ast.Node.InfixOp.Op.LessOrEqual => " <= ", + ast.Node.InfixOp.Op.LessThan => " < ", + ast.Node.InfixOp.Op.MergeErrorSets => " || ", + ast.Node.InfixOp.Op.Mod => " % ", + ast.Node.InfixOp.Op.Mult => " * ", + ast.Node.InfixOp.Op.MultWrap => " *% ", + ast.Node.InfixOp.Op.Period => ".", + ast.Node.InfixOp.Op.Sub => " - ", + ast.Node.InfixOp.Op.SubWrap => " -% ", + ast.Node.InfixOp.Op.UnwrapMaybe => " ?? ", + ast.Node.InfixOp.Op.Range => " ... ", + ast.Node.InfixOp.Op.Catch => unreachable, }; try stack.append(RenderState { .Text = text }); @@ -3525,10 +3543,10 @@ pub const Parser = struct { try stack.append(RenderState { .Expression = prefix_op_node.lhs }); }, ast.Node.Id.PrefixOp => { - const prefix_op_node = @fieldParentPtr(ast.NodePrefixOp, "base", base); + const prefix_op_node = @fieldParentPtr(ast.Node.PrefixOp, "base", base); try stack.append(RenderState { .Expression = prefix_op_node.rhs }); switch (prefix_op_node.op) { - ast.NodePrefixOp.PrefixOp.AddrOf => |addr_of_info| { + ast.Node.PrefixOp.Op.AddrOf => |addr_of_info| { try stream.write("&"); if (addr_of_info.volatile_token != null) { try stack.append(RenderState { .Text = "volatile "}); @@ -3542,7 +3560,7 @@ pub const Parser = struct { try stack.append(RenderState { .Expression = align_expr}); } }, - ast.NodePrefixOp.PrefixOp.SliceType => |addr_of_info| { + ast.Node.PrefixOp.Op.SliceType => |addr_of_info| { try stream.write("[]"); if (addr_of_info.volatile_token != null) { try stack.append(RenderState { .Text = "volatile "}); @@ -3556,29 +3574,29 @@ pub const Parser = struct { try stack.append(RenderState { .Expression = align_expr}); } }, - ast.NodePrefixOp.PrefixOp.ArrayType => |array_index| { + ast.Node.PrefixOp.Op.ArrayType => |array_index| { try stack.append(RenderState { .Text = "]"}); try stack.append(RenderState { .Expression = array_index}); try stack.append(RenderState { .Text = "["}); }, - ast.NodePrefixOp.PrefixOp.BitNot => try stream.write("~"), - ast.NodePrefixOp.PrefixOp.BoolNot => try stream.write("!"), - ast.NodePrefixOp.PrefixOp.Deref => try stream.write("*"), - ast.NodePrefixOp.PrefixOp.Negation => try stream.write("-"), - ast.NodePrefixOp.PrefixOp.NegationWrap => try stream.write("-%"), - ast.NodePrefixOp.PrefixOp.Try => try stream.write("try "), - ast.NodePrefixOp.PrefixOp.UnwrapMaybe => try stream.write("??"), - ast.NodePrefixOp.PrefixOp.MaybeType => try stream.write("?"), - ast.NodePrefixOp.PrefixOp.Await => try stream.write("await "), - ast.NodePrefixOp.PrefixOp.Cancel => try stream.write("cancel "), - ast.NodePrefixOp.PrefixOp.Resume => try stream.write("resume "), + ast.Node.PrefixOp.Op.BitNot => try stream.write("~"), + ast.Node.PrefixOp.Op.BoolNot => try stream.write("!"), + ast.Node.PrefixOp.Op.Deref => try stream.write("*"), + ast.Node.PrefixOp.Op.Negation => try stream.write("-"), + ast.Node.PrefixOp.Op.NegationWrap => try stream.write("-%"), + ast.Node.PrefixOp.Op.Try => try stream.write("try "), + ast.Node.PrefixOp.Op.UnwrapMaybe => try stream.write("??"), + ast.Node.PrefixOp.Op.MaybeType => try stream.write("?"), + ast.Node.PrefixOp.Op.Await => try stream.write("await "), + ast.Node.PrefixOp.Op.Cancel => try stream.write("cancel "), + ast.Node.PrefixOp.Op.Resume => try stream.write("resume "), } }, ast.Node.Id.SuffixOp => { - const suffix_op = @fieldParentPtr(ast.NodeSuffixOp, "base", base); + const suffix_op = @fieldParentPtr(ast.Node.SuffixOp, "base", base); switch (suffix_op.op) { - ast.NodeSuffixOp.SuffixOp.Call => |call_info| { + ast.Node.SuffixOp.Op.Call => |call_info| { try stack.append(RenderState { .Text = ")"}); var i = call_info.params.len; while (i != 0) { @@ -3597,13 +3615,13 @@ pub const Parser = struct { try stack.append(RenderState { .Expression = &async_attr.base }); } }, - ast.NodeSuffixOp.SuffixOp.ArrayAccess => |index_expr| { + ast.Node.SuffixOp.Op.ArrayAccess => |index_expr| { try stack.append(RenderState { .Text = "]"}); try stack.append(RenderState { .Expression = index_expr}); try stack.append(RenderState { .Text = "["}); try stack.append(RenderState { .Expression = suffix_op.lhs }); }, - ast.NodeSuffixOp.SuffixOp.Slice => |range| { + ast.Node.SuffixOp.Op.Slice => |range| { try stack.append(RenderState { .Text = "]"}); if (range.end) |end| { try stack.append(RenderState { .Expression = end}); @@ -3613,7 +3631,7 @@ pub const Parser = struct { try stack.append(RenderState { .Text = "["}); try stack.append(RenderState { .Expression = suffix_op.lhs }); }, - ast.NodeSuffixOp.SuffixOp.StructInitializer => |field_inits| { + ast.Node.SuffixOp.Op.StructInitializer => |field_inits| { if (field_inits.len == 0) { try stack.append(RenderState { .Text = "{}" }); try stack.append(RenderState { .Expression = suffix_op.lhs }); @@ -3634,7 +3652,7 @@ pub const Parser = struct { try stack.append(RenderState { .Text = " {\n"}); try stack.append(RenderState { .Expression = suffix_op.lhs }); }, - ast.NodeSuffixOp.SuffixOp.ArrayInitializer => |exprs| { + ast.Node.SuffixOp.Op.ArrayInitializer => |exprs| { if (exprs.len == 0) { try stack.append(RenderState { .Text = "{}" }); try stack.append(RenderState { .Expression = suffix_op.lhs }); @@ -3658,7 +3676,7 @@ pub const Parser = struct { } }, ast.Node.Id.ControlFlowExpression => { - const flow_expr = @fieldParentPtr(ast.NodeControlFlowExpression, "base", base); + const flow_expr = @fieldParentPtr(ast.Node.ControlFlowExpression, "base", base); if (flow_expr.rhs) |rhs| { try stack.append(RenderState { .Expression = rhs }); @@ -3666,34 +3684,34 @@ pub const Parser = struct { } switch (flow_expr.kind) { - ast.NodeControlFlowExpression.Kind.Break => |maybe_label| { + ast.Node.ControlFlowExpression.Kind.Break => |maybe_label| { try stream.print("break"); if (maybe_label) |label| { try stream.print(" :"); try stack.append(RenderState { .Expression = label }); } }, - ast.NodeControlFlowExpression.Kind.Continue => |maybe_label| { + ast.Node.ControlFlowExpression.Kind.Continue => |maybe_label| { try stream.print("continue"); if (maybe_label) |label| { try stream.print(" :"); try stack.append(RenderState { .Expression = label }); } }, - ast.NodeControlFlowExpression.Kind.Return => { + ast.Node.ControlFlowExpression.Kind.Return => { try stream.print("return"); }, } }, ast.Node.Id.Payload => { - const payload = @fieldParentPtr(ast.NodePayload, "base", base); + const payload = @fieldParentPtr(ast.Node.Payload, "base", base); try stack.append(RenderState { .Text = "|"}); try stack.append(RenderState { .Expression = payload.error_symbol }); try stack.append(RenderState { .Text = "|"}); }, ast.Node.Id.PointerPayload => { - const payload = @fieldParentPtr(ast.NodePointerPayload, "base", base); + const payload = @fieldParentPtr(ast.Node.PointerPayload, "base", base); try stack.append(RenderState { .Text = "|"}); try stack.append(RenderState { .Expression = payload.value_symbol }); @@ -3704,7 +3722,7 @@ pub const Parser = struct { try stack.append(RenderState { .Text = "|"}); }, ast.Node.Id.PointerIndexPayload => { - const payload = @fieldParentPtr(ast.NodePointerIndexPayload, "base", base); + const payload = @fieldParentPtr(ast.Node.PointerIndexPayload, "base", base); try stack.append(RenderState { .Text = "|"}); if (payload.index_symbol) |index_symbol| { @@ -3721,69 +3739,69 @@ pub const Parser = struct { try stack.append(RenderState { .Text = "|"}); }, ast.Node.Id.GroupedExpression => { - const grouped_expr = @fieldParentPtr(ast.NodeGroupedExpression, "base", base); + const grouped_expr = @fieldParentPtr(ast.Node.GroupedExpression, "base", base); try stack.append(RenderState { .Text = ")"}); try stack.append(RenderState { .Expression = grouped_expr.expr }); try stack.append(RenderState { .Text = "("}); }, ast.Node.Id.FieldInitializer => { - const field_init = @fieldParentPtr(ast.NodeFieldInitializer, "base", base); + const field_init = @fieldParentPtr(ast.Node.FieldInitializer, "base", base); try stream.print(".{} = ", self.tokenizer.getTokenSlice(field_init.name_token)); try stack.append(RenderState { .Expression = field_init.expr }); }, ast.Node.Id.IntegerLiteral => { - const integer_literal = @fieldParentPtr(ast.NodeIntegerLiteral, "base", base); + const integer_literal = @fieldParentPtr(ast.Node.IntegerLiteral, "base", base); try stream.print("{}", self.tokenizer.getTokenSlice(integer_literal.token)); }, ast.Node.Id.FloatLiteral => { - const float_literal = @fieldParentPtr(ast.NodeFloatLiteral, "base", base); + const float_literal = @fieldParentPtr(ast.Node.FloatLiteral, "base", base); try stream.print("{}", self.tokenizer.getTokenSlice(float_literal.token)); }, ast.Node.Id.StringLiteral => { - const string_literal = @fieldParentPtr(ast.NodeStringLiteral, "base", base); + const string_literal = @fieldParentPtr(ast.Node.StringLiteral, "base", base); try stream.print("{}", self.tokenizer.getTokenSlice(string_literal.token)); }, ast.Node.Id.CharLiteral => { - const char_literal = @fieldParentPtr(ast.NodeCharLiteral, "base", base); + const char_literal = @fieldParentPtr(ast.Node.CharLiteral, "base", base); try stream.print("{}", self.tokenizer.getTokenSlice(char_literal.token)); }, ast.Node.Id.BoolLiteral => { - const bool_literal = @fieldParentPtr(ast.NodeCharLiteral, "base", base); + const bool_literal = @fieldParentPtr(ast.Node.CharLiteral, "base", base); try stream.print("{}", self.tokenizer.getTokenSlice(bool_literal.token)); }, ast.Node.Id.NullLiteral => { - const null_literal = @fieldParentPtr(ast.NodeNullLiteral, "base", base); + const null_literal = @fieldParentPtr(ast.Node.NullLiteral, "base", base); try stream.print("{}", self.tokenizer.getTokenSlice(null_literal.token)); }, ast.Node.Id.ThisLiteral => { - const this_literal = @fieldParentPtr(ast.NodeThisLiteral, "base", base); + const this_literal = @fieldParentPtr(ast.Node.ThisLiteral, "base", base); try stream.print("{}", self.tokenizer.getTokenSlice(this_literal.token)); }, ast.Node.Id.Unreachable => { - const unreachable_node = @fieldParentPtr(ast.NodeUnreachable, "base", base); + const unreachable_node = @fieldParentPtr(ast.Node.Unreachable, "base", base); try stream.print("{}", self.tokenizer.getTokenSlice(unreachable_node.token)); }, ast.Node.Id.ErrorType => { - const error_type = @fieldParentPtr(ast.NodeErrorType, "base", base); + const error_type = @fieldParentPtr(ast.Node.ErrorType, "base", base); try stream.print("{}", self.tokenizer.getTokenSlice(error_type.token)); }, ast.Node.Id.VarType => { - const var_type = @fieldParentPtr(ast.NodeVarType, "base", base); + const var_type = @fieldParentPtr(ast.Node.VarType, "base", base); try stream.print("{}", self.tokenizer.getTokenSlice(var_type.token)); }, ast.Node.Id.ContainerDecl => { - const container_decl = @fieldParentPtr(ast.NodeContainerDecl, "base", base); + const container_decl = @fieldParentPtr(ast.Node.ContainerDecl, "base", base); switch (container_decl.layout) { - ast.NodeContainerDecl.Layout.Packed => try stream.print("packed "), - ast.NodeContainerDecl.Layout.Extern => try stream.print("extern "), - ast.NodeContainerDecl.Layout.Auto => { }, + ast.Node.ContainerDecl.Layout.Packed => try stream.print("packed "), + ast.Node.ContainerDecl.Layout.Extern => try stream.print("extern "), + ast.Node.ContainerDecl.Layout.Auto => { }, } switch (container_decl.kind) { - ast.NodeContainerDecl.Kind.Struct => try stream.print("struct"), - ast.NodeContainerDecl.Kind.Enum => try stream.print("enum"), - ast.NodeContainerDecl.Kind.Union => try stream.print("union"), + ast.Node.ContainerDecl.Kind.Struct => try stream.print("struct"), + ast.Node.ContainerDecl.Kind.Enum => try stream.print("enum"), + ast.Node.ContainerDecl.Kind.Union => try stream.print("union"), } try stack.append(RenderState { .Text = "}"}); @@ -3823,9 +3841,9 @@ pub const Parser = struct { try stack.append(RenderState { .Text = "{"}); switch (container_decl.init_arg_expr) { - ast.NodeContainerDecl.InitArg.None => try stack.append(RenderState { .Text = " "}), - ast.NodeContainerDecl.InitArg.Enum => try stack.append(RenderState { .Text = "(enum) "}), - ast.NodeContainerDecl.InitArg.Type => |type_expr| { + ast.Node.ContainerDecl.InitArg.None => try stack.append(RenderState { .Text = " "}), + ast.Node.ContainerDecl.InitArg.Enum => try stack.append(RenderState { .Text = "(enum) "}), + ast.Node.ContainerDecl.InitArg.Type => |type_expr| { try stack.append(RenderState { .Text = ") "}); try stack.append(RenderState { .Expression = type_expr}); try stack.append(RenderState { .Text = "("}); @@ -3833,7 +3851,7 @@ pub const Parser = struct { } }, ast.Node.Id.ErrorSetDecl => { - const err_set_decl = @fieldParentPtr(ast.NodeErrorSetDecl, "base", base); + const err_set_decl = @fieldParentPtr(ast.Node.ErrorSetDecl, "base", base); try stream.print("error "); try stack.append(RenderState { .Text = "}"}); @@ -3866,7 +3884,7 @@ pub const Parser = struct { try stack.append(RenderState { .Text = "{"}); }, ast.Node.Id.MultilineStringLiteral => { - const multiline_str_literal = @fieldParentPtr(ast.NodeMultilineStringLiteral, "base", base); + const multiline_str_literal = @fieldParentPtr(ast.Node.MultilineStringLiteral, "base", base); try stream.print("\n"); var i : usize = 0; @@ -3878,11 +3896,11 @@ pub const Parser = struct { try stream.writeByteNTimes(' ', indent + indent_delta); }, ast.Node.Id.UndefinedLiteral => { - const undefined_literal = @fieldParentPtr(ast.NodeUndefinedLiteral, "base", base); + const undefined_literal = @fieldParentPtr(ast.Node.UndefinedLiteral, "base", base); try stream.print("{}", self.tokenizer.getTokenSlice(undefined_literal.token)); }, ast.Node.Id.BuiltinCall => { - const builtin_call = @fieldParentPtr(ast.NodeBuiltinCall, "base", base); + const builtin_call = @fieldParentPtr(ast.Node.BuiltinCall, "base", base); try stream.print("{}(", self.tokenizer.getTokenSlice(builtin_call.builtin_token)); try stack.append(RenderState { .Text = ")"}); var i = builtin_call.params.len; @@ -3896,13 +3914,13 @@ pub const Parser = struct { } }, ast.Node.Id.FnProto => { - const fn_proto = @fieldParentPtr(ast.NodeFnProto, "base", base); + const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", base); switch (fn_proto.return_type) { - ast.NodeFnProto.ReturnType.Explicit => |node| { + ast.Node.FnProto.ReturnType.Explicit => |node| { try stack.append(RenderState { .Expression = node}); }, - ast.NodeFnProto.ReturnType.InferErrorSet => |node| { + ast.Node.FnProto.ReturnType.InferErrorSet => |node| { try stack.append(RenderState { .Expression = node}); try stack.append(RenderState { .Text = "!"}); }, @@ -3960,7 +3978,7 @@ pub const Parser = struct { }, ast.Node.Id.LineComment => @panic("TODO render line comment in an expression"), ast.Node.Id.Switch => { - const switch_node = @fieldParentPtr(ast.NodeSwitch, "base", base); + const switch_node = @fieldParentPtr(ast.Node.Switch, "base", base); try stream.print("{} (", self.tokenizer.getTokenSlice(switch_node.switch_token)); try stack.append(RenderState { .Text = "}"}); @@ -3994,7 +4012,7 @@ pub const Parser = struct { try stack.append(RenderState { .Expression = switch_node.expr }); }, ast.Node.Id.SwitchCase => { - const switch_case = @fieldParentPtr(ast.NodeSwitchCase, "base", base); + const switch_case = @fieldParentPtr(ast.Node.SwitchCase, "base", base); try stack.append(RenderState { .Expression = switch_case.expr }); if (switch_case.payload) |payload| { @@ -4016,11 +4034,11 @@ pub const Parser = struct { } }, ast.Node.Id.SwitchElse => { - const switch_else = @fieldParentPtr(ast.NodeSwitchElse, "base", base); + const switch_else = @fieldParentPtr(ast.Node.SwitchElse, "base", base); try stream.print("{}", self.tokenizer.getTokenSlice(switch_else.token)); }, ast.Node.Id.Else => { - const else_node = @fieldParentPtr(ast.NodeElse, "base", base); + const else_node = @fieldParentPtr(ast.Node.Else, "base", base); try stream.print("{}", self.tokenizer.getTokenSlice(else_node.else_token)); switch (else_node.body.id) { @@ -4045,7 +4063,7 @@ pub const Parser = struct { } }, ast.Node.Id.While => { - const while_node = @fieldParentPtr(ast.NodeWhile, "base", base); + const while_node = @fieldParentPtr(ast.Node.While, "base", base); if (while_node.label) |label| { try stream.print("{}: ", self.tokenizer.getTokenSlice(label)); } @@ -4095,7 +4113,7 @@ pub const Parser = struct { try stack.append(RenderState { .Text = "(" }); }, ast.Node.Id.For => { - const for_node = @fieldParentPtr(ast.NodeFor, "base", base); + const for_node = @fieldParentPtr(ast.Node.For, "base", base); if (for_node.label) |label| { try stream.print("{}: ", self.tokenizer.getTokenSlice(label)); } @@ -4138,7 +4156,7 @@ pub const Parser = struct { try stack.append(RenderState { .Text = "(" }); }, ast.Node.Id.If => { - const if_node = @fieldParentPtr(ast.NodeIf, "base", base); + const if_node = @fieldParentPtr(ast.Node.If, "base", base); try stream.print("{} ", self.tokenizer.getTokenSlice(if_node.if_token)); switch (if_node.body.id) { @@ -4185,7 +4203,7 @@ pub const Parser = struct { try stack.append(RenderState { .Text = "(" }); }, ast.Node.Id.Asm => { - const asm_node = @fieldParentPtr(ast.NodeAsm, "base", base); + const asm_node = @fieldParentPtr(ast.Node.Asm, "base", base); try stream.print("{} ", self.tokenizer.getTokenSlice(asm_node.asm_token)); if (asm_node.volatile_token) |volatile_token| { @@ -4272,7 +4290,7 @@ pub const Parser = struct { try stack.append(RenderState { .Text = "(" }); }, ast.Node.Id.AsmInput => { - const asm_input = @fieldParentPtr(ast.NodeAsmInput, "base", base); + const asm_input = @fieldParentPtr(ast.Node.AsmInput, "base", base); try stack.append(RenderState { .Text = ")"}); try stack.append(RenderState { .Expression = asm_input.expr}); @@ -4283,14 +4301,14 @@ pub const Parser = struct { try stack.append(RenderState { .Text = "["}); }, ast.Node.Id.AsmOutput => { - const asm_output = @fieldParentPtr(ast.NodeAsmOutput, "base", base); + const asm_output = @fieldParentPtr(ast.Node.AsmOutput, "base", base); try stack.append(RenderState { .Text = ")"}); switch (asm_output.kind) { - ast.NodeAsmOutput.Kind.Variable => |variable_name| { + ast.Node.AsmOutput.Kind.Variable => |variable_name| { try stack.append(RenderState { .Expression = &variable_name.base}); }, - ast.NodeAsmOutput.Kind.Return => |return_type| { + ast.Node.AsmOutput.Kind.Return => |return_type| { try stack.append(RenderState { .Expression = return_type}); try stack.append(RenderState { .Text = "-> "}); }, @@ -4312,15 +4330,10 @@ pub const Parser = struct { ast.Node.Id.ParamDecl => unreachable, }, RenderState.Statement => |base| { - if (base.comment) |comment| { - for (comment.lines.toSliceConst()) |line_token| { - try stream.print("{}\n", self.tokenizer.getTokenSlice(line_token)); - try stream.writeByteNTimes(' ', indent); - } - } switch (base.id) { ast.Node.Id.VarDecl => { - const var_decl = @fieldParentPtr(ast.NodeVarDecl, "base", base); + const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", base); + try self.renderComments(stream, var_decl, indent); try stack.append(RenderState { .VarDecl = var_decl}); }, else => { @@ -4337,6 +4350,14 @@ pub const Parser = struct { } } + fn renderComments(self: &Parser, stream: var, node: var, indent: usize) !void { + const comment = node.comments ?? return; + for (comment.lines.toSliceConst()) |line_token| { + try stream.print("{}\n", self.tokenizer.getTokenSlice(line_token)); + try stream.writeByteNTimes(' ', indent); + } + } + fn initUtilityArrayList(self: &Parser, comptime T: type) ArrayList(T) { const new_byte_count = self.utility_bytes.len - self.utility_bytes.len % @sizeOf(T); self.utility_bytes = self.util_allocator.alignedShrink(u8, utility_bytes_align, self.utility_bytes, new_byte_count); @@ -4411,6 +4432,14 @@ fn testCanonical(source: []const u8) !void { } } +test "zig fmt: preserve top level comments" { + try testCanonical( + \\// top level comment + \\test "hi" {} + \\ + ); +} + test "zig fmt: get stdout or fail" { try testCanonical( \\const std = @import("std");