| author | |
| committer | |
| log | f11909227312882f29dbfc484dc79ab622792787 |
| tree | 3f327f4d16c32034cb1eea79dfaeadfef6303d9b |
| parent | e70d6d19f5a937504ce0e2f79d03a6275b6ff357 |
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) { |
| 323 | 323 | node: *Node, |
| 324 | 324 | |
| 325 | 325 | 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), | |
| 328 | 328 | }); |
| 329 | 329 | } |
| 330 | 330 | }; |
| ... | ... | @@ -333,8 +333,8 @@ pub const Error = union(enum) { |
| 333 | 333 | node: *Node, |
| 334 | 334 | |
| 335 | 335 | 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)}); | |
| 338 | 338 | } |
| 339 | 339 | }; |
| 340 | 340 | |
| ... | ... | @@ -396,9 +396,9 @@ pub const Error = union(enum) { |
| 396 | 396 | }; |
| 397 | 397 | |
| 398 | 398 | pub const Node = struct { |
| 399 | id: Id, | |
| 399 | tag: Tag, | |
| 400 | 400 | |
| 401 | pub const Id = enum { | |
| 401 | pub const Tag = enum { | |
| 402 | 402 | // Top level |
| 403 | 403 | Root, |
| 404 | 404 | Use, |
| ... | ... | @@ -484,49 +484,129 @@ pub const Node = struct { |
| 484 | 484 | ContainerField, |
| 485 | 485 | ErrorTag, |
| 486 | 486 | 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 | } | |
| 487 | 559 | }; |
| 488 | 560 | |
| 561 | /// Prefer `castTag` to this. | |
| 489 | 562 | 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); | |
| 492 | 581 | } |
| 493 | 582 | return null; |
| 494 | 583 | } |
| 495 | 584 | |
| 496 | 585 | 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); | |
| 501 | 590 | } |
| 502 | 591 | } |
| 503 | 592 | unreachable; |
| 504 | 593 | } |
| 505 | 594 | |
| 506 | 595 | 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(); | |
| 511 | 600 | } |
| 512 | 601 | } |
| 513 | 602 | unreachable; |
| 514 | 603 | } |
| 515 | 604 | |
| 516 | 605 | 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(); | |
| 530 | 610 | } |
| 531 | 611 | } |
| 532 | 612 | unreachable; |
| ... | ... | @@ -535,7 +615,7 @@ pub const Node = struct { |
| 535 | 615 | pub fn requireSemiColon(base: *const Node) bool { |
| 536 | 616 | var n = base; |
| 537 | 617 | while (true) { |
| 538 | switch (n.id) { | |
| 618 | switch (n.tag) { | |
| 539 | 619 | .Root, |
| 540 | 620 | .ContainerField, |
| 541 | 621 | .Block, |
| ... | ... | @@ -556,7 +636,7 @@ pub const Node = struct { |
| 556 | 636 | continue; |
| 557 | 637 | } |
| 558 | 638 | |
| 559 | return while_node.body.id != .Block; | |
| 639 | return while_node.body.tag != .Block; | |
| 560 | 640 | }, |
| 561 | 641 | .For => { |
| 562 | 642 | const for_node = @fieldParentPtr(For, "base", n); |
| ... | ... | @@ -565,7 +645,7 @@ pub const Node = struct { |
| 565 | 645 | continue; |
| 566 | 646 | } |
| 567 | 647 | |
| 568 | return for_node.body.id != .Block; | |
| 648 | return for_node.body.tag != .Block; | |
| 569 | 649 | }, |
| 570 | 650 | .If => { |
| 571 | 651 | const if_node = @fieldParentPtr(If, "base", n); |
| ... | ... | @@ -574,7 +654,7 @@ pub const Node = struct { |
| 574 | 654 | continue; |
| 575 | 655 | } |
| 576 | 656 | |
| 577 | return if_node.body.id != .Block; | |
| 657 | return if_node.body.tag != .Block; | |
| 578 | 658 | }, |
| 579 | 659 | .Else => { |
| 580 | 660 | const else_node = @fieldParentPtr(Else, "base", n); |
| ... | ... | @@ -583,23 +663,23 @@ pub const Node = struct { |
| 583 | 663 | }, |
| 584 | 664 | .Defer => { |
| 585 | 665 | const defer_node = @fieldParentPtr(Defer, "base", n); |
| 586 | return defer_node.expr.id != .Block; | |
| 666 | return defer_node.expr.tag != .Block; | |
| 587 | 667 | }, |
| 588 | 668 | .Comptime => { |
| 589 | 669 | const comptime_node = @fieldParentPtr(Comptime, "base", n); |
| 590 | return comptime_node.expr.id != .Block; | |
| 670 | return comptime_node.expr.tag != .Block; | |
| 591 | 671 | }, |
| 592 | 672 | .Suspend => { |
| 593 | 673 | const suspend_node = @fieldParentPtr(Suspend, "base", n); |
| 594 | 674 | if (suspend_node.body) |body| { |
| 595 | return body.id != .Block; | |
| 675 | return body.tag != .Block; | |
| 596 | 676 | } |
| 597 | 677 | |
| 598 | 678 | return true; |
| 599 | 679 | }, |
| 600 | 680 | .Nosuspend => { |
| 601 | 681 | const nosuspend_node = @fieldParentPtr(Nosuspend, "base", n); |
| 602 | return nosuspend_node.expr.id != .Block; | |
| 682 | return nosuspend_node.expr.tag != .Block; | |
| 603 | 683 | }, |
| 604 | 684 | else => return true, |
| 605 | 685 | } |
| ... | ... | @@ -613,7 +693,7 @@ pub const Node = struct { |
| 613 | 693 | std.debug.warn(" ", .{}); |
| 614 | 694 | } |
| 615 | 695 | } |
| 616 | std.debug.warn("{}\n", .{@tagName(self.id)}); | |
| 696 | std.debug.warn("{}\n", .{@tagName(self.tag)}); | |
| 617 | 697 | |
| 618 | 698 | var child_i: usize = 0; |
| 619 | 699 | while (self.iterate(child_i)) |child| : (child_i += 1) { |
| ... | ... | @@ -623,7 +703,7 @@ pub const Node = struct { |
| 623 | 703 | |
| 624 | 704 | /// The decls data follows this struct in memory as an array of Node pointers. |
| 625 | 705 | pub const Root = struct { |
| 626 | base: Node = Node{ .id = .Root }, | |
| 706 | base: Node = Node{ .tag = .Root }, | |
| 627 | 707 | eof_token: TokenIndex, |
| 628 | 708 | decls_len: NodeIndex, |
| 629 | 709 | |
| ... | ... | @@ -678,7 +758,7 @@ pub const Node = struct { |
| 678 | 758 | /// Trailed in memory by possibly many things, with each optional thing |
| 679 | 759 | /// determined by a bit in `trailer_flags`. |
| 680 | 760 | pub const VarDecl = struct { |
| 681 | base: Node = Node{ .id = .VarDecl }, | |
| 761 | base: Node = Node{ .tag = .VarDecl }, | |
| 682 | 762 | trailer_flags: TrailerFlags, |
| 683 | 763 | mut_token: TokenIndex, |
| 684 | 764 | name_token: TokenIndex, |
| ... | ... | @@ -779,7 +859,7 @@ pub const Node = struct { |
| 779 | 859 | }; |
| 780 | 860 | |
| 781 | 861 | pub const Use = struct { |
| 782 | base: Node = Node{ .id = .Use }, | |
| 862 | base: Node = Node{ .tag = .Use }, | |
| 783 | 863 | doc_comments: ?*DocComment, |
| 784 | 864 | visib_token: ?TokenIndex, |
| 785 | 865 | use_token: TokenIndex, |
| ... | ... | @@ -806,7 +886,7 @@ pub const Node = struct { |
| 806 | 886 | }; |
| 807 | 887 | |
| 808 | 888 | pub const ErrorSetDecl = struct { |
| 809 | base: Node = Node{ .id = .ErrorSetDecl }, | |
| 889 | base: Node = Node{ .tag = .ErrorSetDecl }, | |
| 810 | 890 | error_token: TokenIndex, |
| 811 | 891 | rbrace_token: TokenIndex, |
| 812 | 892 | decls_len: NodeIndex, |
| ... | ... | @@ -856,7 +936,7 @@ pub const Node = struct { |
| 856 | 936 | |
| 857 | 937 | /// The fields and decls Node pointers directly follow this struct in memory. |
| 858 | 938 | pub const ContainerDecl = struct { |
| 859 | base: Node = Node{ .id = .ContainerDecl }, | |
| 939 | base: Node = Node{ .tag = .ContainerDecl }, | |
| 860 | 940 | kind_token: TokenIndex, |
| 861 | 941 | layout_token: ?TokenIndex, |
| 862 | 942 | lbrace_token: TokenIndex, |
| ... | ... | @@ -925,7 +1005,7 @@ pub const Node = struct { |
| 925 | 1005 | }; |
| 926 | 1006 | |
| 927 | 1007 | pub const ContainerField = struct { |
| 928 | base: Node = Node{ .id = .ContainerField }, | |
| 1008 | base: Node = Node{ .tag = .ContainerField }, | |
| 929 | 1009 | doc_comments: ?*DocComment, |
| 930 | 1010 | comptime_token: ?TokenIndex, |
| 931 | 1011 | name_token: TokenIndex, |
| ... | ... | @@ -976,7 +1056,7 @@ pub const Node = struct { |
| 976 | 1056 | }; |
| 977 | 1057 | |
| 978 | 1058 | pub const ErrorTag = struct { |
| 979 | base: Node = Node{ .id = .ErrorTag }, | |
| 1059 | base: Node = Node{ .tag = .ErrorTag }, | |
| 980 | 1060 | doc_comments: ?*DocComment, |
| 981 | 1061 | name_token: TokenIndex, |
| 982 | 1062 | |
| ... | ... | @@ -1001,7 +1081,7 @@ pub const Node = struct { |
| 1001 | 1081 | }; |
| 1002 | 1082 | |
| 1003 | 1083 | pub const Identifier = struct { |
| 1004 | base: Node = Node{ .id = .Identifier }, | |
| 1084 | base: Node = Node{ .tag = .Identifier }, | |
| 1005 | 1085 | token: TokenIndex, |
| 1006 | 1086 | |
| 1007 | 1087 | pub fn iterate(self: *const Identifier, index: usize) ?*Node { |
| ... | ... | @@ -1020,7 +1100,7 @@ pub const Node = struct { |
| 1020 | 1100 | /// The params are directly after the FnProto in memory. |
| 1021 | 1101 | /// Next, each optional thing determined by a bit in `trailer_flags`. |
| 1022 | 1102 | pub const FnProto = struct { |
| 1023 | base: Node = Node{ .id = .FnProto }, | |
| 1103 | base: Node = Node{ .tag = .FnProto }, | |
| 1024 | 1104 | trailer_flags: TrailerFlags, |
| 1025 | 1105 | fn_token: TokenIndex, |
| 1026 | 1106 | params_len: NodeIndex, |
| ... | ... | @@ -1230,7 +1310,7 @@ pub const Node = struct { |
| 1230 | 1310 | }; |
| 1231 | 1311 | |
| 1232 | 1312 | pub const AnyFrameType = struct { |
| 1233 | base: Node = Node{ .id = .AnyFrameType }, | |
| 1313 | base: Node = Node{ .tag = .AnyFrameType }, | |
| 1234 | 1314 | anyframe_token: TokenIndex, |
| 1235 | 1315 | result: ?Result, |
| 1236 | 1316 | |
| ... | ... | @@ -1262,7 +1342,7 @@ pub const Node = struct { |
| 1262 | 1342 | |
| 1263 | 1343 | /// The statements of the block follow Block directly in memory. |
| 1264 | 1344 | pub const Block = struct { |
| 1265 | base: Node = Node{ .id = .Block }, | |
| 1345 | base: Node = Node{ .tag = .Block }, | |
| 1266 | 1346 | statements_len: NodeIndex, |
| 1267 | 1347 | lbrace: TokenIndex, |
| 1268 | 1348 | rbrace: TokenIndex, |
| ... | ... | @@ -1316,7 +1396,7 @@ pub const Node = struct { |
| 1316 | 1396 | }; |
| 1317 | 1397 | |
| 1318 | 1398 | pub const Defer = struct { |
| 1319 | base: Node = Node{ .id = .Defer }, | |
| 1399 | base: Node = Node{ .tag = .Defer }, | |
| 1320 | 1400 | defer_token: TokenIndex, |
| 1321 | 1401 | payload: ?*Node, |
| 1322 | 1402 | expr: *Node, |
| ... | ... | @@ -1340,7 +1420,7 @@ pub const Node = struct { |
| 1340 | 1420 | }; |
| 1341 | 1421 | |
| 1342 | 1422 | pub const Comptime = struct { |
| 1343 | base: Node = Node{ .id = .Comptime }, | |
| 1423 | base: Node = Node{ .tag = .Comptime }, | |
| 1344 | 1424 | doc_comments: ?*DocComment, |
| 1345 | 1425 | comptime_token: TokenIndex, |
| 1346 | 1426 | expr: *Node, |
| ... | ... | @@ -1364,7 +1444,7 @@ pub const Node = struct { |
| 1364 | 1444 | }; |
| 1365 | 1445 | |
| 1366 | 1446 | pub const Nosuspend = struct { |
| 1367 | base: Node = Node{ .id = .Nosuspend }, | |
| 1447 | base: Node = Node{ .tag = .Nosuspend }, | |
| 1368 | 1448 | nosuspend_token: TokenIndex, |
| 1369 | 1449 | expr: *Node, |
| 1370 | 1450 | |
| ... | ... | @@ -1387,7 +1467,7 @@ pub const Node = struct { |
| 1387 | 1467 | }; |
| 1388 | 1468 | |
| 1389 | 1469 | pub const Payload = struct { |
| 1390 | base: Node = Node{ .id = .Payload }, | |
| 1470 | base: Node = Node{ .tag = .Payload }, | |
| 1391 | 1471 | lpipe: TokenIndex, |
| 1392 | 1472 | error_symbol: *Node, |
| 1393 | 1473 | rpipe: TokenIndex, |
| ... | ... | @@ -1411,7 +1491,7 @@ pub const Node = struct { |
| 1411 | 1491 | }; |
| 1412 | 1492 | |
| 1413 | 1493 | pub const PointerPayload = struct { |
| 1414 | base: Node = Node{ .id = .PointerPayload }, | |
| 1494 | base: Node = Node{ .tag = .PointerPayload }, | |
| 1415 | 1495 | lpipe: TokenIndex, |
| 1416 | 1496 | ptr_token: ?TokenIndex, |
| 1417 | 1497 | value_symbol: *Node, |
| ... | ... | @@ -1436,7 +1516,7 @@ pub const Node = struct { |
| 1436 | 1516 | }; |
| 1437 | 1517 | |
| 1438 | 1518 | pub const PointerIndexPayload = struct { |
| 1439 | base: Node = Node{ .id = .PointerIndexPayload }, | |
| 1519 | base: Node = Node{ .tag = .PointerIndexPayload }, | |
| 1440 | 1520 | lpipe: TokenIndex, |
| 1441 | 1521 | ptr_token: ?TokenIndex, |
| 1442 | 1522 | value_symbol: *Node, |
| ... | ... | @@ -1467,7 +1547,7 @@ pub const Node = struct { |
| 1467 | 1547 | }; |
| 1468 | 1548 | |
| 1469 | 1549 | pub const Else = struct { |
| 1470 | base: Node = Node{ .id = .Else }, | |
| 1550 | base: Node = Node{ .tag = .Else }, | |
| 1471 | 1551 | else_token: TokenIndex, |
| 1472 | 1552 | payload: ?*Node, |
| 1473 | 1553 | body: *Node, |
| ... | ... | @@ -1498,7 +1578,7 @@ pub const Node = struct { |
| 1498 | 1578 | /// The cases node pointers are found in memory after Switch. |
| 1499 | 1579 | /// They must be SwitchCase or SwitchElse nodes. |
| 1500 | 1580 | pub const Switch = struct { |
| 1501 | base: Node = Node{ .id = .Switch }, | |
| 1581 | base: Node = Node{ .tag = .Switch }, | |
| 1502 | 1582 | switch_token: TokenIndex, |
| 1503 | 1583 | rbrace: TokenIndex, |
| 1504 | 1584 | cases_len: NodeIndex, |
| ... | ... | @@ -1552,7 +1632,7 @@ pub const Node = struct { |
| 1552 | 1632 | |
| 1553 | 1633 | /// Items sub-nodes appear in memory directly following SwitchCase. |
| 1554 | 1634 | pub const SwitchCase = struct { |
| 1555 | base: Node = Node{ .id = .SwitchCase }, | |
| 1635 | base: Node = Node{ .tag = .SwitchCase }, | |
| 1556 | 1636 | arrow_token: TokenIndex, |
| 1557 | 1637 | payload: ?*Node, |
| 1558 | 1638 | expr: *Node, |
| ... | ... | @@ -1610,7 +1690,7 @@ pub const Node = struct { |
| 1610 | 1690 | }; |
| 1611 | 1691 | |
| 1612 | 1692 | pub const SwitchElse = struct { |
| 1613 | base: Node = Node{ .id = .SwitchElse }, | |
| 1693 | base: Node = Node{ .tag = .SwitchElse }, | |
| 1614 | 1694 | token: TokenIndex, |
| 1615 | 1695 | |
| 1616 | 1696 | pub fn iterate(self: *const SwitchElse, index: usize) ?*Node { |
| ... | ... | @@ -1627,7 +1707,7 @@ pub const Node = struct { |
| 1627 | 1707 | }; |
| 1628 | 1708 | |
| 1629 | 1709 | pub const While = struct { |
| 1630 | base: Node = Node{ .id = .While }, | |
| 1710 | base: Node = Node{ .tag = .While }, | |
| 1631 | 1711 | label: ?TokenIndex, |
| 1632 | 1712 | inline_token: ?TokenIndex, |
| 1633 | 1713 | while_token: TokenIndex, |
| ... | ... | @@ -1686,7 +1766,7 @@ pub const Node = struct { |
| 1686 | 1766 | }; |
| 1687 | 1767 | |
| 1688 | 1768 | pub const For = struct { |
| 1689 | base: Node = Node{ .id = .For }, | |
| 1769 | base: Node = Node{ .tag = .For }, | |
| 1690 | 1770 | label: ?TokenIndex, |
| 1691 | 1771 | inline_token: ?TokenIndex, |
| 1692 | 1772 | for_token: TokenIndex, |
| ... | ... | @@ -1737,7 +1817,7 @@ pub const Node = struct { |
| 1737 | 1817 | }; |
| 1738 | 1818 | |
| 1739 | 1819 | pub const If = struct { |
| 1740 | base: Node = Node{ .id = .If }, | |
| 1820 | base: Node = Node{ .tag = .If }, | |
| 1741 | 1821 | if_token: TokenIndex, |
| 1742 | 1822 | condition: *Node, |
| 1743 | 1823 | payload: ?*Node, |
| ... | ... | @@ -1779,8 +1859,9 @@ pub const Node = struct { |
| 1779 | 1859 | } |
| 1780 | 1860 | }; |
| 1781 | 1861 | |
| 1862 | /// TODO split up and make every op its own AST Node tag | |
| 1782 | 1863 | pub const InfixOp = struct { |
| 1783 | base: Node = Node{ .id = .InfixOp }, | |
| 1864 | base: Node = Node{ .tag = .InfixOp }, | |
| 1784 | 1865 | op_token: TokenIndex, |
| 1785 | 1866 | lhs: *Node, |
| 1786 | 1867 | op: Op, |
| ... | ... | @@ -1906,41 +1987,29 @@ pub const Node = struct { |
| 1906 | 1987 | } |
| 1907 | 1988 | }; |
| 1908 | 1989 | |
| 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, | |
| 1924 | 1994 | |
| 1925 | const Self = @This(); | |
| 1995 | const Self = @This(); | |
| 1926 | 1996 | |
| 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 | } | |
| 1931 | 2001 | |
| 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 | } | |
| 1935 | 2005 | |
| 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 | }; | |
| 1941 | 2010 | |
| 1942 | 2011 | pub const ArrayType = struct { |
| 1943 | base: Node = Node{ .id = .ArrayType }, | |
| 2012 | base: Node = Node{ .tag = .ArrayType }, | |
| 1944 | 2013 | op_token: TokenIndex, |
| 1945 | 2014 | rhs: *Node, |
| 1946 | 2015 | len_expr: *Node, |
| ... | ... | @@ -1967,7 +2036,7 @@ pub const Node = struct { |
| 1967 | 2036 | }; |
| 1968 | 2037 | |
| 1969 | 2038 | pub const ArrayTypeSentinel = struct { |
| 1970 | base: Node = Node{ .id = .ArrayTypeSentinel }, | |
| 2039 | base: Node = Node{ .tag = .ArrayTypeSentinel }, | |
| 1971 | 2040 | op_token: TokenIndex, |
| 1972 | 2041 | rhs: *Node, |
| 1973 | 2042 | len_expr: *Node, |
| ... | ... | @@ -1998,7 +2067,7 @@ pub const Node = struct { |
| 1998 | 2067 | }; |
| 1999 | 2068 | |
| 2000 | 2069 | pub const PtrType = struct { |
| 2001 | base: Node = Node{ .id = .PtrType }, | |
| 2070 | base: Node = Node{ .tag = .PtrType }, | |
| 2002 | 2071 | op_token: TokenIndex, |
| 2003 | 2072 | rhs: *Node, |
| 2004 | 2073 | /// 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 { |
| 2034 | 2103 | }; |
| 2035 | 2104 | |
| 2036 | 2105 | pub const SliceType = struct { |
| 2037 | base: Node = Node{ .id = .SliceType }, | |
| 2106 | base: Node = Node{ .tag = .SliceType }, | |
| 2038 | 2107 | op_token: TokenIndex, |
| 2039 | 2108 | rhs: *Node, |
| 2040 | 2109 | /// 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 { |
| 2070 | 2139 | }; |
| 2071 | 2140 | |
| 2072 | 2141 | pub const FieldInitializer = struct { |
| 2073 | base: Node = Node{ .id = .FieldInitializer }, | |
| 2142 | base: Node = Node{ .tag = .FieldInitializer }, | |
| 2074 | 2143 | period_token: TokenIndex, |
| 2075 | 2144 | name_token: TokenIndex, |
| 2076 | 2145 | expr: *Node, |
| ... | ... | @@ -2095,7 +2164,7 @@ pub const Node = struct { |
| 2095 | 2164 | |
| 2096 | 2165 | /// Elements occur directly in memory after ArrayInitializer. |
| 2097 | 2166 | pub const ArrayInitializer = struct { |
| 2098 | base: Node = Node{ .id = .ArrayInitializer }, | |
| 2167 | base: Node = Node{ .tag = .ArrayInitializer }, | |
| 2099 | 2168 | rtoken: TokenIndex, |
| 2100 | 2169 | list_len: NodeIndex, |
| 2101 | 2170 | lhs: *Node, |
| ... | ... | @@ -2148,7 +2217,7 @@ pub const Node = struct { |
| 2148 | 2217 | |
| 2149 | 2218 | /// Elements occur directly in memory after ArrayInitializerDot. |
| 2150 | 2219 | pub const ArrayInitializerDot = struct { |
| 2151 | base: Node = Node{ .id = .ArrayInitializerDot }, | |
| 2220 | base: Node = Node{ .tag = .ArrayInitializerDot }, | |
| 2152 | 2221 | dot: TokenIndex, |
| 2153 | 2222 | rtoken: TokenIndex, |
| 2154 | 2223 | list_len: NodeIndex, |
| ... | ... | @@ -2198,7 +2267,7 @@ pub const Node = struct { |
| 2198 | 2267 | |
| 2199 | 2268 | /// Elements occur directly in memory after StructInitializer. |
| 2200 | 2269 | pub const StructInitializer = struct { |
| 2201 | base: Node = Node{ .id = .StructInitializer }, | |
| 2270 | base: Node = Node{ .tag = .StructInitializer }, | |
| 2202 | 2271 | rtoken: TokenIndex, |
| 2203 | 2272 | list_len: NodeIndex, |
| 2204 | 2273 | lhs: *Node, |
| ... | ... | @@ -2251,7 +2320,7 @@ pub const Node = struct { |
| 2251 | 2320 | |
| 2252 | 2321 | /// Elements occur directly in memory after StructInitializerDot. |
| 2253 | 2322 | pub const StructInitializerDot = struct { |
| 2254 | base: Node = Node{ .id = .StructInitializerDot }, | |
| 2323 | base: Node = Node{ .tag = .StructInitializerDot }, | |
| 2255 | 2324 | dot: TokenIndex, |
| 2256 | 2325 | rtoken: TokenIndex, |
| 2257 | 2326 | list_len: NodeIndex, |
| ... | ... | @@ -2301,7 +2370,7 @@ pub const Node = struct { |
| 2301 | 2370 | |
| 2302 | 2371 | /// Parameter nodes directly follow Call in memory. |
| 2303 | 2372 | pub const Call = struct { |
| 2304 | base: Node = Node{ .id = .Call }, | |
| 2373 | base: Node = Node{ .tag = .Call }, | |
| 2305 | 2374 | lhs: *Node, |
| 2306 | 2375 | rtoken: TokenIndex, |
| 2307 | 2376 | params_len: NodeIndex, |
| ... | ... | @@ -2355,7 +2424,7 @@ pub const Node = struct { |
| 2355 | 2424 | }; |
| 2356 | 2425 | |
| 2357 | 2426 | pub const SuffixOp = struct { |
| 2358 | base: Node = Node{ .id = .SuffixOp }, | |
| 2427 | base: Node = Node{ .tag = .SuffixOp }, | |
| 2359 | 2428 | op: Op, |
| 2360 | 2429 | lhs: *Node, |
| 2361 | 2430 | rtoken: TokenIndex, |
| ... | ... | @@ -2415,7 +2484,7 @@ pub const Node = struct { |
| 2415 | 2484 | }; |
| 2416 | 2485 | |
| 2417 | 2486 | pub const GroupedExpression = struct { |
| 2418 | base: Node = Node{ .id = .GroupedExpression }, | |
| 2487 | base: Node = Node{ .tag = .GroupedExpression }, | |
| 2419 | 2488 | lparen: TokenIndex, |
| 2420 | 2489 | expr: *Node, |
| 2421 | 2490 | rparen: TokenIndex, |
| ... | ... | @@ -2441,7 +2510,7 @@ pub const Node = struct { |
| 2441 | 2510 | /// TODO break this into separate Break, Continue, Return AST Nodes to save memory. |
| 2442 | 2511 | /// Could be further broken into LabeledBreak, LabeledContinue, and ReturnVoid to save even more. |
| 2443 | 2512 | pub const ControlFlowExpression = struct { |
| 2444 | base: Node = Node{ .id = .ControlFlowExpression }, | |
| 2513 | base: Node = Node{ .tag = .ControlFlowExpression }, | |
| 2445 | 2514 | ltoken: TokenIndex, |
| 2446 | 2515 | kind: Kind, |
| 2447 | 2516 | rhs: ?*Node, |
| ... | ... | @@ -2496,7 +2565,7 @@ pub const Node = struct { |
| 2496 | 2565 | }; |
| 2497 | 2566 | |
| 2498 | 2567 | pub const Suspend = struct { |
| 2499 | base: Node = Node{ .id = .Suspend }, | |
| 2568 | base: Node = Node{ .tag = .Suspend }, | |
| 2500 | 2569 | suspend_token: TokenIndex, |
| 2501 | 2570 | body: ?*Node, |
| 2502 | 2571 | |
| ... | ... | @@ -2525,7 +2594,7 @@ pub const Node = struct { |
| 2525 | 2594 | }; |
| 2526 | 2595 | |
| 2527 | 2596 | pub const IntegerLiteral = struct { |
| 2528 | base: Node = Node{ .id = .IntegerLiteral }, | |
| 2597 | base: Node = Node{ .tag = .IntegerLiteral }, | |
| 2529 | 2598 | token: TokenIndex, |
| 2530 | 2599 | |
| 2531 | 2600 | pub fn iterate(self: *const IntegerLiteral, index: usize) ?*Node { |
| ... | ... | @@ -2542,7 +2611,7 @@ pub const Node = struct { |
| 2542 | 2611 | }; |
| 2543 | 2612 | |
| 2544 | 2613 | pub const EnumLiteral = struct { |
| 2545 | base: Node = Node{ .id = .EnumLiteral }, | |
| 2614 | base: Node = Node{ .tag = .EnumLiteral }, | |
| 2546 | 2615 | dot: TokenIndex, |
| 2547 | 2616 | name: TokenIndex, |
| 2548 | 2617 | |
| ... | ... | @@ -2560,7 +2629,7 @@ pub const Node = struct { |
| 2560 | 2629 | }; |
| 2561 | 2630 | |
| 2562 | 2631 | pub const FloatLiteral = struct { |
| 2563 | base: Node = Node{ .id = .FloatLiteral }, | |
| 2632 | base: Node = Node{ .tag = .FloatLiteral }, | |
| 2564 | 2633 | token: TokenIndex, |
| 2565 | 2634 | |
| 2566 | 2635 | pub fn iterate(self: *const FloatLiteral, index: usize) ?*Node { |
| ... | ... | @@ -2578,7 +2647,7 @@ pub const Node = struct { |
| 2578 | 2647 | |
| 2579 | 2648 | /// Parameters are in memory following BuiltinCall. |
| 2580 | 2649 | pub const BuiltinCall = struct { |
| 2581 | base: Node = Node{ .id = .BuiltinCall }, | |
| 2650 | base: Node = Node{ .tag = .BuiltinCall }, | |
| 2582 | 2651 | params_len: NodeIndex, |
| 2583 | 2652 | builtin_token: TokenIndex, |
| 2584 | 2653 | rparen_token: TokenIndex, |
| ... | ... | @@ -2627,7 +2696,7 @@ pub const Node = struct { |
| 2627 | 2696 | }; |
| 2628 | 2697 | |
| 2629 | 2698 | pub const StringLiteral = struct { |
| 2630 | base: Node = Node{ .id = .StringLiteral }, | |
| 2699 | base: Node = Node{ .tag = .StringLiteral }, | |
| 2631 | 2700 | token: TokenIndex, |
| 2632 | 2701 | |
| 2633 | 2702 | pub fn iterate(self: *const StringLiteral, index: usize) ?*Node { |
| ... | ... | @@ -2645,7 +2714,7 @@ pub const Node = struct { |
| 2645 | 2714 | |
| 2646 | 2715 | /// The string literal tokens appear directly in memory after MultilineStringLiteral. |
| 2647 | 2716 | pub const MultilineStringLiteral = struct { |
| 2648 | base: Node = Node{ .id = .MultilineStringLiteral }, | |
| 2717 | base: Node = Node{ .tag = .MultilineStringLiteral }, | |
| 2649 | 2718 | lines_len: TokenIndex, |
| 2650 | 2719 | |
| 2651 | 2720 | /// After this the caller must initialize the lines list. |
| ... | ... | @@ -2687,7 +2756,7 @@ pub const Node = struct { |
| 2687 | 2756 | }; |
| 2688 | 2757 | |
| 2689 | 2758 | pub const CharLiteral = struct { |
| 2690 | base: Node = Node{ .id = .CharLiteral }, | |
| 2759 | base: Node = Node{ .tag = .CharLiteral }, | |
| 2691 | 2760 | token: TokenIndex, |
| 2692 | 2761 | |
| 2693 | 2762 | pub fn iterate(self: *const CharLiteral, index: usize) ?*Node { |
| ... | ... | @@ -2704,7 +2773,7 @@ pub const Node = struct { |
| 2704 | 2773 | }; |
| 2705 | 2774 | |
| 2706 | 2775 | pub const BoolLiteral = struct { |
| 2707 | base: Node = Node{ .id = .BoolLiteral }, | |
| 2776 | base: Node = Node{ .tag = .BoolLiteral }, | |
| 2708 | 2777 | token: TokenIndex, |
| 2709 | 2778 | |
| 2710 | 2779 | pub fn iterate(self: *const BoolLiteral, index: usize) ?*Node { |
| ... | ... | @@ -2721,7 +2790,7 @@ pub const Node = struct { |
| 2721 | 2790 | }; |
| 2722 | 2791 | |
| 2723 | 2792 | pub const NullLiteral = struct { |
| 2724 | base: Node = Node{ .id = .NullLiteral }, | |
| 2793 | base: Node = Node{ .tag = .NullLiteral }, | |
| 2725 | 2794 | token: TokenIndex, |
| 2726 | 2795 | |
| 2727 | 2796 | pub fn iterate(self: *const NullLiteral, index: usize) ?*Node { |
| ... | ... | @@ -2738,7 +2807,7 @@ pub const Node = struct { |
| 2738 | 2807 | }; |
| 2739 | 2808 | |
| 2740 | 2809 | pub const UndefinedLiteral = struct { |
| 2741 | base: Node = Node{ .id = .UndefinedLiteral }, | |
| 2810 | base: Node = Node{ .tag = .UndefinedLiteral }, | |
| 2742 | 2811 | token: TokenIndex, |
| 2743 | 2812 | |
| 2744 | 2813 | pub fn iterate(self: *const UndefinedLiteral, index: usize) ?*Node { |
| ... | ... | @@ -2755,7 +2824,7 @@ pub const Node = struct { |
| 2755 | 2824 | }; |
| 2756 | 2825 | |
| 2757 | 2826 | pub const Asm = struct { |
| 2758 | base: Node = Node{ .id = .Asm }, | |
| 2827 | base: Node = Node{ .tag = .Asm }, | |
| 2759 | 2828 | asm_token: TokenIndex, |
| 2760 | 2829 | rparen: TokenIndex, |
| 2761 | 2830 | volatile_token: ?TokenIndex, |
| ... | ... | @@ -2875,7 +2944,7 @@ pub const Node = struct { |
| 2875 | 2944 | }; |
| 2876 | 2945 | |
| 2877 | 2946 | pub const Unreachable = struct { |
| 2878 | base: Node = Node{ .id = .Unreachable }, | |
| 2947 | base: Node = Node{ .tag = .Unreachable }, | |
| 2879 | 2948 | token: TokenIndex, |
| 2880 | 2949 | |
| 2881 | 2950 | pub fn iterate(self: *const Unreachable, index: usize) ?*Node { |
| ... | ... | @@ -2892,7 +2961,7 @@ pub const Node = struct { |
| 2892 | 2961 | }; |
| 2893 | 2962 | |
| 2894 | 2963 | pub const ErrorType = struct { |
| 2895 | base: Node = Node{ .id = .ErrorType }, | |
| 2964 | base: Node = Node{ .tag = .ErrorType }, | |
| 2896 | 2965 | token: TokenIndex, |
| 2897 | 2966 | |
| 2898 | 2967 | pub fn iterate(self: *const ErrorType, index: usize) ?*Node { |
| ... | ... | @@ -2909,7 +2978,7 @@ pub const Node = struct { |
| 2909 | 2978 | }; |
| 2910 | 2979 | |
| 2911 | 2980 | pub const AnyType = struct { |
| 2912 | base: Node = Node{ .id = .AnyType }, | |
| 2981 | base: Node = Node{ .tag = .AnyType }, | |
| 2913 | 2982 | token: TokenIndex, |
| 2914 | 2983 | |
| 2915 | 2984 | pub fn iterate(self: *const AnyType, index: usize) ?*Node { |
| ... | ... | @@ -2929,7 +2998,7 @@ pub const Node = struct { |
| 2929 | 2998 | /// TODO actually maybe remove entirely in favor of iterating backward from Node.firstToken() |
| 2930 | 2999 | /// and forwards to find same-line doc comments. |
| 2931 | 3000 | pub const DocComment = struct { |
| 2932 | base: Node = Node{ .id = .DocComment }, | |
| 3001 | base: Node = Node{ .tag = .DocComment }, | |
| 2933 | 3002 | /// Points to the first doc comment token. API users are expected to iterate over the |
| 2934 | 3003 | /// tokens array, looking for more doc comments, ignoring line comments, and stopping |
| 2935 | 3004 | /// at the first other token. |
| ... | ... | @@ -2951,7 +3020,7 @@ pub const Node = struct { |
| 2951 | 3020 | }; |
| 2952 | 3021 | |
| 2953 | 3022 | pub const TestDecl = struct { |
| 2954 | base: Node = Node{ .id = .TestDecl }, | |
| 3023 | base: Node = Node{ .tag = .TestDecl }, | |
| 2955 | 3024 | doc_comments: ?*DocComment, |
| 2956 | 3025 | test_token: TokenIndex, |
| 2957 | 3026 | name: *Node, |
| ... | ... | @@ -2996,7 +3065,7 @@ pub const PtrInfo = struct { |
| 2996 | 3065 | |
| 2997 | 3066 | test "iterate" { |
| 2998 | 3067 | var root = Node.Root{ |
| 2999 | .base = Node{ .id = Node.Id.Root }, | |
| 3068 | .base = Node{ .tag = Node.Tag.Root }, | |
| 3000 | 3069 | .decls_len = 0, |
| 3001 | 3070 | .eof_token = 0, |
| 3002 | 3071 | }; |
lib/std/zig/parse.zig+36-111| ... | ... | @@ -1128,8 +1128,9 @@ const Parser = struct { |
| 1128 | 1128 | const expr_node = try p.expectNode(parseExpr, .{ |
| 1129 | 1129 | .ExpectedExpr = .{ .token = p.tok_i }, |
| 1130 | 1130 | }); |
| 1131 | const node = try p.arena.allocator.create(Node.Resume); | |
| 1131 | const node = try p.arena.allocator.create(Node.SimplePrefixOp); | |
| 1132 | 1132 | node.* = .{ |
| 1133 | .base = .{ .tag = .Resume }, | |
| 1133 | 1134 | .op_token = token, |
| 1134 | 1135 | .rhs = expr_node, |
| 1135 | 1136 | }; |
| ... | ... | @@ -1439,7 +1440,7 @@ const Parser = struct { |
| 1439 | 1440 | }); |
| 1440 | 1441 | |
| 1441 | 1442 | while (try p.parseSuffixOp()) |node| { |
| 1442 | switch (node.id) { | |
| 1443 | switch (node.tag) { | |
| 1443 | 1444 | .SuffixOp => node.cast(Node.SuffixOp).?.lhs = res, |
| 1444 | 1445 | .InfixOp => node.cast(Node.InfixOp).?.lhs = res, |
| 1445 | 1446 | else => unreachable, |
| ... | ... | @@ -1470,7 +1471,7 @@ const Parser = struct { |
| 1470 | 1471 | |
| 1471 | 1472 | while (true) { |
| 1472 | 1473 | if (try p.parseSuffixOp()) |node| { |
| 1473 | switch (node.id) { | |
| 1474 | switch (node.tag) { | |
| 1474 | 1475 | .SuffixOp => node.cast(Node.SuffixOp).?.lhs = res, |
| 1475 | 1476 | .InfixOp => node.cast(Node.InfixOp).?.lhs = res, |
| 1476 | 1477 | else => unreachable, |
| ... | ... | @@ -1660,7 +1661,7 @@ const Parser = struct { |
| 1660 | 1661 | } |
| 1661 | 1662 | |
| 1662 | 1663 | if (try p.parseLoopTypeExpr()) |node| { |
| 1663 | switch (node.id) { | |
| 1664 | switch (node.tag) { | |
| 1664 | 1665 | .For => node.cast(Node.For).?.label = label, |
| 1665 | 1666 | .While => node.cast(Node.While).?.label = label, |
| 1666 | 1667 | else => unreachable, |
| ... | ... | @@ -2434,9 +2435,10 @@ const Parser = struct { |
| 2434 | 2435 | } |
| 2435 | 2436 | } |
| 2436 | 2437 | |
| 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); | |
| 2439 | 2440 | node.* = .{ |
| 2441 | .base = .{ .tag = tag }, | |
| 2440 | 2442 | .op_token = token, |
| 2441 | 2443 | .rhs = undefined, // set by caller |
| 2442 | 2444 | }; |
| ... | ... | @@ -2457,8 +2459,9 @@ const Parser = struct { |
| 2457 | 2459 | /// / PtrTypeStart (KEYWORD_align LPAREN Expr (COLON INTEGER COLON INTEGER)? RPAREN / KEYWORD_const / KEYWORD_volatile / KEYWORD_allowzero)* |
| 2458 | 2460 | fn parsePrefixTypeOp(p: *Parser) !?*Node { |
| 2459 | 2461 | 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); | |
| 2461 | 2463 | node.* = .{ |
| 2464 | .base = .{ .tag = .OptionalType }, | |
| 2462 | 2465 | .op_token = token, |
| 2463 | 2466 | .rhs = undefined, // set by caller |
| 2464 | 2467 | }; |
| ... | ... | @@ -3072,7 +3075,6 @@ const Parser = struct { |
| 3072 | 3075 | fn createLiteral(p: *Parser, comptime T: type, token: TokenIndex) !*Node { |
| 3073 | 3076 | const result = try p.arena.allocator.create(T); |
| 3074 | 3077 | result.* = T{ |
| 3075 | .base = Node{ .id = Node.typeToId(T) }, | |
| 3076 | 3078 | .token = token, |
| 3077 | 3079 | }; |
| 3078 | 3080 | return &result.base; |
| ... | ... | @@ -3148,8 +3150,9 @@ const Parser = struct { |
| 3148 | 3150 | |
| 3149 | 3151 | fn parseTry(p: *Parser) !?*Node { |
| 3150 | 3152 | 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); | |
| 3152 | 3154 | node.* = .{ |
| 3155 | .base = .{ .tag = .Try }, | |
| 3153 | 3156 | .op_token = token, |
| 3154 | 3157 | .rhs = undefined, // set by caller |
| 3155 | 3158 | }; |
| ... | ... | @@ -3213,58 +3216,19 @@ const Parser = struct { |
| 3213 | 3216 | if (try opParseFn(p)) |first_op| { |
| 3214 | 3217 | var rightmost_op = first_op; |
| 3215 | 3218 | 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 | => { | |
| 3218 | 3230 | 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; | |
| 3268 | 3232 | rightmost_op = rhs; |
| 3269 | 3233 | } else break; |
| 3270 | 3234 | }, |
| ... | ... | @@ -3310,57 +3274,18 @@ const Parser = struct { |
| 3310 | 3274 | } |
| 3311 | 3275 | |
| 3312 | 3276 | // 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).?; | |
| 3364 | 3289 | prefix_op.rhs = try p.expectNode(childParseFn, .{ |
| 3365 | 3290 | .InvalidToken = .{ .token = p.tok_i }, |
| 3366 | 3291 | }); |
lib/std/zig/render.zig+33-58| ... | ... | @@ -223,7 +223,7 @@ fn renderTopLevelDecl(allocator: *mem.Allocator, stream: anytype, tree: *ast.Tre |
| 223 | 223 | } |
| 224 | 224 | |
| 225 | 225 | 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 { |
| 226 | switch (decl.id) { | |
| 226 | switch (decl.tag) { | |
| 227 | 227 | .FnProto => { |
| 228 | 228 | const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl); |
| 229 | 229 | |
| ... | ... | @@ -365,7 +365,7 @@ fn renderExpression( |
| 365 | 365 | base: *ast.Node, |
| 366 | 366 | space: Space, |
| 367 | 367 | ) (@TypeOf(stream).Error || Error)!void { |
| 368 | switch (base.id) { | |
| 368 | switch (base.tag) { | |
| 369 | 369 | .Identifier => { |
| 370 | 370 | const identifier = @fieldParentPtr(ast.Node.Identifier, "base", base); |
| 371 | 371 | return renderToken(tree, stream, identifier.token, indent, start_col, space); |
| ... | ... | @@ -468,50 +468,25 @@ fn renderExpression( |
| 468 | 468 | return renderExpression(allocator, stream, tree, indent, start_col, infix_op_node.rhs, space); |
| 469 | 469 | }, |
| 470 | 470 | |
| 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); | |
| 475 | 481 | }, |
| 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); | |
| 515 | 490 | }, |
| 516 | 491 | |
| 517 | 492 | .ArrayType => { |
| ... | ... | @@ -659,7 +634,7 @@ fn renderExpression( |
| 659 | 634 | .ArrayInitializer, .ArrayInitializerDot => { |
| 660 | 635 | var rtoken: ast.TokenIndex = undefined; |
| 661 | 636 | 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) { | |
| 663 | 638 | .ArrayInitializerDot => blk: { |
| 664 | 639 | const casted = @fieldParentPtr(ast.Node.ArrayInitializerDot, "base", base); |
| 665 | 640 | rtoken = casted.rtoken; |
| ... | ... | @@ -793,14 +768,14 @@ fn renderExpression( |
| 793 | 768 | } |
| 794 | 769 | |
| 795 | 770 | try renderExtraNewline(tree, stream, start_col, next_expr); |
| 796 | if (next_expr.id != .MultilineStringLiteral) { | |
| 771 | if (next_expr.tag != .MultilineStringLiteral) { | |
| 797 | 772 | try stream.writeByteNTimes(' ', new_indent); |
| 798 | 773 | } |
| 799 | 774 | } else { |
| 800 | 775 | try renderExpression(allocator, stream, tree, new_indent, start_col, expr, Space.Comma); // , |
| 801 | 776 | } |
| 802 | 777 | } |
| 803 | if (exprs[exprs.len - 1].id != .MultilineStringLiteral) { | |
| 778 | if (exprs[exprs.len - 1].tag != .MultilineStringLiteral) { | |
| 804 | 779 | try stream.writeByteNTimes(' ', indent); |
| 805 | 780 | } |
| 806 | 781 | return renderToken(tree, stream, rtoken, indent, start_col, space); |
| ... | ... | @@ -823,7 +798,7 @@ fn renderExpression( |
| 823 | 798 | .StructInitializer, .StructInitializerDot => { |
| 824 | 799 | var rtoken: ast.TokenIndex = undefined; |
| 825 | 800 | 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) { | |
| 827 | 802 | .StructInitializerDot => blk: { |
| 828 | 803 | const casted = @fieldParentPtr(ast.Node.StructInitializerDot, "base", base); |
| 829 | 804 | rtoken = casted.rtoken; |
| ... | ... | @@ -877,7 +852,7 @@ fn renderExpression( |
| 877 | 852 | if (field_inits.len == 1) blk: { |
| 878 | 853 | const field_init = field_inits[0].cast(ast.Node.FieldInitializer).?; |
| 879 | 854 | |
| 880 | switch (field_init.expr.id) { | |
| 855 | switch (field_init.expr.tag) { | |
| 881 | 856 | .StructInitializer, |
| 882 | 857 | .StructInitializerDot, |
| 883 | 858 | => break :blk, |
| ... | ... | @@ -974,7 +949,7 @@ fn renderExpression( |
| 974 | 949 | |
| 975 | 950 | const params = call.params(); |
| 976 | 951 | 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: { | |
| 978 | 953 | break :blk indent; |
| 979 | 954 | } else blk: { |
| 980 | 955 | try stream.writeByteNTimes(' ', new_indent); |
| ... | ... | @@ -1284,7 +1259,7 @@ fn renderExpression( |
| 1284 | 1259 | // declarations inside are fields |
| 1285 | 1260 | const src_has_only_fields = blk: { |
| 1286 | 1261 | for (fields_and_decls) |decl| { |
| 1287 | if (decl.id != .ContainerField) break :blk false; | |
| 1262 | if (decl.tag != .ContainerField) break :blk false; | |
| 1288 | 1263 | } |
| 1289 | 1264 | break :blk true; |
| 1290 | 1265 | }; |
| ... | ... | @@ -1831,7 +1806,7 @@ fn renderExpression( |
| 1831 | 1806 | |
| 1832 | 1807 | const rparen = tree.nextToken(for_node.array_expr.lastToken()); |
| 1833 | 1808 | |
| 1834 | const body_is_block = for_node.body.id == .Block; | |
| 1809 | const body_is_block = for_node.body.tag == .Block; | |
| 1835 | 1810 | const src_one_line_to_body = !body_is_block and tree.tokensOnSameLine(rparen, for_node.body.firstToken()); |
| 1836 | 1811 | const body_on_same_line = body_is_block or src_one_line_to_body; |
| 1837 | 1812 | |
| ... | ... | @@ -1874,7 +1849,7 @@ fn renderExpression( |
| 1874 | 1849 | |
| 1875 | 1850 | try renderExpression(allocator, stream, tree, indent, start_col, if_node.condition, Space.None); // condition |
| 1876 | 1851 | |
| 1877 | const body_is_if_block = if_node.body.id == .If; | |
| 1852 | const body_is_if_block = if_node.body.tag == .If; | |
| 1878 | 1853 | const body_is_block = nodeIsBlock(if_node.body); |
| 1879 | 1854 | |
| 1880 | 1855 | if (body_is_if_block) { |
| ... | ... | @@ -1978,7 +1953,7 @@ fn renderExpression( |
| 1978 | 1953 | |
| 1979 | 1954 | const indent_once = indent + indent_delta; |
| 1980 | 1955 | |
| 1981 | if (asm_node.template.id == .MultilineStringLiteral) { | |
| 1956 | if (asm_node.template.tag == .MultilineStringLiteral) { | |
| 1982 | 1957 | // After rendering a multiline string literal the cursor is |
| 1983 | 1958 | // already offset by indent |
| 1984 | 1959 | try stream.writeByteNTimes(' ', indent_delta); |
| ... | ... | @@ -2245,7 +2220,7 @@ fn renderVarDecl( |
| 2245 | 2220 | } |
| 2246 | 2221 | |
| 2247 | 2222 | 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; | |
| 2249 | 2224 | try renderToken(tree, stream, var_decl.getTrailer("eq_token").?, indent, start_col, s); // = |
| 2250 | 2225 | try renderExpression(allocator, stream, tree, indent, start_col, init_node, Space.None); |
| 2251 | 2226 | } |
| ... | ... | @@ -2287,7 +2262,7 @@ fn renderStatement( |
| 2287 | 2262 | start_col: *usize, |
| 2288 | 2263 | base: *ast.Node, |
| 2289 | 2264 | ) (@TypeOf(stream).Error || Error)!void { |
| 2290 | switch (base.id) { | |
| 2265 | switch (base.tag) { | |
| 2291 | 2266 | .VarDecl => { |
| 2292 | 2267 | const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", base); |
| 2293 | 2268 | try renderVarDecl(allocator, stream, tree, indent, start_col, var_decl); |
| ... | ... | @@ -2566,7 +2541,7 @@ fn renderDocCommentsToken( |
| 2566 | 2541 | } |
| 2567 | 2542 | |
| 2568 | 2543 | fn nodeIsBlock(base: *const ast.Node) bool { |
| 2569 | return switch (base.id) { | |
| 2544 | return switch (base.tag) { | |
| 2570 | 2545 | .Block, |
| 2571 | 2546 | .If, |
| 2572 | 2547 | .For, |
src-self-hosted/Module.zig+43-1| ... | ... | @@ -212,6 +212,7 @@ pub const Decl = struct { |
| 212 | 212 | }, |
| 213 | 213 | .block => unreachable, |
| 214 | 214 | .gen_zir => unreachable, |
| 215 | .local_var => unreachable, | |
| 215 | 216 | .decl => unreachable, |
| 216 | 217 | } |
| 217 | 218 | } |
| ... | ... | @@ -307,6 +308,7 @@ pub const Scope = struct { |
| 307 | 308 | .block => return self.cast(Block).?.arena, |
| 308 | 309 | .decl => return &self.cast(DeclAnalysis).?.arena.allocator, |
| 309 | 310 | .gen_zir => return self.cast(GenZIR).?.arena, |
| 311 | .local_var => return self.cast(LocalVar).?.gen_zir.arena, | |
| 310 | 312 | .zir_module => return &self.cast(ZIRModule).?.contents.module.arena.allocator, |
| 311 | 313 | .file => unreachable, |
| 312 | 314 | } |
| ... | ... | @@ -318,6 +320,7 @@ pub const Scope = struct { |
| 318 | 320 | return switch (self.tag) { |
| 319 | 321 | .block => self.cast(Block).?.decl, |
| 320 | 322 | .gen_zir => self.cast(GenZIR).?.decl, |
| 323 | .local_var => return self.cast(LocalVar).?.gen_zir.decl, | |
| 321 | 324 | .decl => self.cast(DeclAnalysis).?.decl, |
| 322 | 325 | .zir_module => null, |
| 323 | 326 | .file => null, |
| ... | ... | @@ -330,6 +333,7 @@ pub const Scope = struct { |
| 330 | 333 | switch (self.tag) { |
| 331 | 334 | .block => return self.cast(Block).?.decl.scope, |
| 332 | 335 | .gen_zir => return self.cast(GenZIR).?.decl.scope, |
| 336 | .local_var => return self.cast(LocalVar).?.gen_zir.decl.scope, | |
| 333 | 337 | .decl => return self.cast(DeclAnalysis).?.decl.scope, |
| 334 | 338 | .zir_module, .file => return self, |
| 335 | 339 | } |
| ... | ... | @@ -342,6 +346,7 @@ pub const Scope = struct { |
| 342 | 346 | switch (self.tag) { |
| 343 | 347 | .block => unreachable, |
| 344 | 348 | .gen_zir => unreachable, |
| 349 | .local_var => unreachable, | |
| 345 | 350 | .decl => unreachable, |
| 346 | 351 | .zir_module => return self.cast(ZIRModule).?.fullyQualifiedNameHash(name), |
| 347 | 352 | .file => return self.cast(File).?.fullyQualifiedNameHash(name), |
| ... | ... | @@ -356,9 +361,22 @@ pub const Scope = struct { |
| 356 | 361 | .decl => return self.cast(DeclAnalysis).?.decl.scope.cast(File).?.contents.tree, |
| 357 | 362 | .block => return self.cast(Block).?.decl.scope.cast(File).?.contents.tree, |
| 358 | 363 | .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, | |
| 359 | 365 | } |
| 360 | 366 | } |
| 361 | 367 | |
| 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 | ||
| 362 | 380 | pub fn dumpInst(self: *Scope, inst: *Inst) void { |
| 363 | 381 | const zir_module = self.namespace(); |
| 364 | 382 | const loc = std.zig.findLineColumn(zir_module.source.bytes, inst.src); |
| ... | ... | @@ -379,6 +397,7 @@ pub const Scope = struct { |
| 379 | 397 | .zir_module => return @fieldParentPtr(ZIRModule, "base", base).sub_file_path, |
| 380 | 398 | .block => unreachable, |
| 381 | 399 | .gen_zir => unreachable, |
| 400 | .local_var => unreachable, | |
| 382 | 401 | .decl => unreachable, |
| 383 | 402 | } |
| 384 | 403 | } |
| ... | ... | @@ -389,6 +408,7 @@ pub const Scope = struct { |
| 389 | 408 | .zir_module => return @fieldParentPtr(ZIRModule, "base", base).unload(gpa), |
| 390 | 409 | .block => unreachable, |
| 391 | 410 | .gen_zir => unreachable, |
| 411 | .local_var => unreachable, | |
| 392 | 412 | .decl => unreachable, |
| 393 | 413 | } |
| 394 | 414 | } |
| ... | ... | @@ -398,6 +418,7 @@ pub const Scope = struct { |
| 398 | 418 | .file => return @fieldParentPtr(File, "base", base).getSource(module), |
| 399 | 419 | .zir_module => return @fieldParentPtr(ZIRModule, "base", base).getSource(module), |
| 400 | 420 | .gen_zir => unreachable, |
| 421 | .local_var => unreachable, | |
| 401 | 422 | .block => unreachable, |
| 402 | 423 | .decl => unreachable, |
| 403 | 424 | } |
| ... | ... | @@ -410,6 +431,7 @@ pub const Scope = struct { |
| 410 | 431 | .zir_module => return @fieldParentPtr(ZIRModule, "base", base).removeDecl(child), |
| 411 | 432 | .block => unreachable, |
| 412 | 433 | .gen_zir => unreachable, |
| 434 | .local_var => unreachable, | |
| 413 | 435 | .decl => unreachable, |
| 414 | 436 | } |
| 415 | 437 | } |
| ... | ... | @@ -429,6 +451,7 @@ pub const Scope = struct { |
| 429 | 451 | }, |
| 430 | 452 | .block => unreachable, |
| 431 | 453 | .gen_zir => unreachable, |
| 454 | .local_var => unreachable, | |
| 432 | 455 | .decl => unreachable, |
| 433 | 456 | } |
| 434 | 457 | } |
| ... | ... | @@ -449,6 +472,7 @@ pub const Scope = struct { |
| 449 | 472 | block, |
| 450 | 473 | decl, |
| 451 | 474 | gen_zir, |
| 475 | local_var, | |
| 452 | 476 | }; |
| 453 | 477 | |
| 454 | 478 | pub const File = struct { |
| ... | ... | @@ -680,6 +704,18 @@ pub const Scope = struct { |
| 680 | 704 | arena: *Allocator, |
| 681 | 705 | instructions: std.ArrayListUnmanaged(*zir.Inst) = .{}, |
| 682 | 706 | }; |
| 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 | }; | |
| 683 | 719 | }; |
| 684 | 720 | |
| 685 | 721 | pub const AllErrors = struct { |
| ... | ... | @@ -1114,7 +1150,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { |
| 1114 | 1150 | const file_scope = decl.scope.cast(Scope.File).?; |
| 1115 | 1151 | const tree = try self.getAstTree(file_scope); |
| 1116 | 1152 | const ast_node = tree.root_node.decls()[decl.src_index]; |
| 1117 | switch (ast_node.id) { | |
| 1153 | switch (ast_node.tag) { | |
| 1118 | 1154 | .FnProto => { |
| 1119 | 1155 | const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", ast_node); |
| 1120 | 1156 | |
| ... | ... | @@ -3247,6 +3283,12 @@ fn failWithOwnedErrorMsg(self: *Module, scope: *Scope, src: usize, err_msg: *Err |
| 3247 | 3283 | gen_zir.decl.generation = self.generation; |
| 3248 | 3284 | self.failed_decls.putAssumeCapacityNoClobber(gen_zir.decl, err_msg); |
| 3249 | 3285 | }, |
| 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 | }, | |
| 3250 | 3292 | .zir_module => { |
| 3251 | 3293 | const zir_module = scope.cast(Scope.ZIRModule).?; |
| 3252 | 3294 | zir_module.status = .loaded_sema_failure; |
src-self-hosted/astgen.zig+133-11| ... | ... | @@ -11,8 +11,11 @@ const trace = @import("tracy.zig").trace; |
| 11 | 11 | const Scope = Module.Scope; |
| 12 | 12 | const InnerError = Module.InnerError; |
| 13 | 13 | |
| 14 | /// Turn Zig AST into untyped ZIR istructions. | |
| 14 | 15 | pub 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 | ||
| 16 | 19 | .Identifier => return identifier(mod, scope, @fieldParentPtr(ast.Node.Identifier, "base", ast_node)), |
| 17 | 20 | .Asm => return assembly(mod, scope, @fieldParentPtr(ast.Node.Asm, "base", ast_node)), |
| 18 | 21 | .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 |
| 23 | 26 | .ControlFlowExpression => return controlFlowExpr(mod, scope, @fieldParentPtr(ast.Node.ControlFlowExpression, "base", ast_node)), |
| 24 | 27 | .If => return ifExpr(mod, scope, @fieldParentPtr(ast.Node.If, "base", ast_node)), |
| 25 | 28 | .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)}), | |
| 29 | 31 | } |
| 30 | 32 | } |
| 31 | 33 | |
| 32 | pub fn blockExpr(mod: *Module, scope: *Scope, block_node: *ast.Node.Block) !void { | |
| 34 | pub fn blockExpr(mod: *Module, parent_scope: *Scope, block_node: *ast.Node.Block) !void { | |
| 33 | 35 | const tracy = trace(@src()); |
| 34 | 36 | defer tracy.end(); |
| 35 | 37 | |
| 36 | 38 | 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", .{}); | |
| 38 | 40 | } |
| 41 | ||
| 42 | var block_arena = std.heap.ArenaAllocator.init(mod.gpa); | |
| 43 | defer block_arena.deinit(); | |
| 44 | ||
| 45 | var scope = parent_scope; | |
| 39 | 46 | 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 | } | |
| 41 | 56 | } |
| 42 | 57 | } |
| 43 | 58 | |
| 44 | fn varDecl(mod: *Module, scope: *Scope, node: *ast.Node.VarDecl) InnerError!*zir.Inst { | |
| 45 | return mod.failNode(scope, &node.base, "TODO implement var decls", .{}); | |
| 59 | fn 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 | }; | |
| 46 | 92 | } |
| 47 | 93 | |
| 48 | fn boolNot(mod: *Module, scope: *Scope, node: *ast.Node.BoolNot) InnerError!*zir.Inst { | |
| 94 | fn boolNot(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerError!*zir.Inst { | |
| 49 | 95 | const operand = try expr(mod, scope, node.rhs); |
| 50 | 96 | const tree = scope.tree(); |
| 51 | 97 | 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 |
| 55 | 101 | fn infixOp(mod: *Module, scope: *Scope, infix_node: *ast.Node.InfixOp) InnerError!*zir.Inst { |
| 56 | 102 | switch (infix_node.op) { |
| 57 | 103 | .Assign => { |
| 58 | if (infix_node.lhs.id == .Identifier) { | |
| 104 | if (infix_node.lhs.tag == .Identifier) { | |
| 59 | 105 | const ident = @fieldParentPtr(ast.Node.Identifier, "base", infix_node.lhs); |
| 60 | 106 | const tree = scope.tree(); |
| 61 | 107 | const ident_name = tree.tokenSlice(ident.token); |
| ... | ... | @@ -474,3 +520,79 @@ fn getSimplePrimitiveValue(name: []const u8) ?TypedValue { |
| 474 | 520 | } |
| 475 | 521 | return null; |
| 476 | 522 | } |
| 523 | ||
| 524 | fn 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( |
| 1219 | 1219 | .StringLiteralClass => return transStringLiteral(rp, scope, @ptrCast(*const ZigClangStringLiteral, stmt), result_used), |
| 1220 | 1220 | .ParenExprClass => { |
| 1221 | 1221 | 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); | |
| 1223 | 1223 | const node = try rp.c.arena.create(ast.Node.GroupedExpression); |
| 1224 | 1224 | node.* = .{ |
| 1225 | 1225 | .lparen = try appendToken(rp.c, .LParen, "("), |
| ... | ... | @@ -1264,7 +1264,7 @@ fn transStmt( |
| 1264 | 1264 | .OpaqueValueExprClass => { |
| 1265 | 1265 | const source_expr = ZigClangOpaqueValueExpr_getSourceExpr(@ptrCast(*const ZigClangOpaqueValueExpr, stmt)).?; |
| 1266 | 1266 | 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); | |
| 1268 | 1268 | const node = try rp.c.arena.create(ast.Node.GroupedExpression); |
| 1269 | 1269 | node.* = .{ |
| 1270 | 1270 | .lparen = try appendToken(rp.c, .LParen, "("), |
| ... | ... | @@ -1693,7 +1693,7 @@ fn transBoolExpr( |
| 1693 | 1693 | var res = try transExpr(rp, scope, expr, used, lrvalue); |
| 1694 | 1694 | |
| 1695 | 1695 | if (isBoolRes(res)) { |
| 1696 | if (!grouped and res.id == .GroupedExpression) { | |
| 1696 | if (!grouped and res.tag == .GroupedExpression) { | |
| 1697 | 1697 | const group = @fieldParentPtr(ast.Node.GroupedExpression, "base", res); |
| 1698 | 1698 | res = group.expr; |
| 1699 | 1699 | // get zig fmt to work properly |
| ... | ... | @@ -1736,7 +1736,7 @@ fn exprIsStringLiteral(expr: *const ZigClangExpr) bool { |
| 1736 | 1736 | } |
| 1737 | 1737 | |
| 1738 | 1738 | fn isBoolRes(res: *ast.Node) bool { |
| 1739 | switch (res.id) { | |
| 1739 | switch (res.tag) { | |
| 1740 | 1740 | .InfixOp => switch (@fieldParentPtr(ast.Node.InfixOp, "base", res).op) { |
| 1741 | 1741 | .BoolOr, |
| 1742 | 1742 | .BoolAnd, |
| ... | ... | @@ -4107,12 +4107,13 @@ fn transCreateNodeFieldAccess(c: *Context, container: *ast.Node, field_name: []c |
| 4107 | 4107 | |
| 4108 | 4108 | fn transCreateNodeSimplePrefixOp( |
| 4109 | 4109 | c: *Context, |
| 4110 | comptime tag: ast.Node.Id, | |
| 4110 | comptime tag: ast.Node.Tag, | |
| 4111 | 4111 | op_tok_id: std.zig.Token.Id, |
| 4112 | 4112 | 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); | |
| 4115 | 4115 | node.* = .{ |
| 4116 | .base = .{ .tag = tag }, | |
| 4116 | 4117 | .op_token = try appendToken(c, op_tok_id, bytes), |
| 4117 | 4118 | .rhs = undefined, // translate and set afterward |
| 4118 | 4119 | }; |
| ... | ... | @@ -5338,10 +5339,10 @@ fn transMacroFnDefine(c: *Context, it: *CTokenList.Iterator, source: []const u8, |
| 5338 | 5339 | .{@tagName(last.id)}, |
| 5339 | 5340 | ); |
| 5340 | 5341 | _ = 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: { | |
| 5342 | 5343 | const blk = @fieldParentPtr(ast.Node.Block, "base", expr); |
| 5343 | 5344 | 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); | |
| 5345 | 5346 | const br = @fieldParentPtr(ast.Node.ControlFlowExpression, "base", blk_last); |
| 5346 | 5347 | break :blk br.rhs.?; |
| 5347 | 5348 | }; |
| ... | ... | @@ -5788,7 +5789,7 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, |
| 5788 | 5789 | |
| 5789 | 5790 | fn macroBoolToInt(c: *Context, node: *ast.Node) !*ast.Node { |
| 5790 | 5791 | if (!isBoolRes(node)) { |
| 5791 | if (node.id != .InfixOp) return node; | |
| 5792 | if (node.tag != .InfixOp) return node; | |
| 5792 | 5793 | |
| 5793 | 5794 | const group_node = try c.arena.create(ast.Node.GroupedExpression); |
| 5794 | 5795 | group_node.* = .{ |
| ... | ... | @@ -5807,7 +5808,7 @@ fn macroBoolToInt(c: *Context, node: *ast.Node) !*ast.Node { |
| 5807 | 5808 | |
| 5808 | 5809 | fn macroIntToBool(c: *Context, node: *ast.Node) !*ast.Node { |
| 5809 | 5810 | if (isBoolRes(node)) { |
| 5810 | if (node.id != .InfixOp) return node; | |
| 5811 | if (node.tag != .InfixOp) return node; | |
| 5811 | 5812 | |
| 5812 | 5813 | const group_node = try c.arena.create(ast.Node.GroupedExpression); |
| 5813 | 5814 | group_node.* = .{ |
| ... | ... | @@ -6105,7 +6106,7 @@ fn tokenSlice(c: *Context, token: ast.TokenIndex) []u8 { |
| 6105 | 6106 | } |
| 6106 | 6107 | |
| 6107 | 6108 | fn getContainer(c: *Context, node: *ast.Node) ?*ast.Node { |
| 6108 | switch (node.id) { | |
| 6109 | switch (node.tag) { | |
| 6109 | 6110 | .ContainerDecl, |
| 6110 | 6111 | .AddressOf, |
| 6111 | 6112 | .Await, |
| ... | ... | @@ -6182,7 +6183,7 @@ fn getContainerTypeOf(c: *Context, ref: *ast.Node) ?*ast.Node { |
| 6182 | 6183 | fn getFnProto(c: *Context, ref: *ast.Node) ?*ast.Node.FnProto { |
| 6183 | 6184 | const init = if (ref.cast(ast.Node.VarDecl)) |v| v.getTrailer("init_node").? else return null; |
| 6184 | 6185 | if (getContainerTypeOf(c, init)) |ty_node| { |
| 6185 | if (ty_node.cast(ast.Node.OptionalType)) |prefix| { | |
| 6186 | if (ty_node.castTag(.OptionalType)) |prefix| { | |
| 6186 | 6187 | if (prefix.rhs.cast(ast.Node.FnProto)) |fn_proto| { |
| 6187 | 6188 | return fn_proto; |
| 6188 | 6189 | } |