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

Attachment: signature.asc
Description: This is a digitally signed message part.

Reply via email to