Ale*_*kin 2 metaprogramming abstract-syntax-tree julia
朱莉娅手册指出:
每个Julia程序都以字符串开头:
Run Code Online (Sandbox Code Playgroud)julia> prog = "1 + 1" "1 + 1"
我可以很容易地获得简单表达式的AST,甚至可以在quote/ 的帮助下获得一个函数,如果我在字符串中包含表达式code_*,则可以使用Meta.parse/ Meta.show_sexpr。
问题:是否有办法获取编码的整个AST,可能包括几个原子表达式?像,读取源文件并将其转换为AST?
如果要使用Julia而不是FemtoLisp进行此操作,则可以执行
function parse_file(path::AbstractString)
code = read(path, String)
Meta.parse("begin $code end")
end
Run Code Online (Sandbox Code Playgroud)
这将采用一个文件路径,将其读取并解析为一个可以计算的大表达式。
这来自@NHDaly的答案,在这里:https ://stackoverflow.com/a/54317201/751061
如果您已经将文件作为字符串,并且不想再次读取,则可以执行
parse_all(code::AbstractString) = Meta.parse("begin $code end")
Run Code Online (Sandbox Code Playgroud)
Nathan Daly和Taine Zhao在Slack上指出,此代码不适用于模块:
julia> eval(parse_all("module M x = 1 end"))
ERROR: syntax: "module" expression not at top level
Stacktrace:
[1] top-level scope at REPL[50]:1
[2] eval at ./boot.jl:331 [inlined]
[3] eval(::Expr) at ./client.jl:449
[4] |>(::Expr, ::typeof(eval)) at ./operators.jl:823
[5] top-level scope at REPL[50]:1
Run Code Online (Sandbox Code Playgroud)
可以将其固定如下:
julia> eval_all(ex::Expr) = ex.head == :block ? for e in ex eval_all(e) end : eval(e);
julia> eval_all(ex::Expr) = ex.head == :block ? eval.(ex.args) : eval(e);
julia> eval_all(parse_all("module M x = 1 end"));
julia> M.x
1
Run Code Online (Sandbox Code Playgroud)
由于提问者不相信上面的代码会产生一棵树,因此这是的输出的图形表示形式parse_all,清楚地显示了树结构。
如果您感到好奇,则标记的那些叶子#= none:1 =#是行号节点,指示每个后面的表达式所在的行。
正如评论中所建议的,默认情况下,也可以Meta.show_sexpr将一个Expr对象应用于一个对象,以获取AST的更多“轻快”表示,而无需执行所有漂亮的打印julia操作:
julia> (Meta.show_sexpr ? Meta.parse)("begin x = 1\n y = 2\n z = ?(x^2 + y^2)\n end")
(:block,
:(#= none:1 =#),
(:(=), :x, 1),
:(#= none:2 =#),
(:(=), :y, 2),
:(#= none:3 =#),
(:(=), :z, (:call, :?, (:call, :+, (:call, :^, :x, 2), (:call, :^, :y, 2))))
)
Run Code Online (Sandbox Code Playgroud)