On 2014年12月19日 星期五 04:38:50, Jameson Nash <[email protected]> wrote: > The lowered AST is what you get when you call expand on any other AST. It > is a simplified format that is easier to analyze, type-infer, and execute. > However, it is still a regular AST object, so you can modify it and > recreate another function with it just like the pre-expanded version (in > fact, this is what inference.jl does). The first few arrays in the lambda > provide information to the compiler. The first is the argument list. The > next is a list of (local variables list, variable info, captured variable > list)
So does it mean that .args[2] of the AST can be ignored when recompiling the
function and it will be automatically generated again (which I assume is what
you did below)? I guess what confuses me is that I've tried to just eval the
AST but it basically constructs a function that returnes the "useless"
args[2].
```
julia> eval(Base.uncompressed_ast((() -> ()).code))()
3-element Array{Any,1}:
Any[]
Any[]
Any[]
```
>
> The problem with your code is that you are trying to mutate internal
> compiler state, and it has no idea that you are trying to do so. It has
> already optimized the call for that function, and no longer cares about the
> code.ast field for that lambda. What you really want is a new function
> entirely:
I C.
>
> julia> function recompile(func1, func2, args)
> code1 = get_code(func1, args)
> code2 = get_code(func2, args)
>
> @assert code1.module == code2.module
>
> eval_code1 = code1.module.eval(code1)
> eval_res1 = eval_code1(args...)
> @assert eval_res1 == func1(args...)
> println("eval_code: $(eval_res1)")
>
> eval_code2 = code2.module.eval(code2)
> eval_res2 = eval_code2(args...)
> @assert eval_res2 == func2(args...)
> println("eval_code: $(eval_res2)")
>
> ast1 = ccall(:jl_uncompress_ast, Any, (Any, Any), code1,
> code1.ast) println("ast1: $(ast1.args[3])")
>
> ast2 = ccall(:jl_uncompress_ast, Any, (Any, Any), code2,
> code2.ast)
>
> code3 = Expr(:function, Expr(:tuple, ast2.args[1]...),
> Expr(:block, ast2.args[3].args...))
> # what did we construct? how does it compare to `:(
> function(a,b) a+b end )|>dump`?
> # dump(code3); Meta.show_sexpr(code3); println()
> eval_new_code = code1.module.eval(code3)
> eval_new_res = eval_new_code(args...)
>
> @assert eval_new_res == func2(args...)
> println("eval_new_code: $(eval_new_res)")
> end
> recompile (generic function with 1 method)
>
> julia> recompile(+, -, (1.2, 3.4))
> eval_code: 4.6
> eval_code: -2.2
> ast1: begin # float.jl, line 192:
> return box(Float64,sub_float(unbox(Float64,x),unbox(Float64,y)))
> end
> Expr
> head: Symbol function
> args: Array(Any,(2,))
> 1: Expr
> head: Symbol tuple
> args: Array(Any,(2,))
> 1: Symbol x
> 2: Symbol y
> typ: Any
> 2: Expr
> head: Symbol block
> args: Array(Any,(2,))
> 1: Expr
> head: Symbol line
> args: Array(Any,(2,))
> typ: Any
> 2: Expr
> head: Symbol return
> args: Array(Any,(1,))
> typ: Any
> typ: Any
> typ: Any
> (:function, (:tuple, :x, :y), (:block,
> (:line, 192, symbol("float.jl")),
> (:return, (:call, :box, :Float64, (:call, :sub_float, (:call,
>
> :unbox, :Float64, :x), (:call, :unbox, :Float64, :y))))
>
> ))
> eval_new_code: -2.2
Thank you very much.
Yichao Yu
>
> On Thu Dec 18 2014 at 1:14:32 PM Yichao Yu <[email protected]> wrote:
>
> Hi,
>
> > I'm wondering if there's a way to recompile the lowered AST back into a
> > function and what additional information (other than the module it should
> > be
> > evaluate in) is necessary to do that what I've tried and would like to do
> > is
> > demonstrated with the code attached. The idea is that I would like to
> > modify
> > the code of a function/method before calling it (in this case, I am
> > replacing
> > it with the code from another function with the same signature). (In
> > another
> > word, the question is how to construct a function from code1 with ast2 and
> > run
> > it.)
> >
> > It will also be nice if there's more documentation on this "lowered AST"
> > since
> > it seems to be very different form the one you get in a function
> > definition.
> > (e.g. what is the array in `code_lowered(+, (Float64,
> > Float64))[1].args[2]`
> > mean)
> >
> > A brief description of what I want to do. I'm writing a control system
> > with
> > dynamic logic. However, since the code might not be running on a single
> > host,
> > it is hard to use an existing interpreter to do what I want. Trying to
> > avoid
> > inventing yet another language, I hope to use a subset of an existing
> > language
> > and somehow transform it into a representation that can be run somewhere
> > else
> > and it seems that the inspection and meta programming feature in julia is
> > very
> > useful for this. It might be possible to just apply a macro to every
> > function
> > / method definition but it will be much harder to write. I would rather
> > try to
> > "trace" the excution and use the AST acquired at runtime. For that I would
> > like to know more about the lowered AST and possibly how to execute a
> > modified
> > version in order to trace recursive / nested function calls. This might
> > not be
> > the best way to do it and I'm still in planning stage so any suggestions
> > on
> > the design is also welcome.
> >
> > Cheers,
> >
> > Yichao Yu
>
>
ff
signature.asc
Description: This is a digitally signed message part.
