/ld27

To get this branch, use:
bzr branch http://9ix.org/bzr/ld27

« back to all changes in this revision

Viewing changes to zoetrope/debug/stepper.lua

  • Committer: Josh C
  • Date: 2013-08-25 02:04:52 UTC
  • Revision ID: josh@9ix.org-20130825020452-py8fijli8m5te5gv
improve performance with (sketchy, experimental) sprite batches

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
 
2
 
DebugStepper = DebugInstrument:extend
3
 
{
4
 
        visible = false,
5
 
        lineContext = 10,
6
 
        width = 'wide',
7
 
        _fileCache = {},
8
 
 
9
 
        onNew = function (self)
10
 
                self.stepIntoButton = self:add(DebugInstrumentButton:new
11
 
                {
12
 
                        label = 'Step Into',
13
 
                        onMouseUp = function (self)
14
 
                                debugger._stepPaused = false
15
 
                                debugger._stepFilter = nil
16
 
                        end
17
 
                })
18
 
 
19
 
                self.stepOverButton = self:add(DebugInstrumentButton:new
20
 
                {
21
 
                        label = 'Step Over',
22
 
                        onMouseUp = function (self)
23
 
                                debugger._stepPaused = false
24
 
                                local prevStack = debugger._stepStack()
25
 
 
26
 
                                debugger._stepFilter = function (stack)
27
 
                                        for i = 1, #stack - #prevStack do
28
 
                                                local match = true
29
 
 
30
 
                                                for j = 1, #prevStack do
31
 
                                                        if stack[i + j] ~= prevStack[j] then
32
 
                                                                match = false
33
 
                                                                break
34
 
                                                        end
35
 
                                                end
36
 
 
37
 
                                                -- we are now executing a sub-call;
38
 
                                                -- temporarily disable our line hook until
39
 
                                                -- we return to the previous function
40
 
 
41
 
                                                if match then
42
 
                                                        debug.sethook(function()
43
 
                                                                local state = debug.getinfo(3, 'f')
44
 
 
45
 
                                                                if state.func == prevStack[1] then 
46
 
                                                                        -- we're at least on our old function, but is
47
 
                                                                        -- the stack depth the same?
48
 
 
49
 
                                                                        local depth = 1
50
 
                                                                        
51
 
                                                                        while true do
52
 
                                                                                state = debug.getinfo(3 + depth, 'f')
53
 
                                                                                if not state then break end
54
 
                                                                                depth = depth + 1
55
 
                                                                        end
56
 
 
57
 
                                                                        if depth == #prevStack then
58
 
                                                                                debug.sethook(debugger._stepLine, 'l')
59
 
                                                                        end
60
 
                                                                end
61
 
                                                        end, 'r')
62
 
                                                        return false
63
 
                                                end
64
 
                                        end
65
 
 
66
 
                                        return true
67
 
                                end
68
 
                        end
69
 
                })
70
 
 
71
 
                self.stepOutButton = self:add(DebugInstrumentButton:new
72
 
                {
73
 
                        label = 'Step Out',
74
 
                        onMouseUp = function (self)
75
 
                                debugger._stepPaused = false
76
 
                                local prevStack = debugger._stepStack()
77
 
 
78
 
                                -- disable our line hook until the current function returns
79
 
 
80
 
                                debug.sethook(function()
81
 
                                        local depth = 2
82
 
                                        local match = false
83
 
 
84
 
                                        while true do
85
 
                                                local state = debug.getinfo(depth, 'f')
86
 
 
87
 
                                                if not state then
88
 
                                                        match = true
89
 
                                                        break
90
 
                                                elseif state.func ~= prevStack[depth - 1] then
91
 
                                                        break
92
 
                                                end
93
 
 
94
 
                                                depth = depth + 1
95
 
                                        end
96
 
 
97
 
                                        if match then
98
 
                                                debug.sethook(debugger._stepLine, 'l')
99
 
                                        end
100
 
                                end, 'r')
101
 
                        end
102
 
                })
103
 
 
104
 
                self.continueButton = self:add(DebugInstrumentButton:new
105
 
                {
106
 
                        label = 'Continue',
107
 
                        onMouseUp = function (self)
108
 
                                debugger._stepPaused = false
109
 
                                debugger.endBreakpt()
110
 
                        end
111
 
                })
112
 
 
113
 
                self.lineHighlight = self:add(Fill:new{ fill = {64, 64, 64}, height = 0, width = 0 })
114
 
 
115
 
                self.sourceLines = self:add(Text:new
116
 
                {
117
 
                        font = self.font,
118
 
                        width = 20,
119
 
                        align = 'right',
120
 
                        wordWrap = false,
121
 
                })
122
 
 
123
 
                self.sourceView = self:add(Text:new{ font = self.font, wordWrap = false })
124
 
                self.lineHeight = self.sourceView._fontObj:getHeight()
125
 
 
126
 
                self.title.text = 'Source'
127
 
                self.contentHeight = self.lineHeight * (self.lineContext + 1) * 2 + self.spacing * 3 +
128
 
                                     DebugInstrumentButton.height
129
 
 
130
 
                debugger.breakpt = function()
131
 
                        local print = debugger.unsourcedPrint or print
132
 
                        local caller = debug.getinfo(2, 'S')
133
 
 
134
 
                        debugger.showConsole()
135
 
                        self.visible = true
136
 
 
137
 
                        print('\n' .. string.rep('=', 40))
138
 
                        print('Breakpoint, ' .. caller.short_src .. ', ' .. caller.linedefined)
139
 
                        print(string.rep('=', 40))
140
 
                        debug.sethook(debugger._stepLine, 'l')
141
 
                end
142
 
 
143
 
                debugger.endBreakpt = function()
144
 
                        self.visible = false
145
 
                        if debugger.hideStack then debugger.hideStack() end
146
 
                        if debugger.hideLocals then debugger.hideLocals() end
147
 
                        debugger.hideConsole()
148
 
                        debug.sethook()
149
 
                end
150
 
 
151
 
                -- hook to handle stepping over source
152
 
 
153
 
                debugger._stepLine = function (_, line)
154
 
                        local state = debug.getinfo(2, 'Sl')
155
 
 
156
 
                        if string.find(state.source, 'zoetrope/debug') or
157
 
                           (debugger._stepFilter and not debugger._stepFilter(debugger._stepStack())) then
158
 
                                --print('skipping', state.source, state.currentline, #debugger._stepStack())
159
 
                                return
160
 
                        end
161
 
 
162
 
                        if debugger.showStack then debugger.showStack(4) end
163
 
                        if debugger.showLocals then debugger.showLocals(4) end
164
 
 
165
 
                        local file = string.match(state.source, '^@(.*)')
166
 
                        self:showLine(file, line)
167
 
 
168
 
                        debugger._stepPaused = true
169
 
                        local quit = false
170
 
 
171
 
                        while debugger._stepPaused and not quit do
172
 
                                quit = debugger._miniEventLoop()
173
 
                        end
174
 
 
175
 
                        if quit then
176
 
                                debug.sethook()
177
 
                                love.event.quit()
178
 
                        end
179
 
                end
180
 
 
181
 
                -- returns a table representing the call stack during a source step
182
 
 
183
 
                debugger._stepStack = function()
184
 
                        local level = 2
185
 
                        local result = {}
186
 
                        local info = {}
187
 
                        local afterHook = false
188
 
 
189
 
                        while true do
190
 
                                info = debug.getinfo(level, 'f')
191
 
                                if not info then break end
192
 
 
193
 
                                if afterHook then
194
 
                                        table.insert(result, info.func)
195
 
                                elseif info.func == debugger._stepLine then
196
 
                                        afterHook = true
197
 
                                end
198
 
 
199
 
                                level = level + 1
200
 
                        end
201
 
 
202
 
                        return result
203
 
                end
204
 
        end,
205
 
 
206
 
        onResize = function (self, x, y, width, height)
207
 
                self.sourceLines.x = x + self.spacing
208
 
                self.sourceLines.y = y + self.spacing
209
 
                self.sourceLines.height = height - self.sourceLines.y - self.spacing
210
 
                
211
 
                self.sourceView.x = self.sourceLines.x + self.sourceLines.width + self.spacing
212
 
                self.sourceView.y = self.sourceLines.y
213
 
                self.sourceView.width = width - self.sourceView.x - self.spacing * 2
214
 
                self.sourceView.height = self.sourceLines.height
215
 
 
216
 
                self.lineHighlight.x = x + self.spacing
217
 
                self.lineHighlight.y = self.sourceLines.y + self.lineHeight * self.lineContext
218
 
                self.lineHighlight.width = width - self.spacing * 2
219
 
                self.lineHighlight.height = self.lineHeight
220
 
 
221
 
                self.stepIntoButton.x = self.sourceLines.x
222
 
                self.stepIntoButton.y = self.sourceView.y + self.sourceView.height + self.spacing
223
 
 
224
 
                self.stepOverButton.x = self.stepIntoButton.x + self.stepIntoButton.width + self.spacing
225
 
                self.stepOverButton.y = self.stepIntoButton.y
226
 
 
227
 
                self.stepOutButton.x = self.stepOverButton.x + self.stepOverButton.width + self.spacing
228
 
                self.stepOutButton.y = self.stepOverButton.y
229
 
 
230
 
                self.continueButton.x = width - self.stepOverButton.width
231
 
                self.continueButton.y = self.stepOverButton.y
232
 
        end,
233
 
 
234
 
        showLine = function (self, file, line)
235
 
                if file then
236
 
                        self.sourceLines.text = ''
237
 
                        self.sourceView.text = ''
238
 
 
239
 
                        for i = line - self.lineContext, line + self.lineContext + 1 do
240
 
                                local source = debugger.sourceLine(file, i)
241
 
 
242
 
                                if source then
243
 
                                        self.sourceLines.text = self.sourceLines.text .. i .. '\n'
244
 
                                        self.sourceView.text = self.sourceView.text .. string.gsub(debugger.sourceLine(file, i), '\t', string.rep(' ', 4)) .. '\n'
245
 
                                end
246
 
                        end
247
 
 
248
 
                        self.title.text = file .. ':' .. line
249
 
                else
250
 
                        self.title.text = 'Source'
251
 
                        self.sourceView.text = '(source not available)'
252
 
                end
253
 
        end
254
 
}
255