| author | |
| committer | |
| log | 290dc5d95b986464a5be91bb3fd0ada2dd0840ae |
| tree | 1e004f521047ead2fb52855da7bc4fa819020548 |
| parent | ce444771c5a4da1d6caab0959e5c8dd5f2df820e |
| signature |
5 files changed, 40 insertions(+), 2 deletions(-)
lib/std/zig/ast.zig+5| ... | @@ -1701,6 +1701,7 @@ pub const Node = struct { | ... | @@ -1701,6 +1701,7 @@ pub const Node = struct { |
| 1701 | pub const Slice = struct { | 1701 | pub const Slice = struct { |
| 1702 | start: *Node, | 1702 | start: *Node, |
| 1703 | end: ?*Node, | 1703 | end: ?*Node, |
| 1704 | sentinel: ?*Node, | ||
| 1704 | }; | 1705 | }; |
| 1705 | }; | 1706 | }; |
| 1706 | 1707 | ||
| ... | @@ -1732,6 +1733,10 @@ pub const Node = struct { | ... | @@ -1732,6 +1733,10 @@ pub const Node = struct { |
| 1732 | if (i < 1) return end; | 1733 | if (i < 1) return end; |
| 1733 | i -= 1; | 1734 | i -= 1; |
| 1734 | } | 1735 | } |
| 1736 | if (range.sentinel) |sentinel| { | ||
| 1737 | if (i < 1) return sentinel; | ||
| 1738 | i -= 1; | ||
| 1739 | } | ||
| 1735 | }, | 1740 | }, |
| 1736 | .ArrayInitializer => |*exprs| { | 1741 | .ArrayInitializer => |*exprs| { |
| 1737 | if (i < exprs.len) return exprs.at(i).*; | 1742 | 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 | ... | @@ -2331,7 +2331,7 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node |
| 2331 | } | 2331 | } |
| 2332 | 2332 | ||
| 2333 | /// SuffixOp | 2333 | /// SuffixOp |
| 2334 | /// <- LBRACKET Expr (DOT2 Expr?)? RBRACKET | 2334 | /// <- LBRACKET Expr (DOT2 (Expr (COLON Expr)?)?)? RBRACKET |
| 2335 | /// / DOT IDENTIFIER | 2335 | /// / DOT IDENTIFIER |
| 2336 | /// / DOTASTERISK | 2336 | /// / DOTASTERISK |
| 2337 | /// / DOTQUESTIONMARK | 2337 | /// / DOTQUESTIONMARK |
| ... | @@ -2349,11 +2349,16 @@ fn parseSuffixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { | ... | @@ -2349,11 +2349,16 @@ fn parseSuffixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { |
| 2349 | 2349 | ||
| 2350 | if (eatToken(it, .Ellipsis2) != null) { | 2350 | if (eatToken(it, .Ellipsis2) != null) { |
| 2351 | const end_expr = try parseExpr(arena, it, tree); | 2351 | 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; | ||
| 2352 | break :blk OpAndToken{ | 2356 | break :blk OpAndToken{ |
| 2353 | .op = Op{ | 2357 | .op = Op{ |
| 2354 | .Slice = Op.Slice{ | 2358 | .Slice = Op.Slice{ |
| 2355 | .start = index_expr, | 2359 | .start = index_expr, |
| 2356 | .end = end_expr, | 2360 | .end = end_expr, |
| 2361 | .sentinel = sentinel, | ||
| 2357 | }, | 2362 | }, |
| 2358 | }, | 2363 | }, |
| 2359 | .token = try expectToken(it, tree, .RBracket), | 2364 | .token = try expectToken(it, tree, .RBracket), |
lib/std/zig/parser_test.zig+3| ... | @@ -419,10 +419,13 @@ test "zig fmt: pointer of unknown length" { | ... | @@ -419,10 +419,13 @@ test "zig fmt: pointer of unknown length" { |
| 419 | test "zig fmt: spaces around slice operator" { | 419 | test "zig fmt: spaces around slice operator" { |
| 420 | try testCanonical( | 420 | try testCanonical( |
| 421 | \\var a = b[c..d]; | 421 | \\var a = b[c..d]; |
| 422 | \\var a = b[c..d :0]; | ||
| 422 | \\var a = b[c + 1 .. d]; | 423 | \\var a = b[c + 1 .. d]; |
| 423 | \\var a = b[c + 1 ..]; | 424 | \\var a = b[c + 1 ..]; |
| 424 | \\var a = b[c .. d + 1]; | 425 | \\var a = b[c .. d + 1]; |
| 426 | \\var a = b[c .. d + 1 :0]; | ||
| 425 | \\var a = b[c.a..d.e]; | 427 | \\var a = b[c.a..d.e]; |
| 428 | \\var a = b[c.a..d.e :0]; | ||
| 426 | \\ | 429 | \\ |
| 427 | ); | 430 | ); |
| 428 | } | 431 | } |
lib/std/zig/render.zig+7-1| ... | @@ -689,7 +689,13 @@ fn renderExpression( | ... | @@ -689,7 +689,13 @@ fn renderExpression( |
| 689 | try renderExpression(allocator, stream, tree, indent, start_col, range.start, after_start_space); | 689 | try renderExpression(allocator, stream, tree, indent, start_col, range.start, after_start_space); |
| 690 | try renderToken(tree, stream, dotdot, indent, start_col, after_op_space); // .. | 690 | try renderToken(tree, stream, dotdot, indent, start_col, after_op_space); // .. |
| 691 | if (range.end) |end| { | 691 | 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); | ||
| 693 | } | 699 | } |
| 694 | return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // ] | 700 | return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // ] |
| 695 | }, | 701 | }, |
test/stage1/behavior/slice.zig+19| ... | @@ -78,3 +78,22 @@ test "access len index of sentinel-terminated slice" { | ... | @@ -78,3 +78,22 @@ test "access len index of sentinel-terminated slice" { |
| 78 | S.doTheTest(); | 78 | S.doTheTest(); |
| 79 | comptime S.doTheTest(); | 79 | comptime S.doTheTest(); |
| 80 | } | 80 | } |
| 81 | |||
| 82 | test "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 | } |