Browse Source

helios: first debugger implementation

Nicolas Petton 11 years ago
parent
commit
7915ddab6a

+ 1 - 1
helios.html

@@ -14,7 +14,7 @@
   </head> 
   <body> 
     
-    <script type='text/javascript'> loadAmber({packages: ['Spaces', 'Helios-Core', 'Helios-Exceptions', 'Helios-Commands-Core','Helios-Commands-Tools', 'Helios-Commands-Browser', 'Helios-Layout','Helios-KeyBindings', 'Helios-Browser', 'Helios-Workspace', 'Helios-Transcript', 'Helios-Inspector', 'Helios-References', 'Helios-Announcements']}) </script>
+    <script type='text/javascript'> loadAmber({packages: ['Spaces', 'Helios-Core', 'Helios-Exceptions', 'Helios-Commands-Core','Helios-Commands-Tools', 'Helios-Commands-Browser', 'Helios-Layout','Helios-KeyBindings', 'Helios-Browser', 'Helios-Workspace', 'Helios-Transcript', 'Helios-Debugger', 'Helios-Inspector', 'Helios-References', 'Helios-Announcements']}) </script>
     <link rel="stylesheet" type="text/css" href='css/helios.css' />
     
     <div id="helper">Loading Helios...</div>

+ 46 - 12
js/Compiler-Interpreter.deploy.js

@@ -1,5 +1,36 @@
 smalltalk.addPackage('Compiler-Interpreter');
-smalltalk.addClass('AIContext', smalltalk.NodeVisitor, ['outerContext', 'pc', 'locals', 'method'], 'Compiler-Interpreter');
+smalltalk.addClass('AIContext', smalltalk.NodeVisitor, ['methodContext', 'outerContext', 'pc', 'locals', 'method'], 'Compiler-Interpreter');
+smalltalk.addMethod(
+smalltalk.method({
+selector: "asString",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(self["@methodContext"])._asString();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"asString",{},smalltalk.AIContext)})},
+messageSends: ["asString"]}),
+smalltalk.AIContext);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "home",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $2,$1;
+$2=_st(self)._isBlockContext();
+if(smalltalk.assert($2)){
+$1=_st(_st(self)._outerContext())._methodContext();
+} else {
+$1=self;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"home",{},smalltalk.AIContext)})},
+messageSends: ["ifTrue:ifFalse:", "methodContext", "outerContext", "isBlockContext"]}),
+smalltalk.AIContext);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "initializeFromMethodContext:",
@@ -7,6 +38,7 @@ fn: function (aMethodContext){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 var $1;
+self["@methodContext"]=aMethodContext;
 _st(self)._pc_(_st(aMethodContext)._pc());
 _st(self)._receiver_(_st(aMethodContext)._receiver());
 _st(self)._method_(_st(aMethodContext)._method());
@@ -37,6 +69,19 @@ return self}, function($ctx1) {$ctx1.fill(self,"initializeLocals",{},smalltalk.A
 messageSends: ["new", "at:put:"]}),
 smalltalk.AIContext);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "isBlockContext",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(self["@methodContext"])._isBlockContext();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"isBlockContext",{},smalltalk.AIContext)})},
+messageSends: ["isBlockContext"]}),
+smalltalk.AIContext);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "localAt:",
@@ -381,17 +426,6 @@ return self}, function($ctx1) {$ctx1.fill(self,"restart",{},smalltalk.ASTDebugge
 messageSends: ["shouldBeImplemented"]}),
 smalltalk.ASTDebugger);
 
-smalltalk.addMethod(
-smalltalk.method({
-selector: "resume",
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-_st(self)._shouldBeImplemented();
-return self}, function($ctx1) {$ctx1.fill(self,"resume",{},smalltalk.ASTDebugger)})},
-messageSends: ["shouldBeImplemented"]}),
-smalltalk.ASTDebugger);
-
 smalltalk.addMethod(
 smalltalk.method({
 selector: "step",

+ 62 - 18
js/Compiler-Interpreter.js

@@ -1,6 +1,47 @@
 smalltalk.addPackage('Compiler-Interpreter');
-smalltalk.addClass('AIContext', smalltalk.NodeVisitor, ['outerContext', 'pc', 'locals', 'method'], 'Compiler-Interpreter');
+smalltalk.addClass('AIContext', smalltalk.NodeVisitor, ['methodContext', 'outerContext', 'pc', 'locals', 'method'], 'Compiler-Interpreter');
 smalltalk.AIContext.comment="I am like a `MethodContext`, used by the `ASTInterpreter`.\x0aUnlike a `MethodContext`, my instances are not read-only.\x0a\x0aWhen debugging, my instances are created by copying the current `MethodContext` (thisContext)"
+smalltalk.addMethod(
+smalltalk.method({
+selector: "asString",
+category: 'converting',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(self["@methodContext"])._asString();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"asString",{},smalltalk.AIContext)})},
+args: [],
+source: "asString\x0a\x09^ methodContext asString",
+messageSends: ["asString"],
+referencedClasses: []
+}),
+smalltalk.AIContext);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "home",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $2,$1;
+$2=_st(self)._isBlockContext();
+if(smalltalk.assert($2)){
+$1=_st(_st(self)._outerContext())._methodContext();
+} else {
+$1=self;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"home",{},smalltalk.AIContext)})},
+args: [],
+source: "home\x0a\x09^ self isBlockContext \x0a\x09\x09ifTrue: [ self outerContext methodContext ]\x0a\x09\x09ifFalse: [ self ]",
+messageSends: ["ifTrue:ifFalse:", "methodContext", "outerContext", "isBlockContext"],
+referencedClasses: []
+}),
+smalltalk.AIContext);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "initializeFromMethodContext:",
@@ -9,6 +50,7 @@ fn: function (aMethodContext){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 var $1;
+self["@methodContext"]=aMethodContext;
 _st(self)._pc_(_st(aMethodContext)._pc());
 _st(self)._receiver_(_st(aMethodContext)._receiver());
 _st(self)._method_(_st(aMethodContext)._method());
@@ -24,7 +66,7 @@ return _st(_st(self)._locals())._at_put_(key,value);
 }, function($ctx2) {$ctx2.fillBlock({key:key,value:value},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"initializeFromMethodContext:",{aMethodContext:aMethodContext},smalltalk.AIContext)})},
 args: ["aMethodContext"],
-source: "initializeFromMethodContext: aMethodContext\x0a\x09self pc: aMethodContext pc.\x0a\x09self receiver: aMethodContext receiver.\x0a\x09self method: aMethodContext method.\x0a\x09aMethodContext outerContext ifNotNil: [\x0a\x09\x09self outerContext: (self class fromMethodContext: aMethodContext outerContext) ].\x0a\x09aMethodContext locals keysAndValuesDo: [ :key :value |\x0a\x09\x09self locals at: key put: value ]",
+source: "initializeFromMethodContext: aMethodContext\x0a\x09methodContext := aMethodContext.\x0a\x09\x0a\x09self pc: aMethodContext pc.\x0a\x09self receiver: aMethodContext receiver.\x0a\x09self method: aMethodContext method.\x0a\x09aMethodContext outerContext ifNotNil: [\x0a\x09\x09self outerContext: (self class fromMethodContext: aMethodContext outerContext) ].\x0a\x09aMethodContext locals keysAndValuesDo: [ :key :value |\x0a\x09\x09self locals at: key put: value ]",
 messageSends: ["pc:", "pc", "receiver:", "receiver", "method:", "method", "ifNotNil:", "outerContext:", "fromMethodContext:", "outerContext", "class", "keysAndValuesDo:", "at:put:", "locals"],
 referencedClasses: []
 }),
@@ -48,6 +90,24 @@ referencedClasses: ["Dictionary"]
 }),
 smalltalk.AIContext);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "isBlockContext",
