diff options
Diffstat (limited to 'lib/std')
| -rw-r--r-- | lib/std/zig/ast.zig | 546 | ||||
| -rw-r--r-- | lib/std/zig/parse.zig | 314 | ||||
| -rw-r--r-- | lib/std/zig/render.zig | 222 |
3 files changed, 643 insertions, 439 deletions
diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig index 7f066f541b..b91cac7865 100644 --- a/lib/std/zig/ast.zig +++ b/lib/std/zig/ast.zig @@ -323,8 +323,8 @@ pub const Error = union(enum) { node: *Node, pub fn render(self: *const ExpectedCall, tokens: []const Token.Id, stream: anytype) !void { - return stream.print("expected " ++ @tagName(Node.Id.Call) ++ ", found {}", .{ - @tagName(self.node.id), + return stream.print("expected " ++ @tagName(Node.Tag.Call) ++ ", found {}", .{ + @tagName(self.node.tag), }); } }; @@ -333,8 +333,8 @@ pub const Error = union(enum) { node: *Node, pub fn render(self: *const ExpectedCallOrFnProto, tokens: []const Token.Id, stream: anytype) !void { - return stream.print("expected " ++ @tagName(Node.Id.Call) ++ " or " ++ - @tagName(Node.Id.FnProto) ++ ", found {}", .{@tagName(self.node.id)}); + return stream.print("expected " ++ @tagName(Node.Tag.Call) ++ " or " ++ + @tagName(Node.Tag.FnProto) ++ ", found {}", .{@tagName(self.node.tag)}); } }; @@ -396,9 +396,9 @@ pub const Error = union(enum) { }; pub const Node = struct { - id: Id, + tag: Tag, - pub const Id = enum { + pub const Tag = enum { // Top level Root, Use, @@ -408,8 +408,54 @@ pub const Node = struct { VarDecl, Defer, - // Operators - InfixOp, + // Infix operators + Catch, + + // SimpleInfixOp + Add, + AddWrap, + ArrayCat, + ArrayMult, + Assign, + AssignBitAnd, + AssignBitOr, + AssignBitShiftLeft, + AssignBitShiftRight, + AssignBitXor, + AssignDiv, + AssignSub, + AssignSubWrap, + AssignMod, + AssignAdd, + AssignAddWrap, + AssignMul, + AssignMulWrap, + BangEqual, + BitAnd, + BitOr, + BitShiftLeft, + BitShiftRight, + BitXor, + BoolAnd, + BoolOr, + Div, + EqualEqual, + ErrorUnion, + GreaterOrEqual, + GreaterThan, + LessOrEqual, + LessThan, + MergeErrorSets, + Mod, + Mul, + MulWrap, + Period, + Range, + Sub, + SubWrap, + UnwrapOptional, + + // SimplePrefixOp AddressOf, Await, BitNot, @@ -419,6 +465,7 @@ pub const Node = struct { NegationWrap, Resume, Try, + ArrayType, /// ArrayType but has a sentinel node. ArrayTypeSentinel, @@ -484,49 +531,177 @@ pub const Node = struct { ContainerField, ErrorTag, FieldInitializer, + + pub fn Type(tag: Tag) type { + return switch (tag) { + .Root => Root, + .Use => Use, + .TestDecl => TestDecl, + .VarDecl => VarDecl, + .Defer => Defer, + .Catch => Catch, + + .Add, + .AddWrap, + .ArrayCat, + .ArrayMult, + .Assign, + .AssignBitAnd, + .AssignBitOr, + .AssignBitShiftLeft, + .AssignBitShiftRight, + .AssignBitXor, + .AssignDiv, + .AssignSub, + .AssignSubWrap, + .AssignMod, + .AssignAdd, + .AssignAddWrap, + .AssignMul, + .AssignMulWrap, + .BangEqual, + .BitAnd, + .BitOr, + .BitShiftLeft, + .BitShiftRight, + .BitXor, + .BoolAnd, + .BoolOr, + .Div, + .EqualEqual, + .ErrorUnion, + .GreaterOrEqual, + .GreaterThan, + .LessOrEqual, + .LessThan, + .MergeErrorSets, + .Mod, + .Mul, + .MulWrap, + .Period, + .Range, + .Sub, + .SubWrap, + .UnwrapOptional, + => SimpleInfixOp, + + .AddressOf, + .Await, + .BitNot, + .BoolNot, + .OptionalType, + .Negation, + .NegationWrap, + .Resume, + .Try, + => SimplePrefixOp, + + .ArrayType => ArrayType, + .ArrayTypeSentinel => ArrayTypeSentinel, + + .PtrType => PtrType, + .SliceType => SliceType, + .SuffixOp => SuffixOp, + + .ArrayInitializer => ArrayInitializer, + .ArrayInitializerDot => ArrayInitializerDot, + + .StructInitializer => StructInitializer, + .StructInitializerDot => StructInitializerDot, + + .Call => Call, + .Switch => Switch, + .While => While, + .For => For, + .If => If, + .ControlFlowExpression => ControlFlowExpression, + .Suspend => Suspend, + .AnyType => AnyType, + .ErrorType => ErrorType, + .FnProto => FnProto, + .AnyFrameType => AnyFrameType, + .IntegerLiteral => IntegerLiteral, + .FloatLiteral => FloatLiteral, + .EnumLiteral => EnumLiteral, + .StringLiteral => StringLiteral, + .MultilineStringLiteral => MultilineStringLiteral, + .CharLiteral => CharLiteral, + .BoolLiteral => BoolLiteral, + .NullLiteral => NullLiteral, + .UndefinedLiteral => UndefinedLiteral, + .Unreachable => Unreachable, + .Identifier => Identifier, + .GroupedExpression => GroupedExpression, + .BuiltinCall => BuiltinCall, + .ErrorSetDecl => ErrorSetDecl, + .ContainerDecl => ContainerDecl, + .Asm => Asm, + .Comptime => Comptime, + .Nosuspend => Nosuspend, + .Block => Block, + .DocComment => DocComment, + .SwitchCase => SwitchCase, + .SwitchElse => SwitchElse, + .Else => Else, + .Payload => Payload, + .PointerPayload => PointerPayload, + .PointerIndexPayload => PointerIndexPayload, + .ContainerField => ContainerField, + .ErrorTag => ErrorTag, + .FieldInitializer => FieldInitializer, + }; + } }; + /// Prefer `castTag` to this. pub fn cast(base: *Node, comptime T: type) ?*T { - if (base.id == comptime typeToId(T)) { - return @fieldParentPtr(T, "base", base); + if (std.meta.fieldInfo(T, "base").default_value) |default_base| { + return base.castTag(default_base.tag); + } + inline for (@typeInfo(Tag).Enum.fields) |field| { + const tag = @intToEnum(Tag, field.value); + if (base.tag == tag) { + if (T == tag.Type()) { + return @fieldParentPtr(T, "base", base); + } + return null; + } + } + unreachable; + } + + pub fn castTag(base: *Node, comptime tag: Tag) ?*tag.Type() { + if (base.tag == tag) { + return @fieldParentPtr(tag.Type(), "base", base); } return null; } pub fn iterate(base: *Node, index: usize) ?*Node { - inline for (@typeInfo(Id).Enum.fields) |f| { - if (base.id == @field(Id, f.name)) { - const T = @field(Node, f.name); - return @fieldParentPtr(T, "base", base).iterate(index); + inline for (@typeInfo(Tag).Enum.fields) |field| { + const tag = @intToEnum(Tag, field.value); + if (base.tag == tag) { + return @fieldParentPtr(tag.Type(), "base", base).iterate(index); } } unreachable; } pub fn firstToken(base: *const Node) TokenIndex { - inline for (@typeInfo(Id).Enum.fields) |f| { - if (base.id == @field(Id, f.name)) { - const T = @field(Node, f.name); - return @fieldParentPtr(T, "base", base).firstToken(); + inline for (@typeInfo(Tag).Enum.fields) |field| { + const tag = @intToEnum(Tag, field.value); + if (base.tag == tag) { + return @fieldParentPtr(tag.Type(), "base", base).firstToken(); } } unreachable; } pub fn lastToken(base: *const Node) TokenIndex { - inline for (@typeInfo(Id).Enum.fields) |f| { - if (base.id == @field(Id, f.name)) { - const T = @field(Node, f.name); - return @fieldParentPtr(T, "base", base).lastToken(); - } - } - unreachable; - } - - pub fn typeToId(comptime T: type) Id { - inline for (@typeInfo(Id).Enum.fields) |f| { - if (T == @field(Node, f.name)) { - return @field(Id, f.name); + inline for (@typeInfo(Tag).Enum.fields) |field| { + const tag = @intToEnum(Tag, field.value); + if (base.tag == tag) { + return @fieldParentPtr(tag.Type(), "base", base).lastToken(); } } unreachable; @@ -535,7 +710,7 @@ pub const Node = struct { pub fn requireSemiColon(base: *const Node) bool { var n = base; while (true) { - switch (n.id) { + switch (n.tag) { .Root, .ContainerField, .Block, @@ -556,7 +731,7 @@ pub const Node = struct { continue; } - return while_node.body.id != .Block; + return while_node.body.tag != .Block; }, .For => { const for_node = @fieldParentPtr(For, "base", n); @@ -565,7 +740,7 @@ pub const Node = struct { continue; } - return for_node.body.id != .Block; + return for_node.body.tag != .Block; }, .If => { const if_node = @fieldParentPtr(If, "base", n); @@ -574,7 +749,7 @@ pub const Node = struct { continue; } - return if_node.body.id != .Block; + return if_node.body.tag != .Block; }, .Else => { const else_node = @fieldParentPtr(Else, "base", n); @@ -583,23 +758,23 @@ pub const Node = struct { }, .Defer => { const defer_node = @fieldParentPtr(Defer, "base", n); - return defer_node.expr.id != .Block; + return defer_node.expr.tag != .Block; }, .Comptime => { const comptime_node = @fieldParentPtr(Comptime, "base", n); - return comptime_node.expr.id != .Block; + return comptime_node.expr.tag != .Block; }, .Suspend => { const suspend_node = @fieldParentPtr(Suspend, "base", n); if (suspend_node.body) |body| { - return body.id != .Block; + return body.tag != .Block; } return true; }, .Nosuspend => { const nosuspend_node = @fieldParentPtr(Nosuspend, "base", n); - return nosuspend_node.expr.id != .Block; + return nosuspend_node.expr.tag != .Block; }, else => return true, } @@ -613,7 +788,7 @@ pub const Node = struct { std.debug.warn(" ", .{}); } } - std.debug.warn("{}\n", .{@tagName(self.id)}); + std.debug.warn("{}\n", .{@tagName(self.tag)}); var child_i: usize = 0; while (self.iterate(child_i)) |child| : (child_i += 1) { @@ -623,7 +798,7 @@ pub const Node = struct { /// The decls data follows this struct in memory as an array of Node pointers. pub const Root = struct { - base: Node = Node{ .id = .Root }, + base: Node = Node{ .tag = .Root }, eof_token: TokenIndex, decls_len: NodeIndex, @@ -678,7 +853,7 @@ pub const Node = struct { /// Trailed in memory by possibly many things, with each optional thing /// determined by a bit in `trailer_flags`. pub const VarDecl = struct { - base: Node = Node{ .id = .VarDecl }, + base: Node = Node{ .tag = .VarDecl }, trailer_flags: TrailerFlags, mut_token: TokenIndex, name_token: TokenIndex, @@ -779,7 +954,7 @@ pub const Node = struct { }; pub const Use = struct { - base: Node = Node{ .id = .Use }, + base: Node = Node{ .tag = .Use }, doc_comments: ?*DocComment, visib_token: ?TokenIndex, use_token: TokenIndex, @@ -806,7 +981,7 @@ pub const Node = struct { }; pub const ErrorSetDecl = struct { - base: Node = Node{ .id = .ErrorSetDecl }, + base: Node = Node{ .tag = .ErrorSetDecl }, error_token: TokenIndex, rbrace_token: TokenIndex, decls_len: NodeIndex, @@ -856,7 +1031,7 @@ pub const Node = struct { /// The fields and decls Node pointers directly follow this struct in memory. pub const ContainerDecl = struct { - base: Node = Node{ .id = .ContainerDecl }, + base: Node = Node{ .tag = .ContainerDecl }, kind_token: TokenIndex, layout_token: ?TokenIndex, lbrace_token: TokenIndex, @@ -925,7 +1100,7 @@ pub const Node = struct { }; pub const ContainerField = struct { - base: Node = Node{ .id = .ContainerField }, + base: Node = Node{ .tag = .ContainerField }, doc_comments: ?*DocComment, comptime_token: ?TokenIndex, name_token: TokenIndex, @@ -976,7 +1151,7 @@ pub const Node = struct { }; pub const ErrorTag = struct { - base: Node = Node{ .id = .ErrorTag }, + base: Node = Node{ .tag = .ErrorTag }, doc_comments: ?*DocComment, name_token: TokenIndex, @@ -1001,7 +1176,7 @@ pub const Node = struct { }; pub const Identifier = struct { - base: Node = Node{ .id = .Identifier }, + base: Node = Node{ .tag = .Identifier }, token: TokenIndex, pub fn iterate(self: *const Identifier, index: usize) ?*Node { @@ -1020,7 +1195,7 @@ pub const Node = struct { /// The params are directly after the FnProto in memory. /// Next, each optional thing determined by a bit in `trailer_flags`. pub const FnProto = struct { - base: Node = Node{ .id = .FnProto }, + base: Node = Node{ .tag = .FnProto }, trailer_flags: TrailerFlags, fn_token: TokenIndex, params_len: NodeIndex, @@ -1230,7 +1405,7 @@ pub const Node = struct { }; pub const AnyFrameType = struct { - base: Node = Node{ .id = .AnyFrameType }, + base: Node = Node{ .tag = .AnyFrameType }, anyframe_token: TokenIndex, result: ?Result, @@ -1262,7 +1437,7 @@ pub const Node = struct { /// The statements of the block follow Block directly in memory. pub const Block = struct { - base: Node = Node{ .id = .Block }, + base: Node = Node{ .tag = .Block }, statements_len: NodeIndex, lbrace: TokenIndex, rbrace: TokenIndex, @@ -1316,7 +1491,7 @@ pub const Node = struct { }; pub const Defer = struct { - base: Node = Node{ .id = .Defer }, + base: Node = Node{ .tag = .Defer }, defer_token: TokenIndex, payload: ?*Node, expr: *Node, @@ -1340,7 +1515,7 @@ pub const Node = struct { }; pub const Comptime = struct { - base: Node = Node{ .id = .Comptime }, + base: Node = Node{ .tag = .Comptime }, doc_comments: ?*DocComment, comptime_token: TokenIndex, expr: *Node, @@ -1364,7 +1539,7 @@ pub const Node = struct { }; pub const Nosuspend = struct { - base: Node = Node{ .id = .Nosuspend }, + base: Node = Node{ .tag = .Nosuspend }, nosuspend_token: TokenIndex, expr: *Node, @@ -1387,7 +1562,7 @@ pub const Node = struct { }; pub const Payload = struct { - base: Node = Node{ .id = .Payload }, + base: Node = Node{ .tag = .Payload }, lpipe: TokenIndex, error_symbol: *Node, rpipe: TokenIndex, @@ -1411,7 +1586,7 @@ pub const Node = struct { }; pub const PointerPayload = struct { - base: Node = Node{ .id = .PointerPayload }, + base: Node = Node{ .tag = .PointerPayload }, lpipe: TokenIndex, ptr_token: ?TokenIndex, value_symbol: *Node, @@ -1436,7 +1611,7 @@ pub const Node = struct { }; pub const PointerIndexPayload = struct { - base: Node = Node{ .id = .PointerIndexPayload }, + base: Node = Node{ .tag = .PointerIndexPayload }, lpipe: TokenIndex, ptr_token: ?TokenIndex, value_symbol: *Node, @@ -1467,7 +1642,7 @@ pub const Node = struct { }; pub const Else = struct { - base: Node = Node{ .id = .Else }, + base: Node = Node{ .tag = .Else }, else_token: TokenIndex, payload: ?*Node, body: *Node, @@ -1498,7 +1673,7 @@ pub const Node = struct { /// The cases node pointers are found in memory after Switch. /// They must be SwitchCase or SwitchElse nodes. pub const Switch = struct { - base: Node = Node{ .id = .Switch }, + base: Node = Node{ .tag = .Switch }, switch_token: TokenIndex, rbrace: TokenIndex, cases_len: NodeIndex, @@ -1552,7 +1727,7 @@ pub const Node = struct { /// Items sub-nodes appear in memory directly following SwitchCase. pub const SwitchCase = struct { - base: Node = Node{ .id = .SwitchCase }, + base: Node = Node{ .tag = .SwitchCase }, arrow_token: TokenIndex, payload: ?*Node, expr: *Node, @@ -1610,7 +1785,7 @@ pub const Node = struct { }; pub const SwitchElse = struct { - base: Node = Node{ .id = .SwitchElse }, + base: Node = Node{ .tag = .SwitchElse }, token: TokenIndex, pub fn iterate(self: *const SwitchElse, index: usize) ?*Node { @@ -1627,7 +1802,7 @@ pub const Node = struct { }; pub const While = struct { - base: Node = Node{ .id = .While }, + base: Node = Node{ .tag = .While }, label: ?TokenIndex, inline_token: ?TokenIndex, while_token: TokenIndex, @@ -1686,7 +1861,7 @@ pub const Node = struct { }; pub const For = struct { - base: Node = Node{ .id = .For }, + base: Node = Node{ .tag = .For }, label: ?TokenIndex, inline_token: ?TokenIndex, for_token: TokenIndex, @@ -1737,7 +1912,7 @@ pub const Node = struct { }; pub const If = struct { - base: Node = Node{ .id = .If }, + base: Node = Node{ .tag = .If }, if_token: TokenIndex, condition: *Node, payload: ?*Node, @@ -1779,116 +1954,22 @@ pub const Node = struct { } }; - pub const InfixOp = struct { - base: Node = Node{ .id = .InfixOp }, + pub const Catch = struct { + base: Node = Node{ .tag = .Catch }, op_token: TokenIndex, lhs: *Node, - op: Op, rhs: *Node, + payload: ?*Node, - pub const Op = union(enum) { - Add, - AddWrap, - ArrayCat, - ArrayMult, - Assign, - AssignBitAnd, - AssignBitOr, - AssignBitShiftLeft, - AssignBitShiftRight, - AssignBitXor, - AssignDiv, - AssignSub, - AssignSubWrap, - AssignMod, - AssignAdd, - AssignAddWrap, - AssignMul, - AssignMulWrap, - BangEqual, - BitAnd, - BitOr, - BitShiftLeft, - BitShiftRight, - BitXor, - BoolAnd, - BoolOr, - Catch: ?*Node, - Div, - EqualEqual, - ErrorUnion, - GreaterOrEqual, - GreaterThan, - LessOrEqual, - LessThan, - MergeErrorSets, - Mod, - Mul, - MulWrap, - Period, - Range, - Sub, - SubWrap, - UnwrapOptional, - }; - - pub fn iterate(self: *const InfixOp, index: usize) ?*Node { + pub fn iterate(self: *const Catch, index: usize) ?*Node { var i = index; if (i < 1) return self.lhs; i -= 1; - switch (self.op) { - .Catch => |maybe_payload| { - if (maybe_payload) |payload| { - if (i < 1) return payload; - i -= 1; - } - }, - - .Add, - .AddWrap, - .ArrayCat, - .ArrayMult, - .Assign, - .AssignBitAnd, - .AssignBitOr, - .AssignBitShiftLeft, - .AssignBitShiftRight, - .AssignBitXor, - .AssignDiv, - .AssignSub, - .AssignSubWrap, - .AssignMod, - .AssignAdd, - .AssignAddWrap, - .AssignMul, - .AssignMulWrap, - .BangEqual, - .BitAnd, - .BitOr, - .BitShiftLeft, - .BitShiftRight, - .BitXor, - .BoolAnd, - .BoolOr, - .Div, - .EqualEqual, - .ErrorUnion, - .GreaterOrEqual, - .GreaterThan, - .LessOrEqual, - .LessThan, - .MergeErrorSets, - .Mod, - .Mul, - .MulWrap, - .Period, - .Range, - .Sub, - .SubWrap, - .UnwrapOptional, - => {}, + if (self.payload) |payload| { + if (i < 1) return payload; + i -= 1; } if (i < 1) return self.rhs; @@ -1897,50 +1978,65 @@ pub const Node = struct { return null; } - pub fn firstToken(self: *const InfixOp) TokenIndex { + pub fn firstToken(self: *const Catch) TokenIndex { return self.lhs.firstToken(); } - pub fn lastToken(self: *const InfixOp) TokenIndex { + pub fn lastToken(self: *const Catch) TokenIndex { return self.rhs.lastToken(); } }; - pub const AddressOf = SimplePrefixOp(.AddressOf); - pub const Await = SimplePrefixOp(.Await); - pub const BitNot = SimplePrefixOp(.BitNot); - pub const BoolNot = SimplePrefixOp(.BoolNot); - pub const OptionalType = SimplePrefixOp(.OptionalType); - pub const Negation = SimplePrefixOp(.Negation); - pub const NegationWrap = SimplePrefixOp(.NegationWrap); - pub const Resume = SimplePrefixOp(.Resume); - pub const Try = SimplePrefixOp(.Try); + pub const SimpleInfixOp = struct { + base: Node, + op_token: TokenIndex, + lhs: *Node, + rhs: *Node, - pub fn SimplePrefixOp(comptime tag: Id) type { - return struct { - base: Node = Node{ .id = tag }, - op_token: TokenIndex, - rhs: *Node, + pub fn iterate(self: *const SimpleInfixOp, index: usize) ?*Node { + var i = index; - const Self = @This(); + if (i < 1) return self.lhs; + i -= 1; - pub fn iterate(self: *const Self, index: usize) ?*Node { - if (index == 0) return self.rhs; - return null; - } + if (i < 1) return self.rhs; + i -= 1; - pub fn firstToken(self: *const Self) TokenIndex { - return self.op_token; - } + return null; + } - pub fn lastToken(self: *const Self) TokenIndex { - return self.rhs.lastToken(); - } - }; - } + pub fn firstToken(self: *const SimpleInfixOp) TokenIndex { + return self.lhs.firstToken(); + } + + pub fn lastToken(self: *const SimpleInfixOp) TokenIndex { + return self.rhs.lastToken(); + } + }; + + pub const SimplePrefixOp = struct { + base: Node, + op_token: TokenIndex, + rhs: *Node, + + const Self = @This(); + + pub fn iterate(self: *const Self, index: usize) ?*Node { + if (index == 0) return self.rhs; + return null; + } + + pub fn firstToken(self: *const Self) TokenIndex { + return self.op_token; + } + + pub fn lastToken(self: *const Self) TokenIndex { + return self.rhs.lastToken(); + } + }; pub const ArrayType = struct { - base: Node = Node{ .id = .ArrayType }, + base: Node = Node{ .tag = .ArrayType }, op_token: TokenIndex, rhs: *Node, len_expr: *Node, @@ -1967,7 +2063,7 @@ pub const Node = struct { }; pub const ArrayTypeSentinel = struct { - base: Node = Node{ .id = .ArrayTypeSentinel }, + base: Node = Node{ .tag = .ArrayTypeSentinel }, op_token: TokenIndex, rhs: *Node, len_expr: *Node, @@ -1998,7 +2094,7 @@ pub const Node = struct { }; pub const PtrType = struct { - base: Node = Node{ .id = .PtrType }, + base: Node = Node{ .tag = .PtrType }, op_token: TokenIndex, rhs: *Node, /// TODO Add a u8 flags field to Node where it would otherwise be padding, and each bit represents @@ -2034,7 +2130,7 @@ pub const Node = struct { }; pub const SliceType = struct { - base: Node = Node{ .id = .SliceType }, + base: Node = Node{ .tag = .SliceType }, op_token: TokenIndex, rhs: *Node, /// TODO Add a u8 flags field to Node where it would otherwise be padding, and each bit represents @@ -2070,7 +2166,7 @@ pub const Node = struct { }; pub const FieldInitializer = struct { - base: Node = Node{ .id = .FieldInitializer }, + base: Node = Node{ .tag = .FieldInitializer }, period_token: TokenIndex, name_token: TokenIndex, expr: *Node, @@ -2095,7 +2191,7 @@ pub const Node = struct { /// Elements occur directly in memory after ArrayInitializer. pub const ArrayInitializer = struct { - base: Node = Node{ .id = .ArrayInitializer }, + base: Node = Node{ .tag = .ArrayInitializer }, rtoken: TokenIndex, list_len: NodeIndex, lhs: *Node, @@ -2148,7 +2244,7 @@ pub const Node = struct { /// Elements occur directly in memory after ArrayInitializerDot. pub const ArrayInitializerDot = struct { - base: Node = Node{ .id = .ArrayInitializerDot }, + base: Node = Node{ .tag = .ArrayInitializerDot }, dot: TokenIndex, rtoken: TokenIndex, list_len: NodeIndex, @@ -2198,7 +2294,7 @@ pub const Node = struct { /// Elements occur directly in memory after StructInitializer. pub const StructInitializer = struct { - base: Node = Node{ .id = .StructInitializer }, + base: Node = Node{ .tag = .StructInitializer }, rtoken: TokenIndex, list_len: NodeIndex, lhs: *Node, @@ -2251,7 +2347,7 @@ pub const Node = struct { /// Elements occur directly in memory after StructInitializerDot. pub const StructInitializerDot = struct { - base: Node = Node{ .id = .StructInitializerDot }, + base: Node = Node{ .tag = .StructInitializerDot }, dot: TokenIndex, rtoken: TokenIndex, list_len: NodeIndex, @@ -2301,7 +2397,7 @@ pub const Node = struct { /// Parameter nodes directly follow Call in memory. pub const Call = struct { - base: Node = Node{ .id = .Call }, + base: Node = Node{ .tag = .Call }, lhs: *Node, rtoken: TokenIndex, params_len: NodeIndex, @@ -2355,7 +2451,7 @@ pub const Node = struct { }; pub const SuffixOp = struct { - base: Node = Node{ .id = .SuffixOp }, + base: Node = Node{ .tag = .SuffixOp }, op: Op, lhs: *Node, rtoken: TokenIndex, @@ -2415,7 +2511,7 @@ pub const Node = struct { }; pub const GroupedExpression = struct { - base: Node = Node{ .id = .GroupedExpression }, + base: Node = Node{ .tag = .GroupedExpression }, lparen: TokenIndex, expr: *Node, rparen: TokenIndex, @@ -2441,7 +2537,7 @@ pub const Node = struct { /// TODO break this into separate Break, Continue, Return AST Nodes to save memory. /// Could be further broken into LabeledBreak, LabeledContinue, and ReturnVoid to save even more. pub const ControlFlowExpression = struct { - base: Node = Node{ .id = .ControlFlowExpression }, + base: Node = Node{ .tag = .ControlFlowExpression }, ltoken: TokenIndex, kind: Kind, rhs: ?*Node, @@ -2496,7 +2592,7 @@ pub const Node = struct { }; pub const Suspend = struct { - base: Node = Node{ .id = .Suspend }, + base: Node = Node{ .tag = .Suspend }, suspend_token: TokenIndex, body: ?*Node, @@ -2525,7 +2621,7 @@ pub const Node = struct { }; pub const IntegerLiteral = struct { - base: Node = Node{ .id = .IntegerLiteral }, + base: Node = Node{ .tag = .IntegerLiteral }, token: TokenIndex, pub fn iterate(self: *const IntegerLiteral, index: usize) ?*Node { @@ -2542,7 +2638,7 @@ pub const Node = struct { }; pub const EnumLiteral = struct { - base: Node = Node{ .id = .EnumLiteral }, + base: Node = Node{ .tag = .EnumLiteral }, dot: TokenIndex, name: TokenIndex, @@ -2560,7 +2656,7 @@ pub const Node = struct { }; pub const FloatLiteral = struct { - base: Node = Node{ .id = .FloatLiteral }, + base: Node = Node{ .tag = .FloatLiteral }, token: TokenIndex, pub fn iterate(self: *const FloatLiteral, index: usize) ?*Node { @@ -2578,7 +2674,7 @@ pub const Node = struct { /// Parameters are in memory following BuiltinCall. pub const BuiltinCall = struct { - base: Node = Node{ .id = .BuiltinCall }, + base: Node = Node{ .tag = .BuiltinCall }, params_len: NodeIndex, builtin_token: TokenIndex, rparen_token: TokenIndex, @@ -2627,7 +2723,7 @@ pub const Node = struct { }; pub const StringLiteral = struct { - base: Node = Node{ .id = .StringLiteral }, + base: Node = Node{ .tag = .StringLiteral }, token: TokenIndex, pub fn iterate(self: *const StringLiteral, index: usize) ?*Node { @@ -2645,7 +2741,7 @@ pub const Node = struct { /// The string literal tokens appear directly in memory after MultilineStringLiteral. pub const MultilineStringLiteral = struct { - base: Node = Node{ .id = .MultilineStringLiteral }, + base: Node = Node{ .tag = .MultilineStringLiteral }, lines_len: TokenIndex, /// After this the caller must initialize the lines list. @@ -2687,7 +2783,7 @@ pub const Node = struct { }; pub const CharLiteral = struct { - base: Node = Node{ .id = .CharLiteral }, + base: Node = Node{ .tag = .CharLiteral }, token: TokenIndex, pub fn iterate(self: *const CharLiteral, index: usize) ?*Node { @@ -2704,7 +2800,7 @@ pub const Node = struct { }; pub const BoolLiteral = struct { - base: Node = Node{ .id = .BoolLiteral }, + base: Node = Node{ .tag = .BoolLiteral }, token: TokenIndex, pub fn iterate(self: *const BoolLiteral, index: usize) ?*Node { @@ -2721,7 +2817,7 @@ pub const Node = struct { }; pub const NullLiteral = struct { - base: Node = Node{ .id = .NullLiteral }, + base: Node = Node{ .tag = .NullLiteral }, token: TokenIndex, pub fn iterate(self: *const NullLiteral, index: usize) ?*Node { @@ -2738,7 +2834,7 @@ pub const Node = struct { }; pub const UndefinedLiteral = struct { - base: Node = Node{ .id = .UndefinedLiteral }, + base: Node = Node{ .tag = .UndefinedLiteral }, token: TokenIndex, pub fn iterate(self: *const UndefinedLiteral, index: usize) ?*Node { @@ -2755,7 +2851,7 @@ pub const Node = struct { }; pub const Asm = struct { - base: Node = Node{ .id = .Asm }, + base: Node = Node{ .tag = .Asm }, asm_token: TokenIndex, rparen: TokenIndex, volatile_token: ?TokenIndex, @@ -2875,7 +2971,7 @@ pub const Node = struct { }; pub const Unreachable = struct { - base: Node = Node{ .id = .Unreachable }, + base: Node = Node{ .tag = .Unreachable }, token: TokenIndex, pub fn iterate(self: *const Unreachable, index: usize) ?*Node { @@ -2892,7 +2988,7 @@ pub const Node = struct { }; pub const ErrorType = struct { - base: Node = Node{ .id = .ErrorType }, + base: Node = Node{ .tag = .ErrorType }, token: TokenIndex, pub fn iterate(self: *const ErrorType, index: usize) ?*Node { @@ -2909,7 +3005,7 @@ pub const Node = struct { }; pub const AnyType = struct { - base: Node = Node{ .id = .AnyType }, + base: Node = Node{ .tag = .AnyType }, token: TokenIndex, pub fn iterate(self: *const AnyType, index: usize) ?*Node { @@ -2929,7 +3025,7 @@ pub const Node = struct { /// TODO actually maybe remove entirely in favor of iterating backward from Node.firstToken() /// and forwards to find same-line doc comments. pub const DocComment = struct { - base: Node = Node{ .id = .DocComment }, + base: Node = Node{ .tag = .DocComment }, /// Points to the first doc comment token. API users are expected to iterate over the /// tokens array, looking for more doc comments, ignoring line comments, and stopping /// at the first other token. @@ -2951,7 +3047,7 @@ pub const Node = struct { }; pub const TestDecl = struct { - base: Node = Node{ .id = .TestDecl }, + base: Node = Node{ .tag = .TestDecl }, doc_comments: ?*DocComment, test_token: TokenIndex, name: *Node, @@ -2996,7 +3092,7 @@ pub const PtrInfo = struct { test "iterate" { var root = Node.Root{ - .base = Node{ .id = Node.Id.Root }, + .base = Node{ .tag = Node.Tag.Root }, .decls_len = 0, .eof_token = 0, }; diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig index 9f2aea390a..b02cdcc1fd 100644 --- a/lib/std/zig/parse.zig +++ b/lib/std/zig/parse.zig @@ -1015,7 +1015,7 @@ const Parser = struct { /// BoolOrExpr <- BoolAndExpr (KEYWORD_or BoolAndExpr)* fn parseBoolOrExpr(p: *Parser) !?*Node { return p.parseBinOpExpr( - SimpleBinOpParseFn(.Keyword_or, Node.InfixOp.Op.BoolOr), + SimpleBinOpParseFn(.Keyword_or, .BoolOr), parseBoolAndExpr, .Infinitely, ); @@ -1128,8 +1128,9 @@ const Parser = struct { const expr_node = try p.expectNode(parseExpr, .{ .ExpectedExpr = .{ .token = p.tok_i }, }); - const node = try p.arena.allocator.create(Node.Resume); + const node = try p.arena.allocator.create(Node.SimplePrefixOp); node.* = .{ + .base = .{ .tag = .Resume }, .op_token = token, .rhs = expr_node, }; @@ -1404,8 +1405,8 @@ const Parser = struct { fn parseErrorUnionExpr(p: *Parser) !?*Node { const suffix_expr = (try p.parseSuffixExpr()) orelse return null; - if (try SimpleBinOpParseFn(.Bang, Node.InfixOp.Op.ErrorUnion)(p)) |node| { - const error_union = node.cast(Node.InfixOp).?; + if (try SimpleBinOpParseFn(.Bang, .ErrorUnion)(p)) |node| { + const error_union = node.castTag(.ErrorUnion).?; const type_expr = try p.expectNode(parseTypeExpr, .{ .ExpectedTypeExpr = .{ .token = p.tok_i }, }); @@ -1438,10 +1439,56 @@ const Parser = struct { .ExpectedPrimaryTypeExpr = .{ .token = p.tok_i }, }); + // TODO pass `res` into `parseSuffixOp` rather than patching it up afterwards. while (try p.parseSuffixOp()) |node| { - switch (node.id) { + switch (node.tag) { .SuffixOp => node.cast(Node.SuffixOp).?.lhs = res, - .InfixOp => node.cast(Node.InfixOp).?.lhs = res, + .Catch => node.castTag(.Catch).?.lhs = res, + + .Add, + .AddWrap, + .ArrayCat, + .ArrayMult, + .Assign, + .AssignBitAnd, + .AssignBitOr, + .AssignBitShiftLeft, + .AssignBitShiftRight, + .AssignBitXor, + .AssignDiv, + .AssignSub, + .AssignSubWrap, + .AssignMod, + .AssignAdd, + .AssignAddWrap, + .AssignMul, + .AssignMulWrap, + .BangEqual, + .BitAnd, + .BitOr, + .BitShiftLeft, + .BitShiftRight, + .BitXor, + .BoolAnd, + .BoolOr, + .Div, + .EqualEqual, + .ErrorUnion, + .GreaterOrEqual, + .GreaterThan, + .LessOrEqual, + .LessThan, + .MergeErrorSets, + .Mod, + .Mul, + .MulWrap, + .Period, + .Range, + .Sub, + .SubWrap, + .UnwrapOptional, + => node.cast(Node.SimpleInfixOp).?.lhs = res, + else => unreachable, } res = node; @@ -1469,10 +1516,55 @@ const Parser = struct { var res = expr; while (true) { + // TODO pass `res` into `parseSuffixOp` rather than patching it up afterwards. if (try p.parseSuffixOp()) |node| { - switch (node.id) { + switch (node.tag) { .SuffixOp => node.cast(Node.SuffixOp).?.lhs = res, - .InfixOp => node.cast(Node.InfixOp).?.lhs = res, + .Catch => node.castTag(.Catch).?.lhs = res, + + .Add, + .AddWrap, + .ArrayCat, + .ArrayMult, + .Assign, + .AssignBitAnd, + .AssignBitOr, + .AssignBitShiftLeft, + .AssignBitShiftRight, + .AssignBitXor, + .AssignDiv, + .AssignSub, + .AssignSubWrap, + .AssignMod, + .AssignAdd, + .AssignAddWrap, + .AssignMul, + .AssignMulWrap, + .BangEqual, + .BitAnd, + .BitOr, + .BitShiftLeft, + .BitShiftRight, + .BitXor, + .BoolAnd, + .BoolOr, + .Div, + .EqualEqual, + .ErrorUnion, + .GreaterOrEqual, + .GreaterThan, + .LessOrEqual, + .LessThan, + .MergeErrorSets, + .Mod, + .Mul, + .MulWrap, + .Period, + .Range, + .Sub, + .SubWrap, + .UnwrapOptional, + => node.cast(Node.SimpleInfixOp).?.lhs = res, else => unreachable, } res = node; @@ -1559,11 +1651,11 @@ const Parser = struct { const global_error_set = try p.createLiteral(Node.ErrorType, token); if (period == null or identifier == null) return global_error_set; - const node = try p.arena.allocator.create(Node.InfixOp); + const node = try p.arena.allocator.create(Node.SimpleInfixOp); node.* = .{ + .base = Node{ .tag = .Period }, .op_token = period.?, .lhs = global_error_set, - .op = .Period, .rhs = identifier.?, }; return &node.base; @@ -1660,7 +1752,7 @@ const Parser = struct { } if (try p.parseLoopTypeExpr()) |node| { - switch (node.id) { + switch (node.tag) { .For => node.cast(Node.For).?.label = label, .While => node.cast(Node.While).?.label = label, else => unreachable, @@ -2236,11 +2328,11 @@ const Parser = struct { .ExpectedExpr = .{ .token = p.tok_i }, }); - const node = try p.arena.allocator.create(Node.InfixOp); + const node = try p.arena.allocator.create(Node.SimpleInfixOp); node.* = .{ + .base = Node{ .tag = .Range }, .op_token = token, .lhs = expr, - .op = .Range, .rhs = range_end, }; return &node.base; @@ -2265,7 +2357,7 @@ const Parser = struct { /// / EQUAL fn parseAssignOp(p: *Parser) !?*Node { const token = p.nextToken(); - const op: Node.InfixOp.Op = switch (p.token_ids[token]) { + const op: Node.Tag = switch (p.token_ids[token]) { .AsteriskEqual => .AssignMul, .SlashEqual => .AssignDiv, .PercentEqual => .AssignMod, @@ -2286,11 +2378,11 @@ const Parser = struct { }, }; - const node = try p.arena.allocator.create(Node.InfixOp); + const node = try p.arena.allocator.create(Node.SimpleInfixOp); node.* = .{ + .base = .{ .tag = op }, .op_token = token, .lhs = undefined, // set by caller - .op = op, .rhs = undefined, // set by caller }; return &node.base; @@ -2305,7 +2397,7 @@ const Parser = struct { /// / RARROWEQUAL fn parseCompareOp(p: *Parser) !?*Node { const token = p.nextToken(); - const op: Node.InfixOp.Op = switch (p.token_ids[token]) { + const op: Node.Tag = switch (p.token_ids[token]) { .EqualEqual => .EqualEqual, .BangEqual => .BangEqual, .AngleBracketLeft => .LessThan, @@ -2329,12 +2421,22 @@ const Parser = struct { /// / KEYWORD_catch Payload? fn parseBitwiseOp(p: *Parser) !?*Node { const token = p.nextToken(); - const op: Node.InfixOp.Op = switch (p.token_ids[token]) { + const op: Node.Tag = switch (p.token_ids[token]) { .Ampersand => .BitAnd, .Caret => .BitXor, .Pipe => .BitOr, .Keyword_orelse => .UnwrapOptional, - .Keyword_catch => .{ .Catch = try p.parsePayload() }, + .Keyword_catch => { + const payload = try p.parsePayload(); + const node = try p.arena.allocator.create(Node.Catch); + node.* = .{ + .op_token = token, + .lhs = undefined, // set by caller + .rhs = undefined, // set by caller + .payload = payload, + }; + return &node.base; + }, else => { p.putBackToken(token); return null; @@ -2349,7 +2451,7 @@ const Parser = struct { /// / RARROW2 fn parseBitShiftOp(p: *Parser) !?*Node { const token = p.nextToken(); - const op: Node.InfixOp.Op = switch (p.token_ids[token]) { + const op: Node.Tag = switch (p.token_ids[token]) { .AngleBracketAngleBracketLeft => .BitShiftLeft, .AngleBracketAngleBracketRight => .BitShiftRight, else => { @@ -2369,7 +2471,7 @@ const Parser = struct { /// / MINUSPERCENT fn parseAdditionOp(p: *Parser) !?*Node { const token = p.nextToken(); - const op: Node.InfixOp.Op = switch (p.token_ids[token]) { + const op: Node.Tag = switch (p.token_ids[token]) { .Plus => .Add, .Minus => .Sub, .PlusPlus => .ArrayCat, @@ -2393,7 +2495,7 @@ const Parser = struct { /// / ASTERISKPERCENT fn parseMultiplyOp(p: *Parser) !?*Node { const token = p.nextToken(); - const op: Node.InfixOp.Op = switch (p.token_ids[token]) { + const op: Node.Tag = switch (p.token_ids[token]) { .PipePipe => .MergeErrorSets, .Asterisk => .Mul, .Slash => .Div, @@ -2434,9 +2536,10 @@ const Parser = struct { } } - fn allocSimplePrefixOp(p: *Parser, comptime tag: Node.Id, token: TokenIndex) !?*Node { - const node = try p.arena.allocator.create(Node.SimplePrefixOp(tag)); + fn allocSimplePrefixOp(p: *Parser, comptime tag: Node.Tag, token: TokenIndex) !?*Node { + const node = try p.arena.allocator.create(Node.SimplePrefixOp); node.* = .{ + .base = .{ .tag = tag }, .op_token = token, .rhs = undefined, // set by caller }; @@ -2457,8 +2560,9 @@ const Parser = struct { /// / PtrTypeStart (KEYWORD_align LPAREN Expr (COLON INTEGER COLON INTEGER)? RPAREN / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)* fn parsePrefixTypeOp(p: *Parser) !?*Node { if (p.eatToken(.QuestionMark)) |token| { - const node = try p.arena.allocator.create(Node.OptionalType); + const node = try p.arena.allocator.create(Node.SimplePrefixOp); node.* = .{ + .base = .{ .tag = .OptionalType }, .op_token = token, .rhs = undefined, // set by caller }; @@ -2670,14 +2774,14 @@ const Parser = struct { if (p.eatToken(.Period)) |period| { if (try p.parseIdentifier()) |identifier| { - // TODO: It's a bit weird to return an InfixOp from the SuffixOp parser. + // TODO: It's a bit weird to return a SimpleInfixOp from the SuffixOp parser. // Should there be an Node.SuffixOp.FieldAccess variant? Or should // this grammar rule be altered? - const node = try p.arena.allocator.create(Node.InfixOp); + const node = try p.arena.allocator.create(Node.SimpleInfixOp); node.* = .{ + .base = Node{ .tag = .Period }, .op_token = period, .lhs = undefined, // set by caller - .op = .Period, .rhs = identifier, }; return &node.base; @@ -2984,7 +3088,7 @@ const Parser = struct { }.parse; } - fn SimpleBinOpParseFn(comptime token: Token.Id, comptime op: Node.InfixOp.Op) NodeParseFn { + fn SimpleBinOpParseFn(comptime token: Token.Id, comptime op: Node.Tag) NodeParseFn { return struct { pub fn parse(p: *Parser) Error!?*Node { const op_token = if (token == .Keyword_and) switch (p.token_ids[p.tok_i]) { @@ -2998,11 +3102,11 @@ const Parser = struct { else => return null, } else p.eatToken(token) orelse return null; - const node = try p.arena.allocator.create(Node.InfixOp); + const node = try p.arena.allocator.create(Node.SimpleInfixOp); node.* = .{ + .base = .{ .tag = op }, .op_token = op_token, .lhs = undefined, // set by caller - .op = op, .rhs = undefined, // set by caller }; return &node.base; @@ -3072,7 +3176,6 @@ const Parser = struct { fn createLiteral(p: *Parser, comptime T: type, token: TokenIndex) !*Node { const result = try p.arena.allocator.create(T); result.* = T{ - .base = Node{ .id = Node.typeToId(T) }, .token = token, }; return &result.base; @@ -3148,8 +3251,9 @@ const Parser = struct { fn parseTry(p: *Parser) !?*Node { const token = p.eatToken(.Keyword_try) orelse return null; - const node = try p.arena.allocator.create(Node.Try); + const node = try p.arena.allocator.create(Node.SimplePrefixOp); node.* = .{ + .base = .{ .tag = .Try }, .op_token = token, .rhs = undefined, // set by caller }; @@ -3213,58 +3317,19 @@ const Parser = struct { if (try opParseFn(p)) |first_op| { var rightmost_op = first_op; while (true) { - switch (rightmost_op.id) { - .AddressOf => { - if (try opParseFn(p)) |rhs| { - rightmost_op.cast(Node.AddressOf).?.rhs = rhs; - rightmost_op = rhs; - } else break; - }, - .Await => { - if (try opParseFn(p)) |rhs| { - rightmost_op.cast(Node.Await).?.rhs = rhs; - rightmost_op = rhs; - } else break; - }, - .BitNot => { - if (try opParseFn(p)) |rhs| { - rightmost_op.cast(Node.BitNot).?.rhs = rhs; - rightmost_op = rhs; - } else break; - }, - .BoolNot => { - if (try opParseFn(p)) |rhs| { - rightmost_op.cast(Node.BoolNot).?.rhs = rhs; - rightmost_op = rhs; - } else break; - }, - .OptionalType => { - if (try opParseFn(p)) |rhs| { - rightmost_op.cast(Node.OptionalType).?.rhs = rhs; - rightmost_op = rhs; - } else break; - }, - .Negation => { + switch (rightmost_op.tag) { + .AddressOf, + .Await, + .BitNot, + .BoolNot, + .OptionalType, + .Negation, + .NegationWrap, + .Resume, + .Try, + => { if (try opParseFn(p)) |rhs| { - rightmost_op.cast(Node.Negation).?.rhs = rhs; - rightmost_op = rhs; - } else break; - }, - .NegationWrap => { - if (try opParseFn(p)) |rhs| { - rightmost_op.cast(Node.NegationWrap).?.rhs = rhs; - rightmost_op = rhs; - } else break; - }, - .Resume => { - if (try opParseFn(p)) |rhs| { - rightmost_op.cast(Node.Resume).?.rhs = rhs; - rightmost_op = rhs; - } else break; - }, - .Try => { - if (try opParseFn(p)) |rhs| { - rightmost_op.cast(Node.Try).?.rhs = rhs; + rightmost_op.cast(Node.SimplePrefixOp).?.rhs = rhs; rightmost_op = rhs; } else break; }, @@ -3310,57 +3375,18 @@ const Parser = struct { } // If any prefix op existed, a child node on the RHS is required - switch (rightmost_op.id) { - .AddressOf => { - const prefix_op = rightmost_op.cast(Node.AddressOf).?; - prefix_op.rhs = try p.expectNode(childParseFn, .{ - .InvalidToken = .{ .token = p.tok_i }, - }); - }, - .Await => { - const prefix_op = rightmost_op.cast(Node.Await).?; - prefix_op.rhs = try p.expectNode(childParseFn, .{ - .InvalidToken = .{ .token = p.tok_i }, - }); - }, - .BitNot => { - const prefix_op = rightmost_op.cast(Node.BitNot).?; - prefix_op.rhs = try p.expectNode(childParseFn, .{ - .InvalidToken = .{ .token = p.tok_i }, - }); - }, - .BoolNot => { - const prefix_op = rightmost_op.cast(Node.BoolNot).?; - prefix_op.rhs = try p.expectNode(childParseFn, .{ - .InvalidToken = .{ .token = p.tok_i }, - }); - }, - .OptionalType => { - const prefix_op = rightmost_op.cast(Node.OptionalType).?; - prefix_op.rhs = try p.expectNode(childParseFn, .{ - .InvalidToken = .{ .token = p.tok_i }, - }); - }, - .Negation => { - const prefix_op = rightmost_op.cast(Node.Negation).?; - prefix_op.rhs = try p.expectNode(childParseFn, .{ - .InvalidToken = .{ .token = p.tok_i }, - }); - }, - .NegationWrap => { - const prefix_op = rightmost_op.cast(Node.NegationWrap).?; - prefix_op.rhs = try p.expectNode(childParseFn, .{ - .InvalidToken = .{ .token = p.tok_i }, - }); - }, - .Resume => { - const prefix_op = rightmost_op.cast(Node.Resume).?; - prefix_op.rhs = try p.expectNode(childParseFn, .{ - .InvalidToken = .{ .token = p.tok_i }, - }); - }, - .Try => { - const prefix_op = rightmost_op.cast(Node.Try).?; + switch (rightmost_op.tag) { + .AddressOf, + .Await, + .BitNot, + .BoolNot, + .OptionalType, + .Negation, + .NegationWrap, + .Resume, + .Try, + => { + const prefix_op = rightmost_op.cast(Node.SimplePrefixOp).?; prefix_op.rhs = try p.expectNode(childParseFn, .{ .InvalidToken = .{ .token = p.tok_i }, }); @@ -3425,9 +3451,13 @@ const Parser = struct { const left = res; res = node; - const op = node.cast(Node.InfixOp).?; - op.*.lhs = left; - op.*.rhs = right; + if (node.castTag(.Catch)) |op| { + op.lhs = left; + op.rhs = right; + } else if (node.cast(Node.SimpleInfixOp)) |op| { + op.lhs = left; + op.rhs = right; + } switch (chain) { .Once => break, @@ -3438,12 +3468,12 @@ const Parser = struct { return res; } - fn createInfixOp(p: *Parser, index: TokenIndex, op: Node.InfixOp.Op) !*Node { - const node = try p.arena.allocator.create(Node.InfixOp); + fn createInfixOp(p: *Parser, op_token: TokenIndex, tag: Node.Tag) !*Node { + const node = try p.arena.allocator.create(Node.SimpleInfixOp); node.* = .{ - .op_token = index, + .base = Node{ .tag = tag }, + .op_token = op_token, .lhs = undefined, // set by caller - .op = op, .rhs = undefined, // set by caller }; return &node.base; diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig index 4f9eb0e4cd..7f8a18299b 100644 --- a/lib/std/zig/render.zig +++ b/lib/std/zig/render.zig @@ -223,7 +223,7 @@ fn renderTopLevelDecl(allocator: *mem.Allocator, stream: anytype, tree: *ast.Tre } fn renderContainerDecl(allocator: *mem.Allocator, stream: anytype, tree: *ast.Tree, indent: usize, start_col: *usize, decl: *ast.Node, space: Space) (@TypeOf(stream).Error || Error)!void { - switch (decl.id) { + switch (decl.tag) { .FnProto => { const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl); @@ -365,7 +365,7 @@ fn renderExpression( base: *ast.Node, space: Space, ) (@TypeOf(stream).Error || Error)!void { - switch (base.id) { + switch (base.tag) { .Identifier => { const identifier = @fieldParentPtr(ast.Node.Identifier, "base", base); return renderToken(tree, stream, identifier.token, indent, start_col, space); @@ -436,13 +436,10 @@ fn renderExpression( } }, - .InfixOp => { - const infix_op_node = @fieldParentPtr(ast.Node.InfixOp, "base", base); + .Catch => { + const infix_op_node = @fieldParentPtr(ast.Node.Catch, "base", base); - const op_space = switch (infix_op_node.op) { - ast.Node.InfixOp.Op.Period, ast.Node.InfixOp.Op.ErrorUnion, ast.Node.InfixOp.Op.Range => Space.None, - else => Space.Space, - }; + const op_space = Space.Space; try renderExpression(allocator, stream, tree, indent, start_col, infix_op_node.lhs, op_space); const after_op_space = blk: { @@ -458,60 +455,99 @@ fn renderExpression( start_col.* = indent + indent_delta; } - switch (infix_op_node.op) { - ast.Node.InfixOp.Op.Catch => |maybe_payload| if (maybe_payload) |payload| { - try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Space); - }, - else => {}, + if (infix_op_node.payload) |payload| { + try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Space); } return renderExpression(allocator, stream, tree, indent, start_col, infix_op_node.rhs, space); }, - .BitNot => { - const bit_not = @fieldParentPtr(ast.Node.BitNot, "base", base); - try renderToken(tree, stream, bit_not.op_token, indent, start_col, Space.None); - return renderExpression(allocator, stream, tree, indent, start_col, bit_not.rhs, space); - }, - .BoolNot => { - const bool_not = @fieldParentPtr(ast.Node.BoolNot, "base", base); - try renderToken(tree, stream, bool_not.op_token, indent, start_col, Space.None); - return renderExpression(allocator, stream, tree, indent, start_col, bool_not.rhs, space); - }, - .Negation => { - const negation = @fieldParentPtr(ast.Node.Negation, "base", base); - try renderToken(tree, stream, negation.op_token, indent, start_col, Space.None); - return renderExpression(allocator, stream, tree, indent, start_col, negation.rhs, space); - }, - .NegationWrap => { - const negation_wrap = @fieldParentPtr(ast.Node.NegationWrap, "base", base); - try renderToken(tree, stream, negation_wrap.op_token, indent, start_col, Space.None); - return renderExpression(allocator, stream, tree, indent, start_col, negation_wrap.rhs, space); - }, - .OptionalType => { - const opt_type = @fieldParentPtr(ast.Node.OptionalType, "base", base); - try renderToken(tree, stream, opt_type.op_token, indent, start_col, Space.None); - return renderExpression(allocator, stream, tree, indent, start_col, opt_type.rhs, space); - }, - .AddressOf => { - const addr_of = @fieldParentPtr(ast.Node.AddressOf, "base", base); - try renderToken(tree, stream, addr_of.op_token, indent, start_col, Space.None); - return renderExpression(allocator, stream, tree, indent, start_col, addr_of.rhs, space); - }, - .Try => { - const try_node = @fieldParentPtr(ast.Node.Try, "base", base); - try renderToken(tree, stream, try_node.op_token, indent, start_col, Space.Space); - return renderExpression(allocator, stream, tree, indent, start_col, try_node.rhs, space); + .Add, + .AddWrap, + .ArrayCat, + .ArrayMult, + .Assign, + .AssignBitAnd, + .AssignBitOr, + .AssignBitShiftLeft, + .AssignBitShiftRight, + .AssignBitXor, + .AssignDiv, + .AssignSub, + .AssignSubWrap, + .AssignMod, + .AssignAdd, + .AssignAddWrap, + .AssignMul, + .AssignMulWrap, + .BangEqual, + .BitAnd, + .BitOr, + .BitShiftLeft, + .BitShiftRight, + .BitXor, + .BoolAnd, + .BoolOr, + .Div, + .EqualEqual, + .ErrorUnion, + .GreaterOrEqual, + .GreaterThan, + .LessOrEqual, + .LessThan, + .MergeErrorSets, + .Mod, + .Mul, + .MulWrap, + .Period, + .Range, + .Sub, + .SubWrap, + .UnwrapOptional, + => { + const infix_op_node = @fieldParentPtr(ast.Node.SimpleInfixOp, "base", base); + + const op_space = switch (base.tag) { + .Period, .ErrorUnion, .Range => Space.None, + else => Space.Space, + }; + try renderExpression(allocator, stream, tree, indent, start_col, infix_op_node.lhs, op_space); + + const after_op_space = blk: { + const loc = tree.tokenLocation(tree.token_locs[infix_op_node.op_token].end, tree.nextToken(infix_op_node.op_token)); + break :blk if (loc.line == 0) op_space else Space.Newline; + }; + + try renderToken(tree, stream, infix_op_node.op_token, indent, start_col, after_op_space); + if (after_op_space == Space.Newline and + tree.token_ids[tree.nextToken(infix_op_node.op_token)] != .MultilineStringLiteralLine) + { + try stream.writeByteNTimes(' ', indent + indent_delta); + start_col.* = indent + indent_delta; + } + + return renderExpression(allocator, stream, tree, indent, start_col, infix_op_node.rhs, space); }, - .Resume => { - const resume_node = @fieldParentPtr(ast.Node.Resume, "base", base); - try renderToken(tree, stream, resume_node.op_token, indent, start_col, Space.Space); - return renderExpression(allocator, stream, tree, indent, start_col, resume_node.rhs, space); + + .BitNot, + .BoolNot, + .Negation, + .NegationWrap, + .OptionalType, + .AddressOf, + => { + const casted_node = @fieldParentPtr(ast.Node.SimplePrefixOp, "base", base); + try renderToken(tree, stream, casted_node.op_token, indent, start_col, Space.None); + return renderExpression(allocator, stream, tree, indent, start_col, casted_node.rhs, space); }, - .Await => { - const await_node = @fieldParentPtr(ast.Node.Await, "base", base); - try renderToken(tree, stream, await_node.op_token, indent, start_col, Space.Space); - return renderExpression(allocator, stream, tree, indent, start_col, await_node.rhs, space); + + .Try, + .Resume, + .Await, + => { + const casted_node = @fieldParentPtr(ast.Node.SimplePrefixOp, "base", base); + try renderToken(tree, stream, casted_node.op_token, indent, start_col, Space.Space); + return renderExpression(allocator, stream, tree, indent, start_col, casted_node.rhs, space); }, .ArrayType => { @@ -659,7 +695,7 @@ fn renderExpression( .ArrayInitializer, .ArrayInitializerDot => { var rtoken: ast.TokenIndex = undefined; var exprs: []*ast.Node = undefined; - const lhs: union(enum) { dot: ast.TokenIndex, node: *ast.Node } = switch (base.id) { + const lhs: union(enum) { dot: ast.TokenIndex, node: *ast.Node } = switch (base.tag) { .ArrayInitializerDot => blk: { const casted = @fieldParentPtr(ast.Node.ArrayInitializerDot, "base", base); rtoken = casted.rtoken; @@ -793,14 +829,14 @@ fn renderExpression( } try renderExtraNewline(tree, stream, start_col, next_expr); - if (next_expr.id != .MultilineStringLiteral) { + if (next_expr.tag != .MultilineStringLiteral) { try stream.writeByteNTimes(' ', new_indent); } } else { try renderExpression(allocator, stream, tree, new_indent, start_col, expr, Space.Comma); // , } } - if (exprs[exprs.len - 1].id != .MultilineStringLiteral) { + if (exprs[exprs.len - 1].tag != .MultilineStringLiteral) { try stream.writeByteNTimes(' ', indent); } return renderToken(tree, stream, rtoken, indent, start_col, space); @@ -823,7 +859,7 @@ fn renderExpression( .StructInitializer, .StructInitializerDot => { var rtoken: ast.TokenIndex = undefined; var field_inits: []*ast.Node = undefined; - const lhs: union(enum) { dot: ast.TokenIndex, node: *ast.Node } = switch (base.id) { + const lhs: union(enum) { dot: ast.TokenIndex, node: *ast.Node } = switch (base.tag) { .StructInitializerDot => blk: { const casted = @fieldParentPtr(ast.Node.StructInitializerDot, "base", base); rtoken = casted.rtoken; @@ -877,7 +913,7 @@ fn renderExpression( if (field_inits.len == 1) blk: { const field_init = field_inits[0].cast(ast.Node.FieldInitializer).?; - switch (field_init.expr.id) { + switch (field_init.expr.tag) { .StructInitializer, .StructInitializerDot, => break :blk, @@ -974,7 +1010,7 @@ fn renderExpression( const params = call.params(); for (params) |param_node, i| { - const param_node_new_indent = if (param_node.id == .MultilineStringLiteral) blk: { + const param_node_new_indent = if (param_node.tag == .MultilineStringLiteral) blk: { break :blk indent; } else blk: { try stream.writeByteNTimes(' ', new_indent); @@ -1284,7 +1320,7 @@ fn renderExpression( // declarations inside are fields const src_has_only_fields = blk: { for (fields_and_decls) |decl| { - if (decl.id != .ContainerField) break :blk false; + if (decl.tag != .ContainerField) break :blk false; } break :blk true; }; @@ -1831,7 +1867,7 @@ fn renderExpression( const rparen = tree.nextToken(for_node.array_expr.lastToken()); - const body_is_block = for_node.body.id == .Block; + const body_is_block = for_node.body.tag == .Block; const src_one_line_to_body = !body_is_block and tree.tokensOnSameLine(rparen, for_node.body.firstToken()); const body_on_same_line = body_is_block or src_one_line_to_body; @@ -1874,7 +1910,7 @@ fn renderExpression( try renderExpression(allocator, stream, tree, indent, start_col, if_node.condition, Space.None); // condition - const body_is_if_block = if_node.body.id == .If; + const body_is_if_block = if_node.body.tag == .If; const body_is_block = nodeIsBlock(if_node.body); if (body_is_if_block) { @@ -1978,7 +2014,7 @@ fn renderExpression( const indent_once = indent + indent_delta; - if (asm_node.template.id == .MultilineStringLiteral) { + if (asm_node.template.tag == .MultilineStringLiteral) { // After rendering a multiline string literal the cursor is // already offset by indent try stream.writeByteNTimes(' ', indent_delta); @@ -2245,7 +2281,7 @@ fn renderVarDecl( } if (var_decl.getTrailer("init_node")) |init_node| { - const s = if (init_node.id == .MultilineStringLiteral) Space.None else Space.Space; + const s = if (init_node.tag == .MultilineStringLiteral) Space.None else Space.Space; try renderToken(tree, stream, var_decl.getTrailer("eq_token").?, indent, start_col, s); // = try renderExpression(allocator, stream, tree, indent, start_col, init_node, Space.None); } @@ -2287,7 +2323,7 @@ fn renderStatement( start_col: *usize, base: *ast.Node, ) (@TypeOf(stream).Error || Error)!void { - switch (base.id) { + switch (base.tag) { .VarDecl => { const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", base); try renderVarDecl(allocator, stream, tree, indent, start_col, var_decl); @@ -2566,7 +2602,7 @@ fn renderDocCommentsToken( } fn nodeIsBlock(base: *const ast.Node) bool { - return switch (base.id) { + return switch (base.tag) { .Block, .If, .For, @@ -2578,10 +2614,52 @@ fn nodeIsBlock(base: *const ast.Node) bool { } fn nodeCausesSliceOpSpace(base: *ast.Node) bool { - const infix_op = base.cast(ast.Node.InfixOp) orelse return false; - return switch (infix_op.op) { - ast.Node.InfixOp.Op.Period => false, - else => true, + return switch (base.tag) { + .Catch, + .Add, + .AddWrap, + .ArrayCat, + .ArrayMult, + .Assign, + .AssignBitAnd, + .AssignBitOr, + .AssignBitShiftLeft, + .AssignBitShiftRight, + .AssignBitXor, + .AssignDiv, + .AssignSub, + .AssignSubWrap, + .AssignMod, + .AssignAdd, + .AssignAddWrap, + .AssignMul, + .AssignMulWrap, + .BangEqual, + .BitAnd, + .BitOr, + .BitShiftLeft, + .BitShiftRight, + .BitXor, + .BoolAnd, + .BoolOr, + .Div, + .EqualEqual, + .ErrorUnion, + .GreaterOrEqual, + .GreaterThan, + .LessOrEqual, + .LessThan, + .MergeErrorSets, + .Mod, + .Mul, + .MulWrap, + .Range, + .Sub, + .SubWrap, + .UnwrapOptional, + => true, + + else => false, }; } |
