| author | |
| committer | |
| log | cde3dd365e1fed806294eddc91700558d2135a64 |
| tree | e0477b65a71c3068eba481d552f3d11c71fabb80 |
| parent | 40cbf525f7d7b17b0728f835e6f68efe3c2eabf6 |
| parent | 7b00bef6bf91e69b0bc3a7cec31476573301a3dc |
| signature | Signed by PGP key 4AEE18F83AFDEB23 |
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, |
| 882 | 882 | ||
| 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( |
| 6413 | fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 6413 | fn 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 }; |
| 6418 | 6418 | 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 | } |
| 6421 | 6444 | ||
| 6422 | fn zirHasDecl(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 6445 | fn 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 | } |
| 3254 | 3254 | ||
| 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 | } |
| 3277 | 3277 | ||
| 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 | } |
| 3305 | 3281 | ||
| 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 | } |
| 3333 | 3285 | ||
| 3334 | /// Asserts `ty` is an enum. `enum_tag` can either be `enum_field_index` or | 3286 | /// 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-rt | 150 | // * 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"); |