+category: 'testing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(self["@methodContext"])._isBlockContext();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"isBlockContext",{},smalltalk.AIContext)})},
+args: [],
+source: "isBlockContext\x0a\x09^ methodContext isBlockContext",
+messageSends: ["isBlockContext"],
+referencedClasses: []
+}),
+smalltalk.AIContext);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "localAt:",
@@ -518,22 +578,6 @@ referencedClasses: []
 }),
 smalltalk.ASTDebugger);
 
-smalltalk.addMethod(
-smalltalk.method({
-selector: "resume",
-category: 'stepping',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
-_st(self)._shouldBeImplemented();
-return self}, function($ctx1) {$ctx1.fill(self,"resume",{},smalltalk.ASTDebugger)})},
-args: [],
-source: "resume\x0a\x09self shouldBeImplemented",
-messageSends: ["shouldBeImplemented"],
-referencedClasses: []
-}),
-smalltalk.ASTDebugger);
-
 smalltalk.addMethod(
 smalltalk.method({
 selector: "step",

+ 27 - 0
js/Helios-Announcements.deploy.js

@@ -84,6 +84,33 @@ smalltalk.addClass('HLInspectItRequested', smalltalk.HLCodeHandled, [], 'Helios-
 smalltalk.addClass('HLPrintItRequested', smalltalk.HLCodeHandled, [], 'Helios-Announcements');
 
 
+smalltalk.addClass('HLDebuggerContextSelected', smalltalk.HLAnnouncement, ['context'], 'Helios-Announcements');
+smalltalk.addMethod(
+smalltalk.method({
+selector: "context",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=self["@context"];
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"context",{},smalltalk.HLDebuggerContextSelected)})},
+messageSends: []}),
+smalltalk.HLDebuggerContextSelected);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "context:",
+fn: function (aContext){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self["@context"]=aContext;
+return self}, function($ctx1) {$ctx1.fill(self,"context:",{aContext:aContext},smalltalk.HLDebuggerContextSelected)})},
+messageSends: []}),
+smalltalk.HLDebuggerContextSelected);
+
+
+
 smalltalk.addClass('HLDiveRequested', smalltalk.HLAnnouncement, [], 'Helios-Announcements');
 
 

+ 37 - 0
js/Helios-Announcements.js

@@ -109,6 +109,43 @@ smalltalk.addClass('HLInspectItRequested', smalltalk.HLCodeHandled, [], 'Helios-
 smalltalk.addClass('HLPrintItRequested', smalltalk.HLCodeHandled, [], 'Helios-Announcements');
 
 
+smalltalk.addClass('HLDebuggerContextSelected', smalltalk.HLAnnouncement, ['context'], 'Helios-Announcements');
+smalltalk.addMethod(
+smalltalk.method({
+selector: "context",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=self["@context"];
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"context",{},smalltalk.HLDebuggerContextSelected)})},
+args: [],
+source: "context\x0a\x09^ context",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLDebuggerContextSelected);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "context:",
+category: 'accessing',
+fn: function (aContext){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self["@context"]=aContext;
+return self}, function($ctx1) {$ctx1.fill(self,"context:",{aContext:aContext},smalltalk.HLDebuggerContextSelected)})},
+args: ["aContext"],
+source: "context: aContext\x0a\x09context := aContext",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLDebuggerContextSelected);
+
+
+
 smalltalk.addClass('HLDiveRequested', smalltalk.HLAnnouncement, [], 'Helios-Announcements');
 
 

+ 1 - 1
js/Helios-Browser.js

@@ -3097,7 +3097,7 @@ $1=$2;
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"items",{},smalltalk.HLPackagesListWidget)})},
 args: [],
-source: "items\x0a\x09^ items ifNil: [self initializeItems]",
+source: "items\x0a\x09^ items ifNil: [ self initializeItems ]",
 messageSends: ["ifNil:", "initializeItems"],
 referencedClasses: []
 }),

+ 0 - 3
js/Helios-Core.deploy.js

@@ -1648,9 +1648,6 @@ smalltalk.HLRequest);
 
 
 
-smalltalk.addClass('HLDebugger', smalltalk.HLWidget, [], 'Helios-Core');
-
-
 smalltalk.addClass('HLFocusableWidget', smalltalk.HLWidget, [], 'Helios-Core');
 smalltalk.addMethod(
 smalltalk.method({

+ 0 - 3
js/Helios-Core.js

@@ -2177,9 +2177,6 @@ smalltalk.HLRequest);
 
 
 
-smalltalk.addClass('HLDebugger', smalltalk.HLWidget, [], 'Helios-Core');
-
-
 smalltalk.addClass('HLFocusableWidget', smalltalk.HLWidget, [], 'Helios-Core');
 smalltalk.addMethod(
 smalltalk.method({

+ 429 - 0
js/Helios-Debugger.deploy.js

@@ -0,0 +1,429 @@
+smalltalk.addPackage('Helios-Debugger');
+smalltalk.addClass('HLContextInspectorDecorator', smalltalk.Object, ['context'], 'Helios-Debugger');
+smalltalk.addMethod(
+smalltalk.method({
+selector: "context",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=self["@context"];
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"context",{},smalltalk.HLContextInspectorDecorator)})},
+messageSends: []}),
+smalltalk.HLContextInspectorDecorator);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "initializeFromContext:",
+fn: function (aContext){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self["@context"]=aContext;
+return self}, function($ctx1) {$ctx1.fill(self,"initializeFromContext:",{aContext:aContext},smalltalk.HLContextInspectorDecorator)})},
+messageSends: []}),
+smalltalk.HLContextInspectorDecorator);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "inspectOn:",
+fn: function (anInspector){
+var self=this;
+var variables,inspectedContext;
+function $Dictionary(){return smalltalk.Dictionary||(typeof Dictionary=="undefined"?nil:Dictionary)}
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2;
+variables=_st($Dictionary())._new();
+inspectedContext=_st(self)._context();
+_st(variables)._addAll_(_st(inspectedContext)._locals());
+_st((function(){
+return smalltalk.withContext(function($ctx2) {
+return _st(inspectedContext)._isBlockContext();
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}))._whileTrue_((function(){
+return smalltalk.withContext(function($ctx2) {
+inspectedContext=_st(inspectedContext)._outerContext();
+inspectedContext;
+return _st(variables)._addAll_(_st(inspectedContext)._locals());
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+$1=anInspector;
+_st($1)._setLabel_("Context");
+$2=_st($1)._setVariables_(variables);
+return self}, function($ctx1) {$ctx1.fill(self,"inspectOn:",{anInspector:anInspector,variables:variables,inspectedContext:inspectedContext},smalltalk.HLContextInspectorDecorator)})},
+messageSends: ["new", "context", "addAll:", "locals", "whileTrue:", "outerContext", "isBlockContext", "setLabel:", "setVariables:"]}),
+smalltalk.HLContextInspectorDecorator);
+
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "on:",
+fn: function (aContext){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $2,$3,$1;
+$2=_st(self)._new();
+_st($2)._initializeFromContext_(aContext);
+$3=_st($2)._yourself();
+$1=$3;
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"on:",{aContext:aContext},smalltalk.HLContextInspectorDecorator.klass)})},
+messageSends: ["initializeFromContext:", "new", "yourself"]}),
+smalltalk.HLContextInspectorDecorator.klass);
+
+
+smalltalk.addClass('HLDebugger', smalltalk.HLFocusableWidget, ['model', 'stackListWidget', 'codeWidget', 'inspectorWidget'], 'Helios-Debugger');
+smalltalk.addMethod(
+smalltalk.method({
+selector: "codeWidget",
+fn: function (){
+var self=this;
+function $HLBrowserCodeWidget(){return smalltalk.HLBrowserCodeWidget||(typeof HLBrowserCodeWidget=="undefined"?nil:HLBrowserCodeWidget)}
+return smalltalk.withContext(function($ctx1) { 
+var $2,$3,$4,$1;
+$2=self["@codeWidget"];
+if(($receiver = $2) == nil || $receiver == undefined){
+$3=_st($HLBrowserCodeWidget())._new();
+_st($3)._browserModel_(_st(self)._model());
+$4=_st($3)._yourself();
+self["@codeWidget"]=$4;
+$1=self["@codeWidget"];
+} else {
+$1=$2;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"codeWidget",{},smalltalk.HLDebugger)})},
+messageSends: ["ifNil:", "browserModel:", "model", "new", "yourself"]}),
+smalltalk.HLDebugger);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "focus",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+_st(_st(self)._stackListWidget())._focus();
+return self}, function($ctx1) {$ctx1.fill(self,"focus",{},smalltalk.HLDebugger)})},
+messageSends: ["focus", "stackListWidget"]}),
+smalltalk.HLDebugger);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "initializeFromMethodContext:",
+fn: function (aMethodContext){
+var self=this;
+function $HLDebuggerModel(){return smalltalk.HLDebuggerModel||(typeof HLDebuggerModel=="undefined"?nil:HLDebuggerModel)}
+return smalltalk.withContext(function($ctx1) { 
+self["@model"]=_st($HLDebuggerModel())._on_(aMethodContext);
+_st(self)._observeModel();
+return self}, function($ctx1) {$ctx1.fill(self,"initializeFromMethodContext:",{aMethodContext:aMethodContext},smalltalk.HLDebugger)})},
+messageSends: ["on:", "observeModel"]}),
+smalltalk.HLDebugger);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "inspectorWidget",
+fn: function (){
+var self=this;
+function $HLInspectorWidget(){return smalltalk.HLInspectorWidget||(typeof HLInspectorWidget=="undefined"?nil:HLInspectorWidget)}
+return smalltalk.withContext(function($ctx1) { 
+var $2,$1;
+$2=self["@inspectorWidget"];
+if(($receiver = $2) == nil || $receiver == undefined){
+self["@inspectorWidget"]=_st($HLInspectorWidget())._new();
+$1=self["@inspectorWidget"];
+} else {
+$1=$2;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"inspectorWidget",{},smalltalk.HLDebugger)})},
+messageSends: ["ifNil:", "new"]}),
+smalltalk.HLDebugger);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "model",
+fn: function (){
+var self=this;
+function $HLDebuggerModel(){return smalltalk.HLDebuggerModel||(typeof HLDebuggerModel=="undefined"?nil:HLDebuggerModel)}
+return smalltalk.withContext(function($ctx1) { 
+var $2,$1;
+$2=self["@model"];
+if(($receiver = $2) == nil || $receiver == undefined){
+self["@model"]=_st($HLDebuggerModel())._new();
+$1=self["@model"];
+} else {
+$1=$2;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"model",{},smalltalk.HLDebugger)})},
+messageSends: ["ifNil:", "new"]}),
+smalltalk.HLDebugger);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "observeModel",
+fn: function (){
+var self=this;
+function $HLDebuggerContextSelected(){return smalltalk.HLDebuggerContextSelected||(typeof HLDebuggerContextSelected=="undefined"?nil:HLDebuggerContextSelected)}
+return smalltalk.withContext(function($ctx1) { 
+_st(_st(_st(self)._model())._announcer())._on_send_to_($HLDebuggerContextSelected(),"onContextSelected:",self);
+return self}, function($ctx1) {$ctx1.fill(self,"observeModel",{},smalltalk.HLDebugger)})},
+messageSends: ["on:send:to:", "announcer", "model"]}),
+smalltalk.HLDebugger);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "onContextSelected:",
+fn: function (anAnnouncement){
+var self=this;
+function $HLContextInspectorDecorator(){return smalltalk.HLContextInspectorDecorator||(typeof HLContextInspectorDecorator=="undefined"?nil:HLContextInspectorDecorator)}
+return smalltalk.withContext(function($ctx1) { 
+_st(_st(self)._inspectorWidget())._inspect_(_st($HLContextInspectorDecorator())._on_(_st(anAnnouncement)._context()));
+return self}, function($ctx1) {$ctx1.fill(self,"onContextSelected:",{anAnnouncement:anAnnouncement},smalltalk.HLDebugger)})},
+messageSends: ["inspect:", "on:", "context", "inspectorWidget"]}),
+smalltalk.HLDebugger);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "open",
+fn: function (){
+var self=this;
+function $HLTab(){return smalltalk.HLTab||(typeof HLTab=="undefined"?nil:HLTab)}
+function $HLManager(){return smalltalk.HLManager||(typeof HLManager=="undefined"?nil:HLManager)}
+return smalltalk.withContext(function($ctx1) { 
+_st(_st($HLManager())._current())._addTab_(_st($HLTab())._on_labelled_(self,_st(_st(self)._class())._tabLabel()));
+return self}, function($ctx1) {$ctx1.fill(self,"open",{},smalltalk.HLDebugger)})},
+messageSends: ["addTab:", "on:labelled:", "tabLabel", "class", "current"]}),
+smalltalk.HLDebugger);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "renderContentOn:",
+fn: function (html){
+var self=this;
+function $HLVerticalSplitter(){return smalltalk.HLVerticalSplitter||(typeof HLVerticalSplitter=="undefined"?nil:HLVerticalSplitter)}
+function $HLHorizontalSplitter(){return smalltalk.HLHorizontalSplitter||(typeof HLHorizontalSplitter=="undefined"?nil:HLHorizontalSplitter)}
+function $HLContainer(){return smalltalk.HLContainer||(typeof HLContainer=="undefined"?nil:HLContainer)}
+return smalltalk.withContext(function($ctx1) { 
+_st(html)._with_(_st($HLContainer())._with_(_st($HLHorizontalSplitter())._with_with_(_st(self)._stackListWidget(),_st($HLVerticalSplitter())._with_with_(_st(self)._codeWidget(),_st(self)._inspectorWidget()))));
+return self}, function($ctx1) {$ctx1.fill(self,"renderContentOn:",{html:html},smalltalk.HLDebugger)})},
+messageSends: ["with:", "with:with:", "stackListWidget", "codeWidget", "inspectorWidget"]}),
+smalltalk.HLDebugger);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "stackListWidget",
+fn: function (){
+var self=this;
+function $HLStackListWidget(){return smalltalk.HLStackListWidget||(typeof HLStackListWidget=="undefined"?nil:HLStackListWidget)}
+return smalltalk.withContext(function($ctx1) { 
+var $2,$3,$4,$1;
+$2=self["@stackListWidget"];
+if(($receiver = $2) == nil || $receiver == undefined){
+$3=_st($HLStackListWidget())._on_(_st(self)._model());
+_st($3)._next_(_st(self)._codeWidget());
+$4=_st($3)._yourself();
+self["@stackListWidget"]=$4;
+$1=self["@stackListWidget"];
+} else {
+$1=$2;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"stackListWidget",{},smalltalk.HLDebugger)})},
+messageSends: ["ifNil:", "next:", "codeWidget", "on:", "model", "yourself"]}),
+smalltalk.HLDebugger);
+
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "on:",
+fn: function (aMethodContext){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $2,$3,$1;
+$2=_st(self)._new();
+_st($2)._initializeFromMethodContext_(aMethodContext);
+$3=_st($2)._yourself();
+$1=$3;
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"on:",{aMethodContext:aMethodContext},smalltalk.HLDebugger.klass)})},
+messageSends: ["initializeFromMethodContext:", "new", "yourself"]}),
+smalltalk.HLDebugger.klass);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "tabLabel",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return "Debugger";
+}, function($ctx1) {$ctx1.fill(self,"tabLabel",{},smalltalk.HLDebugger.klass)})},
+messageSends: []}),
+smalltalk.HLDebugger.klass);
+
+
+smalltalk.addClass('HLDebuggerModel', smalltalk.HLToolModel, ['rootContext', 'currentContext', 'contexts'], 'Helios-Debugger');
+smalltalk.addMethod(
+smalltalk.method({
+selector: "contexts",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=self["@contexts"];
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"contexts",{},smalltalk.HLDebuggerModel)})},
+messageSends: []}),
+smalltalk.HLDebuggerModel);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "currentContext",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2;
+$1=self["@currentContext"];
+if(($receiver = $1) == nil || $receiver == undefined){
+_st(self)._currentContext_(_st(self)._rootContext());
+} else {
+$1;
+};
+$2=self["@currentContext"];
+return $2;
+}, function($ctx1) {$ctx1.fill(self,"currentContext",{},smalltalk.HLDebuggerModel)})},
+messageSends: ["ifNil:", "currentContext:", "rootContext"]}),
+smalltalk.HLDebuggerModel);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "currentContext:",
+fn: function (aContext){
+var self=this;
+function $HLDebuggerContextSelected(){return smalltalk.HLDebuggerContextSelected||(typeof HLDebuggerContextSelected=="undefined"?nil:HLDebuggerContextSelected)}
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2;
+_st(self)._withChangesDo_((function(){
+return smalltalk.withContext(function($ctx2) {
+self["@currentContext"]=aContext;
+self["@currentContext"];
+$1=_st($HLDebuggerContextSelected())._new();
+_st($1)._context_(aContext);
+$2=_st($1)._yourself();
+_st(_st(self)._announcer())._announce_($2);
+return _st(self)._selectedMethod_(_st(aContext)._method());
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+return self}, function($ctx1) {$ctx1.fill(self,"currentContext:",{aContext:aContext},smalltalk.HLDebuggerModel)})},
+messageSends: ["withChangesDo:", "announce:", "context:", "new", "yourself", "announcer", "selectedMethod:", "method"]}),
+smalltalk.HLDebuggerModel);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "initializeContexts",
+fn: function (){
+var self=this;
+var context;
+function $OrderedCollection(){return smalltalk.OrderedCollection||(typeof OrderedCollection=="undefined"?nil:OrderedCollection)}
+return smalltalk.withContext(function($ctx1) { 
+self["@contexts"]=_st($OrderedCollection())._new();
+context=_st(self)._rootContext();
+_st((function(){
+return smalltalk.withContext(function($ctx2) {
+return _st(context)._notNil();
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}))._whileTrue_((function(){
+return smalltalk.withContext(function($ctx2) {
+_st(self["@contexts"])._add_(context);
+context=_st(context)._outerContext();
+return context;
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+return self}, function($ctx1) {$ctx1.fill(self,"initializeContexts",{context:context},smalltalk.HLDebuggerModel)})},
+messageSends: ["new", "rootContext", "whileTrue:", "add:", "outerContext", "notNil"]}),
+smalltalk.HLDebuggerModel);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "initializeFromContext:",
+fn: function (aMethodContext){
+var self=this;
+function $AIContext(){return smalltalk.AIContext||(typeof AIContext=="undefined"?nil:AIContext)}
+return smalltalk.withContext(function($ctx1) { 
+self["@rootContext"]=_st($AIContext())._fromMethodContext_(aMethodContext);
+_st(self)._initializeContexts();
+return self}, function($ctx1) {$ctx1.fill(self,"initializeFromContext:",{aMethodContext:aMethodContext},smalltalk.HLDebuggerModel)})},
+messageSends: ["fromMethodContext:", "initializeContexts"]}),
+smalltalk.HLDebuggerModel);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "rootContext",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=self["@rootContext"];
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"rootContext",{},smalltalk.HLDebuggerModel)})},
+messageSends: []}),
+smalltalk.HLDebuggerModel);
+
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "on:",
+fn: function (aMethodContext){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $2,$3,$1;
+$2=_st(self)._new();
+_st($2)._initializeFromContext_(aMethodContext);
+$3=_st($2)._yourself();
+$1=$3;
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"on:",{aMethodContext:aMethodContext},smalltalk.HLDebuggerModel.klass)})},
+messageSends: ["initializeFromContext:", "new", "yourself"]}),
+smalltalk.HLDebuggerModel.klass);
+
+
+smalltalk.addClass('HLStackListWidget', smalltalk.HLToolListWidget, [], 'Helios-Debugger');
+smalltalk.addMethod(
+smalltalk.method({
+selector: "items",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $2,$1;
+$2=self["@items"];
+if(($receiver = $2) == nil || $receiver == undefined){
+self["@items"]=_st(_st(self)._model())._contexts();
+$1=self["@items"];
+} else {
+$1=$2;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"items",{},smalltalk.HLStackListWidget)})},
+messageSends: ["ifNil:", "contexts", "model"]}),
+smalltalk.HLStackListWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "label",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return "Stack";
+}, function($ctx1) {$ctx1.fill(self,"label",{},smalltalk.HLStackListWidget)})},
+messageSends: []}),
+smalltalk.HLStackListWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "selectItem:",
+fn: function (aContext){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+_st(_st(self)._model())._currentContext_(aContext);
+return self}, function($ctx1) {$ctx1.fill(self,"selectItem:",{aContext:aContext},smalltalk.HLStackListWidget)})},
+messageSends: ["currentContext:", "model"]}),
+smalltalk.HLStackListWidget);
+
+
+

