Julia 的宏可以访问嵌套函数吗?

Can Julia's macros access nested functions?

我正在研究 Julia 的宏。我特别好奇的一件事是无需完全编译代码即可提取函数的可访问调用图的能力。 'reachable call graph' 是指在函数体内找到的所有可能可达的函数,以及这些函数中的函数,等等。

例如:

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

这非常简陋,但能够在解析时访问调用图,即使仅就潜在可访问的函数而言,对我正在尝试做的事情也非常有用。如果我必须完全编译代码才能使类似的东西工作,那将大大抵消它的好处。

这样的事情可能吗?

@code_lowered 可能有用:

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
)

要获得函数调用,您可以这样做:

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