Helios-Debugger.st 9.4 KB

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