Hi there, stoked to be finally be using Julia. I had a question regarding how powerful Julia’s macros can be. I already asked on Stack Overflow, but figured worth pinging here as well.
Basically, I was wondering if it was possible to extract a function’s reachable call graph without fully compiling the code, i.e. with macros. By ‘reachable call graph’, I mean all of the functions (more generally, functors) found in the body of the function that are potentially reachable, and the functions/functors in the bodies of those, and so on. This would be much easier if macros can recurse into the functors found in the caller’s body.
Some code might demonstrate this idea better:
do_something(x::Int) = println(x*2)
do_something(x::String) = println(x)
function foo(a, b)::Bool
do_something_with(a)
do_something_with(b)
return true
end
# Ideally something like this would be accessible from Base
functions_in_codebase = [:do_something, :foo]
# Not correct, but gets the idea across
macro access_call_graph(f)
tokens = f.text.tokens
graph = [f]
for t in tokens
go_deeper = t in functions_in_codebase
!go_deeper && append!(graph, access_call_graph(get_function_for(t))...)
end
return graph
end
@access_call_graph(foo)
# Should get something like the following, nesting notwithstanding:
# foo
# do_something, do_something
If you can access any kind of call-graph at parse-time, you could use this information to compute the intersection of a Git diff’s changed/modified functions and the union of its call graphs with those of tests, thus allowing automatic filtering and only running tests that are functionally affected by your change. Something that achieves the same as what Mozilla did with Firefox. Instead of ML however we’d be leveraging the expressiveness of Julia itself
I am aware this sounds like the ramblings of a mad lunatic and just the issue of multiple dispatch alone is terrifying but I’d love to know if something like this could conceivably work.