zig fmt: implement slices

This commit is contained in:
Isaac Freund 2021-02-07 12:43:53 +01:00 committed by Andrew Kelley
parent 33915cb1ed
commit 0929fcbc34
3 changed files with 114 additions and 36 deletions

View File

@ -688,6 +688,20 @@ 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;
}
end_offset += 1; // rbracket
},
// These are not supported by lastToken() because implementation would
// require recursion due to the optional comma followed by rbrace.
@ -708,8 +722,6 @@ pub const Tree = struct {
.ErrorSetDecl => unreachable, // TODO
.AsmSimple => unreachable, // TODO
.Asm => unreachable, // TODO
.SliceOpen => unreachable, // TODO
.Slice => unreachable, // TODO
.SwitchCaseOne => unreachable, // TODO
.SwitchRange => unreachable, // TODO
.ArrayType => unreachable, // TODO
@ -1094,6 +1106,35 @@ pub const Tree = struct {
});
}
pub fn sliceOpen(tree: Tree, node: Node.Index) Full.Slice {
assert(tree.nodes.items(.tag)[node] == .SliceOpen);
const data = tree.nodes.items(.data)[node];
return .{
.ast = .{
.sliced = data.lhs,
.lbracket = tree.nodes.items(.main_token)[node],
.start = data.rhs,
.end = 0,
.sentinel = 0,
},
};
}
pub fn slice(tree: Tree, node: Node.Index) Full.Slice {
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 = extra.sentinel,
},
};
}
pub fn containerDeclTwo(tree: Tree, buffer: *[2]Node.Index, node: Node.Index) Full.ContainerDecl {
assert(tree.nodes.items(.tag)[node] == .ContainerDeclTwo or
tree.nodes.items(.tag)[node] == .ContainerDeclTwoComma);
@ -1452,6 +1493,18 @@ pub const Full = struct {
};
};
pub const Slice = struct {
ast: Ast,
pub const Ast = struct {
sliced: Node.Index,
lbracket: TokenIndex,
start: Node.Index,
end: Node.Index,
sentinel: Node.Index,
};
};
pub const ContainerDecl = struct {
layout_token: ?TokenIndex,
ast: Ast,
@ -1860,10 +1913,10 @@ pub const Node = struct {
/// main_token is the asterisk if a pointer or the lbrace if a slice
PtrTypeBitRange,
/// `lhs[rhs..]`
/// main_token is the `[`.
/// main_token is the lbracket.
SliceOpen,
/// `lhs[b..c :d]`. `slice_list[rhs]`.
/// main_token is the `[`.
/// `lhs[b..c :d]`. rhs is index into Slice
/// main_token is the lbracket.
Slice,
/// `lhs.*`. rhs is unused.
Deref,

View File

@ -637,6 +637,24 @@ test "zig fmt: sentinel array literal 1 element" {
);
}
test "zig fmt: slices" {
try testCanonical(
\\const a = b[0..];
\\const c = d[0..1];
\\const e = f[0..1 :0];
\\
);
}
test "zig fmt: slices with spaces in bounds" {
try testCanonical(
\\const a = b[0 + 0 ..];
\\const c = d[0 + 0 .. 1];
\\const e = f[0 .. 1 + 1 :0];
\\
);
}
//test "zig fmt: async function" {
// try testCanonical(
// \\pub const Server = struct {

View File

@ -466,34 +466,8 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
return renderToken(ais, tree, rbracket, space); // ]
},
.Slice => unreachable, // TODO
.SliceOpen => unreachable, // TODO
//.Slice => {
// const suffix_op = base.castTag(.Slice).?;
// try renderExpression(ais, tree, suffix_op.lhs, Space.None);
// const lbracket = tree.prevToken(suffix_op.start.firstToken());
// const dotdot = tree.nextToken(suffix_op.start.lastToken());
// const after_start_space_bool = nodeCausesSliceOpSpace(suffix_op.start) or
// (if (suffix_op.end) |end| nodeCausesSliceOpSpace(end) else false);
// const after_start_space = if (after_start_space_bool) Space.Space else Space.None;
// const after_op_space = if (suffix_op.end != null) after_start_space else Space.None;
// try renderToken(ais, tree, lbracket, Space.None); // [
// try renderExpression(ais, tree, suffix_op.start, after_start_space);
// try renderToken(ais, tree, dotdot, after_op_space); // ..
// if (suffix_op.end) |end| {
// const after_end_space = if (suffix_op.sentinel != null) Space.Space else Space.None;
// try renderExpression(ais, tree, end, after_end_space);
// }
// if (suffix_op.sentinel) |sentinel| {
// const colon = tree.prevToken(sentinel.firstToken());
// try renderToken(ais, tree, colon, Space.None); // :
// try renderExpression(ais, tree, sentinel, Space.None);
// }
// return renderToken(ais, tree, suffix_op.rtoken, space); // ]
//},
.SliceOpen => try renderSlice(ais, tree, tree.sliceOpen(node), space),
.Slice => try renderSlice(ais, tree, tree.slice(node), space),
.Deref => {
try renderExpression(ais, tree, datas[node].lhs, .None);
@ -1142,6 +1116,40 @@ fn renderPtrType(
try renderExpression(ais, tree, ptr_type.ast.child_type, space);
}
fn renderSlice(
ais: *Ais,
tree: ast.Tree,
slice: ast.Full.Slice,
space: Space,
) Error!void {
const node_tags = tree.nodes.items(.tag);
const after_start_space_bool = nodeCausesSliceOpSpace(node_tags[slice.ast.start]) or
if (slice.ast.end != 0) nodeCausesSliceOpSpace(node_tags[slice.ast.end]) else false;
const after_start_space = if (after_start_space_bool) Space.Space else Space.None;
const after_dots_space = if (slice.ast.end != 0) after_start_space else Space.None;
try renderExpression(ais, tree, slice.ast.sliced, .None);
try renderToken(ais, tree, slice.ast.lbracket, .None); // lbracket
const start_last = tree.lastToken(slice.ast.start);
try renderExpression(ais, tree, slice.ast.start, after_start_space);
try renderToken(ais, tree, start_last + 1, after_dots_space); // ellipsis2 ("..")
if (slice.ast.end == 0) {
return renderToken(ais, tree, start_last + 2, space); // rbracket
}
const end_last = tree.lastToken(slice.ast.end);
const after_end_space = if (slice.ast.sentinel != 0) Space.Space else Space.None;
try renderExpression(ais, tree, slice.ast.end, after_end_space);
if (slice.ast.sentinel == 0) {
return renderToken(ais, tree, end_last + 1, space); // rbracket
}
try renderToken(ais, tree, end_last + 1, .None); // colon
try renderExpression(ais, tree, slice.ast.sentinel, .None);
try renderToken(ais, tree, tree.lastToken(slice.ast.sentinel) + 1, space); // rbracket
}
fn renderAsmOutput(
allocator: *mem.Allocator,
ais: *Ais,
@ -2099,8 +2107,8 @@ fn nodeIsBlock(tag: ast.Node.Tag) bool {
};
}
fn nodeCausesSliceOpSpace(base: ast.Node.Index) bool {
return switch (base.tag) {
fn nodeCausesSliceOpSpace(tag: ast.Node.Tag) bool {
return switch (tag) {
.Catch,
.Add,
.AddWrap,
@ -2139,7 +2147,6 @@ fn nodeCausesSliceOpSpace(base: ast.Node.Index) bool {
.Mod,
.Mul,
.MulWrap,
.Range,
.Sub,
.SubWrap,
.OrElse,