| author | |
| committer | |
| log | 7a1a92478878f591abbadcd5735f03c817c6eb53 |
| tree | 6ee2180f07905856f0f16864708352087fcf3e7b |
| parent | 1ac28eed839663a7d12bbbf131596b6abd8b0744 |
5 files changed, 246 insertions(+), 310 deletions(-)
lib/std/zig/ast.zig+78-43| ... | @@ -471,9 +471,14 @@ pub const Node = struct { | ... | @@ -471,9 +471,14 @@ pub const Node = struct { |
| 471 | ArrayTypeSentinel, | 471 | ArrayTypeSentinel, |
| 472 | PtrType, | 472 | PtrType, |
| 473 | SliceType, | 473 | SliceType, |
| 474 | /// Not all suffix operations are under this tag. To save memory, some | 474 | /// `a[b..c]` |
| 475 | /// suffix operations have dedicated Node tags. | 475 | Slice, |
| 476 | SuffixOp, | 476 | /// `a.*` |
| 477 | Deref, | ||
| 478 | /// `a.?` | ||
| 479 | UnwrapOptional, | ||
| 480 | /// `a[b]` | ||
| 481 | ArrayAccess, | ||
| 477 | /// `T{a, b}` | 482 | /// `T{a, b}` |
| 478 | ArrayInitializer, | 483 | ArrayInitializer, |
| 479 | /// ArrayInitializer but with `.` instead of a left-hand-side operand. | 484 | /// ArrayInitializer but with `.` instead of a left-hand-side operand. |
| ... | @@ -601,7 +606,9 @@ pub const Node = struct { | ... | @@ -601,7 +606,9 @@ pub const Node = struct { |
| 601 | 606 | ||
| 602 | .PtrType => PtrType, | 607 | .PtrType => PtrType, |
| 603 | .SliceType => SliceType, | 608 | .SliceType => SliceType, |
| 604 | .SuffixOp => SuffixOp, | 609 | .Slice => Slice, |
| 610 | .Deref, .UnwrapOptional => SimpleSuffixOp, | ||
| 611 | .ArrayAccess => ArrayAccess, | ||
| 605 | 612 | ||
| 606 | .ArrayInitializer => ArrayInitializer, | 613 | .ArrayInitializer => ArrayInitializer, |
| 607 | .ArrayInitializerDot => ArrayInitializerDot, | 614 | .ArrayInitializerDot => ArrayInitializerDot, |
| ... | @@ -2398,8 +2405,8 @@ pub const Node = struct { | ... | @@ -2398,8 +2405,8 @@ pub const Node = struct { |
| 2398 | /// Parameter nodes directly follow Call in memory. | 2405 | /// Parameter nodes directly follow Call in memory. |
| 2399 | pub const Call = struct { | 2406 | pub const Call = struct { |
| 2400 | base: Node = Node{ .tag = .Call }, | 2407 | base: Node = Node{ .tag = .Call }, |
| 2401 | lhs: *Node, | ||
| 2402 | rtoken: TokenIndex, | 2408 | rtoken: TokenIndex, |
| 2409 | lhs: *Node, | ||
| 2403 | params_len: NodeIndex, | 2410 | params_len: NodeIndex, |
| 2404 | async_token: ?TokenIndex, | 2411 | async_token: ?TokenIndex, |
| 2405 | 2412 | ||
| ... | @@ -2450,62 +2457,90 @@ pub const Node = struct { | ... | @@ -2450,62 +2457,90 @@ pub const Node = struct { |
| 2450 | } | 2457 | } |
| 2451 | }; | 2458 | }; |
| 2452 | 2459 | ||
| 2453 | pub const SuffixOp = struct { | 2460 | pub const ArrayAccess = struct { |
| 2454 | base: Node = Node{ .tag = .SuffixOp }, | 2461 | base: Node = Node{ .tag = .ArrayAccess }, |
| 2455 | op: Op, | 2462 | rtoken: TokenIndex, |
| 2456 | lhs: *Node, | 2463 | lhs: *Node, |
| 2464 | index_expr: *Node, | ||
| 2465 | |||
| 2466 | pub fn iterate(self: *const ArrayAccess, index: usize) ?*Node { | ||
| 2467 | var i = index; | ||
| 2468 | |||
| 2469 | if (i < 1) return self.lhs; | ||
| 2470 | i -= 1; | ||
| 2471 | |||
| 2472 | if (i < 1) return self.index_expr; | ||
| 2473 | i -= 1; | ||
| 2474 | |||
| 2475 | return null; | ||
| 2476 | } | ||
| 2477 | |||
| 2478 | pub fn firstToken(self: *const ArrayAccess) TokenIndex { | ||
| 2479 | return self.lhs.firstToken(); | ||
| 2480 | } | ||
| 2481 | |||
| 2482 | pub fn lastToken(self: *const ArrayAccess) TokenIndex { | ||
| 2483 | return self.rtoken; | ||
| 2484 | } | ||
| 2485 | }; | ||
| 2486 | |||
| 2487 | pub const SimpleSuffixOp = struct { | ||
| 2488 | base: Node, | ||
| 2457 | rtoken: TokenIndex, | 2489 | rtoken: TokenIndex, |
| 2490 | lhs: *Node, | ||
| 2458 | 2491 | ||
| 2459 | pub const Op = union(enum) { | 2492 | pub fn iterate(self: *const SimpleSuffixOp, index: usize) ?*Node { |
| 2460 | ArrayAccess: *Node, | 2493 | var i = index; |
| 2461 | Slice: Slice, | ||
| 2462 | Deref, | ||
| 2463 | UnwrapOptional, | ||
| 2464 | 2494 | ||
| 2465 | pub const Slice = struct { | 2495 | if (i < 1) return self.lhs; |
| 2466 | start: *Node, | 2496 | i -= 1; |
| 2467 | end: ?*Node, | ||
| 2468 | sentinel: ?*Node, | ||
| 2469 | }; | ||
| 2470 | }; | ||
| 2471 | 2497 | ||
| 2472 | pub fn iterate(self: *const SuffixOp, index: usize) ?*Node { | 2498 | return null; |
| 2499 | } | ||
| 2500 | |||
| 2501 | pub fn firstToken(self: *const SimpleSuffixOp) TokenIndex { | ||
| 2502 | return self.lhs.firstToken(); | ||
| 2503 | } | ||
| 2504 | |||
| 2505 | pub fn lastToken(self: *const SimpleSuffixOp) TokenIndex { | ||
| 2506 | return self.rtoken; | ||
| 2507 | } | ||
| 2508 | }; | ||
| 2509 | |||
| 2510 | pub const Slice = struct { | ||
| 2511 | base: Node = Node{ .tag = .Slice }, | ||
| 2512 | rtoken: TokenIndex, | ||
| 2513 | lhs: *Node, | ||
| 2514 | start: *Node, | ||
| 2515 | end: ?*Node, | ||
| 2516 | sentinel: ?*Node, | ||
| 2517 | |||
| 2518 | pub fn iterate(self: *const Slice, index: usize) ?*Node { | ||
| 2473 | var i = index; | 2519 | var i = index; |
| 2474 | 2520 | ||
| 2475 | if (i == 0) return self.lhs; | 2521 | if (i < 1) return self.lhs; |
| 2476 | i -= 1; | 2522 | i -= 1; |
| 2477 | 2523 | ||
| 2478 | switch (self.op) { | 2524 | if (i < 1) return self.start; |
| 2479 | .ArrayAccess => |index_expr| { | 2525 | i -= 1; |
| 2480 | if (i < 1) return index_expr; | ||
| 2481 | i -= 1; | ||
| 2482 | }, | ||
| 2483 | .Slice => |range| { | ||
| 2484 | if (i < 1) return range.start; | ||
| 2485 | i -= 1; | ||
| 2486 | 2526 | ||
| 2487 | if (range.end) |end| { | 2527 | if (self.end) |end| { |
| 2488 | if (i < 1) return end; | 2528 | if (i < 1) return end; |
| 2489 | i -= 1; | 2529 | i -= 1; |
| 2490 | } | 2530 | } |
| 2491 | if (range.sentinel) |sentinel| { | 2531 | if (self.sentinel) |sentinel| { |
| 2492 | if (i < 1) return sentinel; | 2532 | if (i < 1) return sentinel; |
| 2493 | i -= 1; | 2533 | i -= 1; |
| 2494 | } | ||
| 2495 | }, | ||
| 2496 | .UnwrapOptional, | ||
| 2497 | .Deref, | ||
| 2498 | => {}, | ||
| 2499 | } | 2534 | } |
| 2500 | 2535 | ||
| 2501 | return null; | 2536 | return null; |
| 2502 | } | 2537 | } |
| 2503 | 2538 | ||
| 2504 | pub fn firstToken(self: *const SuffixOp) TokenIndex { | 2539 | pub fn firstToken(self: *const Slice) TokenIndex { |
| 2505 | return self.lhs.firstToken(); | 2540 | return self.lhs.firstToken(); |
| 2506 | } | 2541 | } |
| 2507 | 2542 | ||
| 2508 | pub fn lastToken(self: *const SuffixOp) TokenIndex { | 2543 | pub fn lastToken(self: *const Slice) TokenIndex { |
| 2509 | return self.rtoken; | 2544 | return self.rtoken; |
| 2510 | } | 2545 | } |
| 2511 | }; | 2546 | }; |
lib/std/zig/parse.zig+65-167| ... | @@ -1439,58 +1439,7 @@ const Parser = struct { | ... | @@ -1439,58 +1439,7 @@ const Parser = struct { |
| 1439 | .ExpectedPrimaryTypeExpr = .{ .token = p.tok_i }, | 1439 | .ExpectedPrimaryTypeExpr = .{ .token = p.tok_i }, |
| 1440 | }); | 1440 | }); |
| 1441 | 1441 | ||
| 1442 | // TODO pass `res` into `parseSuffixOp` rather than patching it up afterwards. | 1442 | while (try p.parseSuffixOp(res)) |node| { |
| 1443 | while (try p.parseSuffixOp()) |node| { | ||
| 1444 | switch (node.tag) { | ||
| 1445 | .SuffixOp => node.cast(Node.SuffixOp).?.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 | .OrElse, | ||
| 1490 | => node.cast(Node.SimpleInfixOp).?.lhs = res, | ||
| 1491 | |||
| 1492 | else => unreachable, | ||
| 1493 | } | ||
| 1494 | res = node; | 1443 | res = node; |
| 1495 | } | 1444 | } |
| 1496 | 1445 | ||
| ... | @@ -1516,57 +1465,7 @@ const Parser = struct { | ... | @@ -1516,57 +1465,7 @@ const Parser = struct { |
| 1516 | var res = expr; | 1465 | var res = expr; |
| 1517 | 1466 | ||
| 1518 | while (true) { | 1467 | while (true) { |
| 1519 | // TODO pass `res` into `parseSuffixOp` rather than patching it up afterwards. | 1468 | if (try p.parseSuffixOp(res)) |node| { |
| 1520 | if (try p.parseSuffixOp()) |node| { | ||
| 1521 | switch (node.tag) { | ||
| 1522 | .SuffixOp => node.cast(Node.SuffixOp).?.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 | .OrElse, | ||
| 1567 | => node.cast(Node.SimpleInfixOp).?.lhs = res, | ||
| 1568 | else => unreachable, | ||
| 1569 | } | ||
| 1570 | res = node; | 1469 | res = node; |
| 1571 | continue; | 1470 | continue; |
| 1572 | } | 1471 | } |
| ... | @@ -2733,78 +2632,77 @@ const Parser = struct { | ... | @@ -2733,78 +2632,77 @@ const Parser = struct { |
| 2733 | /// / DOT IDENTIFIER | 2632 | /// / DOT IDENTIFIER |
| 2734 | /// / DOTASTERISK | 2633 | /// / DOTASTERISK |
| 2735 | /// / DOTQUESTIONMARK | 2634 | /// / DOTQUESTIONMARK |
| 2736 | fn parseSuffixOp(p: *Parser) !?*Node { | 2635 | fn parseSuffixOp(p: *Parser, lhs: *Node) !?*Node { |
| 2737 | const OpAndToken = struct { | 2636 | if (p.eatToken(.LBracket)) |_| { |
| 2738 | op: Node.SuffixOp.Op, | 2637 | const index_expr = try p.expectNode(parseExpr, .{ |
| 2739 | token: TokenIndex, | 2638 | .ExpectedExpr = .{ .token = p.tok_i }, |
| 2740 | }; | 2639 | }); |
| 2741 | const op_and_token: OpAndToken = blk: { | ||
| 2742 | if (p.eatToken(.LBracket)) |_| { | ||
| 2743 | const index_expr = try p.expectNode(parseExpr, .{ | ||
| 2744 | .ExpectedExpr = .{ .token = p.tok_i }, | ||
| 2745 | }); | ||
| 2746 | |||
| 2747 | if (p.eatToken(.Ellipsis2) != null) { | ||
| 2748 | const end_expr = try p.parseExpr(); | ||
| 2749 | const sentinel: ?*Node = if (p.eatToken(.Colon) != null) | ||
| 2750 | try p.parseExpr() | ||
| 2751 | else | ||
| 2752 | null; | ||
| 2753 | break :blk .{ | ||
| 2754 | .op = .{ | ||
| 2755 | .Slice = .{ | ||
| 2756 | .start = index_expr, | ||
| 2757 | .end = end_expr, | ||
| 2758 | .sentinel = sentinel, | ||
| 2759 | }, | ||
| 2760 | }, | ||
| 2761 | .token = try p.expectToken(.RBracket), | ||
| 2762 | }; | ||
| 2763 | } | ||
| 2764 | 2640 | ||
| 2765 | break :blk .{ | 2641 | if (p.eatToken(.Ellipsis2) != null) { |
| 2766 | .op = .{ .ArrayAccess = index_expr }, | 2642 | const end_expr = try p.parseExpr(); |
| 2767 | .token = try p.expectToken(.RBracket), | 2643 | const sentinel: ?*Node = if (p.eatToken(.Colon) != null) |
| 2644 | try p.parseExpr() | ||
| 2645 | else | ||
| 2646 | null; | ||
| 2647 | const rtoken = try p.expectToken(.RBracket); | ||
| 2648 | const node = try p.arena.allocator.create(Node.Slice); | ||
| 2649 | node.* = .{ | ||
| 2650 | .lhs = lhs, | ||
| 2651 | .rtoken = rtoken, | ||
| 2652 | .start = index_expr, | ||
| 2653 | .end = end_expr, | ||
| 2654 | .sentinel = sentinel, | ||
| 2768 | }; | 2655 | }; |
| 2656 | return &node.base; | ||
| 2769 | } | 2657 | } |
| 2770 | 2658 | ||
| 2771 | if (p.eatToken(.PeriodAsterisk)) |period_asterisk| { | 2659 | const rtoken = try p.expectToken(.RBracket); |
| 2772 | break :blk .{ .op = .Deref, .token = period_asterisk }; | 2660 | const node = try p.arena.allocator.create(Node.ArrayAccess); |
| 2773 | } | 2661 | node.* = .{ |
| 2662 | .lhs = lhs, | ||
| 2663 | .rtoken = rtoken, | ||
| 2664 | .index_expr = index_expr, | ||
| 2665 | }; | ||
| 2666 | return &node.base; | ||
| 2667 | } | ||
| 2774 | 2668 | ||
| 2775 | if (p.eatToken(.Period)) |period| { | 2669 | if (p.eatToken(.PeriodAsterisk)) |period_asterisk| { |
| 2776 | if (try p.parseIdentifier()) |identifier| { | 2670 | const node = try p.arena.allocator.create(Node.SimpleSuffixOp); |
| 2777 | // TODO: It's a bit weird to return a SimpleInfixOp from the SuffixOp parser. | 2671 | node.* = .{ |
| 2778 | // Should there be an Node.SuffixOp.FieldAccess variant? Or should | 2672 | .base = .{ .tag = .Deref }, |
| 2779 | // this grammar rule be altered? | 2673 | .lhs = lhs, |
| 2780 | const node = try p.arena.allocator.create(Node.SimpleInfixOp); | 2674 | .rtoken = period_asterisk, |
| 2781 | node.* = .{ | 2675 | }; |
| 2782 | .base = Node{ .tag = .Period }, | 2676 | return &node.base; |
| 2783 | .op_token = period, | 2677 | } |
| 2784 | .lhs = undefined, // set by caller | ||
| 2785 | .rhs = identifier, | ||
| 2786 | }; | ||
| 2787 | return &node.base; | ||
| 2788 | } | ||
| 2789 | if (p.eatToken(.QuestionMark)) |question_mark| { | ||
| 2790 | break :blk .{ .op = .UnwrapOptional, .token = question_mark }; | ||
| 2791 | } | ||
| 2792 | try p.errors.append(p.gpa, .{ | ||
| 2793 | .ExpectedSuffixOp = .{ .token = p.tok_i }, | ||
| 2794 | }); | ||
| 2795 | return null; | ||
| 2796 | } | ||
| 2797 | 2678 | ||
| 2679 | if (p.eatToken(.Period)) |period| { | ||
| 2680 | if (try p.parseIdentifier()) |identifier| { | ||
| 2681 | const node = try p.arena.allocator.create(Node.SimpleInfixOp); | ||
| 2682 | node.* = .{ | ||
| 2683 | .base = Node{ .tag = .Period }, | ||
| 2684 | .op_token = period, | ||
| 2685 | .lhs = lhs, | ||
| 2686 | .rhs = identifier, | ||
| 2687 | }; | ||
| 2688 | return &node.base; | ||
| 2689 | } | ||
| 2690 | if (p.eatToken(.QuestionMark)) |question_mark| { | ||
| 2691 | const node = try p.arena.allocator.create(Node.SimpleSuffixOp); | ||
| 2692 | node.* = .{ | ||
| 2693 | .base = .{ .tag = .UnwrapOptional }, | ||
| 2694 | .lhs = lhs, | ||
| 2695 | .rtoken = question_mark, | ||
| 2696 | }; | ||
| 2697 | return &node.base; | ||
| 2698 | } | ||
| 2699 | try p.errors.append(p.gpa, .{ | ||
| 2700 | .ExpectedSuffixOp = .{ .token = p.tok_i }, | ||
| 2701 | }); | ||
| 2798 | return null; | 2702 | return null; |
| 2799 | }; | 2703 | } |
| 2800 | 2704 | ||
| 2801 | const node = try p.arena.allocator.create(Node.SuffixOp); | 2705 | return null; |
| 2802 | node.* = .{ | ||
| 2803 | .lhs = undefined, // set by caller | ||
| 2804 | .op = op_and_token.op, | ||
| 2805 | .rtoken = op_and_token.token, | ||
| 2806 | }; | ||
| 2807 | return &node.base; | ||
| 2808 | } | 2706 | } |
| 2809 | 2707 | ||
| 2810 | /// FnCallArguments <- LPAREN ExprList RPAREN | 2708 | /// FnCallArguments <- LPAREN ExprList RPAREN |
lib/std/zig/render.zig+54-55| ... | @@ -1044,68 +1044,67 @@ fn renderExpression( | ... | @@ -1044,68 +1044,67 @@ fn renderExpression( |
| 1044 | return renderToken(tree, stream, call.rtoken, indent, start_col, space); | 1044 | return renderToken(tree, stream, call.rtoken, indent, start_col, space); |
| 1045 | }, | 1045 | }, |
| 1046 | 1046 | ||
| 1047 | .SuffixOp => { | 1047 | .ArrayAccess => { |
| 1048 | const suffix_op = @fieldParentPtr(ast.Node.SuffixOp, "base", base); | 1048 | const suffix_op = base.castTag(.ArrayAccess).?; |
| 1049 | |||
| 1050 | switch (suffix_op.op) { | ||
| 1051 | .ArrayAccess => |index_expr| { | ||
| 1052 | const lbracket = tree.nextToken(suffix_op.lhs.lastToken()); | ||
| 1053 | const rbracket = tree.nextToken(index_expr.lastToken()); | ||
| 1054 | |||
| 1055 | try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None); | ||
| 1056 | try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [ | ||
| 1057 | |||
| 1058 | const starts_with_comment = tree.token_ids[lbracket + 1] == .LineComment; | ||
| 1059 | const ends_with_comment = tree.token_ids[rbracket - 1] == .LineComment; | ||
| 1060 | const new_indent = if (ends_with_comment) indent + indent_delta else indent; | ||
| 1061 | const new_space = if (ends_with_comment) Space.Newline else Space.None; | ||
| 1062 | try renderExpression(allocator, stream, tree, new_indent, start_col, index_expr, new_space); | ||
| 1063 | if (starts_with_comment) { | ||
| 1064 | try stream.writeByte('\n'); | ||
| 1065 | } | ||
| 1066 | if (ends_with_comment or starts_with_comment) { | ||
| 1067 | try stream.writeByteNTimes(' ', indent); | ||
| 1068 | } | ||
| 1069 | return renderToken(tree, stream, rbracket, indent, start_col, space); // ] | ||
| 1070 | }, | ||
| 1071 | 1049 | ||
| 1072 | .Deref => { | 1050 | const lbracket = tree.nextToken(suffix_op.lhs.lastToken()); |
| 1073 | try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None); | 1051 | const rbracket = tree.nextToken(suffix_op.index_expr.lastToken()); |
| 1074 | return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // .* | ||
| 1075 | }, | ||
| 1076 | 1052 | ||
| 1077 | .UnwrapOptional => { | 1053 | try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None); |
| 1078 | try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None); | 1054 | try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [ |
| 1079 | try renderToken(tree, stream, tree.prevToken(suffix_op.rtoken), indent, start_col, Space.None); // . | 1055 | |
| 1080 | return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // ? | 1056 | const starts_with_comment = tree.token_ids[lbracket + 1] == .LineComment; |
| 1081 | }, | 1057 | const ends_with_comment = tree.token_ids[rbracket - 1] == .LineComment; |
| 1058 | const new_indent = if (ends_with_comment) indent + indent_delta else indent; | ||
| 1059 | const new_space = if (ends_with_comment) Space.Newline else Space.None; | ||
| 1060 | try renderExpression(allocator, stream, tree, new_indent, start_col, suffix_op.index_expr, new_space); | ||
| 1061 | if (starts_with_comment) { | ||
| 1062 | try stream.writeByte('\n'); | ||
| 1063 | } | ||
| 1064 | if (ends_with_comment or starts_with_comment) { | ||
| 1065 | try stream.writeByteNTimes(' ', indent); | ||
| 1066 | } | ||
| 1067 | return renderToken(tree, stream, rbracket, indent, start_col, space); // ] | ||
| 1068 | }, | ||
| 1069 | .Slice => { | ||
| 1070 | const suffix_op = base.castTag(.Slice).?; | ||
| 1082 | 1071 | ||
| 1083 | .Slice => |range| { | 1072 | try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None); |
| 1084 | try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None); | ||
| 1085 | 1073 | ||
| 1086 | const lbracket = tree.prevToken(range.start.firstToken()); | 1074 | const lbracket = tree.prevToken(suffix_op.start.firstToken()); |
| 1087 | const dotdot = tree.nextToken(range.start.lastToken()); | 1075 | const dotdot = tree.nextToken(suffix_op.start.lastToken()); |
| 1088 | 1076 | ||
| 1089 | const after_start_space_bool = nodeCausesSliceOpSpace(range.start) or | 1077 | const after_start_space_bool = nodeCausesSliceOpSpace(suffix_op.start) or |
| 1090 | (if (range.end) |end| nodeCausesSliceOpSpace(end) else false); | 1078 | (if (suffix_op.end) |end| nodeCausesSliceOpSpace(end) else false); |
| 1091 | const after_start_space = if (after_start_space_bool) Space.Space else Space.None; | 1079 | const after_start_space = if (after_start_space_bool) Space.Space else Space.None; |
| 1092 | const after_op_space = if (range.end != null) after_start_space else Space.None; | 1080 | const after_op_space = if (suffix_op.end != null) after_start_space else Space.None; |
| 1093 | 1081 | ||
| 1094 | try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [ | 1082 | try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [ |
| 1095 | try renderExpression(allocator, stream, tree, indent, start_col, range.start, after_start_space); | 1083 | try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.start, after_start_space); |
| 1096 | try renderToken(tree, stream, dotdot, indent, start_col, after_op_space); // .. | 1084 | try renderToken(tree, stream, dotdot, indent, start_col, after_op_space); // .. |
| 1097 | if (range.end) |end| { | 1085 | if (suffix_op.end) |end| { |
| 1098 | const after_end_space = if (range.sentinel != null) Space.Space else Space.None; | 1086 | const after_end_space = if (suffix_op.sentinel != null) Space.Space else Space.None; |
| 1099 | try renderExpression(allocator, stream, tree, indent, start_col, end, after_end_space); | 1087 | try renderExpression(allocator, stream, tree, indent, start_col, end, after_end_space); |
| 1100 | } | ||
| 1101 | if (range.sentinel) |sentinel| { | ||
| 1102 | const colon = tree.prevToken(sentinel.firstToken()); | ||
| 1103 | try renderToken(tree, stream, colon, indent, start_col, Space.None); // : | ||
| 1104 | try renderExpression(allocator, stream, tree, indent, start_col, sentinel, Space.None); | ||
| 1105 | } | ||
| 1106 | return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // ] | ||
| 1107 | }, | ||
| 1108 | } | 1088 | } |
| 1089 | if (suffix_op.sentinel) |sentinel| { | ||
| 1090 | const colon = tree.prevToken(sentinel.firstToken()); | ||
| 1091 | try renderToken(tree, stream, colon, indent, start_col, Space.None); // : | ||
| 1092 | try renderExpression(allocator, stream, tree, indent, start_col, sentinel, Space.None); | ||
| 1093 | } | ||
| 1094 | return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // ] | ||
| 1095 | }, | ||
| 1096 | .Deref => { | ||
| 1097 | const suffix_op = base.castTag(.Deref).?; | ||
| 1098 | |||
| 1099 | try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None); | ||
| 1100 | return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // .* | ||
| 1101 | }, | ||
| 1102 | .UnwrapOptional => { | ||
| 1103 | const suffix_op = base.castTag(.UnwrapOptional).?; | ||
| 1104 | |||
| 1105 | try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None); | ||
| 1106 | try renderToken(tree, stream, tree.prevToken(suffix_op.rtoken), indent, start_col, Space.None); // . | ||
| 1107 | return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // ? | ||
| 1109 | }, | 1108 | }, |
| 1110 | 1109 | ||
| 1111 | .ControlFlowExpression => { | 1110 | .ControlFlowExpression => { |
src-self-hosted/astgen.zig+39-32| ... | @@ -34,7 +34,7 @@ pub fn expr(mod: *Module, scope: *Scope, node: *ast.Node) InnerError!*zir.Inst { | ... | @@ -34,7 +34,7 @@ pub fn expr(mod: *Module, scope: *Scope, node: *ast.Node) InnerError!*zir.Inst { |
| 34 | .LessThan => return cmp(mod, scope, node.castTag(.LessThan).?, .lt), | 34 | .LessThan => return cmp(mod, scope, node.castTag(.LessThan).?, .lt), |
| 35 | .LessOrEqual => return cmp(mod, scope, node.castTag(.LessOrEqual).?, .lte), | 35 | .LessOrEqual => return cmp(mod, scope, node.castTag(.LessOrEqual).?, .lte), |
| 36 | .Period => return field(mod, scope, node.castTag(.Period).?), | 36 | .Period => return field(mod, scope, node.castTag(.Period).?), |
| 37 | .SuffixOp => return suffixOp(mod, scope, node.castTag(.SuffixOp).?), | 37 | .Deref => return deref(mod, scope, node.castTag(.Deref).?), |
| 38 | .BoolNot => return boolNot(mod, scope, node.castTag(.BoolNot).?), | 38 | .BoolNot => return boolNot(mod, scope, node.castTag(.BoolNot).?), |
| 39 | else => return mod.failNode(scope, node, "TODO implement astgen.Expr for {}", .{@tagName(node.tag)}), | 39 | else => return mod.failNode(scope, node, "TODO implement astgen.Expr for {}", .{@tagName(node.tag)}), |
| 40 | } | 40 | } |
| ... | @@ -73,32 +73,41 @@ fn varDecl(mod: *Module, scope: *Scope, node: *ast.Node.VarDecl) InnerError!Scop | ... | @@ -73,32 +73,41 @@ fn varDecl(mod: *Module, scope: *Scope, node: *ast.Node.VarDecl) InnerError!Scop |
| 73 | if (node.getTrailer("align_node")) |align_node| { | 73 | if (node.getTrailer("align_node")) |align_node| { |
| 74 | return mod.failNode(scope, align_node, "TODO implement alignment on locals", .{}); | 74 | return mod.failNode(scope, align_node, "TODO implement alignment on locals", .{}); |
| 75 | } | 75 | } |
| 76 | if (node.getTrailer("type_node")) |type_node| { | ||
| 77 | return mod.failNode(scope, type_node, "TODO implement typed locals", .{}); | ||
| 78 | } | ||
| 79 | const tree = scope.tree(); | 76 | const tree = scope.tree(); |
| 80 | switch (tree.token_ids[node.mut_token]) { | 77 | switch (tree.token_ids[node.mut_token]) { |
| 81 | .Keyword_const => {}, | 78 | .Keyword_const => { |
| 79 | if (node.getTrailer("type_node")) |type_node| { | ||
| 80 | return mod.failNode(scope, type_node, "TODO implement typed const locals", .{}); | ||
| 81 | } | ||
| 82 | // Depending on the type of AST the initialization expression is, we may need an lvalue | ||
| 83 | // or an rvalue as a result location. If it is an rvalue, we can use the instruction as | ||
| 84 | // the variable, no memory location needed. | ||
| 85 | const init_node = node.getTrailer("init_node").?; | ||
| 86 | if (nodeMayNeedMemoryLocation(init_node)) { | ||
| 87 | return mod.failNode(scope, init_node, "TODO implement result locations", .{}); | ||
| 88 | } | ||
| 89 | const init_inst = try expr(mod, scope, init_node); | ||
| 90 | const ident_name = try identifierTokenString(mod, scope, node.name_token); | ||
| 91 | return Scope.LocalVar{ | ||
| 92 | .parent = scope, | ||
| 93 | .gen_zir = scope.getGenZIR(), | ||
| 94 | .name = ident_name, | ||
| 95 | .inst = init_inst, | ||
| 96 | }; | ||
| 97 | }, | ||
| 82 | .Keyword_var => { | 98 | .Keyword_var => { |
| 83 | return mod.failTok(scope, node.mut_token, "TODO implement mutable locals", .{}); | 99 | return mod.failNode(scope, &node.base, "TODO implement local vars", .{}); |
| 100 | //const src = tree.token_locs[node.name_token].start; | ||
| 101 | //const alloc = mod.addZIRInst(scope, src, zir.Inst.Alloc, .{}, .{}); | ||
| 102 | //if (node.getTrailer("type_node")) |type_node| { | ||
| 103 | // const type_inst = try expr(mod, scope, type_node); | ||
| 104 | // return mod.failNode(scope, type_node, "TODO implement typed var locals", .{}); | ||
| 105 | //} else { | ||
| 106 | // return mod.failTok(scope, node.mut_token, "TODO implement mutable type-inferred locals", .{}); | ||
| 107 | //} | ||
| 84 | }, | 108 | }, |
| 85 | else => unreachable, | 109 | else => unreachable, |
| 86 | } | 110 | } |
| 87 | // Depending on the type of AST the initialization expression is, we may need an lvalue | ||
| 88 | // or an rvalue as a result location. If it is an rvalue, we can use the instruction as | ||
| 89 | // the variable, no memory location needed. | ||
| 90 | const init_node = node.getTrailer("init_node").?; | ||
| 91 | if (nodeMayNeedMemoryLocation(init_node)) { | ||
| 92 | return mod.failNode(scope, init_node, "TODO implement result locations", .{}); | ||
| 93 | } | ||
| 94 | const init_inst = try expr(mod, scope, init_node); | ||
| 95 | const ident_name = try identifierTokenString(mod, scope, node.name_token); | ||
| 96 | return Scope.LocalVar{ | ||
| 97 | .parent = scope, | ||
| 98 | .gen_zir = scope.getGenZIR(), | ||
| 99 | .name = ident_name, | ||
| 100 | .inst = init_inst, | ||
| 101 | }; | ||
| 102 | } | 111 | } |
| 103 | 112 | ||
| 104 | fn boolNot(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerError!*zir.Inst { | 113 | fn boolNot(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerError!*zir.Inst { |
| ... | @@ -163,18 +172,13 @@ fn field(mod: *Module, scope: *Scope, node: *ast.Node.SimpleInfixOp) InnerError! | ... | @@ -163,18 +172,13 @@ fn field(mod: *Module, scope: *Scope, node: *ast.Node.SimpleInfixOp) InnerError! |
| 163 | return mod.addZIRInst(scope, src, zir.Inst.Deref, .{ .ptr = pointer }, .{}); | 172 | return mod.addZIRInst(scope, src, zir.Inst.Deref, .{ .ptr = pointer }, .{}); |
| 164 | } | 173 | } |
| 165 | 174 | ||
| 166 | fn suffixOp(mod: *Module, scope: *Scope, node: *ast.Node.SuffixOp) InnerError!*zir.Inst { | 175 | fn deref(mod: *Module, scope: *Scope, node: *ast.Node.SimpleSuffixOp) InnerError!*zir.Inst { |
| 167 | switch (node.op) { | 176 | const tree = scope.tree(); |
| 168 | .Deref => { | 177 | const src = tree.token_locs[node.rtoken].start; |
| 169 | const tree = scope.tree(); | ||
| 170 | const src = tree.token_locs[node.rtoken].start; | ||
| 171 | 178 | ||
| 172 | const lhs = try expr(mod, scope, node.lhs); | 179 | const lhs = try expr(mod, scope, node.lhs); |
| 173 | 180 | ||
| 174 | return mod.addZIRInst(scope, src, zir.Inst.Deref, .{ .ptr = lhs }, .{}); | 181 | return mod.addZIRInst(scope, src, zir.Inst.Deref, .{ .ptr = lhs }, .{}); |
| 175 | }, | ||
| 176 | else => return mod.failNode(scope, &node.base, "TODO implement astGenExpr for suffixOp {}", .{node.op}), | ||
| 177 | } | ||
| 178 | } | 182 | } |
| 179 | 183 | ||
| 180 | fn add(mod: *Module, scope: *Scope, infix_node: *ast.Node.SimpleInfixOp) InnerError!*zir.Inst { | 184 | fn add(mod: *Module, scope: *Scope, infix_node: *ast.Node.SimpleInfixOp) InnerError!*zir.Inst { |
| ... | @@ -672,6 +676,9 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node) bool { | ... | @@ -672,6 +676,9 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node) bool { |
| 672 | .Period, | 676 | .Period, |
| 673 | .Sub, | 677 | .Sub, |
| 674 | .SubWrap, | 678 | .SubWrap, |
| 679 | .Slice, | ||
| 680 | .Deref, | ||
| 681 | .ArrayAccess, | ||
| 675 | => return false, | 682 | => return false, |
| 676 | 683 | ||
| 677 | // Forward the question to a sub-expression. | 684 | // Forward the question to a sub-expression. |
| ... | @@ -682,6 +689,7 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node) bool { | ... | @@ -682,6 +689,7 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node) bool { |
| 682 | .OrElse => node = node.castTag(.OrElse).?.rhs, | 689 | .OrElse => node = node.castTag(.OrElse).?.rhs, |
| 683 | .Comptime => node = node.castTag(.Comptime).?.expr, | 690 | .Comptime => node = node.castTag(.Comptime).?.expr, |
| 684 | .Nosuspend => node = node.castTag(.Nosuspend).?.expr, | 691 | .Nosuspend => node = node.castTag(.Nosuspend).?.expr, |
| 692 | .UnwrapOptional => node = node.castTag(.UnwrapOptional).?.lhs, | ||
| 685 | 693 | ||
| 686 | // True because these are exactly the expressions we need memory locations for. | 694 | // True because these are exactly the expressions we need memory locations for. |
| 687 | .ArrayInitializer, | 695 | .ArrayInitializer, |
| ... | @@ -697,7 +705,6 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node) bool { | ... | @@ -697,7 +705,6 @@ fn nodeMayNeedMemoryLocation(start_node: *ast.Node) bool { |
| 697 | .Switch, | 705 | .Switch, |
| 698 | .Call, | 706 | .Call, |
| 699 | .BuiltinCall, // TODO some of these can return false | 707 | .BuiltinCall, // TODO some of these can return false |
| 700 | .SuffixOp, // TODO this should be split up | ||
| 701 | => return true, | 708 | => return true, |
| 702 | 709 | ||
| 703 | // Depending on AST properties, they may need memory locations. | 710 | // Depending on AST properties, they may need memory locations. |
src-self-hosted/translate_c.zig+10-13| ... | @@ -2962,9 +2962,9 @@ fn transArrayAccess(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangArrayS | ... | @@ -2962,9 +2962,9 @@ fn transArrayAccess(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangArrayS |
| 2962 | cast_node.params()[1] = try transExpr(rp, scope, subscr_expr, .used, .r_value); | 2962 | cast_node.params()[1] = try transExpr(rp, scope, subscr_expr, .used, .r_value); |
| 2963 | cast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); | 2963 | cast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); |
| 2964 | node.rtoken = try appendToken(rp.c, .RBrace, "]"); | 2964 | node.rtoken = try appendToken(rp.c, .RBrace, "]"); |
| 2965 | node.op.ArrayAccess = &cast_node.base; | 2965 | node.index_expr = &cast_node.base; |
| 2966 | } else { | 2966 | } else { |
| 2967 | node.op.ArrayAccess = try transExpr(rp, scope, subscr_expr, .used, .r_value); | 2967 | node.index_expr = try transExpr(rp, scope, subscr_expr, .used, .r_value); |
| 2968 | node.rtoken = try appendToken(rp.c, .RBrace, "]"); | 2968 | node.rtoken = try appendToken(rp.c, .RBrace, "]"); |
| 2969 | } | 2969 | } |
| 2970 | return maybeSuppressResult(rp, scope, result_used, &node.base); | 2970 | return maybeSuppressResult(rp, scope, result_used, &node.base); |
| ... | @@ -4405,9 +4405,9 @@ fn transCreateNodeMacroFn(c: *Context, name: []const u8, ref: *ast.Node, proto_a | ... | @@ -4405,9 +4405,9 @@ fn transCreateNodeMacroFn(c: *Context, name: []const u8, ref: *ast.Node, proto_a |
| 4405 | fn transCreateNodeUnwrapNull(c: *Context, wrapped: *ast.Node) !*ast.Node { | 4405 | fn transCreateNodeUnwrapNull(c: *Context, wrapped: *ast.Node) !*ast.Node { |
| 4406 | _ = try appendToken(c, .Period, "."); | 4406 | _ = try appendToken(c, .Period, "."); |
| 4407 | const qm = try appendToken(c, .QuestionMark, "?"); | 4407 | const qm = try appendToken(c, .QuestionMark, "?"); |
| 4408 | const node = try c.arena.create(ast.Node.SuffixOp); | 4408 | const node = try c.arena.create(ast.Node.SimpleSuffixOp); |
| 4409 | node.* = .{ | 4409 | node.* = .{ |
| 4410 | .op = .UnwrapOptional, | 4410 | .base = .{ .tag = .UnwrapOptional }, |
| 4411 | .lhs = wrapped, | 4411 | .lhs = wrapped, |
| 4412 | .rtoken = qm, | 4412 | .rtoken = qm, |
| 4413 | }; | 4413 | }; |
| ... | @@ -4567,23 +4567,21 @@ fn transCreateNodeShiftOp( | ... | @@ -4567,23 +4567,21 @@ fn transCreateNodeShiftOp( |
| 4567 | } | 4567 | } |
| 4568 | 4568 | ||
| 4569 | fn transCreateNodePtrDeref(c: *Context, lhs: *ast.Node) !*ast.Node { | 4569 | fn transCreateNodePtrDeref(c: *Context, lhs: *ast.Node) !*ast.Node { |
| 4570 | const node = try c.arena.create(ast.Node.SuffixOp); | 4570 | const node = try c.arena.create(ast.Node.SimpleSuffixOp); |
| 4571 | node.* = .{ | 4571 | node.* = .{ |
| 4572 | .base = .{ .tag = .Deref }, | ||
| 4572 | .lhs = lhs, | 4573 | .lhs = lhs, |
| 4573 | .op = .Deref, | ||
| 4574 | .rtoken = try appendToken(c, .PeriodAsterisk, ".*"), | 4574 | .rtoken = try appendToken(c, .PeriodAsterisk, ".*"), |
| 4575 | }; | 4575 | }; |
| 4576 | return &node.base; | 4576 | return &node.base; |
| 4577 | } | 4577 | } |
| 4578 | 4578 | ||
| 4579 | fn transCreateNodeArrayAccess(c: *Context, lhs: *ast.Node) !*ast.Node.SuffixOp { | 4579 | fn transCreateNodeArrayAccess(c: *Context, lhs: *ast.Node) !*ast.Node.ArrayAccess { |
| 4580 | _ = try appendToken(c, .LBrace, "["); | 4580 | _ = try appendToken(c, .LBrace, "["); |
| 4581 | const node = try c.arena.create(ast.Node.SuffixOp); | 4581 | const node = try c.arena.create(ast.Node.ArrayAccess); |
| 4582 | node.* = .{ | 4582 | node.* = .{ |
| 4583 | .lhs = lhs, | 4583 | .lhs = lhs, |
| 4584 | .op = .{ | 4584 | .index_expr = undefined, |
| 4585 | .ArrayAccess = undefined, | ||
| 4586 | }, | ||
| 4587 | .rtoken = undefined, | 4585 | .rtoken = undefined, |
| 4588 | }; | 4586 | }; |
| 4589 | return node; | 4587 | return node; |
| ... | @@ -6010,7 +6008,7 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, | ... | @@ -6010,7 +6008,7 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, |
| 6010 | }, | 6008 | }, |
| 6011 | .LBracket => { | 6009 | .LBracket => { |
| 6012 | const arr_node = try transCreateNodeArrayAccess(c, node); | 6010 | const arr_node = try transCreateNodeArrayAccess(c, node); |
| 6013 | arr_node.op.ArrayAccess = try parseCPrefixOpExpr(c, it, source, source_loc, scope); | 6011 | arr_node.index_expr = try parseCPrefixOpExpr(c, it, source, source_loc, scope); |
| 6014 | arr_node.rtoken = try appendToken(c, .RBracket, "]"); | 6012 | arr_node.rtoken = try appendToken(c, .RBracket, "]"); |
| 6015 | node = &arr_node.base; | 6013 | node = &arr_node.base; |
| 6016 | if (it.next().?.id != .RBracket) { | 6014 | if (it.next().?.id != .RBracket) { |
| ... | @@ -6099,7 +6097,6 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, | ... | @@ -6099,7 +6097,6 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, |
| 6099 | }; | 6097 | }; |
| 6100 | mem.copy(*ast.Node, tuple_node.list(), init_vals.items); | 6098 | mem.copy(*ast.Node, tuple_node.list(), init_vals.items); |
| 6101 | 6099 | ||
| 6102 | |||
| 6103 | //(@import("std").mem.zeroInit(T, .{x})) | 6100 | //(@import("std").mem.zeroInit(T, .{x})) |
| 6104 | const import_fn_call = try c.createBuiltinCall("@import", 1); | 6101 | const import_fn_call = try c.createBuiltinCall("@import", 1); |
| 6105 | const std_node = try transCreateNodeStringLiteral(c, "\"std\""); | 6102 | const std_node = try transCreateNodeStringLiteral(c, "\"std\""); |