Skip to content

Instantly share code, notes, and snippets.

@davidagold
Last active Aug 29, 2015
Embed
What would you like to do?
Merge two functions from different modules
function metamerge(f::Function, modulef::Module, g::Function, moduleg::Module, h::Function)
# Generate arrays of Method objects for f, g
const fmethods = methods(f, (Any...))
const gmethods = methods(g, (Any...))
# println(gmethods)
# Generate arrays of method signatures for f, g.
# Note that the 'sig' field of a Method is a tuple of types.
const fsigs = [ fmethods[i].sig for i in 1:length(fmethods) ]
const gsigs = [ gmethods[i].sig for i in 1:length(gmethods) ]
# Loop through elements of fsigs and assign appropriate methods of f to h
for (i, sig) in enumerate(fsigs)
# println(sig)
makemethod(h, f, sig, symbol("$modulef"))
end
# Loop through elements of fsigs and assign appropriate methods of g to h
for (i, sig) in enumerate(gsigs)
# println(sig)
makemethod(h, g, sig, symbol("$moduleg"))
end
return h
end
function makemethod(newf::Function, oldf::Function, argtypes::Tuple, modulename::Symbol)
# Note that passing a value such as 'A.f' to makemethod() will drop the module
# from the function name. We must therefore add it to the expression passed to
# RHS (below):
exoldf = Expr(:., modulename, QuoteNode(symbol("$oldf")))
# Expression calling 'newf'
LHS = Expr(:call, symbol("$newf"))
# Expression calling 'oldf' with proper module prefix
RHS = Expr(:call, exoldf)
# Adds argument symbols with type annotations to signature of call to 'newf'
# Adds just argument symbols to call of 'oldf'
for (i, arg) in enumerate(argtypes)
push!(LHS.args, Expr(:(::), symbol("x$i"), arg))
push!(RHS.args, symbol("x$i"))
end
# println(LHS)
# println(RHS)
# Sets the calls of 'newf' and 'oldf' equal to one another and evaluates.
exeq = Expr(:(=), LHS, RHS)
@eval($exeq)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment