authorgravatar for xq@random-projects.netFelix "xq" Queißner <xq@random-projects.net> 2020-09-25 09:27:00+02:00
committergravatar for xq@random-projects.netFelix "xq" Queißner <xq@random-projects.net> 2020-09-25 09:27:00+02:00
log7f68b14377ffe33ded2866f6bf53f213a9c5f620
tree0d0297954006d8365d0fddce49d9a52cf1faefcf
parentf8b3543cabc28df15e85085a72adb474b345cf93

Implements std.meta.Tuple(), implements #4607 in userland.


1 files changed, 63 insertions(+), 1 deletions(-)

lib/std/meta.zig+63-1
...@@ -807,7 +807,7 @@ pub fn sizeof(target: anytype) usize {...@@ -807,7 +807,7 @@ pub fn sizeof(target: anytype) usize {
807 // TODO to get the correct result we have to translate807 // TODO to get the correct result we have to translate
808 // `1073741824 * 4` as `int(1073741824) *% int(4)` since808 // `1073741824 * 4` as `int(1073741824) *% int(4)` since
809 // sizeof(1073741824 * 4) != sizeof(4294967296).809 // sizeof(1073741824 * 4) != sizeof(4294967296).
810 810
811 // TODO test if target fits in int, long or long long811 // TODO test if target fits in int, long or long long
812 return @sizeOf(c_int);812 return @sizeOf(c_int);
813 },813 },
...@@ -826,3 +826,65 @@ test "sizeof" {...@@ -826,3 +826,65 @@ test "sizeof" {
826 testing.expect(sizeof(E.One) == @sizeOf(c_int));826 testing.expect(sizeof(E.One) == @sizeOf(c_int));
827 testing.expect(sizeof(S) == 4);827 testing.expect(sizeof(S) == 4);
828}828}
829
830/// For a given anonymous list of types, returns a new tuple type
831/// with those types as fields.
832///
833/// Examples:
834/// - `Tuple(.{})` ⇒ `tuple { }`
835/// - `Tuple(.{f32})` ⇒ `tuple { f32 }`
836/// - `Tuple(.{f32,u32})` ⇒ `tuple { f32, u32 }`
837pub fn Tuple(comptime types: anytype) type {
838 var tuple_fields: [types.len]std.builtin.TypeInfo.StructField = undefined;
839 inline for (types) |T, i| {
840 @setEvalBranchQuota(10_000);
841 var num_buf: [128]u8 = undefined;
842 tuple_fields[i] = std.builtin.TypeInfo.StructField{
843 .name = std.fmt.bufPrint(&num_buf, "{d}", .{i}) catch unreachable,
844 .field_type = T,
845 .default_value = @as(?T, null),
846 .is_comptime = false,
847 };
848 }
849
850 return @Type(std.builtin.TypeInfo{
851 .Struct = std.builtin.TypeInfo.Struct{
852 .is_tuple = true,
853 .layout = .Auto,
854 .decls = &[_]std.builtin.TypeInfo.Declaration{},
855 .fields = &tuple_fields,
856 },
857 });
858}
859
860comptime {
861 const T = struct {
862 fn assertTypeEqual(comptime Expected: type, comptime Actual: type) void {
863 if (Expected != Actual)
864 @compileError("Expected type " ++ @typeName(Expected) ++ ", but got type " ++ @typeName(Actual));
865 }
866
867 fn assertTuple(comptime expected: anytype, comptime Actual: type) void {
868 const info = @typeInfo(Actual);
869 if (info != .Struct)
870 @compileError("Expected struct type");
871 if (!info.Struct.is_tuple)
872 @compileError("Struct type must be a tuple type");
873
874 const fields_list = std.meta.fields(Actual);
875 if (expected.len != fields_list.len)
876 @compileError("Argument count mismatch");
877
878 inline for (fields_list) |fld, i| {
879 if (expected[i] != fld.field_type) {
880 @compileError("Field " ++ fld.name ++ " expected to be type " ++ @typeName(expected[i]) ++ ", but was type " ++ @typeName(fld.field_type));
881 }
882 }
883 }
884 };
885
886 T.assertTuple(.{}, Tuple(.{}));
887 T.assertTuple(.{u32}, Tuple(.{u32}));
888 T.assertTuple(.{ u32, f16 }, Tuple(.{ u32, f16 }));
889 T.assertTuple(.{ u32, f16, []const u8 }, Tuple(.{ u32, f16, []const u8 }));
890}