From 7f68b14377ffe33ded2866f6bf53f213a9c5f620 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20=28xq=29=20Quei=C3=9Fner?= Date: Fri, 25 Sep 2020 09:27:00 +0200 Subject: [PATCH 1/3] Implements std.meta.Tuple(), implements #4607 in userland. --- lib/std/meta.zig | 64 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/lib/std/meta.zig b/lib/std/meta.zig index 1507aa9de8..c92637250f 100644 --- a/lib/std/meta.zig +++ b/lib/std/meta.zig @@ -807,7 +807,7 @@ pub fn sizeof(target: anytype) usize { // TODO to get the correct result we have to translate // `1073741824 * 4` as `int(1073741824) *% int(4)` since // sizeof(1073741824 * 4) != sizeof(4294967296). - + // TODO test if target fits in int, long or long long return @sizeOf(c_int); }, @@ -826,3 +826,65 @@ test "sizeof" { testing.expect(sizeof(E.One) == @sizeOf(c_int)); testing.expect(sizeof(S) == 4); } + +/// For a given anonymous list of types, returns a new tuple type +/// with those types as fields. +/// +/// Examples: +/// - `Tuple(.{})` ⇒ `tuple { }` +/// - `Tuple(.{f32})` ⇒ `tuple { f32 }` +/// - `Tuple(.{f32,u32})` ⇒ `tuple { f32, u32 }` +pub fn Tuple(comptime types: anytype) type { + var tuple_fields: [types.len]std.builtin.TypeInfo.StructField = undefined; + inline for (types) |T, i| { + @setEvalBranchQuota(10_000); + var num_buf: [128]u8 = undefined; + tuple_fields[i] = std.builtin.TypeInfo.StructField{ + .name = std.fmt.bufPrint(&num_buf, "{d}", .{i}) catch unreachable, + .field_type = T, + .default_value = @as(?T, null), + .is_comptime = false, + }; + } + + return @Type(std.builtin.TypeInfo{ + .Struct = std.builtin.TypeInfo.Struct{ + .is_tuple = true, + .layout = .Auto, + .decls = &[_]std.builtin.TypeInfo.Declaration{}, + .fields = &tuple_fields, + }, + }); +} + +comptime { + const T = struct { + fn assertTypeEqual(comptime Expected: type, comptime Actual: type) void { + if (Expected != Actual) + @compileError("Expected type " ++ @typeName(Expected) ++ ", but got type " ++ @typeName(Actual)); + } + + fn assertTuple(comptime expected: anytype, comptime Actual: type) void { + const info = @typeInfo(Actual); + if (info != .Struct) + @compileError("Expected struct type"); + if (!info.Struct.is_tuple) + @compileError("Struct type must be a tuple type"); + + const fields_list = std.meta.fields(Actual); + if (expected.len != fields_list.len) + @compileError("Argument count mismatch"); + + inline for (fields_list) |fld, i| { + if (expected[i] != fld.field_type) { + @compileError("Field " ++ fld.name ++ " expected to be type " ++ @typeName(expected[i]) ++ ", but was type " ++ @typeName(fld.field_type)); + } + } + } + }; + + T.assertTuple(.{}, Tuple(.{})); + T.assertTuple(.{u32}, Tuple(.{u32})); + T.assertTuple(.{ u32, f16 }, Tuple(.{ u32, f16 })); + T.assertTuple(.{ u32, f16, []const u8 }, Tuple(.{ u32, f16, []const u8 })); +} From 933146699806fc25f8182f53cd8c217654d51664 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20=28xq=29=20Quei=C3=9Fner?= Date: Mon, 28 Sep 2020 11:42:39 +0200 Subject: [PATCH 2/3] Changes comptime block to test. --- lib/std/meta.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/meta.zig b/lib/std/meta.zig index c92637250f..5b4920157a 100644 --- a/lib/std/meta.zig +++ b/lib/std/meta.zig @@ -857,7 +857,7 @@ pub fn Tuple(comptime types: anytype) type { }); } -comptime { +test "Tuple" { const T = struct { fn assertTypeEqual(comptime Expected: type, comptime Actual: type) void { if (Expected != Actual) From c2d60bc5b5dd9ac39760588c777cc6809732af19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20=28xq=29=20Quei=C3=9Fner?= Date: Mon, 28 Sep 2020 12:24:22 +0200 Subject: [PATCH 3/3] Follows @tadeokondrak remark about taking `[]const type`. --- lib/std/meta.zig | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/std/meta.zig b/lib/std/meta.zig index 5b4920157a..13d3c574e9 100644 --- a/lib/std/meta.zig +++ b/lib/std/meta.zig @@ -831,10 +831,10 @@ test "sizeof" { /// with those types as fields. /// /// Examples: -/// - `Tuple(.{})` ⇒ `tuple { }` -/// - `Tuple(.{f32})` ⇒ `tuple { f32 }` -/// - `Tuple(.{f32,u32})` ⇒ `tuple { f32, u32 }` -pub fn Tuple(comptime types: anytype) type { +/// - `Tuple(&[_]type {})` ⇒ `tuple { }` +/// - `Tuple(&[_]type {f32})` ⇒ `tuple { f32 }` +/// - `Tuple(&[_]type {f32,u32})` ⇒ `tuple { f32, u32 }` +pub fn Tuple(comptime types: []const type) type { var tuple_fields: [types.len]std.builtin.TypeInfo.StructField = undefined; inline for (types) |T, i| { @setEvalBranchQuota(10_000); @@ -883,8 +883,8 @@ test "Tuple" { } }; - T.assertTuple(.{}, Tuple(.{})); - T.assertTuple(.{u32}, Tuple(.{u32})); - T.assertTuple(.{ u32, f16 }, Tuple(.{ u32, f16 })); - T.assertTuple(.{ u32, f16, []const u8 }, Tuple(.{ u32, f16, []const u8 })); + T.assertTuple(.{}, Tuple(&[_]type{})); + T.assertTuple(.{u32}, Tuple(&[_]type{u32})); + T.assertTuple(.{ u32, f16 }, Tuple(&[_]type{ u32, f16 })); + T.assertTuple(.{ u32, f16, []const u8 }, Tuple(&[_]type{ u32, f16, []const u8 })); }