zig fmt: split Slice and SliceSentinel

This saves 4 whole bytes in the common case where there is no sentinel.
This commit is contained in:
Isaac Freund 2021-02-07 22:26:43 +01:00 committed by Andrew Kelley
parent 1d71b19c0d
commit 0e38362d24
3 changed files with 64 additions and 24 deletions

View File

@ -304,6 +304,7 @@ pub const Tree = struct {
.BoolOr,
.SliceOpen,
.Slice,
.SliceSentinel,
.Deref,
.ArrayAccess,
.ArrayInitOne,
@ -694,19 +695,22 @@ pub const Tree = struct {
return main_tokens[n] + end_offset;
}
},
.SliceOpen => {
end_offset += 2; // ellipsis2 and rbracket
n = datas[n].rhs;
},
.Slice => {
const extra = tree.extraData(datas[n].rhs, Node.Slice);
if (extra.sentinel != 0) {
n = extra.sentinel;
} else {
assert(extra.end != 0); // should have used SliceOpen if end and sentinel are 0
n = extra.end;
}
assert(extra.end != 0); // should have used SliceOpen
end_offset += 1; // rbracket
n = extra.end;
},
.SliceSentinel => {
const extra = tree.extraData(datas[n].rhs, Node.SliceSentinel);
assert(extra.sentinel != 0); // should have used Slice
end_offset += 1; // rbracket
n = extra.sentinel;
},
// These are not supported by lastToken() because implementation would
@ -1129,6 +1133,21 @@ pub const Tree = struct {
assert(tree.nodes.items(.tag)[node] == .Slice);
const data = tree.nodes.items(.data)[node];
const extra = tree.extraData(data.rhs, Node.Slice);
return .{
.ast = .{
.sliced = data.lhs,
.lbracket = tree.nodes.items(.main_token)[node],
.start = extra.start,
.end = extra.end,
.sentinel = 0,
},
};
}
pub fn sliceSentinel(tree: Tree, node: Node.Index) Full.Slice {
assert(tree.nodes.items(.tag)[node] == .SliceSentinel);
const data = tree.nodes.items(.data)[node];
const extra = tree.extraData(data.rhs, Node.SliceSentinel);
return .{
.ast = .{
.sliced = data.lhs,
@ -1922,9 +1941,12 @@ pub const Node = struct {
/// `lhs[rhs..]`
/// main_token is the lbracket.
SliceOpen,
/// `lhs[b..c :d]`. rhs is index into Slice
/// `lhs[b..c]`. rhs is index into Slice
/// main_token is the lbracket.
Slice,
/// `lhs[b..c :d]`. rhs is index into SliceSentinel
/// main_token is the lbracket.
SliceSentinel,
/// `lhs.*`. rhs is unused.
Deref,
/// `lhs[rhs]`.
@ -2202,6 +2224,11 @@ pub const Node = struct {
pub const Slice = struct {
start: Index,
end: Index,
};
pub const SliceSentinel = struct {
start: Index,
end: Index,
sentinel: Index,
};

View File

@ -3326,23 +3326,35 @@ const Parser = struct {
},
});
}
const sentinel: Node.Index = if (p.eatToken(.Colon)) |_|
try p.parseExpr()
else
0;
_ = try p.expectToken(.RBracket);
return p.addNode(.{
.tag = .Slice,
.main_token = lbracket,
.data = .{
.lhs = lhs,
.rhs = try p.addExtra(.{
.start = index_expr,
.end = end_expr,
.sentinel = sentinel,
}),
},
});
if (p.eatToken(.Colon)) |_| {
const sentinel = try p.parseExpr();
_ = try p.expectToken(.RBracket);
return p.addNode(.{
.tag = .SliceSentinel,
.main_token = lbracket,
.data = .{
.lhs = lhs,
.rhs = try p.addExtra(Node.SliceSentinel{
.start = index_expr,
.end = end_expr,
.sentinel = sentinel,
}),
},
});
} else {
_ = try p.expectToken(.RBracket);
return p.addNode(.{
.tag = .Slice,
.main_token = lbracket,
.data = .{
.lhs = lhs,
.rhs = try p.addExtra(Node.Slice{
.start = index_expr,
.end = end_expr,
}),
},
});
}
}
_ = try p.expectToken(.RBracket);
return p.addNode(.{

View File

@ -470,6 +470,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
.SliceOpen => try renderSlice(ais, tree, tree.sliceOpen(node), space),
.Slice => try renderSlice(ais, tree, tree.slice(node), space),
.SliceSentinel => try renderSlice(ais, tree, tree.sliceSentinel(node), space),
.Deref => {
try renderExpression(ais, tree, datas[node].lhs, .None);