authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-21 13:44:00-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-21 14:03:36-05:00
log290dc5d95b986464a5be91bb3fd0ada2dd0840ae
tree1e004f521047ead2fb52855da7bc4fa819020548
parentce444771c5a4da1d6caab0959e5c8dd5f2df820e
signaturelock-open Commit is signed but in an unrecognized format.

zig fmt support for slice sentinel syntax


5 files changed, 40 insertions(+), 2 deletions(-)

lib/std/zig/ast.zig+5
......@@ -1701,6 +1701,7 @@ pub const Node = struct {
17011701 pub const Slice = struct {
17021702 start: *Node,
17031703 end: ?*Node,
1704 sentinel: ?*Node,
17041705 };
17051706 };
17061707
......@@ -1732,6 +1733,10 @@ pub const Node = struct {
17321733 if (i < 1) return end;
17331734 i -= 1;
17341735 }
1736 if (range.sentinel) |sentinel| {
1737 if (i < 1) return sentinel;
1738 i -= 1;
1739 }
17351740 },
17361741 .ArrayInitializer => |*exprs| {
17371742 if (i < exprs.len) return exprs.at(i).*;
lib/std/zig/parse.zig+6-1
......@@ -2331,7 +2331,7 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
23312331}
23322332
23332333/// SuffixOp
2334/// <- LBRACKET Expr (DOT2 Expr?)? RBRACKET
2334/// <- LBRACKET Expr (DOT2 (Expr (COLON Expr)?)?)? RBRACKET
23352335/// / DOT IDENTIFIER
23362336/// / DOTASTERISK
23372337/// / DOTQUESTIONMARK
......@@ -2349,11 +2349,16 @@ fn parseSuffixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
23492349
23502350 if (eatToken(it, .Ellipsis2) != null) {
23512351 const end_expr = try parseExpr(arena, it, tree);
2352 const sentinel: ?*ast.Node = if (eatToken(it, .Colon) != null)
2353 try parseExpr(arena, it, tree)
2354 else
2355 null;
23522356 break :blk OpAndToken{
23532357 .op = Op{
23542358 .Slice = Op.Slice{
23552359 .start = index_expr,
23562360 .end = end_expr,
2361 .sentinel = sentinel,
23572362 },
23582363 },
23592364 .token = try expectToken(it, tree, .RBracket),
lib/std/zig/parser_test.zig+3
......@@ -419,10 +419,13 @@ test "zig fmt: pointer of unknown length" {
419419test "zig fmt: spaces around slice operator" {
420420 try testCanonical(
421421 \\var a = b[c..d];
422 \\var a = b[c..d :0];
422423 \\var a = b[c + 1 .. d];
423424 \\var a = b[c + 1 ..];
424425 \\var a = b[c .. d + 1];
426 \\var a = b[c .. d + 1 :0];
425427 \\var a = b[c.a..d.e];
428 \\var a = b[c.a..d.e :0];
426429 \\
427430 );
428431}
lib/std/zig/render.zig+7-1
......@@ -689,7 +689,13 @@ fn renderExpression(
689689 try renderExpression(allocator, stream, tree, indent, start_col, range.start, after_start_space);
690690 try renderToken(tree, stream, dotdot, indent, start_col, after_op_space); // ..
691691 if (range.end) |end| {
692 try renderExpression(allocator, stream, tree, indent, start_col, end, Space.None);
692 const after_end_space = if (range.sentinel != null) Space.Space else Space.None;
693 try renderExpression(allocator, stream, tree, indent, start_col, end, after_end_space);
694 }
695 if (range.sentinel) |sentinel| {
696 const colon = tree.prevToken(sentinel.firstToken());
697 try renderToken(tree, stream, colon, indent, start_col, Space.None); // :
698 try renderExpression(allocator, stream, tree, indent, start_col, sentinel, Space.None);
693699 }
694700 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // ]
695701 },
test/stage1/behavior/slice.zig+19
......@@ -78,3 +78,22 @@ test "access len index of sentinel-terminated slice" {
7878 S.doTheTest();
7979 comptime S.doTheTest();
8080}
81
82test "obtaining a null terminated slice" {
83 // here we have a normal array
84 var buf: [50]u8 = undefined;
85
86 buf[0] = 'a';
87 buf[1] = 'b';
88 buf[2] = 'c';
89 buf[3] = 0;
90
91 // now we obtain a null terminated slice:
92 const ptr = buf[0..3 :0];
93
94 var runtime_len: usize = 3;
95 const ptr2 = buf[0..runtime_len :0];
96 // ptr2 is a null-terminated slice
97 comptime expect(@TypeOf(ptr2) == [:0]u8);
98 comptime expect(@TypeOf(ptr2[0..2]) == []u8);
99}