stage2: implement @hasField
struct and union are kept in stage1 because struct/unionFieldCount are returning zero
This commit is contained in:
committed by
Andrew Kelley
parent
7d0a74456b
commit
0ef2e2520a
@@ -876,10 +876,12 @@ pub const EnumSimple = struct {
|
||||
/// The Decl that corresponds to the enum itself.
|
||||
owner_decl: *Decl,
|
||||
/// Set of field names in declaration order.
|
||||
fields: std.StringArrayHashMapUnmanaged(void),
|
||||
fields: NameMap,
|
||||
/// Offset from `owner_decl`, points to the enum decl AST node.
|
||||
node_offset: i32,
|
||||
|
||||
pub const NameMap = EnumFull.NameMap;
|
||||
|
||||
pub fn srcLoc(self: EnumSimple) SrcLoc {
|
||||
return .{
|
||||
.file_scope = self.owner_decl.getFileScope(),
|
||||
|
||||
17
src/Sema.zig
17
src/Sema.zig
@@ -6413,10 +6413,21 @@ fn validateSwitchNoRange(
|
||||
fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
|
||||
const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
|
||||
_ = extra;
|
||||
const src = inst_data.src();
|
||||
const lhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
|
||||
const rhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
|
||||
const container_type = try sema.resolveType(block, lhs_src, extra.lhs);
|
||||
const field_name = try sema.resolveConstString(block, rhs_src, extra.rhs);
|
||||
|
||||
return sema.fail(block, src, "TODO implement zirHasField", .{});
|
||||
const has_field = switch (container_type.zigTypeTag()) {
|
||||
.Struct => container_type.structFields().contains(field_name),
|
||||
.Union => container_type.unionFields().contains(field_name),
|
||||
.Enum => container_type.enumFields().contains(field_name),
|
||||
else => return sema.fail(block, lhs_src, "expected struct, enum, or union, found '{}'", .{container_type}),
|
||||
};
|
||||
if (has_field) {
|
||||
return Air.Inst.Ref.bool_true;
|
||||
}
|
||||
return Air.Inst.Ref.bool_false;
|
||||
}
|
||||
|
||||
fn zirHasDecl(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
||||
|
||||
72
src/type.zig
72
src/type.zig
@@ -3252,14 +3252,11 @@ pub const Type = extern union {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn enumFieldCount(ty: Type) usize {
|
||||
switch (ty.tag()) {
|
||||
.enum_full, .enum_nonexhaustive => {
|
||||
const enum_full = ty.cast(Payload.EnumFull).?.data;
|
||||
return enum_full.fields.count();
|
||||
},
|
||||
.enum_simple => return ty.castTag(.enum_simple).?.data.fields.count(),
|
||||
.enum_numbered => return ty.castTag(.enum_numbered).?.data.fields.count(),
|
||||
pub fn enumFields(ty: Type) Module.EnumFull.NameMap {
|
||||
return switch (ty.tag()) {
|
||||
.enum_full, .enum_nonexhaustive => ty.cast(Payload.EnumFull).?.data.fields,
|
||||
.enum_simple => ty.castTag(.enum_simple).?.data.fields,
|
||||
.enum_numbered => ty.castTag(.enum_numbered).?.data.fields,
|
||||
.atomic_order,
|
||||
.atomic_rmw_op,
|
||||
.calling_convention,
|
||||
@@ -3270,65 +3267,20 @@ pub const Type = extern union {
|
||||
.export_options,
|
||||
.extern_options,
|
||||
=> @panic("TODO resolve std.builtin types"),
|
||||
|
||||
else => unreachable,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub fn enumFieldCount(ty: Type) usize {
|
||||
return ty.enumFields().count();
|
||||
}
|
||||
|
||||
pub fn enumFieldName(ty: Type, field_index: usize) []const u8 {
|
||||
switch (ty.tag()) {
|
||||
.enum_full, .enum_nonexhaustive => {
|
||||
const enum_full = ty.cast(Payload.EnumFull).?.data;
|
||||
return enum_full.fields.keys()[field_index];
|
||||
},
|
||||
.enum_simple => {
|
||||
const enum_simple = ty.castTag(.enum_simple).?.data;
|
||||
return enum_simple.fields.keys()[field_index];
|
||||
},
|
||||
.enum_numbered => {
|
||||
const enum_numbered = ty.castTag(.enum_numbered).?.data;
|
||||
return enum_numbered.fields.keys()[field_index];
|
||||
},
|
||||
.atomic_order,
|
||||
.atomic_rmw_op,
|
||||
.calling_convention,
|
||||
.address_space,
|
||||
.float_mode,
|
||||
.reduce_op,
|
||||
.call_options,
|
||||
.export_options,
|
||||
.extern_options,
|
||||
=> @panic("TODO resolve std.builtin types"),
|
||||
else => unreachable,
|
||||
}
|
||||
return ty.enumFields().keys()[field_index];
|
||||
}
|
||||
|
||||
pub fn enumFieldIndex(ty: Type, field_name: []const u8) ?usize {
|
||||
switch (ty.tag()) {
|
||||
.enum_full, .enum_nonexhaustive => {
|
||||
const enum_full = ty.cast(Payload.EnumFull).?.data;
|
||||
return enum_full.fields.getIndex(field_name);
|
||||
},
|
||||
.enum_simple => {
|
||||
const enum_simple = ty.castTag(.enum_simple).?.data;
|
||||
return enum_simple.fields.getIndex(field_name);
|
||||
},
|
||||
.enum_numbered => {
|
||||
const enum_numbered = ty.castTag(.enum_numbered).?.data;
|
||||
return enum_numbered.fields.getIndex(field_name);
|
||||
},
|
||||
.atomic_order,
|
||||
.atomic_rmw_op,
|
||||
.calling_convention,
|
||||
.address_space,
|
||||
.float_mode,
|
||||
.reduce_op,
|
||||
.call_options,
|
||||
.export_options,
|
||||
.extern_options,
|
||||
=> @panic("TODO resolve std.builtin types"),
|
||||
else => unreachable,
|
||||
}
|
||||
return ty.enumFields().getIndex(field_name);
|
||||
}
|
||||
|
||||
/// Asserts `ty` is an enum. `enum_tag` can either be `enum_field_index` or
|
||||
|
||||
@@ -35,6 +35,7 @@ test {
|
||||
_ = @import("behavior/for.zig");
|
||||
_ = @import("behavior/generics.zig");
|
||||
_ = @import("behavior/hasdecl.zig");
|
||||
_ = @import("behavior/hasfield.zig");
|
||||
_ = @import("behavior/if.zig");
|
||||
_ = @import("behavior/math.zig");
|
||||
_ = @import("behavior/maximum_minimum.zig");
|
||||
@@ -127,7 +128,7 @@ test {
|
||||
_ = @import("behavior/fn_in_struct_in_comptime.zig");
|
||||
_ = @import("behavior/for_stage1.zig");
|
||||
_ = @import("behavior/generics_stage1.zig");
|
||||
_ = @import("behavior/hasfield.zig");
|
||||
_ = @import("behavior/hasfield_stage1.zig");
|
||||
_ = @import("behavior/if_stage1.zig");
|
||||
_ = @import("behavior/import.zig");
|
||||
_ = @import("behavior/incomplete_struct_param_tld.zig");
|
||||
|
||||
@@ -2,28 +2,6 @@ const expect = @import("std").testing.expect;
|
||||
const builtin = @import("builtin");
|
||||
|
||||
test "@hasField" {
|
||||
const struc = struct {
|
||||
a: i32,
|
||||
b: []u8,
|
||||
|
||||
pub const nope = 1;
|
||||
};
|
||||
try expect(@hasField(struc, "a") == true);
|
||||
try expect(@hasField(struc, "b") == true);
|
||||
try expect(@hasField(struc, "non-existant") == false);
|
||||
try expect(@hasField(struc, "nope") == false);
|
||||
|
||||
const unin = union {
|
||||
a: u64,
|
||||
b: []u16,
|
||||
|
||||
pub const nope = 1;
|
||||
};
|
||||
try expect(@hasField(unin, "a") == true);
|
||||
try expect(@hasField(unin, "b") == true);
|
||||
try expect(@hasField(unin, "non-existant") == false);
|
||||
try expect(@hasField(unin, "nope") == false);
|
||||
|
||||
const enm = enum {
|
||||
a,
|
||||
b,
|
||||
|
||||
26
test/behavior/hasfield_stage1.zig
Normal file
26
test/behavior/hasfield_stage1.zig
Normal file
@@ -0,0 +1,26 @@
|
||||
const expect = @import("std").testing.expect;
|
||||
const builtin = @import("builtin");
|
||||
|
||||
test "@hasField" {
|
||||
const struc = struct {
|
||||
a: i32,
|
||||
b: []const u8,
|
||||
|
||||
pub const nope = 1;
|
||||
};
|
||||
try expect(@hasField(struc, "a") == true);
|
||||
try expect(@hasField(struc, "b") == true);
|
||||
try expect(@hasField(struc, "non-existant") == false);
|
||||
try expect(@hasField(struc, "nope") == false);
|
||||
|
||||
const unin = union {
|
||||
a: u64,
|
||||
b: []const u16,
|
||||
|
||||
pub const nope = 1;
|
||||
};
|
||||
try expect(@hasField(unin, "a") == true);
|
||||
try expect(@hasField(unin, "b") == true);
|
||||
try expect(@hasField(unin, "non-existant") == false);
|
||||
try expect(@hasField(unin, "nope") == false);
|
||||
}
|
||||
Reference in New Issue
Block a user