+ 561 - 0
js/Helios-Debugger.js

@@ -0,0 +1,561 @@
+smalltalk.addPackage('Helios-Debugger');
+smalltalk.addClass('HLContextInspectorDecorator', smalltalk.Object, ['context'], 'Helios-Debugger');
+smalltalk.addMethod(
+smalltalk.method({
+selector: "context",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=self["@context"];
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"context",{},smalltalk.HLContextInspectorDecorator)})},
+args: [],
+source: "context\x0a\x09^ context",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLContextInspectorDecorator);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "initializeFromContext:",
+category: 'initialization',
+fn: function (aContext){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self["@context"]=aContext;
+return self}, function($ctx1) {$ctx1.fill(self,"initializeFromContext:",{aContext:aContext},smalltalk.HLContextInspectorDecorator)})},
+args: ["aContext"],
+source: "initializeFromContext: aContext\x0a\x09context := aContext",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLContextInspectorDecorator);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "inspectOn:",
+category: 'inspecting',
+fn: function (anInspector){
+var self=this;
+var variables,inspectedContext;
+function $Dictionary(){return smalltalk.Dictionary||(typeof Dictionary=="undefined"?nil:Dictionary)}
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2;
+variables=_st($Dictionary())._new();
+inspectedContext=_st(self)._context();
+_st(variables)._addAll_(_st(inspectedContext)._locals());
+_st((function(){
+return smalltalk.withContext(function($ctx2) {
+return _st(inspectedContext)._isBlockContext();
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}))._whileTrue_((function(){
+return smalltalk.withContext(function($ctx2) {
+inspectedContext=_st(inspectedContext)._outerContext();
+inspectedContext;
+return _st(variables)._addAll_(_st(inspectedContext)._locals());
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+$1=anInspector;
+_st($1)._setLabel_("Context");
+$2=_st($1)._setVariables_(variables);
+return self}, function($ctx1) {$ctx1.fill(self,"inspectOn:",{anInspector:anInspector,variables:variables,inspectedContext:inspectedContext},smalltalk.HLContextInspectorDecorator)})},
+args: ["anInspector"],
+source: "inspectOn: anInspector\x0a\x09| variables inspectedContext |\x0a\x09\x0a\x09variables := Dictionary new.\x0a\x09inspectedContext := self context.\x0a\x09\x0a\x09variables addAll: inspectedContext locals.\x0a\x09\x0a\x09[ inspectedContext isBlockContext ] whileTrue: [\x0a\x09\x09inspectedContext := inspectedContext outerContext.\x0a\x09\x09variables addAll: inspectedContext locals ].\x0a\x09\x0a\x09anInspector\x0a\x09\x09setLabel: 'Context';\x0a\x09\x09setVariables: variables",
+messageSends: ["new", "context", "addAll:", "locals", "whileTrue:", "outerContext", "isBlockContext", "setLabel:", "setVariables:"],
+referencedClasses: ["Dictionary"]
+}),
+smalltalk.HLContextInspectorDecorator);
+
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "on:",
+category: 'instance creation',
+fn: function (aContext){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $2,$3,$1;
+$2=_st(self)._new();
+_st($2)._initializeFromContext_(aContext);
+$3=_st($2)._yourself();
+$1=$3;
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"on:",{aContext:aContext},smalltalk.HLContextInspectorDecorator.klass)})},
+args: ["aContext"],
+source: "on: aContext\x0a\x09^ self new\x0a\x09\x09initializeFromContext: aContext;\x0a\x09\x09yourself",
+messageSends: ["initializeFromContext:", "new", "yourself"],
+referencedClasses: []
+}),
+smalltalk.HLContextInspectorDecorator.klass);
+
+
+smalltalk.addClass('HLDebugger', smalltalk.HLFocusableWidget, ['model', 'stackListWidget', 'codeWidget', 'inspectorWidget'], 'Helios-Debugger');
+smalltalk.HLDebugger.comment="I am the main widget for the Helios debugger."
+smalltalk.addMethod(
+smalltalk.method({
+selector: "codeWidget",
+category: 'accessing',
+fn: function (){
+var self=this;
+function $HLBrowserCodeWidget(){return smalltalk.HLBrowserCodeWidget||(typeof HLBrowserCodeWidget=="undefined"?nil:HLBrowserCodeWidget)}
+return smalltalk.withContext(function($ctx1) { 
+var $2,$3,$4,$1;
+$2=self["@codeWidget"];
+if(($receiver = $2) == nil || $receiver == undefined){
+$3=_st($HLBrowserCodeWidget())._new();
+_st($3)._browserModel_(_st(self)._model());
+$4=_st($3)._yourself();
+self["@codeWidget"]=$4;
+$1=self["@codeWidget"];
+} else {
+$1=$2;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"codeWidget",{},smalltalk.HLDebugger)})},
+args: [],
+source: "codeWidget\x0a\x09^ codeWidget ifNil: [ codeWidget := HLBrowserCodeWidget new\x0a\x09\x09browserModel: self model;\x0a\x09\x09yourself ]",
+messageSends: ["ifNil:", "browserModel:", "model", "new", "yourself"],
+referencedClasses: ["HLBrowserCodeWidget"]
+}),
+smalltalk.HLDebugger);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "focus",
+category: 'actions',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+_st(_st(self)._stackListWidget())._focus();
+return self}, function($ctx1) {$ctx1.fill(self,"focus",{},smalltalk.HLDebugger)})},
+args: [],
+source: "focus\x0a\x09self stackListWidget focus",
+messageSends: ["focus", "stackListWidget"],
+referencedClasses: []
+}),
+smalltalk.HLDebugger);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "initializeFromMethodContext:",
+category: 'accessing',
+fn: function (aMethodContext){
+var self=this;
+function $HLDebuggerModel(){return smalltalk.HLDebuggerModel||(typeof HLDebuggerModel=="undefined"?nil:HLDebuggerModel)}
+return smalltalk.withContext(function($ctx1) { 
+self["@model"]=_st($HLDebuggerModel())._on_(aMethodContext);
+_st(self)._observeModel();
+return self}, function($ctx1) {$ctx1.fill(self,"initializeFromMethodContext:",{aMethodContext:aMethodContext},smalltalk.HLDebugger)})},
+args: ["aMethodContext"],
+source: "initializeFromMethodContext: aMethodContext\x0a\x09model := HLDebuggerModel on: aMethodContext.\x0a\x09self observeModel",
+messageSends: ["on:", "observeModel"],
+referencedClasses: ["HLDebuggerModel"]
+}),
+smalltalk.HLDebugger);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "inspectorWidget",
+category: 'accessing',
+fn: function (){
+var self=this;
+function $HLInspectorWidget(){return smalltalk.HLInspectorWidget||(typeof HLInspectorWidget=="undefined"?nil:HLInspectorWidget)}
+return smalltalk.withContext(function($ctx1) { 
+var $2,$1;
+$2=self["@inspectorWidget"];
+if(($receiver = $2) == nil || $receiver == undefined){
+self["@inspectorWidget"]=_st($HLInspectorWidget())._new();
+$1=self["@inspectorWidget"];
+} else {
+$1=$2;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"inspectorWidget",{},smalltalk.HLDebugger)})},
+args: [],
+source: "inspectorWidget\x0a\x09^ inspectorWidget ifNil: [ \x0a\x09\x09inspectorWidget := HLInspectorWidget new ]",
+messageSends: ["ifNil:", "new"],
+referencedClasses: ["HLInspectorWidget"]
+}),
+smalltalk.HLDebugger);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "model",
+category: 'accessing',
+fn: function (){
+var self=this;
+function $HLDebuggerModel(){return smalltalk.HLDebuggerModel||(typeof HLDebuggerModel=="undefined"?nil:HLDebuggerModel)}
+return smalltalk.withContext(function($ctx1) { 
+var $2,$1;
+$2=self["@model"];
+if(($receiver = $2) == nil || $receiver == undefined){
+self["@model"]=_st($HLDebuggerModel())._new();
+$1=self["@model"];
+} else {
+$1=$2;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"model",{},smalltalk.HLDebugger)})},
+args: [],
+source: "model\x0a\x09^ model ifNil: [ model := HLDebuggerModel new ]",
+messageSends: ["ifNil:", "new"],
+referencedClasses: ["HLDebuggerModel"]
+}),
+smalltalk.HLDebugger);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "observeModel",
+category: 'actions',
+fn: function (){
+var self=this;
+function $HLDebuggerContextSelected(){return smalltalk.HLDebuggerContextSelected||(typeof HLDebuggerContextSelected=="undefined"?nil:HLDebuggerContextSelected)}
+return smalltalk.withContext(function($ctx1) { 
+_st(_st(_st(self)._model())._announcer())._on_send_to_($HLDebuggerContextSelected(),"onContextSelected:",self);
+return self}, function($ctx1) {$ctx1.fill(self,"observeModel",{},smalltalk.HLDebugger)})},
+args: [],
+source: "observeModel\x0a\x09self model announcer \x0a\x09\x09on: HLDebuggerContextSelected\x0a\x09\x09send: #onContextSelected:\x0a\x09\x09to: self",
+messageSends: ["on:send:to:", "announcer", "model"],
+referencedClasses: ["HLDebuggerContextSelected"]
+}),
+smalltalk.HLDebugger);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "onContextSelected:",
+category: 'reactions',
+fn: function (anAnnouncement){
+var self=this;
+function $HLContextInspectorDecorator(){return smalltalk.HLContextInspectorDecorator||(typeof HLContextInspectorDecorator=="undefined"?nil:HLContextInspectorDecorator)}
+return smalltalk.withContext(function($ctx1) { 
+_st(_st(self)._inspectorWidget())._inspect_(_st($HLContextInspectorDecorator())._on_(_st(anAnnouncement)._context()));
+return self}, function($ctx1) {$ctx1.fill(self,"onContextSelected:",{anAnnouncement:anAnnouncement},smalltalk.HLDebugger)})},
+args: ["anAnnouncement"],
+source: "onContextSelected: anAnnouncement\x0a\x09self inspectorWidget inspect: (HLContextInspectorDecorator on: anAnnouncement context)",
+messageSends: ["inspect:", "on:", "context", "inspectorWidget"],
+referencedClasses: ["HLContextInspectorDecorator"]
+}),
+smalltalk.HLDebugger);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "open",
+category: 'rendering',
+fn: function (){
+var self=this;
+function $HLTab(){return smalltalk.HLTab||(typeof HLTab=="undefined"?nil:HLTab)}
+function $HLManager(){return smalltalk.HLManager||(typeof HLManager=="undefined"?nil:HLManager)}
+return smalltalk.withContext(function($ctx1) { 
+_st(_st($HLManager())._current())._addTab_(_st($HLTab())._on_labelled_(self,_st(_st(self)._class())._tabLabel()));
+return self}, function($ctx1) {$ctx1.fill(self,"open",{},smalltalk.HLDebugger)})},
+args: [],
+source: "open\x0a\x09HLManager current addTab: (HLTab on: self labelled: self class tabLabel)",
+messageSends: ["addTab:", "on:labelled:", "tabLabel", "class", "current"],
+referencedClasses: ["HLTab", "HLManager"]
+}),
+smalltalk.HLDebugger);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "renderContentOn:",
+category: 'rendering',
+fn: function (html){
+var self=this;
+function $HLVerticalSplitter(){return smalltalk.HLVerticalSplitter||(typeof HLVerticalSplitter=="undefined"?nil:HLVerticalSplitter)}
+function $HLHorizontalSplitter(){return smalltalk.HLHorizontalSplitter||(typeof HLHorizontalSplitter=="undefined"?nil:HLHorizontalSplitter)}
+function $HLContainer(){return smalltalk.HLContainer||(typeof HLContainer=="undefined"?nil:HLContainer)}
+return smalltalk.withContext(function($ctx1) { 
+_st(html)._with_(_st($HLContainer())._with_(_st($HLHorizontalSplitter())._with_with_(_st(self)._stackListWidget(),_st($HLVerticalSplitter())._with_with_(_st(self)._codeWidget(),_st(self)._inspectorWidget()))));
+return self}, function($ctx1) {$ctx1.fill(self,"renderContentOn:",{html:html},smalltalk.HLDebugger)})},
+args: ["html"],
+source: "renderContentOn: html\x0a\x09html with: (HLContainer with: (HLHorizontalSplitter\x0a\x09\x09with: self stackListWidget\x0a\x09\x09with: (HLVerticalSplitter\x0a\x09\x09\x09with: self codeWidget\x0a\x09\x09\x09with: self inspectorWidget)))",
+messageSends: ["with:", "with:with:", "stackListWidget", "codeWidget", "inspectorWidget"],
+referencedClasses: ["HLVerticalSplitter", "HLHorizontalSplitter", "HLContainer"]
+}),
+smalltalk.HLDebugger);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "stackListWidget",
+category: 'accessing',
+fn: function (){
+var self=this;
+function $HLStackListWidget(){return smalltalk.HLStackListWidget||(typeof HLStackListWidget=="undefined"?nil:HLStackListWidget)}
+return smalltalk.withContext(function($ctx1) { 
+var $2,$3,$4,$1;
+$2=self["@stackListWidget"];
+if(($receiver = $2) == nil || $receiver == undefined){
+$3=_st($HLStackListWidget())._on_(_st(self)._model());
+_st($3)._next_(_st(self)._codeWidget());
+$4=_st($3)._yourself();
+self["@stackListWidget"]=$4;
+$1=self["@stackListWidget"];
+} else {
+$1=$2;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"stackListWidget",{},smalltalk.HLDebugger)})},
+args: [],
+source: "stackListWidget\x0a\x09^ stackListWidget ifNil: [ \x0a\x09\x09stackListWidget := (HLStackListWidget on: self model)\x0a\x09\x09\x09next: self codeWidget;\x0a\x09\x09\x09yourself ]",
+messageSends: ["ifNil:", "next:", "codeWidget", "on:", "model", "yourself"],
+referencedClasses: ["HLStackListWidget"]
+}),
+smalltalk.HLDebugger);
+
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "on:",
+category: 'instance creation',
+fn: function (aMethodContext){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $2,$3,$1;
+$2=_st(self)._new();
+_st($2)._initializeFromMethodContext_(aMethodContext);
+$3=_st($2)._yourself();
+$1=$3;
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"on:",{aMethodContext:aMethodContext},smalltalk.HLDebugger.klass)})},
+args: ["aMethodContext"],
+source: "on: aMethodContext\x0a\x09^ self new\x0a\x09\x09initializeFromMethodContext: aMethodContext;\x0a\x09\x09yourself",
+messageSends: ["initializeFromMethodContext:", "new", "yourself"],
+referencedClasses: []
+}),
+smalltalk.HLDebugger.klass);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "tabLabel",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return "Debugger";
+}, function($ctx1) {$ctx1.fill(self,"tabLabel",{},smalltalk.HLDebugger.klass)})},
+args: [],
+source: "tabLabel\x0a\x09^ 'Debugger'",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLDebugger.klass);
+
+
+smalltalk.addClass('HLDebuggerModel', smalltalk.HLToolModel, ['rootContext', 'currentContext', 'contexts'], 'Helios-Debugger');
+smalltalk.HLDebuggerModel.comment="I am a model for Helios debugging.\x0a\x0aMy instances hold a reference to an `AIContext` instance, built from a `MethodContext`. The context should be the root of the context stack."
+smalltalk.addMethod(
+smalltalk.method({
+selector: "contexts",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=self["@contexts"];
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"contexts",{},smalltalk.HLDebuggerModel)})},
+args: [],
+source: "contexts\x0a\x09^ contexts",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLDebuggerModel);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "currentContext",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2;
+$1=self["@currentContext"];
+if(($receiver = $1) == nil || $receiver == undefined){
+_st(self)._currentContext_(_st(self)._rootContext());
+} else {
+$1;
+};
+$2=self["@currentContext"];
+return $2;
+}, function($ctx1) {$ctx1.fill(self,"currentContext",{},smalltalk.HLDebuggerModel)})},
+args: [],
+source: "currentContext\x0a\x09currentContext ifNil: [ self currentContext: self rootContext ].\x0a\x09^ currentContext",
+messageSends: ["ifNil:", "currentContext:", "rootContext"],
+referencedClasses: []
+}),
+smalltalk.HLDebuggerModel);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "currentContext:",
+category: 'accessing',
+fn: function (aContext){
+var self=this;
+function $HLDebuggerContextSelected(){return smalltalk.HLDebuggerContextSelected||(typeof HLDebuggerContextSelected=="undefined"?nil:HLDebuggerContextSelected)}
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2;
+_st(self)._withChangesDo_((function(){
+return smalltalk.withContext(function($ctx2) {
+self["@currentContext"]=aContext;
+self["@currentContext"];
+$1=_st($HLDebuggerContextSelected())._new();
+_st($1)._context_(aContext);
+$2=_st($1)._yourself();
+_st(_st(self)._announcer())._announce_($2);
+return _st(self)._selectedMethod_(_st(aContext)._method());
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+return self}, function($ctx1) {$ctx1.fill(self,"currentContext:",{aContext:aContext},smalltalk.HLDebuggerModel)})},
+args: ["aContext"],
+source: "currentContext: aContext\x0a\x09self withChangesDo: [ \x0a\x09\x09currentContext := aContext.\x0a\x09\x09self announcer announce: (HLDebuggerContextSelected new\x0a\x09\x09\x09context: aContext;\x0a\x09\x09\x09yourself).\x0a\x09\x09self selectedMethod: aContext method ]",
+messageSends: ["withChangesDo:", "announce:", "context:", "new", "yourself", "announcer", "selectedMethod:", "method"],
+referencedClasses: ["HLDebuggerContextSelected"]
+}),
+smalltalk.HLDebuggerModel);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "initializeContexts",
+category: 'initialization',
+fn: function (){
+var self=this;
+var context;
+function $OrderedCollection(){return smalltalk.OrderedCollection||(typeof OrderedCollection=="undefined"?nil:OrderedCollection)}
+return smalltalk.withContext(function($ctx1) { 
+self["@contexts"]=_st($OrderedCollection())._new();
+context=_st(self)._rootContext();
+_st((function(){
+return smalltalk.withContext(function($ctx2) {
+return _st(context)._notNil();
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}))._whileTrue_((function(){
+return smalltalk.withContext(function($ctx2) {
+_st(self["@contexts"])._add_(context);
+context=_st(context)._outerContext();
+return context;
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+return self}, function($ctx1) {$ctx1.fill(self,"initializeContexts",{context:context},smalltalk.HLDebuggerModel)})},
+args: [],
+source: "initializeContexts\x0a\x09\x22Flatten the context stack into an OrderedCollection\x22\x0a\x09\x0a\x09| context |\x0a\x09\x0a\x09contexts := OrderedCollection new.\x0a\x09context := self rootContext.\x0a\x09\x0a\x09[ context notNil ] whileTrue: [\x0a\x09\x09contexts add: context.\x0a\x09\x09context := context outerContext ]",
+messageSends: ["new", "rootContext", "whileTrue:", "add:", "outerContext", "notNil"],
+referencedClasses: ["OrderedCollection"]
+}),
+smalltalk.HLDebuggerModel);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "initializeFromContext:",
+category: 'initialization',
+fn: function (aMethodContext){
+var self=this;
+function $AIContext(){return smalltalk.AIContext||(typeof AIContext=="undefined"?nil:AIContext)}
+return smalltalk.withContext(function($ctx1) { 
+self["@rootContext"]=_st($AIContext())._fromMethodContext_(aMethodContext);
+_st(self)._initializeContexts();
+return self}, function($ctx1) {$ctx1.fill(self,"initializeFromContext:",{aMethodContext:aMethodContext},smalltalk.HLDebuggerModel)})},
+args: ["aMethodContext"],
+source: "initializeFromContext: aMethodContext\x0a\x09rootContext := AIContext fromMethodContext: aMethodContext.\x0a\x09self initializeContexts",
+messageSends: ["fromMethodContext:", "initializeContexts"],
+referencedClasses: ["AIContext"]
+}),
+smalltalk.HLDebuggerModel);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "rootContext",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=self["@rootContext"];
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"rootContext",{},smalltalk.HLDebuggerModel)})},
+args: [],
+source: "rootContext\x0a\x09^ rootContext",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLDebuggerModel);
+
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "on:",
+category: 'instance creation',
+fn: function (aMethodContext){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $2,$3,$1;
+$2=_st(self)._new();
+_st($2)._initializeFromContext_(aMethodContext);
+$3=_st($2)._yourself();
+$1=$3;
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"on:",{aMethodContext:aMethodContext},smalltalk.HLDebuggerModel.klass)})},
+args: ["aMethodContext"],
+source: "on: aMethodContext\x0a\x09^ self new\x0a\x09\x09initializeFromContext: aMethodContext;\x0a\x09\x09yourself",
+messageSends: ["initializeFromContext:", "new", "yourself"],
+referencedClasses: []
+}),
+smalltalk.HLDebuggerModel.klass);
+
+
+smalltalk.addClass('HLStackListWidget', smalltalk.HLToolListWidget, [], 'Helios-Debugger');
+smalltalk.addMethod(
+smalltalk.method({
+selector: "items",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $2,$1;
+$2=self["@items"];
+if(($receiver = $2) == nil || $receiver == undefined){
+self["@items"]=_st(_st(self)._model())._contexts();
+$1=self["@items"];
+} else {
+$1=$2;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"items",{},smalltalk.HLStackListWidget)})},
+args: [],
+source: "items\x0a\x09^ items ifNil: [ items := self model contexts ]",
+messageSends: ["ifNil:", "contexts", "model"],
+referencedClasses: []
+}),
+smalltalk.HLStackListWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "label",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return "Stack";
+}, function($ctx1) {$ctx1.fill(self,"label",{},smalltalk.HLStackListWidget)})},
+args: [],
+source: "label\x0a\x09^ 'Stack'",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLStackListWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "selectItem:",
+category: 'actions',
+fn: function (aContext){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+_st(_st(self)._model())._currentContext_(aContext);
+return self}, function($ctx1) {$ctx1.fill(self,"selectItem:",{aContext:aContext},smalltalk.HLStackListWidget)})},
+args: ["aContext"],
+source: "selectItem: aContext\x0a   \x09self model currentContext: aContext",
+messageSends: ["currentContext:", "model"],
+referencedClasses: []
+}),
+smalltalk.HLStackListWidget);
+
+
+

+ 26 - 3
js/Helios-Inspector.deploy.js

@@ -514,6 +514,23 @@ messageSends: ["valueWithInterval:", "do:", "refresh", "inspectors"]}),
 smalltalk.HLInspector.klass);
 
 
+smalltalk.addClass('HLInspectorWidget', smalltalk.HLInspector, [], 'Helios-Inspector');
+smalltalk.addMethod(
+smalltalk.method({
+selector: "renderContentOn:",
+fn: function (html){
+var self=this;
+function $HLVerticalSplitter(){return smalltalk.HLVerticalSplitter||(typeof HLVerticalSplitter=="undefined"?nil:HLVerticalSplitter)}
+function $HLHorizontalSplitter(){return smalltalk.HLHorizontalSplitter||(typeof HLHorizontalSplitter=="undefined"?nil:HLHorizontalSplitter)}
+return smalltalk.withContext(function($ctx1) { 
+_st(html)._with_(_st($HLHorizontalSplitter())._with_with_(_st($HLVerticalSplitter())._with_with_(_st(self)._variablesWidget(),_st(self)._displayWidget()),_st(self)._codeWidget()));
+_st(_st(self)._variablesWidget())._focus();
+return self}, function($ctx1) {$ctx1.fill(self,"renderContentOn:",{html:html},smalltalk.HLInspectorWidget)})},
+messageSends: ["with:", "with:with:", "variablesWidget", "displayWidget", "codeWidget", "focus"]}),
+smalltalk.HLInspectorWidget);
+
+
+
 smalltalk.addClass('HLInspectorDisplayWidget', smalltalk.HLNavigationListWidget, ['model'], 'Helios-Inspector');
 smalltalk.addMethod(
 smalltalk.method({
@@ -791,12 +808,18 @@ smalltalk.method({
 selector: "variables",
 fn: function (){
 var self=this;
+function $Dictionary(){return smalltalk.Dictionary||(typeof Dictionary=="undefined"?nil:Dictionary)}
 return smalltalk.withContext(function($ctx1) { 
-var $1;
-$1=self["@variables"];
+var $2,$1;
+$2=self["@variables"];
+if(($receiver = $2) == nil || $receiver == undefined){
+$1=_st($Dictionary())._new();
+} else {
+$1=$2;
+};
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"variables",{},smalltalk.HLInspectorModel)})},
-messageSends: []}),
+messageSends: ["ifNil:", "new"]}),
 smalltalk.HLInspectorModel);
 
 smalltalk.addMethod(

+ 33 - 5
js/Helios-Inspector.js

@@ -699,6 +699,28 @@ referencedClasses: []
 smalltalk.HLInspector.klass);
 
 
+smalltalk.addClass('HLInspectorWidget', smalltalk.HLInspector, [], 'Helios-Inspector');
+smalltalk.addMethod(
+smalltalk.method({
+selector: "renderContentOn:",
+category: 'rendering',
+fn: function (html){
+var self=this;
+function $HLVerticalSplitter(){return smalltalk.HLVerticalSplitter||(typeof HLVerticalSplitter=="undefined"?nil:HLVerticalSplitter)}
+function $HLHorizontalSplitter(){return smalltalk.HLHorizontalSplitter||(typeof HLHorizontalSplitter=="undefined"?nil:HLHorizontalSplitter)}
+return smalltalk.withContext(function($ctx1) { 
+_st(html)._with_(_st($HLHorizontalSplitter())._with_with_(_st($HLVerticalSplitter())._with_with_(_st(self)._variablesWidget(),_st(self)._displayWidget()),_st(self)._codeWidget()));
+_st(_st(self)._variablesWidget())._focus();
+return self}, function($ctx1) {$ctx1.fill(self,"renderContentOn:",{html:html},smalltalk.HLInspectorWidget)})},
+args: ["html"],
+source: "renderContentOn: html\x0a   \x09html with: (HLHorizontalSplitter\x0a    \x09with: (HLVerticalSplitter \x0a            \x09\x09with: self variablesWidget\x0a            \x09    with: self displayWidget)\x0a        with: self codeWidget).\x0a\x09\x0a\x09self variablesWidget focus\x0a ",
+messageSends: ["with:", "with:with:", "variablesWidget", "displayWidget", "codeWidget", "focus"],
+referencedClasses: ["HLVerticalSplitter", "HLHorizontalSplitter"]
+}),
+smalltalk.HLInspectorWidget);
+
+
+
 smalltalk.addClass('HLInspectorDisplayWidget', smalltalk.HLNavigationListWidget, ['model'], 'Helios-Inspector');
 smalltalk.addMethod(
 smalltalk.method({
@@ -1067,15 +1089,21 @@ selector: "variables",
 category: 'accessing',
 fn: function (){
 var self=this;
+function $Dictionary(){return smalltalk.Dictionary||(typeof Dictionary=="undefined"?nil:Dictionary)}
 return smalltalk.withContext(function($ctx1) { 
-var $1;
-$1=self["@variables"];
+var $2,$1;
+$2=self["@variables"];
+if(($receiver = $2) == nil || $receiver == undefined){
+$1=_st($Dictionary())._new();
+} else {
+$1=$2;
+};
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"variables",{},smalltalk.HLInspectorModel)})},
 args: [],
-source: "variables\x0a\x09^ variables",
-messageSends: [],
-referencedClasses: []
+source: "variables\x0a\x09^ variables ifNil: [ Dictionary new ]",
+messageSends: ["ifNil:", "new"],
+referencedClasses: ["Dictionary"]
 }),
 smalltalk.HLInspectorModel);
 

