authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-07-15 18:15:59-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-07-15 18:15:59-07:00
logf11909227312882f29dbfc484dc79ab622792787
tree3f327f4d16c32034cb1eea79dfaeadfef6303d9b
parente70d6d19f5a937504ce0e2f79d03a6275b6ff357

stage2: breaking AST memory layout modifications

ast.Node.Id => ast.Node.Tag, matching recent style conventions. Now multiple different AST node tags can map to the same AST node data structures. In this commit, simple prefix operators now all map top SimplePrefixOp. `ast.Node.castTag` is now preferred over `ast.Node.cast`. Upcoming: InfixOp flattened out.

6 files changed, 450 insertions(+), 316 deletions(-)

lib/std/zig/ast.zig+191-122
......@@ -323,8 +323,8 @@ pub const Error = union(enum) {
323323 node: *Node,
324324
325325 pub fn render(self: *const ExpectedCall, tokens: []const Token.Id, stream: anytype) !void {
326 return stream.print("expected " ++ @tagName(Node.Id.Call) ++ ", found {}", .{
327 @tagName(self.node.id),
326 return stream.print("expected " ++ @tagName(Node.Tag.Call) ++ ", found {}", .{
327 @tagName(self.node.tag),
328328 });
329329 }
330330 };
......@@ -333,8 +333,8 @@ pub const Error = union(enum) {
333333 node: *Node,
334334
335335 pub fn render(self: *const ExpectedCallOrFnProto, tokens: []const Token.Id, stream: anytype) !void {
336 return stream.print("expected " ++ @tagName(Node.Id.Call) ++ " or " ++
337 @tagName(Node.Id.FnProto) ++ ", found {}", .{@tagName(self.node.id)});
336 return stream.print("expected " ++ @tagName(Node.Tag.Call) ++ " or " ++
337 @tagName(Node.Tag.FnProto) ++ ", found {}", .{@tagName(self.node.tag)});
338338 }
339339 };
340340
......@@ -396,9 +396,9 @@ pub const Error = union(enum) {
396396};
397397
398398pub const Node = struct {
399 id: Id,
399 tag: Tag,
400400
401 pub const Id = enum {
401 pub const Tag = enum {
402402 // Top level
403403 Root,
404404 Use,
......@@ -484,49 +484,129 @@ pub const Node = struct {
484484 ContainerField,
485485 ErrorTag,
486486 FieldInitializer,
487
488 pub fn Type(tag: Tag) type {
489 return switch (tag) {
490 .Root => Root,
491 .Use => Use,
492 .TestDecl => TestDecl,
493 .VarDecl => VarDecl,
494 .Defer => Defer,
495 .InfixOp => InfixOp,
496
497 .AddressOf,
498 .Await,
499 .BitNot,
500 .BoolNot,
501 .OptionalType,
502 .Negation,
503 .NegationWrap,
504 .Resume,
505 .Try,
506 => SimplePrefixOp,
507
508 .ArrayType => ArrayType,
509 .ArrayTypeSentinel => ArrayTypeSentinel,
510 .PtrType => PtrType,
511 .SliceType => SliceType,
512 .SuffixOp => SuffixOp,
513 .ArrayInitializer => ArrayInitializer,
514 .ArrayInitializerDot => ArrayInitializerDot,
515 .StructInitializer => StructInitializer,
516 .StructInitializerDot => StructInitializerDot,
517 .Call => Call,
518 .Switch => Switch,
519 .While => While,
520 .For => For,
521 .If => If,
522 .ControlFlowExpression => ControlFlowExpression,
523 .Suspend => Suspend,
524 .AnyType => AnyType,
525 .ErrorType => ErrorType,
526 .FnProto => FnProto,
527 .AnyFrameType => AnyFrameType,
528 .IntegerLiteral => IntegerLiteral,
529 .FloatLiteral => FloatLiteral,
530 .EnumLiteral => EnumLiteral,
531 .StringLiteral => StringLiteral,
532 .MultilineStringLiteral => MultilineStringLiteral,
533 .CharLiteral => CharLiteral,
534 .BoolLiteral => BoolLiteral,
535 .NullLiteral => NullLiteral,
536 .UndefinedLiteral => UndefinedLiteral,
537 .Unreachable => Unreachable,
538 .Identifier => Identifier,
539 .GroupedExpression => GroupedExpression,
540 .BuiltinCall => BuiltinCall,
541 .ErrorSetDecl => ErrorSetDecl,
542 .ContainerDecl => ContainerDecl,
543 .Asm => Asm,
544 .Comptime => Comptime,
545 .Nosuspend => Nosuspend,
546 .Block => Block,
547 .DocComment => DocComment,
548 .SwitchCase => SwitchCase,
549 .SwitchElse => SwitchElse,
550 .Else => Else,
551 .Payload => Payload,
552 .PointerPayload => PointerPayload,
553 .PointerIndexPayload => PointerIndexPayload,
554 .ContainerField => ContainerField,
555 .ErrorTag => ErrorTag,
556 .FieldInitializer => FieldInitializer,
557 };
558 }
487559 };
488560
561 /// Prefer `castTag` to this.
489562 pub fn cast(base: *Node, comptime T: type) ?*T {
490 if (base.id == comptime typeToId(T)) {
491 return @fieldParentPtr(T, "base", base);
563 if (std.meta.fieldInfo(T, "base").default_value) |default_base| {
564 return base.castTag(default_base.tag);
565 }
566 inline for (@typeInfo(Tag).Enum.fields) |field| {
567 const tag = @intToEnum(Tag, field.value);
568 if (base.tag == tag) {
569 if (T == tag.Type()) {
570 return @fieldParentPtr(T, "base", base);
571 }
572 return null;
573 }
574 }
575 unreachable;
576 }
577
578 pub fn castTag(base: *Node, comptime tag: Tag) ?*tag.Type() {
579 if (base.tag == tag) {
580 return @fieldParentPtr(tag.Type(), "base", base);
492581 }
493582 return null;
494583 }
495584
496585 pub fn iterate(base: *Node, index: usize) ?*Node {
497 inline for (@typeInfo(Id).Enum.fields) |f| {
498 if (base.id == @field(Id, f.name)) {
499 const T = @field(Node, f.name);
500 return @fieldParentPtr(T, "base", base).iterate(index);
586 inline for (@typeInfo(Tag).Enum.fields) |field| {
587 const tag = @intToEnum(Tag, field.value);
588 if (base.tag == tag) {
589 return @fieldParentPtr(tag.Type(), "base", base).iterate(index);
501590 }
502591 }
503592 unreachable;
504593 }
505594
506595 pub fn firstToken(base: *const Node) TokenIndex {
507 inline for (@typeInfo(Id).Enum.fields) |f| {
508 if (base.id == @field(Id, f.name)) {
509 const T = @field(Node, f.name);
510 return @fieldParentPtr(T, "base", base).firstToken();
596 inline for (@typeInfo(Tag).Enum.fields) |field| {
597 const tag = @intToEnum(Tag, field.value);
598 if (base.tag == tag) {
599 return @fieldParentPtr(tag.Type(), "base", base).firstToken();
511600 }
512601 }
513602 unreachable;
514603 }
515604
516605 pub fn lastToken(base: *const Node) TokenIndex {
517 inline for (@typeInfo(Id).Enum.fields) |f| {
518 if (base.id == @field(Id, f.name)) {
519 const T = @field(Node, f.name);
520 return @fieldParentPtr(T, "base", base).lastToken();
521 }
522 }
523 unreachable;
524 }
525
526 pub fn typeToId(comptime T: type) Id {
527 inline for (@typeInfo(Id).Enum.fields) |f| {
528 if (T == @field(Node, f.name)) {
529 return @field(Id, f.name);
606 inline for (@typeInfo(Tag).Enum.fields) |field| {
607 const tag = @intToEnum(Tag, field.value);
608 if (base.tag == tag) {
609 return @fieldParentPtr(tag.Type(), "base", base).lastToken();
530610 }
531611 }
532612 unreachable;
......@@ -535,7 +615,7 @@ pub const Node = struct {
535615 pub fn requireSemiColon(base: *const Node) bool {
536616 var n = base;
537617 while (true) {
538 switch (n.id) {
618 switch (n.tag) {
539619 .Root,
540620 .ContainerField,
541621 .Block,
......@@ -556,7 +636,7 @@ pub const Node = struct {
556636 continue;
557637 }
558638
559 return while_node.body.id != .Block;
639 return while_node.body.tag != .Block;
560640 },
561641 .For => {
562642 const for_node = @fieldParentPtr(For, "base", n);
......@@ -565,7 +645,7 @@ pub const Node = struct {
565645 continue;
566646 }
567647
568 return for_node.body.id != .Block;
648 return for_node.body.tag != .Block;
569649 },
570650 .If => {
571651 const if_node = @fieldParentPtr(If, "base", n);
......@@ -574,7 +654,7 @@ pub const Node = struct {
574654 continue;
575655 }
576656
577 return if_node.body.id != .Block;
657 return if_node.body.tag != .Block;
578658 },
579659 .Else => {
580660 const else_node = @fieldParentPtr(Else, "base", n);
......@@ -583,23 +663,23 @@ pub const Node = struct {
583663 },
584664 .Defer => {
585665 const defer_node = @fieldParentPtr(Defer, "base", n);
586 return defer_node.expr.id != .Block;
666 return defer_node.expr.tag != .Block;
587667 },
588668 .Comptime => {
589669 const comptime_node = @fieldParentPtr(Comptime, "base", n);
590 return comptime_node.expr.id != .Block;
670 return comptime_node.expr.tag != .Block;
591671 },
592672 .Suspend => {
593673 const suspend_node = @fieldParentPtr(Suspend, "base", n);
594674 if (suspend_node.body) |body| {
595 return body.id != .Block;
675 return body.tag != .Block;
596676 }
597677
598678 return true;
599679 },
600680 .Nosuspend => {
601681 const nosuspend_node = @fieldParentPtr(Nosuspend, "base", n);
602 return nosuspend_node.expr.id != .Block;
682 return nosuspend_node.expr.tag != .Block;
603683 },
604684 else => return true,
605685 }
......@@ -613,7 +693,7 @@ pub const Node = struct {
613693 std.debug.warn(" ", .{});
614694 }
615695 }
616 std.debug.warn("{}\n", .{@tagName(self.id)});
696 std.debug.warn("{}\n", .{@tagName(self.tag)});
617697
618698 var child_i: usize = 0;
619699 while (self.iterate(child_i)) |child| : (child_i += 1) {
......@@ -623,7 +703,7 @@ pub const Node = struct {
623703
624704 /// The decls data follows this struct in memory as an array of Node pointers.
625705 pub const Root = struct {
626 base: Node = Node{ .id = .Root },
706 base: Node = Node{ .tag = .Root },
627707 eof_token: TokenIndex,
628708 decls_len: NodeIndex,
629709
......@@ -678,7 +758,7 @@ pub const Node = struct {
678758 /// Trailed in memory by possibly many things, with each optional thing
679759 /// determined by a bit in `trailer_flags`.
680760 pub const VarDecl = struct {
681 base: Node = Node{ .id = .VarDecl },
761 base: Node = Node{ .tag = .VarDecl },
682762 trailer_flags: TrailerFlags,
683763 mut_token: TokenIndex,
684764 name_token: TokenIndex,
......@@ -779,7 +859,7 @@ pub const Node = struct {
779859 };
780860
781861 pub const Use = struct {
782 base: Node = Node{ .id = .Use },
862 base: Node = Node{ .tag = .Use },
783863 doc_comments: ?*DocComment,
784864 visib_token: ?TokenIndex,
785865 use_token: TokenIndex,
......@@ -806,7 +886,7 @@ pub const Node = struct {
806886 };
807887
808888 pub const ErrorSetDecl = struct {
809 base: Node = Node{ .id = .ErrorSetDecl },
889 base: Node = Node{ .tag = .ErrorSetDecl },
810890 error_token: TokenIndex,
811891 rbrace_token: TokenIndex,
812892 decls_len: NodeIndex,
......@@ -856,7 +936,7 @@ pub const Node = struct {
856936
857937 /// The fields and decls Node pointers directly follow this struct in memory.
858938 pub const ContainerDecl = struct {
859 base: Node = Node{ .id = .ContainerDecl },
939 base: Node = Node{ .tag = .ContainerDecl },
860940 kind_token: TokenIndex,
861941 layout_token: ?TokenIndex,
862942 lbrace_token: TokenIndex,
......@@ -925,7 +1005,7 @@ pub const Node = struct {
9251005 };
9261006
9271007 pub const ContainerField = struct {
928 base: Node = Node{ .id = .ContainerField },
1008 base: Node = Node{ .tag = .ContainerField },
9291009 doc_comments: ?*DocComment,
9301010 comptime_token: ?TokenIndex,
9311011 name_token: TokenIndex,
......@@ -976,7 +1056,7 @@ pub const Node = struct {
9761056 };
9771057
9781058 pub const ErrorTag = struct {
979 base: Node = Node{ .id = .ErrorTag },
1059 base: Node = Node{ .tag = .ErrorTag },
9801060 doc_comments: ?*DocComment,
9811061 name_token: TokenIndex,
9821062
......@@ -1001,7 +1081,7 @@ pub const Node = struct {
10011081 };
10021082
10031083 pub const Identifier = struct {
1004 base: Node = Node{ .id = .Identifier },
1084 base: Node = Node{ .tag = .Identifier },
10051085 token: TokenIndex,
10061086
10071087 pub fn iterate(self: *const Identifier, index: usize) ?*Node {
......@@ -1020,7 +1100,7 @@ pub const Node = struct {
10201100 /// The params are directly after the FnProto in memory.
10211101 /// Next, each optional thing determined by a bit in `trailer_flags`.
10221102 pub const FnProto = struct {
1023 base: Node = Node{ .id = .FnProto },
1103 base: Node = Node{ .tag = .FnProto },
10241104 trailer_flags: TrailerFlags,
10251105 fn_token: TokenIndex,
10261106 params_len: NodeIndex,
......@@ -1230,7 +1310,7 @@ pub const Node = struct {
12301310 };
12311311
12321312 pub const AnyFrameType = struct {
1233 base: Node = Node{ .id = .AnyFrameType },
1313 base: Node = Node{ .tag = .AnyFrameType },
12341314 anyframe_token: TokenIndex,
12351315 result: ?Result,
12361316
......@@ -1262,7 +1342,7 @@ pub const Node = struct {
12621342
12631343 /// The statements of the block follow Block directly in memory.
12641344 pub const Block = struct {
1265 base: Node = Node{ .id = .Block },
1345 base: Node = Node{ .tag = .Block },
12661346 statements_len: NodeIndex,
12671347 lbrace: TokenIndex,
12681348 rbrace: TokenIndex,
......@@ -1316,7 +1396,7 @@ pub const Node = struct {
13161396 };
13171397
13181398 pub const Defer = struct {
1319 base: Node = Node{ .id = .Defer },
1399 base: Node = Node{ .tag = .Defer },
13201400 defer_token: TokenIndex,
13211401 payload: ?*Node,
13221402 expr: *Node,
......@@ -1340,7 +1420,7 @@ pub const Node = struct {
13401420 };
13411421
13421422 pub const Comptime = struct {
1343 base: Node = Node{ .id = .Comptime },
1423 base: Node = Node{ .tag = .Comptime },
13441424 doc_comments: ?*DocComment,
13451425 comptime_token: TokenIndex,
13461426 expr: *Node,
......@@ -1364,7 +1444,7 @@ pub const Node = struct {
13641444 };
13651445
13661446 pub const Nosuspend = struct {
1367 base: Node = Node{ .id = .Nosuspend },
1447 base: Node = Node{ .tag = .Nosuspend },
13681448 nosuspend_token: TokenIndex,
13691449 expr: *Node,
13701450
......@@ -1387,7 +1467,7 @@ pub const Node = struct {
13871467 };
13881468
13891469 pub const Payload = struct {
1390 base: Node = Node{ .id = .Payload },
1470 base: Node = Node{ .tag = .Payload },
13911471 lpipe: TokenIndex,
13921472 error_symbol: *Node,
13931473 rpipe: TokenIndex,
......@@ -1411,7 +1491,7 @@ pub const Node = struct {
14111491 };
14121492
14131493 pub const PointerPayload = struct {
1414 base: Node = Node{ .id = .PointerPayload },
1494 base: Node = Node{ .tag = .PointerPayload },
14151495 lpipe: TokenIndex,
14161496 ptr_token: ?TokenIndex,
14171497 value_symbol: *Node,
......@@ -1436,7 +1516,7 @@ pub const Node = struct {
14361516 };
14371517
14381518 pub const PointerIndexPayload = struct {
1439 base: Node = Node{ .id = .PointerIndexPayload },
1519 base: Node = Node{ .tag = .PointerIndexPayload },
14401520 lpipe: TokenIndex,
14411521 ptr_token: ?TokenIndex,
14421522 value_symbol: *Node,
......@@ -1467,7 +1547,7 @@ pub const Node = struct {
14671547 };
14681548
14691549 pub const Else = struct {
1470 base: Node = Node{ .id = .Else },
1550 base: Node = Node{ .tag = .Else },
14711551 else_token: TokenIndex,
14721552 payload: ?*Node,
14731553 body: *Node,
......@@ -1498,7 +1578,7 @@ pub const Node = struct {
14981578 /// The cases node pointers are found in memory after Switch.
14991579 /// They must be SwitchCase or SwitchElse nodes.
15001580 pub const Switch = struct {
1501 base: Node = Node{ .id = .Switch },
1581 base: Node = Node{ .tag = .Switch },
15021582 switch_token: TokenIndex,
15031583 rbrace: TokenIndex,
15041584 cases_len: NodeIndex,
......@@ -1552,7 +1632,7 @@ pub const Node = struct {
15521632
15531633 /// Items sub-nodes appear in memory directly following SwitchCase.
15541634 pub const SwitchCase = struct {
1555 base: Node = Node{ .id = .SwitchCase },
1635 base: Node = Node{ .tag = .SwitchCase },
15561636 arrow_token: TokenIndex,
15571637 payload: ?*Node,
15581638 expr: *Node,
......@@ -1610,7 +1690,7 @@ pub const Node = struct {
16101690 };
16111691
16121692 pub const SwitchElse = struct {
1613 base: Node = Node{ .id = .SwitchElse },
1693 base: Node = Node{ .tag = .SwitchElse },
16141694 token: TokenIndex,
16151695
16161696 pub fn iterate(self: *const SwitchElse, index: usize) ?*Node {
......@@ -1627,7 +1707,7 @@ pub const Node = struct {
16271707 };
16281708
16291709 pub const While = struct {
1630 base: Node = Node{ .id = .While },
1710 base: Node = Node{ .tag = .While },
16311711 label: ?TokenIndex,
16321712 inline_token: ?TokenIndex,
16331713 while_token: TokenIndex,
......@@ -1686,7 +1766,7 @@ pub const Node = struct {
16861766 };
16871767
16881768 pub const For = struct {
1689 base: Node = Node{ .id = .For },
1769 base: Node = Node{ .tag = .For },
16901770 label: ?TokenIndex,
16911771 inline_token: ?TokenIndex,
16921772 for_token: TokenIndex,
......@@ -1737,7 +1817,7 @@ pub const Node = struct {
17371817 };
17381818
17391819 pub const If = struct {
1740 base: Node = Node{ .id = .If },
1820 base: Node = Node{ .tag = .If },
17411821 if_token: TokenIndex,
17421822 condition: *Node,
17431823 payload: ?*Node,
......@@ -1779,8 +1859,9 @@ pub const Node = struct {
17791859 }
17801860 };
17811861
1862 /// TODO split up and make every op its own AST Node tag
17821863 pub const InfixOp = struct {
1783 base: Node = Node{ .id = .InfixOp },
1864 base: Node = Node{ .tag = .InfixOp },
17841865 op_token: TokenIndex,
17851866 lhs: *Node,
17861867 op: Op,
......@@ -1906,41 +1987,29 @@ pub const Node = struct {
19061987 }
19071988 };
19081989
1909 pub const AddressOf = SimplePrefixOp(.AddressOf);
1910 pub const Await = SimplePrefixOp(.Await);
1911 pub const BitNot = SimplePrefixOp(.BitNot);
1912 pub const BoolNot = SimplePrefixOp(.BoolNot);
1913 pub const OptionalType = SimplePrefixOp(.OptionalType);
1914 pub const Negation = SimplePrefixOp(.Negation);
1915 pub const NegationWrap = SimplePrefixOp(.NegationWrap);
1916 pub const Resume = SimplePrefixOp(.Resume);
1917 pub const Try = SimplePrefixOp(.Try);
1918
1919 pub fn SimplePrefixOp(comptime tag: Id) type {
1920 return struct {
1921 base: Node = Node{ .id = tag },
1922 op_token: TokenIndex,
1923 rhs: *Node,
1990 pub const SimplePrefixOp = struct {
1991 base: Node,
1992 op_token: TokenIndex,
1993 rhs: *Node,
19241994
1925 const Self = @This();
1995 const Self = @This();
19261996
1927 pub fn iterate(self: *const Self, index: usize) ?*Node {
1928 if (index == 0) return self.rhs;
1929 return null;
1930 }
1997 pub fn iterate(self: *const Self, index: usize) ?*Node {
1998 if (index == 0) return self.rhs;
1999 return null;
2000 }
19312001
1932 pub fn firstToken(self: *const Self) TokenIndex {
1933 return self.op_token;
1934 }
2002 pub fn firstToken(self: *const Self) TokenIndex {
2003 return self.op_token;
2004 }
19352005
1936 pub fn lastToken(self: *const Self) TokenIndex {
1937 return self.rhs.lastToken();
1938 }
1939 };
1940 }
2006 pub fn lastToken(self: *const Self) TokenIndex {
2007 return self.rhs.lastToken();
2008 }
2009 };
19412010
19422011 pub const ArrayType = struct {
1943 base: Node = Node{ .id = .ArrayType },
2012 base: Node = Node{ .tag = .ArrayType },
19442013 op_token: TokenIndex,
19452014 rhs: *Node,
19462015 len_expr: *Node,
......@@ -1967,7 +2036,7 @@ pub const Node = struct {
19672036 };
19682037
19692038 pub const ArrayTypeSentinel = struct {
1970 base: Node = Node{ .id = .ArrayTypeSentinel },
2039 base: Node = Node{ .tag = .ArrayTypeSentinel },
19712040 op_token: TokenIndex,
19722041 rhs: *Node,
19732042 len_expr: *Node,
......@@ -1998,7 +2067,7 @@ pub const Node = struct {
19982067 };
19992068
20002069 pub const PtrType = struct {
2001 base: Node = Node{ .id = .PtrType },
2070 base: Node = Node{ .tag = .PtrType },
20022071 op_token: TokenIndex,
20032072 rhs: *Node,
20042073 /// TODO Add a u8 flags field to Node where it would otherwise be padding, and each bit represents
......@@ -2034,7 +2103,7 @@ pub const Node = struct {
20342103 };
20352104
20362105 pub const SliceType = struct {
2037 base: Node = Node{ .id = .SliceType },
2106 base: Node = Node{ .tag = .SliceType },
20382107 op_token: TokenIndex,
20392108 rhs: *Node,
20402109 /// TODO Add a u8 flags field to Node where it would otherwise be padding, and each bit represents
......@@ -2070,7 +2139,7 @@ pub const Node = struct {
20702139 };
20712140
20722141 pub const FieldInitializer = struct {
2073 base: Node = Node{ .id = .FieldInitializer },
2142 base: Node = Node{ .tag = .FieldInitializer },
20742143 period_token: TokenIndex,
20752144 name_token: TokenIndex,
20762145 expr: *Node,
......@@ -2095,7 +2164,7 @@ pub const Node = struct {
20952164
20962165 /// Elements occur directly in memory after ArrayInitializer.
20972166 pub const ArrayInitializer = struct {
2098 base: Node = Node{ .id = .ArrayInitializer },
2167 base: Node = Node{ .tag = .ArrayInitializer },
20992168 rtoken: TokenIndex,
21002169 list_len: NodeIndex,
21012170 lhs: *Node,
......@@ -2148,7 +2217,7 @@ pub const Node = struct {
21482217
21492218 /// Elements occur directly in memory after ArrayInitializerDot.
21502219 pub const ArrayInitializerDot = struct {
2151 base: Node = Node{ .id = .ArrayInitializerDot },
2220 base: Node = Node{ .tag = .ArrayInitializerDot },
21522221 dot: TokenIndex,
21532222 rtoken: TokenIndex,
21542223 list_len: NodeIndex,
......@@ -2198,7 +2267,7 @@ pub const Node = struct {
21982267
21992268 /// Elements occur directly in memory after StructInitializer.
22002269 pub const StructInitializer = struct {
2201 base: Node = Node{ .id = .StructInitializer },
2270 base: Node = Node{ .tag = .StructInitializer },
22022271 rtoken: TokenIndex,
22032272 list_len: NodeIndex,
22042273 lhs: *Node,
......@@ -2251,7 +2320,7 @@ pub const Node = struct {
22512320
22522321 /// Elements occur directly in memory after StructInitializerDot.
22532322 pub const StructInitializerDot = struct {
2254 base: Node = Node{ .id = .StructInitializerDot },
2323 base: Node = Node{ .tag = .StructInitializerDot },
22552324 dot: TokenIndex,
22562325 rtoken: TokenIndex,
22572326 list_len: NodeIndex,
......@@ -2301,7 +2370,7 @@ pub const Node = struct {
23012370
23022371 /// Parameter nodes directly follow Call in memory.
23032372 pub const Call = struct {
2304 base: Node = Node{ .id = .Call },
2373 base: Node = Node{ .tag = .Call },
23052374 lhs: *Node,
23062375 rtoken: TokenIndex,
23072376 params_len: NodeIndex,
......@@ -2355,7 +2424,7 @@ pub const Node = struct {
23552424 };
23562425
23572426 pub const SuffixOp = struct {
2358 base: Node = Node{ .id = .SuffixOp },
2427 base: Node = Node{ .tag = .SuffixOp },
23592428 op: Op,
23602429 lhs: *Node,
23612430 rtoken: TokenIndex,
......@@ -2415,7 +2484,7 @@ pub const Node = struct {
24152484 };
24162485
24172486 pub const GroupedExpression = struct {
2418 base: Node = Node{ .id = .GroupedExpression },
2487 base: Node = Node{ .tag = .GroupedExpression },
24192488 lparen: TokenIndex,
24202489 expr: *Node,
24212490 rparen: TokenIndex,
......@@ -2441,7 +2510,7 @@ pub const Node = struct {
24412510 /// TODO break this into separate Break, Continue, Return AST Nodes to save memory.
24422511 /// Could be further broken into LabeledBreak, LabeledContinue, and ReturnVoid to save even more.
24432512 pub const ControlFlowExpression = struct {
2444 base: Node = Node{ .id = .ControlFlowExpression },
2513 base: Node = Node{ .tag = .ControlFlowExpression },
24452514 ltoken: TokenIndex,
24462515 kind: Kind,
24472516 rhs: ?*Node,
......@@ -2496,7 +2565,7 @@ pub const Node = struct {
24962565 };
24972566
24982567 pub const Suspend = struct {
2499 base: Node = Node{ .id = .Suspend },
2568 base: Node = Node{ .tag = .Suspend },
25002569 suspend_token: TokenIndex,
25012570 body: ?*Node,
25022571
......@@ -2525,7 +2594,7 @@ pub const Node = struct {
25252594 };
25262595
25272596 pub const IntegerLiteral = struct {
2528 base: Node = Node{ .id = .IntegerLiteral },
2597 base: Node = Node{ .tag = .IntegerLiteral },
25292598 token: TokenIndex,
25302599
25312600 pub fn iterate(self: *const IntegerLiteral, index: usize) ?*Node {
......@@ -2542,7 +2611,7 @@ pub const Node = struct {
25422611 };
25432612
25442613 pub const EnumLiteral = struct {
2545 base: Node = Node{ .id = .EnumLiteral },
2614 base: Node = Node{ .tag = .EnumLiteral },
25462615 dot: TokenIndex,
25472616 name: TokenIndex,
25482617
......@@ -2560,7 +2629,7 @@ pub const Node = struct {
25602629 };
25612630
25622631 pub const FloatLiteral = struct {
2563 base: Node = Node{ .id = .FloatLiteral },
2632 base: Node = Node{ .tag = .FloatLiteral },
25642633 token: TokenIndex,
25652634
25662635 pub fn iterate(self: *const FloatLiteral, index: usize) ?*Node {
......@@ -2578,7 +2647,7 @@ pub const Node = struct {
25782647
25792648 /// Parameters are in memory following BuiltinCall.
25802649 pub const BuiltinCall = struct {
2581 base: Node = Node{ .id = .BuiltinCall },
2650 base: Node = Node{ .tag = .BuiltinCall },
25822651 params_len: NodeIndex,
25832652 builtin_token: TokenIndex,
25842653 rparen_token: TokenIndex,
......@@ -2627,7 +2696,7 @@ pub const Node = struct {
26272696 };
26282697
26292698 pub const StringLiteral = struct {
2630 base: Node = Node{ .id = .StringLiteral },
2699 base: Node = Node{ .tag = .StringLiteral },
26312700 token: TokenIndex,
26322701
26332702 pub fn iterate(self: *const StringLiteral, index: usize) ?*Node {
......@@ -2645,7 +2714,7 @@ pub const Node = struct {
26452714
26462715 /// The string literal tokens appear directly in memory after MultilineStringLiteral.
26472716 pub const MultilineStringLiteral = struct {
2648 base: Node = Node{ .id = .MultilineStringLiteral },
2717 base: Node = Node{ .tag = .MultilineStringLiteral },
26492718 lines_len: TokenIndex,
26502719
26512720 /// After this the caller must initialize the lines list.
......@@ -2687,7 +2756,7 @@ pub const Node = struct {
26872756 };
26882757
26892758 pub const CharLiteral = struct {
2690 base: Node = Node{ .id = .CharLiteral },
2759 base: Node = Node{ .tag = .CharLiteral },
26912760 token: TokenIndex,
26922761
26932762 pub fn iterate(self: *const CharLiteral, index: usize) ?*Node {
......@@ -2704,7 +2773,7 @@ pub const Node = struct {
27042773 };
27052774
27062775 pub const BoolLiteral = struct {
2707 base: Node = Node{ .id = .BoolLiteral },
2776 base: Node = Node{ .tag = .BoolLiteral },
27082777 token: TokenIndex,
27092778
27102779 pub fn iterate(self: *const BoolLiteral, index: usize) ?*Node {
......@@ -2721,7 +2790,7 @@ pub const Node = struct {
27212790 };
27222791
27232792 pub const NullLiteral = struct {
2724 base: Node = Node{ .id = .NullLiteral },
2793 base: Node = Node{ .tag = .NullLiteral },
27252794 token: TokenIndex,
27262795
27272796 pub fn iterate(self: *const NullLiteral, index: usize) ?*Node {
......@@ -2738,7 +2807,7 @@ pub const Node = struct {
27382807 };
27392808
27402809 pub const UndefinedLiteral = struct {
2741 base: Node = Node{ .id = .UndefinedLiteral },
2810 base: Node = Node{ .tag = .UndefinedLiteral },
27422811 token: TokenIndex,
27432812
27442813 pub fn iterate(self: *const UndefinedLiteral, index: usize) ?*Node {
......@@ -2755,7 +2824,7 @@ pub const Node = struct {
27552824 };
27562825
27572826 pub const Asm = struct {
2758 base: Node = Node{ .id = .Asm },
2827 base: Node = Node{ .tag = .Asm },
27592828 asm_token: TokenIndex,
27602829 rparen: TokenIndex,
27612830 volatile_token: ?TokenIndex,
......@@ -2875,7 +2944,7 @@ pub const Node = struct {
28752944 };
28762945
28772946 pub const Unreachable = struct {
2878 base: Node = Node{ .id = .Unreachable },
2947 base: Node = Node{ .tag = .Unreachable },
28792948 token: TokenIndex,
28802949
28812950 pub fn iterate(self: *const Unreachable, index: usize) ?*Node {
......@@ -2892,7 +2961,7 @@ pub const Node = struct {
28922961 };
28932962
28942963 pub const ErrorType = struct {
2895 base: Node = Node{ .id = .ErrorType },
2964 base: Node = Node{ .tag = .ErrorType },
28962965 token: TokenIndex,
28972966
28982967 pub fn iterate(self: *const ErrorType, index: usize) ?*Node {
......@@ -2909,7 +2978,7 @@ pub const Node = struct {
29092978 };
29102979
29112980 pub const AnyType = struct {
2912 base: Node = Node{ .id = .AnyType },
2981 base: Node = Node{ .tag = .AnyType },
29132982 token: TokenIndex,
29142983
29152984 pub fn iterate(self: *const AnyType, index: usize) ?*Node {
......@@ -2929,7 +2998,7 @@ pub const Node = struct {
29292998 /// TODO actually maybe remove entirely in favor of iterating backward from Node.firstToken()
29302999 /// and forwards to find same-line doc comments.
29313000 pub const DocComment = struct {
2932 base: Node = Node{ .id = .DocComment },
3001 base: Node = Node{ .tag = .DocComment },
29333002 /// Points to the first doc comment token. API users are expected to iterate over the
29343003 /// tokens array, looking for more doc comments, ignoring line comments, and stopping
29353004 /// at the first other token.
......@@ -2951,7 +3020,7 @@ pub const Node = struct {
29513020 };
29523021
29533022 pub const TestDecl = struct {
2954 base: Node = Node{ .id = .TestDecl },
3023 base: Node = Node{ .tag = .TestDecl },
29553024 doc_comments: ?*DocComment,
29563025 test_token: TokenIndex,
29573026 name: *Node,
......@@ -2996,7 +3065,7 @@ pub const PtrInfo = struct {
29963065
29973066test "iterate" {
29983067 var root = Node.Root{
2999 .base = Node{ .id = Node.Id.Root },
3068 .base = Node{ .tag = Node.Tag.Root },
30003069 .decls_len = 0,
30013070 .eof_token = 0,
30023071 };
lib/std/zig/parse.zig+36-111
......@@ -1128,8 +1128,9 @@ const Parser = struct {
11281128 const expr_node = try p.expectNode(parseExpr, .{
11291129 .ExpectedExpr = .{ .token = p.tok_i },
11301130 });
1131 const node = try p.arena.allocator.create(Node.Resume);
1131 const node = try p.arena.allocator.create(Node.SimplePrefixOp);
11321132 node.* = .{
1133 .base = .{ .tag = .Resume },
11331134 .op_token = token,
11341135 .rhs = expr_node,
11351136 };
......@@ -1439,7 +1440,7 @@ const Parser = struct {
14391440 });
14401441
14411442 while (try p.parseSuffixOp()) |node| {
1442 switch (node.id) {
1443 switch (node.tag) {
14431444 .SuffixOp => node.cast(Node.SuffixOp).?.lhs = res,
14441445 .InfixOp => node.cast(Node.InfixOp).?.lhs = res,
14451446 else => unreachable,
......@@ -1470,7 +1471,7 @@ const Parser = struct {
14701471
14711472 while (true) {
14721473 if (try p.parseSuffixOp()) |node| {
1473 switch (node.id) {
1474 switch (node.tag) {
14741475 .SuffixOp => node.cast(Node.SuffixOp).?.lhs = res,
14751476 .InfixOp => node.cast(Node.InfixOp).?.lhs = res,
14761477 else => unreachable,
......@@ -1660,7 +1661,7 @@ const Parser = struct {
16601661 }
16611662
16621663 if (try p.parseLoopTypeExpr()) |node| {
1663 switch (node.id) {
1664 switch (node.tag) {
16641665 .For => node.cast(Node.For).?.label = label,
16651666 .While => node.cast(Node.While).?.label = label,
16661667 else => unreachable,
......@@ -2434,9 +2435,10 @@ const Parser = struct {
24342435 }
24352436 }
24362437
2437 fn allocSimplePrefixOp(p: *Parser, comptime tag: Node.Id, token: TokenIndex) !?*Node {
2438 const node = try p.arena.allocator.create(Node.SimplePrefixOp(tag));
2438 fn allocSimplePrefixOp(p: *Parser, comptime tag: Node.Tag, token: TokenIndex) !?*Node {
2439 const node = try p.arena.allocator.create(Node.SimplePrefixOp);
24392440 node.* = .{
2441 .base = .{ .tag = tag },
24402442 .op_token = token,
24412443 .rhs = undefined, // set by caller
24422444 };
......@@ -2457,8 +2459,9 @@ const Parser = struct {
24572459 /// / PtrTypeStart (KEYWORD_align LPAREN Expr (COLON INTEGER COLON INTEGER)? RPAREN / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)*
24582460 fn parsePrefixTypeOp(p: *Parser) !?*Node {
24592461 if (p.eatToken(.QuestionMark)) |token| {
2460 const node = try p.arena.allocator.create(Node.OptionalType);
2462 const node = try p.arena.allocator.create(Node.SimplePrefixOp);
24612463 node.* = .{
2464 .base = .{ .tag = .OptionalType },
24622465 .op_token = token,
24632466 .rhs = undefined, // set by caller
24642467 };
......@@ -3072,7 +3075,6 @@ const Parser = struct {
30723075 fn createLiteral(p: *Parser, comptime T: type, token: TokenIndex) !*Node {
30733076 const result = try p.arena.allocator.create(T);
30743077 result.* = T{
3075 .base = Node{ .id = Node.typeToId(T) },
30763078 .token = token,
30773079 };
30783080 return &result.base;
......@@ -3148,8 +3150,9 @@ const Parser = struct {
31483150
31493151 fn parseTry(p: *Parser) !?*Node {
31503152 const token = p.eatToken(.Keyword_try) orelse return null;
3151 const node = try p.arena.allocator.create(Node.Try);
3153 const node = try p.arena.allocator.create(Node.SimplePrefixOp);
31523154 node.* = .{
3155 .base = .{ .tag = .Try },
31533156 .op_token = token,
31543157 .rhs = undefined, // set by caller
31553158 };
......@@ -3213,58 +3216,19 @@ const Parser = struct {
32133216 if (try opParseFn(p)) |first_op| {
32143217 var rightmost_op = first_op;
32153218 while (true) {
3216 switch (rightmost_op.id) {
3217 .AddressOf => {
3219 switch (rightmost_op.tag) {
3220 .AddressOf,
3221 .Await,
3222 .BitNot,
3223 .BoolNot,
3224 .OptionalType,
3225 .Negation,
3226 .NegationWrap,
3227 .Resume,
3228 .Try,
3229 => {
32183230 if (try opParseFn(p)) |rhs| {
3219 rightmost_op.cast(Node.AddressOf).?.rhs = rhs;
3220 rightmost_op = rhs;
3221 } else break;
3222 },
3223 .Await => {
3224 if (try opParseFn(p)) |rhs| {
3225 rightmost_op.cast(Node.Await).?.rhs = rhs;
3226 rightmost_op = rhs;
3227 } else break;
3228 },
3229 .BitNot => {
3230 if (try opParseFn(p)) |rhs| {
3231 rightmost_op.cast(Node.BitNot).?.rhs = rhs;
3232 rightmost_op = rhs;
3233 } else break;
3234 },
3235 .BoolNot => {
3236 if (try opParseFn(p)) |rhs| {
3237 rightmost_op.cast(Node.BoolNot).?.rhs = rhs;
3238 rightmost_op = rhs;
3239 } else break;
3240 },
3241 .OptionalType => {
3242 if (try opParseFn(p)) |rhs| {
3243 rightmost_op.cast(Node.OptionalType).?.rhs = rhs;
3244 rightmost_op = rhs;
3245 } else break;
3246 },
3247 .Negation => {
3248 if (try opParseFn(p)) |rhs| {
3249 rightmost_op.cast(Node.Negation).?.rhs = rhs;
3250 rightmost_op = rhs;
3251 } else break;
3252 },
3253 .NegationWrap => {
3254 if (try opParseFn(p)) |rhs| {
3255 rightmost_op.cast(Node.NegationWrap).?.rhs = rhs;
3256 rightmost_op = rhs;
3257 } else break;
3258 },
3259 .Resume => {
3260 if (try opParseFn(p)) |rhs| {
3261 rightmost_op.cast(Node.Resume).?.rhs = rhs;
3262 rightmost_op = rhs;
3263 } else break;
3264 },
3265 .Try => {
3266 if (try opParseFn(p)) |rhs| {
3267 rightmost_op.cast(Node.Try).?.rhs = rhs;
3231 rightmost_op.cast(Node.SimplePrefixOp).?.rhs = rhs;
32683232 rightmost_op = rhs;
32693233 } else break;
32703234 },
......@@ -3310,57 +3274,18 @@ const Parser = struct {
33103274 }
33113275
33123276 // If any prefix op existed, a child node on the RHS is required
3313 switch (rightmost_op.id) {
3314 .AddressOf => {
3315 const prefix_op = rightmost_op.cast(Node.AddressOf).?;
3316 prefix_op.rhs = try p.expectNode(childParseFn, .{
3317 .InvalidToken = .{ .token = p.tok_i },
3318 });
3319 },
3320 .Await => {
3321 const prefix_op = rightmost_op.cast(Node.Await).?;
3322 prefix_op.rhs = try p.expectNode(childParseFn, .{
3323 .InvalidToken = .{ .token = p.tok_i },
3324 });
3325 },
3326 .BitNot => {
3327 const prefix_op = rightmost_op.cast(Node.BitNot).?;
3328 prefix_op.rhs = try p.expectNode(childParseFn, .{
3329 .InvalidToken = .{ .token = p.tok_i },
3330 });
3331 },
3332 .BoolNot => {
3333 const prefix_op = rightmost_op.cast(Node.BoolNot).?;
3334 prefix_op.rhs = try p.expectNode(childParseFn, .{
3335 .InvalidToken = .{ .token = p.tok_i },
3336 });
3337 },
3338 .OptionalType => {
3339 const prefix_op = rightmost_op.cast(Node.OptionalType).?;
3340 prefix_op.rhs = try p.expectNode(childParseFn, .{
3341 .InvalidToken = .{ .token = p.tok_i },
3342 });
3343 },
3344 .Negation => {
3345 const prefix_op = rightmost_op.cast(Node.Negation).?;
3346 prefix_op.rhs = try p.expectNode(childParseFn, .{
3347 .InvalidToken = .{ .token = p.tok_i },
3348 });
3349 },
3350 .NegationWrap => {
3351 const prefix_op = rightmost_op.cast(Node.NegationWrap).?;
3352 prefix_op.rhs = try p.expectNode(childParseFn, .{
3353 .InvalidToken = .{ .token = p.tok_i },
3354 });
3355 },
3356 .Resume => {
3357 const prefix_op = rightmost_op.cast(Node.Resume).?;
3358 prefix_op.rhs = try p.expectNode(childParseFn, .{
3359 .InvalidToken = .{ .token = p.tok_i },
3360 });
3361 },
3362 .Try => {
3363 const prefix_op = rightmost_op.cast(Node.Try).?;
3277 switch (rightmost_op.tag) {
3278 .AddressOf,
3279 .Await,
3280 .BitNot,
3281 .BoolNot,
3282 .OptionalType,
3283 .Negation,
3284 .NegationWrap,
3285 .Resume,
3286 .Try,
3287 => {
3288 const prefix_op = rightmost_op.cast(Node.SimplePrefixOp).?;
33643289 prefix_op.rhs = try p.expectNode(childParseFn, .{
33653290 .InvalidToken = .{ .token = p.tok_i },
33663291 });
lib/std/zig/render.zig+33-58
......@@ -223,7 +223,7 @@ fn renderTopLevelDecl(allocator: *mem.Allocator, stream: anytype, tree: *ast.Tre
223223}
224224
225225fn renderContainerDecl(allocator: *mem.Allocator, stream: anytype, tree: *ast.Tree, indent: usize, start_col: *usize, decl: *ast.Node, space: Space) (@TypeOf(stream).Error || Error)!void {
226 switch (decl.id) {
226 switch (decl.tag) {
227227 .FnProto => {
228228 const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl);
229229
......@@ -365,7 +365,7 @@ fn renderExpression(
365365 base: *ast.Node,
366366 space: Space,
367367) (@TypeOf(stream).Error || Error)!void {
368 switch (base.id) {
368 switch (base.tag) {
369369 .Identifier => {
370370 const identifier = @fieldParentPtr(ast.Node.Identifier, "base", base);
371371 return renderToken(tree, stream, identifier.token, indent, start_col, space);
......@@ -468,50 +468,25 @@ fn renderExpression(
468468 return renderExpression(allocator, stream, tree, indent, start_col, infix_op_node.rhs, space);
469469 },
470470
471 .BitNot => {
472 const bit_not = @fieldParentPtr(ast.Node.BitNot, "base", base);
473 try renderToken(tree, stream, bit_not.op_token, indent, start_col, Space.None);
474 return renderExpression(allocator, stream, tree, indent, start_col, bit_not.rhs, space);
471 .BitNot,
472 .BoolNot,
473 .Negation,
474 .NegationWrap,
475 .OptionalType,
476 .AddressOf,
477 => {
478 const casted_node = @fieldParentPtr(ast.Node.SimplePrefixOp, "base", base);
479 try renderToken(tree, stream, casted_node.op_token, indent, start_col, Space.None);
480 return renderExpression(allocator, stream, tree, indent, start_col, casted_node.rhs, space);
475481 },
476 .BoolNot => {
477 const bool_not = @fieldParentPtr(ast.Node.BoolNot, "base", base);
478 try renderToken(tree, stream, bool_not.op_token, indent, start_col, Space.None);
479 return renderExpression(allocator, stream, tree, indent, start_col, bool_not.rhs, space);
480 },
481 .Negation => {
482 const negation = @fieldParentPtr(ast.Node.Negation, "base", base);
483 try renderToken(tree, stream, negation.op_token, indent, start_col, Space.None);
484 return renderExpression(allocator, stream, tree, indent, start_col, negation.rhs, space);
485 },
486 .NegationWrap => {
487 const negation_wrap = @fieldParentPtr(ast.Node.NegationWrap, "base", base);
488 try renderToken(tree, stream, negation_wrap.op_token, indent, start_col, Space.None);
489 return renderExpression(allocator, stream, tree, indent, start_col, negation_wrap.rhs, space);
490 },
491 .OptionalType => {
492 const opt_type = @fieldParentPtr(ast.Node.OptionalType, "base", base);
493 try renderToken(tree, stream, opt_type.op_token, indent, start_col, Space.None);
494 return renderExpression(allocator, stream, tree, indent, start_col, opt_type.rhs, space);
495 },
496 .AddressOf => {
497 const addr_of = @fieldParentPtr(ast.Node.AddressOf, "base", base);
498 try renderToken(tree, stream, addr_of.op_token, indent, start_col, Space.None);
499 return renderExpression(allocator, stream, tree, indent, start_col, addr_of.rhs, space);
500 },
501 .Try => {
502 const try_node = @fieldParentPtr(ast.Node.Try, "base", base);
503 try renderToken(tree, stream, try_node.op_token, indent, start_col, Space.Space);
504 return renderExpression(allocator, stream, tree, indent, start_col, try_node.rhs, space);
505 },
506 .Resume => {
507 const resume_node = @fieldParentPtr(ast.Node.Resume, "base", base);
508 try renderToken(tree, stream, resume_node.op_token, indent, start_col, Space.Space);
509 return renderExpression(allocator, stream, tree, indent, start_col, resume_node.rhs, space);
510 },
511 .Await => {
512 const await_node = @fieldParentPtr(ast.Node.Await, "base", base);
513 try renderToken(tree, stream, await_node.op_token, indent, start_col, Space.Space);
514 return renderExpression(allocator, stream, tree, indent, start_col, await_node.rhs, space);
482
483 .Try,
484 .Resume,
485 .Await,
486 => {
487 const casted_node = @fieldParentPtr(ast.Node.SimplePrefixOp, "base", base);
488 try renderToken(tree, stream, casted_node.op_token, indent, start_col, Space.Space);
489 return renderExpression(allocator, stream, tree, indent, start_col, casted_node.rhs, space);
515490 },
516491
517492 .ArrayType => {
......@@ -659,7 +634,7 @@ fn renderExpression(
659634 .ArrayInitializer, .ArrayInitializerDot => {
660635 var rtoken: ast.TokenIndex = undefined;
661636 var exprs: []*ast.Node = undefined;
662 const lhs: union(enum) { dot: ast.TokenIndex, node: *ast.Node } = switch (base.id) {
637 const lhs: union(enum) { dot: ast.TokenIndex, node: *ast.Node } = switch (base.tag) {
663638 .ArrayInitializerDot => blk: {
664639 const casted = @fieldParentPtr(ast.Node.ArrayInitializerDot, "base", base);
665640 rtoken = casted.rtoken;
......@@ -793,14 +768,14 @@ fn renderExpression(
793768 }
794769
795770 try renderExtraNewline(tree, stream, start_col, next_expr);
796 if (next_expr.id != .MultilineStringLiteral) {
771 if (next_expr.tag != .MultilineStringLiteral) {
797772 try stream.writeByteNTimes(' ', new_indent);
798773 }
799774 } else {
800775 try renderExpression(allocator, stream, tree, new_indent, start_col, expr, Space.Comma); // ,
801776 }
802777 }
803 if (exprs[exprs.len - 1].id != .MultilineStringLiteral) {
778 if (exprs[exprs.len - 1].tag != .MultilineStringLiteral) {
804779 try stream.writeByteNTimes(' ', indent);
805780 }
806781 return renderToken(tree, stream, rtoken, indent, start_col, space);
......@@ -823,7 +798,7 @@ fn renderExpression(
823798 .StructInitializer, .StructInitializerDot => {
824799 var rtoken: ast.TokenIndex = undefined;
825800 var field_inits: []*ast.Node = undefined;
826 const lhs: union(enum) { dot: ast.TokenIndex, node: *ast.Node } = switch (base.id) {
801 const lhs: union(enum) { dot: ast.TokenIndex, node: *ast.Node } = switch (base.tag) {
827802 .StructInitializerDot => blk: {
828803 const casted = @fieldParentPtr(ast.Node.StructInitializerDot, "base", base);
829804 rtoken = casted.rtoken;
......@@ -877,7 +852,7 @@ fn renderExpression(
877852 if (field_inits.len == 1) blk: {
878853 const field_init = field_inits[0].cast(ast.Node.FieldInitializer).?;
879854
880 switch (field_init.expr.id) {
855 switch (field_init.expr.tag) {
881856 .StructInitializer,
882857 .StructInitializerDot,
883858 => break :blk,
......@@ -974,7 +949,7 @@ fn renderExpression(
974949
975950 const params = call.params();
976951 for (params) |param_node, i| {
977 const param_node_new_indent = if (param_node.id == .MultilineStringLiteral) blk: {
952 const param_node_new_indent = if (param_node.tag == .MultilineStringLiteral) blk: {
978953 break :blk indent;
979954 } else blk: {
980955 try stream.writeByteNTimes(' ', new_indent);
......@@ -1284,7 +1259,7 @@ fn renderExpression(
12841259 // declarations inside are fields
12851260 const src_has_only_fields = blk: {
12861261 for (fields_and_decls) |decl| {
1287 if (decl.id != .ContainerField) break :blk false;
1262 if (decl.tag != .ContainerField) break :blk false;
12881263 }
12891264 break :blk true;
12901265 };
......@@ -1831,7 +1806,7 @@ fn renderExpression(
18311806
18321807 const rparen = tree.nextToken(for_node.array_expr.lastToken());
18331808
1834 const body_is_block = for_node.body.id == .Block;
1809 const body_is_block = for_node.body.tag == .Block;
18351810 const src_one_line_to_body = !body_is_block and tree.tokensOnSameLine(rparen, for_node.body.firstToken());
18361811 const body_on_same_line = body_is_block or src_one_line_to_body;
18371812
......@@ -1874,7 +1849,7 @@ fn renderExpression(
18741849
18751850 try renderExpression(allocator, stream, tree, indent, start_col, if_node.condition, Space.None); // condition
18761851
1877 const body_is_if_block = if_node.body.id == .If;
1852 const body_is_if_block = if_node.body.tag == .If;
18781853 const body_is_block = nodeIsBlock(if_node.body);
18791854
18801855 if (body_is_if_block) {
......@@ -1978,7 +1953,7 @@ fn renderExpression(
19781953
19791954 const indent_once = indent + indent_delta;
19801955
1981 if (asm_node.template.id == .MultilineStringLiteral) {
1956 if (asm_node.template.tag == .MultilineStringLiteral) {
19821957 // After rendering a multiline string literal the cursor is
19831958 // already offset by indent
19841959 try stream.writeByteNTimes(' ', indent_delta);
......@@ -2245,7 +2220,7 @@ fn renderVarDecl(
22452220 }
22462221
22472222 if (var_decl.getTrailer("init_node")) |init_node| {
2248 const s = if (init_node.id == .MultilineStringLiteral) Space.None else Space.Space;
2223 const s = if (init_node.tag == .MultilineStringLiteral) Space.None else Space.Space;
22492224 try renderToken(tree, stream, var_decl.getTrailer("eq_token").?, indent, start_col, s); // =
22502225 try renderExpression(allocator, stream, tree, indent, start_col, init_node, Space.None);
22512226 }
......@@ -2287,7 +2262,7 @@ fn renderStatement(
22872262 start_col: *usize,
22882263 base: *ast.Node,
22892264) (@TypeOf(stream).Error || Error)!void {
2290 switch (base.id) {
2265 switch (base.tag) {
22912266 .VarDecl => {
22922267 const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", base);
22932268 try renderVarDecl(allocator, stream, tree, indent, start_col, var_decl);
......@@ -2566,7 +2541,7 @@ fn renderDocCommentsToken(
25662541}
25672542
25682543fn nodeIsBlock(base: *const ast.Node) bool {
2569 return switch (base.id) {
2544 return switch (base.tag) {
25702545 .Block,
25712546 .If,
25722547 .For,
src-self-hosted/Module.zig+43-1
......@@ -212,6 +212,7 @@ pub const Decl = struct {
212212 },
213213 .block => unreachable,
214214 .gen_zir => unreachable,
215 .local_var => unreachable,
215216 .decl => unreachable,
216217 }
217218 }
......@@ -307,6 +308,7 @@ pub const Scope = struct {
307308 .block => return self.cast(Block).?.arena,
308309 .decl => return &self.cast(DeclAnalysis).?.arena.allocator,
309310 .gen_zir => return self.cast(GenZIR).?.arena,
311 .local_var => return self.cast(LocalVar).?.gen_zir.arena,
310312 .zir_module => return &self.cast(ZIRModule).?.contents.module.arena.allocator,
311313 .file => unreachable,
312314 }
......@@ -318,6 +320,7 @@ pub const Scope = struct {
318320 return switch (self.tag) {
319321 .block => self.cast(Block).?.decl,
320322 .gen_zir => self.cast(GenZIR).?.decl,
323 .local_var => return self.cast(LocalVar).?.gen_zir.decl,
321324 .decl => self.cast(DeclAnalysis).?.decl,
322325 .zir_module => null,
323326 .file => null,
......@@ -330,6 +333,7 @@ pub const Scope = struct {
330333 switch (self.tag) {
331334 .block => return self.cast(Block).?.decl.scope,
332335 .gen_zir => return self.cast(GenZIR).?.decl.scope,
336 .local_var => return self.cast(LocalVar).?.gen_zir.decl.scope,
333337 .decl => return self.cast(DeclAnalysis).?.decl.scope,
334338 .zir_module, .file => return self,
335339 }
......@@ -342,6 +346,7 @@ pub const Scope = struct {
342346 switch (self.tag) {
343347 .block => unreachable,
344348 .gen_zir => unreachable,
349 .local_var => unreachable,
345350 .decl => unreachable,
346351 .zir_module => return self.cast(ZIRModule).?.fullyQualifiedNameHash(name),
347352 .file => return self.cast(File).?.fullyQualifiedNameHash(name),
......@@ -356,9 +361,22 @@ pub const Scope = struct {
356361 .decl => return self.cast(DeclAnalysis).?.decl.scope.cast(File).?.contents.tree,
357362 .block => return self.cast(Block).?.decl.scope.cast(File).?.contents.tree,
358363 .gen_zir => return self.cast(GenZIR).?.decl.scope.cast(File).?.contents.tree,
364 .local_var => return self.cast(LocalVar).?.gen_zir.decl.scope.cast(File).?.contents.tree,
359365 }
360366 }
361367
368 /// Asserts the scope is a child of a `GenZIR` and returns it.
369 pub fn getGenZIR(self: *Scope) *GenZIR {
370 return switch (self.tag) {
371 .block => unreachable,
372 .gen_zir => self.cast(GenZIR).?,
373 .local_var => return self.cast(LocalVar).?.gen_zir,
374 .decl => unreachable,
375 .zir_module => unreachable,
376 .file => unreachable,
377 };
378 }
379
362380 pub fn dumpInst(self: *Scope, inst: *Inst) void {
363381 const zir_module = self.namespace();
364382 const loc = std.zig.findLineColumn(zir_module.source.bytes, inst.src);
......@@ -379,6 +397,7 @@ pub const Scope = struct {
379397 .zir_module => return @fieldParentPtr(ZIRModule, "base", base).sub_file_path,
380398 .block => unreachable,
381399 .gen_zir => unreachable,
400 .local_var => unreachable,
382401 .decl => unreachable,
383402 }
384403 }
......@@ -389,6 +408,7 @@ pub const Scope = struct {
389408 .zir_module => return @fieldParentPtr(ZIRModule, "base", base).unload(gpa),
390409 .block => unreachable,
391410 .gen_zir => unreachable,
411 .local_var => unreachable,
392412 .decl => unreachable,
393413 }
394414 }
......@@ -398,6 +418,7 @@ pub const Scope = struct {
398418 .file => return @fieldParentPtr(File, "base", base).getSource(module),
399419 .zir_module => return @fieldParentPtr(ZIRModule, "base", base).getSource(module),
400420 .gen_zir => unreachable,
421 .local_var => unreachable,
401422 .block => unreachable,
402423 .decl => unreachable,
403424 }
......@@ -410,6 +431,7 @@ pub const Scope = struct {
410431 .zir_module => return @fieldParentPtr(ZIRModule, "base", base).removeDecl(child),
411432 .block => unreachable,
412433 .gen_zir => unreachable,
434 .local_var => unreachable,
413435 .decl => unreachable,
414436 }
415437 }
......@@ -429,6 +451,7 @@ pub const Scope = struct {
429451 },
430452 .block => unreachable,
431453 .gen_zir => unreachable,
454 .local_var => unreachable,
432455 .decl => unreachable,
433456 }
434457 }
......@@ -449,6 +472,7 @@ pub const Scope = struct {
449472 block,
450473 decl,
451474 gen_zir,
475 local_var,
452476 };
453477
454478 pub const File = struct {
......@@ -680,6 +704,18 @@ pub const Scope = struct {
680704 arena: *Allocator,
681705 instructions: std.ArrayListUnmanaged(*zir.Inst) = .{},
682706 };
707
708 /// This structure lives as long as the AST generation of the Block
709 /// node that contains the variable. This struct's parents can be
710 /// other `LocalVar` and finally a `GenZIR` at the top.
711 pub const LocalVar = struct {
712 pub const base_tag: Tag = .local_var;
713 base: Scope = Scope{ .tag = base_tag },
714 gen_zir: *GenZIR,
715 parent: *Scope,
716 name: []const u8,
717 inst: *zir.Inst,
718 };
683719};
684720
685721pub const AllErrors = struct {
......@@ -1114,7 +1150,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
11141150 const file_scope = decl.scope.cast(Scope.File).?;
11151151 const tree = try self.getAstTree(file_scope);
11161152 const ast_node = tree.root_node.decls()[decl.src_index];
1117 switch (ast_node.id) {
1153 switch (ast_node.tag) {
11181154 .FnProto => {
11191155 const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", ast_node);
11201156
......@@ -3247,6 +3283,12 @@ fn failWithOwnedErrorMsg(self: *Module, scope: *Scope, src: usize, err_msg: *Err
32473283 gen_zir.decl.generation = self.generation;
32483284 self.failed_decls.putAssumeCapacityNoClobber(gen_zir.decl, err_msg);
32493285 },
3286 .local_var => {
3287 const gen_zir = scope.cast(Scope.LocalVar).?.gen_zir;
3288 gen_zir.decl.analysis = .sema_failure;
3289 gen_zir.decl.generation = self.generation;
3290 self.failed_decls.putAssumeCapacityNoClobber(gen_zir.decl, err_msg);
3291 },
32503292 .zir_module => {
32513293 const zir_module = scope.cast(Scope.ZIRModule).?;
32523294 zir_module.status = .loaded_sema_failure;
src-self-hosted/astgen.zig+133-11
......@@ -11,8 +11,11 @@ const trace = @import("tracy.zig").trace;
1111const Scope = Module.Scope;
1212const InnerError = Module.InnerError;
1313
14/// Turn Zig AST into untyped ZIR istructions.
1415pub fn expr(mod: *Module, scope: *Scope, ast_node: *ast.Node) InnerError!*zir.Inst {
15 switch (ast_node.id) {
16 switch (ast_node.tag) {
17 .VarDecl => unreachable, // Handled in `blockExpr`.
18
1619 .Identifier => return identifier(mod, scope, @fieldParentPtr(ast.Node.Identifier, "base", ast_node)),
1720 .Asm => return assembly(mod, scope, @fieldParentPtr(ast.Node.Asm, "base", ast_node)),
1821 .StringLiteral => return stringLiteral(mod, scope, @fieldParentPtr(ast.Node.StringLiteral, "base", ast_node)),
......@@ -23,29 +26,72 @@ pub fn expr(mod: *Module, scope: *Scope, ast_node: *ast.Node) InnerError!*zir.In
2326 .ControlFlowExpression => return controlFlowExpr(mod, scope, @fieldParentPtr(ast.Node.ControlFlowExpression, "base", ast_node)),
2427 .If => return ifExpr(mod, scope, @fieldParentPtr(ast.Node.If, "base", ast_node)),
2528 .InfixOp => return infixOp(mod, scope, @fieldParentPtr(ast.Node.InfixOp, "base", ast_node)),
26 .BoolNot => return boolNot(mod, scope, @fieldParentPtr(ast.Node.BoolNot, "base", ast_node)),
27 .VarDecl => return varDecl(mod, scope, @fieldParentPtr(ast.Node.VarDecl, "base", ast_node)),
28 else => return mod.failNode(scope, ast_node, "TODO implement astgen.Expr for {}", .{@tagName(ast_node.id)}),
29 .BoolNot => return boolNot(mod, scope, @fieldParentPtr(ast.Node.SimplePrefixOp, "base", ast_node)),
30 else => return mod.failNode(scope, ast_node, "TODO implement astgen.Expr for {}", .{@tagName(ast_node.tag)}),
2931 }
3032}
3133
32pub fn blockExpr(mod: *Module, scope: *Scope, block_node: *ast.Node.Block) !void {
34pub fn blockExpr(mod: *Module, parent_scope: *Scope, block_node: *ast.Node.Block) !void {
3335 const tracy = trace(@src());
3436 defer tracy.end();
3537
3638 if (block_node.label) |label| {
37 return mod.failTok(scope, label, "TODO implement labeled blocks", .{});
39 return mod.failTok(parent_scope, label, "TODO implement labeled blocks", .{});
3840 }
41
42 var block_arena = std.heap.ArenaAllocator.init(mod.gpa);
43 defer block_arena.deinit();
44
45 var scope = parent_scope;
3946 for (block_node.statements()) |statement| {
40 _ = try expr(mod, scope, statement);
47 switch (statement.tag) {
48 .VarDecl => {
49 const sub_scope = try block_arena.allocator.create(Scope.LocalVar);
50 const var_decl_node = @fieldParentPtr(ast.Node.VarDecl, "base", statement);
51 sub_scope.* = try varDecl(mod, scope, var_decl_node);
52 scope = &sub_scope.base;
53 },
54 else => _ = try expr(mod, scope, statement),
55 }
4156 }
4257}
4358
44fn varDecl(mod: *Module, scope: *Scope, node: *ast.Node.VarDecl) InnerError!*zir.Inst {
45 return mod.failNode(scope, &node.base, "TODO implement var decls", .{});
59fn varDecl(mod: *Module, scope: *Scope, node: *ast.Node.VarDecl) InnerError!Scope.LocalVar {
60 if (node.getTrailer("comptime_token")) |comptime_token| {
61 return mod.failTok(scope, comptime_token, "TODO implement comptime locals", .{});
62 }
63 if (node.getTrailer("align_node")) |align_node| {
64 return mod.failNode(scope, align_node, "TODO implement alignment on locals", .{});
65 }
66 if (node.getTrailer("type_node")) |type_node| {
67 return mod.failNode(scope, type_node, "TODO implement typed locals", .{});
68 }
69 const tree = scope.tree();
70 switch (tree.token_ids[node.mut_token]) {
71 .Keyword_const => {},
72 .Keyword_var => {
73 return mod.failTok(scope, node.mut_token, "TODO implement mutable locals", .{});
74 },
75 else => unreachable,
76 }
77 // Depending on the type of AST the initialization expression is, we may need an lvalue
78 // or an rvalue as a result location. If it is an rvalue, we can use the instruction as
79 // the variable, no memory location needed.
80 const init_node = node.getTrailer("init_node").?;
81 if (nodeNeedsMemoryLocation(init_node)) {
82 return mod.failNode(scope, init_node, "TODO implement result locations", .{});
83 }
84 const init_inst = try expr(mod, scope, init_node);
85 const ident_name = tree.tokenSlice(node.name_token); // TODO support @"aoeu" identifiers
86 return Scope.LocalVar{
87 .parent = scope,
88 .gen_zir = scope.getGenZIR(),
89 .name = ident_name,
90 .inst = init_inst,
91 };
4692}
4793
48fn boolNot(mod: *Module, scope: *Scope, node: *ast.Node.BoolNot) InnerError!*zir.Inst {
94fn boolNot(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerError!*zir.Inst {
4995 const operand = try expr(mod, scope, node.rhs);
5096 const tree = scope.tree();
5197 const src = tree.token_locs[node.op_token].start;
......@@ -55,7 +101,7 @@ fn boolNot(mod: *Module, scope: *Scope, node: *ast.Node.BoolNot) InnerError!*zir
55101fn infixOp(mod: *Module, scope: *Scope, infix_node: *ast.Node.InfixOp) InnerError!*zir.Inst {
56102 switch (infix_node.op) {
57103 .Assign => {
58 if (infix_node.lhs.id == .Identifier) {
104 if (infix_node.lhs.tag == .Identifier) {
59105 const ident = @fieldParentPtr(ast.Node.Identifier, "base", infix_node.lhs);
60106 const tree = scope.tree();
61107 const ident_name = tree.tokenSlice(ident.token);
......@@ -474,3 +520,79 @@ fn getSimplePrimitiveValue(name: []const u8) ?TypedValue {
474520 }
475521 return null;
476522}
523
524fn nodeNeedsMemoryLocation(node: *ast.Node) bool {
525 return switch (node.tag) {
526 .Root,
527 .Use,
528 .TestDecl,
529 .DocComment,
530 .SwitchCase,
531 .SwitchElse,
532 .Else,
533 .Payload,
534 .PointerPayload,
535 .PointerIndexPayload,
536 .ContainerField,
537 .ErrorTag,
538 .FieldInitializer,
539 => unreachable,
540
541 .ControlFlowExpression,
542 .BitNot,
543 .BoolNot,
544 .VarDecl,
545 .Defer,
546 .AddressOf,
547 .OptionalType,
548 .Negation,
549 .NegationWrap,
550 .Resume,
551 .ArrayType,
552 .ArrayTypeSentinel,
553 .PtrType,
554 .SliceType,
555 .Suspend,
556 .AnyType,
557 .ErrorType,
558 .FnProto,
559 .AnyFrameType,
560 .IntegerLiteral,
561 .FloatLiteral,
562 .EnumLiteral,
563 .StringLiteral,
564 .MultilineStringLiteral,
565 .CharLiteral,
566 .BoolLiteral,
567 .NullLiteral,
568 .UndefinedLiteral,
569 .Unreachable,
570 .Identifier,
571 .ErrorSetDecl,
572 .ContainerDecl,
573 .Asm,
574 => false,
575
576 .ArrayInitializer,
577 .ArrayInitializerDot,
578 .StructInitializer,
579 .StructInitializerDot,
580 => true,
581
582 .GroupedExpression => nodeNeedsMemoryLocation(node.cast(ast.Node.GroupedExpression).?.expr),
583
584 .InfixOp => @panic("TODO nodeNeedsMemoryLocation for InfixOp"),
585 .Await => @panic("TODO nodeNeedsMemoryLocation for Await"),
586 .Try => @panic("TODO nodeNeedsMemoryLocation for Try"),
587 .If => @panic("TODO nodeNeedsMemoryLocation for If"),
588 .SuffixOp => @panic("TODO nodeNeedsMemoryLocation for SuffixOp"),
589 .Call => @panic("TODO nodeNeedsMemoryLocation for Call"),
590 .Switch => @panic("TODO nodeNeedsMemoryLocation for Switch"),
591 .While => @panic("TODO nodeNeedsMemoryLocation for While"),
592 .For => @panic("TODO nodeNeedsMemoryLocation for For"),
593 .BuiltinCall => @panic("TODO nodeNeedsMemoryLocation for BuiltinCall"),
594 .Comptime => @panic("TODO nodeNeedsMemoryLocation for Comptime"),
595 .Nosuspend => @panic("TODO nodeNeedsMemoryLocation for Nosuspend"),
596 .Block => @panic("TODO nodeNeedsMemoryLocation for Block"),
597 };
598}
src-self-hosted/translate_c.zig+14-13
......@@ -1219,7 +1219,7 @@ fn transStmt(
12191219 .StringLiteralClass => return transStringLiteral(rp, scope, @ptrCast(*const ZigClangStringLiteral, stmt), result_used),
12201220 .ParenExprClass => {
12211221 const expr = try transExpr(rp, scope, ZigClangParenExpr_getSubExpr(@ptrCast(*const ZigClangParenExpr, stmt)), .used, lrvalue);
1222 if (expr.id == .GroupedExpression) return maybeSuppressResult(rp, scope, result_used, expr);
1222 if (expr.tag == .GroupedExpression) return maybeSuppressResult(rp, scope, result_used, expr);
12231223 const node = try rp.c.arena.create(ast.Node.GroupedExpression);
12241224 node.* = .{
12251225 .lparen = try appendToken(rp.c, .LParen, "("),
......@@ -1264,7 +1264,7 @@ fn transStmt(
12641264 .OpaqueValueExprClass => {
12651265 const source_expr = ZigClangOpaqueValueExpr_getSourceExpr(@ptrCast(*const ZigClangOpaqueValueExpr, stmt)).?;
12661266 const expr = try transExpr(rp, scope, source_expr, .used, lrvalue);
1267 if (expr.id == .GroupedExpression) return maybeSuppressResult(rp, scope, result_used, expr);
1267 if (expr.tag == .GroupedExpression) return maybeSuppressResult(rp, scope, result_used, expr);
12681268 const node = try rp.c.arena.create(ast.Node.GroupedExpression);
12691269 node.* = .{
12701270 .lparen = try appendToken(rp.c, .LParen, "("),
......@@ -1693,7 +1693,7 @@ fn transBoolExpr(
16931693 var res = try transExpr(rp, scope, expr, used, lrvalue);
16941694
16951695 if (isBoolRes(res)) {
1696 if (!grouped and res.id == .GroupedExpression) {
1696 if (!grouped and res.tag == .GroupedExpression) {
16971697 const group = @fieldParentPtr(ast.Node.GroupedExpression, "base", res);
16981698 res = group.expr;
16991699 // get zig fmt to work properly
......@@ -1736,7 +1736,7 @@ fn exprIsStringLiteral(expr: *const ZigClangExpr) bool {
17361736}
17371737
17381738fn isBoolRes(res: *ast.Node) bool {
1739 switch (res.id) {
1739 switch (res.tag) {
17401740 .InfixOp => switch (@fieldParentPtr(ast.Node.InfixOp, "base", res).op) {
17411741 .BoolOr,
17421742 .BoolAnd,
......@@ -4107,12 +4107,13 @@ fn transCreateNodeFieldAccess(c: *Context, container: *ast.Node, field_name: []c
41074107
41084108fn transCreateNodeSimplePrefixOp(
41094109 c: *Context,
4110 comptime tag: ast.Node.Id,
4110 comptime tag: ast.Node.Tag,
41114111 op_tok_id: std.zig.Token.Id,
41124112 bytes: []const u8,
4113) !*ast.Node.SimplePrefixOp(tag) {
4114 const node = try c.arena.create(ast.Node.SimplePrefixOp(tag));
4113) !*ast.Node.SimplePrefixOp {
4114 const node = try c.arena.create(ast.Node.SimplePrefixOp);
41154115 node.* = .{
4116 .base = .{ .tag = tag },
41164117 .op_token = try appendToken(c, op_tok_id, bytes),
41174118 .rhs = undefined, // translate and set afterward
41184119 };
......@@ -5338,10 +5339,10 @@ fn transMacroFnDefine(c: *Context, it: *CTokenList.Iterator, source: []const u8,
53385339 .{@tagName(last.id)},
53395340 );
53405341 _ = try appendToken(c, .Semicolon, ";");
5341 const type_of_arg = if (expr.id != .Block) expr else blk: {
5342 const type_of_arg = if (expr.tag != .Block) expr else blk: {
53425343 const blk = @fieldParentPtr(ast.Node.Block, "base", expr);
53435344 const blk_last = blk.statements()[blk.statements_len - 1];
5344 std.debug.assert(blk_last.id == .ControlFlowExpression);
5345 std.debug.assert(blk_last.tag == .ControlFlowExpression);
53455346 const br = @fieldParentPtr(ast.Node.ControlFlowExpression, "base", blk_last);
53465347 break :blk br.rhs.?;
53475348 };
......@@ -5788,7 +5789,7 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
57885789
57895790fn macroBoolToInt(c: *Context, node: *ast.Node) !*ast.Node {
57905791 if (!isBoolRes(node)) {
5791 if (node.id != .InfixOp) return node;
5792 if (node.tag != .InfixOp) return node;
57925793
57935794 const group_node = try c.arena.create(ast.Node.GroupedExpression);
57945795 group_node.* = .{
......@@ -5807,7 +5808,7 @@ fn macroBoolToInt(c: *Context, node: *ast.Node) !*ast.Node {
58075808
58085809fn macroIntToBool(c: *Context, node: *ast.Node) !*ast.Node {
58095810 if (isBoolRes(node)) {
5810 if (node.id != .InfixOp) return node;
5811 if (node.tag != .InfixOp) return node;
58115812
58125813 const group_node = try c.arena.create(ast.Node.GroupedExpression);
58135814 group_node.* = .{
......@@ -6105,7 +6106,7 @@ fn tokenSlice(c: *Context, token: ast.TokenIndex) []u8 {
61056106}
61066107
61076108fn getContainer(c: *Context, node: *ast.Node) ?*ast.Node {
6108 switch (node.id) {
6109 switch (node.tag) {
61096110 .ContainerDecl,
61106111 .AddressOf,
61116112 .Await,
......@@ -6182,7 +6183,7 @@ fn getContainerTypeOf(c: *Context, ref: *ast.Node) ?*ast.Node {
61826183fn getFnProto(c: *Context, ref: *ast.Node) ?*ast.Node.FnProto {
61836184 const init = if (ref.cast(ast.Node.VarDecl)) |v| v.getTrailer("init_node").? else return null;
61846185 if (getContainerTypeOf(c, init)) |ty_node| {
6185 if (ty_node.cast(ast.Node.OptionalType)) |prefix| {
6186 if (ty_node.castTag(.OptionalType)) |prefix| {
61866187 if (prefix.rhs.cast(ast.Node.FnProto)) |fn_proto| {
61876188 return fn_proto;
61886189 }