mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
AstGen: implement tuple declarations
This commit is contained in:
parent
6fb689e97a
commit
80575face7
4 changed files with 96 additions and 19 deletions
|
|
@ -4386,6 +4386,7 @@ fn structDeclInner(
|
||||||
.backing_int_body_len = 0,
|
.backing_int_body_len = 0,
|
||||||
.known_non_opv = false,
|
.known_non_opv = false,
|
||||||
.known_comptime_only = false,
|
.known_comptime_only = false,
|
||||||
|
.is_tuple = false,
|
||||||
});
|
});
|
||||||
return indexToRef(decl_inst);
|
return indexToRef(decl_inst);
|
||||||
}
|
}
|
||||||
|
|
@ -4467,22 +4468,59 @@ fn structDeclInner(
|
||||||
// No defer needed here because it is handled by `wip_members.deinit()` above.
|
// No defer needed here because it is handled by `wip_members.deinit()` above.
|
||||||
const bodies_start = astgen.scratch.items.len;
|
const bodies_start = astgen.scratch.items.len;
|
||||||
|
|
||||||
|
var is_tuple = false;
|
||||||
|
const node_tags = tree.nodes.items(.tag);
|
||||||
|
for (container_decl.ast.members) |member_node| {
|
||||||
|
switch (node_tags[member_node]) {
|
||||||
|
.container_field_init => is_tuple = tree.containerFieldInit(member_node).ast.tuple_like,
|
||||||
|
.container_field_align => is_tuple = tree.containerFieldAlign(member_node).ast.tuple_like,
|
||||||
|
.container_field => is_tuple = tree.containerField(member_node).ast.tuple_like,
|
||||||
|
else => continue,
|
||||||
|
}
|
||||||
|
if (is_tuple) break;
|
||||||
|
}
|
||||||
|
if (is_tuple) for (container_decl.ast.members) |member_node| {
|
||||||
|
switch (node_tags[member_node]) {
|
||||||
|
.container_field_init,
|
||||||
|
.container_field_align,
|
||||||
|
.container_field,
|
||||||
|
.@"comptime",
|
||||||
|
=> continue,
|
||||||
|
else => {
|
||||||
|
return astgen.failNode(member_node, "tuple declarations cannot contain declarations", .{});
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
var known_non_opv = false;
|
var known_non_opv = false;
|
||||||
var known_comptime_only = false;
|
var known_comptime_only = false;
|
||||||
for (container_decl.ast.members) |member_node| {
|
for (container_decl.ast.members) |member_node| {
|
||||||
const member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) {
|
var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) {
|
||||||
.decl => continue,
|
.decl => continue,
|
||||||
.field => |field| field,
|
.field => |field| field,
|
||||||
};
|
};
|
||||||
|
if (member.ast.tuple_like and !is_tuple and member.ast.type_expr != 0 and
|
||||||
|
astgen.tree.nodes.items(.tag)[member.ast.type_expr] == .identifier)
|
||||||
|
{
|
||||||
|
const ident = astgen.tree.nodes.items(.main_token)[member.ast.type_expr];
|
||||||
|
member.ast.tuple_like = false;
|
||||||
|
member.ast.main_token = ident;
|
||||||
|
member.ast.type_expr = 0;
|
||||||
|
} else if (is_tuple and !member.ast.tuple_like) {
|
||||||
|
return astgen.failTok(member.ast.main_token, "tuple field has a name", .{});
|
||||||
|
}
|
||||||
|
|
||||||
const field_name = try astgen.identAsString(member.ast.name_token);
|
if (!is_tuple) {
|
||||||
|
if (member.ast.tuple_like) return astgen.failTok(member.ast.main_token, "struct field missing name", .{});
|
||||||
|
const field_name = try astgen.identAsString(member.ast.main_token);
|
||||||
wip_members.appendToField(field_name);
|
wip_members.appendToField(field_name);
|
||||||
|
}
|
||||||
|
|
||||||
const doc_comment_index = try astgen.docCommentAsString(member.firstToken());
|
const doc_comment_index = try astgen.docCommentAsString(member.firstToken());
|
||||||
wip_members.appendToField(doc_comment_index);
|
wip_members.appendToField(doc_comment_index);
|
||||||
|
|
||||||
if (member.ast.type_expr == 0) {
|
if (member.ast.type_expr == 0) {
|
||||||
return astgen.failTok(member.ast.name_token, "struct field missing type", .{});
|
return astgen.failTok(member.ast.main_token, "struct field missing type", .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
const field_type = try typeExpr(&block_scope, &namespace.base, member.ast.type_expr);
|
const field_type = try typeExpr(&block_scope, &namespace.base, member.ast.type_expr);
|
||||||
|
|
@ -4562,6 +4600,7 @@ fn structDeclInner(
|
||||||
.backing_int_body_len = @intCast(u32, backing_int_body_len),
|
.backing_int_body_len = @intCast(u32, backing_int_body_len),
|
||||||
.known_non_opv = known_non_opv,
|
.known_non_opv = known_non_opv,
|
||||||
.known_comptime_only = known_comptime_only,
|
.known_comptime_only = known_comptime_only,
|
||||||
|
.is_tuple = is_tuple,
|
||||||
});
|
});
|
||||||
|
|
||||||
wip_members.finishBits(bits_per_field);
|
wip_members.finishBits(bits_per_field);
|
||||||
|
|
@ -4640,15 +4679,25 @@ fn unionDeclInner(
|
||||||
defer wip_members.deinit();
|
defer wip_members.deinit();
|
||||||
|
|
||||||
for (members) |member_node| {
|
for (members) |member_node| {
|
||||||
const member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) {
|
var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) {
|
||||||
.decl => continue,
|
.decl => continue,
|
||||||
.field => |field| field,
|
.field => |field| field,
|
||||||
};
|
};
|
||||||
|
if (member.ast.tuple_like and member.ast.type_expr != 0 and
|
||||||
|
astgen.tree.nodes.items(.tag)[member.ast.type_expr] == .identifier)
|
||||||
|
{
|
||||||
|
const ident = astgen.tree.nodes.items(.main_token)[member.ast.type_expr];
|
||||||
|
member.ast.tuple_like = false;
|
||||||
|
member.ast.main_token = ident;
|
||||||
|
member.ast.type_expr = 0;
|
||||||
|
} else if (member.ast.tuple_like) {
|
||||||
|
return astgen.failTok(member.ast.main_token, "union field missing name", .{});
|
||||||
|
}
|
||||||
if (member.comptime_token) |comptime_token| {
|
if (member.comptime_token) |comptime_token| {
|
||||||
return astgen.failTok(comptime_token, "union fields cannot be marked comptime", .{});
|
return astgen.failTok(comptime_token, "union fields cannot be marked comptime", .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
const field_name = try astgen.identAsString(member.ast.name_token);
|
const field_name = try astgen.identAsString(member.ast.main_token);
|
||||||
wip_members.appendToField(field_name);
|
wip_members.appendToField(field_name);
|
||||||
|
|
||||||
const doc_comment_index = try astgen.docCommentAsString(member.firstToken());
|
const doc_comment_index = try astgen.docCommentAsString(member.firstToken());
|
||||||
|
|
@ -4787,7 +4836,7 @@ fn containerDecl(
|
||||||
var nonexhaustive_node: Ast.Node.Index = 0;
|
var nonexhaustive_node: Ast.Node.Index = 0;
|
||||||
var nonfinal_nonexhaustive = false;
|
var nonfinal_nonexhaustive = false;
|
||||||
for (container_decl.ast.members) |member_node| {
|
for (container_decl.ast.members) |member_node| {
|
||||||
const member = switch (node_tags[member_node]) {
|
var member = switch (node_tags[member_node]) {
|
||||||
.container_field_init => tree.containerFieldInit(member_node),
|
.container_field_init => tree.containerFieldInit(member_node),
|
||||||
.container_field_align => tree.containerFieldAlign(member_node),
|
.container_field_align => tree.containerFieldAlign(member_node),
|
||||||
.container_field => tree.containerField(member_node),
|
.container_field => tree.containerField(member_node),
|
||||||
|
|
@ -4796,6 +4845,16 @@ fn containerDecl(
|
||||||
continue;
|
continue;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
if (member.ast.tuple_like and member.ast.type_expr != 0 and
|
||||||
|
astgen.tree.nodes.items(.tag)[member.ast.type_expr] == .identifier)
|
||||||
|
{
|
||||||
|
const ident = astgen.tree.nodes.items(.main_token)[member.ast.type_expr];
|
||||||
|
member.ast.tuple_like = false;
|
||||||
|
member.ast.main_token = ident;
|
||||||
|
member.ast.type_expr = 0;
|
||||||
|
} else if (member.ast.tuple_like) {
|
||||||
|
return astgen.failTok(member.ast.main_token, "enum field missing name", .{});
|
||||||
|
}
|
||||||
if (member.comptime_token) |comptime_token| {
|
if (member.comptime_token) |comptime_token| {
|
||||||
return astgen.failTok(comptime_token, "enum fields cannot be marked comptime", .{});
|
return astgen.failTok(comptime_token, "enum fields cannot be marked comptime", .{});
|
||||||
}
|
}
|
||||||
|
|
@ -4816,7 +4875,7 @@ fn containerDecl(
|
||||||
// Alignment expressions in enums are caught by the parser.
|
// Alignment expressions in enums are caught by the parser.
|
||||||
assert(member.ast.align_expr == 0);
|
assert(member.ast.align_expr == 0);
|
||||||
|
|
||||||
const name_token = member.ast.name_token;
|
const name_token = member.ast.main_token;
|
||||||
if (mem.eql(u8, tree.tokenSlice(name_token), "_")) {
|
if (mem.eql(u8, tree.tokenSlice(name_token), "_")) {
|
||||||
if (nonexhaustive_node != 0) {
|
if (nonexhaustive_node != 0) {
|
||||||
return astgen.failNodeNotes(
|
return astgen.failNodeNotes(
|
||||||
|
|
@ -4915,15 +4974,23 @@ fn containerDecl(
|
||||||
for (container_decl.ast.members) |member_node| {
|
for (container_decl.ast.members) |member_node| {
|
||||||
if (member_node == counts.nonexhaustive_node)
|
if (member_node == counts.nonexhaustive_node)
|
||||||
continue;
|
continue;
|
||||||
const member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) {
|
var member = switch (try containerMember(&block_scope, &namespace.base, &wip_members, member_node)) {
|
||||||
.decl => continue,
|
.decl => continue,
|
||||||
.field => |field| field,
|
.field => |field| field,
|
||||||
};
|
};
|
||||||
|
if (member.ast.tuple_like and member.ast.type_expr != 0 and
|
||||||
|
astgen.tree.nodes.items(.tag)[member.ast.type_expr] == .identifier)
|
||||||
|
{
|
||||||
|
const ident = astgen.tree.nodes.items(.main_token)[member.ast.type_expr];
|
||||||
|
member.ast.tuple_like = false;
|
||||||
|
member.ast.main_token = ident;
|
||||||
|
member.ast.type_expr = 0;
|
||||||
|
}
|
||||||
assert(member.comptime_token == null);
|
assert(member.comptime_token == null);
|
||||||
assert(member.ast.type_expr == 0);
|
assert(member.ast.type_expr == 0);
|
||||||
assert(member.ast.align_expr == 0);
|
assert(member.ast.align_expr == 0);
|
||||||
|
|
||||||
const field_name = try astgen.identAsString(member.ast.name_token);
|
const field_name = try astgen.identAsString(member.ast.main_token);
|
||||||
wip_members.appendToField(field_name);
|
wip_members.appendToField(field_name);
|
||||||
|
|
||||||
const doc_comment_index = try astgen.docCommentAsString(member.firstToken());
|
const doc_comment_index = try astgen.docCommentAsString(member.firstToken());
|
||||||
|
|
@ -11786,6 +11853,7 @@ const GenZir = struct {
|
||||||
layout: std.builtin.Type.ContainerLayout,
|
layout: std.builtin.Type.ContainerLayout,
|
||||||
known_non_opv: bool,
|
known_non_opv: bool,
|
||||||
known_comptime_only: bool,
|
known_comptime_only: bool,
|
||||||
|
is_tuple: bool,
|
||||||
}) !void {
|
}) !void {
|
||||||
const astgen = gz.astgen;
|
const astgen = gz.astgen;
|
||||||
const gpa = astgen.gpa;
|
const gpa = astgen.gpa;
|
||||||
|
|
@ -11820,6 +11888,7 @@ const GenZir = struct {
|
||||||
.has_backing_int = args.backing_int_ref != .none,
|
.has_backing_int = args.backing_int_ref != .none,
|
||||||
.known_non_opv = args.known_non_opv,
|
.known_non_opv = args.known_non_opv,
|
||||||
.known_comptime_only = args.known_comptime_only,
|
.known_comptime_only = args.known_comptime_only,
|
||||||
|
.is_tuple = args.is_tuple,
|
||||||
.name_strategy = gz.anon_name_strategy,
|
.name_strategy = gz.anon_name_strategy,
|
||||||
.layout = args.layout,
|
.layout = args.layout,
|
||||||
}),
|
}),
|
||||||
|
|
|
||||||
|
|
@ -6138,7 +6138,7 @@ fn queryFieldSrc(
|
||||||
.name => .{
|
.name => .{
|
||||||
.file_scope = file_scope,
|
.file_scope = file_scope,
|
||||||
.parent_decl_node = 0,
|
.parent_decl_node = 0,
|
||||||
.lazy = .{ .token_abs = field.ast.name_token },
|
.lazy = .{ .token_abs = field.ast.main_token },
|
||||||
},
|
},
|
||||||
.type => .{
|
.type => .{
|
||||||
.file_scope = file_scope,
|
.file_scope = file_scope,
|
||||||
|
|
|
||||||
|
|
@ -3166,7 +3166,7 @@ pub const Inst = struct {
|
||||||
/// 0b0X00: whether corresponding field is comptime
|
/// 0b0X00: whether corresponding field is comptime
|
||||||
/// 0bX000: whether corresponding field has a type expression
|
/// 0bX000: whether corresponding field has a type expression
|
||||||
/// 9. fields: { // for every fields_len
|
/// 9. fields: { // for every fields_len
|
||||||
/// field_name: u32,
|
/// field_name: u32, // if !is_tuple
|
||||||
/// doc_comment: u32, // 0 if no doc comment
|
/// doc_comment: u32, // 0 if no doc comment
|
||||||
/// field_type: Ref, // if corresponding bit is not set. none means anytype.
|
/// field_type: Ref, // if corresponding bit is not set. none means anytype.
|
||||||
/// field_type_body_len: u32, // if corresponding bit is set
|
/// field_type_body_len: u32, // if corresponding bit is set
|
||||||
|
|
@ -3186,9 +3186,10 @@ pub const Inst = struct {
|
||||||
has_backing_int: bool,
|
has_backing_int: bool,
|
||||||
known_non_opv: bool,
|
known_non_opv: bool,
|
||||||
known_comptime_only: bool,
|
known_comptime_only: bool,
|
||||||
|
is_tuple: bool,
|
||||||
name_strategy: NameStrategy,
|
name_strategy: NameStrategy,
|
||||||
layout: std.builtin.Type.ContainerLayout,
|
layout: std.builtin.Type.ContainerLayout,
|
||||||
_: u6 = undefined,
|
_: u5 = undefined,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1262,6 +1262,7 @@ const Writer = struct {
|
||||||
|
|
||||||
try self.writeFlag(stream, "known_non_opv, ", small.known_non_opv);
|
try self.writeFlag(stream, "known_non_opv, ", small.known_non_opv);
|
||||||
try self.writeFlag(stream, "known_comptime_only, ", small.known_comptime_only);
|
try self.writeFlag(stream, "known_comptime_only, ", small.known_comptime_only);
|
||||||
|
try self.writeFlag(stream, "tuple, ", small.is_tuple);
|
||||||
|
|
||||||
try stream.print("{s}, ", .{@tagName(small.name_strategy)});
|
try stream.print("{s}, ", .{@tagName(small.name_strategy)});
|
||||||
|
|
||||||
|
|
@ -1335,8 +1336,11 @@ const Writer = struct {
|
||||||
const has_type_body = @truncate(u1, cur_bit_bag) != 0;
|
const has_type_body = @truncate(u1, cur_bit_bag) != 0;
|
||||||
cur_bit_bag >>= 1;
|
cur_bit_bag >>= 1;
|
||||||
|
|
||||||
const field_name = self.code.extra[extra_index];
|
var field_name: u32 = 0;
|
||||||
|
if (!small.is_tuple) {
|
||||||
|
field_name = self.code.extra[extra_index];
|
||||||
extra_index += 1;
|
extra_index += 1;
|
||||||
|
}
|
||||||
const doc_comment_index = self.code.extra[extra_index];
|
const doc_comment_index = self.code.extra[extra_index];
|
||||||
extra_index += 1;
|
extra_index += 1;
|
||||||
|
|
||||||
|
|
@ -1370,13 +1374,16 @@ const Writer = struct {
|
||||||
try stream.writeAll("{\n");
|
try stream.writeAll("{\n");
|
||||||
self.indent += 2;
|
self.indent += 2;
|
||||||
|
|
||||||
for (fields) |field| {
|
for (fields) |field, i| {
|
||||||
const field_name = self.code.nullTerminatedString(field.name);
|
|
||||||
|
|
||||||
try self.writeDocComment(stream, field.doc_comment_index);
|
try self.writeDocComment(stream, field.doc_comment_index);
|
||||||
try stream.writeByteNTimes(' ', self.indent);
|
try stream.writeByteNTimes(' ', self.indent);
|
||||||
try self.writeFlag(stream, "comptime ", field.is_comptime);
|
try self.writeFlag(stream, "comptime ", field.is_comptime);
|
||||||
|
if (field.name != 0) {
|
||||||
|
const field_name = self.code.nullTerminatedString(field.name);
|
||||||
try stream.print("{}: ", .{std.zig.fmtId(field_name)});
|
try stream.print("{}: ", .{std.zig.fmtId(field_name)});
|
||||||
|
} else {
|
||||||
|
try stream.print("@\"{d}\": ", .{i});
|
||||||
|
}
|
||||||
if (field.field_type != .none) {
|
if (field.field_type != .none) {
|
||||||
try self.writeInstRef(stream, field.field_type);
|
try self.writeInstRef(stream, field.field_type);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue