Kaynağa Gözat

first (work in progress) stepping debugger

Nicolas Petton 11 yıl önce
ebeveyn
işleme
44ad2eb4c2

+ 29 - 0
js/Compiler-Interpreter.deploy.js

@@ -1674,6 +1674,17 @@ return $1;
 messageSends: ["add:", "stack"]}),
 smalltalk.Interpreter);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "restart",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self._node_(_st(_st(self._context())._ast())._nextChild());
+return self}, function($ctx1) {$ctx1.fill(self,"restart",{},smalltalk.Interpreter)})},
+messageSends: ["node:", "nextChild", "ast", "context"]}),
+smalltalk.Interpreter);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "result",
@@ -1809,6 +1820,24 @@ return self}, function($ctx1) {$ctx1.fill(self,"step",{},smalltalk.Interpreter)}
 messageSends: ["interpret", "next"]}),
 smalltalk.Interpreter);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "stepOver",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self._step();
+_st((function(){
+return smalltalk.withContext(function($ctx2) {
+return _st(self._node())._isSteppingNode();
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}))._whileFalse_((function(){
+return smalltalk.withContext(function($ctx2) {
+return self._step();
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+return self}, function($ctx1) {$ctx1.fill(self,"stepOver",{},smalltalk.Interpreter)})},
+messageSends: ["step", "whileFalse:", "isSteppingNode", "node"]}),
+smalltalk.Interpreter);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "visit:",

+ 39 - 0
js/Compiler-Interpreter.js

@@ -2214,6 +2214,22 @@ referencedClasses: []
 }),
 smalltalk.Interpreter);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "restart",
+category: 'interpreting',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self._node_(_st(_st(self._context())._ast())._nextChild());
+return self}, function($ctx1) {$ctx1.fill(self,"restart",{},smalltalk.Interpreter)})},
+args: [],
+source: "restart\x0a\x09self node: self context ast nextChild",
+messageSends: ["node:", "nextChild", "ast", "context"],
+referencedClasses: []
+}),
+smalltalk.Interpreter);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "result",
@@ -2389,6 +2405,29 @@ referencedClasses: []
 }),
 smalltalk.Interpreter);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "stepOver",
+category: 'interpreting',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self._step();
+_st((function(){
+return smalltalk.withContext(function($ctx2) {
+return _st(self._node())._isSteppingNode();
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}))._whileFalse_((function(){
+return smalltalk.withContext(function($ctx2) {
+return self._step();
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+return self}, function($ctx1) {$ctx1.fill(self,"stepOver",{},smalltalk.Interpreter)})},
+args: [],
+source: "stepOver\x0a\x09self step.\x0a\x09\x0a\x09[ self node isSteppingNode ] whileFalse: [ \x0a\x09\x09self step ]",
+messageSends: ["step", "whileFalse:", "isSteppingNode", "node"],
+referencedClasses: []
+}),
+smalltalk.Interpreter);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "visit:",

+ 23 - 0
js/Compiler-Tests.deploy.js

@@ -636,6 +636,29 @@ return self}, function($ctx1) {$ctx1.fill(self,"testKeywordSend",{},smalltalk.In
 messageSends: ["assert:equals:", "interpret:", "@"]}),
 smalltalk.InterpreterTest);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "testMultipleSequences",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self._assert_equals_(self._interpret_("foo | a b c | a := 2. b := 3. c := a + b. ^ c * 6"),(30));
+return self}, function($ctx1) {$ctx1.fill(self,"testMultipleSequences",{},smalltalk.InterpreterTest)})},
+messageSends: ["assert:equals:", "interpret:"]}),
+smalltalk.InterpreterTest);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "testNestedSends",
+fn: function (){
+var self=this;
+function $Point(){return smalltalk.Point||(typeof Point=="undefined"?nil:Point)}
+return smalltalk.withContext(function($ctx1) { 
+self._assert_equals_(self._interpret_("foo ^ (Point x: (Point x: 2 y: 3) y: 4) asString"),_st(_st($Point())._x_y_((2).__at((3)),(4)))._asString());
+return self}, function($ctx1) {$ctx1.fill(self,"testNestedSends",{},smalltalk.InterpreterTest)})},
+messageSends: ["assert:equals:", "interpret:", "asString", "x:y:", "@"]}),
+smalltalk.InterpreterTest);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "testNonlocalReturn",

+ 34 - 1
js/Compiler-Tests.js

@@ -655,7 +655,7 @@ smalltalk.addClass('InterpreterTest', smalltalk.AbstractASTInterpreterTest, [],
 smalltalk.addMethod(
 smalltalk.method({
 selector: "interpret:receiver:withArguments:",
-category: 'as yet unclassified',
+category: 'interpreting',
 fn: function (aString,anObject,aDictionary){
 var self=this;
 var ctx;
@@ -851,6 +851,39 @@ referencedClasses: []
 }),
 smalltalk.InterpreterTest);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "testMultipleSequences",
+category: 'tests',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self._assert_equals_(self._interpret_("foo | a b c | a := 2. b := 3. c := a + b. ^ c * 6"),(30));
+return self}, function($ctx1) {$ctx1.fill(self,"testMultipleSequences",{},smalltalk.InterpreterTest)})},
+args: [],
+source: "testMultipleSequences\x0a\x09self assert: (self interpret: 'foo | a b c | a := 2. b := 3. c := a + b. ^ c * 6') equals: 30",
+messageSends: ["assert:equals:", "interpret:"],
+referencedClasses: []
+}),
+smalltalk.InterpreterTest);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "testNestedSends",
+category: 'tests',
+fn: function (){
+var self=this;
+function $Point(){return smalltalk.Point||(typeof Point=="undefined"?nil:Point)}
+return smalltalk.withContext(function($ctx1) { 
+self._assert_equals_(self._interpret_("foo ^ (Point x: (Point x: 2 y: 3) y: 4) asString"),_st(_st($Point())._x_y_((2).__at((3)),(4)))._asString());
+return self}, function($ctx1) {$ctx1.fill(self,"testNestedSends",{},smalltalk.InterpreterTest)})},
+args: [],
+source: "testNestedSends\x0a\x09self assert: (self interpret: 'foo ^ (Point x: (Point x: 2 y: 3) y: 4) asString') equals: (Point x: (2@3) y: 4) asString",
+messageSends: ["assert:equals:", "interpret:", "asString", "x:y:", "@"],
+referencedClasses: ["Point"]
+}),
+smalltalk.InterpreterTest);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "testNonlocalReturn",

+ 31 - 1
js/Helios-Announcements.deploy.js

@@ -95,7 +95,34 @@ smalltalk.addClass('HLInspectItRequested', smalltalk.HLCodeHandled, [], 'Helios-
 smalltalk.addClass('HLPrintItRequested', smalltalk.HLCodeHandled, [], 'Helios-Announcements');
 
 
-smalltalk.addClass('HLDebuggerContextSelected', smalltalk.HLAnnouncement, ['context'], 'Helios-Announcements');
+smalltalk.addClass('HLDebuggerAnnouncement', 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.HLDebuggerAnnouncement)})},
+messageSends: []}),
+smalltalk.HLDebuggerAnnouncement);
+
+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.HLDebuggerAnnouncement)})},
+messageSends: []}),
+smalltalk.HLDebuggerAnnouncement);
+
+
+
+smalltalk.addClass('HLDebuggerContextSelected', smalltalk.HLDebuggerAnnouncement, [], 'Helios-Announcements');
 smalltalk.addMethod(
 smalltalk.method({
 selector: "context",
@@ -122,6 +149,9 @@ smalltalk.HLDebuggerContextSelected);
 
 
 
+smalltalk.addClass('HLDebuggerStepped', smalltalk.HLDebuggerAnnouncement, [], 'Helios-Announcements');
+
+
 smalltalk.addClass('HLDiveRequested', smalltalk.HLAnnouncement, [], 'Helios-Announcements');
 
 

+ 41 - 1
js/Helios-Announcements.js

@@ -131,7 +131,44 @@ smalltalk.addClass('HLPrintItRequested', smalltalk.HLCodeHandled, [], 'Helios-An
 smalltalk.HLPrintItRequested.comment="I am emitted by a `HLCodeWidget` before an object is printed.";
 
 
-smalltalk.addClass('HLDebuggerContextSelected', smalltalk.HLAnnouncement, ['context'], 'Helios-Announcements');
+smalltalk.addClass('HLDebuggerAnnouncement', 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.HLDebuggerAnnouncement)})},
+args: [],
+source: "context\x0a\x09^ context",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLDebuggerAnnouncement);
+
+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.HLDebuggerAnnouncement)})},
+args: ["aContext"],
+source: "context: aContext\x0a\x09context := aContext",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLDebuggerAnnouncement);
+
+
+
+smalltalk.addClass('HLDebuggerContextSelected', smalltalk.HLDebuggerAnnouncement, [], 'Helios-Announcements');
 smalltalk.addMethod(
 smalltalk.method({
 selector: "context",
@@ -168,6 +205,9 @@ smalltalk.HLDebuggerContextSelected);
 
 
 
+smalltalk.addClass('HLDebuggerStepped', smalltalk.HLDebuggerAnnouncement, [], 'Helios-Announcements');
+
+
 smalltalk.addClass('HLDiveRequested', smalltalk.HLAnnouncement, [], 'Helios-Announcements');
 
 

+ 97 - 5
js/Helios-Debugger.deploy.js

@@ -172,8 +172,10 @@ selector: "observeModel",
 fn: function (){
 var self=this;
 function $HLDebuggerContextSelected(){return smalltalk.HLDebuggerContextSelected||(typeof HLDebuggerContextSelected=="undefined"?nil:HLDebuggerContextSelected)}
+function $HLDebuggerStepped(){return smalltalk.HLDebuggerStepped||(typeof HLDebuggerStepped=="undefined"?nil:HLDebuggerStepped)}
 return smalltalk.withContext(function($ctx1) { 
 _st(_st(self._model())._announcer())._on_send_to_($HLDebuggerContextSelected(),"onContextSelected:",self);
+_st(_st(self._model())._announcer())._on_send_to_($HLDebuggerStepped(),"onContextSelected:",self);
 return self}, function($ctx1) {$ctx1.fill(self,"observeModel",{},smalltalk.HLDebugger)})},
 messageSends: ["on:send:to:", "announcer", "model"]}),
 smalltalk.HLDebugger);
@@ -431,9 +433,11 @@ selector: "observeBrowserModel",
 fn: function (){
 var self=this;
 function $HLDebuggerContextSelected(){return smalltalk.HLDebuggerContextSelected||(typeof HLDebuggerContextSelected=="undefined"?nil:HLDebuggerContextSelected)}
+function $HLDebuggerStepped(){return smalltalk.HLDebuggerStepped||(typeof HLDebuggerStepped=="undefined"?nil:HLDebuggerStepped)}
 return smalltalk.withContext(function($ctx1) { 
 smalltalk.HLBrowserCodeWidget.fn.prototype._observeBrowserModel.apply(_st(self), []);
 _st(_st(self._browserModel())._announcer())._on_send_to_($HLDebuggerContextSelected(),"onContextSelected",self);
+_st(_st(self._browserModel())._announcer())._on_send_to_($HLDebuggerStepped(),"onContextSelected",self);
 return self}, function($ctx1) {$ctx1.fill(self,"observeBrowserModel",{},smalltalk.HLDebuggerCodeWidget)})},
 messageSends: ["observeBrowserModel", "on:send:to:", "announcer", "browserModel"]}),
 smalltalk.HLDebuggerCodeWidget);
@@ -451,7 +455,7 @@ smalltalk.HLDebuggerCodeWidget);
 
 
 
-smalltalk.addClass('HLDebuggerModel', smalltalk.HLToolModel, ['rootContext', 'currentContext', 'contexts', 'interpreter'], 'Helios-Debugger');
+smalltalk.addClass('HLDebuggerModel', smalltalk.HLToolModel, ['rootContext', 'currentContext', 'contexts'], 'Helios-Debugger');
 smalltalk.addMethod(
 smalltalk.method({
 selector: "contexts",
@@ -552,10 +556,10 @@ fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 var $1;
-$1=self["@interpreter"];
+$1=_st(self._currentContext())._interpreter();
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"interpreter",{},smalltalk.HLDebuggerModel)})},
-messageSends: []}),
+messageSends: ["interpreter", "currentContext"]}),
 smalltalk.HLDebuggerModel);
 
 smalltalk.addMethod(
@@ -565,10 +569,27 @@ fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 var $1;
-$1=_st(self._interpreter())._nextNode();
+$1=_st(self._interpreter())._node();
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"nextNode",{},smalltalk.HLDebuggerModel)})},
-messageSends: ["nextNode", "interpreter"]}),
+messageSends: ["node", "interpreter"]}),
+smalltalk.HLDebuggerModel);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "restart",
+fn: function (){
+var self=this;
+function $HLDebuggerStepped(){return smalltalk.HLDebuggerStepped||(typeof HLDebuggerStepped=="undefined"?nil:HLDebuggerStepped)}
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2;
+_st(self._interpreter())._restart();
+$1=_st($HLDebuggerStepped())._new();
+_st($1)._context_(self._currentContext());
+$2=_st($1)._yourself();
+_st(self._announcer())._announce_($2);
+return self}, function($ctx1) {$ctx1.fill(self,"restart",{},smalltalk.HLDebuggerModel)})},
+messageSends: ["restart", "interpreter", "announce:", "announcer", "context:", "new", "currentContext", "yourself"]}),
 smalltalk.HLDebuggerModel);
 
 smalltalk.addMethod(
@@ -584,6 +605,23 @@ return $1;
 messageSends: []}),
 smalltalk.HLDebuggerModel);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "stepOver",
+fn: function (){
+var self=this;
+function $HLDebuggerStepped(){return smalltalk.HLDebuggerStepped||(typeof HLDebuggerStepped=="undefined"?nil:HLDebuggerStepped)}
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2;
+_st(self._interpreter())._stepOver();
+$1=_st($HLDebuggerStepped())._new();
+_st($1)._context_(self._currentContext());
+$2=_st($1)._yourself();
+_st(self._announcer())._announce_($2);
+return self}, function($ctx1) {$ctx1.fill(self,"stepOver",{},smalltalk.HLDebuggerModel)})},
+messageSends: ["stepOver", "interpreter", "announce:", "announcer", "context:", "new", "currentContext", "yourself"]}),
+smalltalk.HLDebuggerModel);
+
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -685,6 +723,49 @@ return "Call stack";
 messageSends: []}),
 smalltalk.HLStackListWidget);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "renderButtonsOn:",
+fn: function (html){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1,$3,$4,$5,$6,$2;
+$1=_st(html)._div();
+_st($1)._class_("debugger_bar");
+$2=_st($1)._with_((function(){
+return smalltalk.withContext(function($ctx2) {
+$3=_st(html)._button();
+_st($3)._class_("btn restart");
+_st($3)._with_("Restart");
+$4=_st($3)._onClick_((function(){
+return smalltalk.withContext(function($ctx3) {
+return self._restart();
+}, function($ctx3) {$ctx3.fillBlock({},$ctx2)})}));
+$4;
+$5=_st(html)._button();
+_st($5)._class_("btn stepOver");
+_st($5)._with_("Step over");
+$6=_st($5)._onClick_((function(){
+return smalltalk.withContext(function($ctx3) {
+return self._stepOver();
+}, function($ctx3) {$ctx3.fillBlock({},$ctx2)})}));
+return $6;
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+return self}, function($ctx1) {$ctx1.fill(self,"renderButtonsOn:",{html:html},smalltalk.HLStackListWidget)})},
+messageSends: ["class:", "div", "with:", "button", "onClick:", "restart", "stepOver"]}),
+smalltalk.HLStackListWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "restart",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+_st(self._model())._restart();
+return self}, function($ctx1) {$ctx1.fill(self,"restart",{},smalltalk.HLStackListWidget)})},
+messageSends: ["restart", "model"]}),
+smalltalk.HLStackListWidget);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "selectItem:",
@@ -696,5 +777,16 @@ return self}, function($ctx1) {$ctx1.fill(self,"selectItem:",{aContext:aContext}
 messageSends: ["currentContext:", "model"]}),
 smalltalk.HLStackListWidget);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "stepOver",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+_st(self._model())._stepOver();
+return self}, function($ctx1) {$ctx1.fill(self,"stepOver",{},smalltalk.HLStackListWidget)})},
+messageSends: ["stepOver", "model"]}),
+smalltalk.HLStackListWidget);
+
 
 

+ 128 - 11
js/Helios-Debugger.js

@@ -219,13 +219,15 @@ category: 'actions',
 fn: function (){
 var self=this;
 function $HLDebuggerContextSelected(){return smalltalk.HLDebuggerContextSelected||(typeof HLDebuggerContextSelected=="undefined"?nil:HLDebuggerContextSelected)}
+function $HLDebuggerStepped(){return smalltalk.HLDebuggerStepped||(typeof HLDebuggerStepped=="undefined"?nil:HLDebuggerStepped)}
 return smalltalk.withContext(function($ctx1) { 
 _st(_st(self._model())._announcer())._on_send_to_($HLDebuggerContextSelected(),"onContextSelected:",self);
+_st(_st(self._model())._announcer())._on_send_to_($HLDebuggerStepped(),"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",
+source: "observeModel\x0a\x09self model announcer \x0a\x09\x09on: HLDebuggerContextSelected\x0a\x09\x09send: #onContextSelected:\x0a\x09\x09to: self.\x0a\x09\x09\x0a\x09self model announcer \x0a\x09\x09on: HLDebuggerStepped\x0a\x09\x09send: #onContextSelected:\x0a\x09\x09to: self",
 messageSends: ["on:send:to:", "announcer", "model"],
-referencedClasses: ["HLDebuggerContextSelected"]
+referencedClasses: ["HLDebuggerContextSelected", "HLDebuggerStepped"]
 }),
 smalltalk.HLDebugger);
 
@@ -568,14 +570,16 @@ category: 'actions',
 fn: function (){
 var self=this;
 function $HLDebuggerContextSelected(){return smalltalk.HLDebuggerContextSelected||(typeof HLDebuggerContextSelected=="undefined"?nil:HLDebuggerContextSelected)}
+function $HLDebuggerStepped(){return smalltalk.HLDebuggerStepped||(typeof HLDebuggerStepped=="undefined"?nil:HLDebuggerStepped)}
 return smalltalk.withContext(function($ctx1) { 
 smalltalk.HLBrowserCodeWidget.fn.prototype._observeBrowserModel.apply(_st(self), []);
 _st(_st(self._browserModel())._announcer())._on_send_to_($HLDebuggerContextSelected(),"onContextSelected",self);
+_st(_st(self._browserModel())._announcer())._on_send_to_($HLDebuggerStepped(),"onContextSelected",self);
 return self}, function($ctx1) {$ctx1.fill(self,"observeBrowserModel",{},smalltalk.HLDebuggerCodeWidget)})},
 args: [],
-source: "observeBrowserModel\x0a\x09super observeBrowserModel.\x0a\x09\x0a\x09self browserModel announcer \x0a\x09\x09on: HLDebuggerContextSelected\x0a\x09\x09send: #onContextSelected\x0a\x09\x09to: self",
+source: "observeBrowserModel\x0a\x09super observeBrowserModel.\x0a\x09\x0a\x09self browserModel announcer \x0a\x09\x09on: HLDebuggerContextSelected\x0a\x09\x09send: #onContextSelected\x0a\x09\x09to: self.\x0a\x09\x0a\x09self browserModel announcer \x0a\x09\x09on: HLDebuggerStepped\x0a\x09\x09send: #onContextSelected\x0a\x09\x09to: self",
 messageSends: ["observeBrowserModel", "on:send:to:", "announcer", "browserModel"],
-referencedClasses: ["HLDebuggerContextSelected"]
+referencedClasses: ["HLDebuggerContextSelected", "HLDebuggerStepped"]
 }),
 smalltalk.HLDebuggerCodeWidget);
 
@@ -597,7 +601,7 @@ smalltalk.HLDebuggerCodeWidget);
 
 
 
-smalltalk.addClass('HLDebuggerModel', smalltalk.HLToolModel, ['rootContext', 'currentContext', 'contexts', 'interpreter'], 'Helios-Debugger');
+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({
@@ -725,12 +729,12 @@ fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 var $1;
-$1=self["@interpreter"];
+$1=_st(self._currentContext())._interpreter();
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"interpreter",{},smalltalk.HLDebuggerModel)})},
 args: [],
-source: "interpreter\x0a\x09^ interpreter",
-messageSends: [],
+source: "interpreter\x0a\x09^ self currentContext interpreter",
+messageSends: ["interpreter", "currentContext"],
 referencedClasses: []
 }),
 smalltalk.HLDebuggerModel);
@@ -743,16 +747,38 @@ fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
 var $1;
-$1=_st(self._interpreter())._nextNode();
+$1=_st(self._interpreter())._node();
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"nextNode",{},smalltalk.HLDebuggerModel)})},
 args: [],
-source: "nextNode\x0a\x09^ self interpreter nextNode",
-messageSends: ["nextNode", "interpreter"],
+source: "nextNode\x0a\x09^ self interpreter node",
+messageSends: ["node", "interpreter"],
 referencedClasses: []
 }),
 smalltalk.HLDebuggerModel);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "restart",
+category: 'actions',
+fn: function (){
+var self=this;
+function $HLDebuggerStepped(){return smalltalk.HLDebuggerStepped||(typeof HLDebuggerStepped=="undefined"?nil:HLDebuggerStepped)}
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2;
+_st(self._interpreter())._restart();
+$1=_st($HLDebuggerStepped())._new();
+_st($1)._context_(self._currentContext());
+$2=_st($1)._yourself();
+_st(self._announcer())._announce_($2);
+return self}, function($ctx1) {$ctx1.fill(self,"restart",{},smalltalk.HLDebuggerModel)})},
+args: [],
+source: "restart\x0a\x09self interpreter restart.\x0a\x09self announcer announce: (HLDebuggerStepped new\x0a\x09\x09context: self currentContext;\x0a\x09\x09yourself)",
+messageSends: ["restart", "interpreter", "announce:", "announcer", "context:", "new", "currentContext", "yourself"],
+referencedClasses: ["HLDebuggerStepped"]
+}),
+smalltalk.HLDebuggerModel);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "rootContext",
@@ -771,6 +797,28 @@ referencedClasses: []
 }),
 smalltalk.HLDebuggerModel);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "stepOver",
+category: 'actions',
+fn: function (){
+var self=this;
+function $HLDebuggerStepped(){return smalltalk.HLDebuggerStepped||(typeof HLDebuggerStepped=="undefined"?nil:HLDebuggerStepped)}
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2;
+_st(self._interpreter())._stepOver();
+$1=_st($HLDebuggerStepped())._new();
+_st($1)._context_(self._currentContext());
+$2=_st($1)._yourself();
+_st(self._announcer())._announce_($2);
+return self}, function($ctx1) {$ctx1.fill(self,"stepOver",{},smalltalk.HLDebuggerModel)})},
+args: [],
+source: "stepOver\x0a\x09self interpreter stepOver.\x0a\x09self announcer announce: (HLDebuggerStepped new\x0a\x09\x09context: self currentContext;\x0a\x09\x09yourself)",
+messageSends: ["stepOver", "interpreter", "announce:", "announcer", "context:", "new", "currentContext", "yourself"],
+referencedClasses: ["HLDebuggerStepped"]
+}),
+smalltalk.HLDebuggerModel);
+
 
 smalltalk.addMethod(
 smalltalk.method({
@@ -902,6 +950,59 @@ referencedClasses: []
 }),
 smalltalk.HLStackListWidget);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "renderButtonsOn:",
+category: 'rendering',
+fn: function (html){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1,$3,$4,$5,$6,$2;
+$1=_st(html)._div();
+_st($1)._class_("debugger_bar");
+$2=_st($1)._with_((function(){
+return smalltalk.withContext(function($ctx2) {
+$3=_st(html)._button();
+_st($3)._class_("btn restart");
+_st($3)._with_("Restart");
+$4=_st($3)._onClick_((function(){
+return smalltalk.withContext(function($ctx3) {
+return self._restart();
+}, function($ctx3) {$ctx3.fillBlock({},$ctx2)})}));
+$4;
+$5=_st(html)._button();
+_st($5)._class_("btn stepOver");
+_st($5)._with_("Step over");
+$6=_st($5)._onClick_((function(){
+return smalltalk.withContext(function($ctx3) {
+return self._stepOver();
+}, function($ctx3) {$ctx3.fillBlock({},$ctx2)})}));
+return $6;
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+return self}, function($ctx1) {$ctx1.fill(self,"renderButtonsOn:",{html:html},smalltalk.HLStackListWidget)})},
+args: ["html"],
+source: "renderButtonsOn: html\x0a\x09html div \x0a\x09\x09class: 'debugger_bar'; \x0a\x09\x09with: [\x0a\x09\x09\x09html button \x0a\x09\x09\x09\x09class: 'btn restart';\x0a\x09\x09\x09\x09with: 'Restart';\x0a\x09\x09\x09\x09onClick: [ self restart ].\x0a\x09\x09\x09html button \x0a\x09\x09\x09\x09class: 'btn stepOver';\x0a\x09\x09\x09\x09with: 'Step over';\x0a\x09\x09\x09\x09onClick: [ self stepOver ] ]",
+messageSends: ["class:", "div", "with:", "button", "onClick:", "restart", "stepOver"],
+referencedClasses: []
+}),
+smalltalk.HLStackListWidget);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "restart",
+category: 'actions',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+_st(self._model())._restart();
+return self}, function($ctx1) {$ctx1.fill(self,"restart",{},smalltalk.HLStackListWidget)})},
+args: [],
+source: "restart\x0a\x09self model restart",
+messageSends: ["restart", "model"],
+referencedClasses: []
+}),
+smalltalk.HLStackListWidget);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "selectItem:",
@@ -918,5 +1019,21 @@ referencedClasses: []
 }),
 smalltalk.HLStackListWidget);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "stepOver",
+category: 'actions',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+_st(self._model())._stepOver();
+return self}, function($ctx1) {$ctx1.fill(self,"stepOver",{},smalltalk.HLStackListWidget)})},
+args: [],
+source: "stepOver\x0a\x09self model stepOver",
+messageSends: ["stepOver", "model"],
+referencedClasses: []
+}),
+smalltalk.HLStackListWidget);
+
 
 

+ 11 - 0
st/Compiler-Interpreter.st

@@ -743,6 +743,10 @@ proceed
 		self step ]
 !
 
+restart
+	self node: self context ast nextChild
+!
+
 skip
 	self next
 !
@@ -751,6 +755,13 @@ step
 	self 
 		interpret; 
 		next
+!
+
+stepOver
+	self step.
+	
+	[ self node isSteppingNode ] whileFalse: [ 
+		self step ]
 ! !
 
 !Interpreter methodsFor: 'private'!

+ 9 - 1
st/Compiler-Tests.st

@@ -302,7 +302,7 @@ interpreter
 	^ Interpreter new
 ! !
 
-!InterpreterTest methodsFor: 'as yet unclassified'!
+!InterpreterTest methodsFor: 'interpreting'!
 
 interpret: aString receiver: anObject withArguments: aDictionary
 	"The food is a methodNode. Interpret the sequenceNode only"
@@ -377,6 +377,14 @@ testKeywordSend
 	self assert: (self interpret: 'foo ^ Point x: 1 y: 2') equals: 1@2
 !
 
+testMultipleSequences
+	self assert: (self interpret: 'foo | a b c | a := 2. b := 3. c := a + b. ^ c * 6') equals: 30
+!
+
+testNestedSends
+	self assert: (self interpret: 'foo ^ (Point x: (Point x: 2 y: 3) y: 4) asString') equals: (Point x: (2@3) y: 4) asString
+!
+
 testNonlocalReturn
 	self assert: (self interpret: 'foo true ifTrue: [ ^ 1 ]. ^2') equals: 1
 !

+ 19 - 1
st/Helios-Announcements.st

@@ -76,10 +76,24 @@ HLCodeHandled subclass: #HLPrintItRequested
 !HLPrintItRequested commentStamp!
 I am emitted by a `HLCodeWidget` before an object is printed.!
 
-HLAnnouncement subclass: #HLDebuggerContextSelected
+HLAnnouncement subclass: #HLDebuggerAnnouncement
 	instanceVariableNames: 'context'
 	package: 'Helios-Announcements'!
 
+!HLDebuggerAnnouncement methodsFor: 'accessing'!
+
+context
+	^ context
+!
+
+context: aContext
+	context := aContext
+! !
+
+HLDebuggerAnnouncement subclass: #HLDebuggerContextSelected
+	instanceVariableNames: ''
+	package: 'Helios-Announcements'!
+
 !HLDebuggerContextSelected methodsFor: 'accessing'!
 
 context
@@ -90,6 +104,10 @@ context: aContext
 	context := aContext
 ! !
 
+HLDebuggerAnnouncement subclass: #HLDebuggerStepped
+	instanceVariableNames: ''
+	package: 'Helios-Announcements'!
+
 HLAnnouncement subclass: #HLDiveRequested
 	instanceVariableNames: ''
 	package: 'Helios-Announcements'!

+ 53 - 3
st/Helios-Debugger.st

@@ -88,6 +88,11 @@ observeModel
 	self model announcer 
 		on: HLDebuggerContextSelected
 		send: #onContextSelected:
+		to: self.
+		
+	self model announcer 
+		on: HLDebuggerStepped
+		send: #onContextSelected:
 		to: self
 !
 
@@ -222,6 +227,11 @@ observeBrowserModel
 	self browserModel announcer 
 		on: HLDebuggerContextSelected
 		send: #onContextSelected
+		to: self.
+	
+	self browserModel announcer 
+		on: HLDebuggerStepped
+		send: #onContextSelected
 		to: self
 ! !
 
@@ -232,7 +242,7 @@ onContextSelected
 ! !
 
 HLToolModel subclass: #HLDebuggerModel
-	instanceVariableNames: 'rootContext currentContext contexts interpreter'
+	instanceVariableNames: 'rootContext currentContext contexts'
 	package: 'Helios-Debugger'!
 !HLDebuggerModel commentStamp!
 I am a model for Helios debugging.
@@ -261,17 +271,33 @@ currentContext: aContext
 !
 
 interpreter
-	^ interpreter
+	^ self currentContext interpreter
 !
 
 nextNode
-	^ self interpreter nextNode
+	^ self interpreter node
 !
 
 rootContext
 	^ rootContext
 ! !
 
+!HLDebuggerModel methodsFor: 'actions'!
+
+restart
+	self interpreter restart.
+	self announcer announce: (HLDebuggerStepped new
+		context: self currentContext;
+		yourself)
+!
+
+stepOver
+	self interpreter stepOver.
+	self announcer announce: (HLDebuggerStepped new
+		context: self currentContext;
+		yourself)
+! !
+
 !HLDebuggerModel methodsFor: 'initialization'!
 
 initializeContexts
@@ -348,7 +374,31 @@ label
 
 !HLStackListWidget methodsFor: 'actions'!
 
+restart
+	self model restart
+!
+
 selectItem: aContext
    	self model currentContext: aContext
+!
+
+stepOver
+	self model stepOver
+! !
+
+!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 stepOver';
+				with: 'Step over';
+				onClick: [ self stepOver ] ]
 ! !