Helios-Debugger.st 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  1. Smalltalk createPackage: 'Helios-Debugger'!
  2. Object subclass: #HLContextInspectorDecorator
  3. instanceVariableNames: 'context'
  4. package: 'Helios-Debugger'!
  5. !HLContextInspectorDecorator methodsFor: 'accessing'!
  6. context
  7. ^ context
  8. ! !
  9. !HLContextInspectorDecorator methodsFor: 'initialization'!
  10. initializeFromContext: aContext
  11. context := aContext
  12. ! !
  13. !HLContextInspectorDecorator methodsFor: 'inspecting'!
  14. inspectOn: anInspector
  15. | variables inspectedContext |
  16. variables := Dictionary new.
  17. inspectedContext := self context.
  18. variables addAll: inspectedContext locals.
  19. [ inspectedContext notNil and: [ inspectedContext isBlockContext ] ] whileTrue: [
  20. inspectedContext := inspectedContext outerContext.
  21. inspectedContext ifNotNil: [
  22. variables addAll: inspectedContext locals ] ].
  23. anInspector
  24. setLabel: 'Context';
  25. setVariables: variables
  26. ! !
  27. !HLContextInspectorDecorator class methodsFor: 'instance creation'!
  28. on: aContext
  29. ^ self new
  30. initializeFromContext: aContext;
  31. yourself
  32. ! !
  33. HLFocusableWidget subclass: #HLDebugger
  34. instanceVariableNames: 'model stackListWidget codeWidget inspectorWidget'
  35. package: 'Helios-Debugger'!
  36. !HLDebugger commentStamp!
  37. I am the main widget for the Helios debugger.!
  38. !HLDebugger methodsFor: 'accessing'!
  39. initializeFromMethodContext: aMethodContext
  40. model := HLDebuggerModel on: aMethodContext.
  41. self observeModel
  42. !
  43. model
  44. ^ model ifNil: [ model := HLDebuggerModel new ]
  45. ! !
  46. !HLDebugger methodsFor: 'actions'!
  47. focus
  48. self stackListWidget focus
  49. !
  50. observeModel
  51. self model announcer
  52. on: HLDebuggerContextSelected
  53. send: #onContextSelected:
  54. to: self.
  55. self model announcer
  56. on: HLDebuggerStepped
  57. send: #onContextSelected:
  58. to: self
  59. !
  60. unregister
  61. super unregister.
  62. self inspectorWidget unregister
  63. ! !
  64. !HLDebugger methodsFor: 'keybindings'!
  65. registerBindingsOn: aBindingGroup
  66. HLToolCommand
  67. registerConcreteClassesOn: aBindingGroup
  68. for: self model
  69. ! !
  70. !HLDebugger methodsFor: 'reactions'!
  71. onContextSelected: anAnnouncement
  72. self inspectorWidget inspect: (HLContextInspectorDecorator on: anAnnouncement context)
  73. ! !
  74. !HLDebugger methodsFor: 'rendering'!
  75. renderContentOn: html
  76. html with: (HLContainer with: (HLHorizontalSplitter
  77. with: self stackListWidget
  78. with: (HLVerticalSplitter
  79. with: self codeWidget
  80. with: self inspectorWidget)))
  81. ! !
  82. !HLDebugger methodsFor: 'widgets'!
  83. codeWidget
  84. ^ codeWidget ifNil: [ codeWidget := HLDebuggerCodeWidget new
  85. model: (HLDebuggerCodeModel new
  86. debuggerModel: self model;
  87. yourself);
  88. browserModel: self model;
  89. yourself ]
  90. !
  91. inspectorWidget
  92. ^ inspectorWidget ifNil: [
  93. inspectorWidget := HLInspectorWidget new ]
  94. !
  95. stackListWidget
  96. ^ stackListWidget ifNil: [
  97. stackListWidget := (HLStackListWidget on: self model)
  98. next: self codeWidget;
  99. yourself ]
  100. ! !
  101. !HLDebugger class methodsFor: 'accessing'!
  102. tabClass
  103. ^ 'debugger'
  104. !
  105. tabLabel
  106. ^ 'Debugger'
  107. ! !
  108. !HLDebugger class methodsFor: 'instance creation'!
  109. on: aMethodContext
  110. ^ self new
  111. initializeFromMethodContext: aMethodContext;
  112. yourself
  113. ! !
  114. HLCodeModel subclass: #HLDebuggerCodeModel
  115. instanceVariableNames: 'debuggerModel'
  116. package: 'Helios-Debugger'!
  117. !HLDebuggerCodeModel methodsFor: 'accessing'!
  118. debuggerModel
  119. ^ debuggerModel
  120. !
  121. debuggerModel: anObject
  122. debuggerModel := anObject
  123. ! !
  124. !HLDebuggerCodeModel methodsFor: 'actions'!
  125. doIt: aString
  126. ^ self
  127. try: [ self debuggerModel evaluate: aString ]
  128. catch: [ :e |
  129. ErrorHandler handleError: e.
  130. nil ]
  131. ! !
  132. HLBrowserCodeWidget subclass: #HLDebuggerCodeWidget
  133. instanceVariableNames: ''
  134. package: 'Helios-Debugger'!
  135. !HLDebuggerCodeWidget methodsFor: 'accessing'!
  136. contents: aString
  137. self clearHighlight.
  138. super contents: aString
  139. !
  140. editorOptions
  141. ^ super editorOptions
  142. at: 'gutters' put: #('CodeMirror-linenumbers' 'stops');
  143. yourself
  144. ! !
  145. !HLDebuggerCodeWidget methodsFor: 'actions'!
  146. addStopAt: anInteger
  147. editor
  148. setGutterMarker: anInteger
  149. gutter: 'stops'
  150. value: '<div class="stop"></stop>' asJQuery toArray first
  151. !
  152. clearHighlight
  153. self editor clearGutter: 'stops'
  154. !
  155. highlight
  156. self highlightNode: self browserModel nextNode
  157. !
  158. highlightNode: aNode
  159. | token |
  160. aNode ifNotNil: [
  161. self
  162. clearHighlight;
  163. addStopAt: aNode positionStart x - 1.
  164. self editor
  165. setSelection: #{ 'line' -> (aNode positionStart x - 1). 'ch' -> (aNode positionStart y - 1) }
  166. to: #{ 'line' -> (aNode positionEnd x - 1). 'ch' -> (aNode positionEnd y) } ]
  167. !
  168. observeBrowserModel
  169. super observeBrowserModel.
  170. self browserModel announcer
  171. on: HLDebuggerContextSelected
  172. send: #onContextSelected
  173. to: self.
  174. self browserModel announcer
  175. on: HLDebuggerStepped
  176. send: #onContextSelected
  177. to: self.
  178. self browserModel announcer
  179. on: HLDebuggerWhere
  180. send: #onContextSelected
  181. to: self
  182. ! !
  183. !HLDebuggerCodeWidget methodsFor: 'reactions'!
  184. onContextSelected
  185. self highlight
  186. ! !
  187. HLToolModel subclass: #HLDebuggerModel
  188. instanceVariableNames: 'rootContext currentContext contexts'
  189. package: 'Helios-Debugger'!
  190. !HLDebuggerModel commentStamp!
  191. I am a model for debugging Amber code in Helios.
  192. My instances hold a reference to an `AIContext` instance, built from a `MethodContext`. The context should be the root of the context stack.!
  193. !HLDebuggerModel methodsFor: 'accessing'!
  194. contexts
  195. ^ contexts
  196. !
  197. currentContext
  198. currentContext ifNil: [ self currentContext: self rootContext ].
  199. ^ currentContext
  200. !
  201. currentContext: aContext
  202. self withChangesDo: [
  203. self selectedMethod: aContext method.
  204. currentContext := aContext.
  205. self announcer announce: (HLDebuggerContextSelected new
  206. context: aContext;
  207. yourself) ]
  208. !
  209. interpreter
  210. ^ self currentContext interpreter
  211. !
  212. nextNode
  213. ^ self interpreter node
  214. !
  215. rootContext
  216. ^ rootContext
  217. ! !
  218. !HLDebuggerModel methodsFor: 'actions'!
  219. restart
  220. self interpreter restart.
  221. self flushInnerContexts.
  222. self announcer announce: (HLDebuggerStepped new
  223. context: self currentContext;
  224. yourself)
  225. !
  226. skip
  227. self interpreter skip.
  228. self flushInnerContexts.
  229. self announcer announce: (HLDebuggerStepped new
  230. context: self currentContext;
  231. yourself)
  232. !
  233. stepOver
  234. self interpreter stepOver.
  235. self flushInnerContexts.
  236. self announcer announce: (HLDebuggerStepped new
  237. context: self currentContext;
  238. yourself)
  239. !
  240. where
  241. self announcer announce: HLDebuggerWhere new
  242. ! !
  243. !HLDebuggerModel methodsFor: 'evaluating'!
  244. evaluate: aString
  245. ^ self environment
  246. interpret: aString
  247. inContext: self currentContext
  248. ! !
  249. !HLDebuggerModel methodsFor: 'initialization'!
  250. initializeContexts
  251. "Flatten the context stack into an OrderedCollection"
  252. | context |
  253. contexts := OrderedCollection new.
  254. context := self rootContext.
  255. [ context notNil ] whileTrue: [
  256. contexts add: context.
  257. context := context outerContext ]
  258. !
  259. initializeFromContext: aMethodContext
  260. rootContext := (AIContext fromMethodContext: aMethodContext).
  261. self initializeContexts
  262. ! !
  263. !HLDebuggerModel methodsFor: 'private'!
  264. flushInnerContexts
  265. "When stepping, the inner contexts are not relevent anymore,
  266. and can be flushed"
  267. self currentContext innerContext: nil.
  268. rootContext := self currentContext.
  269. self initializeContexts
  270. ! !
  271. !HLDebuggerModel class methodsFor: 'instance creation'!
  272. on: aMethodContext
  273. ^ self new
  274. initializeFromContext: aMethodContext;
  275. yourself
  276. ! !
  277. Object subclass: #HLErrorHandler
  278. instanceVariableNames: ''
  279. package: 'Helios-Debugger'!
  280. !HLErrorHandler methodsFor: 'error handling'!
  281. handleError: anError
  282. self onErrorHandled.
  283. [
  284. (HLDebugger on: anError context) openAsTab
  285. ]
  286. on: Error
  287. do: [ :error | ErrorHandler new handleError: error ]
  288. !
  289. onErrorHandled
  290. "when an error is handled, we need to make sure that
  291. any progress bar widget gets removed. Because HLProgressBarWidget is asynchronous,
  292. it has to be done here."
  293. HLProgressWidget default
  294. flush;
  295. remove
  296. ! !
  297. HLToolListWidget subclass: #HLStackListWidget
  298. instanceVariableNames: ''
  299. package: 'Helios-Debugger'!
  300. !HLStackListWidget methodsFor: 'accessing'!
  301. items
  302. ^ items ifNil: [ items := self model contexts ]
  303. !
  304. label
  305. ^ 'Call stack'
  306. ! !
  307. !HLStackListWidget methodsFor: 'actions'!
  308. observeModel
  309. super observeModel.
  310. self model announcer
  311. on: HLDebuggerStepped
  312. send: #onDebuggerStepped:
  313. to: self
  314. !
  315. restart
  316. self model restart
  317. !
  318. selectItem: aContext
  319. self model currentContext: aContext.
  320. super selectItem: aContext
  321. !
  322. skip
  323. self model skip
  324. !
  325. stepOver
  326. self model stepOver
  327. !
  328. where
  329. self model where
  330. ! !
  331. !HLStackListWidget methodsFor: 'reactions'!
  332. onDebuggerStepped: anAnnouncement
  333. items := nil.
  334. self refresh
  335. ! !
  336. !HLStackListWidget methodsFor: 'rendering'!
  337. renderButtonsOn: html
  338. html div
  339. class: 'debugger_bar';
  340. with: [
  341. html button
  342. class: 'btn restart';
  343. with: 'Restart';
  344. onClick: [ self restart ].
  345. html button
  346. class: 'btn where';
  347. with: 'Where';
  348. onClick: [ self where ].
  349. html button
  350. class: 'btn stepOver';
  351. with: 'Step over';
  352. onClick: [ self stepOver ].
  353. html button
  354. class: 'btn skip';
  355. with: 'Skip';
  356. onClick: [ self skip ] ]
  357. ! !