| author | |
| committer | |
| log | 9377af934f5be92821f36b5d2255f086e5a84cda |
| tree | e58814eecf85d3e59da6b7bc04c6a432fd1689cd |
| parent | d37b81d43bc52daa94dd1ad1631018ea0cd11f77 |
no perf impact, but the API is better3 files changed, 49 insertions(+), 29 deletions(-)
lib/std/zig/ast.zig+30-9| ... | @@ -1552,28 +1552,35 @@ pub const Node = struct { | ... | @@ -1552,28 +1552,35 @@ pub const Node = struct { |
| 1552 | } | 1552 | } |
| 1553 | }; | 1553 | }; |
| 1554 | 1554 | ||
| 1555 | /// Items sub-nodes appear in memory directly following SwitchCase. | ||
| 1555 | pub const SwitchCase = struct { | 1556 | pub const SwitchCase = struct { |
| 1556 | base: Node = Node{ .id = .SwitchCase }, | 1557 | base: Node = Node{ .id = .SwitchCase }, |
| 1557 | items: ItemList, | ||
| 1558 | arrow_token: TokenIndex, | 1558 | arrow_token: TokenIndex, |
| 1559 | payload: ?*Node, | 1559 | payload: ?*Node, |
| 1560 | expr: *Node, | 1560 | expr: *Node, |
| 1561 | items_len: NodeIndex, | ||
| 1561 | 1562 | ||
| 1562 | pub const ItemList = LinkedList(*Node); | 1563 | /// After this the caller must initialize the fields_and_decls list. |
| 1564 | pub fn alloc(allocator: *mem.Allocator, items_len: NodeIndex) !*SwitchCase { | ||
| 1565 | const bytes = try allocator.alignedAlloc(u8, @alignOf(SwitchCase), sizeInBytes(items_len)); | ||
| 1566 | return @ptrCast(*SwitchCase, bytes.ptr); | ||
| 1567 | } | ||
| 1568 | |||
| 1569 | pub fn free(self: *SwitchCase, allocator: *mem.Allocator) void { | ||
| 1570 | const bytes = @ptrCast([*]u8, self)[0..sizeInBytes(self.items_len)]; | ||
| 1571 | allocator.free(bytes); | ||
| 1572 | } | ||
| 1563 | 1573 | ||
| 1564 | pub fn iterate(self: *const SwitchCase) Node.Iterator { | 1574 | pub fn iterate(self: *const SwitchCase) Node.Iterator { |
| 1565 | return .{ .parent_node = &self.base, .index = 0, .node = self.items.first }; | 1575 | return .{ .parent_node = &self.base, .index = 0, .node = null }; |
| 1566 | } | 1576 | } |
| 1567 | 1577 | ||
| 1568 | pub fn iterateNext(self: *const SwitchCase, it: *Node.Iterator) ?*Node { | 1578 | pub fn iterateNext(self: *const SwitchCase, it: *Node.Iterator) ?*Node { |
| 1569 | var i = it.index; | 1579 | var i = it.index; |
| 1570 | it.index += 1; | 1580 | it.index += 1; |
| 1571 | 1581 | ||
| 1572 | if (it.node) |child| { | 1582 | if (i < self.items_len) return self.itemsConst()[i]; |
| 1573 | it.index -= 1; | 1583 | i -= self.items_len; |
| 1574 | it.node = child.next; | ||
| 1575 | return child.data; | ||
| 1576 | } | ||
| 1577 | 1584 | ||
| 1578 | if (self.payload) |payload| { | 1585 | if (self.payload) |payload| { |
| 1579 | if (i < 1) return payload; | 1586 | if (i < 1) return payload; |
| ... | @@ -1587,12 +1594,26 @@ pub const Node = struct { | ... | @@ -1587,12 +1594,26 @@ pub const Node = struct { |
| 1587 | } | 1594 | } |
| 1588 | 1595 | ||
| 1589 | pub fn firstToken(self: *const SwitchCase) TokenIndex { | 1596 | pub fn firstToken(self: *const SwitchCase) TokenIndex { |
| 1590 | return self.items.first.?.data.firstToken(); | 1597 | return self.itemsConst()[0].firstToken(); |
| 1591 | } | 1598 | } |
| 1592 | 1599 | ||
| 1593 | pub fn lastToken(self: *const SwitchCase) TokenIndex { | 1600 | pub fn lastToken(self: *const SwitchCase) TokenIndex { |
| 1594 | return self.expr.lastToken(); | 1601 | return self.expr.lastToken(); |
| 1595 | } | 1602 | } |
| 1603 | |||
| 1604 | pub fn items(self: *SwitchCase) []*Node { | ||
| 1605 | const decls_start = @ptrCast([*]u8, self) + @sizeOf(SwitchCase); | ||
| 1606 | return @ptrCast([*]*Node, decls_start)[0..self.items_len]; | ||
| 1607 | } | ||
| 1608 | |||
| 1609 | pub fn itemsConst(self: *const SwitchCase) []const *Node { | ||
| 1610 | const decls_start = @ptrCast([*]const u8, self) + @sizeOf(SwitchCase); | ||
| 1611 | return @ptrCast([*]const *Node, decls_start)[0..self.items_len]; | ||
| 1612 | } | ||
| 1613 | |||
| 1614 | fn sizeInBytes(items_len: NodeIndex) usize { | ||
| 1615 | return @sizeOf(SwitchCase) + @sizeOf(*Node) * @as(usize, items_len); | ||
| 1616 | } | ||
| 1596 | }; | 1617 | }; |
| 1597 | 1618 | ||
| 1598 | pub const SwitchElse = struct { | 1619 | pub const SwitchElse = struct { |
lib/std/zig/parse.zig+8-7| ... | @@ -2205,30 +2205,31 @@ const Parser = struct { | ... | @@ -2205,30 +2205,31 @@ const Parser = struct { |
| 2205 | /// <- SwitchItem (COMMA SwitchItem)* COMMA? | 2205 | /// <- SwitchItem (COMMA SwitchItem)* COMMA? |
| 2206 | /// / KEYWORD_else | 2206 | /// / KEYWORD_else |
| 2207 | fn parseSwitchCase(p: *Parser) !?*Node { | 2207 | fn parseSwitchCase(p: *Parser) !?*Node { |
| 2208 | var list = Node.SwitchCase.ItemList{}; | 2208 | var list = std.ArrayList(*Node).init(p.gpa); |
| 2209 | var list_it = &list.first; | 2209 | defer list.deinit(); |
| 2210 | 2210 | ||
| 2211 | if (try p.parseSwitchItem()) |first_item| { | 2211 | if (try p.parseSwitchItem()) |first_item| { |
| 2212 | list_it = try p.llpush(*Node, list_it, first_item); | 2212 | try list.append(first_item); |
| 2213 | while (p.eatToken(.Comma) != null) { | 2213 | while (p.eatToken(.Comma) != null) { |
| 2214 | const next_item = (try p.parseSwitchItem()) orelse break; | 2214 | const next_item = (try p.parseSwitchItem()) orelse break; |
| 2215 | list_it = try p.llpush(*Node, list_it, next_item); | 2215 | try list.append(next_item); |
| 2216 | } | 2216 | } |
| 2217 | } else if (p.eatToken(.Keyword_else)) |else_token| { | 2217 | } else if (p.eatToken(.Keyword_else)) |else_token| { |
| 2218 | const else_node = try p.arena.allocator.create(Node.SwitchElse); | 2218 | const else_node = try p.arena.allocator.create(Node.SwitchElse); |
| 2219 | else_node.* = .{ | 2219 | else_node.* = .{ |
| 2220 | .token = else_token, | 2220 | .token = else_token, |
| 2221 | }; | 2221 | }; |
| 2222 | list_it = try p.llpush(*Node, list_it, &else_node.base); | 2222 | try list.append(&else_node.base); |
| 2223 | } else return null; | 2223 | } else return null; |
| 2224 | 2224 | ||
| 2225 | const node = try p.arena.allocator.create(Node.SwitchCase); | 2225 | const node = try Node.SwitchCase.alloc(&p.arena.allocator, list.items.len); |
| 2226 | node.* = .{ | 2226 | node.* = .{ |
| 2227 | .items = list, | 2227 | .items_len = list.items.len, |
| 2228 | .arrow_token = undefined, // set by caller | 2228 | .arrow_token = undefined, // set by caller |
| 2229 | .payload = null, | 2229 | .payload = null, |
| 2230 | .expr = undefined, // set by caller | 2230 | .expr = undefined, // set by caller |
| 2231 | }; | 2231 | }; |
| 2232 | std.mem.copy(*Node, node.items(), list.items); | ||
| 2232 | return &node.base; | 2233 | return &node.base; |
| 2233 | } | 2234 | } |
| 2234 | 2235 |
lib/std/zig/render.zig+11-13| ... | @@ -1613,37 +1613,35 @@ fn renderExpression( | ... | @@ -1613,37 +1613,35 @@ fn renderExpression( |
| 1613 | .SwitchCase => { | 1613 | .SwitchCase => { |
| 1614 | const switch_case = @fieldParentPtr(ast.Node.SwitchCase, "base", base); | 1614 | const switch_case = @fieldParentPtr(ast.Node.SwitchCase, "base", base); |
| 1615 | 1615 | ||
| 1616 | assert(switch_case.items.first != null); | 1616 | assert(switch_case.items_len != 0); |
| 1617 | const src_has_trailing_comma = blk: { | 1617 | const src_has_trailing_comma = blk: { |
| 1618 | const last_node = switch_case.items.first.?.findLast().data; | 1618 | const last_node = switch_case.items()[switch_case.items_len - 1]; |
| 1619 | const maybe_comma = tree.nextToken(last_node.lastToken()); | 1619 | const maybe_comma = tree.nextToken(last_node.lastToken()); |
| 1620 | break :blk tree.tokens[maybe_comma].id == .Comma; | 1620 | break :blk tree.tokens[maybe_comma].id == .Comma; |
| 1621 | }; | 1621 | }; |
| 1622 | 1622 | ||
| 1623 | if (switch_case.items.first.?.next == null or !src_has_trailing_comma) { | 1623 | if (switch_case.items_len == 1 or !src_has_trailing_comma) { |
| 1624 | var it = switch_case.items.first; | 1624 | const items = switch_case.items(); |
| 1625 | while (it) |node_node| : (it = node_node.next) { | 1625 | for (items) |node, i| { |
| 1626 | const node = node_node.data; | 1626 | if (i + 1 < items.len) { |
| 1627 | if (node_node.next) |next_node| { | ||
| 1628 | try renderExpression(allocator, stream, tree, indent, start_col, node, Space.None); | 1627 | try renderExpression(allocator, stream, tree, indent, start_col, node, Space.None); |
| 1629 | 1628 | ||
| 1630 | const comma_token = tree.nextToken(node.lastToken()); | 1629 | const comma_token = tree.nextToken(node.lastToken()); |
| 1631 | try renderToken(tree, stream, comma_token, indent, start_col, Space.Space); // , | 1630 | try renderToken(tree, stream, comma_token, indent, start_col, Space.Space); // , |
| 1632 | try renderExtraNewline(tree, stream, start_col, next_node.data); | 1631 | try renderExtraNewline(tree, stream, start_col, items[i + 1]); |
| 1633 | } else { | 1632 | } else { |
| 1634 | try renderExpression(allocator, stream, tree, indent, start_col, node, Space.Space); | 1633 | try renderExpression(allocator, stream, tree, indent, start_col, node, Space.Space); |
| 1635 | } | 1634 | } |
| 1636 | } | 1635 | } |
| 1637 | } else { | 1636 | } else { |
| 1638 | var it = switch_case.items.first; | 1637 | const items = switch_case.items(); |
| 1639 | while (it) |node_node| : (it = node_node.next) { | 1638 | for (items) |node, i| { |
| 1640 | const node = node_node.data; | 1639 | if (i + 1 < items.len) { |
| 1641 | if (node_node.next) |next_node| { | ||
| 1642 | try renderExpression(allocator, stream, tree, indent, start_col, node, Space.None); | 1640 | try renderExpression(allocator, stream, tree, indent, start_col, node, Space.None); |
| 1643 | 1641 | ||
| 1644 | const comma_token = tree.nextToken(node.lastToken()); | 1642 | const comma_token = tree.nextToken(node.lastToken()); |
| 1645 | try renderToken(tree, stream, comma_token, indent, start_col, Space.Newline); // , | 1643 | try renderToken(tree, stream, comma_token, indent, start_col, Space.Newline); // , |
| 1646 | try renderExtraNewline(tree, stream, start_col, next_node.data); | 1644 | try renderExtraNewline(tree, stream, start_col, items[i + 1]); |
| 1647 | try stream.writeByteNTimes(' ', indent); | 1645 | try stream.writeByteNTimes(' ', indent); |
| 1648 | } else { | 1646 | } else { |
| 1649 | try renderExpression(allocator, stream, tree, indent, start_col, node, Space.Comma); | 1647 | try renderExpression(allocator, stream, tree, indent, start_col, node, Space.Comma); |