JuliaDebug / JuliaInterpreter.jl

Interpreter for Julia code
Other
163 stars 35 forks source link

@interpreter^2 fails #228

Open KristofferC opened 5 years ago

KristofferC commented 5 years ago

Would be cool if this would work:

julia> f() = @interpret 1+1
f (generic function with 1 method)

julia> @interpret f()
ERROR: TypeError: in typeassert, expected JuliaInterpreter.FrameData, got Nothing
Stacktrace:
 [1] maybe_evaluate_builtin(::Frame, ::Expr, ::Bool) at C:\Users\Kristoffer\.julia\packages\JuliaInterpreter\ZrOBa\src\builtins-julia1.1.jl:162
 [2] #evaluate_call_recurse!#37(::Bool, ::Function, ::Any, ::Frame, ::Expr) at C:\Users\Kristoffer\.julia\packages\JuliaInterpreter\ZrOBa\src\interpret.jl:208
 [3] evaluate_call_recurse! at C:\Users\Kristoffer\.julia\packages\JuliaInterpreter\ZrOBa\src\interpret.jl:205 [inlined]
 [4] eval_rhs(::Any, ::Frame, ::Expr) at C:\Users\Kristoffer\.julia\packages\JuliaInterpreter\ZrOBa\src\interpret.jl:371
 [5] step_expr!(::Any, ::Frame, ::Any, ::Bool) at C:\Users\Kristoffer\.julia\packages\JuliaInterpreter\ZrOBa\src\interpret.jl:504
...

Might be problematic with our globals and so on.

KristofferC commented 5 years ago

This now works if we disable recycle:

julia> f() = @interpret 1+1
f (generic function with 1 method)

julia> @interpret f()
2

If I add it back (note that I run the check to see that we are not double adding a FrameData):

julia> JuliaInterpreter.debug_recycle[] = true;

julia> @interpret f()
ERROR: add_int: types of a and b must match
Stacktrace:
 [1] #evaluate_call_recurse!#37(::Bool, ::Function, ::Any, ::Frame, ::Expr) at C:\Users\Kristoffer\Debugging\JuliaInterpreter\src\interpret.jl:216
 [2] evaluate_call_recurse! at C:\Users\Kristoffer\Debugging\JuliaInterpreter\src\interpret.jl:205 [inlined]
 [3] eval_rhs(::Any, ::Frame, ::Expr) at C:\Users\Kristoffer\Debugging\JuliaInterpreter\src\interpret.jl:371

We have some kind of corruption because the value of a here is the frame itself which likely comes from the outer @interpret call. So I'm guessing the recycles from the other and inner interpretation are fighting with each other somehow. Cool that it is possible to do @interpret^2 now though.

Edit: Changing f() to @interpret sin(2.0) and it starts to fail.

KristofferC commented 5 years ago

Here is a MWE of an error (with recycle disabled):

struct S
    a::Float64
end
f() = @interpret S(1.0)
julia> f()
S(1.0)

julia> @interpret f()
S(0.0)
KristofferC commented 5 years ago

For anyone that would like to debug the nested interpretation and want to keep your sanity. Duplicate JuliaInterpreter into a new package (JuliaInterpreter2) and do something like

f() = JuliaInterpreter2.@interpret
@interpret f()

Otherwise you don't know which print statements comes from the innner or outer interpretation etc...

KristofferC commented 5 years ago

I think there might be confusion with SSAValues from the outer interpreter getting mixed with SSAValues of the inner interpreter. Presumably, we would need some "tagging" system to tag SSAVaulues from differents nesting level of interpretation.

projekter commented 3 months ago

Would it be possible to have some flag to tell JuliaInterpreter to simply ignore any nested interpretation (maybe this is already what you had in mind here, though I interpreted this issue more as "allow the interpreter to interpret itself")? The use case for this is that I have a testsuite with very large autogenerated functions - but they are actually quite primitive, just a huge if/ifelse block and very few instructions per condition. So the interpretation of this function is extremely fast, while compilation takes a lot of time (minutes). Hence, I wrap the functions (which are callback containing the tests) in an outer call that just interprets them. However, when I now want to debug the call of the callback, this is of course quite impossible. So remove the @interpret again. And don't forget not to call the function without debugger... If there was some flag similar to the compiled methods that would allow to disable nested interpretation (which could then be integrated into julia-vscode), this would be great. Or perhaps even adding a magic handling of JuliaInterpreter.@interpret to the compiled methods?