+ 21 - 5
st/Compiler-Interpreter.st

@@ -1,6 +1,6 @@
 Smalltalk current createPackage: 'Compiler-Interpreter'!
 NodeVisitor subclass: #AIContext
-	instanceVariableNames: 'outerContext pc locals method'
+	instanceVariableNames: 'methodContext outerContext pc locals method'
 	package: 'Compiler-Interpreter'!
 !AIContext commentStamp!
 I am like a `MethodContext`, used by the `ASTInterpreter`.
@@ -10,6 +10,12 @@ When debugging, my instances are created by copying the current `MethodContext`
 
 !AIContext methodsFor: 'accessing'!
 
+home
+	^ self isBlockContext 
+		ifTrue: [ self outerContext methodContext ]
+		ifFalse: [ self ]
+!
+
 localAt: aString
 	^ self locals at: aString ifAbsent: [ nil ]
 !
@@ -61,9 +67,17 @@ selector
 		ifNotNil: [ self method selector ]
 ! !
 
+!AIContext methodsFor: 'converting'!
+
+asString
+	^ methodContext asString
+! !
+
 !AIContext methodsFor: 'initialization'!
 
 initializeFromMethodContext: aMethodContext
+	methodContext := aMethodContext.
+	
 	self pc: aMethodContext pc.
 	self receiver: aMethodContext receiver.
 	self method: aMethodContext method.
