| author | |
| committer | |
| log | af12596e8d728423e361e4755a6078c5ef8faf69 |
| tree | a19190d14848b536cae262789573531c47b42f10 |
| parent | f11909227312882f29dbfc484dc79ab622792787 |
InfixOp is flattened out so that each operator is an independent AST
node tag. The two kinds of structs are now Catch and SimpleInfixOp.
Beginning implementation of supporting codegen for const locals.6 files changed, 599 insertions(+), 285 deletions(-)
lib/std/zig/ast.zig+134-107| ... | @@ -408,8 +408,54 @@ pub const Node = struct { | ... | @@ -408,8 +408,54 @@ pub const Node = struct { |
| 408 | VarDecl, | 408 | VarDecl, |
| 409 | Defer, | 409 | Defer, |
| 410 | 410 | ||
| 411 | // Operators | 411 | // Infix operators |
| 412 | InfixOp, | 412 | Catch, |
| 413 | |||
| 414 | // SimpleInfixOp | ||
| 415 | Add, | ||
| 416 | AddWrap, | ||
| 417 | ArrayCat, | ||
| 418 | ArrayMult, | ||
| 419 | Assign, | ||
| 420 | AssignBitAnd, | ||
| 421 | AssignBitOr, | ||
| 422 | AssignBitShiftLeft, | ||
| 423 | AssignBitShiftRight, | ||
| 424 | AssignBitXor, | ||
| 425 | AssignDiv, | ||
| 426 | AssignSub, | ||
| 427 | AssignSubWrap, | ||
| 428 | AssignMod, | ||
| 429 | AssignAdd, | ||
| 430 | AssignAddWrap, | ||
| 431 | AssignMul, | ||
| 432 | AssignMulWrap, | ||
| 433 | BangEqual, | ||
| 434 | BitAnd, | ||
| 435 | BitOr, | ||
| 436 | BitShiftLeft, | ||
| 437 | BitShiftRight, | ||
| 438 | BitXor, | ||
| 439 | BoolAnd, | ||
| 440 | BoolOr, | ||
| 441 | Div, | ||
| 442 | EqualEqual, | ||
| 443 | ErrorUnion, | ||
| 444 | GreaterOrEqual, | ||
| 445 | GreaterThan, | ||
| 446 | LessOrEqual, | ||
| 447 | LessThan, | ||
| 448 | MergeErrorSets, | ||
| 449 | Mod, | ||
| 450 | Mul, | ||
| 451 | MulWrap, | ||
| 452 | Period, | ||
| 453 | Range, | ||
| 454 | Sub, | ||
| 455 | SubWrap, | ||
| 456 | UnwrapOptional, | ||
| 457 | |||
| 458 | // SimplePrefixOp | ||
| 413 | AddressOf, | 459 | AddressOf, |
| 414 | Await, | 460 | Await, |
| 415 | BitNot, | 461 | BitNot, |
| ... | @@ -419,6 +465,7 @@ pub const Node = struct { | ... | @@ -419,6 +465,7 @@ pub const Node = struct { |
| 419 | NegationWrap, | 465 | NegationWrap, |
| 420 | Resume, | 466 | Resume, |
| 421 | Try, | 467 | Try, |
| 468 | |||
| 422 | ArrayType, | 469 | ArrayType, |
| 423 | /// ArrayType but has a sentinel node. | 470 | /// ArrayType but has a sentinel node. |
| 424 | ArrayTypeSentinel, | 471 | ArrayTypeSentinel, |
| ... | @@ -492,7 +539,51 @@ pub const Node = struct { | ... | @@ -492,7 +539,51 @@ pub const Node = struct { |
| 492 | .TestDecl => TestDecl, | 539 | .TestDecl => TestDecl, |
| 493 | .VarDecl => VarDecl, | 540 | .VarDecl => VarDecl, |
| 494 | .Defer => Defer, | 541 | .Defer => Defer, |
| 495 | .InfixOp => InfixOp, | 542 | .Catch => Catch, |
| 543 | |||
| 544 | .Add, | ||
| 545 | .AddWrap, | ||
| 546 | .ArrayCat, | ||
| 547 | .ArrayMult, | ||
| 548 | .Assign, | ||
| 549 | .AssignBitAnd, | ||
| 550 | .AssignBitOr, | ||
| 551 | .AssignBitShiftLeft, | ||
| 552 | .AssignBitShiftRight, | ||
| 553 | .AssignBitXor, | ||
| 554 | .AssignDiv, | ||
| 555 | .AssignSub, | ||
| 556 | .AssignSubWrap, | ||
| 557 | .AssignMod, | ||
| 558 | .AssignAdd, | ||
| 559 | .AssignAddWrap, | ||
| 560 | .AssignMul, | ||
| 561 | .AssignMulWrap, | ||
| 562 | .BangEqual, | ||
| 563 | .BitAnd, | ||
| 564 | .BitOr, | ||
| 565 | .BitShiftLeft, | ||
| 566 | .BitShiftRight, | ||
| 567 | .BitXor, | ||
| 568 | .BoolAnd, | ||
| 569 | .BoolOr, | ||
| 570 | .Div, | ||
| 571 | .EqualEqual, | ||
| 572 | .ErrorUnion, | ||
| 573 | .GreaterOrEqual, | ||
| 574 | .GreaterThan, | ||
| 575 | .LessOrEqual, | ||
| 576 | .LessThan, | ||
| 577 | .MergeErrorSets, | ||
| 578 | .Mod, | ||
| 579 | .Mul, | ||
| 580 | .MulWrap, | ||
| 581 | .Period, | ||
| 582 | .Range, | ||
| 583 | .Sub, | ||
| 584 | .SubWrap, | ||
| 585 | .UnwrapOptional, | ||
| 586 | => SimpleInfixOp, | ||
| 496 | 587 | ||
| 497 | .AddressOf, | 588 | .AddressOf, |
| 498 | .Await, | 589 | .Await, |
| ... | @@ -507,13 +598,17 @@ pub const Node = struct { | ... | @@ -507,13 +598,17 @@ pub const Node = struct { |
| 507 | 598 | ||
| 508 | .ArrayType => ArrayType, | 599 | .ArrayType => ArrayType, |
| 509 | .ArrayTypeSentinel => ArrayTypeSentinel, | 600 | .ArrayTypeSentinel => ArrayTypeSentinel, |
| 601 | |||
| 510 | .PtrType => PtrType, | 602 | .PtrType => PtrType, |
| 511 | .SliceType => SliceType, | 603 | .SliceType => SliceType, |
| 512 | .SuffixOp => SuffixOp, | 604 | .SuffixOp => SuffixOp, |
| 605 | |||
| 513 | .ArrayInitializer => ArrayInitializer, | 606 | .ArrayInitializer => ArrayInitializer, |
| 514 | .ArrayInitializerDot => ArrayInitializerDot, | 607 | .ArrayInitializerDot => ArrayInitializerDot, |
| 608 | |||
| 515 | .StructInitializer => StructInitializer, | 609 | .StructInitializer => StructInitializer, |
| 516 | .StructInitializerDot => StructInitializerDot, | 610 | .StructInitializerDot => StructInitializerDot, |
| 611 | |||
| 517 | .Call => Call, | 612 | .Call => Call, |
| 518 | .Switch => Switch, | 613 | .Switch => Switch, |
| 519 | .While => While, | 614 | .While => While, |
| ... | @@ -1859,117 +1954,22 @@ pub const Node = struct { | ... | @@ -1859,117 +1954,22 @@ pub const Node = struct { |
| 1859 | } | 1954 | } |
| 1860 | }; | 1955 | }; |
| 1861 | 1956 | ||
| 1862 | /// TODO split up and make every op its own AST Node tag | 1957 | pub const Catch = struct { |
| 1863 | pub const InfixOp = struct { | 1958 | base: Node = Node{ .tag = .Catch }, |
| 1864 | base: Node = Node{ .tag = .InfixOp }, | ||
| 1865 | op_token: TokenIndex, | 1959 | op_token: TokenIndex, |
| 1866 | lhs: *Node, | 1960 | lhs: *Node, |
| 1867 | op: Op, | ||
| 1868 | rhs: *Node, | 1961 | rhs: *Node, |
| 1962 | payload: ?*Node, | ||
| 1869 | 1963 | ||
| 1870 | pub const Op = union(enum) { | 1964 | pub fn iterate(self: *const Catch, index: usize) ?*Node { |
| 1871 | Add, | ||
| 1872 | AddWrap, | ||
| 1873 | ArrayCat, | ||
| 1874 | ArrayMult, | ||
| 1875 | Assign, | ||
| 1876 | AssignBitAnd, | ||
| 1877 | AssignBitOr, | ||
| 1878 | AssignBitShiftLeft, | ||
| 1879 | AssignBitShiftRight, | ||
| 1880 | AssignBitXor, | ||
| 1881 | AssignDiv, | ||
| 1882 | AssignSub, | ||
| 1883 | AssignSubWrap, | ||
| 1884 | AssignMod, | ||
| 1885 | AssignAdd, | ||
| 1886 | AssignAddWrap, | ||
| 1887 | AssignMul, | ||
| 1888 | AssignMulWrap, | ||
| 1889 | BangEqual, | ||
| 1890 | BitAnd, | ||
| 1891 | BitOr, | ||
| 1892 | BitShiftLeft, | ||
| 1893 | BitShiftRight, | ||
| 1894 | BitXor, | ||
| 1895 | BoolAnd, | ||
| 1896 | BoolOr, | ||
| 1897 | Catch: ?*Node, | ||
| 1898 | Div, | ||
| 1899 | EqualEqual, | ||
| 1900 | ErrorUnion, | ||
| 1901 | GreaterOrEqual, | ||
| 1902 | GreaterThan, | ||
| 1903 | LessOrEqual, | ||
| 1904 | LessThan, | ||
| 1905 | MergeErrorSets, | ||
| 1906 | Mod, | ||
| 1907 | Mul, | ||
| 1908 | MulWrap, | ||
| 1909 | Period, | ||
| 1910 | Range, | ||
| 1911 | Sub, | ||
| 1912 | SubWrap, | ||
| 1913 | UnwrapOptional, | ||
| 1914 | }; | ||
| 1915 | |||
| 1916 | pub fn iterate(self: *const InfixOp, index: usize) ?*Node { | ||
| 1917 | var i = index; | 1965 | var i = index; |
| 1918 | 1966 | ||
| 1919 | if (i < 1) return self.lhs; | 1967 | if (i < 1) return self.lhs; |
| 1920 | i -= 1; | 1968 | i -= 1; |
| 1921 | 1969 | ||
| 1922 | switch (self.op) { | 1970 | if (self.payload) |payload| { |
| 1923 | .Catch => |maybe_payload| { | 1971 | if (i < 1) return payload; |
| 1924 | if (maybe_payload) |payload| { | 1972 | i -= 1; |
| 1925 | if (i < 1) return payload; | ||
| 1926 | i -= 1; | ||
| 1927 | } | ||
| 1928 | }, | ||
| 1929 | |||
| 1930 | .Add, | ||
| 1931 | .AddWrap, | ||
| 1932 | .ArrayCat, | ||
| 1933 | .ArrayMult, | ||
| 1934 | .Assign, | ||
| 1935 | .AssignBitAnd, | ||
| 1936 | .AssignBitOr, | ||
| 1937 | .AssignBitShiftLeft, | ||
| 1938 | .AssignBitShiftRight, | ||
| 1939 | .AssignBitXor, | ||
| 1940 | .AssignDiv, | ||
| 1941 | .AssignSub, | ||
| 1942 | .AssignSubWrap, | ||
| 1943 | .AssignMod, | ||
| 1944 | .AssignAdd, | ||
| 1945 | .AssignAddWrap, | ||
| 1946 | .AssignMul, | ||
| 1947 | .AssignMulWrap, | ||
| 1948 | .BangEqual, | ||
| 1949 | .BitAnd, | ||
| 1950 | .BitOr, | ||
| 1951 | .BitShiftLeft, | ||
| 1952 | .BitShiftRight, | ||
| 1953 | .BitXor, | ||
| 1954 | .BoolAnd, | ||
| 1955 | .BoolOr, | ||
| 1956 | .Div, | ||
| 1957 | .EqualEqual, | ||
| 1958 | .ErrorUnion, | ||
| 1959 | .GreaterOrEqual, | ||
| 1960 | .GreaterThan, | ||
| 1961 | .LessOrEqual, | ||
| 1962 | .LessThan, | ||
| 1963 | .MergeErrorSets, | ||
| 1964 | .Mod, | ||
| 1965 | .Mul, | ||
| 1966 | .MulWrap, | ||
| 1967 | .Period, | ||
| 1968 | .Range, | ||
| 1969 | .Sub, | ||
| 1970 | .SubWrap, | ||
| 1971 | .UnwrapOptional, | ||
| 1972 | => {}, | ||
| 1973 | } | 1973 | } |
| 1974 | 1974 | ||
| 1975 | if (i < 1) return self.rhs; | 1975 | if (i < 1) return self.rhs; |
| ... | @@ -1978,11 +1978,38 @@ pub const Node = struct { | ... | @@ -1978,11 +1978,38 @@ pub const Node = struct { |
| 1978 | return null; | 1978 | return null; |
| 1979 | } | 1979 | } |
| 1980 | 1980 | ||
| 1981 | pub fn firstToken(self: *const InfixOp) TokenIndex { | 1981 | pub fn firstToken(self: *const Catch) TokenIndex { |
| 1982 | return self.lhs.firstToken(); | ||
| 1983 | } | ||
| 1984 | |||
| 1985 | pub fn lastToken(self: *const Catch) TokenIndex { | ||
| 1986 | return self.rhs.lastToken(); | ||
| 1987 | } | ||
| 1988 | }; | ||
| 1989 | |||
| 1990 | pub const SimpleInfixOp = struct { | ||
| 1991 | base: Node, | ||
| 1992 | op_token: TokenIndex, | ||
| 1993 | lhs: *Node, | ||
| 1994 | rhs: *Node, | ||
| 1995 | |||
| 1996 | pub fn iterate(self: *const SimpleInfixOp, index: usize) ?*Node { | ||
| 1997 | var i = index; | ||
| 1998 | |||
| 1999 | if (i < 1) return self.lhs; | ||
| 2000 | i -= 1; | ||
| 2001 | |||
| 2002 | if (i < 1) return self.rhs; | ||
| 2003 | i -= 1; | ||
| 2004 | |||
| 2005 | return null; | ||
| 2006 | } | ||
| 2007 | |||
| 2008 | pub fn firstToken(self: *const SimpleInfixOp) TokenIndex { | ||
| 1982 | return self.lhs.firstToken(); | 2009 | return self.lhs.firstToken(); |
| 1983 | } | 2010 | } |
| 1984 | 2011 | ||
| 1985 | pub fn lastToken(self: *const InfixOp) TokenIndex { | 2012 | pub fn lastToken(self: *const SimpleInfixOp) TokenIndex { |
| 1986 | return self.rhs.lastToken(); | 2013 | return self.rhs.lastToken(); |
| 1987 | } | 2014 | } |
| 1988 | }; | 2015 | }; |
lib/std/zig/parse.zig+136-31| ... | @@ -1015,7 +1015,7 @@ const Parser = struct { | ... | @@ -1015,7 +1015,7 @@ const Parser = struct { |
| 1015 | /// BoolOrExpr <- BoolAndExpr (KEYWORD_or BoolAndExpr)* | 1015 | /// BoolOrExpr <- BoolAndExpr (KEYWORD_or BoolAndExpr)* |
| 1016 | fn parseBoolOrExpr(p: *Parser) !?*Node { | 1016 | fn parseBoolOrExpr(p: *Parser) !?*Node { |
| 1017 | return p.parseBinOpExpr( | 1017 | return p.parseBinOpExpr( |
| 1018 | SimpleBinOpParseFn(.Keyword_or, Node.InfixOp.Op.BoolOr), | 1018 | SimpleBinOpParseFn(.Keyword_or, .BoolOr), |
| 1019 | parseBoolAndExpr, | 1019 | parseBoolAndExpr, |
| 1020 | .Infinitely, | 1020 | .Infinitely, |
| 1021 | ); | 1021 | ); |
| ... | @@ -1405,8 +1405,8 @@ const Parser = struct { | ... | @@ -1405,8 +1405,8 @@ const Parser = struct { |
| 1405 | fn parseErrorUnionExpr(p: *Parser) !?*Node { | 1405 | fn parseErrorUnionExpr(p: *Parser) !?*Node { |
| 1406 | const suffix_expr = (try p.parseSuffixExpr()) orelse return null; | 1406 | const suffix_expr = (try p.parseSuffixExpr()) orelse return null; |
| 1407 | 1407 | ||
| 1408 | if (try SimpleBinOpParseFn(.Bang, Node.InfixOp.Op.ErrorUnion)(p)) |node| { | 1408 | if (try SimpleBinOpParseFn(.Bang, .ErrorUnion)(p)) |node| { |
| 1409 | const error_union = node.cast(Node.InfixOp).?; | 1409 | const error_union = node.castTag(.ErrorUnion).?; |
| 1410 | const type_expr = try p.expectNode(parseTypeExpr, .{ | 1410 | const type_expr = try p.expectNode(parseTypeExpr, .{ |
| 1411 | .ExpectedTypeExpr = .{ .token = p.tok_i }, | 1411 | .ExpectedTypeExpr = .{ .token = p.tok_i }, |
| 1412 | }); | 1412 | }); |
| ... | @@ -1439,10 +1439,56 @@ const Parser = struct { | ... | @@ -1439,10 +1439,56 @@ const Parser = struct { |
| 1439 | .ExpectedPrimaryTypeExpr = .{ .token = p.tok_i }, | 1439 | .ExpectedPrimaryTypeExpr = .{ .token = p.tok_i }, |
| 1440 | }); | 1440 | }); |
| 1441 | 1441 | ||
| 1442 | // TODO pass `res` into `parseSuffixOp` rather than patching it up afterwards. | ||
| 1442 | while (try p.parseSuffixOp()) |node| { | 1443 | while (try p.parseSuffixOp()) |node| { |
| 1443 | switch (node.tag) { | 1444 | switch (node.tag) { |
| 1444 | .SuffixOp => node.cast(Node.SuffixOp).?.lhs = res, | 1445 | .SuffixOp => node.cast(Node.SuffixOp).?.lhs = res, |
| 1445 | .InfixOp => node.cast(Node.InfixOp).?.lhs = res, | 1446 | .Catch => node.castTag(.Catch).?.lhs = res, |
| 1447 | |||
| 1448 | .Add, | ||
| 1449 | .AddWrap, | ||
| 1450 | .ArrayCat, | ||
| 1451 | .ArrayMult, | ||
| 1452 | .Assign, | ||
| 1453 | .AssignBitAnd, | ||
| 1454 | .AssignBitOr, | ||
| 1455 | .AssignBitShiftLeft, | ||
| 1456 | .AssignBitShiftRight, | ||
| 1457 | .AssignBitXor, | ||
| 1458 | .AssignDiv, | ||
| 1459 | .AssignSub, | ||
| 1460 | .AssignSubWrap, | ||
| 1461 | .AssignMod, | ||
| 1462 | .AssignAdd, | ||
| 1463 | .AssignAddWrap, | ||
| 1464 | .AssignMul, | ||
| 1465 | .AssignMulWrap, | ||
| 1466 | .BangEqual, | ||
| 1467 | .BitAnd, | ||
| 1468 | .BitOr, | ||
| 1469 | .BitShiftLeft, | ||
| 1470 | .BitShiftRight, | ||
| 1471 | .BitXor, | ||
| 1472 | .BoolAnd, | ||
| 1473 | .BoolOr, | ||
| 1474 | .Div, | ||
| 1475 | .EqualEqual, | ||
| 1476 | .ErrorUnion, | ||
| 1477 | .GreaterOrEqual, | ||
| 1478 | .GreaterThan, | ||
| 1479 | .LessOrEqual, | ||
| 1480 | .LessThan, | ||
| 1481 | .MergeErrorSets, | ||
| 1482 | .Mod, | ||
| 1483 | .Mul, | ||
| 1484 | .MulWrap, | ||
| 1485 | .Period, | ||
| 1486 | .Range, | ||
| 1487 | .Sub, | ||
| 1488 | .SubWrap, | ||
| 1489 | .UnwrapOptional, | ||
| 1490 | => node.cast(Node.SimpleInfixOp).?.lhs = res, | ||
| 1491 | |||
| 1446 | else => unreachable, | 1492 | else => unreachable, |
| 1447 | } | 1493 | } |
| 1448 | res = node; | 1494 | res = node; |
| ... | @@ -1470,10 +1516,55 @@ const Parser = struct { | ... | @@ -1470,10 +1516,55 @@ const Parser = struct { |
| 1470 | var res = expr; | 1516 | var res = expr; |
| 1471 | 1517 | ||
| 1472 | while (true) { | 1518 | while (true) { |
| 1519 | // TODO pass `res` into `parseSuffixOp` rather than patching it up afterwards. | ||
| 1473 | if (try p.parseSuffixOp()) |node| { | 1520 | if (try p.parseSuffixOp()) |node| { |
| 1474 | switch (node.tag) { | 1521 | switch (node.tag) { |
| 1475 | .SuffixOp => node.cast(Node.SuffixOp).?.lhs = res, | 1522 | .SuffixOp => node.cast(Node.SuffixOp).?.lhs = res, |
| 1476 | .InfixOp => node.cast(Node.InfixOp).?.lhs = res, | 1523 | .Catch => node.castTag(.Catch).?.lhs = res, |
| 1524 | |||
| 1525 | .Add, | ||
| 1526 | .AddWrap, | ||
| 1527 | .ArrayCat, | ||
| 1528 | .ArrayMult, | ||
| 1529 | .Assign, | ||
| 1530 | .AssignBitAnd, | ||
| 1531 | .AssignBitOr, | ||
| 1532 | .AssignBitShiftLeft, | ||
| 1533 | .AssignBitShiftRight, | ||
| 1534 | .AssignBitXor, | ||
| 1535 | .AssignDiv, | ||
| 1536 | .AssignSub, | ||
| 1537 | .AssignSubWrap, | ||
| 1538 | .AssignMod, | ||
| 1539 | .AssignAdd, | ||
| 1540 | .AssignAddWrap, | ||
| 1541 | .AssignMul, | ||
| 1542 | .AssignMulWrap, | ||
| 1543 | .BangEqual, | ||
| 1544 | .BitAnd, | ||
| 1545 | .BitOr, | ||
| 1546 | .BitShiftLeft, | ||
| 1547 | .BitShiftRight, | ||
| 1548 | .BitXor, | ||
| 1549 | .BoolAnd, | ||
| 1550 | .BoolOr, | ||
| 1551 | .Div, | ||
| 1552 | .EqualEqual, | ||
| 1553 | .ErrorUnion, | ||
| 1554 | .GreaterOrEqual, | ||
| 1555 | .GreaterThan, | ||
| 1556 | .LessOrEqual, | ||
| 1557 | .LessThan, | ||
| 1558 | .MergeErrorSets, | ||
| 1559 | .Mod, | ||
| 1560 | .Mul, | ||
| 1561 | .MulWrap, | ||
| 1562 | .Period, | ||
| 1563 | .Range, | ||
| 1564 | .Sub, | ||
| 1565 | .SubWrap, | ||
| 1566 | .UnwrapOptional, | ||
| 1567 | => node.cast(Node.SimpleInfixOp).?.lhs = res, | ||
| 1477 | else => unreachable, | 1568 | else => unreachable, |
| 1478 | } | 1569 | } |
| 1479 | res = node; | 1570 | res = node; |
| ... | @@ -1560,11 +1651,11 @@ const Parser = struct { | ... | @@ -1560,11 +1651,11 @@ const Parser = struct { |
| 1560 | const global_error_set = try p.createLiteral(Node.ErrorType, token); | 1651 | const global_error_set = try p.createLiteral(Node.ErrorType, token); |
| 1561 | if (period == null or identifier == null) return global_error_set; | 1652 | if (period == null or identifier == null) return global_error_set; |
| 1562 | 1653 | ||
| 1563 | const node = try p.arena.allocator.create(Node.InfixOp); | 1654 | const node = try p.arena.allocator.create(Node.SimpleInfixOp); |
| 1564 | node.* = .{ | 1655 | node.* = .{ |
| 1656 | .base = Node{ .tag = .Period }, | ||
| 1565 | .op_token = period.?, | 1657 | .op_token = period.?, |
| 1566 | .lhs = global_error_set, | 1658 | .lhs = global_error_set, |
| 1567 | .op = .Period, | ||
| 1568 | .rhs = identifier.?, | 1659 | .rhs = identifier.?, |
| 1569 | }; | 1660 | }; |
| 1570 | return &node.base; | 1661 | return &node.base; |
| ... | @@ -2237,11 +2328,11 @@ const Parser = struct { | ... | @@ -2237,11 +2328,11 @@ const Parser = struct { |
| 2237 | .ExpectedExpr = .{ .token = p.tok_i }, | 2328 | .ExpectedExpr = .{ .token = p.tok_i }, |
| 2238 | }); | 2329 | }); |
| 2239 | 2330 | ||
| 2240 | const node = try p.arena.allocator.create(Node.InfixOp); | 2331 | const node = try p.arena.allocator.create(Node.SimpleInfixOp); |
| 2241 | node.* = .{ | 2332 | node.* = .{ |
| 2333 | .base = Node{ .tag = .Range }, | ||
| 2242 | .op_token = token, | 2334 | .op_token = token, |
| 2243 | .lhs = expr, | 2335 | .lhs = expr, |
| 2244 | .op = .Range, | ||
| 2245 | .rhs = range_end, | 2336 | .rhs = range_end, |
| 2246 | }; | 2337 | }; |
| 2247 | return &node.base; | 2338 | return &node.base; |
| ... | @@ -2266,7 +2357,7 @@ const Parser = struct { | ... | @@ -2266,7 +2357,7 @@ const Parser = struct { |
| 2266 | /// / EQUAL | 2357 | /// / EQUAL |
| 2267 | fn parseAssignOp(p: *Parser) !?*Node { | 2358 | fn parseAssignOp(p: *Parser) !?*Node { |
| 2268 | const token = p.nextToken(); | 2359 | const token = p.nextToken(); |
| 2269 | const op: Node.InfixOp.Op = switch (p.token_ids[token]) { | 2360 | const op: Node.Tag = switch (p.token_ids[token]) { |
| 2270 | .AsteriskEqual => .AssignMul, | 2361 | .AsteriskEqual => .AssignMul, |
| 2271 | .SlashEqual => .AssignDiv, | 2362 | .SlashEqual => .AssignDiv, |
| 2272 | .PercentEqual => .AssignMod, | 2363 | .PercentEqual => .AssignMod, |
| ... | @@ -2287,11 +2378,11 @@ const Parser = struct { | ... | @@ -2287,11 +2378,11 @@ const Parser = struct { |
| 2287 | }, | 2378 | }, |
| 2288 | }; | 2379 | }; |
| 2289 | 2380 | ||
| 2290 | const node = try p.arena.allocator.create(Node.InfixOp); | 2381 | const node = try p.arena.allocator.create(Node.SimpleInfixOp); |
| 2291 | node.* = .{ | 2382 | node.* = .{ |
| 2383 | .base = .{ .tag = op }, | ||
| 2292 | .op_token = token, | 2384 | .op_token = token, |
| 2293 | .lhs = undefined, // set by caller | 2385 | .lhs = undefined, // set by caller |
| 2294 | .op = op, | ||
| 2295 | .rhs = undefined, // set by caller | 2386 | .rhs = undefined, // set by caller |
| 2296 | }; | 2387 | }; |
| 2297 | return &node.base; | 2388 | return &node.base; |
| ... | @@ -2306,7 +2397,7 @@ const Parser = struct { | ... | @@ -2306,7 +2397,7 @@ const Parser = struct { |
| 2306 | /// / RARROWEQUAL | 2397 | /// / RARROWEQUAL |
| 2307 | fn parseCompareOp(p: *Parser) !?*Node { | 2398 | fn parseCompareOp(p: *Parser) !?*Node { |
| 2308 | const token = p.nextToken(); | 2399 | const token = p.nextToken(); |
| 2309 | const op: Node.InfixOp.Op = switch (p.token_ids[token]) { | 2400 | const op: Node.Tag = switch (p.token_ids[token]) { |
| 2310 | .EqualEqual => .EqualEqual, | 2401 | .EqualEqual => .EqualEqual, |
| 2311 | .BangEqual => .BangEqual, | 2402 | .BangEqual => .BangEqual, |
| 2312 | .AngleBracketLeft => .LessThan, | 2403 | .AngleBracketLeft => .LessThan, |
| ... | @@ -2330,12 +2421,22 @@ const Parser = struct { | ... | @@ -2330,12 +2421,22 @@ const Parser = struct { |
| 2330 | /// / KEYWORD_catch Payload? | 2421 | /// / KEYWORD_catch Payload? |
| 2331 | fn parseBitwiseOp(p: *Parser) !?*Node { | 2422 | fn parseBitwiseOp(p: *Parser) !?*Node { |
| 2332 | const token = p.nextToken(); | 2423 | const token = p.nextToken(); |
| 2333 | const op: Node.InfixOp.Op = switch (p.token_ids[token]) { | 2424 | const op: Node.Tag = switch (p.token_ids[token]) { |
| 2334 | .Ampersand => .BitAnd, | 2425 | .Ampersand => .BitAnd, |
| 2335 | .Caret => .BitXor, | 2426 | .Caret => .BitXor, |
| 2336 | .Pipe => .BitOr, | 2427 | .Pipe => .BitOr, |
| 2337 | .Keyword_orelse => .UnwrapOptional, | 2428 | .Keyword_orelse => .UnwrapOptional, |
| 2338 | .Keyword_catch => .{ .Catch = try p.parsePayload() }, | 2429 | .Keyword_catch => { |
| 2430 | const payload = try p.parsePayload(); | ||
| 2431 | const node = try p.arena.allocator.create(Node.Catch); | ||
| 2432 | node.* = .{ | ||
| 2433 | .op_token = token, | ||
| 2434 | .lhs = undefined, // set by caller | ||
| 2435 | .rhs = undefined, // set by caller | ||
| 2436 | .payload = payload, | ||
| 2437 | }; | ||
| 2438 | return &node.base; | ||
| 2439 | }, | ||
| 2339 | else => { | 2440 | else => { |
| 2340 | p.putBackToken(token); | 2441 | p.putBackToken(token); |
| 2341 | return null; | 2442 | return null; |
| ... | @@ -2350,7 +2451,7 @@ const Parser = struct { | ... | @@ -2350,7 +2451,7 @@ const Parser = struct { |
| 2350 | /// / RARROW2 | 2451 | /// / RARROW2 |
| 2351 | fn parseBitShiftOp(p: *Parser) !?*Node { | 2452 | fn parseBitShiftOp(p: *Parser) !?*Node { |
| 2352 | const token = p.nextToken(); | 2453 | const token = p.nextToken(); |
| 2353 | const op: Node.InfixOp.Op = switch (p.token_ids[token]) { | 2454 | const op: Node.Tag = switch (p.token_ids[token]) { |
| 2354 | .AngleBracketAngleBracketLeft => .BitShiftLeft, | 2455 | .AngleBracketAngleBracketLeft => .BitShiftLeft, |
| 2355 | .AngleBracketAngleBracketRight => .BitShiftRight, | 2456 | .AngleBracketAngleBracketRight => .BitShiftRight, |
| 2356 | else => { | 2457 | else => { |
| ... | @@ -2370,7 +2471,7 @@ const Parser = struct { | ... | @@ -2370,7 +2471,7 @@ const Parser = struct { |
| 2370 | /// / MINUSPERCENT | 2471 | /// / MINUSPERCENT |
| 2371 | fn parseAdditionOp(p: *Parser) !?*Node { | 2472 | fn parseAdditionOp(p: *Parser) !?*Node { |
| 2372 | const token = p.nextToken(); | 2473 | const token = p.nextToken(); |
| 2373 | const op: Node.InfixOp.Op = switch (p.token_ids[token]) { | 2474 | const op: Node.Tag = switch (p.token_ids[token]) { |
| 2374 | .Plus => .Add, | 2475 | .Plus => .Add, |
| 2375 | .Minus => .Sub, | 2476 | .Minus => .Sub, |
| 2376 | .PlusPlus => .ArrayCat, | 2477 | .PlusPlus => .ArrayCat, |
| ... | @@ -2394,7 +2495,7 @@ const Parser = struct { | ... | @@ -2394,7 +2495,7 @@ const Parser = struct { |
| 2394 | /// / ASTERISKPERCENT | 2495 | /// / ASTERISKPERCENT |
| 2395 | fn parseMultiplyOp(p: *Parser) !?*Node { | 2496 | fn parseMultiplyOp(p: *Parser) !?*Node { |
| 2396 | const token = p.nextToken(); | 2497 | const token = p.nextToken(); |
| 2397 | const op: Node.InfixOp.Op = switch (p.token_ids[token]) { | 2498 | const op: Node.Tag = switch (p.token_ids[token]) { |
| 2398 | .PipePipe => .MergeErrorSets, | 2499 | .PipePipe => .MergeErrorSets, |
| 2399 | .Asterisk => .Mul, | 2500 | .Asterisk => .Mul, |
| 2400 | .Slash => .Div, | 2501 | .Slash => .Div, |
| ... | @@ -2673,14 +2774,14 @@ const Parser = struct { | ... | @@ -2673,14 +2774,14 @@ const Parser = struct { |
| 2673 | 2774 | ||
| 2674 | if (p.eatToken(.Period)) |period| { | 2775 | if (p.eatToken(.Period)) |period| { |
| 2675 | if (try p.parseIdentifier()) |identifier| { | 2776 | if (try p.parseIdentifier()) |identifier| { |
| 2676 | // TODO: It's a bit weird to return an InfixOp from the SuffixOp parser. | 2777 | // TODO: It's a bit weird to return a SimpleInfixOp from the SuffixOp parser. |
| 2677 | // Should there be an Node.SuffixOp.FieldAccess variant? Or should | 2778 | // Should there be an Node.SuffixOp.FieldAccess variant? Or should |
| 2678 | // this grammar rule be altered? | 2779 | // this grammar rule be altered? |
| 2679 | const node = try p.arena.allocator.create(Node.InfixOp); | 2780 | const node = try p.arena.allocator.create(Node.SimpleInfixOp); |
| 2680 | node.* = .{ | 2781 | node.* = .{ |
| 2782 | .base = Node{ .tag = .Period }, | ||
| 2681 | .op_token = period, | 2783 | .op_token = period, |
| 2682 | .lhs = undefined, // set by caller | 2784 | .lhs = undefined, // set by caller |
| 2683 | .op = .Period, | ||
| 2684 | .rhs = identifier, | 2785 | .rhs = identifier, |
| 2685 | }; | 2786 | }; |
| 2686 | return &node.base; | 2787 | return &node.base; |
| ... | @@ -2987,7 +3088,7 @@ const Parser = struct { | ... | @@ -2987,7 +3088,7 @@ const Parser = struct { |
| 2987 | }.parse; | 3088 | }.parse; |
| 2988 | } | 3089 | } |
| 2989 | 3090 | ||
| 2990 | fn SimpleBinOpParseFn(comptime token: Token.Id, comptime op: Node.InfixOp.Op) NodeParseFn { | 3091 | fn SimpleBinOpParseFn(comptime token: Token.Id, comptime op: Node.Tag) NodeParseFn { |
| 2991 | return struct { | 3092 | return struct { |
| 2992 | pub fn parse(p: *Parser) Error!?*Node { | 3093 | pub fn parse(p: *Parser) Error!?*Node { |
| 2993 | const op_token = if (token == .Keyword_and) switch (p.token_ids[p.tok_i]) { | 3094 | const op_token = if (token == .Keyword_and) switch (p.token_ids[p.tok_i]) { |
| ... | @@ -3001,11 +3102,11 @@ const Parser = struct { | ... | @@ -3001,11 +3102,11 @@ const Parser = struct { |
| 3001 | else => return null, | 3102 | else => return null, |
| 3002 | } else p.eatToken(token) orelse return null; | 3103 | } else p.eatToken(token) orelse return null; |
| 3003 | 3104 | ||
| 3004 | const node = try p.arena.allocator.create(Node.InfixOp); | 3105 | const node = try p.arena.allocator.create(Node.SimpleInfixOp); |
| 3005 | node.* = .{ | 3106 | node.* = .{ |
| 3107 | .base = .{ .tag = op }, | ||
| 3006 | .op_token = op_token, | 3108 | .op_token = op_token, |
| 3007 | .lhs = undefined, // set by caller | 3109 | .lhs = undefined, // set by caller |
| 3008 | .op = op, | ||
| 3009 | .rhs = undefined, // set by caller | 3110 | .rhs = undefined, // set by caller |
| 3010 | }; | 3111 | }; |
| 3011 | return &node.base; | 3112 | return &node.base; |
| ... | @@ -3350,9 +3451,13 @@ const Parser = struct { | ... | @@ -3350,9 +3451,13 @@ const Parser = struct { |
| 3350 | const left = res; | 3451 | const left = res; |
| 3351 | res = node; | 3452 | res = node; |
| 3352 | 3453 | ||
| 3353 | const op = node.cast(Node.InfixOp).?; | 3454 | if (node.castTag(.Catch)) |op| { |
| 3354 | op.*.lhs = left; | 3455 | op.lhs = left; |
| 3355 | op.*.rhs = right; | 3456 | op.rhs = right; |
| 3457 | } else if (node.cast(Node.SimpleInfixOp)) |op| { | ||
| 3458 | op.lhs = left; | ||
| 3459 | op.rhs = right; | ||
| 3460 | } | ||
| 3356 | 3461 | ||
| 3357 | switch (chain) { | 3462 | switch (chain) { |
| 3358 | .Once => break, | 3463 | .Once => break, |
| ... | @@ -3363,12 +3468,12 @@ const Parser = struct { | ... | @@ -3363,12 +3468,12 @@ const Parser = struct { |
| 3363 | return res; | 3468 | return res; |
| 3364 | } | 3469 | } |
| 3365 | 3470 | ||
| 3366 | fn createInfixOp(p: *Parser, index: TokenIndex, op: Node.InfixOp.Op) !*Node { | 3471 | fn createInfixOp(p: *Parser, op_token: TokenIndex, tag: Node.Tag) !*Node { |
| 3367 | const node = try p.arena.allocator.create(Node.InfixOp); | 3472 | const node = try p.arena.allocator.create(Node.SimpleInfixOp); |
| 3368 | node.* = .{ | 3473 | node.* = .{ |
| 3369 | .op_token = index, | 3474 | .base = Node{ .tag = tag }, |
| 3475 | .op_token = op_token, | ||
| 3370 | .lhs = undefined, // set by caller | 3476 | .lhs = undefined, // set by caller |
| 3371 | .op = op, | ||
| 3372 | .rhs = undefined, // set by caller | 3477 | .rhs = undefined, // set by caller |
| 3373 | }; | 3478 | }; |
| 3374 | return &node.base; | 3479 | return &node.base; |
lib/std/zig/render.zig+118-15| ... | @@ -436,13 +436,10 @@ fn renderExpression( | ... | @@ -436,13 +436,10 @@ fn renderExpression( |
| 436 | } | 436 | } |
| 437 | }, | 437 | }, |
| 438 | 438 | ||
| 439 | .InfixOp => { | 439 | .Catch => { |
| 440 | const infix_op_node = @fieldParentPtr(ast.Node.InfixOp, "base", base); | 440 | const infix_op_node = @fieldParentPtr(ast.Node.Catch, "base", base); |
| 441 | 441 | ||
| 442 | const op_space = switch (infix_op_node.op) { | 442 | const op_space = Space.Space; |
| 443 | ast.Node.InfixOp.Op.Period, ast.Node.InfixOp.Op.ErrorUnion, ast.Node.InfixOp.Op.Range => Space.None, | ||
| 444 | else => Space.Space, | ||
| 445 | }; | ||
| 446 | try renderExpression(allocator, stream, tree, indent, start_col, infix_op_node.lhs, op_space); | 443 | try renderExpression(allocator, stream, tree, indent, start_col, infix_op_node.lhs, op_space); |
| 447 | 444 | ||
| 448 | const after_op_space = blk: { | 445 | const after_op_space = blk: { |
| ... | @@ -458,11 +455,75 @@ fn renderExpression( | ... | @@ -458,11 +455,75 @@ fn renderExpression( |
| 458 | start_col.* = indent + indent_delta; | 455 | start_col.* = indent + indent_delta; |
| 459 | } | 456 | } |
| 460 | 457 | ||
| 461 | switch (infix_op_node.op) { | 458 | if (infix_op_node.payload) |payload| { |
| 462 | ast.Node.InfixOp.Op.Catch => |maybe_payload| if (maybe_payload) |payload| { | 459 | try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Space); |
| 463 | try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Space); | 460 | } |
| 464 | }, | 461 | |
| 465 | else => {}, | 462 | return renderExpression(allocator, stream, tree, indent, start_col, infix_op_node.rhs, space); |
| 463 | }, | ||
| 464 | |||
| 465 | .Add, | ||
| 466 | .AddWrap, | ||
| 467 | .ArrayCat, | ||
| 468 | .ArrayMult, | ||
| 469 | .Assign, | ||
| 470 | .AssignBitAnd, | ||
| 471 | .AssignBitOr, | ||
| 472 | .AssignBitShiftLeft, | ||
| 473 | .AssignBitShiftRight, | ||
| 474 | .AssignBitXor, | ||
| 475 | .AssignDiv, | ||
| 476 | .AssignSub, | ||
| 477 | .AssignSubWrap, | ||
| 478 | .AssignMod, | ||
| 479 | .AssignAdd, | ||
| 480 | .AssignAddWrap, | ||
| 481 | .AssignMul, | ||
| 482 | .AssignMulWrap, | ||
| 483 | .BangEqual, | ||
| 484 | .BitAnd, | ||
| 485 | .BitOr, | ||
| 486 | .BitShiftLeft, | ||
| 487 | .BitShiftRight, | ||
| 488 | .BitXor, | ||
| 489 | .BoolAnd, | ||
| 490 | .BoolOr, | ||
| 491 | .Div, | ||
| 492 | .EqualEqual, | ||
| 493 | .ErrorUnion, | ||
| 494 | .GreaterOrEqual, | ||
| 495 | .GreaterThan, | ||
| 496 | .LessOrEqual, | ||
| 497 | .LessThan, | ||
| 498 | .MergeErrorSets, | ||
| 499 | .Mod, | ||
| 500 | .Mul, | ||
| 501 | .MulWrap, | ||
| 502 | .Period, | ||
| 503 | .Range, | ||
| 504 | .Sub, | ||
| 505 | .SubWrap, | ||
| 506 | .UnwrapOptional, | ||
| 507 | => { | ||
| 508 | const infix_op_node = @fieldParentPtr(ast.Node.SimpleInfixOp, "base", base); | ||
| 509 | |||
| 510 | const op_space = switch (base.tag) { | ||
| 511 | .Period, .ErrorUnion, .Range => Space.None, | ||
| 512 | else => Space.Space, | ||
| 513 | }; | ||
| 514 | try renderExpression(allocator, stream, tree, indent, start_col, infix_op_node.lhs, op_space); | ||
| 515 | |||
| 516 | const after_op_space = blk: { | ||
| 517 | const loc = tree.tokenLocation(tree.token_locs[infix_op_node.op_token].end, tree.nextToken(infix_op_node.op_token)); | ||
| 518 | break :blk if (loc.line == 0) op_space else Space.Newline; | ||
| 519 | }; | ||
| 520 | |||
| 521 | try renderToken(tree, stream, infix_op_node.op_token, indent, start_col, after_op_space); | ||
| 522 | if (after_op_space == Space.Newline and | ||
| 523 | tree.token_ids[tree.nextToken(infix_op_node.op_token)] != .MultilineStringLiteralLine) | ||
| 524 | { | ||
| 525 | try stream.writeByteNTimes(' ', indent + indent_delta); | ||
| 526 | start_col.* = indent + indent_delta; | ||
| 466 | } | 527 | } |
| 467 | 528 | ||
| 468 | return renderExpression(allocator, stream, tree, indent, start_col, infix_op_node.rhs, space); | 529 | return renderExpression(allocator, stream, tree, indent, start_col, infix_op_node.rhs, space); |
| ... | @@ -2553,10 +2614,52 @@ fn nodeIsBlock(base: *const ast.Node) bool { | ... | @@ -2553,10 +2614,52 @@ fn nodeIsBlock(base: *const ast.Node) bool { |
| 2553 | } | 2614 | } |
| 2554 | 2615 | ||
| 2555 | fn nodeCausesSliceOpSpace(base: *ast.Node) bool { | 2616 | fn nodeCausesSliceOpSpace(base: *ast.Node) bool { |
| 2556 | const infix_op = base.cast(ast.Node.InfixOp) orelse return false; | 2617 | return switch (base.tag) { |
| 2557 | return switch (infix_op.op) { | 2618 | .Catch, |
| 2558 | ast.Node.InfixOp.Op.Period => false, | 2619 | .Add, |
| 2559 | else => true, | 2620 | .AddWrap, |
| 2621 | .ArrayCat, | ||
| 2622 | .ArrayMult, | ||
| 2623 | .Assign, | ||
| 2624 | .AssignBitAnd, | ||
| 2625 | .AssignBitOr, | ||
| 2626 | .AssignBitShiftLeft, | ||
| 2627 | .AssignBitShiftRight, | ||
| 2628 | .AssignBitXor, | ||
| 2629 | .AssignDiv, | ||
| 2630 | .AssignSub, | ||
| 2631 | .AssignSubWrap, | ||
| 2632 | .AssignMod, | ||
| 2633 | .AssignAdd, | ||
| 2634 | .AssignAddWrap, | ||
| 2635 | .AssignMul, | ||
| 2636 | .AssignMulWrap, | ||
| 2637 | .BangEqual, | ||
| 2638 | .BitAnd, | ||
| 2639 | .BitOr, | ||
| 2640 | .BitShiftLeft, | ||
| 2641 | .BitShiftRight, | ||
| 2642 | .BitXor, | ||
| 2643 | .BoolAnd, | ||
| 2644 | .BoolOr, | ||
| 2645 | .Div, | ||
| 2646 | .EqualEqual, | ||
| 2647 | .ErrorUnion, | ||
| 2648 | .GreaterOrEqual, | ||
| 2649 | .GreaterThan, | ||
| 2650 | .LessOrEqual, | ||
| 2651 | .LessThan, | ||
| 2652 | .MergeErrorSets, | ||
| 2653 | .Mod, | ||
| 2654 | .Mul, | ||
| 2655 | .MulWrap, | ||
| 2656 | .Range, | ||
| 2657 | .Sub, | ||
| 2658 | .SubWrap, | ||
| 2659 | .UnwrapOptional, | ||
| 2660 | => true, | ||
| 2661 | |||
| 2662 | else => false, | ||
| 2560 | }; | 2663 | }; |
| 2561 | } | 2664 | } |
| 2562 | 2665 |
src-self-hosted/Module.zig+1-1| ... | @@ -1954,7 +1954,7 @@ pub fn addZIRInstSpecial( | ... | @@ -1954,7 +1954,7 @@ pub fn addZIRInstSpecial( |
| 1954 | positionals: std.meta.fieldInfo(T, "positionals").field_type, | 1954 | positionals: std.meta.fieldInfo(T, "positionals").field_type, |
| 1955 | kw_args: std.meta.fieldInfo(T, "kw_args").field_type, | 1955 | kw_args: std.meta.fieldInfo(T, "kw_args").field_type, |
| 1956 | ) !*T { | 1956 | ) !*T { |
| 1957 | const gen_zir = scope.cast(Scope.GenZIR).?; | 1957 | const gen_zir = scope.getGenZIR(); |
| 1958 | try gen_zir.instructions.ensureCapacity(self.gpa, gen_zir.instructions.items.len + 1); | 1958 | try gen_zir.instructions.ensureCapacity(self.gpa, gen_zir.instructions.items.len + 1); |
| 1959 | const inst = try newZIRInst(gen_zir.arena, src, T, positionals, kw_args); | 1959 | const inst = try newZIRInst(gen_zir.arena, src, T, positionals, kw_args); |
| 1960 | gen_zir.instructions.appendAssumeCapacity(&inst.base); | 1960 | gen_zir.instructions.appendAssumeCapacity(&inst.base); |
src-self-hosted/astgen.zig+105-71| ... | @@ -12,22 +12,29 @@ const Scope = Module.Scope; | ... | @@ -12,22 +12,29 @@ const Scope = Module.Scope; |
| 12 | const InnerError = Module.InnerError; | 12 | const InnerError = Module.InnerError; |
| 13 | 13 | ||
| 14 | /// Turn Zig AST into untyped ZIR istructions. | 14 | /// Turn Zig AST into untyped ZIR istructions. |
| 15 | pub fn expr(mod: *Module, scope: *Scope, ast_node: *ast.Node) InnerError!*zir.Inst { | 15 | pub fn expr(mod: *Module, scope: *Scope, node: *ast.Node) InnerError!*zir.Inst { |
| 16 | switch (ast_node.tag) { | 16 | switch (node.tag) { |
| 17 | .VarDecl => unreachable, // Handled in `blockExpr`. | 17 | .VarDecl => unreachable, // Handled in `blockExpr`. |
| 18 | 18 | ||
| 19 | .Identifier => return identifier(mod, scope, @fieldParentPtr(ast.Node.Identifier, "base", ast_node)), | 19 | .Identifier => return identifier(mod, scope, node.castTag(.Identifier).?), |
| 20 | .Asm => return assembly(mod, scope, @fieldParentPtr(ast.Node.Asm, "base", ast_node)), | 20 | .Asm => return assembly(mod, scope, node.castTag(.Asm).?), |
| 21 | .StringLiteral => return stringLiteral(mod, scope, @fieldParentPtr(ast.Node.StringLiteral, "base", ast_node)), | 21 | .StringLiteral => return stringLiteral(mod, scope, node.castTag(.StringLiteral).?), |
| 22 | .IntegerLiteral => return integerLiteral(mod, scope, @fieldParentPtr(ast.Node.IntegerLiteral, "base", ast_node)), | 22 | .IntegerLiteral => return integerLiteral(mod, scope, node.castTag(.IntegerLiteral).?), |
| 23 | .BuiltinCall => return builtinCall(mod, scope, @fieldParentPtr(ast.Node.BuiltinCall, "base", ast_node)), | 23 | .BuiltinCall => return builtinCall(mod, scope, node.castTag(.BuiltinCall).?), |
| 24 | .Call => return callExpr(mod, scope, @fieldParentPtr(ast.Node.Call, "base", ast_node)), | 24 | .Call => return callExpr(mod, scope, node.castTag(.Call).?), |
| 25 | .Unreachable => return unreach(mod, scope, @fieldParentPtr(ast.Node.Unreachable, "base", ast_node)), | 25 | .Unreachable => return unreach(mod, scope, node.castTag(.Unreachable).?), |
| 26 | .ControlFlowExpression => return controlFlowExpr(mod, scope, @fieldParentPtr(ast.Node.ControlFlowExpression, "base", ast_node)), | 26 | .ControlFlowExpression => return controlFlowExpr(mod, scope, node.castTag(.ControlFlowExpression).?), |
| 27 | .If => return ifExpr(mod, scope, @fieldParentPtr(ast.Node.If, "base", ast_node)), | 27 | .If => return ifExpr(mod, scope, node.castTag(.If).?), |
| 28 | .InfixOp => return infixOp(mod, scope, @fieldParentPtr(ast.Node.InfixOp, "base", ast_node)), | 28 | .Assign => return assign(mod, scope, node.castTag(.Assign).?), |
| 29 | .BoolNot => return boolNot(mod, scope, @fieldParentPtr(ast.Node.SimplePrefixOp, "base", ast_node)), | 29 | .Add => return add(mod, scope, node.castTag(.Add).?), |
| 30 | else => return mod.failNode(scope, ast_node, "TODO implement astgen.Expr for {}", .{@tagName(ast_node.tag)}), | 30 | .BangEqual => return cmp(mod, scope, node.castTag(.BangEqual).?, .neq), |
| 31 | .EqualEqual => return cmp(mod, scope, node.castTag(.EqualEqual).?, .eq), | ||
| 32 | .GreaterThan => return cmp(mod, scope, node.castTag(.GreaterThan).?, .gt), | ||
| 33 | .GreaterOrEqual => return cmp(mod, scope, node.castTag(.GreaterOrEqual).?, .gte), | ||
| 34 | .LessThan => return cmp(mod, scope, node.castTag(.LessThan).?, .lt), | ||
| 35 | .LessOrEqual => return cmp(mod, scope, node.castTag(.LessOrEqual).?, .lte), | ||
| 36 | .BoolNot => return boolNot(mod, scope, node.castTag(.BoolNot).?), | ||
| 37 | else => return mod.failNode(scope, node, "TODO implement astgen.Expr for {}", .{@tagName(node.tag)}), | ||
| 31 | } | 38 | } |
| 32 | } | 39 | } |
| 33 | 40 | ||
| ... | @@ -57,6 +64,7 @@ pub fn blockExpr(mod: *Module, parent_scope: *Scope, block_node: *ast.Node.Block | ... | @@ -57,6 +64,7 @@ pub fn blockExpr(mod: *Module, parent_scope: *Scope, block_node: *ast.Node.Block |
| 57 | } | 64 | } |
| 58 | 65 | ||
| 59 | fn varDecl(mod: *Module, scope: *Scope, node: *ast.Node.VarDecl) InnerError!Scope.LocalVar { | 66 | fn varDecl(mod: *Module, scope: *Scope, node: *ast.Node.VarDecl) InnerError!Scope.LocalVar { |
| 67 | // TODO implement detection of shadowing | ||
| 60 | if (node.getTrailer("comptime_token")) |comptime_token| { | 68 | if (node.getTrailer("comptime_token")) |comptime_token| { |
| 61 | return mod.failTok(scope, comptime_token, "TODO implement comptime locals", .{}); | 69 | return mod.failTok(scope, comptime_token, "TODO implement comptime locals", .{}); |
| 62 | } | 70 | } |
| ... | @@ -98,64 +106,48 @@ fn boolNot(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerErr | ... | @@ -98,64 +106,48 @@ fn boolNot(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerErr |
| 98 | return mod.addZIRInst(scope, src, zir.Inst.BoolNot, .{ .operand = operand }, .{}); | 106 | return mod.addZIRInst(scope, src, zir.Inst.BoolNot, .{ .operand = operand }, .{}); |
| 99 | } | 107 | } |
| 100 | 108 | ||
| 101 | fn infixOp(mod: *Module, scope: *Scope, infix_node: *ast.Node.InfixOp) InnerError!*zir.Inst { | 109 | fn assign(mod: *Module, scope: *Scope, infix_node: *ast.Node.SimpleInfixOp) InnerError!*zir.Inst { |
| 102 | switch (infix_node.op) { | 110 | if (infix_node.lhs.tag == .Identifier) { |
| 103 | .Assign => { | 111 | const ident = @fieldParentPtr(ast.Node.Identifier, "base", infix_node.lhs); |
| 104 | if (infix_node.lhs.tag == .Identifier) { | 112 | const tree = scope.tree(); |
| 105 | const ident = @fieldParentPtr(ast.Node.Identifier, "base", infix_node.lhs); | 113 | const ident_name = tree.tokenSlice(ident.token); |
| 106 | const tree = scope.tree(); | 114 | if (std.mem.eql(u8, ident_name, "_")) { |
| 107 | const ident_name = tree.tokenSlice(ident.token); | 115 | return expr(mod, scope, infix_node.rhs); |
| 108 | if (std.mem.eql(u8, ident_name, "_")) { | 116 | } else { |
| 109 | return expr(mod, scope, infix_node.rhs); | 117 | return mod.failNode(scope, &infix_node.base, "TODO implement infix operator assign", .{}); |
| 110 | } else { | 118 | } |
| 111 | return mod.failNode(scope, &infix_node.base, "TODO implement infix operator assign", .{}); | 119 | } else { |
| 112 | } | 120 | return mod.failNode(scope, &infix_node.base, "TODO implement infix operator assign", .{}); |
| 113 | } else { | 121 | } |
| 114 | return mod.failNode(scope, &infix_node.base, "TODO implement infix operator assign", .{}); | 122 | } |
| 115 | } | ||
| 116 | }, | ||
| 117 | .Add => { | ||
| 118 | const lhs = try expr(mod, scope, infix_node.lhs); | ||
| 119 | const rhs = try expr(mod, scope, infix_node.rhs); | ||
| 120 | 123 | ||
| 121 | const tree = scope.tree(); | 124 | fn add(mod: *Module, scope: *Scope, infix_node: *ast.Node.SimpleInfixOp) InnerError!*zir.Inst { |
| 122 | const src = tree.token_locs[infix_node.op_token].start; | 125 | const lhs = try expr(mod, scope, infix_node.lhs); |
| 126 | const rhs = try expr(mod, scope, infix_node.rhs); | ||
| 123 | 127 | ||
| 124 | return mod.addZIRInst(scope, src, zir.Inst.Add, .{ .lhs = lhs, .rhs = rhs }, .{}); | 128 | const tree = scope.tree(); |
| 125 | }, | 129 | const src = tree.token_locs[infix_node.op_token].start; |
| 126 | .BangEqual, | ||
| 127 | .EqualEqual, | ||
| 128 | .GreaterThan, | ||
| 129 | .GreaterOrEqual, | ||
| 130 | .LessThan, | ||
| 131 | .LessOrEqual, | ||
| 132 | => { | ||
| 133 | const lhs = try expr(mod, scope, infix_node.lhs); | ||
| 134 | const rhs = try expr(mod, scope, infix_node.rhs); | ||
| 135 | |||
| 136 | const tree = scope.tree(); | ||
| 137 | const src = tree.token_locs[infix_node.op_token].start; | ||
| 138 | |||
| 139 | const op: std.math.CompareOperator = switch (infix_node.op) { | ||
| 140 | .BangEqual => .neq, | ||
| 141 | .EqualEqual => .eq, | ||
| 142 | .GreaterThan => .gt, | ||
| 143 | .GreaterOrEqual => .gte, | ||
| 144 | .LessThan => .lt, | ||
| 145 | .LessOrEqual => .lte, | ||
| 146 | else => unreachable, | ||
| 147 | }; | ||
| 148 | 130 | ||
| 149 | return mod.addZIRInst(scope, src, zir.Inst.Cmp, .{ | 131 | return mod.addZIRInst(scope, src, zir.Inst.Add, .{ .lhs = lhs, .rhs = rhs }, .{}); |
| 150 | .lhs = lhs, | 132 | } |
| 151 | .op = op, | 133 | |
| 152 | .rhs = rhs, | 134 | fn cmp( |
| 153 | }, .{}); | 135 | mod: *Module, |
| 154 | }, | 136 | scope: *Scope, |
| 155 | else => |op| { | 137 | infix_node: *ast.Node.SimpleInfixOp, |
| 156 | return mod.failNode(scope, &infix_node.base, "TODO implement infix operator {}", .{op}); | 138 | op: std.math.CompareOperator, |
| 157 | }, | 139 | ) InnerError!*zir.Inst { |
| 158 | } | 140 | const lhs = try expr(mod, scope, infix_node.lhs); |
| 141 | const rhs = try expr(mod, scope, infix_node.rhs); | ||
| 142 | |||
| 143 | const tree = scope.tree(); | ||
| 144 | const src = tree.token_locs[infix_node.op_token].start; | ||
| 145 | |||
| 146 | return mod.addZIRInst(scope, src, zir.Inst.Cmp, .{ | ||
| 147 | .lhs = lhs, | ||
| 148 | .op = op, | ||
| 149 | .rhs = rhs, | ||
| 150 | }, .{}); | ||
| 159 | } | 151 | } |
| 160 | 152 | ||
| 161 | fn ifExpr(mod: *Module, scope: *Scope, if_node: *ast.Node.If) InnerError!*zir.Inst { | 153 | fn ifExpr(mod: *Module, scope: *Scope, if_node: *ast.Node.If) InnerError!*zir.Inst { |
| ... | @@ -571,6 +563,47 @@ fn nodeNeedsMemoryLocation(node: *ast.Node) bool { | ... | @@ -571,6 +563,47 @@ fn nodeNeedsMemoryLocation(node: *ast.Node) bool { |
| 571 | .ErrorSetDecl, | 563 | .ErrorSetDecl, |
| 572 | .ContainerDecl, | 564 | .ContainerDecl, |
| 573 | .Asm, | 565 | .Asm, |
| 566 | .Add, | ||
| 567 | .AddWrap, | ||
| 568 | .ArrayCat, | ||
| 569 | .ArrayMult, | ||
| 570 | .Assign, | ||
| 571 | .AssignBitAnd, | ||
| 572 | .AssignBitOr, | ||
| 573 | .AssignBitShiftLeft, | ||
| 574 | .AssignBitShiftRight, | ||
| 575 | .AssignBitXor, | ||
| 576 | .AssignDiv, | ||
| 577 | .AssignSub, | ||
| 578 | .AssignSubWrap, | ||
| 579 | .AssignMod, | ||
| 580 | .AssignAdd, | ||
| 581 | .AssignAddWrap, | ||
| 582 | .AssignMul, | ||
| 583 | .AssignMulWrap, | ||
| 584 | .BangEqual, | ||
| 585 | .BitAnd, | ||
| 586 | .BitOr, | ||
| 587 | .BitShiftLeft, | ||
| 588 | .BitShiftRight, | ||
| 589 | .BitXor, | ||
| 590 | .BoolAnd, | ||
| 591 | .BoolOr, | ||
| 592 | .Div, | ||
| 593 | .EqualEqual, | ||
| 594 | .ErrorUnion, | ||
| 595 | .GreaterOrEqual, | ||
| 596 | .GreaterThan, | ||
| 597 | .LessOrEqual, | ||
| 598 | .LessThan, | ||
| 599 | .MergeErrorSets, | ||
| 600 | .Mod, | ||
| 601 | .Mul, | ||
| 602 | .MulWrap, | ||
| 603 | .Range, | ||
| 604 | .Period, | ||
| 605 | .Sub, | ||
| 606 | .SubWrap, | ||
| 574 | => false, | 607 | => false, |
| 575 | 608 | ||
| 576 | .ArrayInitializer, | 609 | .ArrayInitializer, |
| ... | @@ -579,9 +612,10 @@ fn nodeNeedsMemoryLocation(node: *ast.Node) bool { | ... | @@ -579,9 +612,10 @@ fn nodeNeedsMemoryLocation(node: *ast.Node) bool { |
| 579 | .StructInitializerDot, | 612 | .StructInitializerDot, |
| 580 | => true, | 613 | => true, |
| 581 | 614 | ||
| 582 | .GroupedExpression => nodeNeedsMemoryLocation(node.cast(ast.Node.GroupedExpression).?.expr), | 615 | .GroupedExpression => nodeNeedsMemoryLocation(node.castTag(.GroupedExpression).?.expr), |
| 583 | 616 | ||
| 584 | .InfixOp => @panic("TODO nodeNeedsMemoryLocation for InfixOp"), | 617 | .UnwrapOptional => @panic("TODO nodeNeedsMemoryLocation for UnwrapOptional"), |
| 618 | .Catch => @panic("TODO nodeNeedsMemoryLocation for Catch"), | ||
| 585 | .Await => @panic("TODO nodeNeedsMemoryLocation for Await"), | 619 | .Await => @panic("TODO nodeNeedsMemoryLocation for Await"), |
| 586 | .Try => @panic("TODO nodeNeedsMemoryLocation for Try"), | 620 | .Try => @panic("TODO nodeNeedsMemoryLocation for Try"), |
| 587 | .If => @panic("TODO nodeNeedsMemoryLocation for If"), | 621 | .If => @panic("TODO nodeNeedsMemoryLocation for If"), |
src-self-hosted/translate_c.zig+105-60| ... | @@ -1103,11 +1103,11 @@ fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.No | ... | @@ -1103,11 +1103,11 @@ fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.No |
| 1103 | const enum_ident = try transCreateNodeIdentifier(c, name); | 1103 | const enum_ident = try transCreateNodeIdentifier(c, name); |
| 1104 | const period_tok = try appendToken(c, .Period, "."); | 1104 | const period_tok = try appendToken(c, .Period, "."); |
| 1105 | const field_ident = try transCreateNodeIdentifier(c, field_name); | 1105 | const field_ident = try transCreateNodeIdentifier(c, field_name); |
| 1106 | const field_access_node = try c.arena.create(ast.Node.InfixOp); | 1106 | const field_access_node = try c.arena.create(ast.Node.SimpleInfixOp); |
| 1107 | field_access_node.* = .{ | 1107 | field_access_node.* = .{ |
| 1108 | .base = .{ .tag = .Period }, | ||
| 1108 | .op_token = period_tok, | 1109 | .op_token = period_tok, |
| 1109 | .lhs = enum_ident, | 1110 | .lhs = enum_ident, |
| 1110 | .op = .Period, | ||
| 1111 | .rhs = field_ident, | 1111 | .rhs = field_ident, |
| 1112 | }; | 1112 | }; |
| 1113 | cast_node.params()[0] = &field_access_node.base; | 1113 | cast_node.params()[0] = &field_access_node.base; |
| ... | @@ -1294,7 +1294,7 @@ fn transBinaryOperator( | ... | @@ -1294,7 +1294,7 @@ fn transBinaryOperator( |
| 1294 | const op = ZigClangBinaryOperator_getOpcode(stmt); | 1294 | const op = ZigClangBinaryOperator_getOpcode(stmt); |
| 1295 | const qt = ZigClangBinaryOperator_getType(stmt); | 1295 | const qt = ZigClangBinaryOperator_getType(stmt); |
| 1296 | var op_token: ast.TokenIndex = undefined; | 1296 | var op_token: ast.TokenIndex = undefined; |
| 1297 | var op_id: ast.Node.InfixOp.Op = undefined; | 1297 | var op_id: ast.Node.Tag = undefined; |
| 1298 | switch (op) { | 1298 | switch (op) { |
| 1299 | .Assign => return try transCreateNodeAssign(rp, scope, result_used, ZigClangBinaryOperator_getLHS(stmt), ZigClangBinaryOperator_getRHS(stmt)), | 1299 | .Assign => return try transCreateNodeAssign(rp, scope, result_used, ZigClangBinaryOperator_getLHS(stmt), ZigClangBinaryOperator_getRHS(stmt)), |
| 1300 | .Comma => { | 1300 | .Comma => { |
| ... | @@ -1737,25 +1737,22 @@ fn exprIsStringLiteral(expr: *const ZigClangExpr) bool { | ... | @@ -1737,25 +1737,22 @@ fn exprIsStringLiteral(expr: *const ZigClangExpr) bool { |
| 1737 | 1737 | ||
| 1738 | fn isBoolRes(res: *ast.Node) bool { | 1738 | fn isBoolRes(res: *ast.Node) bool { |
| 1739 | switch (res.tag) { | 1739 | switch (res.tag) { |
| 1740 | .InfixOp => switch (@fieldParentPtr(ast.Node.InfixOp, "base", res).op) { | 1740 | .BoolOr, |
| 1741 | .BoolOr, | 1741 | .BoolAnd, |
| 1742 | .BoolAnd, | 1742 | .EqualEqual, |
| 1743 | .EqualEqual, | 1743 | .BangEqual, |
| 1744 | .BangEqual, | 1744 | .LessThan, |
| 1745 | .LessThan, | 1745 | .GreaterThan, |
| 1746 | .GreaterThan, | 1746 | .LessOrEqual, |
| 1747 | .LessOrEqual, | 1747 | .GreaterOrEqual, |
| 1748 | .GreaterOrEqual, | 1748 | .BoolNot, |
| 1749 | => return true, | 1749 | .BoolLiteral, |
| 1750 | => return true, | ||
| 1750 | 1751 | ||
| 1751 | else => {}, | ||
| 1752 | }, | ||
| 1753 | .BoolNot => return true, | ||
| 1754 | .BoolLiteral => return true, | ||
| 1755 | .GroupedExpression => return isBoolRes(@fieldParentPtr(ast.Node.GroupedExpression, "base", res).expr), | 1752 | .GroupedExpression => return isBoolRes(@fieldParentPtr(ast.Node.GroupedExpression, "base", res).expr), |
| 1756 | else => {}, | 1753 | |
| 1754 | else => return false, | ||
| 1757 | } | 1755 | } |
| 1758 | return false; | ||
| 1759 | } | 1756 | } |
| 1760 | 1757 | ||
| 1761 | fn finishBoolExpr( | 1758 | fn finishBoolExpr( |
| ... | @@ -2312,11 +2309,11 @@ fn transInitListExprArray( | ... | @@ -2312,11 +2309,11 @@ fn transInitListExprArray( |
| 2312 | &filler_init_node.base | 2309 | &filler_init_node.base |
| 2313 | else blk: { | 2310 | else blk: { |
| 2314 | const mul_tok = try appendToken(rp.c, .AsteriskAsterisk, "**"); | 2311 | const mul_tok = try appendToken(rp.c, .AsteriskAsterisk, "**"); |
| 2315 | const mul_node = try rp.c.arena.create(ast.Node.InfixOp); | 2312 | const mul_node = try rp.c.arena.create(ast.Node.SimpleInfixOp); |
| 2316 | mul_node.* = .{ | 2313 | mul_node.* = .{ |
| 2314 | .base = .{ .tag = .ArrayMult }, | ||
| 2317 | .op_token = mul_tok, | 2315 | .op_token = mul_tok, |
| 2318 | .lhs = &filler_init_node.base, | 2316 | .lhs = &filler_init_node.base, |
| 2319 | .op = .ArrayMult, | ||
| 2320 | .rhs = try transCreateNodeInt(rp.c, leftover_count), | 2317 | .rhs = try transCreateNodeInt(rp.c, leftover_count), |
| 2321 | }; | 2318 | }; |
| 2322 | break :blk &mul_node.base; | 2319 | break :blk &mul_node.base; |
| ... | @@ -2326,11 +2323,11 @@ fn transInitListExprArray( | ... | @@ -2326,11 +2323,11 @@ fn transInitListExprArray( |
| 2326 | return rhs_node; | 2323 | return rhs_node; |
| 2327 | } | 2324 | } |
| 2328 | 2325 | ||
| 2329 | const cat_node = try rp.c.arena.create(ast.Node.InfixOp); | 2326 | const cat_node = try rp.c.arena.create(ast.Node.SimpleInfixOp); |
| 2330 | cat_node.* = .{ | 2327 | cat_node.* = .{ |
| 2328 | .base = .{ .tag = .ArrayCat }, | ||
| 2331 | .op_token = cat_tok, | 2329 | .op_token = cat_tok, |
| 2332 | .lhs = &init_node.base, | 2330 | .lhs = &init_node.base, |
| 2333 | .op = .ArrayCat, | ||
| 2334 | .rhs = rhs_node, | 2331 | .rhs = rhs_node, |
| 2335 | }; | 2332 | }; |
| 2336 | return &cat_node.base; | 2333 | return &cat_node.base; |
| ... | @@ -2723,11 +2720,11 @@ fn transCase( | ... | @@ -2723,11 +2720,11 @@ fn transCase( |
| 2723 | const ellips = try appendToken(rp.c, .Ellipsis3, "..."); | 2720 | const ellips = try appendToken(rp.c, .Ellipsis3, "..."); |
| 2724 | const rhs_node = try transExpr(rp, scope, rhs, .used, .r_value); | 2721 | const rhs_node = try transExpr(rp, scope, rhs, .used, .r_value); |
| 2725 | 2722 | ||
| 2726 | const node = try rp.c.arena.create(ast.Node.InfixOp); | 2723 | const node = try rp.c.arena.create(ast.Node.SimpleInfixOp); |
| 2727 | node.* = .{ | 2724 | node.* = .{ |
| 2725 | .base = .{ .tag = .Range }, | ||
| 2728 | .op_token = ellips, | 2726 | .op_token = ellips, |
| 2729 | .lhs = lhs_node, | 2727 | .lhs = lhs_node, |
| 2730 | .op = .Range, | ||
| 2731 | .rhs = rhs_node, | 2728 | .rhs = rhs_node, |
| 2732 | }; | 2729 | }; |
| 2733 | break :blk &node.base; | 2730 | break :blk &node.base; |
| ... | @@ -3153,7 +3150,7 @@ fn transCreatePreCrement( | ... | @@ -3153,7 +3150,7 @@ fn transCreatePreCrement( |
| 3153 | rp: RestorePoint, | 3150 | rp: RestorePoint, |
| 3154 | scope: *Scope, | 3151 | scope: *Scope, |
| 3155 | stmt: *const ZigClangUnaryOperator, | 3152 | stmt: *const ZigClangUnaryOperator, |
| 3156 | op: ast.Node.InfixOp.Op, | 3153 | op: ast.Node.Tag, |
| 3157 | op_tok_id: std.zig.Token.Id, | 3154 | op_tok_id: std.zig.Token.Id, |
| 3158 | bytes: []const u8, | 3155 | bytes: []const u8, |
| 3159 | used: ResultUsed, | 3156 | used: ResultUsed, |
| ... | @@ -3227,7 +3224,7 @@ fn transCreatePostCrement( | ... | @@ -3227,7 +3224,7 @@ fn transCreatePostCrement( |
| 3227 | rp: RestorePoint, | 3224 | rp: RestorePoint, |
| 3228 | scope: *Scope, | 3225 | scope: *Scope, |
| 3229 | stmt: *const ZigClangUnaryOperator, | 3226 | stmt: *const ZigClangUnaryOperator, |
| 3230 | op: ast.Node.InfixOp.Op, | 3227 | op: ast.Node.Tag, |
| 3231 | op_tok_id: std.zig.Token.Id, | 3228 | op_tok_id: std.zig.Token.Id, |
| 3232 | bytes: []const u8, | 3229 | bytes: []const u8, |
| 3233 | used: ResultUsed, | 3230 | used: ResultUsed, |
| ... | @@ -3349,10 +3346,10 @@ fn transCreateCompoundAssign( | ... | @@ -3349,10 +3346,10 @@ fn transCreateCompoundAssign( |
| 3349 | rp: RestorePoint, | 3346 | rp: RestorePoint, |
| 3350 | scope: *Scope, | 3347 | scope: *Scope, |
| 3351 | stmt: *const ZigClangCompoundAssignOperator, | 3348 | stmt: *const ZigClangCompoundAssignOperator, |
| 3352 | assign_op: ast.Node.InfixOp.Op, | 3349 | assign_op: ast.Node.Tag, |
| 3353 | assign_tok_id: std.zig.Token.Id, | 3350 | assign_tok_id: std.zig.Token.Id, |
| 3354 | assign_bytes: []const u8, | 3351 | assign_bytes: []const u8, |
| 3355 | bin_op: ast.Node.InfixOp.Op, | 3352 | bin_op: ast.Node.Tag, |
| 3356 | bin_tok_id: std.zig.Token.Id, | 3353 | bin_tok_id: std.zig.Token.Id, |
| 3357 | bin_bytes: []const u8, | 3354 | bin_bytes: []const u8, |
| 3358 | used: ResultUsed, | 3355 | used: ResultUsed, |
| ... | @@ -3377,7 +3374,7 @@ fn transCreateCompoundAssign( | ... | @@ -3377,7 +3374,7 @@ fn transCreateCompoundAssign( |
| 3377 | // zig: lhs += rhs | 3374 | // zig: lhs += rhs |
| 3378 | if ((is_mod or is_div) and is_signed) { | 3375 | if ((is_mod or is_div) and is_signed) { |
| 3379 | const op_token = try appendToken(rp.c, .Equal, "="); | 3376 | const op_token = try appendToken(rp.c, .Equal, "="); |
| 3380 | const op_node = try rp.c.arena.create(ast.Node.InfixOp); | 3377 | const op_node = try rp.c.arena.create(ast.Node.SimpleInfixOp); |
| 3381 | const builtin = if (is_mod) "@rem" else "@divTrunc"; | 3378 | const builtin = if (is_mod) "@rem" else "@divTrunc"; |
| 3382 | const builtin_node = try rp.c.createBuiltinCall(builtin, 2); | 3379 | const builtin_node = try rp.c.createBuiltinCall(builtin, 2); |
| 3383 | const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value); | 3380 | const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value); |
| ... | @@ -3386,9 +3383,9 @@ fn transCreateCompoundAssign( | ... | @@ -3386,9 +3383,9 @@ fn transCreateCompoundAssign( |
| 3386 | builtin_node.params()[1] = try transExpr(rp, scope, rhs, .used, .r_value); | 3383 | builtin_node.params()[1] = try transExpr(rp, scope, rhs, .used, .r_value); |
| 3387 | builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | 3384 | builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); |
| 3388 | op_node.* = .{ | 3385 | op_node.* = .{ |
| 3386 | .base = .{ .tag = .Assign }, | ||
| 3389 | .op_token = op_token, | 3387 | .op_token = op_token, |
| 3390 | .lhs = lhs_node, | 3388 | .lhs = lhs_node, |
| 3391 | .op = .Assign, | ||
| 3392 | .rhs = &builtin_node.base, | 3389 | .rhs = &builtin_node.base, |
| 3393 | }; | 3390 | }; |
| 3394 | _ = try appendToken(rp.c, .Semicolon, ";"); | 3391 | _ = try appendToken(rp.c, .Semicolon, ";"); |
| ... | @@ -3452,7 +3449,7 @@ fn transCreateCompoundAssign( | ... | @@ -3452,7 +3449,7 @@ fn transCreateCompoundAssign( |
| 3452 | 3449 | ||
| 3453 | if ((is_mod or is_div) and is_signed) { | 3450 | if ((is_mod or is_div) and is_signed) { |
| 3454 | const op_token = try appendToken(rp.c, .Equal, "="); | 3451 | const op_token = try appendToken(rp.c, .Equal, "="); |
| 3455 | const op_node = try rp.c.arena.create(ast.Node.InfixOp); | 3452 | const op_node = try rp.c.arena.create(ast.Node.SimpleInfixOp); |
| 3456 | const builtin = if (is_mod) "@rem" else "@divTrunc"; | 3453 | const builtin = if (is_mod) "@rem" else "@divTrunc"; |
| 3457 | const builtin_node = try rp.c.createBuiltinCall(builtin, 2); | 3454 | const builtin_node = try rp.c.createBuiltinCall(builtin, 2); |
| 3458 | builtin_node.params()[0] = try transCreateNodePtrDeref(rp.c, lhs_node); | 3455 | builtin_node.params()[0] = try transCreateNodePtrDeref(rp.c, lhs_node); |
| ... | @@ -3461,9 +3458,9 @@ fn transCreateCompoundAssign( | ... | @@ -3461,9 +3458,9 @@ fn transCreateCompoundAssign( |
| 3461 | builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | 3458 | builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); |
| 3462 | _ = try appendToken(rp.c, .Semicolon, ";"); | 3459 | _ = try appendToken(rp.c, .Semicolon, ";"); |
| 3463 | op_node.* = .{ | 3460 | op_node.* = .{ |
| 3461 | .base = .{ .tag = .Assign }, | ||
| 3464 | .op_token = op_token, | 3462 | .op_token = op_token, |
| 3465 | .lhs = ref_node, | 3463 | .lhs = ref_node, |
| 3466 | .op = .Assign, | ||
| 3467 | .rhs = &builtin_node.base, | 3464 | .rhs = &builtin_node.base, |
| 3468 | }; | 3465 | }; |
| 3469 | _ = try appendToken(rp.c, .Semicolon, ";"); | 3466 | _ = try appendToken(rp.c, .Semicolon, ";"); |
| ... | @@ -3716,11 +3713,11 @@ fn maybeSuppressResult( | ... | @@ -3716,11 +3713,11 @@ fn maybeSuppressResult( |
| 3716 | } | 3713 | } |
| 3717 | const lhs = try transCreateNodeIdentifier(rp.c, "_"); | 3714 | const lhs = try transCreateNodeIdentifier(rp.c, "_"); |
| 3718 | const op_token = try appendToken(rp.c, .Equal, "="); | 3715 | const op_token = try appendToken(rp.c, .Equal, "="); |
| 3719 | const op_node = try rp.c.arena.create(ast.Node.InfixOp); | 3716 | const op_node = try rp.c.arena.create(ast.Node.SimpleInfixOp); |
| 3720 | op_node.* = .{ | 3717 | op_node.* = .{ |
| 3718 | .base = .{ .tag = .Assign }, | ||
| 3721 | .op_token = op_token, | 3719 | .op_token = op_token, |
| 3722 | .lhs = lhs, | 3720 | .lhs = lhs, |
| 3723 | .op = .Assign, | ||
| 3724 | .rhs = result, | 3721 | .rhs = result, |
| 3725 | }; | 3722 | }; |
| 3726 | return &op_node.base; | 3723 | return &op_node.base; |
| ... | @@ -4095,11 +4092,11 @@ fn transCreateNodeAssign( | ... | @@ -4095,11 +4092,11 @@ fn transCreateNodeAssign( |
| 4095 | } | 4092 | } |
| 4096 | 4093 | ||
| 4097 | fn transCreateNodeFieldAccess(c: *Context, container: *ast.Node, field_name: []const u8) !*ast.Node { | 4094 | fn transCreateNodeFieldAccess(c: *Context, container: *ast.Node, field_name: []const u8) !*ast.Node { |
| 4098 | const field_access_node = try c.arena.create(ast.Node.InfixOp); | 4095 | const field_access_node = try c.arena.create(ast.Node.SimpleInfixOp); |
| 4099 | field_access_node.* = .{ | 4096 | field_access_node.* = .{ |
| 4097 | .base = .{ .tag = .Period }, | ||
| 4100 | .op_token = try appendToken(c, .Period, "."), | 4098 | .op_token = try appendToken(c, .Period, "."), |
| 4101 | .lhs = container, | 4099 | .lhs = container, |
| 4102 | .op = .Period, | ||
| 4103 | .rhs = try transCreateNodeIdentifier(c, field_name), | 4100 | .rhs = try transCreateNodeIdentifier(c, field_name), |
| 4104 | }; | 4101 | }; |
| 4105 | return &field_access_node.base; | 4102 | return &field_access_node.base; |
| ... | @@ -4124,7 +4121,7 @@ fn transCreateNodeInfixOp( | ... | @@ -4124,7 +4121,7 @@ fn transCreateNodeInfixOp( |
| 4124 | rp: RestorePoint, | 4121 | rp: RestorePoint, |
| 4125 | scope: *Scope, | 4122 | scope: *Scope, |
| 4126 | lhs_node: *ast.Node, | 4123 | lhs_node: *ast.Node, |
| 4127 | op: ast.Node.InfixOp.Op, | 4124 | op: ast.Node.Tag, |
| 4128 | op_token: ast.TokenIndex, | 4125 | op_token: ast.TokenIndex, |
| 4129 | rhs_node: *ast.Node, | 4126 | rhs_node: *ast.Node, |
| 4130 | used: ResultUsed, | 4127 | used: ResultUsed, |
| ... | @@ -4134,11 +4131,11 @@ fn transCreateNodeInfixOp( | ... | @@ -4134,11 +4131,11 @@ fn transCreateNodeInfixOp( |
| 4134 | try appendToken(rp.c, .LParen, "(") | 4131 | try appendToken(rp.c, .LParen, "(") |
| 4135 | else | 4132 | else |
| 4136 | null; | 4133 | null; |
| 4137 | const node = try rp.c.arena.create(ast.Node.InfixOp); | 4134 | const node = try rp.c.arena.create(ast.Node.SimpleInfixOp); |
| 4138 | node.* = .{ | 4135 | node.* = .{ |
| 4136 | .base = .{ .tag = op }, | ||
| 4139 | .op_token = op_token, | 4137 | .op_token = op_token, |
| 4140 | .lhs = lhs_node, | 4138 | .lhs = lhs_node, |
| 4141 | .op = op, | ||
| 4142 | .rhs = rhs_node, | 4139 | .rhs = rhs_node, |
| 4143 | }; | 4140 | }; |
| 4144 | if (!grouped) return maybeSuppressResult(rp, scope, used, &node.base); | 4141 | if (!grouped) return maybeSuppressResult(rp, scope, used, &node.base); |
| ... | @@ -4156,7 +4153,7 @@ fn transCreateNodeBoolInfixOp( | ... | @@ -4156,7 +4153,7 @@ fn transCreateNodeBoolInfixOp( |
| 4156 | rp: RestorePoint, | 4153 | rp: RestorePoint, |
| 4157 | scope: *Scope, | 4154 | scope: *Scope, |
| 4158 | stmt: *const ZigClangBinaryOperator, | 4155 | stmt: *const ZigClangBinaryOperator, |
| 4159 | op: ast.Node.InfixOp.Op, | 4156 | op: ast.Node.Tag, |
| 4160 | used: ResultUsed, | 4157 | used: ResultUsed, |
| 4161 | grouped: bool, | 4158 | grouped: bool, |
| 4162 | ) !*ast.Node { | 4159 | ) !*ast.Node { |
| ... | @@ -4536,7 +4533,7 @@ fn transCreateNodeShiftOp( | ... | @@ -4536,7 +4533,7 @@ fn transCreateNodeShiftOp( |
| 4536 | rp: RestorePoint, | 4533 | rp: RestorePoint, |
| 4537 | scope: *Scope, | 4534 | scope: *Scope, |
| 4538 | stmt: *const ZigClangBinaryOperator, | 4535 | stmt: *const ZigClangBinaryOperator, |
| 4539 | op: ast.Node.InfixOp.Op, | 4536 | op: ast.Node.Tag, |
| 4540 | op_tok_id: std.zig.Token.Id, | 4537 | op_tok_id: std.zig.Token.Id, |
| 4541 | bytes: []const u8, | 4538 | bytes: []const u8, |
| 4542 | ) !*ast.Node { | 4539 | ) !*ast.Node { |
| ... | @@ -4558,11 +4555,11 @@ fn transCreateNodeShiftOp( | ... | @@ -4558,11 +4555,11 @@ fn transCreateNodeShiftOp( |
| 4558 | cast_node.params()[1] = rhs; | 4555 | cast_node.params()[1] = rhs; |
| 4559 | cast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | 4556 | cast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); |
| 4560 | 4557 | ||
| 4561 | const node = try rp.c.arena.create(ast.Node.InfixOp); | 4558 | const node = try rp.c.arena.create(ast.Node.SimpleInfixOp); |
| 4562 | node.* = .{ | 4559 | node.* = .{ |
| 4560 | .base = .{ .tag = op }, | ||
| 4563 | .op_token = op_token, | 4561 | .op_token = op_token, |
| 4564 | .lhs = lhs, | 4562 | .lhs = lhs, |
| 4565 | .op = op, | ||
| 4566 | .rhs = &cast_node.base, | 4563 | .rhs = &cast_node.base, |
| 4567 | }; | 4564 | }; |
| 4568 | 4565 | ||
| ... | @@ -5404,11 +5401,11 @@ fn parseCExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, source_ | ... | @@ -5404,11 +5401,11 @@ fn parseCExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, source_ |
| 5404 | // suppress result | 5401 | // suppress result |
| 5405 | const lhs = try transCreateNodeIdentifier(c, "_"); | 5402 | const lhs = try transCreateNodeIdentifier(c, "_"); |
| 5406 | const op_token = try appendToken(c, .Equal, "="); | 5403 | const op_token = try appendToken(c, .Equal, "="); |
| 5407 | const op_node = try c.arena.create(ast.Node.InfixOp); | 5404 | const op_node = try c.arena.create(ast.Node.SimpleInfixOp); |
| 5408 | op_node.* = .{ | 5405 | op_node.* = .{ |
| 5406 | .base = .{ .tag = .Assign }, | ||
| 5409 | .op_token = op_token, | 5407 | .op_token = op_token, |
| 5410 | .lhs = lhs, | 5408 | .lhs = lhs, |
| 5411 | .op = .Assign, | ||
| 5412 | .rhs = last, | 5409 | .rhs = last, |
| 5413 | }; | 5410 | }; |
| 5414 | try block_scope.statements.append(&op_node.base); | 5411 | try block_scope.statements.append(&op_node.base); |
| ... | @@ -5787,9 +5784,60 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, | ... | @@ -5787,9 +5784,60 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, |
| 5787 | } | 5784 | } |
| 5788 | } | 5785 | } |
| 5789 | 5786 | ||
| 5787 | fn nodeIsInfixOp(tag: ast.Node.Tag) bool { | ||
| 5788 | return switch (tag) { | ||
| 5789 | .Add, | ||
| 5790 | .AddWrap, | ||
| 5791 | .ArrayCat, | ||
| 5792 | .ArrayMult, | ||
| 5793 | .Assign, | ||
| 5794 | .AssignBitAnd, | ||
| 5795 | .AssignBitOr, | ||
| 5796 | .AssignBitShiftLeft, | ||
| 5797 | .AssignBitShiftRight, | ||
| 5798 | .AssignBitXor, | ||
| 5799 | .AssignDiv, | ||
| 5800 | .AssignSub, | ||
| 5801 | .AssignSubWrap, | ||
| 5802 | .AssignMod, | ||
| 5803 | .AssignAdd, | ||
| 5804 | .AssignAddWrap, | ||
| 5805 | .AssignMul, | ||
| 5806 | .AssignMulWrap, | ||
| 5807 | .BangEqual, | ||
| 5808 | .BitAnd, | ||
| 5809 | .BitOr, | ||
| 5810 | .BitShiftLeft, | ||
| 5811 | .BitShiftRight, | ||
| 5812 | .BitXor, | ||
| 5813 | .BoolAnd, | ||
| 5814 | .BoolOr, | ||
| 5815 | .Div, | ||
| 5816 | .EqualEqual, | ||
| 5817 | .ErrorUnion, | ||
| 5818 | .GreaterOrEqual, | ||
| 5819 | .GreaterThan, | ||
| 5820 | .LessOrEqual, | ||
| 5821 | .LessThan, | ||
| 5822 | .MergeErrorSets, | ||
| 5823 | .Mod, | ||
| 5824 | .Mul, | ||
| 5825 | .MulWrap, | ||
| 5826 | .Period, | ||
| 5827 | .Range, | ||
| 5828 | .Sub, | ||
| 5829 | .SubWrap, | ||
| 5830 | .UnwrapOptional, | ||
| 5831 | .Catch, | ||
| 5832 | => true, | ||
| 5833 | |||
| 5834 | else => false, | ||
| 5835 | }; | ||
| 5836 | } | ||
| 5837 | |||
| 5790 | fn macroBoolToInt(c: *Context, node: *ast.Node) !*ast.Node { | 5838 | fn macroBoolToInt(c: *Context, node: *ast.Node) !*ast.Node { |
| 5791 | if (!isBoolRes(node)) { | 5839 | if (!isBoolRes(node)) { |
| 5792 | if (node.tag != .InfixOp) return node; | 5840 | if (!nodeIsInfixOp(node.tag)) return node; |
| 5793 | 5841 | ||
| 5794 | const group_node = try c.arena.create(ast.Node.GroupedExpression); | 5842 | const group_node = try c.arena.create(ast.Node.GroupedExpression); |
| 5795 | group_node.* = .{ | 5843 | group_node.* = .{ |
| ... | @@ -5808,7 +5856,7 @@ fn macroBoolToInt(c: *Context, node: *ast.Node) !*ast.Node { | ... | @@ -5808,7 +5856,7 @@ fn macroBoolToInt(c: *Context, node: *ast.Node) !*ast.Node { |
| 5808 | 5856 | ||
| 5809 | fn macroIntToBool(c: *Context, node: *ast.Node) !*ast.Node { | 5857 | fn macroIntToBool(c: *Context, node: *ast.Node) !*ast.Node { |
| 5810 | if (isBoolRes(node)) { | 5858 | if (isBoolRes(node)) { |
| 5811 | if (node.tag != .InfixOp) return node; | 5859 | if (!nodeIsInfixOp(node.tag)) return node; |
| 5812 | 5860 | ||
| 5813 | const group_node = try c.arena.create(ast.Node.GroupedExpression); | 5861 | const group_node = try c.arena.create(ast.Node.GroupedExpression); |
| 5814 | group_node.* = .{ | 5862 | group_node.* = .{ |
| ... | @@ -5821,11 +5869,11 @@ fn macroIntToBool(c: *Context, node: *ast.Node) !*ast.Node { | ... | @@ -5821,11 +5869,11 @@ fn macroIntToBool(c: *Context, node: *ast.Node) !*ast.Node { |
| 5821 | 5869 | ||
| 5822 | const op_token = try appendToken(c, .BangEqual, "!="); | 5870 | const op_token = try appendToken(c, .BangEqual, "!="); |
| 5823 | const zero = try transCreateNodeInt(c, 0); | 5871 | const zero = try transCreateNodeInt(c, 0); |
| 5824 | const res = try c.arena.create(ast.Node.InfixOp); | 5872 | const res = try c.arena.create(ast.Node.SimpleInfixOp); |
| 5825 | res.* = .{ | 5873 | res.* = .{ |
| 5874 | .base = .{ .tag = .BangEqual }, | ||
| 5826 | .op_token = op_token, | 5875 | .op_token = op_token, |
| 5827 | .lhs = node, | 5876 | .lhs = node, |
| 5828 | .op = .BangEqual, | ||
| 5829 | .rhs = zero, | 5877 | .rhs = zero, |
| 5830 | }; | 5878 | }; |
| 5831 | const group_node = try c.arena.create(ast.Node.GroupedExpression); | 5879 | const group_node = try c.arena.create(ast.Node.GroupedExpression); |
| ... | @@ -5842,7 +5890,7 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, | ... | @@ -5842,7 +5890,7 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, |
| 5842 | while (true) { | 5890 | while (true) { |
| 5843 | const tok = it.next().?; | 5891 | const tok = it.next().?; |
| 5844 | var op_token: ast.TokenIndex = undefined; | 5892 | var op_token: ast.TokenIndex = undefined; |
| 5845 | var op_id: ast.Node.InfixOp.Op = undefined; | 5893 | var op_id: ast.Node.Tag = undefined; |
| 5846 | var bool_op = false; | 5894 | var bool_op = false; |
| 5847 | switch (tok.id) { | 5895 | switch (tok.id) { |
| 5848 | .Period => { | 5896 | .Period => { |
| ... | @@ -6049,11 +6097,11 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, | ... | @@ -6049,11 +6097,11 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, |
| 6049 | const cast_fn = if (bool_op) macroIntToBool else macroBoolToInt; | 6097 | const cast_fn = if (bool_op) macroIntToBool else macroBoolToInt; |
| 6050 | const lhs_node = try cast_fn(c, node); | 6098 | const lhs_node = try cast_fn(c, node); |
| 6051 | const rhs_node = try parseCPrefixOpExpr(c, it, source, source_loc, scope); | 6099 | const rhs_node = try parseCPrefixOpExpr(c, it, source, source_loc, scope); |
| 6052 | const op_node = try c.arena.create(ast.Node.InfixOp); | 6100 | const op_node = try c.arena.create(ast.Node.SimpleInfixOp); |
| 6053 | op_node.* = .{ | 6101 | op_node.* = .{ |
| 6102 | .base = .{ .tag = op_id }, | ||
| 6054 | .op_token = op_token, | 6103 | .op_token = op_token, |
| 6055 | .lhs = lhs_node, | 6104 | .lhs = lhs_node, |
| 6056 | .op = op_id, | ||
| 6057 | .rhs = try cast_fn(c, rhs_node), | 6105 | .rhs = try cast_fn(c, rhs_node), |
| 6058 | }; | 6106 | }; |
| 6059 | node = &op_node.base; | 6107 | node = &op_node.base; |
| ... | @@ -6131,10 +6179,9 @@ fn getContainer(c: *Context, node: *ast.Node) ?*ast.Node { | ... | @@ -6131,10 +6179,9 @@ fn getContainer(c: *Context, node: *ast.Node) ?*ast.Node { |
| 6131 | } | 6179 | } |
| 6132 | }, | 6180 | }, |
| 6133 | 6181 | ||
| 6134 | .InfixOp => { | 6182 | .Period => { |
| 6135 | const infix = node.cast(ast.Node.InfixOp).?; | 6183 | const infix = node.castTag(.Period).?; |
| 6136 | if (infix.op != .Period) | 6184 | |
| 6137 | return null; | ||
| 6138 | if (getContainerTypeOf(c, infix.lhs)) |ty_node| { | 6185 | if (getContainerTypeOf(c, infix.lhs)) |ty_node| { |
| 6139 | if (ty_node.cast(ast.Node.ContainerDecl)) |container| { | 6186 | if (ty_node.cast(ast.Node.ContainerDecl)) |container| { |
| 6140 | for (container.fieldsAndDecls()) |field_ref| { | 6187 | for (container.fieldsAndDecls()) |field_ref| { |
| ... | @@ -6161,9 +6208,7 @@ fn getContainerTypeOf(c: *Context, ref: *ast.Node) ?*ast.Node { | ... | @@ -6161,9 +6208,7 @@ fn getContainerTypeOf(c: *Context, ref: *ast.Node) ?*ast.Node { |
| 6161 | return getContainer(c, ty); | 6208 | return getContainer(c, ty); |
| 6162 | } | 6209 | } |
| 6163 | } | 6210 | } |
| 6164 | } else if (ref.cast(ast.Node.InfixOp)) |infix| { | 6211 | } else if (ref.castTag(.Period)) |infix| { |
| 6165 | if (infix.op != .Period) | ||
| 6166 | return null; | ||
| 6167 | if (getContainerTypeOf(c, infix.lhs)) |ty_node| { | 6212 | if (getContainerTypeOf(c, infix.lhs)) |ty_node| { |
| 6168 | if (ty_node.cast(ast.Node.ContainerDecl)) |container| { | 6213 | if (ty_node.cast(ast.Node.ContainerDecl)) |container| { |
| 6169 | for (container.fieldsAndDecls()) |field_ref| { | 6214 | for (container.fieldsAndDecls()) |field_ref| { |