My goal is to create a macro that takes an arbitrary function and adds additional arguments and changes the docstring.
For example, say I define the following function:
"This is my function"
function f(a, b; x=1.0, y=1.0)
return a + b + x + y
end
And now assume I’d also like to define the following augmented function (where the extra arguments c
and d
have been added:
"This is my augmented function"
function f(a, b, c, d; x=1.0, y=1.0)
return f(a, b; x=x, y=y) + c + d
end
I would like to create a macro that can define an augmented function automatically. Ideally, I would just write:
@augment begin
"This is my function"
function f(a, b; x=1.0, y=1.0)
return a + b + x + y
end
end
and this would define the original function and augmented function to use.
So far I have tried using MacroTools.jl as follows:
using MacroTools
macro augment(expr)
# Evaluate original function expression
func = eval(expr)
# Split function definition into dictionaries
func_dict = MacroTools.splitdef(expr)
new_dict = deepcopy(func_dict)
# Change new function bodies
new_dict[:body] = :($func($(func_dict[:args]...); $(func_dict[:kwargs]...)) + c + d)
# Change new function Arguments
push!(new_dict[:args], :c, :d)
# Convert back to expressions and evaluate
eval(MacroTools.combinedef(new_dict))
return nothing
end
The above code successfully augments functions with c
and d
arguments, however, there are two problems. Firstly, the keyword arguments in the augmented function are always set to their default value, such that calling f(1, 2, 3, 4; x=5, y=6)
acutally calls f(1, 2, 3, 4; x=1.0, y=1.0)
. Secondly, the @augment
macro above does not handle the docstring conversion. As soon as I enter a doctring to the function, the MacroTools.splitdef(expr)
fails.
This task is proving quite difficult to me so any help is appreciated.