@@ -78,6 +92,12 @@ initializeLocals
 	locals at: 'thisContext' put: self.
 ! !
 
+!AIContext methodsFor: 'testing'!
+
+isBlockContext
+	^ methodContext isBlockContext
+! !
+
 !AIContext class methodsFor: 'instance creation'!
 
 fromMethodContext: aMethodContext
@@ -165,10 +185,6 @@ restart
 	self shouldBeImplemented
 !
 
-resume
-	self shouldBeImplemented
-!
-
 step
 	"The ASTSteppingInterpreter stops at each node interpretation.
 	One step will interpret nodes until:

+ 14 - 0
st/Helios-Announcements.st

@@ -58,6 +58,20 @@ HLCodeHandled subclass: #HLPrintItRequested
 	instanceVariableNames: ''
 	package: 'Helios-Announcements'!
 
+HLAnnouncement subclass: #HLDebuggerContextSelected
+	instanceVariableNames: 'context'
+	package: 'Helios-Announcements'!
+
+!HLDebuggerContextSelected methodsFor: 'accessing'!
+
+context
+	^ context
+!
+
+context: aContext
+	context := aContext
+! !
+
 HLAnnouncement subclass: #HLDiveRequested
 	instanceVariableNames: ''
 	package: 'Helios-Announcements'!

+ 1 - 1
st/Helios-Browser.st

@@ -1081,7 +1081,7 @@ HLToolListWidget subclass: #HLPackagesListWidget
 !HLPackagesListWidget methodsFor: 'accessing'!
 
 items
-	^ items ifNil: [self initializeItems]
+	^ items ifNil: [ self initializeItems ]
 !
 
 label

+ 0 - 4
st/Helios-Core.st

@@ -745,10 +745,6 @@ renderMainOn: html
 	input asJQuery val: self value
 ! !
 
-HLWidget subclass: #HLDebugger
-	instanceVariableNames: ''
-	package: 'Helios-Core'!
-
 HLWidget subclass: #HLFocusableWidget
 	instanceVariableNames: ''
 	package: 'Helios-Core'!

+ 206 - 0
st/Helios-Debugger.st

@@ -0,0 +1,206 @@
+Smalltalk current 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 isBlockContext ] whileTrue: [
+		inspectedContext := inspectedContext outerContext.
+		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 := HLBrowserCodeWidget 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
+! !
+
+!HLDebugger methodsFor: 'reactions'!
+
+onContextSelected: anAnnouncement
+	self inspectorWidget inspect: (HLContextInspectorDecorator on: anAnnouncement context)
+! !
+
+!HLDebugger methodsFor: 'rendering'!
+
+open
+	HLManager current addTab: (HLTab on: self labelled: self class tabLabel)
+!
+
+renderContentOn: html
+	html with: (HLContainer with: (HLHorizontalSplitter
+		with: self stackListWidget
+		with: (HLVerticalSplitter
+			with: self codeWidget
+			with: self inspectorWidget)))
+! !
+
+!HLDebugger class methodsFor: 'accessing'!
+
+tabLabel
+	^ 'Debugger'
+! !
+
+!HLDebugger class methodsFor: 'instance creation'!
+
+on: aMethodContext
+	^ self new
+		initializeFromMethodContext: aMethodContext;
+		yourself
+! !
+
+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: [ 
+		currentContext := aContext.
+		self announcer announce: (HLDebuggerContextSelected new
+			context: aContext;
+			yourself).
+		self selectedMethod: aContext method ]
+!
+
+rootContext
+	^ rootContext
+! !
+
+!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
+! !
+
+HLToolListWidget subclass: #HLStackListWidget
+	instanceVariableNames: ''
+	package: 'Helios-Debugger'!
+
+!HLStackListWidget methodsFor: 'accessing'!
+
+items
+	^ items ifNil: [ items := self model contexts ]
+!
+
+label
+	^ 'Stack'
+! !
+
+!HLStackListWidget methodsFor: 'actions'!
+
+selectItem: aContext
+   	self model currentContext: aContext
+! !
+

+ 17 - 1
st/Helios-Inspector.st

@@ -215,6 +215,22 @@ canBeOpenAsTab
 	^ false
 ! !
 
+HLInspector subclass: #HLInspectorWidget
+	instanceVariableNames: ''
+	package: 'Helios-Inspector'!
+
+!HLInspectorWidget methodsFor: 'rendering'!
+
+renderContentOn: html
+   	html with: (HLHorizontalSplitter
+    	with: (HLVerticalSplitter 
+            		with: self variablesWidget
+            	    with: self displayWidget)
+        with: self codeWidget).
+	
+	self variablesWidget focus
+! !
+
 HLNavigationListWidget subclass: #HLInspectorDisplayWidget
 	instanceVariableNames: 'model'
 	package: 'Helios-Inspector'!
@@ -292,7 +308,7 @@ selection: anObject
 !
 
 variables
-	^ variables
+	^ variables ifNil: [ Dictionary new ]
 !
 
 variables: aCollection