| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398 | 
							- Smalltalk createPackage: 'Helios-Debugger'!
 
- Object subclass: #HLContextInspectorDecorator
 
- 	instanceVariableNames: 'context'
 
- 	package: 'Helios-Debugger'!
 
- !HLContextInspectorDecorator methodsFor: 'accessing'!
 
- context
 
- 	^ context
 
- ! !
 
- !HLContextInspectorDecorator methodsFor: 'initialization'!
 
- initializeFromContext: aContext
 
- 	context := aContext
 
- ! !
 
- !HLContextInspectorDecorator methodsFor: 'inspecting'!
 
- inspectOn: anInspector
 
- 	| variables inspectedContext |
 
- 	
 
- 	variables := Dictionary new.
 
- 	inspectedContext := self context.
 
- 	
 
- 	variables addAll: inspectedContext locals.
 
- 	
 
- 	[ inspectedContext notNil and: [ inspectedContext isBlockContext ] ] whileTrue: [
 
- 		inspectedContext := inspectedContext outerContext.
 
- 		inspectedContext ifNotNil: [
 
- 			variables addAll: inspectedContext locals ] ].
 
- 	
 
- 	anInspector
 
- 		setLabel: 'Context';
 
- 		setVariables: variables
 
- ! !
 
- !HLContextInspectorDecorator class methodsFor: 'instance creation'!
 
- on: aContext
 
- 	^ self new
 
- 		initializeFromContext: aContext;
 
- 		yourself
 
- ! !
 
- HLFocusableWidget subclass: #HLDebugger
 
- 	instanceVariableNames: 'model stackListWidget codeWidget inspectorWidget'
 
- 	package: 'Helios-Debugger'!
 
- !HLDebugger commentStamp!
 
- I am the main widget for the Helios debugger.!
 
- !HLDebugger methodsFor: 'accessing'!
 
- codeWidget
 
- 	^ codeWidget ifNil: [ codeWidget := HLDebuggerCodeWidget new
 
- 		browserModel: self model;
 
- 		yourself ]
 
- !
 
- initializeFromMethodContext: aMethodContext
 
- 	model := HLDebuggerModel on: aMethodContext.
 
- 	self observeModel
 
- !
 
- inspectorWidget
 
- 	^ inspectorWidget ifNil: [ 
 
- 		inspectorWidget := HLInspectorWidget new ]
 
- !
 
- model
 
- 	^ model ifNil: [ model := HLDebuggerModel new ]
 
- !
 
- stackListWidget
 
- 	^ stackListWidget ifNil: [ 
 
- 		stackListWidget := (HLStackListWidget on: self model)
 
- 			next: self codeWidget;
 
- 			yourself ]
 
- ! !
 
- !HLDebugger methodsFor: 'actions'!
 
- focus
 
- 	self stackListWidget focus
 
- !
 
- observeModel
 
- 	self model announcer 
 
- 		on: HLDebuggerContextSelected
 
- 		send: #onContextSelected:
 
- 		to: self.
 
- 		
 
- 	self model announcer 
 
- 		on: HLDebuggerStepped
 
- 		send: #onContextSelected:
 
- 		to: self
 
- !
 
- unregister
 
- 	super unregister.
 
- 	self inspectorWidget unregister
 
- ! !
 
- !HLDebugger methodsFor: 'keybindings'!
 
- registerBindingsOn: aBindingGroup
 
- 	HLToolCommand 
 
- 		registerConcreteClassesOn: aBindingGroup 
 
- 		for: self model
 
- ! !
 
- !HLDebugger methodsFor: 'reactions'!
 
- onContextSelected: anAnnouncement
 
- 	self inspectorWidget inspect: (HLContextInspectorDecorator on: anAnnouncement context)
 
- ! !
 
- !HLDebugger methodsFor: 'rendering'!
 
- renderContentOn: html
 
