Why is usage of llvmcall so restricted?

I think I would try the recommended DynamicExpressions.jl first, as that looks pretty powerful and ergonomic.

But if the above solutions don’t work for you, you can also consider FunctionWrappers.jl.

julia> using FunctionWrappers: FunctionWrapper

julia> plus_f64 = FunctionWrapper{Float64, Tuple{Float64, Float64}}(+);

julia> times_f64 = FunctionWrapper{Float64, Tuple{Float64, Float64}}(*);

julia> typeof(+) == typeof(*)
false

julia> typeof(plus_f64) == typeof(times_f64)
true

julia> plus_f64(3.0, 4.0), times_f64(3.0, 4.0)
(7.0, 12.0)

FunctionWrappers lets you make the type of functions based entirely on their (concrete) input/output types, rather than the function itself. This way, you can store and call many functions in a stable way. With that, you should be able to write code to assemble and evaluate runtime expressions while avoiding eval or even dynamic dispatch.

3 Likes