Daniel Soutar
Daniel Soutar

Reputation: 886

Can Julia's macros access nested functions?

I am playing around with Julia's macros. One thing I am particularly curious about is the ability to extract a function's reachable call graph without having to fully compile the code. By 'reachable call graph', I mean all of the functions found inside the body of a function that are potentially reachable, and the functions in those functions, and so on.

For example:

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

This is pretty janky, but being able to access the call graph at parse-time, even if only in terms of potentially reachable functions, would be extremely useful for what I'm trying to do. If I have to fully compile the code in order for something like this to work, that would largely defeat the benefit.

Is something like this possible?

Upvotes: 3

Views: 97

Answers (1)

Przemyslaw Szufel
Przemyslaw Szufel

Reputation: 42214

@code_lowered could be useful:

julia> code = @code_lowered foo(1,"2")
CodeInfo(
1 ─ %1 = Main.Bool
│        Main.do_something_with(a)
│        Main.do_something_with(b)
│   %4 = Base.convert(%1, true)
│   %5 = Core.typeassert(%4, %1)
└──      return %5
)

To get function calls you could do:

julia> code.first.code
5-element Vector{Any}:
 :(Main.do_something_with)
 :((%1)(_2))
 :(Main.do_something_with)
 :((%3)(_3))
 :(return true)

Upvotes: 3

Related Questions