authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2021-10-16 22:49:51-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-17 21:42:22-07:00
log0ef2e2520af59a42014399282ddea983fa526449
treeb186116f3064299d58a81cacb2f68ae492d26d65
parent7d0a74456b0f239e6cc8532143badeb6781bd47d

stage2: implement `@hasField`

struct and union are kept in stage1 because struct/unionFieldCount are returning zero

6 files changed, 57 insertions(+), 87 deletions(-)

src/Module.zig+3-1
......@@ -876,10 +876,12 @@ pub const EnumSimple = struct {
876876 /// The Decl that corresponds to the enum itself.
877877 owner_decl: *Decl,
878878 /// Set of field names in declaration order.
879 fields: std.StringArrayHashMapUnmanaged(void),
879 fields: NameMap,
880880 /// Offset from `owner_decl`, points to the enum decl AST node.
881881 node_offset: i32,
882882
883 pub const NameMap = EnumFull.NameMap;
884
883885 pub fn srcLoc(self: EnumSimple) SrcLoc {
884886 return .{
885887 .file_scope = self.owner_decl.getFileScope(),
src/Sema.zig+14-3
......@@ -6413,10 +6413,21 @@ fn validateSwitchNoRange(
64136413fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
64146414 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
64156415 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
6416 _ = extra;
6417 const src = inst_data.src();
6416 const lhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
6417 const rhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
6418 const container_type = try sema.resolveType(block, lhs_src, extra.lhs);
6419 const field_name = try sema.resolveConstString(block, rhs_src, extra.rhs);
64186420
6419 return sema.fail(block, src, "TODO implement zirHasField", .{});
6421 const has_field = switch (container_type.zigTypeTag()) {
6422 .Struct => container_type.structFields().contains(field_name),
6423 .Union => container_type.unionFields().contains(field_name),
6424 .Enum => container_type.enumFields().contains(field_name),
6425 else => return sema.fail(block, lhs_src, "expected struct, enum, or union, found '{}'", .{container_type}),
6426 };
6427 if (has_field) {
6428 return Air.Inst.Ref.bool_true;
6429 }
6430 return Air.Inst.Ref.bool_false;
64206431}
64216432
64226433fn zirHasDecl(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
src/type.zig+12-60
......@@ -3252,14 +3252,11 @@ pub const Type = extern union {
32523252 };
32533253 }
32543254
3255 pub fn enumFieldCount(ty: Type) usize {
3256 switch (ty.tag()) {
3257 .enum_full, .enum_nonexhaustive => {
3258 const enum_full = ty.cast(Payload.EnumFull).?.data;
3259 return enum_full.fields.count();
3260 },
3261 .enum_simple => return ty.castTag(.enum_simple).?.data.fields.count(),
3262 .enum_numbered => return ty.castTag(.enum_numbered).?.data.fields.count(),
3255 pub fn enumFields(ty: Type) Module.EnumFull.NameMap {
3256 return switch (ty.tag()) {
3257 .enum_full, .enum_nonexhaustive => ty.cast(Payload.EnumFull).?.data.fields,
3258 .enum_simple => ty.castTag(.enum_simple).?.data.fields,
3259 .enum_numbered => ty.castTag(.enum_numbered).?.data.fields,
32633260 .atomic_order,
32643261 .atomic_rmw_op,
32653262 .calling_convention,
......@@ -3270,65 +3267,20 @@ pub const Type = extern union {
32703267 .export_options,
32713268 .extern_options,
32723269 => @panic("TODO resolve std.builtin types"),
3273
32743270 else => unreachable,
3275 }
3271 };
3272 }
3273
3274 pub fn enumFieldCount(ty: Type) usize {
3275 return ty.enumFields().count();
32763276 }
32773277
32783278 pub fn enumFieldName(ty: Type, field_index: usize) []const u8 {
3279 switch (ty.tag()) {
3280 .enum_full, .enum_nonexhaustive => {
3281 const enum_full = ty.cast(Payload.EnumFull).?.data;
3282 return enum_full.fields.keys()[field_index];
3283 },
3284 .enum_simple => {
3285 const enum_simple = ty.castTag(.enum_simple).?.data;
3286 return enum_simple.fields.keys()[field_index];
3287 },
3288 .enum_numbered => {
3289 const enum_numbered = ty.castTag(.enum_numbered).?.data;
3290 return enum_numbered.fields.keys()[field_index];
3291 },
3292 .atomic_order,
3293 .atomic_rmw_op,
3294 .calling_convention,
3295 .address_space,
3296 .float_mode,
3297 .reduce_op,
3298 .call_options,
3299 .export_options,
3300 .extern_options,
3301 => @panic("TODO resolve std.builtin types"),
3302 else => unreachable,
3303 }
3279 return ty.enumFields().keys()[field_index];
33043280 }
33053281
33063282 pub fn enumFieldIndex(ty: Type, field_name: []const u8) ?usize {
3307 switch (ty.tag()) {
3308 .enum_full, .enum_nonexhaustive => {
3309 const enum_full = ty.cast(Payload.EnumFull).?.data;
3310 return enum_full.fields.getIndex(field_name);
3311 },
3312 .enum_simple => {
3313 const enum_simple = ty.castTag(.enum_simple).?.data;
3314 return enum_simple.fields.getIndex(field_name);
3315 },
3316 .enum_numbered => {
3317 const enum_numbered = ty.castTag(.enum_numbered).?.data;
3318 return enum_numbered.fields.getIndex(field_name);
3319 },
3320 .atomic_order,
3321 .atomic_rmw_op,
3322 .calling_convention,
3323 .address_space,
3324 .float_mode,
3325 .reduce_op,
3326 .call_options,
3327 .export_options,
3328 .extern_options,
3329 => @panic("TODO resolve std.builtin types"),
3330 else => unreachable,
3331 }
3283 return ty.enumFields().getIndex(field_name);
33323284 }
33333285
33343286 /// Asserts `ty` is an enum. `enum_tag` can either be `enum_field_index` or
test/behavior.zig+2-1
......@@ -35,6 +35,7 @@ test {
3535 _ = @import("behavior/for.zig");
3636 _ = @import("behavior/generics.zig");
3737 _ = @import("behavior/hasdecl.zig");
38 _ = @import("behavior/hasfield.zig");
3839 _ = @import("behavior/if.zig");
3940 _ = @import("behavior/math.zig");
4041 _ = @import("behavior/maximum_minimum.zig");
......@@ -127,7 +128,7 @@ test {
127128 _ = @import("behavior/fn_in_struct_in_comptime.zig");
128129 _ = @import("behavior/for_stage1.zig");
129130 _ = @import("behavior/generics_stage1.zig");
130 _ = @import("behavior/hasfield.zig");
131 _ = @import("behavior/hasfield_stage1.zig");
131132 _ = @import("behavior/if_stage1.zig");
132133 _ = @import("behavior/import.zig");
133134 _ = @import("behavior/incomplete_struct_param_tld.zig");
test/behavior/hasfield.zig-22
......@@ -2,28 +2,6 @@ const expect = @import("std").testing.expect;
22const builtin = @import("builtin");
33
44test "@hasField" {
5 const struc = struct {
6 a: i32,
7 b: []u8,
8
9 pub const nope = 1;
10 };
11 try expect(@hasField(struc, "a") == true);
12 try expect(@hasField(struc, "b") == true);
13 try expect(@hasField(struc, "non-existant") == false);
14 try expect(@hasField(struc, "nope") == false);
15
16 const unin = union {
17 a: u64,
18 b: []u16,
19
20 pub const nope = 1;
21 };
22 try expect(@hasField(unin, "a") == true);
23 try expect(@hasField(unin, "b") == true);
24 try expect(@hasField(unin, "non-existant") == false);
25 try expect(@hasField(unin, "nope") == false);
26
275 const enm = enum {
286 a,
297 b,
test/behavior/hasfield_stage1.zig created+26
......@@ -0,0 +1,26 @@
1const expect = @import("std").testing.expect;
2const builtin = @import("builtin");
3
4test "@hasField" {
5 const struc = struct {
6 a: i32,
7 b: []const u8,
8
9 pub const nope = 1;
10 };
11 try expect(@hasField(struc, "a") == true);
12 try expect(@hasField(struc, "b") == true);
13 try expect(@hasField(struc, "non-existant") == false);
14 try expect(@hasField(struc, "nope") == false);
15
16 const unin = union {
17 a: u64,
18 b: []const u16,
19
20 pub const nope = 1;
21 };
22 try expect(@hasField(unin, "a") == true);
23 try expect(@hasField(unin, "b") == true);
24 try expect(@hasField(unin, "non-existant") == false);
25 try expect(@hasField(unin, "nope") == false);
26}