Skip to content

Instantly share code, notes, and snippets.

@tauoverpi
Created August 2, 2022 16:42
Show Gist options
  • Save tauoverpi/e8fc90d44659d86a0ac25dc7fb1081bc to your computer and use it in GitHub Desktop.
Save tauoverpi/e8fc90d44659d86a0ac25dc7fb1081bc to your computer and use it in GitHub Desktop.
.Pointer needs to go
// https://github.com/ziglang/zig/issues/10710#issue-1116978295
const std = @import("std");
const assert = std.debug.assert;
const TypeInfo = std.builtin.TypeInfo;
pub fn Type(comptime T: TypeInfo) type {
return comptime switch (T) {
// but what is the type of type?
.Type => type,
// won't work as the result is memoized :(
.Opaque => opaque {},
// the awkward
.Struct => @Type(T),
.Union => @Type(T),
.Enum => @Type(T),
.Int => @Type(T),
.Fn => @Type(T),
.Frame => |info| @Frame(info.function), // ???
.ErrorSet => @Type(T), // sad:
.BoundFn => @compileError("not loved anymore"),
// the good stuff
.Optional => |info| ?info.child,
.AnyFrame => anyframe,
.ComptimeFloat => comptime_float,
.ComptimeInt => comptime_int,
.Void => void,
.Bool => bool,
.NoReturn => noreturn,
.Undefined => @TypeOf(undefined),
.Null => @TypeOf(null),
.EnumLiteral => @TypeOf(.magic),
.Vector => |info| @Vector(info.len, info.child),
.ErrorUnion => |info| info.error_set!info.payload,
// :sad .ErrorSet => |info| @typeInfo(@TypeOf(hack(info orelse return error{}))).ErrorUnion.error_set,
// cute
.Array => |info| if (info.sentinel) |sentinel|
[info.len:@ptrCast(*const info.child, sentinel).*]info.child
else
[info.len]info.child,
.Float => |info| switch (info.bits) {
16 => f16,
32 => f32,
64 => f64,
80 => f80,
128 => f128,
else => @compileError("mate"),
},
// well, it's not that bad
.Pointer => |info| {
const pattern = //
@as(u3, @boolToInt(info.is_volatile)) << 2 |
@as(u3, @boolToInt(info.is_allowzero)) << 1 |
@as(u3, @boolToInt(info.is_const));
switch (info.size) {
.One => return switch (pattern) {
0b111 => *allowzero align(info.alignment) addrspace(info.address_space) const volatile info.child,
0b011 => *allowzero align(info.alignment) addrspace(info.address_space) const info.child,
0b101 => *align(info.alignment) addrspace(info.address_space) const volatile info.child,
0b001 => *align(info.alignment) addrspace(info.address_space) const info.child,
0b110 => *allowzero align(info.alignment) addrspace(info.address_space) volatile info.child,
0b010 => *allowzero align(info.alignment) addrspace(info.address_space) info.child,
0b100 => *align(info.alignment) addrspace(info.address_space) volatile info.child,
0b000 => *align(info.alignment) addrspace(info.address_space) info.child,
},
.Many => {
if (info.sentinel) |tmp| {
const sentinel = @ptrCast(*const info.child, tmp).*;
return switch (pattern) {
0b111 => [*:sentinel]allowzero align(info.alignment) addrspace(info.address_space) const volatile info.child,
0b011 => [*:sentinel]allowzero align(info.alignment) addrspace(info.address_space) const info.child,
0b101 => [*:sentinel]align(info.alignment) addrspace(info.address_space) const volatile info.child,
0b001 => [*:sentinel]align(info.alignment) addrspace(info.address_space) const info.child,
0b110 => [*:sentinel]allowzero align(info.alignment) addrspace(info.address_space) volatile info.child,
0b010 => [*:sentinel]allowzero align(info.alignment) addrspace(info.address_space) info.child,
0b100 => [*:sentinel]align(info.alignment) addrspace(info.address_space) volatile info.child,
0b000 => [*:sentinel]align(info.alignment) addrspace(info.address_space) info.child,
};
} else {
return switch (pattern) {
0b111 => [*]allowzero align(info.alignment) addrspace(info.address_space) const volatile info.child,
0b011 => [*]allowzero align(info.alignment) addrspace(info.address_space) const info.child,
0b101 => [*]align(info.alignment) addrspace(info.address_space) const volatile info.child,
0b001 => [*]align(info.alignment) addrspace(info.address_space) const info.child,
0b110 => [*]allowzero align(info.alignment) addrspace(info.address_space) volatile info.child,
0b010 => [*]allowzero align(info.alignment) addrspace(info.address_space) info.child,
0b100 => [*]align(info.alignment) addrspace(info.address_space) volatile info.child,
0b000 => [*]align(info.alignment) addrspace(info.address_space) info.child,
};
}
},
.Slice => {
if (info.sentinel) |tmp| {
const sentinel = @ptrCast(*const info.child, tmp).*;
return switch (pattern) {
0b111 => [:sentinel]allowzero align(info.alignment) addrspace(info.address_space) const volatile info.child,
0b011 => [:sentinel]allowzero align(info.alignment) addrspace(info.address_space) const info.child,
0b101 => [:sentinel]align(info.alignment) addrspace(info.address_space) const volatile info.child,
0b001 => [:sentinel]align(info.alignment) addrspace(info.address_space) const info.child,
0b110 => [:sentinel]allowzero align(info.alignment) addrspace(info.address_space) volatile info.child,
0b010 => [:sentinel]allowzero align(info.alignment) addrspace(info.address_space) info.child,
0b100 => [:sentinel]align(info.alignment) addrspace(info.address_space) volatile info.child,
0b000 => [:sentinel]align(info.alignment) addrspace(info.address_space) info.child,
};
} else {
return switch (pattern) {
0b111 => []allowzero align(info.alignment) addrspace(info.address_space) const volatile info.child,
0b011 => []allowzero align(info.alignment) addrspace(info.address_space) const info.child,
0b101 => []align(info.alignment) addrspace(info.address_space) const volatile info.child,
0b001 => []align(info.alignment) addrspace(info.address_space) const info.child,
0b110 => []allowzero align(info.alignment) addrspace(info.address_space) volatile info.child,
0b010 => []allowzero align(info.alignment) addrspace(info.address_space) info.child,
0b100 => []align(info.alignment) addrspace(info.address_space) volatile info.child,
0b000 => []align(info.alignment) addrspace(info.address_space) info.child,
};
}
},
.C => return switch (pattern) {
0b101 => [*c]align(info.alignment) addrspace(info.address_space) const volatile info.child,
0b001 => [*c]align(info.alignment) addrspace(info.address_space) const info.child,
0b100 => [*c]align(info.alignment) addrspace(info.address_space) volatile info.child,
0b000 => [*c]align(info.alignment) addrspace(info.address_space) info.child,
else => unreachable, // I can't be bothered to fix this
},
}
},
};
}
fn hack(comptime errors: []const TypeInfo.Error) !void {
var x = false;
inline for (errors) |err| {
if (x) return @field(anyerror, err.name); // sue me
}
}
test {
const everything = *allowzero align(32) addrspace(.generic) const volatile u8;
const shorttype = [*:32]allowzero align(32) addrspace(.generic) const volatile u32;
comptime assert(Type(@typeInfo(everything)) == everything);
comptime assert(Type(@typeInfo(shorttype)) == shorttype);
comptime assert(*const u8 == Type(@typeInfo(*const u8)));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment