Last active
January 6, 2018 21:44
-
-
Save simonbyrne/8194a2134f08d41af6c0ea2d65999c95 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# To ensure correct alignment (e.g. for an 80-bit type) | |
struct StrWrap{T} | |
value::T | |
end | |
function unsafe_reinterpret(T, a::A) where {A} | |
if sizeof(T) <= sizeof(A) | |
r = Ref(a) | |
Base.@gc_preserve r begin | |
u = convert(Ptr{T}, Base.unsafe_convert(Ptr{A}, r)) | |
unsafe_load(u) | |
end | |
else | |
s = Ref{T}() | |
Base.@gc_preserve s begin | |
v = convert(Ptr{A}, Base.unsafe_convert(Ptr{T}, s)) | |
unsafe_store!(v, a) | |
end | |
s[] | |
end | |
end | |
decl!(dict, expr::LineNumberNode) = nothing | |
function decl!(dict, expr::Expr) | |
if expr.head == :block | |
for a in expr.args | |
decl!(dict, a) | |
end | |
elseif expr.head == :(::) | |
dict[expr.args[1]] = expr.args[2] | |
else | |
error("Invalid expression") | |
end | |
end | |
macro Cunion(name, expr) | |
d = Dict{Symbol, Any}() | |
decl!(d, expr) | |
maxsize = maximum(T -> eval(__module__, :(sizeof(StrWrap{$T})*8)), values(d)) | |
defs = quote end | |
lookup = :(getfield(obj, field)) | |
for (k,T) in d | |
lookup = :(field == $(QuoteNode(k)) ? unsafe_reinterpret($(esc(T)), obj) : $lookup) | |
push!(defs.args, :($(esc(name))(x::NamedTuple{($(QuoteNode(k)),),Tuple{$(esc(T))}}) = unsafe_reinterpret($(esc(name)), x.$k) )) | |
end | |
quote | |
primitive type $(esc(name)) $maxsize | |
end | |
$(esc(name))(;kwargs...) = $(esc(name))(kwargs.data) | |
$defs | |
function Base.getproperty(obj::$(esc(name)), field::Symbol) | |
$lookup | |
end | |
end | |
end | |
@Cunion Foo begin | |
a::Int64 | |
b::Float64 | |
end | |
u = Foo(a=1) | |
u.b | |
@Cunion Bar begin | |
a::Int64 | |
b::NTuple{10,UInt8} | |
end | |
v = Bar(a=1) | |
v.b |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment