Here’s a longer but hopefully more representative example:
using RuntimeGeneratedFunctions
RuntimeGeneratedFunctions.init(@__MODULE__)
function get_calc(mysetup::Expr, myalgo::Expr)::Expr
return :(
function calc(myinput::Float32)::Float32
# input always in v1
v1 = myinput
# init variables
$mysetup
# run calculation
$myalgo
# result always in v5
res = v5
return res
end
)
end
get_calc_func(calc_body) =
@RuntimeGeneratedFunction(@__MODULE__, calc_body, opaque_closures = false)
function find_calc()
bestres = typemin(Float32)
bestalgo::Expr = :()
mysetup = Vector{Expr}()
for _ in 1:10
expr_list = Vector{Expr}()
# without v1, which is input
for myvar in [:v2, :v3, :v4]
initval = rand(Float32)
ex = :($myvar = $initval)
push!(expr_list, ex)
end
# v5 is output
push!(expr_list, :(v5 = 0.0))
initvar_expr = quote end
initvar_expr.args = expr_list
push!(mysetup, initvar_expr)
end
myalgo = Vector{Expr}()
for _ in 1:100
algo_inst_list = Vector{Expr}()
algo_len = rand(3:10)
for _ in 1:algo_len
x = rand([:v1, :v2, :v3, :v4, :v5])
y = rand([:v1, :v2, :v3, :v4, :v5])
z = rand([:v1, :v2, :v3, :v4, :v5])
op = rand([:-, :+, :*, :/])
push!(algo_inst_list, :($x = $op($y, $z)))
end
algo_expr = quote end
algo_expr.args = algo_inst_list
push!(myalgo, algo_expr)
end
for setup_expr in mysetup
for algo_expr in myalgo
calc_body = get_calc(setup_expr, algo_expr)
mycalc_expr = get_calc_func(calc_body)
for myinput in range(-10, 10, step=50)
res = mycalc_expr(myinput)
if res > bestres
bestres = res
bestalgo = calc_body
end
end
end
end
return bestalgo, bestres
end
@time @info find_calc()