1
1
module Breakpoints
2
2
3
3
using .. JuliaInterpreter
4
- using JuliaInterpreter: JuliaFrameCode, JuliaStackFrame,
5
- prepare_framecode, framedict, get_source, sparam_syms,
6
- linenumber
4
+ using JuliaInterpreter: JuliaFrameCode, JuliaStackFrame, BreakpointState,
5
+ truecondition, falsecondition, prepare_framecode, get_framecode,
6
+ sparam_syms, linenumber
7
+ using Base. Meta: isexpr
8
+ using InteractiveUtils
7
9
8
- export breakpoint
10
+ export @ breakpoint, breakpoint, enable, disable, remove
9
11
10
12
# A type that is unique to this package for which there are no valid operations
11
13
struct Unassigned end
12
14
13
15
"""
14
- Breakpoint (framecode, stmtidx)
16
+ BreakpointRef (framecode, stmtidx)
15
17
16
18
A reference to a breakpoint at a particular statement index `stmtidx` in `framecode`.
17
19
"""
18
- struct Breakpoint
20
+ struct BreakpointRef
19
21
framecode:: JuliaFrameCode
20
22
stmtidx:: Int
21
23
end
22
24
23
- function Base. show (io:: IO , bp:: Breakpoint )
25
+ function Base. show (io:: IO , bp:: BreakpointRef )
24
26
lineno = linenumber (bp. framecode, bp. stmtidx)
25
27
print (io, " breakpoint(" , bp. framecode. scope, " , " , lineno, ' )' )
26
28
end
27
29
28
- const _breakpoints = Set {Breakpoint} ()
30
+ const _breakpoints = BreakpointRef[]
31
+ breakpoints () = copy (_breakpoints)
32
+
33
+ Base. getindex (bp:: BreakpointRef ) = bp. framecode. breakpoints[bp. stmtidx]
34
+ function Base. setindex! (bp:: BreakpointRef , isactive:: Bool )
35
+ bp. framecode. breakpoints[bp. stmtidx] = BreakpointState (isactive, bp[]. condition)
36
+ end
37
+ function toggle! (bp:: BreakpointRef )
38
+ state = bp[]
39
+ bp. framecode. breakpoints[bp. stmtidx] = BreakpointState (! state. isactive, state. condition)
40
+ end
41
+
42
+ function add_breakpoint (framecode, stmtidx)
43
+ bp = BreakpointRef (framecode, stmtidx)
44
+ # Since there can be only one BreakpointState for a given framecode/stmtidx,
45
+ # check whether _breakpoints is already storing a reference to that location
46
+ idx = findfirst (isequal (bp), _breakpoints)
47
+ if idx === nothing
48
+ push! (_breakpoints, bp)
49
+ end
50
+ return bp
51
+ end
29
52
30
53
function shouldbreak (frame, pc= frame. pc[])
31
54
idx = convert (Int, pc)
32
55
isassigned (frame. code. breakpoints, idx) || return false
33
56
bp = frame. code. breakpoints[idx]
34
- bp[1 ] || return false
35
- slotfunction = bp[2 ]
36
- return slotfunction (frame):: Bool
57
+ bp. isactive || return false
58
+ return bp. condition (frame):: Bool
37
59
end
38
60
39
61
function prepare_slotfunction (framecode:: JuliaFrameCode , body:: Union{Symbol,Expr} )
@@ -65,63 +87,35 @@ function prepare_slotfunction(framecode::JuliaFrameCode, body::Union{Symbol,Expr
65
87
return Expr (:function , Expr (:call , funcname, framename), Expr (:block , assignments... , body))
66
88
end
67
89
68
- truecondition (frame) = true
69
- falsecondition (frame) = false
70
90
71
91
# # The fundamental implementations of breakpoint-setting
72
92
function breakpoint! (framecode:: JuliaFrameCode , pc, condition:: Union{Bool,Expr} = true )
73
93
stmtidx = convert (Int, pc)
74
94
if isa (condition, Bool)
75
- framecode. breakpoints[stmtidx] = condition ? ( true , truecondition) : ( false , falsecondition )
95
+ framecode. breakpoints[stmtidx] = BreakpointState (condition )
76
96
else
77
97
fex = prepare_slotfunction (framecode, condition)
78
- framecode. breakpoints[stmtidx] = (true , eval (fex))
98
+ framecode. breakpoints[stmtidx] = BreakpointState (true , eval (fex))
79
99
end
80
- bp = Breakpoint (framecode, stmtidx)
81
- push! (_breakpoints, bp)
82
- return bp
100
+ return add_breakpoint (framecode, stmtidx)
83
101
end
84
102
breakpoint! (frame:: JuliaStackFrame , pc= frame. pc[], condition:: Union{Bool,Expr} = true ) =
85
103
breakpoint! (frame. code, pc, condition)
86
104
87
- function set_breakpoint_active! (framecode:: JuliaFrameCode , active, pc)
88
- stmtidx = convert (Int, pc)
89
- _, condition = framecode. breakpoints[stmtidx]
90
- framecode. breakpoints[stmtidx] = (active, condition)
91
- active
92
- end
93
- set_breakpoint_active! (frame:: JuliaStackFrame , active, pc) =
94
- set_breakpoint_active! (frame. code, active, pc)
95
-
96
- function get_breakpoint_active (framecode:: JuliaFrameCode , pc)
97
- stmtidx = convert (Int, pc)
98
- return framecode. breakpoints[stmtidx][1 ]
99
- end
100
- get_breakpoint_active (frame:: JuliaStackFrame , pc) =
101
- get_breakpoint_active (frame. code, pc)
102
-
103
- function toggle_breakpoint_active! (framecode:: JuliaFrameCode , pc)
104
- stmtidx = convert (Int, pc)
105
- active, condition = framecode. breakpoints[stmtidx]
106
- framecode. breakpoints[stmtidx] = (! active, condition)
107
- ! active
108
- end
109
- toggle_breakpoint_active! (frame:: JuliaStackFrame , active, pc) =
110
- toggle_breakpoint_active! (frame. code, active, pc)
111
-
112
- enable (bp:: Breakpoint ) = set_breakpoint_active! (bp. framecode, true , bp. stmtidx)
113
- disable (bp:: Breakpoint ) = set_breakpoint_active! (bp. framecode, false , bp. stmtidx)
114
- function remove (bp:: Breakpoint )
115
- bp. framecode. breakpoints[bp. stmtidx] = (false , falsecondition)
116
- delete! (_breakpoints, bp)
105
+ enable (bp:: BreakpointRef ) = bp[] = true
106
+ disable (bp:: BreakpointRef ) = bp[] = false
107
+ function remove (bp:: BreakpointRef )
108
+ idx = findfirst (isequal (bp), _breakpoints)
109
+ deleteat! (_breakpoints, idx)
110
+ bp. framecode. breakpoints[bp. stmtidx] = BreakpointState (false , falsecondition)
117
111
return nothing
118
112
end
119
113
120
114
enable () = for bp in _breakpoints enable (bp) end
121
115
disable () = for bp in _breakpoints disable (bp) end
122
116
function remove ()
123
117
for bp in _breakpoints
124
- bp. framecode. breakpoints[bp. stmtidx] = (false , falsecondition)
118
+ bp. framecode. breakpoints[bp. stmtidx] = BreakpointState (false , falsecondition)
125
119
end
126
120
empty! (_breakpoints)
127
121
return nothing
@@ -155,18 +149,10 @@ end
155
149
breakpoint(method::Method)
156
150
breakpoint(method::Method, condition::Expr)
157
151
158
- Add a breakpoint upon entry to `method`. The first will break unconditionally, the second
159
- only if `condition` evaluates to `true`. `condition` should be written in terms of the
160
- arguments and local variables of `method`.
152
+ Add a breakpoint upon entry to `method`.
161
153
"""
162
154
function breakpoint (method:: Method , condition:: Union{Bool,Expr} = true )
163
- # FIXME : this duplicates stuff in prepare_call
164
- framecode = get (framedict, method, nothing )
165
- if framecode === nothing
166
- code = get_source (method)
167
- framecode = JuliaFrameCode (method, code; generator= false )
168
- framedict[method] = framecode
169
- end
155
+ framecode = get_framecode (method)
170
156
breakpoint! (framecode, 1 , condition)
171
157
end
172
158
@@ -177,10 +163,11 @@ end
177
163
Break-on-entry to all methods of `f`.
178
164
"""
179
165
function breakpoint (f, condition:: Union{Bool,Expr} = true )
166
+ bps = BreakpointRef[]
180
167
for method in methods (f)
181
- breakpoint (method, condition)
168
+ push! (bps, breakpoint (method, condition) )
182
169
end
183
- nothing
170
+ return bps
184
171
end
185
172
186
173
end
0 commit comments