Last active
September 11, 2022 18:29
-
-
Save Clemapfel/31c1c5bb485c27c9e646f2f7cf41cf57 to your computer and use it in GitHub Desktop.
Swizzling in Julia: Basic Mechanism
This file contains 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
# Basic mechanism for how to implement GLSL-like swizzling in Julia | |
mutable struct Vec2 | |
_private_00::Float32 | |
_private_01::Float32 | |
Vec2(x, y) = new(x, y) | |
end | |
function Base.getproperty(instance::Vec2, sym::Symbol) | |
# within this function we still somehow need to get the values of instances field. Using regular Julia syntax `.` | |
# would cause a stackoverflow error as `.` calls `getproperty` which is this function | |
# instead, we use the Julia C-Library to access the values | |
# at that point we simply need to parse the `sym` argument and return the correct value permutation | |
# this function is currently not type stable but with some more effort I feel like this is doable for | |
# all the glm vectors types without sacrificing performance at all | |
if sym == :_private_00 || sym == :_private_00 | |
# prevent users from messing with actual values | |
throw(ErrorException("type " * string(Vec2) * " has no field " * string(sym))) | |
else | |
x_ptr = ccall(:jl_get_nth_field, Ptr{Cvoid}, (Ptr{Cvoid}, Cint), pointer_from_objref(instance), 0) | |
y_ptr = ccall(:jl_get_nth_field, Ptr{Cvoid}, (Ptr{Cvoid}, Cint), pointer_from_objref(instance), 1) | |
x = ccall(:jl_unbox_float32, Float32, (Ptr{Cvoid},), x_ptr) | |
y = ccall(:jl_unbox_float32, Float32, (Ptr{Cvoid},), y_ptr) | |
if sym == :x return x | |
elseif sym == :y return y | |
elseif sym == :xy return Vec2(x, y) | |
elseif sym == :yx return Vec2(y, x) | |
elseif sym == :xx return Vec2(x, x) | |
elseif sym == :yy return Vec2(y, y) | |
else | |
# simulate the regular behavior of a non-overloaded Base.getproperty | |
throw(ErrorException("type " * string(Vec2) * " has no field " * string(sym))) | |
end | |
end | |
end | |
# usage | |
test = Vec2(1, 123) | |
println(test.yx) | |
# prints Vec2(123.0f0, 1.0f0) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment