mirror of
https://github.com/ziglang/zig.git
synced 2024-11-15 00:26:57 +00:00
parent
dc4fa83dd7
commit
b33efa3739
@ -390,6 +390,20 @@ pub const Macros = struct {
|
||||
pub fn WL_CONTAINER_OF(ptr: anytype, sample: anytype, comptime member: []const u8) @TypeOf(sample) {
|
||||
return @fieldParentPtr(@TypeOf(sample.*), member, ptr);
|
||||
}
|
||||
|
||||
/// A 2-argument function-like macro defined as #define FOO(A, B) (A)(B)
|
||||
/// could be either: cast B to A, or call A with the value B.
|
||||
pub fn CAST_OR_CALL(a: anytype, b: anytype) switch (@typeInfo(@TypeOf(a))) {
|
||||
.Type => a,
|
||||
.Fn => |fn_info| fn_info.return_type orelse void,
|
||||
else => |info| @compileError("Unexpected argument type: " ++ @tagName(info)),
|
||||
} {
|
||||
switch (@typeInfo(@TypeOf(a))) {
|
||||
.Type => return cast(a, b),
|
||||
.Fn => return a(b),
|
||||
else => unreachable, // return type will be a compile error otherwise
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
test "Macro suffix functions" {
|
||||
@ -430,3 +444,41 @@ test "WL_CONTAINER_OF" {
|
||||
var ptr = Macros.WL_CONTAINER_OF(&x.b, &y, "b");
|
||||
try testing.expectEqual(&x, ptr);
|
||||
}
|
||||
|
||||
test "CAST_OR_CALL casting" {
|
||||
var arg = @as(c_int, 1000);
|
||||
var casted = Macros.CAST_OR_CALL(u8, arg);
|
||||
try testing.expectEqual(cast(u8, arg), casted);
|
||||
|
||||
const S = struct {
|
||||
x: u32 = 0,
|
||||
};
|
||||
var s = S{};
|
||||
var casted_ptr = Macros.CAST_OR_CALL(*u8, &s);
|
||||
try testing.expectEqual(cast(*u8, &s), casted_ptr);
|
||||
}
|
||||
|
||||
test "CAST_OR_CALL calling" {
|
||||
const Helper = struct {
|
||||
var last_val: bool = false;
|
||||
fn returnsVoid(val: bool) void {
|
||||
last_val = val;
|
||||
}
|
||||
fn returnsBool(f: f32) bool {
|
||||
return f > 0;
|
||||
}
|
||||
fn identity(self: c_uint) c_uint {
|
||||
return self;
|
||||
}
|
||||
};
|
||||
|
||||
Macros.CAST_OR_CALL(Helper.returnsVoid, true);
|
||||
try testing.expectEqual(true, Helper.last_val);
|
||||
Macros.CAST_OR_CALL(Helper.returnsVoid, false);
|
||||
try testing.expectEqual(false, Helper.last_val);
|
||||
|
||||
try testing.expectEqual(Helper.returnsBool(1), Macros.CAST_OR_CALL(Helper.returnsBool, @as(f32, 1)));
|
||||
try testing.expectEqual(Helper.returnsBool(-1), Macros.CAST_OR_CALL(Helper.returnsBool, @as(f32, -1)));
|
||||
|
||||
try testing.expectEqual(Helper.identity(@as(c_uint, 100)), Macros.CAST_OR_CALL(Helper.identity, @as(c_uint, 100)));
|
||||
}
|
||||
|
@ -4868,6 +4868,8 @@ const PatternList = struct {
|
||||
[2][]const u8{ "Ull_SUFFIX(X) (X ## Ull)", "ULL_SUFFIX" },
|
||||
[2][]const u8{ "ULL_SUFFIX(X) (X ## ULL)", "ULL_SUFFIX" },
|
||||
|
||||
[2][]const u8{ "CAST_OR_CALL(X, Y) (X)(Y)", "CAST_OR_CALL" },
|
||||
|
||||
[2][]const u8{
|
||||
\\wl_container_of(ptr, sample, member) \
|
||||
\\(__typeof__(sample))((char *)(ptr) - \
|
||||
@ -5048,6 +5050,7 @@ test "Macro matching" {
|
||||
, "WL_CONTAINER_OF");
|
||||
|
||||
try helper.checkMacro(allocator, pattern_list, "NO_MATCH(X, Y) (X + Y)", null);
|
||||
try helper.checkMacro(allocator, pattern_list, "CAST_OR_CALL(X, Y) (X)(Y)", "CAST_OR_CALL");
|
||||
}
|
||||
|
||||
const MacroCtx = struct {
|
||||
|
Loading…
Reference in New Issue
Block a user