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 {
408408 VarDecl,
409409 Defer,
410410
411 // Operators
412 InfixOp,
411 // Infix operators
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
413459 AddressOf,
414460 Await,
415461 BitNot,
......@@ -419,6 +465,7 @@ pub const Node = struct {
419465 NegationWrap,
420466 Resume,
421467 Try,
468
422469 ArrayType,
423470 /// ArrayType but has a sentinel node.
424471 ArrayTypeSentinel,
......@@ -492,7 +539,51 @@ pub const Node = struct {
492539 .TestDecl => TestDecl,
493540 .VarDecl => VarDecl,
494541 .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
497588 .AddressOf,
498589 .Await,
......@@ -507,13 +598,17 @@ pub const Node = struct {
507598
508599 .ArrayType => ArrayType,
509600 .ArrayTypeSentinel => ArrayTypeSentinel,
601
510602 .PtrType => PtrType,
511603 .SliceType => SliceType,
512604 .SuffixOp => SuffixOp,
605
513606 .ArrayInitializer => ArrayInitializer,
514607 .ArrayInitializerDot => ArrayInitializerDot,
608
515609 .StructInitializer => StructInitializer,
516610 .StructInitializerDot => StructInitializerDot,
611
517612 .Call => Call,
518613 .Switch => Switch,
519614 .While => While,
......@@ -1859,117 +1954,22 @@ pub const Node = struct {
18591954 }
18601955 };
18611956
1862 /// TODO split up and make every op its own AST Node tag
1863 pub const InfixOp = struct {
1864 base: Node = Node{ .tag = .InfixOp },
1957 pub const Catch = struct {
1958 base: Node = Node{ .tag = .Catch },
18651959 op_token: TokenIndex,
18661960 lhs: *Node,
1867 op: Op,
18681961 rhs: *Node,
1962 payload: ?*Node,
18691963
1870 pub const Op = union(enum) {
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 {
1964 pub fn iterate(self: *const Catch, index: usize) ?*Node {
19171965 var i = index;
19181966
19191967 if (i < 1) return self.lhs;
19201968 i -= 1;
19211969
1922 switch (self.op) {
1923 .Catch => |maybe_payload| {
1924 if (maybe_payload) |payload| {
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 => {},
1970 if (self.payload) |payload| {
1971 if (i < 1) return payload;
1972 i -= 1;
19731973 }
19741974
19751975 if (i < 1) return self.rhs;
......@@ -1978,11 +1978,38 @@ pub const Node = struct {
19781978 return null;
19791979 }
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 {
19822009 return self.lhs.firstToken();
19832010 }
19842011
1985 pub fn lastToken(self: *const InfixOp) TokenIndex {
2012 pub fn lastToken(self: *const SimpleInfixOp) TokenIndex {
19862013 return self.rhs.lastToken();
19872014 }
19882015 };
lib/std/zig/parse.zig+136-31
......@@ -1015,7 +1015,7 @@ const Parser = struct {
10151015 /// BoolOrExpr <- BoolAndExpr (KEYWORD_or BoolAndExpr)*
10161016 fn parseBoolOrExpr(p: *Parser) !?*Node {
10171017 return p.parseBinOpExpr(
1018 SimpleBinOpParseFn(.Keyword_or, Node.InfixOp.Op.BoolOr),
1018 SimpleBinOpParseFn(.Keyword_or, .BoolOr),
10191019 parseBoolAndExpr,
10201020 .Infinitely,
10211021 );
......@@ -1405,8 +1405,8 @@ const Parser = struct {
14051405 fn parseErrorUnionExpr(p: *Parser) !?*Node {
14061406 const suffix_expr = (try p.parseSuffixExpr()) orelse return null;
14071407
1408 if (try SimpleBinOpParseFn(.Bang, Node.InfixOp.Op.ErrorUnion)(p)) |node| {
1409 const error_union = node.cast(Node.InfixOp).?;
1408 if (try SimpleBinOpParseFn(.Bang, .ErrorUnion)(p)) |node| {
1409 const error_union = node.castTag(.ErrorUnion).?;
14101410 const type_expr = try p.expectNode(parseTypeExpr, .{
14111411 .ExpectedTypeExpr = .{ .token = p.tok_i },
14121412 });
......@@ -1439,10 +1439,56 @@ const Parser = struct {
14391439 .ExpectedPrimaryTypeExpr = .{ .token = p.tok_i },
14401440 });
14411441
1442 // TODO pass `res` into `parseSuffixOp` rather than patching it up afterwards.
14421443 while (try p.parseSuffixOp()) |node| {
14431444 switch (node.tag) {
14441445 .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
14461492 else => unreachable,
14471493 }
14481494 res = node;
......@@ -1470,10 +1516,55 @@ const Parser = struct {
14701516 var res = expr;
14711517
14721518 while (true) {
1519 // TODO pass `res` into `parseSuffixOp` rather than patching it up afterwards.
14731520 if (try p.parseSuffixOp()) |node| {
14741521 switch (node.tag) {
14751522 .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,
14771568 else => unreachable,
14781569 }
14791570 res = node;
......@@ -1560,11 +1651,11 @@ const Parser = struct {
15601651 const global_error_set = try p.createLiteral(Node.ErrorType, token);
15611652 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);
15641655 node.* = .{
1656 .base = Node{ .tag = .Period },
15651657 .op_token = period.?,
15661658 .lhs = global_error_set,
1567 .op = .Period,
15681659 .rhs = identifier.?,
15691660 };
15701661 return &node.base;
......@@ -2237,11 +2328,11 @@ const Parser = struct {
22372328 .ExpectedExpr = .{ .token = p.tok_i },
22382329 });
22392330
2240 const node = try p.arena.allocator.create(Node.InfixOp);
2331 const node = try p.arena.allocator.create(Node.SimpleInfixOp);
22412332 node.* = .{
2333 .base = Node{ .tag = .Range },
22422334 .op_token = token,
22432335 .lhs = expr,
2244 .op = .Range,
22452336 .rhs = range_end,
22462337 };
22472338 return &node.base;
......@@ -2266,7 +2357,7 @@ const Parser = struct {
22662357 /// / EQUAL
22672358 fn parseAssignOp(p: *Parser) !?*Node {
22682359 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]) {
22702361 .AsteriskEqual => .AssignMul,
22712362 .SlashEqual => .AssignDiv,
22722363 .PercentEqual => .AssignMod,
......@@ -2287,11 +2378,11 @@ const Parser = struct {
22872378 },
22882379 };
22892380
2290 const node = try p.arena.allocator.create(Node.InfixOp);
2381 const node = try p.arena.allocator.create(Node.SimpleInfixOp);
22912382 node.* = .{
2383 .base = .{ .tag = op },
22922384 .op_token = token,
22932385 .lhs = undefined, // set by caller
2294 .op = op,
22952386 .rhs = undefined, // set by caller
22962387 };
22972388 return &node.base;
......@@ -2306,7 +2397,7 @@ const Parser = struct {
23062397 /// / RARROWEQUAL
23072398 fn parseCompareOp(p: *Parser) !?*Node {
23082399 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]) {
23102401 .EqualEqual => .EqualEqual,
23112402 .BangEqual => .BangEqual,
23122403 .AngleBracketLeft => .LessThan,
......@@ -2330,12 +2421,22 @@ const Parser = struct {
23302421 /// / KEYWORD_catch Payload?
23312422 fn parseBitwiseOp(p: *Parser) !?*Node {
23322423 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]) {
23342425 .Ampersand => .BitAnd,
23352426 .Caret => .BitXor,
23362427 .Pipe => .BitOr,
23372428 .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 },
23392440 else => {
23402441 p.putBackToken(token);
23412442 return null;
......@@ -2350,7 +2451,7 @@ const Parser = struct {
23502451 /// / RARROW2
23512452 fn parseBitShiftOp(p: *Parser) !?*Node {
23522453 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]) {
23542455 .AngleBracketAngleBracketLeft => .BitShiftLeft,
23552456 .AngleBracketAngleBracketRight => .BitShiftRight,
23562457 else => {
......@@ -2370,7 +2471,7 @@ const Parser = struct {
23702471 /// / MINUSPERCENT
23712472 fn parseAdditionOp(p: *Parser) !?*Node {
23722473 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]) {
23742475 .Plus => .Add,
23752476 .Minus => .Sub,
23762477 .PlusPlus => .ArrayCat,
......@@ -2394,7 +2495,7 @@ const Parser = struct {
23942495 /// / ASTERISKPERCENT
23952496 fn parseMultiplyOp(p: *Parser) !?*Node {
23962497 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]) {
23982499 .PipePipe => .MergeErrorSets,
23992500 .Asterisk => .Mul,
24002501 .Slash => .Div,
......@@ -2673,14 +2774,14 @@ const Parser = struct {
26732774
26742775 if (p.eatToken(.Period)) |period| {
26752776 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.
26772778 // Should there be an Node.SuffixOp.FieldAccess variant? Or should
26782779 // 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);
26802781 node.* = .{
2782 .base = Node{ .tag = .Period },
26812783 .op_token = period,
26822784 .lhs = undefined, // set by caller
2683 .op = .Period,
26842785 .rhs = identifier,
26852786 };
26862787 return &node.base;
......@@ -2987,7 +3088,7 @@ const Parser = struct {
29873088 }.parse;
29883089 }
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 {
29913092 return struct {
29923093 pub fn parse(p: *Parser) Error!?*Node {
29933094 const op_token = if (token == .Keyword_and) switch (p.token_ids[p.tok_i]) {
......@@ -3001,11 +3102,11 @@ const Parser = struct {
30013102 else => return null,
30023103 } 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);
30053106 node.* = .{
3107 .base = .{ .tag = op },
30063108 .op_token = op_token,
30073109 .lhs = undefined, // set by caller
3008 .op = op,
30093110 .rhs = undefined, // set by caller
30103111 };
30113112 return &node.base;
......@@ -3350,9 +3451,13 @@ const Parser = struct {
33503451 const left = res;
33513452 res = node;
33523453
3353 const op = node.cast(Node.InfixOp).?;
3354 op.*.lhs = left;
3355 op.*.rhs = right;
3454 if (node.castTag(.Catch)) |op| {
3455 op.lhs = left;
3456 op.rhs = right;
3457 } else if (node.cast(Node.SimpleInfixOp)) |op| {
3458 op.lhs = left;
3459 op.rhs = right;
3460 }
33563461
33573462 switch (chain) {
33583463 .Once => break,
......@@ -3363,12 +3468,12 @@ const Parser = struct {
33633468 return res;
33643469 }
33653470
3366 fn createInfixOp(p: *Parser, index: TokenIndex, op: Node.InfixOp.Op) !*Node {
3367 const node = try p.arena.allocator.create(Node.InfixOp);
3471 fn createInfixOp(p: *Parser, op_token: TokenIndex, tag: Node.Tag) !*Node {
3472 const node = try p.arena.allocator.create(Node.SimpleInfixOp);
33683473 node.* = .{
3369 .op_token = index,
3474 .base = Node{ .tag = tag },
3475 .op_token = op_token,
33703476 .lhs = undefined, // set by caller
3371 .op = op,
33723477 .rhs = undefined, // set by caller
33733478 };
33743479 return &node.base;
lib/std/zig/render.zig+118-15
......@@ -436,13 +436,10 @@ fn renderExpression(
436436 }
437437 },
438438
439 .InfixOp => {
440 const infix_op_node = @fieldParentPtr(ast.Node.InfixOp, "base", base);
439 .Catch => {
440 const infix_op_node = @fieldParentPtr(ast.Node.Catch, "base", base);
441441
442 const op_space = switch (infix_op_node.op) {
443 ast.Node.InfixOp.Op.Period, ast.Node.InfixOp.Op.ErrorUnion, ast.Node.InfixOp.Op.Range => Space.None,
444 else => Space.Space,
445 };
442 const op_space = Space.Space;
446443 try renderExpression(allocator, stream, tree, indent, start_col, infix_op_node.lhs, op_space);
447444
448445 const after_op_space = blk: {
......@@ -458,11 +455,75 @@ fn renderExpression(
458455 start_col.* = indent + indent_delta;
459456 }
460457
461 switch (infix_op_node.op) {
462 ast.Node.InfixOp.Op.Catch => |maybe_payload| if (maybe_payload) |payload| {
463 try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Space);
464 },
465 else => {},
458 if (infix_op_node.payload) |payload| {
459 try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Space);
460 }
461
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;
466527 }
467528
468529 return renderExpression(allocator, stream, tree, indent, start_col, infix_op_node.rhs, space);
......@@ -2553,10 +2614,52 @@ fn nodeIsBlock(base: *const ast.Node) bool {
25532614}
25542615
25552616fn nodeCausesSliceOpSpace(base: *ast.Node) bool {
2556 const infix_op = base.cast(ast.Node.InfixOp) orelse return false;
2557 return switch (infix_op.op) {
2558 ast.Node.InfixOp.Op.Period => false,
2559 else => true,
2617 return switch (base.tag) {
2618 .Catch,
2619 .Add,
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,
25602663 };
25612664}
25622665
src-self-hosted/Module.zig+1-1
......@@ -1954,7 +1954,7 @@ pub fn addZIRInstSpecial(
19541954 positionals: std.meta.fieldInfo(T, "positionals").field_type,
19551955 kw_args: std.meta.fieldInfo(T, "kw_args").field_type,
19561956) !*T {
1957 const gen_zir = scope.cast(Scope.GenZIR).?;
1957 const gen_zir = scope.getGenZIR();
19581958 try gen_zir.instructions.ensureCapacity(self.gpa, gen_zir.instructions.items.len + 1);
19591959 const inst = try newZIRInst(gen_zir.arena, src, T, positionals, kw_args);
19601960 gen_zir.instructions.appendAssumeCapacity(&inst.base);
src-self-hosted/astgen.zig+105-71
......@@ -12,22 +12,29 @@ const Scope = Module.Scope;
1212const InnerError = Module.InnerError;
1313
1414/// Turn Zig AST into untyped ZIR istructions.
15pub fn expr(mod: *Module, scope: *Scope, ast_node: *ast.Node) InnerError!*zir.Inst {
16 switch (ast_node.tag) {
15pub fn expr(mod: *Module, scope: *Scope, node: *ast.Node) InnerError!*zir.Inst {
16 switch (node.tag) {
1717 .VarDecl => unreachable, // Handled in `blockExpr`.
1818
19 .Identifier => return identifier(mod, scope, @fieldParentPtr(ast.Node.Identifier, "base", ast_node)),
20 .Asm => return assembly(mod, scope, @fieldParentPtr(ast.Node.Asm, "base", ast_node)),
21 .StringLiteral => return stringLiteral(mod, scope, @fieldParentPtr(ast.Node.StringLiteral, "base", ast_node)),
22 .IntegerLiteral => return integerLiteral(mod, scope, @fieldParentPtr(ast.Node.IntegerLiteral, "base", ast_node)),
23 .BuiltinCall => return builtinCall(mod, scope, @fieldParentPtr(ast.Node.BuiltinCall, "base", ast_node)),
24 .Call => return callExpr(mod, scope, @fieldParentPtr(ast.Node.Call, "base", ast_node)),
25 .Unreachable => return unreach(mod, scope, @fieldParentPtr(ast.Node.Unreachable, "base", ast_node)),
26 .ControlFlowExpression => return controlFlowExpr(mod, scope, @fieldParentPtr(ast.Node.ControlFlowExpression, "base", ast_node)),
27 .If => return ifExpr(mod, scope, @fieldParentPtr(ast.Node.If, "base", ast_node)),
28 .InfixOp => return infixOp(mod, scope, @fieldParentPtr(ast.Node.InfixOp, "base", ast_node)),
29 .BoolNot => return boolNot(mod, scope, @fieldParentPtr(ast.Node.SimplePrefixOp, "base", ast_node)),
30 else => return mod.failNode(scope, ast_node, "TODO implement astgen.Expr for {}", .{@tagName(ast_node.tag)}),
19 .Identifier => return identifier(mod, scope, node.castTag(.Identifier).?),
20 .Asm => return assembly(mod, scope, node.castTag(.Asm).?),
21 .StringLiteral => return stringLiteral(mod, scope, node.castTag(.StringLiteral).?),
22 .IntegerLiteral => return integerLiteral(mod, scope, node.castTag(.IntegerLiteral).?),
23 .BuiltinCall => return builtinCall(mod, scope, node.castTag(.BuiltinCall).?),
24 .Call => return callExpr(mod, scope, node.castTag(.Call).?),
25 .Unreachable => return unreach(mod, scope, node.castTag(.Unreachable).?),
26 .ControlFlowExpression => return controlFlowExpr(mod, scope, node.castTag(.ControlFlowExpression).?),
27 .If => return ifExpr(mod, scope, node.castTag(.If).?),
28 .Assign => return assign(mod, scope, node.castTag(.Assign).?),
29 .Add => return add(mod, scope, node.castTag(.Add).?),
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)}),
3138 }
3239}
3340
......@@ -57,6 +64,7 @@ pub fn blockExpr(mod: *Module, parent_scope: *Scope, block_node: *ast.Node.Block
5764}
5865
5966fn varDecl(mod: *Module, scope: *Scope, node: *ast.Node.VarDecl) InnerError!Scope.LocalVar {
67 // TODO implement detection of shadowing
6068 if (node.getTrailer("comptime_token")) |comptime_token| {
6169 return mod.failTok(scope, comptime_token, "TODO implement comptime locals", .{});
6270 }
......@@ -98,64 +106,48 @@ fn boolNot(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerErr
98106 return mod.addZIRInst(scope, src, zir.Inst.BoolNot, .{ .operand = operand }, .{});
99107}
100108
101fn infixOp(mod: *Module, scope: *Scope, infix_node: *ast.Node.InfixOp) InnerError!*zir.Inst {
102 switch (infix_node.op) {
103 .Assign => {
104 if (infix_node.lhs.tag == .Identifier) {
105 const ident = @fieldParentPtr(ast.Node.Identifier, "base", infix_node.lhs);
106 const tree = scope.tree();
107 const ident_name = tree.tokenSlice(ident.token);
108 if (std.mem.eql(u8, ident_name, "_")) {
109 return expr(mod, scope, infix_node.rhs);
110 } else {
111 return mod.failNode(scope, &infix_node.base, "TODO implement infix operator assign", .{});
112 }
113 } else {
114 return mod.failNode(scope, &infix_node.base, "TODO implement infix operator assign", .{});
115 }
116 },
117 .Add => {
118 const lhs = try expr(mod, scope, infix_node.lhs);
119 const rhs = try expr(mod, scope, infix_node.rhs);
109fn assign(mod: *Module, scope: *Scope, infix_node: *ast.Node.SimpleInfixOp) InnerError!*zir.Inst {
110 if (infix_node.lhs.tag == .Identifier) {
111 const ident = @fieldParentPtr(ast.Node.Identifier, "base", infix_node.lhs);
112 const tree = scope.tree();
113 const ident_name = tree.tokenSlice(ident.token);
114 if (std.mem.eql(u8, ident_name, "_")) {
115 return expr(mod, scope, infix_node.rhs);
116 } else {
117 return mod.failNode(scope, &infix_node.base, "TODO implement infix operator assign", .{});
118 }
119 } else {
120 return mod.failNode(scope, &infix_node.base, "TODO implement infix operator assign", .{});
121 }
122}
120123
121 const tree = scope.tree();
122 const src = tree.token_locs[infix_node.op_token].start;
124fn add(mod: *Module, scope: *Scope, infix_node: *ast.Node.SimpleInfixOp) InnerError!*zir.Inst {
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 }, .{});
125 },
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 };
128 const tree = scope.tree();
129 const src = tree.token_locs[infix_node.op_token].start;
148130
149 return mod.addZIRInst(scope, src, zir.Inst.Cmp, .{
150 .lhs = lhs,
151 .op = op,
152 .rhs = rhs,
153 }, .{});
154 },
155 else => |op| {
156 return mod.failNode(scope, &infix_node.base, "TODO implement infix operator {}", .{op});
157 },
158 }
131 return mod.addZIRInst(scope, src, zir.Inst.Add, .{ .lhs = lhs, .rhs = rhs }, .{});
132}
133
134fn cmp(
135 mod: *Module,
136 scope: *Scope,
137 infix_node: *ast.Node.SimpleInfixOp,
138 op: std.math.CompareOperator,
139) InnerError!*zir.Inst {
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 }, .{});
159151}
160152
161153fn ifExpr(mod: *Module, scope: *Scope, if_node: *ast.Node.If) InnerError!*zir.Inst {
......@@ -571,6 +563,47 @@ fn nodeNeedsMemoryLocation(node: *ast.Node) bool {
571563 .ErrorSetDecl,
572564 .ContainerDecl,
573565 .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,
574607 => false,
575608
576609 .ArrayInitializer,
......@@ -579,9 +612,10 @@ fn nodeNeedsMemoryLocation(node: *ast.Node) bool {
579612 .StructInitializerDot,
580613 => 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"),
585619 .Await => @panic("TODO nodeNeedsMemoryLocation for Await"),
586620 .Try => @panic("TODO nodeNeedsMemoryLocation for Try"),
587621 .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
11031103 const enum_ident = try transCreateNodeIdentifier(c, name);
11041104 const period_tok = try appendToken(c, .Period, ".");
11051105 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);
11071107 field_access_node.* = .{
1108 .base = .{ .tag = .Period },
11081109 .op_token = period_tok,
11091110 .lhs = enum_ident,
1110 .op = .Period,
11111111 .rhs = field_ident,
11121112 };
11131113 cast_node.params()[0] = &field_access_node.base;
......@@ -1294,7 +1294,7 @@ fn transBinaryOperator(
12941294 const op = ZigClangBinaryOperator_getOpcode(stmt);
12951295 const qt = ZigClangBinaryOperator_getType(stmt);
12961296 var op_token: ast.TokenIndex = undefined;
1297 var op_id: ast.Node.InfixOp.Op = undefined;
1297 var op_id: ast.Node.Tag = undefined;
12981298 switch (op) {
12991299 .Assign => return try transCreateNodeAssign(rp, scope, result_used, ZigClangBinaryOperator_getLHS(stmt), ZigClangBinaryOperator_getRHS(stmt)),
13001300 .Comma => {
......@@ -1737,25 +1737,22 @@ fn exprIsStringLiteral(expr: *const ZigClangExpr) bool {
17371737
17381738fn isBoolRes(res: *ast.Node) bool {
17391739 switch (res.tag) {
1740 .InfixOp => switch (@fieldParentPtr(ast.Node.InfixOp, "base", res).op) {
1741 .BoolOr,
1742 .BoolAnd,
1743 .EqualEqual,
1744 .BangEqual,
1745 .LessThan,
1746 .GreaterThan,
1747 .LessOrEqual,
1748 .GreaterOrEqual,
1749 => return true,
1740 .BoolOr,
1741 .BoolAnd,
1742 .EqualEqual,
1743 .BangEqual,
1744 .LessThan,
1745 .GreaterThan,
1746 .LessOrEqual,
1747 .GreaterOrEqual,
1748 .BoolNot,
1749 .BoolLiteral,
1750 => return true,
17501751
1751 else => {},
1752 },
1753 .BoolNot => return true,
1754 .BoolLiteral => return true,
17551752 .GroupedExpression => return isBoolRes(@fieldParentPtr(ast.Node.GroupedExpression, "base", res).expr),
1756 else => {},
1753
1754 else => return false,
17571755 }
1758 return false;
17591756}
17601757
17611758fn finishBoolExpr(
......@@ -2312,11 +2309,11 @@ fn transInitListExprArray(
23122309 &filler_init_node.base
23132310 else blk: {
23142311 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);
23162313 mul_node.* = .{
2314 .base = .{ .tag = .ArrayMult },
23172315 .op_token = mul_tok,
23182316 .lhs = &filler_init_node.base,
2319 .op = .ArrayMult,
23202317 .rhs = try transCreateNodeInt(rp.c, leftover_count),
23212318 };
23222319 break :blk &mul_node.base;
......@@ -2326,11 +2323,11 @@ fn transInitListExprArray(
23262323 return rhs_node;
23272324 }
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);
23302327 cat_node.* = .{
2328 .base = .{ .tag = .ArrayCat },
23312329 .op_token = cat_tok,
23322330 .lhs = &init_node.base,
2333 .op = .ArrayCat,
23342331 .rhs = rhs_node,
23352332 };
23362333 return &cat_node.base;
......@@ -2723,11 +2720,11 @@ fn transCase(
27232720 const ellips = try appendToken(rp.c, .Ellipsis3, "...");
27242721 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);
27272724 node.* = .{
2725 .base = .{ .tag = .Range },
27282726 .op_token = ellips,
27292727 .lhs = lhs_node,
2730 .op = .Range,
27312728 .rhs = rhs_node,
27322729 };
27332730 break :blk &node.base;
......@@ -3153,7 +3150,7 @@ fn transCreatePreCrement(
31533150 rp: RestorePoint,
31543151 scope: *Scope,
31553152 stmt: *const ZigClangUnaryOperator,
3156 op: ast.Node.InfixOp.Op,
3153 op: ast.Node.Tag,
31573154 op_tok_id: std.zig.Token.Id,
31583155 bytes: []const u8,
31593156 used: ResultUsed,
......@@ -3227,7 +3224,7 @@ fn transCreatePostCrement(
32273224 rp: RestorePoint,
32283225 scope: *Scope,
32293226 stmt: *const ZigClangUnaryOperator,
3230 op: ast.Node.InfixOp.Op,
3227 op: ast.Node.Tag,
32313228 op_tok_id: std.zig.Token.Id,
32323229 bytes: []const u8,
32333230 used: ResultUsed,
......@@ -3349,10 +3346,10 @@ fn transCreateCompoundAssign(
33493346 rp: RestorePoint,
33503347 scope: *Scope,
33513348 stmt: *const ZigClangCompoundAssignOperator,
3352 assign_op: ast.Node.InfixOp.Op,
3349 assign_op: ast.Node.Tag,
33533350 assign_tok_id: std.zig.Token.Id,
33543351 assign_bytes: []const u8,
3355 bin_op: ast.Node.InfixOp.Op,
3352 bin_op: ast.Node.Tag,
33563353 bin_tok_id: std.zig.Token.Id,
33573354 bin_bytes: []const u8,
33583355 used: ResultUsed,
......@@ -3377,7 +3374,7 @@ fn transCreateCompoundAssign(
33773374 // zig: lhs += rhs
33783375 if ((is_mod or is_div) and is_signed) {
33793376 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);
33813378 const builtin = if (is_mod) "@rem" else "@divTrunc";
33823379 const builtin_node = try rp.c.createBuiltinCall(builtin, 2);
33833380 const lhs_node = try transExpr(rp, scope, lhs, .used, .l_value);
......@@ -3386,9 +3383,9 @@ fn transCreateCompoundAssign(
33863383 builtin_node.params()[1] = try transExpr(rp, scope, rhs, .used, .r_value);
33873384 builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");
33883385 op_node.* = .{
3386 .base = .{ .tag = .Assign },
33893387 .op_token = op_token,
33903388 .lhs = lhs_node,
3391 .op = .Assign,
33923389 .rhs = &builtin_node.base,
33933390 };
33943391 _ = try appendToken(rp.c, .Semicolon, ";");
......@@ -3452,7 +3449,7 @@ fn transCreateCompoundAssign(
34523449
34533450 if ((is_mod or is_div) and is_signed) {
34543451 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);
34563453 const builtin = if (is_mod) "@rem" else "@divTrunc";
34573454 const builtin_node = try rp.c.createBuiltinCall(builtin, 2);
34583455 builtin_node.params()[0] = try transCreateNodePtrDeref(rp.c, lhs_node);
......@@ -3461,9 +3458,9 @@ fn transCreateCompoundAssign(
34613458 builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");
34623459 _ = try appendToken(rp.c, .Semicolon, ";");
34633460 op_node.* = .{
3461 .base = .{ .tag = .Assign },
34643462 .op_token = op_token,
34653463 .lhs = ref_node,
3466 .op = .Assign,
34673464 .rhs = &builtin_node.base,
34683465 };
34693466 _ = try appendToken(rp.c, .Semicolon, ";");
......@@ -3716,11 +3713,11 @@ fn maybeSuppressResult(
37163713 }
37173714 const lhs = try transCreateNodeIdentifier(rp.c, "_");
37183715 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);
37203717 op_node.* = .{
3718 .base = .{ .tag = .Assign },
37213719 .op_token = op_token,
37223720 .lhs = lhs,
3723 .op = .Assign,
37243721 .rhs = result,
37253722 };
37263723 return &op_node.base;
......@@ -4095,11 +4092,11 @@ fn transCreateNodeAssign(
40954092}
40964093
40974094fn 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);
40994096 field_access_node.* = .{
4097 .base = .{ .tag = .Period },
41004098 .op_token = try appendToken(c, .Period, "."),
41014099 .lhs = container,
4102 .op = .Period,
41034100 .rhs = try transCreateNodeIdentifier(c, field_name),
41044101 };
41054102 return &field_access_node.base;
......@@ -4124,7 +4121,7 @@ fn transCreateNodeInfixOp(
41244121 rp: RestorePoint,
41254122 scope: *Scope,
41264123 lhs_node: *ast.Node,
4127 op: ast.Node.InfixOp.Op,
4124 op: ast.Node.Tag,
41284125 op_token: ast.TokenIndex,
41294126 rhs_node: *ast.Node,
41304127 used: ResultUsed,
......@@ -4134,11 +4131,11 @@ fn transCreateNodeInfixOp(
41344131 try appendToken(rp.c, .LParen, "(")
41354132 else
41364133 null;
4137 const node = try rp.c.arena.create(ast.Node.InfixOp);
4134 const node = try rp.c.arena.create(ast.Node.SimpleInfixOp);
41384135 node.* = .{
4136 .base = .{ .tag = op },
41394137 .op_token = op_token,
41404138 .lhs = lhs_node,
4141 .op = op,
41424139 .rhs = rhs_node,
41434140 };
41444141 if (!grouped) return maybeSuppressResult(rp, scope, used, &node.base);
......@@ -4156,7 +4153,7 @@ fn transCreateNodeBoolInfixOp(
41564153 rp: RestorePoint,
41574154 scope: *Scope,
41584155 stmt: *const ZigClangBinaryOperator,
4159 op: ast.Node.InfixOp.Op,
4156 op: ast.Node.Tag,
41604157 used: ResultUsed,
41614158 grouped: bool,
41624159) !*ast.Node {
......@@ -4536,7 +4533,7 @@ fn transCreateNodeShiftOp(
45364533 rp: RestorePoint,
45374534 scope: *Scope,
45384535 stmt: *const ZigClangBinaryOperator,
4539 op: ast.Node.InfixOp.Op,
4536 op: ast.Node.Tag,
45404537 op_tok_id: std.zig.Token.Id,
45414538 bytes: []const u8,
45424539) !*ast.Node {
......@@ -4558,11 +4555,11 @@ fn transCreateNodeShiftOp(
45584555 cast_node.params()[1] = rhs;
45594556 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);
45624559 node.* = .{
4560 .base = .{ .tag = op },
45634561 .op_token = op_token,
45644562 .lhs = lhs,
4565 .op = op,
45664563 .rhs = &cast_node.base,
45674564 };
45684565
......@@ -5404,11 +5401,11 @@ fn parseCExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, source_
54045401 // suppress result
54055402 const lhs = try transCreateNodeIdentifier(c, "_");
54065403 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);
54085405 op_node.* = .{
5406 .base = .{ .tag = .Assign },
54095407 .op_token = op_token,
54105408 .lhs = lhs,
5411 .op = .Assign,
54125409 .rhs = last,
54135410 };
54145411 try block_scope.statements.append(&op_node.base);
......@@ -5787,9 +5784,60 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
57875784 }
57885785}
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
57905838fn macroBoolToInt(c: *Context, node: *ast.Node) !*ast.Node {
57915839 if (!isBoolRes(node)) {
5792 if (node.tag != .InfixOp) return node;
5840 if (!nodeIsInfixOp(node.tag)) return node;
57935841
57945842 const group_node = try c.arena.create(ast.Node.GroupedExpression);
57955843 group_node.* = .{
......@@ -5808,7 +5856,7 @@ fn macroBoolToInt(c: *Context, node: *ast.Node) !*ast.Node {
58085856
58095857fn macroIntToBool(c: *Context, node: *ast.Node) !*ast.Node {
58105858 if (isBoolRes(node)) {
5811 if (node.tag != .InfixOp) return node;
5859 if (!nodeIsInfixOp(node.tag)) return node;
58125860
58135861 const group_node = try c.arena.create(ast.Node.GroupedExpression);
58145862 group_node.* = .{
......@@ -5821,11 +5869,11 @@ fn macroIntToBool(c: *Context, node: *ast.Node) !*ast.Node {
58215869
58225870 const op_token = try appendToken(c, .BangEqual, "!=");
58235871 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);
58255873 res.* = .{
5874 .base = .{ .tag = .BangEqual },
58265875 .op_token = op_token,
58275876 .lhs = node,
5828 .op = .BangEqual,
58295877 .rhs = zero,
58305878 };
58315879 const group_node = try c.arena.create(ast.Node.GroupedExpression);
......@@ -5842,7 +5890,7 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
58425890 while (true) {
58435891 const tok = it.next().?;
58445892 var op_token: ast.TokenIndex = undefined;
5845 var op_id: ast.Node.InfixOp.Op = undefined;
5893 var op_id: ast.Node.Tag = undefined;
58465894 var bool_op = false;
58475895 switch (tok.id) {
58485896 .Period => {
......@@ -6049,11 +6097,11 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
60496097 const cast_fn = if (bool_op) macroIntToBool else macroBoolToInt;
60506098 const lhs_node = try cast_fn(c, node);
60516099 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);
60536101 op_node.* = .{
6102 .base = .{ .tag = op_id },
60546103 .op_token = op_token,
60556104 .lhs = lhs_node,
6056 .op = op_id,
60576105 .rhs = try cast_fn(c, rhs_node),
60586106 };
60596107 node = &op_node.base;
......@@ -6131,10 +6179,9 @@ fn getContainer(c: *Context, node: *ast.Node) ?*ast.Node {
61316179 }
61326180 },
61336181
6134 .InfixOp => {
6135 const infix = node.cast(ast.Node.InfixOp).?;
6136 if (infix.op != .Period)
6137 return null;
6182 .Period => {
6183 const infix = node.castTag(.Period).?;
6184
61386185 if (getContainerTypeOf(c, infix.lhs)) |ty_node| {
61396186 if (ty_node.cast(ast.Node.ContainerDecl)) |container| {
61406187 for (container.fieldsAndDecls()) |field_ref| {
......@@ -6161,9 +6208,7 @@ fn getContainerTypeOf(c: *Context, ref: *ast.Node) ?*ast.Node {
61616208 return getContainer(c, ty);
61626209 }
61636210 }
6164 } else if (ref.cast(ast.Node.InfixOp)) |infix| {
6165 if (infix.op != .Period)
6166 return null;
6211 } else if (ref.castTag(.Period)) |infix| {
61676212 if (getContainerTypeOf(c, infix.lhs)) |ty_node| {
61686213 if (ty_node.cast(ast.Node.ContainerDecl)) |container| {
61696214 for (container.fieldsAndDecls()) |field_ref| {