| author | |
| committer | |
| log | cde3dd365e1fed806294eddc91700558d2135a64 |
| tree | e0477b65a71c3068eba481d552f3d11c71fabb80 |
| parent | 40cbf525f7d7b17b0728f835e6f68efe3c2eabf6 |
| parent | 7b00bef6bf91e69b0bc3a7cec31476573301a3dc |
| signature |
stage2: implement `@hasField`4 files changed, 49 insertions(+), 72 deletions(-)
src/Module.zig+3-1| ... | ... | @@ -876,10 +876,12 @@ pub const EnumSimple = struct { |
| 876 | 876 | /// The Decl that corresponds to the enum itself. |
| 877 | 877 | owner_decl: *Decl, |
| 878 | 878 | /// Set of field names in declaration order. |
| 879 | fields: std.StringArrayHashMapUnmanaged(void), | |
| 879 | fields: NameMap, | |
| 880 | 880 | /// Offset from `owner_decl`, points to the enum decl AST node. |
| 881 | 881 | node_offset: i32, |
| 882 | 882 | |
| 883 | pub const NameMap = EnumFull.NameMap; | |
| 884 | ||
| 883 | 885 | pub fn srcLoc(self: EnumSimple) SrcLoc { |
| 884 | 886 | return .{ |
| 885 | 887 | .file_scope = self.owner_decl.getFileScope(), |
src/Sema.zig+27-4| ... | ... | @@ -6413,10 +6413,33 @@ fn validateSwitchNoRange( |
| 6413 | 6413 | fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 6414 | 6414 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 6415 | 6415 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 6416 | _ = extra; | |
| 6417 | const src = inst_data.src(); | |
| 6418 | ||
| 6419 | return sema.fail(block, src, "TODO implement zirHasField", .{}); | |
| 6416 | const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | |
| 6417 | const name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; | |
| 6418 | const unresolved_ty = try sema.resolveType(block, ty_src, extra.lhs); | |
| 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 | 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 | 3252 | }; |
| 3253 | 3253 | } |
| 3254 | 3254 | |
| 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, | |
| 3263 | 3260 | .atomic_order, |
| 3264 | 3261 | .atomic_rmw_op, |
| 3265 | 3262 | .calling_convention, |
| ... | ... | @@ -3270,65 +3267,20 @@ pub const Type = extern union { |
| 3270 | 3267 | .export_options, |
| 3271 | 3268 | .extern_options, |
| 3272 | 3269 | => @panic("TODO resolve std.builtin types"), |
| 3273 | ||
| 3274 | 3270 | else => unreachable, |
| 3275 | } | |
| 3271 | }; | |
| 3272 | } | |
| 3273 | ||
| 3274 | pub fn enumFieldCount(ty: Type) usize { | |
| 3275 | return ty.enumFields().count(); | |
| 3276 | 3276 | } |
| 3277 | 3277 | |
| 3278 | 3278 | 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]; | |
| 3304 | 3280 | } |
| 3305 | 3281 | |
| 3306 | 3282 | 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); | |
| 3332 | 3284 | } |
| 3333 | 3285 | |
| 3334 | 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 | 35 | _ = @import("behavior/for.zig"); |
| 36 | 36 | _ = @import("behavior/generics.zig"); |
| 37 | 37 | _ = @import("behavior/hasdecl.zig"); |
| 38 | _ = @import("behavior/hasfield.zig"); | |
| 38 | 39 | _ = @import("behavior/if.zig"); |
| 39 | 40 | _ = @import("behavior/math.zig"); |
| 40 | 41 | _ = @import("behavior/maximum_minimum.zig"); |
| ... | ... | @@ -43,8 +44,8 @@ test { |
| 43 | 44 | _ = @import("behavior/optional.zig"); |
| 44 | 45 | _ = @import("behavior/pointers.zig"); |
| 45 | 46 | _ = @import("behavior/pub_enum.zig"); |
| 46 | _ = @import("behavior/slice.zig"); | |
| 47 | 47 | _ = @import("behavior/sizeof_and_typeof.zig"); |
| 48 | _ = @import("behavior/slice.zig"); | |
| 48 | 49 | _ = @import("behavior/struct.zig"); |
| 49 | 50 | _ = @import("behavior/switch.zig"); |
| 50 | 51 | _ = @import("behavior/this.zig"); |
| ... | ... | @@ -123,11 +124,10 @@ test { |
| 123 | 124 | _ = @import("behavior/field_parent_ptr.zig"); |
| 124 | 125 | _ = @import("behavior/floatop.zig"); |
| 125 | 126 | _ = @import("behavior/fn.zig"); |
| 126 | _ = @import("behavior/fn_in_struct_in_comptime.zig"); | |
| 127 | 127 | _ = @import("behavior/fn_delegation.zig"); |
| 128 | _ = @import("behavior/fn_in_struct_in_comptime.zig"); | |
| 128 | 129 | _ = @import("behavior/for_stage1.zig"); |
| 129 | 130 | _ = @import("behavior/generics_stage1.zig"); |
| 130 | _ = @import("behavior/hasfield.zig"); | |
| 131 | 131 | _ = @import("behavior/if_stage1.zig"); |
| 132 | 132 | _ = @import("behavior/import.zig"); |
| 133 | 133 | _ = @import("behavior/incomplete_struct_param_tld.zig"); |
| ... | ... | @@ -150,17 +150,17 @@ test { |
| 150 | 150 | // * add __muloti4 to compiler-rt |
| 151 | 151 | _ = @import("behavior/saturating_arithmetic.zig"); |
| 152 | 152 | } |
| 153 | _ = @import("behavior/shuffle.zig"); | |
| 154 | 153 | _ = @import("behavior/select.zig"); |
| 154 | _ = @import("behavior/shuffle.zig"); | |
| 155 | 155 | _ = @import("behavior/sizeof_and_typeof_stage1.zig"); |
| 156 | _ = @import("behavior/slice_stage1.zig"); | |
| 157 | 156 | _ = @import("behavior/slice_sentinel_comptime.zig"); |
| 158 | _ = @import("behavior/struct_stage1.zig"); | |
| 157 | _ = @import("behavior/slice_stage1.zig"); | |
| 159 | 158 | _ = @import("behavior/struct_contains_null_ptr_itself.zig"); |
| 160 | 159 | _ = @import("behavior/struct_contains_slice_of_itself.zig"); |
| 161 | _ = @import("behavior/switch_stage1.zig"); | |
| 160 | _ = @import("behavior/struct_stage1.zig"); | |
| 162 | 161 | _ = @import("behavior/switch_prong_err_enum.zig"); |
| 163 | 162 | _ = @import("behavior/switch_prong_implicit_cast.zig"); |
| 163 | _ = @import("behavior/switch_stage1.zig"); | |
| 164 | 164 | _ = @import("behavior/truncate.zig"); |
| 165 | 165 | _ = @import("behavior/try.zig"); |
| 166 | 166 | _ = @import("behavior/tuple.zig"); |