Function that creates generated function using interpolation?

Here is another challenge:

Thanks for your help. You actually somewhat predicted my next goal, but I wanted something different:

hdf(expr,p::Int) = horner(df(expr,:x,p))
function genfun(fun::Symbol,expr;depth=-1)
    if depth < 0
        @eval begin 
            @generated function $fun(x,::Val{p}) where p
                expr = $(Expr(:quote,expr))
                :(@fastmath $(horner(df(expr,:x,p))))
            end
            $fun(x,p::Int) = $fun(x,Val(p))
        end
    else
        lexpr = [Expr(:quote,hdf(expr,i)) for i ∈ 0:depth-1]
        @eval begin
            N = 1+$depth
            expr = $lexpr
            function $fun(x,p)
                macroexpand(quote
                    Base.Cartesian.@nif($N,
                        i->(i-1 == p),
                        i->($(:(expr[i]))),
                        i->throw(error("$(p)-th derivative not supported")))
                end)
            end
        end
    end
end

So the purpose of this function is that you can either make a generated function that evaluates derivatives up to arbitrary depth by default (with slower performance), but one should have the option of specifying a depth limit, which should then produce a plain function that uses the if-then-else structure.

julia> genfun(:fa,:(x^2))
fa (generic function with 2 methods)

julia> fa(2,0)
4

So the generated function now works properly. However, producing the right kind of if-then-else plain function for faster performance requires the expr[i] derivatives to be inserted in each conditional.

In order to help debug this, the produced function outputs the if-then-else code instead of evaluating:

julia> genfun(:fb,:(x^2);depth=2)
fb (generic function with 1 method)

julia> fb(2,0)
quote  # REPL[211], line 17:
    if 0 == p
        expr[1]
    else 
        if 1 == p
            expr[2]
        else 
            throw(error("$(p)-th derivative not supported"))
        end
    end
end

If someone could figure out how to insert / interpolate expr[i] into that, I would be very thankful.

Otherwise, instead of using Base.Cartesian.@nif, a new function needs to take care of it.