authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-18 00:57:10-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-10-18 00:57:10-04:00
logcde3dd365e1fed806294eddc91700558d2135a64
treee0477b65a71c3068eba481d552f3d11c71fabb80
parent40cbf525f7d7b17b0728f835e6f68efe3c2eabf6
parent7b00bef6bf91e69b0bc3a7cec31476573301a3dc
signature Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #9966 from nektro/stage2-hasfield

stage2: implement `@hasField`

4 files changed, 49 insertions(+), 72 deletions(-)

src/Module.zig+3-1
...@@ -876,10 +876,12 @@ pub const EnumSimple = struct {...@@ -876,10 +876,12 @@ pub const EnumSimple = struct {
876 /// The Decl that corresponds to the enum itself.876 /// The Decl that corresponds to the enum itself.
877 owner_decl: *Decl,877 owner_decl: *Decl,
878 /// Set of field names in declaration order.878 /// Set of field names in declaration order.
879 fields: std.StringArrayHashMapUnmanaged(void),879 fields: NameMap,
880 /// Offset from `owner_decl`, points to the enum decl AST node.880 /// Offset from `owner_decl`, points to the enum decl AST node.
881 node_offset: i32,881 node_offset: i32,
882882
883 pub const NameMap = EnumFull.NameMap;
884
883 pub fn srcLoc(self: EnumSimple) SrcLoc {885 pub fn srcLoc(self: EnumSimple) SrcLoc {
884 return .{886 return .{
885 .file_scope = self.owner_decl.getFileScope(),887 .file_scope = self.owner_decl.getFileScope(),
src/Sema.zig+27-4
...@@ -6413,10 +6413,33 @@ fn validateSwitchNoRange(...@@ -6413,10 +6413,33 @@ fn validateSwitchNoRange(
6413fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {6413fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
6414 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;6414 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
6415 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;6415 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
6416 _ = extra;6416 const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
6417 const src = inst_data.src();6417 const name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
64186418 const unresolved_ty = try sema.resolveType(block, ty_src, extra.lhs);
6419 return sema.fail(block, src, "TODO implement zirHasField", .{});6419 const field_name = try sema.resolveConstString(block, name_src, extra.rhs);
6420 const ty = try sema.resolveTypeFields(block, ty_src, unresolved_ty);
6421
6422 const has_field = hf: {
6423 if (ty.isSlice()) {
6424 if (mem.eql(u8, field_name, "ptr")) break :hf true;
6425 if (mem.eql(u8, field_name, "len")) break :hf true;
6426 break :hf false;
6427 }
6428 break :hf switch (ty.zigTypeTag()) {
6429 .Struct => ty.structFields().contains(field_name),
6430 .Union => ty.unionFields().contains(field_name),
6431 .Enum => ty.enumFields().contains(field_name),
6432 .Array => mem.eql(u8, field_name, "len"),
6433 else => return sema.fail(block, ty_src, "type '{}' does not support '@hasField'", .{
6434 ty,
6435 }),
6436 };
6437 };
6438 if (has_field) {
6439 return Air.Inst.Ref.bool_true;
6440 } else {
6441 return Air.Inst.Ref.bool_false;
6442 }
6420}6443}
64216444
6422fn zirHasDecl(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {6445fn 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 {...@@ -3252,14 +3252,11 @@ pub const Type = extern union {
3252 };3252 };
3253 }3253 }
32543254
3255 pub fn enumFieldCount(ty: Type) usize {3255 pub fn enumFields(ty: Type) Module.EnumFull.NameMap {
3256 switch (ty.tag()) {3256 return switch (ty.tag()) {
3257 .enum_full, .enum_nonexhaustive => {3257 .enum_full, .enum_nonexhaustive => ty.cast(Payload.EnumFull).?.data.fields,
3258 const enum_full = ty.cast(Payload.EnumFull).?.data;3258 .enum_simple => ty.castTag(.enum_simple).?.data.fields,
3259 return enum_full.fields.count();3259 .enum_numbered => ty.castTag(.enum_numbered).?.data.fields,
3260 },
3261 .enum_simple => return ty.castTag(.enum_simple).?.data.fields.count(),
3262 .enum_numbered => return ty.castTag(.enum_numbered).?.data.fields.count(),
3263 .atomic_order,3260 .atomic_order,
3264 .atomic_rmw_op,3261 .atomic_rmw_op,
3265 .calling_convention,3262 .calling_convention,
...@@ -3270,65 +3267,20 @@ pub const Type = extern union {...@@ -3270,65 +3267,20 @@ pub const Type = extern union {
3270 .export_options,3267 .export_options,
3271 .extern_options,3268 .extern_options,
3272 => @panic("TODO resolve std.builtin types"),3269 => @panic("TODO resolve std.builtin types"),
3273
3274 else => unreachable,3270 else => unreachable,
3275 }3271 };
3272 }
3273
3274 pub fn enumFieldCount(ty: Type) usize {
3275 return ty.enumFields().count();
3276 }3276 }
32773277
3278 pub fn enumFieldName(ty: Type, field_index: usize) []const u8 {3278 pub fn enumFieldName(ty: Type, field_index: usize) []const u8 {
3279 switch (ty.tag()) {3279 return ty.enumFields().keys()[field_index];
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 }
3304 }3280 }
33053281
3306 pub fn enumFieldIndex(ty: Type, field_name: []const u8) ?usize {3282 pub fn enumFieldIndex(ty: Type, field_name: []const u8) ?usize {
3307 switch (ty.tag()) {3283 return ty.enumFields().getIndex(field_name);
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 }
3332 }3284 }
33333285
3334 /// Asserts `ty` is an enum. `enum_tag` can either be `enum_field_index` or3286 /// Asserts `ty` is an enum. `enum_tag` can either be `enum_field_index` or
test/behavior.zig+7-7
...@@ -35,6 +35,7 @@ test {...@@ -35,6 +35,7 @@ test {
35 _ = @import("behavior/for.zig");35 _ = @import("behavior/for.zig");
36 _ = @import("behavior/generics.zig");36 _ = @import("behavior/generics.zig");
37 _ = @import("behavior/hasdecl.zig");37 _ = @import("behavior/hasdecl.zig");
38 _ = @import("behavior/hasfield.zig");
38 _ = @import("behavior/if.zig");39 _ = @import("behavior/if.zig");
39 _ = @import("behavior/math.zig");40 _ = @import("behavior/math.zig");
40 _ = @import("behavior/maximum_minimum.zig");41 _ = @import("behavior/maximum_minimum.zig");
...@@ -43,8 +44,8 @@ test {...@@ -43,8 +44,8 @@ test {
43 _ = @import("behavior/optional.zig");44 _ = @import("behavior/optional.zig");
44 _ = @import("behavior/pointers.zig");45 _ = @import("behavior/pointers.zig");
45 _ = @import("behavior/pub_enum.zig");46 _ = @import("behavior/pub_enum.zig");
46 _ = @import("behavior/slice.zig");
47 _ = @import("behavior/sizeof_and_typeof.zig");47 _ = @import("behavior/sizeof_and_typeof.zig");
48 _ = @import("behavior/slice.zig");
48 _ = @import("behavior/struct.zig");49 _ = @import("behavior/struct.zig");
49 _ = @import("behavior/switch.zig");50 _ = @import("behavior/switch.zig");
50 _ = @import("behavior/this.zig");51 _ = @import("behavior/this.zig");
...@@ -123,11 +124,10 @@ test {...@@ -123,11 +124,10 @@ test {
123 _ = @import("behavior/field_parent_ptr.zig");124 _ = @import("behavior/field_parent_ptr.zig");
124 _ = @import("behavior/floatop.zig");125 _ = @import("behavior/floatop.zig");
125 _ = @import("behavior/fn.zig");126 _ = @import("behavior/fn.zig");
126 _ = @import("behavior/fn_in_struct_in_comptime.zig");
127 _ = @import("behavior/fn_delegation.zig");127 _ = @import("behavior/fn_delegation.zig");
128 _ = @import("behavior/fn_in_struct_in_comptime.zig");
128 _ = @import("behavior/for_stage1.zig");129 _ = @import("behavior/for_stage1.zig");
129 _ = @import("behavior/generics_stage1.zig");130 _ = @import("behavior/generics_stage1.zig");
130 _ = @import("behavior/hasfield.zig");
131 _ = @import("behavior/if_stage1.zig");131 _ = @import("behavior/if_stage1.zig");
132 _ = @import("behavior/import.zig");132 _ = @import("behavior/import.zig");
133 _ = @import("behavior/incomplete_struct_param_tld.zig");133 _ = @import("behavior/incomplete_struct_param_tld.zig");
...@@ -150,17 +150,17 @@ test {...@@ -150,17 +150,17 @@ test {
150 // * add __muloti4 to compiler-rt150 // * add __muloti4 to compiler-rt
151 _ = @import("behavior/saturating_arithmetic.zig");151 _ = @import("behavior/saturating_arithmetic.zig");
152 }152 }
153 _ = @import("behavior/shuffle.zig");
154 _ = @import("behavior/select.zig");153 _ = @import("behavior/select.zig");
154 _ = @import("behavior/shuffle.zig");
155 _ = @import("behavior/sizeof_and_typeof_stage1.zig");155 _ = @import("behavior/sizeof_and_typeof_stage1.zig");
156 _ = @import("behavior/slice_stage1.zig");
157 _ = @import("behavior/slice_sentinel_comptime.zig");156 _ = @import("behavior/slice_sentinel_comptime.zig");
158 _ = @import("behavior/struct_stage1.zig");157 _ = @import("behavior/slice_stage1.zig");
159 _ = @import("behavior/struct_contains_null_ptr_itself.zig");158 _ = @import("behavior/struct_contains_null_ptr_itself.zig");
160 _ = @import("behavior/struct_contains_slice_of_itself.zig");159 _ = @import("behavior/struct_contains_slice_of_itself.zig");
161 _ = @import("behavior/switch_stage1.zig");160 _ = @import("behavior/struct_stage1.zig");
162 _ = @import("behavior/switch_prong_err_enum.zig");161 _ = @import("behavior/switch_prong_err_enum.zig");
163 _ = @import("behavior/switch_prong_implicit_cast.zig");162 _ = @import("behavior/switch_prong_implicit_cast.zig");
163 _ = @import("behavior/switch_stage1.zig");
164 _ = @import("behavior/truncate.zig");164 _ = @import("behavior/truncate.zig");
165 _ = @import("behavior/try.zig");165 _ = @import("behavior/try.zig");
166 _ = @import("behavior/tuple.zig");166 _ = @import("behavior/tuple.zig");