-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[FR] Release schedule for debugger #257
Comments
I have a working implementation in JunoLab/Atom.jl#138 with a couple of todos left.
Right now I'm using Debugger.jl directly, mostly because I want to steal the REPL mode and things like that. :) |
Do you gain a lot by using Debugger.jl? It would be nice from a Debugger.jl's point of view if the only exported feature would be the REPL interface. Otherwise we need to be very careful not to break the Juno debugger just by changing internals of Debugger.jl |
Right now not really, no, but as I said, I did plan on stealing the REPL as a fallback for code without lineinfo, if that makes sense? I do see the appeal of not having to worry about Juno digging into Debugger's internals :) |
Example? |
JuliaDebug/Debugger.jl#21, but I'm not sure if something like that is still likely to happen -- to be fair I never encountered that situation, so maybe should deal with it when it comes up. |
One option is to rely on Revise + CodeTracking, for which julia> using Debugger
julia> @enter floor(missing)
In floor(#temp#, digits, base) at missing.jl
112 ($f)(::Missing, digits::Integer=0, base::Integer=0) = missing
113 ($f)(::Type{>:Missing}, ::Missing) = missing
114 ($f)(::Type{T}, ::Missing) where {T} =
115 throw(MissingException("cannot convert a missing value to type $T: use Union{$T, Missing} instead"))
116 ($f)(::Type{T}, x::Any) where {T>:Missing} = $f(nonmissingtype(T), x) vs julia> using Rebugger
interpret> floor(missing)[ Info: tracking Base # I hit meta-i here
floor(::Missing) in Base at missing.jl:112
#temp# = missing
112 floor(::Missing, digits::Integer=0, base::Integer=0) = begin
112 missing
end Obviously this can't work for |
In JuliaDebug/Debugger.jl#21 I'm guessing Zygote builds methods by expression, e.g., julia> ex = :(f(x) = convert(UInt, x))
:(f(x) = begin
#= REPL[11]:1 =#
convert(UInt, x)
end)
julia> popfirst!(ex.args[2].args)
:(#= REPL[11]:1 =#)
julia> eval(ex)
f (generic function with 1 method)
julia> using Debugger
julia> @enter f(1)
In f(x) at none
1 1 ─ %1 = (convert)(UInt64, x)
2 └── return %1
About to run: (convert)(UInt64, 1)
1|debug> So yes, you'd sacrifice that, but I'm not sure Juno expects to display lowered code in one of its editing windows? It would seem OK for Juno to rely on source text. Probably you shouldn't display expressions either, so I don't think you need to worry about such "fancy" cases. |
Right, finding the expression is possible, but I'm not sure how to best expose that to the user considering we don't really have a file to show a stepper in. One thing I'm not sure about is how to best handle breakpoints -- the expected workflow probably is to just click a line number in an arbitrary file (and that's it). AFAICT that means that Juno will need to call
might happen. Tracking an individual file doesn't seem to be a good idea, but at least with my Julia version (official download), tracking |
|
In general you shouldn't use Revise directly, perhaps other than to load the package. All "where is my code?" queries should go through CodeTracking. |
Maybe because I'm using the official binaries or something? |
Will fix! |
Awesome, then I don't have to worry about any of that and can just use |
OK, if you're using master on CodeTracking and the very latest julia> using Revise, CodeTracking
julia> f(x, y=1; z="hello") = 1
f (generic function with 2 methods)
julia> m = first(methods(f))
f(x) in Main at REPL[2]:1
julia> sigs = signatures_at(String(m.file), m.line)
5-element Array{Any,1}:
Tuple{getfield(Main, Symbol("##f#13")),Any,Any,Any,Any}
Tuple{typeof(f),Any}
Tuple{typeof(f),Any,Any}
Tuple{getfield(Main, Symbol("#kw##f")),Any,typeof(f),Any}
Tuple{getfield(Main, Symbol("#kw##f")),Any,typeof(f),Any,Any} I'm guessing the breakpoint should go in the first of these---that's the "body method": julia> using JuliaInterpreter
julia> m = JuliaInterpreter.whichtt(sigs[1])
#f#13(z, ::Any, x, y) in Main at REPL[2]:1
julia> Base.uncompressed_ast(m)
CodeInfo(
1 ─ return 1
) For generated functions it's a little trickier. We have to decide which behavior we want from JuliaDebug/JuliaInterpreter.jl#163. And Juno will struggle to present the |
Alright, visual (non-conditional) breakpoints are in. Still need a bit of work to make sure the displayed breakpoints are always in-sync with those in JuliaInterpreter.jl, but the basic functionality is there now. I also want to add a UI element for displaying breakpoints and watch expressions as well as to allow toggling "Break on Exception" etc, but that probably shouldn't hold up the release. This would also provide the interface for conditional breakpoints. |
Alright, this took significantly longer than I anticipated, but seems to work pretty well now. Will release once CI passes. |
Debugger.jl and Rebugger.jl should both be ready to go Tuesday, March 19 (the date we expect Debugger.jl to be registered; I'll tag new releases of Revise & Rebugger the same day). Should we wait for Juno or just go ahead and announce? I'd rather wait, if it's only a few days, but would rather not wait if it will be weeks/months.
In case you missed it, you probably don't need Debugger.jl at all;
JuliaInterpreter.debug_command
should have everything you need (and it's already a tagged, released package). Let me know if I can help! CC @KristofferC.The text was updated successfully, but these errors were encountered: