Helios-Debugger.st 9.5 KB

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