- 	html with: (HLContainer with: (HLHorizontalSplitter
 
- 		with: self stackListWidget
 
- 		with: (HLVerticalSplitter
 
- 			with: self codeWidget
 
- 			with: self inspectorWidget)))
 
- ! !
 
- !HLDebugger class methodsFor: 'accessing'!
 
- tabClass
 
- 	^ 'debugger'
 
- !
 
- tabLabel
 
- 	^ 'Debugger'
 
- ! !
 
- !HLDebugger class methodsFor: 'instance creation'!
 
- on: aMethodContext
 
- 	^ self new
 
- 		initializeFromMethodContext: aMethodContext;
 
- 		yourself
 
- ! !
 
- HLBrowserCodeWidget subclass: #HLDebuggerCodeWidget
 
- 	instanceVariableNames: ''
 
- 	package: 'Helios-Debugger'!
 
- !HLDebuggerCodeWidget methodsFor: 'accessing'!
 
- contents: aString
 
- 	self clearHighlight.
 
- 	super contents: aString
 
- !
 
- editorOptions
 
- 	^ super editorOptions
 
- 		at: 'gutters' put: #('CodeMirror-linenumbers' 'stops');
 
- 		yourself
 
- ! !
 
- !HLDebuggerCodeWidget methodsFor: 'actions'!
 
- addStopAt: anInteger
 
- 	editor
 
- 		setGutterMarker: anInteger
 
- 		gutter: 'stops'
 
- 		value: '<div class="stop"></stop>' asJQuery toArray first
 
- !
 
- clearHighlight
 
- 	self editor clearGutter: 'stops'
 
- !
 
- highlight
 
- 	self highlightNode: self browserModel nextNode
 
- !
 
- highlightNode: aNode
 
- 	| token |
 
- 	
 
