【发布时间】:2015-07-03 19:40:30
【问题描述】:
如何访问 Julia 中泛型函数的抽象语法树?
【问题讨论】:
标签: julia
如何访问 Julia 中泛型函数的抽象语法树?
【问题讨论】:
标签: julia
回顾一下:看起来 Simon 正在寻找与泛型函数关联的特定方法的 AST。我们可以得到一个LambdaStaticData对象,其中包含AST,具体方法如下:
julia> f(x,y)=x+y
julia> f0 = methods(f, (Any, Any))[1]
((Any,Any),(),AST(:($(expr(:lambda, {x, y}, {{}, {{x, Any, 0}, {y, Any, 0}}, {}}, quote # none, line 1:
return +(x,y)
end)))),())
julia> f0[3]
AST(:($(expr(:lambda, {x, y}, {{}, {{x, Any, 0}, {y, Any, 0}}, {}}, quote # none, line 1:
return +(x,y)
end))))
julia> typeof(ans)
LambdaStaticData
显然这个 AST 可以是一个 Expr 对象,也可以是一个压缩的 AST 对象,表示为一个字节序列:
julia> typeof(f0[3].ast)
Array{Uint8,1}
来自base/show.jl 的LambdaStaticData 的show() 方法说明了遇到此问题时如何解压缩:
julia> ccall(:jl_uncompress_ast, Any, (Any, Any), f0[3], f0[3].ast)
:($(expr(:lambda, {x, y}, {{}, {{x, Any, 0}, {y, Any, 0}}, {}}, quote # none, line 1:
return +(x,y)
end)))
julia> typeof(ans)
Expr
【讨论】:
Julia 有四个函数和四个与这些函数类似的宏,用于检查很多关于泛型函数的方法:
julia> f(x, y) = x + y
f (generic function with 1 method)
julia> methods(f)
# 1 method for generic function "f":
f(x,y) at none:1
julia> code_lowered(f, (Int, Int))
1-element Array{Any,1}:
:($(Expr(:lambda, {:x,:y}, {{},{{:x,:Any,0},{:y,:Any,0}},{}}, :(begin # none, line 1:
return x + y
end))))
julia> @code_lowered f(1, 1) # Both `Int`s
...same output.
julia> code_typed(f, (Int, Int))
1-element Array{Any,1}:
:($(Expr(:lambda, {:x,:y}, {{},{{:x,Int64,0},{:y,Int64,0}},{}}, :(begin # none, line 1:
return (top(box))(Int64,(top(add_int))(x::Int64,y::Int64))::Int64
end::Int64))))
julia> @code_lowered f(1, 1) # Both `Int`s
...same output.
julia> code_llvm(f, (Int, Int))
define i64 @julia_f_24771(i64, i64) {
top:
%2 = add i64 %1, %0, !dbg !1014
ret i64 %2, !dbg !1014
}
julia> @code_llvm f(1, 1) # Both `Int`s
...same output.
julia> code_native(f, (Int, Int))
.text
Filename: none
Source line: 1
push RBP
mov RBP, RSP
Source line: 1
add RDI, RSI
mov RAX, RDI
pop RBP
ret
julia> @code_llvm f(1, 1) # Both `Int`s
...same output.
julia> @code_warntype f(1, 1)
Variables:
x::Int64
y::Int64
Body:
begin # In[17], line 1:
return (top(box))(Int64,(top(add_int))(x::Int64,y::Int64))
end::Int64
【讨论】:
由于多次分派,我不确定是否存在与通用函数关联的 AST。如果您正在编写函数定义fbody,您应该能够通过执行dump(quote(fbody)) 来获取AST。
【讨论】:
methods(f,signature)找到具体的方法。然而,其中的 AST 是 Uint8 Array,而不是 Expr 对象。关于如何转换它的任何想法?
dump(quote f end) 得到结果吗?它返回 Nothing 但会打印出我感兴趣的 AST。
quote f end 已经是 AST。 dump 只是漂亮地打印出来。