aboutsummaryrefslogtreecommitdiff
path: root/lib/std
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2019-11-12 01:40:31 +0000
committerGitHub <noreply@github.com>2019-11-12 01:40:31 +0000
commit5502160bd23f14b91ac2bd3726a93bdd0b40cc53 (patch)
tree81ced0f54f4c02eb7fd3bdd5d3d1248014f356a6 /lib/std
parentae0a219d1f5495acc4d82421fa24d84186c2a40d (diff)
parent0c315e7f7613b085a203e9c94d222e846b5b9e46 (diff)
downloadzig-5502160bd23f14b91ac2bd3726a93bdd0b40cc53.tar.gz
zig-5502160bd23f14b91ac2bd3726a93bdd0b40cc53.zip
Merge pull request #3652 from ziglang/anon-container-lit
implement anonymous struct literals and anonymous list literals
Diffstat (limited to 'lib/std')
-rw-r--r--lib/std/builtin.zig33
-rw-r--r--lib/std/zig/ast.zig21
-rw-r--r--lib/std/zig/parse.zig52
-rw-r--r--lib/std/zig/parser_test.zig17
-rw-r--r--lib/std/zig/render.zig57
5 files changed, 110 insertions, 70 deletions
diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig
index 8315cd84cf..8052f0b31a 100644
--- a/lib/std/builtin.zig
+++ b/lib/std/builtin.zig
@@ -90,40 +90,11 @@ pub const Mode = enum {
ReleaseSmall,
};
-/// This data structure is used by the Zig language code generation and
-/// therefore must be kept in sync with the compiler implementation.
-pub const TypeId = enum {
- Type,
- Void,
- Bool,
- NoReturn,
- Int,
- Float,
- Pointer,
- Array,
- Struct,
- ComptimeFloat,
- ComptimeInt,
- Undefined,
- Null,
- Optional,
- ErrorUnion,
- ErrorSet,
- Enum,
- Union,
- Fn,
- BoundFn,
- ArgTuple,
- Opaque,
- Frame,
- AnyFrame,
- Vector,
- EnumLiteral,
-};
+pub const TypeId = @TagType(TypeInfo);
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
-pub const TypeInfo = union(TypeId) {
+pub const TypeInfo = union(enum) {
Type: void,
Void: void,
Bool: void,
diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig
index 9f32c6e54b..e705aea477 100644
--- a/lib/std/zig/ast.zig
+++ b/lib/std/zig/ast.zig
@@ -1648,10 +1648,15 @@ pub const Node = struct {
pub const SuffixOp = struct {
base: Node,
- lhs: *Node,
+ lhs: Lhs,
op: Op,
rtoken: TokenIndex,
+ pub const Lhs = union(enum) {
+ node: *Node,
+ dot: TokenIndex,
+ };
+
pub const Op = union(enum) {
Call: Call,
ArrayAccess: *Node,
@@ -1679,8 +1684,13 @@ pub const Node = struct {
pub fn iterate(self: *SuffixOp, index: usize) ?*Node {
var i = index;
- if (i < 1) return self.lhs;
- i -= 1;
+ switch (self.lhs) {
+ .node => |node| {
+ if (i == 0) return node;
+ i -= 1;
+ },
+ .dot => {},
+ }
switch (self.op) {
.Call => |*call_info| {
@@ -1721,7 +1731,10 @@ pub const Node = struct {
.Call => |*call_info| if (call_info.async_token) |async_token| return async_token,
else => {},
}
- return self.lhs.firstToken();
+ switch (self.lhs) {
+ .node => |node| return node.firstToken(),
+ .dot => |dot| return dot,
+ }
}
pub fn lastToken(self: *const SuffixOp) TokenIndex {
diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig
index 4c6c461c01..6d5d4b5f2d 100644
--- a/lib/std/zig/parse.zig
+++ b/lib/std/zig/parse.zig
@@ -1026,16 +1026,16 @@ fn parseWhileExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
/// CurlySuffixExpr <- TypeExpr InitList?
fn parseCurlySuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
const type_expr = (try parseTypeExpr(arena, it, tree)) orelse return null;
- const init_list = (try parseInitList(arena, it, tree)) orelse return type_expr;
- init_list.cast(Node.SuffixOp).?.lhs = type_expr;
- return init_list;
+ const suffix_op = (try parseInitList(arena, it, tree)) orelse return type_expr;
+ suffix_op.lhs.node = type_expr;
+ return &suffix_op.base;
}
/// InitList
/// <- LBRACE FieldInit (COMMA FieldInit)* COMMA? RBRACE
/// / LBRACE Expr (COMMA Expr)* COMMA? RBRACE
/// / LBRACE RBRACE
-fn parseInitList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
+fn parseInitList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node.SuffixOp {
const lbrace = eatToken(it, .LBrace) orelse return null;
var init_list = Node.SuffixOp.Op.InitList.init(arena);
@@ -1064,11 +1064,11 @@ fn parseInitList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
const node = try arena.create(Node.SuffixOp);
node.* = Node.SuffixOp{
.base = Node{ .id = .SuffixOp },
- .lhs = undefined, // set by caller
+ .lhs = .{.node = undefined}, // set by caller
.op = op,
.rtoken = try expectToken(it, tree, .RBrace),
};
- return &node.base;
+ return node;
}
/// TypeExpr <- PrefixTypeOp* ErrorUnionExpr
@@ -1117,7 +1117,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
while (try parseSuffixOp(arena, it, tree)) |node| {
switch (node.id) {
- .SuffixOp => node.cast(Node.SuffixOp).?.lhs = res,
+ .SuffixOp => node.cast(Node.SuffixOp).?.lhs = .{.node = res},
.InfixOp => node.cast(Node.InfixOp).?.lhs = res,
else => unreachable,
}
@@ -1133,7 +1133,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
const node = try arena.create(Node.SuffixOp);
node.* = Node.SuffixOp{
.base = Node{ .id = .SuffixOp },
- .lhs = res,
+ .lhs = .{.node = res},
.op = Node.SuffixOp.Op{
.Call = Node.SuffixOp.Op.Call{
.params = params.list,
@@ -1150,7 +1150,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
while (true) {
if (try parseSuffixOp(arena, it, tree)) |node| {
switch (node.id) {
- .SuffixOp => node.cast(Node.SuffixOp).?.lhs = res,
+ .SuffixOp => node.cast(Node.SuffixOp).?.lhs = .{.node = res},
.InfixOp => node.cast(Node.InfixOp).?.lhs = res,
else => unreachable,
}
@@ -1161,7 +1161,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
const call = try arena.create(Node.SuffixOp);
call.* = Node.SuffixOp{
.base = Node{ .id = .SuffixOp },
- .lhs = res,
+ .lhs = .{.node = res},
.op = Node.SuffixOp.Op{
.Call = Node.SuffixOp.Op.Call{
.params = params.list,
@@ -1215,7 +1215,7 @@ fn parsePrimaryTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*N
return &node.base;
}
if (try parseContainerDecl(arena, it, tree)) |node| return node;
- if (try parseEnumLiteral(arena, it, tree)) |node| return node;
+ if (try parseAnonLiteral(arena, it, tree)) |node| return node;
if (try parseErrorSetDecl(arena, it, tree)) |node| return node;
if (try parseFloatLiteral(arena, it, tree)) |node| return node;
if (try parseFnProto(arena, it, tree)) |node| return node;
@@ -1494,16 +1494,28 @@ fn parseAsmExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
}
/// DOT IDENTIFIER
-fn parseEnumLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
+fn parseAnonLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
const dot = eatToken(it, .Period) orelse return null;
- const name = try expectToken(it, tree, .Identifier);
- const node = try arena.create(Node.EnumLiteral);
- node.* = Node.EnumLiteral{
- .base = Node{ .id = .EnumLiteral },
- .dot = dot,
- .name = name,
- };
- return &node.base;
+
+ // anon enum literal
+ if (eatToken(it, .Identifier)) |name| {
+ const node = try arena.create(Node.EnumLiteral);
+ node.* = Node.EnumLiteral{
+ .base = Node{ .id = .EnumLiteral },
+ .dot = dot,
+ .name = name,
+ };
+ return &node.base;
+ }
+
+ // anon container literal
+ if (try parseInitList(arena, it, tree)) |node| {
+ node.lhs = .{.dot = dot};
+ return &node.base;
+ }
+
+ putBackToken(it, dot);
+ return null;
}
/// AsmOutput <- COLON AsmOutputList AsmInput?
diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig
index e9b4cd6455..f61442adfc 100644
--- a/lib/std/zig/parser_test.zig
+++ b/lib/std/zig/parser_test.zig
@@ -1,3 +1,20 @@
+test "zig fmt: anon struct literal syntax" {
+ try testCanonical(
+ \\const x = .{
+ \\ .a = b,
+ \\ .c = d,
+ \\};
+ \\
+ );
+}
+
+test "zig fmt: anon list literal syntax" {
+ try testCanonical(
+ \\const x = .{ a, b, c };
+ \\
+ );
+}
+
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 c6912087cf..c824939296 100644
--- a/lib/std/zig/render.zig
+++ b/lib/std/zig/render.zig
@@ -538,9 +538,9 @@ fn renderExpression(
try renderToken(tree, stream, async_token, indent, start_col, Space.Space);
}
- try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
+ try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs.node, Space.None);
- const lparen = tree.nextToken(suffix_op.lhs.lastToken());
+ const lparen = tree.nextToken(suffix_op.lhs.node.lastToken());
if (call_info.params.len == 0) {
try renderToken(tree, stream, lparen, indent, start_col, Space.None);
@@ -598,7 +598,7 @@ fn renderExpression(
const lbracket = tree.prevToken(index_expr.firstToken());
const rbracket = tree.nextToken(index_expr.lastToken());
- try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
+ try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs.node, Space.None);
try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [
const starts_with_comment = tree.tokens.at(lbracket + 1).id == .LineComment;
@@ -616,18 +616,18 @@ fn renderExpression(
},
ast.Node.SuffixOp.Op.Deref => {
- try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
+ try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs.node, Space.None);
return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // .*
},
ast.Node.SuffixOp.Op.UnwrapOptional => {
- try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
+ try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs.node, Space.None);
try renderToken(tree, stream, tree.prevToken(suffix_op.rtoken), indent, start_col, Space.None); // .
return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // ?
},
@TagType(ast.Node.SuffixOp.Op).Slice => |range| {
- try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
+ try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs.node, Space.None);
const lbracket = tree.prevToken(range.start.firstToken());
const dotdot = tree.nextToken(range.start.lastToken());
@@ -647,10 +647,16 @@ fn renderExpression(
},
ast.Node.SuffixOp.Op.StructInitializer => |*field_inits| {
- const lbrace = tree.nextToken(suffix_op.lhs.lastToken());
+ const lbrace = switch (suffix_op.lhs) {
+ .dot => |dot| tree.nextToken(dot),
+ .node => |node| tree.nextToken(node.lastToken()),
+ };
if (field_inits.len == 0) {
- try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
+ switch (suffix_op.lhs) {
+ .dot => |dot| try renderToken(tree, stream, dot, indent, start_col, Space.None),
+ .node => |node| try renderExpression(allocator, stream, tree, indent, start_col, node, Space.None),
+ }
try renderToken(tree, stream, lbrace, indent + indent_delta, start_col, Space.None);
return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
}
@@ -691,7 +697,10 @@ fn renderExpression(
break :blk;
}
- try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
+ switch (suffix_op.lhs) {
+ .dot => |dot| try renderToken(tree, stream, dot, indent, start_col, Space.None),
+ .node => |node| try renderExpression(allocator, stream, tree, indent, start_col, node, Space.None),
+ }
try renderToken(tree, stream, lbrace, indent, start_col, Space.Space);
try renderExpression(allocator, stream, tree, indent, start_col, &field_init.base, Space.Space);
return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
@@ -699,7 +708,10 @@ fn renderExpression(
if (!src_has_trailing_comma and src_same_line and expr_outputs_one_line) {
// render all on one line, no trailing comma
- try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
+ switch (suffix_op.lhs) {
+ .dot => |dot| try renderToken(tree, stream, dot, indent, start_col, Space.None),
+ .node => |node| try renderExpression(allocator, stream, tree, indent, start_col, node, Space.None),
+ }
try renderToken(tree, stream, lbrace, indent, start_col, Space.Space);
var it = field_inits.iterator(0);
@@ -719,7 +731,10 @@ fn renderExpression(
const new_indent = indent + indent_delta;
- try renderExpression(allocator, stream, tree, new_indent, start_col, suffix_op.lhs, Space.None);
+ switch (suffix_op.lhs) {
+ .dot => |dot| try renderToken(tree, stream, dot, new_indent, start_col, Space.None),
+ .node => |node| try renderExpression(allocator, stream, tree, new_indent, start_col, node, Space.None),
+ }
try renderToken(tree, stream, lbrace, new_indent, start_col, Space.Newline);
var it = field_inits.iterator(0);
@@ -743,23 +758,35 @@ fn renderExpression(
},
ast.Node.SuffixOp.Op.ArrayInitializer => |*exprs| {
- const lbrace = tree.nextToken(suffix_op.lhs.lastToken());
+ const lbrace = switch (suffix_op.lhs) {
+ .dot => |dot| tree.nextToken(dot),
+ .node => |node| tree.nextToken(node.lastToken()),
+ };
if (exprs.len == 0) {
- try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
+ switch (suffix_op.lhs) {
+ .dot => |dot| try renderToken(tree, stream, dot, indent, start_col, Space.None),
+ .node => |node| try renderExpression(allocator, stream, tree, indent, start_col, node, Space.None),
+ }
try renderToken(tree, stream, lbrace, indent, start_col, Space.None);
return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
}
if (exprs.len == 1 and tree.tokens.at(exprs.at(0).*.lastToken() + 1).id == .RBrace) {
const expr = exprs.at(0).*;
- try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
+ switch (suffix_op.lhs) {
+ .dot => |dot| try renderToken(tree, stream, dot, indent, start_col, Space.None),
+ .node => |node| try renderExpression(allocator, stream, tree, indent, start_col, node, Space.None),
+ }
try renderToken(tree, stream, lbrace, indent, start_col, Space.None);
try renderExpression(allocator, stream, tree, indent, start_col, expr, Space.None);
return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
}
- try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
+ switch (suffix_op.lhs) {
+ .dot => |dot| try renderToken(tree, stream, dot, indent, start_col, Space.None),
+ .node => |node| try renderExpression(allocator, stream, tree, indent, start_col, node, Space.None),
+ }
// scan to find row size
const maybe_row_size: ?usize = blk: {