Skip to content

Commit 05d4caf

Browse files
authored
add a toggle for showing lowered code and refactor printing a bit (#116)
* use kwdef * add a toggle for lowered code and refactor printing a bit
1 parent be7d4ad commit 05d4caf

File tree

9 files changed

+301
-212
lines changed

9 files changed

+301
-212
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ Basic Commands:
4848
- `o`: open the current line in an editor
4949
- `q`: quit the debugger, returning `nothing`
5050
- `C`: toggle compiled mode
51+
- `L`: toggle showing lowered code instead of source code
5152

5253
Advanced commands:
5354
- `nc`: step to the next call

src/Debugger.jl

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,26 +37,27 @@ using .LineNumbers: SourceFile, compute_line
3737
# watch expressions between invocations of the debugger interface
3838
const WATCH_LIST = []
3939

40-
mutable struct DebuggerState
40+
Base.@kwdef mutable struct DebuggerState
4141
frame::Union{Nothing, Frame}
42-
level::Int
43-
broke_on_error::Bool
44-
watch_list::Vector
45-
mode
46-
repl
47-
terminal
48-
main_mode
49-
julia_prompt::Ref{LineEdit.Prompt}
50-
standard_keymap
51-
overall_result
42+
level::Int = 1
43+
broke_on_error::Bool = false
44+
watch_list::Vector = WATCH_LIST
45+
lowered_status::Bool = false
46+
mode = finish_and_return!
47+
repl = nothing
48+
terminal = nothing
49+
main_mode = nothing
50+
julia_prompt::Ref{LineEdit.Prompt} = Ref{LineEdit.Prompt}()
51+
standard_keymap = nothing
52+
overall_result = nothing
5253
end
53-
DebuggerState(stack, repl, terminal) = DebuggerState(stack, 1, false, WATCH_LIST, finish_and_return!, repl, terminal, nothing, Ref{LineEdit.Prompt}(), nothing, nothing)
54-
DebuggerState(stack, repl) = DebuggerState(stack, repl, nothing)
5554

5655
function toggle_mode(state)
5756
state.mode = (state.mode === finish_and_return! ? (state.mode = Compiled()) : (state.mode = finish_and_return!))
5857
end
5958

59+
toggle_lowered(state) = state.lowered_status = !state.lowered_status
60+
6061
function active_frame(state)
6162
frame = state.frame
6263
for i in 1:(state.level - 1)

src/commands.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ function execute_command(state::DebuggerState, ::Union{Val{:c},Val{:nc},Val{:n},
4242
state.broke_on_error = true
4343
end
4444
end
45-
JuliaInterpreter.maybe_next_call!(state.frame)
45+
if pc_expr(state.frame) === nothing # happens when stopping for @bp
46+
JuliaInterpreter.maybe_next_call!(state.frame)
47+
end
4648
return true
4749
end
4850
end

src/printing.jl

Lines changed: 17 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -91,25 +91,25 @@ function print_next_expr(io::IO, frame::Frame)
9191
println(io)
9292
end
9393

94-
function breakpoint_linenumbers(frame::Frame)
94+
function breakpoint_linenumbers(frame::Frame; lowered=false)
9595
framecode = frame.framecode
9696
breakpoint_lines = Dict{Int, BreakpointState}()
9797
for stmtidx in 1:length(framecode.breakpoints)
9898
isassigned(framecode.breakpoints, stmtidx) || continue
9999
bp = framecode.breakpoints[stmtidx]
100-
line = JuliaInterpreter.linenumber(frame, stmtidx)
100+
line = lowered ? stmtidx : JuliaInterpreter.linenumber(frame, stmtidx)
101101
breakpoint_lines[line] = bp
102102
end
103103
return breakpoint_lines
104104
end
105105

106-
function print_status(io::IO, frame::Frame)
106+
function print_status(io::IO, frame::Frame; force_lowered=false)
107107
# Buffer to avoid flickering
108108
outbuf = IOContext(IOBuffer(), io)
109109
printstyled(outbuf, "In ", locdesc(frame), "\n")
110110
loc = locinfo(frame)
111111

112-
if loc !== nothing
112+
if loc !== nothing && !force_lowered
113113
data = if isa(loc, BufferLocInfo)
114114
loc.data
115115
else
@@ -124,6 +124,8 @@ function print_status(io::IO, frame::Frame)
124124
print(io, String(take!(outbuf.io)))
125125
end
126126

127+
const NUM_SOURCE_LINES_UP_DOWN = Ref(5)
128+
127129
function print_codeinfo(io::IO, frame::Frame)
128130
buf = IOBuffer()
129131
src = frame.framecode.src
@@ -133,27 +135,13 @@ function print_codeinfo(io::IO, frame::Frame)
133135
code = filter!(split(String(take!(buf)), '\n')) do line
134136
!(line == "CodeInfo(" || line == ")" || isempty(line))
135137
end
136-
138+
startline, endline = max(1, active_line - NUM_SOURCE_LINES_UP_DOWN[] + 1), min(length(code), active_line + NUM_SOURCE_LINES_UP_DOWN[]-1)
139+
code = code[startline:endline]
137140
code .= replace.(code, Ref(r"\$\(QuoteNode\((.+?)\)\)" => s"\1"))
138-
139-
for (lineno, line) in enumerate(code)
140-
(lineno < active_line - 3 || lineno > active_line + 2) && continue
141-
142-
color = (lineno < active_line) ? :white : :normal
143-
if lineno == active_line
144-
printstyled(io, rpad(lineno, 4), color = :yellow)
145-
else
146-
printstyled(io, rpad(lineno, 4), color = color)
147-
end
148-
printstyled(io, line, color = color)
149-
println(io)
150-
end
151-
println(io)
141+
breakpoint_lines = breakpoint_linenumbers(frame; lowered=true)
142+
print_lines(io, code, active_line, breakpoint_lines, startline)
152143
end
153144

154-
155-
const NUM_SOURCE_LINES_UP_DOWN = Ref(5)
156-
157145
"""
158146
Determine the offsets in the source code to print, based on the offset of the
159147
currently highlighted part of the code, and the start and stop line of the
@@ -164,7 +152,7 @@ function compute_source_offsets(code::String, offset::Integer, startline::Intege
164152
if offsetline - NUM_SOURCE_LINES_UP_DOWN[] > length(file.offsets) || startline > length(file.offsets)
165153
return -1, -1
166154
end
167-
startoffset = max(file.offsets[max(offsetline - NUM_SOURCE_LINES_UP_DOWN[], 1)], startline == 0 ? 0 : file.offsets[startline])
155+
startoffset = max(file.offsets[max(offsetline - NUM_SOURCE_LINES_UP_DOWN[] + 1, 1)], startline == 0 ? 0 : file.offsets[startline])
168156
stopoffset = lastindex(code)-1
169157
if offsetline + NUM_SOURCE_LINES_UP_DOWN[] < lastindex(file.offsets)
170158
stopoffset = min(stopoffset, file.offsets[offsetline + NUM_SOURCE_LINES_UP_DOWN[]] - 1)
@@ -237,16 +225,16 @@ function print_sourcecode(io::IO, code::String, line::Integer, defline::Integer,
237225

238226
# Compute necessary data for line numbering
239227
startline = compute_line(file, startoffset)
240-
stopline = compute_line(file, stopoffset)
241-
current_line = line
242-
stoplinelength = ndigits(stopline)
243228

244229
code = split(code[(startoffset+1):(stopoffset+1)],'\n')
245-
lineno = startline
230+
print_lines(io, code, line, breakpoint_lines, startline)
231+
end
246232

233+
function print_lines(io, code, current_line, breakpoint_lines, startline)
247234
if !isempty(code) && isempty(code[end])
248235
pop!(code)
249236
end
237+
stopline = startline + length(code) - 1
250238

251239
# Count indentation level (only count spaces for now)
252240
min_indentation = typemax(Int)
@@ -262,7 +250,8 @@ function print_sourcecode(io::IO, code::String, line::Integer, defline::Integer,
262250
for i in 1:length(code)
263251
code[i] = code[i][min_indentation+1:end]
264252
end
265-
253+
lineno = startline
254+
stoplinelength = ndigits(stopline)
266255
for textline in code
267256
break_on_line = haskey(breakpoint_lines, lineno)
268257
prefix = (" ", :normal)

src/repl.jl

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
promptname(level, name) = "$level|$name> "
33
function RunDebugger(frame, repl = Base.active_repl, terminal = Base.active_repl.t; initial_continue=false)
4-
state = DebuggerState(frame, repl, terminal)
4+
state = DebuggerState(; frame=frame, repl=repl, terminal=terminal)
55

66
# Setup debug panel
77
normal_prefix = Sys.iswindows() ? "\e[33m" : "\e[38;5;166m"
@@ -53,7 +53,7 @@ function RunDebugger(frame, repl = Base.active_repl, terminal = Base.active_repl
5353
return false
5454
end
5555
if do_print_status
56-
print_status(Base.pipe_writer(terminal), active_frame(state))
56+
print_status(Base.pipe_writer(terminal), active_frame(state); force_lowered = state.lowered_status)
5757
end
5858
return true
5959
end
@@ -79,7 +79,17 @@ function RunDebugger(frame, repl = Base.active_repl, terminal = Base.active_repl
7979
else
8080
LineEdit.edit_insert(s,key)
8181
end
82+
end,
83+
"L" => function (s, args...)
84+
if isempty(s) || position(LineEdit.buffer(s)) == 0
85+
toggle_lowered(state)
86+
println(Base.pipe_writer(terminal))
87+
print_status(Base.pipe_writer(terminal), active_frame(state); force_lowered=state.lowered_status)
88+
LineEdit.write_prompt(state.terminal, panel)
89+
else
90+
LineEdit.edit_insert(s,key)
8291
end
92+
end
8393
)
8494

8595
state.standard_keymap = Dict{Any,Any}[skeymap, LineEdit.history_keymap, LineEdit.default_keymap, LineEdit.escape_defaults]
@@ -89,7 +99,7 @@ function RunDebugger(frame, repl = Base.active_repl, terminal = Base.active_repl
8999
execute_command(state, Val(:c), "c")
90100
state.frame === nothing && return state.overall_result
91101
end
92-
print_status(Base.pipe_writer(terminal), active_frame(state))
102+
print_status(Base.pipe_writer(terminal), active_frame(state); force_lowered=state.lowered_status)
93103
REPL.run_interface(terminal, LineEdit.ModalInterface([panel,search_prompt]))
94104

95105
return state.overall_result

test/ui.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ end
2727
include_string(@__MODULE__, """
2828
function my_gcd_noinfo(a::T, b::T) where T<:Union{Int8,UInt8,Int16,UInt16,Int32,UInt32,Int64,UInt64,Int128,UInt128}
2929
a == 0 && return abs(b)
30+
Debugger.@bp
3031
b == 0 && return abs(a)
3132
za = trailing_zeros(a)
3233
zb = trailing_zeros(b)
@@ -47,7 +48,6 @@ function my_gcd_noinfo(a::T, b::T) where T<:Union{Int8,UInt8,Int16,UInt16,Int32,
4748
end
4849
""", "nope.jl")
4950

50-
5151
function outer(a, b, c, d)
5252
inner_kw(a, b; c = c)
5353
end

test/ui/history_gcd.multiout

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2107,7 +2107,6 @@
21072107
|1|debug> c
21082108
|Hit breakpoint:
21092109
|In my_gcd(a, b) at ui.jl:5
2110-
| 8 zb = trailing_zeros(b)
21112110
| 9 k = min(za, zb)
21122111
| 10 u = unsigned(abs(a >> za))
21132112
| 11 v = unsigned(abs(b >> zb))
@@ -2219,7 +2218,6 @@
22192218
|EEEEEEEEEA
22202219
|AAAAAAAAAAAAAAA
22212220
|AAAAAAAAAAAAAAAAAAAAAAAAAA
2222-
|AAAAAAAAAAAAAAAAAAAAAAAAAAA
22232221
|AAAAAAAAAAAAAAAAAAAA
22242222
|AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
22252223
|AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
@@ -2331,7 +2329,6 @@
23312329
|1|debug> c
23322330
|Hit breakpoint:
23332331
|In my_gcd(a, b) at ui.jl:5
2334-
| 8 zb = trailing_zeros(b)
23352332
| 9 k = min(za, zb)
23362333
| 10 u = unsigned(abs(a >> za))
23372334
| 11 v = unsigned(abs(b >> zb))
@@ -2443,7 +2440,6 @@
24432440
|EEEEEEEEEA
24442441
|AAAAAAAAAAAAAAA
24452442
|AAAAAAAAAAAAAAAAAAAAAAAAAA
2446-
|AAAAAAAAAAAAAAAAAAAAAAAAAAA
24472443
|AAAAAAAAAAAAAAAAAAAA
24482444
|AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
24492445
|AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

0 commit comments

Comments
 (0)