authorgravatar for alex_naskos@hotmail.comAlexandros Naskos <alex_naskos@hotmail.com> 2020-09-29 15:59:27+03:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-09-29 15:59:27+03:00
log3342e28784b9ef7bf8356004a7b2698edcb70b40
treee0f8443ba2c8cb60b4447c724bfdbcc73d29d59b
parentc98d55626dab1f3b097dc06ec10119eb4a51f128
parentc2d60bc5b5dd9ac39760588c777cc6809732af19
signature Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #6416 from MasterQ32/meta-tuple

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 {
807807 // TODO to get the correct result we have to translate
808808 // `1073741824 * 4` as `int(1073741824) *% int(4)` since
809809 // sizeof(1073741824 * 4) != sizeof(4294967296).
810
810
811811 // TODO test if target fits in int, long or long long
812812 return @sizeOf(c_int);
813813 },
......@@ -826,3 +826,65 @@ test "sizeof" {
826826 testing.expect(sizeof(E.One) == @sizeOf(c_int));
827827 testing.expect(sizeof(S) == 4);
828828}
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(&[_]type {})` ⇒ `tuple { }`
835/// - `Tuple(&[_]type {f32})` ⇒ `tuple { f32 }`
836/// - `Tuple(&[_]type {f32,u32})` ⇒ `tuple { f32, u32 }`
837pub fn Tuple(comptime types: []const type) 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
860test "Tuple" {
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(&[_]type{}));
887 T.assertTuple(.{u32}, Tuple(&[_]type{u32}));
888 T.assertTuple(.{ u32, f16 }, Tuple(&[_]type{ u32, f16 }));
889 T.assertTuple(.{ u32, f16, []const u8 }, Tuple(&[_]type{ u32, f16, []const u8 }));
890}