From 0929fcbc34a2aa8cd69492c9437622d29a9a46b9 Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Sun, 7 Feb 2021 12:43:53 +0100 Subject: [PATCH] zig fmt: implement slices --- lib/std/zig/ast.zig | 63 ++++++++++++++++++++++++++++++--- lib/std/zig/parser_test.zig | 18 ++++++++++ lib/std/zig/render.zig | 69 ++++++++++++++++++++----------------- 3 files changed, 114 insertions(+), 36 deletions(-) diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig index 0fdcf0a4d6..a4d698ecaa 100644 --- a/lib/std/zig/ast.zig +++ b/lib/std/zig/ast.zig @@ -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, diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index 95299b8d94..f09c3f8ade 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -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 { diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig index ba2158ff4e..26bf4d0b72 100644 --- a/lib/std/zig/render.zig +++ b/lib/std/zig/render.zig @@ -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,