- 	aNode ifNotNil: [
 
- 		self
 
- 			clearHighlight;
 
- 			addStopAt: aNode positionStart x - 1.
 
- 		self editor 
 
- 			setSelection: #{ 'line' -> (aNode positionStart x - 1). 'ch' -> (aNode positionStart y - 1) }
 
- 			to: #{ 'line' -> (aNode positionEnd x - 1). 'ch' -> (aNode positionEnd y) } ]
 
- !
 
- observeBrowserModel
 
- 	super observeBrowserModel.
 
- 	
 
- 	self browserModel announcer 
 
- 		on: HLDebuggerContextSelected
 
- 		send: #onContextSelected
 
- 		to: self.
 
- 	
 
- 	self browserModel announcer 
 
- 		on: HLDebuggerStepped
 
- 		send: #onContextSelected
 
- 		to: self.
 
- 	
 
- 	self browserModel announcer 
 
- 		on: HLDebuggerWhere
 
- 		send: #onContextSelected
 
- 		to: self
 
- ! !
 
- !HLDebuggerCodeWidget methodsFor: 'reactions'!
 
- onContextSelected
 
- 	self highlight
 
- ! !
 
- HLToolModel subclass: #HLDebuggerModel
 
- 	instanceVariableNames: 'rootContext currentContext contexts'
 
- 	package: 'Helios-Debugger'!
 
- !HLDebuggerModel commentStamp!
 
- I am a model for Helios debugging.
 
- My instances hold a reference to an `AIContext` instance, built from a `MethodContext`. The context should be the root of the context stack.!
 
- !HLDebuggerModel methodsFor: 'accessing'!
 
- contexts
 
- 	^ contexts
 
- !
 
- currentContext
 
- 	currentContext ifNil: [ self currentContext: self rootContext ].
 
- 	^ currentContext
 
- !
 
- currentContext: aContext
 
- 	self withChangesDo: [ 
 
- 		self selectedMethod: aContext method.
 
- 		currentContext := aContext.
 
- 		self announcer announce: (HLDebuggerContextSelected new
 
- 			context: aContext;
 
- 			yourself) ]
 
- !
 
- interpreter
 
- 	^ self currentContext interpreter
 
- !
 
- nextNode
 
- 	^ self interpreter node
 
- !
 
- rootContext
 
- 	^ rootContext
 
- ! !
 
- !HLDebuggerModel methodsFor: 'actions'!
 
- restart
 
- 	self interpreter restart.
 
- 	self announcer announce: (HLDebuggerStepped new
 
- 		context: self currentContext;
 
- 		yourself)
 
- !
 
- skip
 
- 	self interpreter skip.
 
- 	self announcer announce: (HLDebuggerStepped new
 
- 		context: self currentContext;
 
- 		yourself)
 
- !
 
- stepOver
 
- 	self interpreter stepOver.
 
- 	self announcer announce: (HLDebuggerStepped new
 
- 		context: self currentContext;
 
- 		yourself)
 
- !
 
- where
 
- 	self announcer announce: HLDebuggerWhere new
 
- ! !
 
- !HLDebuggerModel methodsFor: 'initialization'!
 
- initializeContexts
 
- 	"Flatten the context stack into an OrderedCollection"
 
- 	
 
- 	| context |
 
- 	
 
- 	contexts := OrderedCollection new.
 
- 	context := self rootContext.
 
- 	
 
- 	[ context notNil ] whileTrue: [
 
- 		contexts add: context.
 
- 		context := context outerContext ]
 
- !
 
- initializeFromContext: aMethodContext
 
- 	rootContext := AIContext fromMethodContext: aMethodContext.
 
- 	self initializeContexts
 
- ! !
 
- !HLDebuggerModel class methodsFor: 'instance creation'!
 
- on: aMethodContext
 
- 	^ self new
 
- 		initializeFromContext: aMethodContext;
 
- 		yourself
 
- ! !
 
- Object subclass: #HLErrorHandler
 
- 	instanceVariableNames: ''
 
- 	package: 'Helios-Debugger'!
 
- !HLErrorHandler methodsFor: 'error handling'!
 
- handleError: anError
 
- 	self onErrorHandled.
 
- 	[ 
 
- 		(HLDebugger on: anError context) openAsTab 
 
- 	] 
 
- 		on: Error 
 
- 		do: [ :error | ErrorHandler new handleError: error ]
 
- !
 
- onErrorHandled
 
- 	"when an error is handled, we need to make sure that
 
- 	any progress bar widget gets removed. Because HLProgressBarWidget is asynchronous,
 
- 	it has to be done here."
 
- 	
 
- 	HLProgressWidget default 
 
- 		flush; 
 
- 		remove
 
- ! !
 
- HLToolListWidget subclass: #HLStackListWidget
 
- 	instanceVariableNames: ''
 
- 	package: 'Helios-Debugger'!
 
- !HLStackListWidget methodsFor: 'accessing'!
 
- items
 
- 	^ items ifNil: [ items := self model contexts ]
 
- !
 
- label
 
- 	^ 'Call stack'
 
- ! !
 
- !HLStackListWidget methodsFor: 'actions'!
 
- restart
 
- 	self model restart
 
- !
 
- selectItem: aContext
 
-    	self model currentContext: aContext
 
- !
 
- skip
 
- 	self model skip
 
- !
 
- stepOver
 
- 	self model stepOver
 
- !
 
- where
 
- 	self model where
 
- ! !
 
- !HLStackListWidget methodsFor: 'rendering'!
 
- renderButtonsOn: html
 
- 	html div 
 
- 		class: 'debugger_bar'; 
 
- 		with: [
 
- 			html button 
 
- 				class: 'btn restart';
 
- 				with: 'Restart';
 
- 				onClick: [ self restart ].
 
- 			html button 
 
- 				class: 'btn where';
 
- 				with: 'Where';
 
- 				onClick: [ self where ].
 
- 			html button 
 
- 				class: 'btn stepOver';
 
- 				with: 'Step over';
 
- 				onClick: [ self stepOver ].
 
- 			html button 
 
- 				class: 'btn skip';
 
- 				with: 'Skip';
 
- 				onClick: [ self skip ] ]
 
- ! !
 
 
  |