authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-07-15 19:39:18-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-07-15 19:39:18-07:00
logaf12596e8d728423e361e4755a6078c5ef8faf69
treea19190d14848b536cae262789573531c47b42f10
parentf11909227312882f29dbfc484dc79ab622792787

stage2: breaking AST memory layout modifications

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,
410410
411 // Operators411 // 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,
496587
497 .AddressOf,588 .AddressOf,
498 .Await,589 .Await,
...@@ -507,13 +598,17 @@ pub const Node = struct {...@@ -507,13 +598,17 @@ pub const Node = struct {
507598
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 };
18611956
1862 /// TODO split up and make every op its own AST Node tag1957 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,
18691963
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;
19181966
1919 if (i < 1) return self.lhs;1967 if (i < 1) return self.lhs;
1920 i -= 1;1968 i -= 1;
19211969
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 }
19741974
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 }
19801980
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 }
19842011
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;
14071407
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 });
14411441
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;
14711517
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;
15621653
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 });
22392330
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 /// / EQUAL2357 /// / 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 };
22892380
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 caller2385 .lhs = undefined, // set by caller
2294 .op = op,
2295 .rhs = undefined, // set by caller2386 .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 /// / RARROWEQUAL2397 /// / 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 /// / RARROW22451 /// / 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 /// / MINUSPERCENT2471 /// / 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 /// / ASTERISKPERCENT2495 /// / 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 {
26732774
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 should2778 // 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 caller2784 .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 }
29893090
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;
30033104
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 caller3109 .lhs = undefined, // set by caller
3008 .op = op,
3009 .rhs = undefined, // set by caller3110 .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;
33523453
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 }
33563461
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 }
33653470
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 caller3476 .lhs = undefined, // set by caller
3371 .op = op,
3372 .rhs = undefined, // set by caller3477 .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 },
438438
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);
441441
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);
447444
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 }
460457
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 }
467528
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}
25542615
2555fn nodeCausesSliceOpSpace(base: *ast.Node) bool {2616fn 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}
25622665
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;
12const InnerError = Module.InnerError;12const InnerError = Module.InnerError;
1313
14/// Turn Zig AST into untyped ZIR istructions.14/// Turn Zig AST into untyped ZIR istructions.
15pub fn expr(mod: *Module, scope: *Scope, ast_node: *ast.Node) InnerError!*zir.Inst {15pub 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`.
1818
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}
3340
...@@ -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}
5865
59fn varDecl(mod: *Module, scope: *Scope, node: *ast.Node.VarDecl) InnerError!Scope.LocalVar {66fn 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}
100108
101fn infixOp(mod: *Module, scope: *Scope, infix_node: *ast.Node.InfixOp) InnerError!*zir.Inst {109fn 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);
120123
121 const tree = scope.tree();124fn 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);
123127
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 };
148130
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,134fn 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}
160152
161fn ifExpr(mod: *Module, scope: *Scope, if_node: *ast.Node.If) InnerError!*zir.Inst {153fn 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,
575608
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,
581614
582 .GroupedExpression => nodeNeedsMemoryLocation(node.cast(ast.Node.GroupedExpression).?.expr),615 .GroupedExpression => nodeNeedsMemoryLocation(node.castTag(.GroupedExpression).?.expr),
583616
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 {
17371737
1738fn isBoolRes(res: *ast.Node) bool {1738fn 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,
17501751
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}
17601757
1761fn finishBoolExpr(1758fn finishBoolExpr(
...@@ -2312,11 +2309,11 @@ fn transInitListExprArray(...@@ -2312,11 +2309,11 @@ fn transInitListExprArray(
2312 &filler_init_node.base2309 &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 }
23282325
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);
27252722
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 += rhs3374 // 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(
34523449
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}
40964093
4097fn transCreateNodeFieldAccess(c: *Context, container: *ast.Node, field_name: []const u8) !*ast.Node {4094fn 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 else4132 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, ")");
45604557
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 };
45684565
...@@ -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 result5401 // 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}
57895786
5787fn 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
5790fn macroBoolToInt(c: *Context, node: *ast.Node) !*ast.Node {5838fn 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;
57935841
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 {
58085856
5809fn macroIntToBool(c: *Context, node: *ast.Node) !*ast.Node {5857fn 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;
58125860
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 {
58215869
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 },
61336181
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| {