Sfoglia il codice sorgente

Use proper CPS in interpreter

Nicolas Petton 11 anni fa
parent
commit
7b3f992907

+ 344 - 110
js/Compiler-Interpreter.deploy.js

@@ -148,7 +148,7 @@ smalltalk.AIContext);
 
 
 
-smalltalk.addClass('ASTInterpreter', smalltalk.NodeVisitor, ['currentNode', 'context', 'shouldReturn', 'currentValue'], 'Compiler-Interpreter');
+smalltalk.addClass('ASTInterpreter', smalltalk.Object, ['currentNode', 'context', 'shouldReturn', 'result'], 'Compiler-Interpreter');
 smalltalk.addMethod(
 "_assign_to_",
 smalltalk.method({
@@ -198,26 +198,14 @@ return self}, function($ctx1) {$ctx1.fill(self,"context:",{anAIContext:anAIConte
 smalltalk.ASTInterpreter);
 
 smalltalk.addMethod(
-"_continue_",
+"_continue_value_",
 smalltalk.method({
-selector: "continue:",
-fn: function (anObject){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
self["@currentValue"]=anObject;
-return self}, function($ctx1) {$ctx1.fill(self,"continue:",{anObject:anObject}, smalltalk.ASTInterpreter)})}
-}),
-smalltalk.ASTInterpreter);
-
-smalltalk.addMethod(
-"_currentValue",
-smalltalk.method({
-selector: "currentValue",
-fn: function (){
+selector: "continue:value:",
+fn: function (aBlock,anObject){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
-$1=self["@currentValue"];
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"currentValue",{}, smalltalk.ASTInterpreter)})}
+return smalltalk.withContext(function($ctx1) { 
self["@result"]=anObject;
+_st(aBlock)._value_(anObject);
+return self}, function($ctx1) {$ctx1.fill(self,"continue:value:",{aBlock:aBlock,anObject:anObject}, smalltalk.ASTInterpreter)})}
 }),
 smalltalk.ASTInterpreter);
 
@@ -255,7 +243,7 @@ smalltalk.method({
 selector: "initialize",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
smalltalk.NodeVisitor.fn.prototype._initialize.apply(_st(self), []);
+return smalltalk.withContext(function($ctx1) { 
smalltalk.Object.fn.prototype._initialize.apply(_st(self), []);
 self["@shouldReturn"]=false;
 return self}, function($ctx1) {$ctx1.fill(self,"initialize",{}, smalltalk.ASTInterpreter)})}
 }),
@@ -269,8 +257,8 @@ fn: function (aNode){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
self["@shouldReturn"]=false;
 _st(self)._interpret_continue_(aNode,(function(value){
-return smalltalk.withContext(function($ctx2) {
self["@currentValue"]=value;
-return self["@currentValue"];
+return smalltalk.withContext(function($ctx2) {
self["@result"]=value;
+return self["@result"];
 }, function($ctx2) {$ctx2.fillBlock({value:value},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"interpret:",{aNode:aNode}, smalltalk.ASTInterpreter)})}
 }),
@@ -290,12 +278,14 @@ return $2;
 };
 $3=_st(aNode)._isNode();
 if(smalltalk.assert($3)){
-_st(self)._visit_(aNode);
+self["@currentNode"]=aNode;
+self["@currentNode"];
+_st(self)._interpretNode_continue_(aNode,(function(value){
+return smalltalk.withContext(function($ctx2) {
return _st(self)._continue_value_(aBlock,value);
+}, function($ctx2) {$ctx2.fillBlock({value:value},$ctx1)})}));
 } else {
-self["@currentValue"]=aNode;
-self["@currentValue"];
+_st(self)._continue_value_(aBlock,aNode);
 };
-_st(aBlock)._value_(_st(self)._currentValue());
 return self}, function($ctx1) {$ctx1.fill(self,"interpret:continue:",{aNode:aNode,aBlock:aBlock}, smalltalk.ASTInterpreter)})}
 }),
 smalltalk.ASTInterpreter);
@@ -331,58 +321,51 @@ return self}, function($ctx1) {$ctx1.fill(self,"interpretAll:continue:result:",{
 smalltalk.ASTInterpreter);
 
 smalltalk.addMethod(
-"_messageFromSendNode_do_",
+"_interpretAssignmentNode_continue_",
 smalltalk.method({
-selector: "messageFromSendNode:do:",
-fn: function (aSendNode,aBlock){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2;
-_st(self)._interpretAll_continue_(_st(aSendNode)._arguments(),(function(args){
-return smalltalk.withContext(function($ctx2) {
$1=_st((smalltalk.Message || Message))._new();
-_st($1)._selector_(_st(aSendNode)._selector());
-_st($1)._arguments_(args);
-$2=_st($1)._yourself();
-return _st(aBlock)._value_($2);
-}, function($ctx2) {$ctx2.fillBlock({args:args},$ctx1)})}));
-return self}, function($ctx1) {$ctx1.fill(self,"messageFromSendNode:do:",{aSendNode:aSendNode,aBlock:aBlock}, smalltalk.ASTInterpreter)})}
-}),
-smalltalk.ASTInterpreter);
-
-smalltalk.addMethod(
-"_visitAssignmentNode_",
-smalltalk.method({
-selector: "visitAssignmentNode:",
-fn: function (aNode){
+selector: "interpretAssignmentNode:continue:",
+fn: function (aNode,aBlock){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
_st(self)._interpret_continue_(_st(aNode)._right(),(function(value){
-return smalltalk.withContext(function($ctx2) {
return _st(self)._continue_(_st(self)._assign_to_(_st(aNode)._left(),value));
+return smalltalk.withContext(function($ctx2) {
return _st(self)._continue_value_(aBlock,_st(self)._assign_to_(_st(aNode)._left(),value));
 }, function($ctx2) {$ctx2.fillBlock({value:value},$ctx1)})}));
-return self}, function($ctx1) {$ctx1.fill(self,"visitAssignmentNode:",{aNode:aNode}, smalltalk.ASTInterpreter)})}
+return self}, function($ctx1) {$ctx1.fill(self,"interpretAssignmentNode:continue:",{aNode:aNode,aBlock:aBlock}, smalltalk.ASTInterpreter)})}
 }),
 smalltalk.ASTInterpreter);
 
 smalltalk.addMethod(
-"_visitBlockNode_",
+"_interpretBlockNode_continue_",
 smalltalk.method({
-selector: "visitBlockNode:",
-fn: function (aNode){
+selector: "interpretBlockNode:continue:",
+fn: function (aNode,aBlock){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
var $1,$2;
-_st(self)._continue_((function(){
+_st(self)._continue_value_(aBlock,(function(){
 return smalltalk.withContext(function($ctx2) {
$1=self;
 _st($1)._interpret_(_st(_st(aNode)._nodes())._first());
-$2=_st($1)._currentValue();
+$2=_st($1)._result();
 return $2;
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
-return self}, function($ctx1) {$ctx1.fill(self,"visitBlockNode:",{aNode:aNode}, smalltalk.ASTInterpreter)})}
+return self}, function($ctx1) {$ctx1.fill(self,"interpretBlockNode:continue:",{aNode:aNode,aBlock:aBlock}, smalltalk.ASTInterpreter)})}
 }),
 smalltalk.ASTInterpreter);
 
 smalltalk.addMethod(
-"_visitCascadeNode_",
+"_interpretBlockSequenceNode_continue_",
 smalltalk.method({
-selector: "visitCascadeNode:",
-fn: function (aNode){
+selector: "interpretBlockSequenceNode:continue:",
+fn: function (aNode,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(self)._interpretSequenceNode_continue_(aNode,aBlock);
+return self}, function($ctx1) {$ctx1.fill(self,"interpretBlockSequenceNode:continue:",{aNode:aNode,aBlock:aBlock}, smalltalk.ASTInterpreter)})}
+}),
+smalltalk.ASTInterpreter);
+
+smalltalk.addMethod(
+"_interpretCascadeNode_continue_",
+smalltalk.method({
+selector: "interpretCascadeNode:continue:",
+fn: function (aNode,aBlock){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
_st(self)._interpret_continue_(_st(aNode)._receiver(),(function(receiver){
 return smalltalk.withContext(function($ctx2) {
_st(_st(aNode)._nodes())._do_((function(each){
@@ -390,43 +373,43 @@ return smalltalk.withContext(function($ctx3) {
return _st(each)._receiver_(recei
 }, function($ctx3) {$ctx3.fillBlock({each:each},$ctx1)})}));
 return _st(self)._interpretAll_continue_(_st(_st(aNode)._nodes())._allButLast(),(function(){
 return smalltalk.withContext(function($ctx3) {
return _st(self)._interpret_continue_(_st(_st(aNode)._nodes())._last(),(function(val){
-return smalltalk.withContext(function($ctx4) {
return _st(self)._continue_(val);
+return smalltalk.withContext(function($ctx4) {
return _st(self)._continue_value_(aBlock,val);
 }, function($ctx4) {$ctx4.fillBlock({val:val},$ctx1)})}));
 }, function($ctx3) {$ctx3.fillBlock({},$ctx1)})}));
 }, function($ctx2) {$ctx2.fillBlock({receiver:receiver},$ctx1)})}));
-return self}, function($ctx1) {$ctx1.fill(self,"visitCascadeNode:",{aNode:aNode}, smalltalk.ASTInterpreter)})}
+return self}, function($ctx1) {$ctx1.fill(self,"interpretCascadeNode:continue:",{aNode:aNode,aBlock:aBlock}, smalltalk.ASTInterpreter)})}
 }),
 smalltalk.ASTInterpreter);
 
 smalltalk.addMethod(
-"_visitClassReferenceNode_",
+"_interpretClassReferenceNode_continue_",
 smalltalk.method({
-selector: "visitClassReferenceNode:",
-fn: function (aNode){
+selector: "interpretClassReferenceNode:continue:",
+fn: function (aNode,aBlock){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
_st(self)._continue_(_st(_st((smalltalk.Smalltalk || Smalltalk))._current())._at_(_st(aNode)._value()));
-return self}, function($ctx1) {$ctx1.fill(self,"visitClassReferenceNode:",{aNode:aNode}, smalltalk.ASTInterpreter)})}
+return smalltalk.withContext(function($ctx1) { 
_st(self)._continue_value_(aBlock,_st(_st((smalltalk.Smalltalk || Smalltalk))._current())._at_(_st(aNode)._value()));
+return self}, function($ctx1) {$ctx1.fill(self,"interpretClassReferenceNode:continue:",{aNode:aNode,aBlock:aBlock}, smalltalk.ASTInterpreter)})}
 }),
 smalltalk.ASTInterpreter);
 
 smalltalk.addMethod(
-"_visitDynamicArrayNode_",
+"_interpretDynamicArrayNode_continue_",
 smalltalk.method({
-selector: "visitDynamicArrayNode:",
-fn: function (aNode){
+selector: "interpretDynamicArrayNode:continue:",
+fn: function (aNode,aBlock){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
_st(self)._interpretAll_continue_(_st(aNode)._nodes(),(function(array){
-return smalltalk.withContext(function($ctx2) {
return _st(self)._continue_(array);
+return smalltalk.withContext(function($ctx2) {
return _st(self)._continue_value_(aBlock,array);
 }, function($ctx2) {$ctx2.fillBlock({array:array},$ctx1)})}));
-return self}, function($ctx1) {$ctx1.fill(self,"visitDynamicArrayNode:",{aNode:aNode}, smalltalk.ASTInterpreter)})}
+return self}, function($ctx1) {$ctx1.fill(self,"interpretDynamicArrayNode:continue:",{aNode:aNode,aBlock:aBlock}, smalltalk.ASTInterpreter)})}
 }),
 smalltalk.ASTInterpreter);
 
 smalltalk.addMethod(
-"_visitDynamicDictionaryNode_",
+"_interpretDynamicDictionaryNode_continue_",
 smalltalk.method({
-selector: "visitDynamicDictionaryNode:",
-fn: function (aNode){
+selector: "interpretDynamicDictionaryNode:continue:",
+fn: function (aNode,aBlock){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
_st(self)._interpretAll_continue_(_st(aNode)._nodes(),(function(array){
 var hashedCollection;
@@ -435,95 +418,151 @@ hashedCollection;
 _st(array)._do_((function(each){
 return smalltalk.withContext(function($ctx3) {
return _st(hashedCollection)._add_(each);
 }, function($ctx3) {$ctx3.fillBlock({each:each},$ctx1)})}));
-return _st(self)._continue_(hashedCollection);
+return _st(self)._continue_value_(aBlock,hashedCollection);
 }, function($ctx2) {$ctx2.fillBlock({array:array,hashedCollection:hashedCollection},$ctx1)})}));
-return self}, function($ctx1) {$ctx1.fill(self,"visitDynamicDictionaryNode:",{aNode:aNode}, smalltalk.ASTInterpreter)})}
+return self}, function($ctx1) {$ctx1.fill(self,"interpretDynamicDictionaryNode:continue:",{aNode:aNode,aBlock:aBlock}, smalltalk.ASTInterpreter)})}
 }),
 smalltalk.ASTInterpreter);
 
 smalltalk.addMethod(
-"_visitJSStatementNode_",
+"_interpretJSStatementNode_continue_",
 smalltalk.method({
-selector: "visitJSStatementNode:",
-fn: function (aNode){
+selector: "interpretJSStatementNode:continue:",
+fn: function (aNode,aBlock){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
self["@shouldReturn"]=true;
-_st(self)._continue_(_st(self)._eval_(_st(aNode)._source()));
-return self}, function($ctx1) {$ctx1.fill(self,"visitJSStatementNode:",{aNode:aNode}, smalltalk.ASTInterpreter)})}
+_st(self)._continue_value_(aBlock,_st(self)._eval_(_st(aNode)._source()));
+return self}, function($ctx1) {$ctx1.fill(self,"interpretJSStatementNode:continue:",{aNode:aNode,aBlock:aBlock}, smalltalk.ASTInterpreter)})}
 }),
 smalltalk.ASTInterpreter);
 
 smalltalk.addMethod(
-"_visitReturnNode_",
+"_interpretMethodNode_continue_",
 smalltalk.method({
-selector: "visitReturnNode:",
-fn: function (aNode){
+selector: "interpretMethodNode:continue:",
+fn: function (aNode,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(self)._interpretAll_continue_(_st(aNode)._nodes(),(function(array){
+return smalltalk.withContext(function($ctx2) {
return _st(self)._continue_value_(aBlock,_st(array)._first());
+}, function($ctx2) {$ctx2.fillBlock({array:array},$ctx1)})}));
+return self}, function($ctx1) {$ctx1.fill(self,"interpretMethodNode:continue:",{aNode:aNode,aBlock:aBlock}, smalltalk.ASTInterpreter)})}
+}),
+smalltalk.ASTInterpreter);
+
+smalltalk.addMethod(
+"_interpretNode_continue_",
+smalltalk.method({
+selector: "interpretNode:continue:",
+fn: function (aNode,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(aNode)._interpreter_continue_(self,aBlock);
+return self}, function($ctx1) {$ctx1.fill(self,"interpretNode:continue:",{aNode:aNode,aBlock:aBlock}, smalltalk.ASTInterpreter)})}
+}),
+smalltalk.ASTInterpreter);
+
+smalltalk.addMethod(
+"_interpretReturnNode_continue_",
+smalltalk.method({
+selector: "interpretReturnNode:continue:",
+fn: function (aNode,aBlock){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
_st(self)._interpret_continue_(_st(_st(aNode)._nodes())._first(),(function(value){
 return smalltalk.withContext(function($ctx2) {
self["@shouldReturn"]=true;
 self["@shouldReturn"];
-return _st(self)._continue_(value);
+return _st(self)._continue_value_(aBlock,value);
 }, function($ctx2) {$ctx2.fillBlock({value:value},$ctx1)})}));
-return self}, function($ctx1) {$ctx1.fill(self,"visitReturnNode:",{aNode:aNode}, smalltalk.ASTInterpreter)})}
+return self}, function($ctx1) {$ctx1.fill(self,"interpretReturnNode:continue:",{aNode:aNode,aBlock:aBlock}, smalltalk.ASTInterpreter)})}
 }),
 smalltalk.ASTInterpreter);
 
 smalltalk.addMethod(
-"_visitSendNode_",
+"_interpretSendNode_continue_",
 smalltalk.method({
-selector: "visitSendNode:",
-fn: function (aNode){
+selector: "interpretSendNode:continue:",
+fn: function (aNode,aBlock){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
_st(self)._interpret_continue_(_st(aNode)._receiver(),(function(receiver){
 return smalltalk.withContext(function($ctx2) {
return _st(self)._messageFromSendNode_do_(aNode,(function(message){
 return smalltalk.withContext(function($ctx3) {
_st(_st(self)._context())._pc_(_st(_st(_st(self)._context())._pc()).__plus((1)));
-return _st(self)._continue_(_st(message)._sendTo_(receiver));
+return _st(self)._continue_value_(aBlock,_st(message)._sendTo_(receiver));
 }, function($ctx3) {$ctx3.fillBlock({message:message},$ctx1)})}));
 }, function($ctx2) {$ctx2.fillBlock({receiver:receiver},$ctx1)})}));
-return self}, function($ctx1) {$ctx1.fill(self,"visitSendNode:",{aNode:aNode}, smalltalk.ASTInterpreter)})}
+return self}, function($ctx1) {$ctx1.fill(self,"interpretSendNode:continue:",{aNode:aNode,aBlock:aBlock}, smalltalk.ASTInterpreter)})}
 }),
 smalltalk.ASTInterpreter);
 
 smalltalk.addMethod(
-"_visitSequenceNode_",
+"_interpretSequenceNode_continue_",
 smalltalk.method({
-selector: "visitSequenceNode:",
-fn: function (aNode){
+selector: "interpretSequenceNode:continue:",
+fn: function (aNode,aBlock){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
_st(self)._interpretAll_continue_(_st(aNode)._nodes(),(function(array){
-return smalltalk.withContext(function($ctx2) {
return _st(self)._continue_(_st(array)._last());
+return smalltalk.withContext(function($ctx2) {
return _st(self)._continue_value_(aBlock,_st(array)._last());
 }, function($ctx2) {$ctx2.fillBlock({array:array},$ctx1)})}));
-return self}, function($ctx1) {$ctx1.fill(self,"visitSequenceNode:",{aNode:aNode}, smalltalk.ASTInterpreter)})}
+return self}, function($ctx1) {$ctx1.fill(self,"interpretSequenceNode:continue:",{aNode:aNode,aBlock:aBlock}, smalltalk.ASTInterpreter)})}
 }),
 smalltalk.ASTInterpreter);
 
 smalltalk.addMethod(
-"_visitValueNode_",
+"_interpretValueNode_continue_",
 smalltalk.method({
-selector: "visitValueNode:",
-fn: function (aNode){
+selector: "interpretValueNode:continue:",
+fn: function (aNode,aBlock){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
_st(self)._continue_(_st(aNode)._value());
-return self}, function($ctx1) {$ctx1.fill(self,"visitValueNode:",{aNode:aNode}, smalltalk.ASTInterpreter)})}
+return smalltalk.withContext(function($ctx1) { 
_st(self)._continue_value_(aBlock,_st(aNode)._value());
+return self}, function($ctx1) {$ctx1.fill(self,"interpretValueNode:continue:",{aNode:aNode,aBlock:aBlock}, smalltalk.ASTInterpreter)})}
 }),
 smalltalk.ASTInterpreter);
 
 smalltalk.addMethod(
-"_visitVariableNode_",
+"_interpretVariableNode_continue_",
 smalltalk.method({
-selector: "visitVariableNode:",
-fn: function (aNode){
+selector: "interpretVariableNode:continue:",
+fn: function (aNode,aBlock){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$2;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$4,$3;
 $1=self;
-$3=_st(_st(aNode)._binding())._isInstanceVar();
-if(smalltalk.assert($3)){
-$2=_st(_st(_st(self)._context())._receiver())._instVarAt_(_st(aNode)._value());
+$2=aBlock;
+$4=_st(_st(aNode)._binding())._isInstanceVar();
+if(smalltalk.assert($4)){
+$3=_st(_st(_st(self)._context())._receiver())._instVarAt_(_st(aNode)._value());
 } else {
-$2=_st(_st(self)._context())._localAt_(_st(aNode)._value());
+$3=_st(_st(self)._context())._localAt_(_st(aNode)._value());
 };
-_st($1)._continue_($2);
-return self}, function($ctx1) {$ctx1.fill(self,"visitVariableNode:",{aNode:aNode}, smalltalk.ASTInterpreter)})}
+_st($1)._continue_value_($2,$3);
+return self}, function($ctx1) {$ctx1.fill(self,"interpretVariableNode:continue:",{aNode:aNode,aBlock:aBlock}, smalltalk.ASTInterpreter)})}
+}),
+smalltalk.ASTInterpreter);
+
+smalltalk.addMethod(
+"_messageFromSendNode_do_",
+smalltalk.method({
+selector: "messageFromSendNode:do:",
+fn: function (aSendNode,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
+_st(self)._interpretAll_continue_(_st(aSendNode)._arguments(),(function(args){
+return smalltalk.withContext(function($ctx2) {
$1=_st((smalltalk.Message || Message))._new();
+_st($1)._selector_(_st(aSendNode)._selector());
+_st($1)._arguments_(args);
+$2=_st($1)._yourself();
+return _st(aBlock)._value_($2);
+}, function($ctx2) {$ctx2.fillBlock({args:args},$ctx1)})}));
+return self}, function($ctx1) {$ctx1.fill(self,"messageFromSendNode:do:",{aSendNode:aSendNode,aBlock:aBlock}, smalltalk.ASTInterpreter)})}
+}),
+smalltalk.ASTInterpreter);
+
+smalltalk.addMethod(
+"_result",
+smalltalk.method({
+selector: "result",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@result"];
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"result",{}, smalltalk.ASTInterpreter)})}
 }),
 smalltalk.ASTInterpreter);
 
@@ -569,3 +608,198 @@ smalltalk.ASTDebugger);
 
 
 
+smalltalk.addMethod(
+"_interpreter_continue_",
+smalltalk.method({
+selector: "interpreter:continue:",
+fn: function (anInterpreter,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(anInterpreter)._interpretNode_continue_(self,aBlock);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"interpreter:continue:",{anInterpreter:anInterpreter,aBlock:aBlock}, smalltalk.Node)})}
+}),
+smalltalk.Node);
+
+smalltalk.addMethod(
+"_interpreter_continue_",
+smalltalk.method({
+selector: "interpreter:continue:",
+fn: function (anInterpreter,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(anInterpreter)._interpretAssignmentNode_continue_(self,aBlock);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"interpreter:continue:",{anInterpreter:anInterpreter,aBlock:aBlock}, smalltalk.AssignmentNode)})}
+}),
+smalltalk.AssignmentNode);
+
+smalltalk.addMethod(
+"_interpreter_continue_",
+smalltalk.method({
+selector: "interpreter:continue:",
+fn: function (anInterpreter,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(anInterpreter)._interpretBlockNode_continue_(self,aBlock);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"interpreter:continue:",{anInterpreter:anInterpreter,aBlock:aBlock}, smalltalk.BlockNode)})}
+}),
+smalltalk.BlockNode);
+
+smalltalk.addMethod(
+"_interpreter_continue_",
+smalltalk.method({
+selector: "interpreter:continue:",
+fn: function (anInterpreter,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(anInterpreter)._interpretCascadeNode_continue_(self,aBlock);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"interpreter:continue:",{anInterpreter:anInterpreter,aBlock:aBlock}, smalltalk.CascadeNode)})}
+}),
+smalltalk.CascadeNode);
+
+smalltalk.addMethod(
+"_interpreter_continue_",
+smalltalk.method({
+selector: "interpreter:continue:",
+fn: function (anInterpreter,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(anInterpreter)._interpretDynamicArrayNode_continue_(self,aBlock);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"interpreter:continue:",{anInterpreter:anInterpreter,aBlock:aBlock}, smalltalk.DynamicArrayNode)})}
+}),
+smalltalk.DynamicArrayNode);
+
+smalltalk.addMethod(
+"_interpreter_continue_",
+smalltalk.method({
+selector: "interpreter:continue:",
+fn: function (anInterpreter,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(anInterpreter)._interpretDynamicDictionaryNode_continue_(self,aBlock);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"interpreter:continue:",{anInterpreter:anInterpreter,aBlock:aBlock}, smalltalk.DynamicDictionaryNode)})}
+}),
+smalltalk.DynamicDictionaryNode);
+
+smalltalk.addMethod(
+"_interpreter_continue_",
+smalltalk.method({
+selector: "interpreter:continue:",
+fn: function (anInterpreter,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(anInterpreter)._interpretJSStatementNode_continue_(self,aBlock);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"interpreter:continue:",{anInterpreter:anInterpreter,aBlock:aBlock}, smalltalk.JSStatementNode)})}
+}),
+smalltalk.JSStatementNode);
+
+smalltalk.addMethod(
+"_interpreter_continue_",
+smalltalk.method({
+selector: "interpreter:continue:",
+fn: function (anInterpreter,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(anInterpreter)._interpretMethodNode_continue_(self,aBlock);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"interpreter:continue:",{anInterpreter:anInterpreter,aBlock:aBlock}, smalltalk.MethodNode)})}
+}),
+smalltalk.MethodNode);
+
+smalltalk.addMethod(
+"_interpreter_continue_",
+smalltalk.method({
+selector: "interpreter:continue:",
+fn: function (anInterpreter,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(anInterpreter)._interpretReturnNode_continue_(self,aBlock);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"interpreter:continue:",{anInterpreter:anInterpreter,aBlock:aBlock}, smalltalk.ReturnNode)})}
+}),
+smalltalk.ReturnNode);
+
+smalltalk.addMethod(
+"_interpreter_continue_",
+smalltalk.method({
+selector: "interpreter:continue:",
+fn: function (anInterpreter,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(anInterpreter)._interpretSendNode_continue_(self,aBlock);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"interpreter:continue:",{anInterpreter:anInterpreter,aBlock:aBlock}, smalltalk.SendNode)})}
+}),
+smalltalk.SendNode);
+
+smalltalk.addMethod(
+"_interpreter_continue_",
+smalltalk.method({
+selector: "interpreter:continue:",
+fn: function (anInterpreter,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(anInterpreter)._interpretSequenceNode_continue_(self,aBlock);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"interpreter:continue:",{anInterpreter:anInterpreter,aBlock:aBlock}, smalltalk.SequenceNode)})}
+}),
+smalltalk.SequenceNode);
+
+smalltalk.addMethod(
+"_interpreter_continue_",
+smalltalk.method({
+selector: "interpreter:continue:",
+fn: function (anInterpreter,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(anInterpreter)._interpretBlockSequenceNode_continue_(self,aBlock);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"interpreter:continue:",{anInterpreter:anInterpreter,aBlock:aBlock}, smalltalk.BlockSequenceNode)})}
+}),
+smalltalk.BlockSequenceNode);
+
+smalltalk.addMethod(
+"_interpreter_continue_",
+smalltalk.method({
+selector: "interpreter:continue:",
+fn: function (anInterpreter,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(anInterpreter)._interpretValueNode_continue_(self,aBlock);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"interpreter:continue:",{anInterpreter:anInterpreter,aBlock:aBlock}, smalltalk.ValueNode)})}
+}),
+smalltalk.ValueNode);
+
+smalltalk.addMethod(
+"_interpreter_continue_",
+smalltalk.method({
+selector: "interpreter:continue:",
+fn: function (anInterpreter,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(anInterpreter)._interpretVariableNode_continue_(self,aBlock);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"interpreter:continue:",{anInterpreter:anInterpreter,aBlock:aBlock}, smalltalk.VariableNode)})}
+}),
+smalltalk.VariableNode);
+
+smalltalk.addMethod(
+"_interpreter_continue_",
+smalltalk.method({
+selector: "interpreter:continue:",
+fn: function (anInterpreter,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(anInterpreter)._interpretClassReferenceNode_continue_(self,aBlock);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"interpreter:continue:",{anInterpreter:anInterpreter,aBlock:aBlock}, smalltalk.ClassReferenceNode)})}
+}),
+smalltalk.ClassReferenceNode);
+

+ 503 - 178
js/Compiler-Interpreter.js

@@ -198,12 +198,13 @@ smalltalk.AIContext);
 
 
 
-smalltalk.addClass('ASTInterpreter', smalltalk.NodeVisitor, ['currentNode', 'context', 'shouldReturn', 'currentValue'], 'Compiler-Interpreter');
+smalltalk.addClass('ASTInterpreter', smalltalk.Object, ['currentNode', 'context', 'shouldReturn', 'result'], 'Compiler-Interpreter');
+smalltalk.ASTInterpreter.comment="ASTIntepreter is like a `NodeVisitor`, interpreting nodes one after each other.\x0aIt is built using Continuation Passing Style for stepping purposes."
 smalltalk.addMethod(
 "_assign_to_",
 smalltalk.method({
 selector: "assign:to:",
-category: 'interpreting',
+category: 'private',
 fn: function (aNode,anObject){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
var $2,$1;
@@ -263,35 +264,18 @@ referencedClasses: []
 smalltalk.ASTInterpreter);
 
 smalltalk.addMethod(
-"_continue_",
+"_continue_value_",
 smalltalk.method({
-selector: "continue:",
-category: 'interpreting',
-fn: function (anObject){
+selector: "continue:value:",
+category: 'private',
+fn: function (aBlock,anObject){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
self["@currentValue"]=anObject;
-return self}, function($ctx1) {$ctx1.fill(self,"continue:",{anObject:anObject}, smalltalk.ASTInterpreter)})},
-args: ["anObject"],
-source: "continue: anObject\x0a\x09currentValue := anObject",
-messageSends: [],
-referencedClasses: []
-}),
-smalltalk.ASTInterpreter);
-
-smalltalk.addMethod(
-"_currentValue",
-smalltalk.method({
-selector: "currentValue",
-category: 'accessing',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
-$1=self["@currentValue"];
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"currentValue",{}, smalltalk.ASTInterpreter)})},
-args: [],
-source: "currentValue\x0a\x09^ currentValue",
-messageSends: [],
+return smalltalk.withContext(function($ctx1) { 
self["@result"]=anObject;
+_st(aBlock)._value_(anObject);
+return self}, function($ctx1) {$ctx1.fill(self,"continue:value:",{aBlock:aBlock,anObject:anObject}, smalltalk.ASTInterpreter)})},
+args: ["aBlock", "anObject"],
+source: "continue: aBlock value: anObject\x0a\x09result := anObject.\x0a    aBlock value: anObject",
+messageSends: ["value:"],
 referencedClasses: []
 }),
 smalltalk.ASTInterpreter);
@@ -300,7 +284,7 @@ smalltalk.addMethod(
 "_eval_",
 smalltalk.method({
 selector: "eval:",
-category: 'interpreting',
+category: 'private',
 fn: function (aString){
 var self=this;
 var source,function_;
@@ -336,7 +320,7 @@ selector: "initialize",
 category: 'initialization',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
smalltalk.NodeVisitor.fn.prototype._initialize.apply(_st(self), []);
+return smalltalk.withContext(function($ctx1) { 
smalltalk.Object.fn.prototype._initialize.apply(_st(self), []);
 self["@shouldReturn"]=false;
 return self}, function($ctx1) {$ctx1.fill(self,"initialize",{}, smalltalk.ASTInterpreter)})},
 args: [],
@@ -355,12 +339,12 @@ fn: function (aNode){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
self["@shouldReturn"]=false;
 _st(self)._interpret_continue_(aNode,(function(value){
-return smalltalk.withContext(function($ctx2) {
self["@currentValue"]=value;
-return self["@currentValue"];
+return smalltalk.withContext(function($ctx2) {
self["@result"]=value;
+return self["@result"];
 }, function($ctx2) {$ctx2.fillBlock({value:value},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"interpret:",{aNode:aNode}, smalltalk.ASTInterpreter)})},
 args: ["aNode"],
-source: "interpret: aNode\x0a\x09shouldReturn := false.\x0a    self interpret: aNode continue: [ :value |\x0a    \x09currentValue := value ]",
+source: "interpret: aNode\x0a\x09shouldReturn := false.\x0a    self interpret: aNode continue: [ :value |\x0a    \x09result := value ]",
 messageSends: ["interpret:continue:"],
 referencedClasses: []
 }),
@@ -381,16 +365,18 @@ return $2;
 };
 $3=_st(aNode)._isNode();
 if(smalltalk.assert($3)){
-_st(self)._visit_(aNode);
+self["@currentNode"]=aNode;
+self["@currentNode"];
+_st(self)._interpretNode_continue_(aNode,(function(value){
+return smalltalk.withContext(function($ctx2) {
return _st(self)._continue_value_(aBlock,value);
+}, function($ctx2) {$ctx2.fillBlock({value:value},$ctx1)})}));
 } else {
-self["@currentValue"]=aNode;
-self["@currentValue"];
+_st(self)._continue_value_(aBlock,aNode);
 };
-_st(aBlock)._value_(_st(self)._currentValue());
 return self}, function($ctx1) {$ctx1.fill(self,"interpret:continue:",{aNode:aNode,aBlock:aBlock}, smalltalk.ASTInterpreter)})},
 args: ["aNode", "aBlock"],
-source: "interpret: aNode continue: aBlock\x0a\x09shouldReturn ifTrue: [ ^ self ].\x0a\x0a\x09aNode isNode \x0a    \x09ifTrue: [ self visit: aNode ]\x0a        ifFalse: [ currentValue := aNode ].\x0a\x09aBlock value: self currentValue",
-messageSends: ["ifTrue:", "ifTrue:ifFalse:", "visit:", "isNode", "value:", "currentValue"],
+source: "interpret: aNode continue: aBlock\x0a\x09shouldReturn ifTrue: [ ^ self ].\x0a\x0a\x09aNode isNode \x0a    \x09ifTrue: [ \x09\x0a        \x09currentNode := aNode.\x0a            self interpretNode: aNode continue: [ :value |\x0a  \x09\x09\x09\x09self continue: aBlock value: value] ]\x0a        ifFalse: [ self continue: aBlock value: aNode ]",
+messageSends: ["ifTrue:", "ifTrue:ifFalse:", "interpretNode:continue:", "continue:value:", "isNode"],
 referencedClasses: []
 }),
 smalltalk.ASTInterpreter);
@@ -399,7 +385,7 @@ smalltalk.addMethod(
 "_interpretAll_continue_",
 smalltalk.method({
 selector: "interpretAll:continue:",
-category: 'interpreting',
+category: 'private',
 fn: function (aCollection,aBlock){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
_st(self)._interpretAll_continue_result_(aCollection,aBlock,_st((smalltalk.OrderedCollection || OrderedCollection))._new());
@@ -415,7 +401,7 @@ smalltalk.addMethod(
 "_interpretAll_continue_result_",
 smalltalk.method({
 selector: "interpretAll:continue:result:",
-category: 'interpreting',
+category: 'private',
 fn: function (nodes,aBlock,aCollection){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
var $1;
@@ -436,74 +422,67 @@ referencedClasses: []
 smalltalk.ASTInterpreter);
 
 smalltalk.addMethod(
-"_messageFromSendNode_do_",
+"_interpretAssignmentNode_continue_",
 smalltalk.method({
-selector: "messageFromSendNode:do:",
+selector: "interpretAssignmentNode:continue:",
 category: 'interpreting',
-fn: function (aSendNode,aBlock){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2;
-_st(self)._interpretAll_continue_(_st(aSendNode)._arguments(),(function(args){
-return smalltalk.withContext(function($ctx2) {
$1=_st((smalltalk.Message || Message))._new();
-_st($1)._selector_(_st(aSendNode)._selector());
-_st($1)._arguments_(args);
-$2=_st($1)._yourself();
-return _st(aBlock)._value_($2);
-}, function($ctx2) {$ctx2.fillBlock({args:args},$ctx1)})}));
-return self}, function($ctx1) {$ctx1.fill(self,"messageFromSendNode:do:",{aSendNode:aSendNode,aBlock:aBlock}, smalltalk.ASTInterpreter)})},
-args: ["aSendNode", "aBlock"],
-source: "messageFromSendNode: aSendNode do: aBlock\x0a\x09self interpretAll: aSendNode arguments continue: [ :args |\x0a    \x09aBlock value: (Message new\x0a    \x09\x09selector: aSendNode selector;\x0a        \x09arguments: args;\x0a        \x09yourself) ]",
-messageSends: ["interpretAll:continue:", "arguments", "value:", "selector:", "selector", "new", "arguments:", "yourself"],
-referencedClasses: ["Message"]
-}),
-smalltalk.ASTInterpreter);
-
-smalltalk.addMethod(
-"_visitAssignmentNode_",
-smalltalk.method({
-selector: "visitAssignmentNode:",
-category: 'visiting',
-fn: function (aNode){
+fn: function (aNode,aBlock){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
_st(self)._interpret_continue_(_st(aNode)._right(),(function(value){
-return smalltalk.withContext(function($ctx2) {
return _st(self)._continue_(_st(self)._assign_to_(_st(aNode)._left(),value));
+return smalltalk.withContext(function($ctx2) {
return _st(self)._continue_value_(aBlock,_st(self)._assign_to_(_st(aNode)._left(),value));
 }, function($ctx2) {$ctx2.fillBlock({value:value},$ctx1)})}));
-return self}, function($ctx1) {$ctx1.fill(self,"visitAssignmentNode:",{aNode:aNode}, smalltalk.ASTInterpreter)})},
-args: ["aNode"],
-source: "visitAssignmentNode: aNode\x0a\x09self interpret: aNode right continue: [ :value |\x0a    \x09self continue: (self assign: aNode left to: value) ]",
-messageSends: ["interpret:continue:", "right", "continue:", "assign:to:", "left"],
+return self}, function($ctx1) {$ctx1.fill(self,"interpretAssignmentNode:continue:",{aNode:aNode,aBlock:aBlock}, smalltalk.ASTInterpreter)})},
+args: ["aNode", "aBlock"],
+source: "interpretAssignmentNode: aNode continue: aBlock\x0a\x09self interpret: aNode right continue: [ :value |\x0a    \x09self \x0a        \x09continue: aBlock\x0a            value: (self assign: aNode left to: value) ]",
+messageSends: ["interpret:continue:", "right", "continue:value:", "assign:to:", "left"],
 referencedClasses: []
 }),
 smalltalk.ASTInterpreter);
 
 smalltalk.addMethod(
-"_visitBlockNode_",
+"_interpretBlockNode_continue_",
 smalltalk.method({
-selector: "visitBlockNode:",
-category: 'visiting',
-fn: function (aNode){
+selector: "interpretBlockNode:continue:",
+category: 'interpreting',
+fn: function (aNode,aBlock){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
var $1,$2;
-_st(self)._continue_((function(){
+_st(self)._continue_value_(aBlock,(function(){
 return smalltalk.withContext(function($ctx2) {
$1=self;
 _st($1)._interpret_(_st(_st(aNode)._nodes())._first());
-$2=_st($1)._currentValue();
+$2=_st($1)._result();
 return $2;
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
-return self}, function($ctx1) {$ctx1.fill(self,"visitBlockNode:",{aNode:aNode}, smalltalk.ASTInterpreter)})},
-args: ["aNode"],
-source: "visitBlockNode: aNode\x0a\x09\x22TODO: Context should be set\x22\x0a    \x0a    self continue: [ self interpret: aNode nodes first; currentValue ]",
-messageSends: ["continue:", "interpret:", "first", "nodes", "currentValue"],
+return self}, function($ctx1) {$ctx1.fill(self,"interpretBlockNode:continue:",{aNode:aNode,aBlock:aBlock}, smalltalk.ASTInterpreter)})},
+args: ["aNode", "aBlock"],
+source: "interpretBlockNode: aNode continue: aBlock\x0a\x09\x22TODO: Context should be set\x22\x0a    \x0a    self \x0a    \x09continue: aBlock \x0a        value: [ self interpret: aNode nodes first; result ]",
+messageSends: ["continue:value:", "interpret:", "first", "nodes", "result"],
 referencedClasses: []
 }),
 smalltalk.ASTInterpreter);
 
 smalltalk.addMethod(
-"_visitCascadeNode_",
+"_interpretBlockSequenceNode_continue_",
 smalltalk.method({
-selector: "visitCascadeNode:",
-category: 'visiting',
-fn: function (aNode){
+selector: "interpretBlockSequenceNode:continue:",
+category: 'interpreting',
+fn: function (aNode,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(self)._interpretSequenceNode_continue_(aNode,aBlock);
+return self}, function($ctx1) {$ctx1.fill(self,"interpretBlockSequenceNode:continue:",{aNode:aNode,aBlock:aBlock}, smalltalk.ASTInterpreter)})},
+args: ["aNode", "aBlock"],
+source: "interpretBlockSequenceNode: aNode continue: aBlock\x0a\x09self interpretSequenceNode: aNode continue: aBlock",
+messageSends: ["interpretSequenceNode:continue:"],
+referencedClasses: []
+}),
+smalltalk.ASTInterpreter);
+
+smalltalk.addMethod(
+"_interpretCascadeNode_continue_",
+smalltalk.method({
+selector: "interpretCascadeNode:continue:",
+category: 'interpreting',
+fn: function (aNode,aBlock){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
_st(self)._interpret_continue_(_st(aNode)._receiver(),(function(receiver){
 return smalltalk.withContext(function($ctx2) {
_st(_st(aNode)._nodes())._do_((function(each){
@@ -511,58 +490,58 @@ return smalltalk.withContext(function($ctx3) {
return _st(each)._receiver_(recei
 }, function($ctx3) {$ctx3.fillBlock({each:each},$ctx1)})}));
 return _st(self)._interpretAll_continue_(_st(_st(aNode)._nodes())._allButLast(),(function(){
 return smalltalk.withContext(function($ctx3) {
return _st(self)._interpret_continue_(_st(_st(aNode)._nodes())._last(),(function(val){
-return smalltalk.withContext(function($ctx4) {
return _st(self)._continue_(val);
+return smalltalk.withContext(function($ctx4) {
return _st(self)._continue_value_(aBlock,val);
 }, function($ctx4) {$ctx4.fillBlock({val:val},$ctx1)})}));
 }, function($ctx3) {$ctx3.fillBlock({},$ctx1)})}));
 }, function($ctx2) {$ctx2.fillBlock({receiver:receiver},$ctx1)})}));
-return self}, function($ctx1) {$ctx1.fill(self,"visitCascadeNode:",{aNode:aNode}, smalltalk.ASTInterpreter)})},
-args: ["aNode"],
-source: "visitCascadeNode: aNode\x0a\x09\x22TODO: Handle super sends\x22\x0a\x09\x0a    self interpret: aNode receiver continue: [ :receiver |\x0a\x09\x09\x22Only interpret the receiver once\x22\x0a        aNode nodes do: [ :each | each receiver: receiver ].\x0a  \x0a    \x09self \x0a        \x09interpretAll: aNode nodes allButLast\x0a    \x09\x09continue: [\x0a              \x09self \x0a                \x09interpret: aNode nodes last\x0a                \x09continue: [ :val | self continue: val ] ] ]",
-messageSends: ["interpret:continue:", "receiver", "do:", "receiver:", "nodes", "interpretAll:continue:", "allButLast", "last", "continue:"],
+return self}, function($ctx1) {$ctx1.fill(self,"interpretCascadeNode:continue:",{aNode:aNode,aBlock:aBlock}, smalltalk.ASTInterpreter)})},
+args: ["aNode", "aBlock"],
+source: "interpretCascadeNode: aNode continue: aBlock\x0a\x09\x22TODO: Handle super sends\x22\x0a\x09\x0a    self interpret: aNode receiver continue: [ :receiver |\x0a\x09\x09\x22Only interpret the receiver once\x22\x0a        aNode nodes do: [ :each | each receiver: receiver ].\x0a  \x0a    \x09self \x0a        \x09interpretAll: aNode nodes allButLast\x0a    \x09\x09continue: [\x0a              \x09self \x0a                \x09interpret: aNode nodes last\x0a                \x09continue: [ :val | self continue: aBlock value: val ] ] ]",
+messageSends: ["interpret:continue:", "receiver", "do:", "receiver:", "nodes", "interpretAll:continue:", "allButLast", "last", "continue:value:"],
 referencedClasses: []
 }),
 smalltalk.ASTInterpreter);
 
 smalltalk.addMethod(
-"_visitClassReferenceNode_",
+"_interpretClassReferenceNode_continue_",
 smalltalk.method({
-selector: "visitClassReferenceNode:",
-category: 'visiting',
-fn: function (aNode){
+selector: "interpretClassReferenceNode:continue:",
+category: 'interpreting',
+fn: function (aNode,aBlock){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
_st(self)._continue_(_st(_st((smalltalk.Smalltalk || Smalltalk))._current())._at_(_st(aNode)._value()));
-return self}, function($ctx1) {$ctx1.fill(self,"visitClassReferenceNode:",{aNode:aNode}, smalltalk.ASTInterpreter)})},
-args: ["aNode"],
-source: "visitClassReferenceNode: aNode\x0a\x09self continue: (Smalltalk current at: aNode value)",
-messageSends: ["continue:", "at:", "value", "current"],
+return smalltalk.withContext(function($ctx1) { 
_st(self)._continue_value_(aBlock,_st(_st((smalltalk.Smalltalk || Smalltalk))._current())._at_(_st(aNode)._value()));
+return self}, function($ctx1) {$ctx1.fill(self,"interpretClassReferenceNode:continue:",{aNode:aNode,aBlock:aBlock}, smalltalk.ASTInterpreter)})},
+args: ["aNode", "aBlock"],
+source: "interpretClassReferenceNode: aNode continue: aBlock\x0a\x09self continue: aBlock value: (Smalltalk current at: aNode value)",
+messageSends: ["continue:value:", "at:", "value", "current"],
 referencedClasses: ["Smalltalk"]
 }),
 smalltalk.ASTInterpreter);
 
 smalltalk.addMethod(
-"_visitDynamicArrayNode_",
+"_interpretDynamicArrayNode_continue_",
 smalltalk.method({
-selector: "visitDynamicArrayNode:",
-category: 'visiting',
-fn: function (aNode){
+selector: "interpretDynamicArrayNode:continue:",
+category: 'interpreting',
+fn: function (aNode,aBlock){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
_st(self)._interpretAll_continue_(_st(aNode)._nodes(),(function(array){
-return smalltalk.withContext(function($ctx2) {
return _st(self)._continue_(array);
+return smalltalk.withContext(function($ctx2) {
return _st(self)._continue_value_(aBlock,array);
 }, function($ctx2) {$ctx2.fillBlock({array:array},$ctx1)})}));
-return self}, function($ctx1) {$ctx1.fill(self,"visitDynamicArrayNode:",{aNode:aNode}, smalltalk.ASTInterpreter)})},
-args: ["aNode"],
-source: "visitDynamicArrayNode: aNode\x0a\x09self interpretAll: aNode nodes continue: [ :array |\x0a    \x09self continue: array ]",
-messageSends: ["interpretAll:continue:", "nodes", "continue:"],
+return self}, function($ctx1) {$ctx1.fill(self,"interpretDynamicArrayNode:continue:",{aNode:aNode,aBlock:aBlock}, smalltalk.ASTInterpreter)})},
+args: ["aNode", "aBlock"],
+source: "interpretDynamicArrayNode: aNode continue: aBlock\x0a\x09self interpretAll: aNode nodes continue: [ :array |\x0a    \x09self \x0a        \x09continue: aBlock\x0a\x09\x09\x09value: array ]",
+messageSends: ["interpretAll:continue:", "nodes", "continue:value:"],
 referencedClasses: []
 }),
 smalltalk.ASTInterpreter);
 
 smalltalk.addMethod(
-"_visitDynamicDictionaryNode_",
+"_interpretDynamicDictionaryNode_continue_",
 smalltalk.method({
-selector: "visitDynamicDictionaryNode:",
-category: 'visiting',
-fn: function (aNode){
+selector: "interpretDynamicDictionaryNode:continue:",
+category: 'interpreting',
+fn: function (aNode,aBlock){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
_st(self)._interpretAll_continue_(_st(aNode)._nodes(),(function(array){
 var hashedCollection;
@@ -571,128 +550,204 @@ hashedCollection;
 _st(array)._do_((function(each){
 return smalltalk.withContext(function($ctx3) {
return _st(hashedCollection)._add_(each);
 }, function($ctx3) {$ctx3.fillBlock({each:each},$ctx1)})}));
-return _st(self)._continue_(hashedCollection);
+return _st(self)._continue_value_(aBlock,hashedCollection);
 }, function($ctx2) {$ctx2.fillBlock({array:array,hashedCollection:hashedCollection},$ctx1)})}));
-return self}, function($ctx1) {$ctx1.fill(self,"visitDynamicDictionaryNode:",{aNode:aNode}, smalltalk.ASTInterpreter)})},
-args: ["aNode"],
-source: "visitDynamicDictionaryNode: aNode\x0a    self interpretAll: aNode nodes continue: [ :array | | hashedCollection |\x0a    \x09hashedCollection := HashedCollection new.\x0a        array do: [ :each | hashedCollection add: each ].\x0a        self continue: hashedCollection ]",
-messageSends: ["interpretAll:continue:", "nodes", "new", "do:", "add:", "continue:"],
+return self}, function($ctx1) {$ctx1.fill(self,"interpretDynamicDictionaryNode:continue:",{aNode:aNode,aBlock:aBlock}, smalltalk.ASTInterpreter)})},
+args: ["aNode", "aBlock"],
+source: "interpretDynamicDictionaryNode: aNode continue: aBlock\x0a    self interpretAll: aNode nodes continue: [ :array | | hashedCollection |\x0a    \x09hashedCollection := HashedCollection new.\x0a        array do: [ :each | hashedCollection add: each ].\x0a        self \x09\x0a        \x09continue: aBlock\x0a            value: hashedCollection ]",
+messageSends: ["interpretAll:continue:", "nodes", "new", "do:", "add:", "continue:value:"],
 referencedClasses: ["HashedCollection"]
 }),
 smalltalk.ASTInterpreter);
 
 smalltalk.addMethod(
-"_visitJSStatementNode_",
+"_interpretJSStatementNode_continue_",
 smalltalk.method({
-selector: "visitJSStatementNode:",
-category: 'visiting',
-fn: function (aNode){
+selector: "interpretJSStatementNode:continue:",
+category: 'interpreting',
+fn: function (aNode,aBlock){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
self["@shouldReturn"]=true;
-_st(self)._continue_(_st(self)._eval_(_st(aNode)._source()));
-return self}, function($ctx1) {$ctx1.fill(self,"visitJSStatementNode:",{aNode:aNode}, smalltalk.ASTInterpreter)})},
-args: ["aNode"],
-source: "visitJSStatementNode: aNode\x0a\x09shouldReturn := true.\x0a\x09self continue: (self eval: aNode source)",
-messageSends: ["continue:", "eval:", "source"],
+_st(self)._continue_value_(aBlock,_st(self)._eval_(_st(aNode)._source()));
+return self}, function($ctx1) {$ctx1.fill(self,"interpretJSStatementNode:continue:",{aNode:aNode,aBlock:aBlock}, smalltalk.ASTInterpreter)})},
+args: ["aNode", "aBlock"],
+source: "interpretJSStatementNode: aNode continue: aBlock\x0a\x09shouldReturn := true.\x0a\x09self continue: aBlock value: (self eval: aNode source)",
+messageSends: ["continue:value:", "eval:", "source"],
 referencedClasses: []
 }),
 smalltalk.ASTInterpreter);
 
 smalltalk.addMethod(
-"_visitReturnNode_",
+"_interpretMethodNode_continue_",
 smalltalk.method({
-selector: "visitReturnNode:",
-category: 'visiting',
-fn: function (aNode){
+selector: "interpretMethodNode:continue:",
+category: 'interpreting',
+fn: function (aNode,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(self)._interpretAll_continue_(_st(aNode)._nodes(),(function(array){
+return smalltalk.withContext(function($ctx2) {
return _st(self)._continue_value_(aBlock,_st(array)._first());
+}, function($ctx2) {$ctx2.fillBlock({array:array},$ctx1)})}));
+return self}, function($ctx1) {$ctx1.fill(self,"interpretMethodNode:continue:",{aNode:aNode,aBlock:aBlock}, smalltalk.ASTInterpreter)})},
+args: ["aNode", "aBlock"],
+source: "interpretMethodNode: aNode continue: aBlock\x0a\x09self interpretAll: aNode nodes continue: [ :array |\x0a    \x09self continue: aBlock value: array first ]",
+messageSends: ["interpretAll:continue:", "nodes", "continue:value:", "first"],
+referencedClasses: []
+}),
+smalltalk.ASTInterpreter);
+
+smalltalk.addMethod(
+"_interpretNode_continue_",
+smalltalk.method({
+selector: "interpretNode:continue:",
+category: 'interpreting',
+fn: function (aNode,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(aNode)._interpreter_continue_(self,aBlock);
+return self}, function($ctx1) {$ctx1.fill(self,"interpretNode:continue:",{aNode:aNode,aBlock:aBlock}, smalltalk.ASTInterpreter)})},
+args: ["aNode", "aBlock"],
+source: "interpretNode: aNode continue: aBlock\x0a    aNode interpreter: self continue: aBlock",
+messageSends: ["interpreter:continue:"],
+referencedClasses: []
+}),
+smalltalk.ASTInterpreter);
+
+smalltalk.addMethod(
+"_interpretReturnNode_continue_",
+smalltalk.method({
+selector: "interpretReturnNode:continue:",
+category: 'interpreting',
+fn: function (aNode,aBlock){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
_st(self)._interpret_continue_(_st(_st(aNode)._nodes())._first(),(function(value){
 return smalltalk.withContext(function($ctx2) {
self["@shouldReturn"]=true;
 self["@shouldReturn"];
-return _st(self)._continue_(value);
+return _st(self)._continue_value_(aBlock,value);
 }, function($ctx2) {$ctx2.fillBlock({value:value},$ctx1)})}));
-return self}, function($ctx1) {$ctx1.fill(self,"visitReturnNode:",{aNode:aNode}, smalltalk.ASTInterpreter)})},
-args: ["aNode"],
-source: "visitReturnNode: aNode\x0a    self interpret: aNode nodes first continue: [ :value |\x0a    \x09shouldReturn := true.\x0a\x09\x09self continue: value ]",
-messageSends: ["interpret:continue:", "first", "nodes", "continue:"],
+return self}, function($ctx1) {$ctx1.fill(self,"interpretReturnNode:continue:",{aNode:aNode,aBlock:aBlock}, smalltalk.ASTInterpreter)})},
+args: ["aNode", "aBlock"],
+source: "interpretReturnNode: aNode continue: aBlock\x0a    self interpret: aNode nodes first continue: [ :value |\x0a    \x09shouldReturn := true.\x0a\x09\x09self continue: aBlock value: value ]",
+messageSends: ["interpret:continue:", "first", "nodes", "continue:value:"],
 referencedClasses: []
 }),
 smalltalk.ASTInterpreter);
 
 smalltalk.addMethod(
-"_visitSendNode_",
+"_interpretSendNode_continue_",
 smalltalk.method({
-selector: "visitSendNode:",
-category: 'visiting',
-fn: function (aNode){
+selector: "interpretSendNode:continue:",
+category: 'interpreting',
+fn: function (aNode,aBlock){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
_st(self)._interpret_continue_(_st(aNode)._receiver(),(function(receiver){
 return smalltalk.withContext(function($ctx2) {
return _st(self)._messageFromSendNode_do_(aNode,(function(message){
 return smalltalk.withContext(function($ctx3) {
_st(_st(self)._context())._pc_(_st(_st(_st(self)._context())._pc()).__plus((1)));
-return _st(self)._continue_(_st(message)._sendTo_(receiver));
+return _st(self)._continue_value_(aBlock,_st(message)._sendTo_(receiver));
 }, function($ctx3) {$ctx3.fillBlock({message:message},$ctx1)})}));
 }, function($ctx2) {$ctx2.fillBlock({receiver:receiver},$ctx1)})}));
-return self}, function($ctx1) {$ctx1.fill(self,"visitSendNode:",{aNode:aNode}, smalltalk.ASTInterpreter)})},
-args: ["aNode"],
-source: "visitSendNode: aNode\x0a\x09\x22TODO: Handle super sends\x22\x0a    \x0a    self interpret: aNode receiver continue: [ :receiver |\x0a    \x09self messageFromSendNode: aNode do: [ :message |\x0a        \x09self context pc: self context pc + 1.\x0a        \x09self continue: (message sendTo: receiver) ] ]",
-messageSends: ["interpret:continue:", "receiver", "messageFromSendNode:do:", "pc:", "+", "pc", "context", "continue:", "sendTo:"],
+return self}, function($ctx1) {$ctx1.fill(self,"interpretSendNode:continue:",{aNode:aNode,aBlock:aBlock}, smalltalk.ASTInterpreter)})},
+args: ["aNode", "aBlock"],
+source: "interpretSendNode: aNode continue: aBlock\x0a\x09\x22TODO: Handle super sends\x22\x0a    \x0a    self interpret: aNode receiver continue: [ :receiver |\x0a    \x09self messageFromSendNode: aNode do: [ :message |\x0a        \x09self context pc: self context pc + 1.\x0a        \x09self \x0a            \x09continue: aBlock \x0a                value: (message sendTo: receiver) ] ]",
+messageSends: ["interpret:continue:", "receiver", "messageFromSendNode:do:", "pc:", "+", "pc", "context", "continue:value:", "sendTo:"],
 referencedClasses: []
 }),
 smalltalk.ASTInterpreter);
 
 smalltalk.addMethod(
-"_visitSequenceNode_",
+"_interpretSequenceNode_continue_",
 smalltalk.method({
-selector: "visitSequenceNode:",
-category: 'visiting',
-fn: function (aNode){
+selector: "interpretSequenceNode:continue:",
+category: 'interpreting',
+fn: function (aNode,aBlock){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
_st(self)._interpretAll_continue_(_st(aNode)._nodes(),(function(array){
-return smalltalk.withContext(function($ctx2) {
return _st(self)._continue_(_st(array)._last());
+return smalltalk.withContext(function($ctx2) {
return _st(self)._continue_value_(aBlock,_st(array)._last());
 }, function($ctx2) {$ctx2.fillBlock({array:array},$ctx1)})}));
-return self}, function($ctx1) {$ctx1.fill(self,"visitSequenceNode:",{aNode:aNode}, smalltalk.ASTInterpreter)})},
-args: ["aNode"],
-source: "visitSequenceNode: aNode\x0a\x09self interpretAll: aNode nodes continue: [ :array |\x0a    \x09self continue: array last ]",
-messageSends: ["interpretAll:continue:", "nodes", "continue:", "last"],
+return self}, function($ctx1) {$ctx1.fill(self,"interpretSequenceNode:continue:",{aNode:aNode,aBlock:aBlock}, smalltalk.ASTInterpreter)})},
+args: ["aNode", "aBlock"],
+source: "interpretSequenceNode: aNode continue: aBlock\x0a\x09self interpretAll: aNode nodes continue: [ :array |\x0a    \x09self continue: aBlock value: array last ]",
+messageSends: ["interpretAll:continue:", "nodes", "continue:value:", "last"],
 referencedClasses: []
 }),
 smalltalk.ASTInterpreter);
 
 smalltalk.addMethod(
-"_visitValueNode_",
+"_interpretValueNode_continue_",
 smalltalk.method({
-selector: "visitValueNode:",
-category: 'visiting',
-fn: function (aNode){
+selector: "interpretValueNode:continue:",
+category: 'interpreting',
+fn: function (aNode,aBlock){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
_st(self)._continue_(_st(aNode)._value());
-return self}, function($ctx1) {$ctx1.fill(self,"visitValueNode:",{aNode:aNode}, smalltalk.ASTInterpreter)})},
-args: ["aNode"],
-source: "visitValueNode: aNode\x0a\x09self continue: aNode value",
-messageSends: ["continue:", "value"],
+return smalltalk.withContext(function($ctx1) { 
_st(self)._continue_value_(aBlock,_st(aNode)._value());
+return self}, function($ctx1) {$ctx1.fill(self,"interpretValueNode:continue:",{aNode:aNode,aBlock:aBlock}, smalltalk.ASTInterpreter)})},
+args: ["aNode", "aBlock"],
+source: "interpretValueNode: aNode continue: aBlock\x0a\x09self continue: aBlock value: aNode value",
+messageSends: ["continue:value:", "value"],
 referencedClasses: []
 }),
 smalltalk.ASTInterpreter);
 
 smalltalk.addMethod(
-"_visitVariableNode_",
+"_interpretVariableNode_continue_",
 smalltalk.method({
-selector: "visitVariableNode:",
-category: 'visiting',
-fn: function (aNode){
+selector: "interpretVariableNode:continue:",
+category: 'interpreting',
+fn: function (aNode,aBlock){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$2;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$4,$3;
 $1=self;
-$3=_st(_st(aNode)._binding())._isInstanceVar();
-if(smalltalk.assert($3)){
-$2=_st(_st(_st(self)._context())._receiver())._instVarAt_(_st(aNode)._value());
+$2=aBlock;
+$4=_st(_st(aNode)._binding())._isInstanceVar();
+if(smalltalk.assert($4)){
+$3=_st(_st(_st(self)._context())._receiver())._instVarAt_(_st(aNode)._value());
 } else {
-$2=_st(_st(self)._context())._localAt_(_st(aNode)._value());
+$3=_st(_st(self)._context())._localAt_(_st(aNode)._value());
 };
-_st($1)._continue_($2);
-return self}, function($ctx1) {$ctx1.fill(self,"visitVariableNode:",{aNode:aNode}, smalltalk.ASTInterpreter)})},
-args: ["aNode"],
-source: "visitVariableNode: aNode\x0a    self continue: (aNode binding isInstanceVar\x0a\x09\x09ifTrue: [ self context receiver instVarAt: aNode value ]\x0a\x09\x09ifFalse: [ self context localAt: aNode value ])",
-messageSends: ["continue:", "ifTrue:ifFalse:", "instVarAt:", "value", "receiver", "context", "localAt:", "isInstanceVar", "binding"],
+_st($1)._continue_value_($2,$3);
+return self}, function($ctx1) {$ctx1.fill(self,"interpretVariableNode:continue:",{aNode:aNode,aBlock:aBlock}, smalltalk.ASTInterpreter)})},
+args: ["aNode", "aBlock"],
+source: "interpretVariableNode: aNode continue: aBlock\x0a    self \x0a    \x09continue: aBlock\x0a        value: (aNode binding isInstanceVar\x0a\x09\x09\x09ifTrue: [ self context receiver instVarAt: aNode value ]\x0a\x09\x09\x09ifFalse: [ self context localAt: aNode value ])",
+messageSends: ["continue:value:", "ifTrue:ifFalse:", "instVarAt:", "value", "receiver", "context", "localAt:", "isInstanceVar", "binding"],
+referencedClasses: []
+}),
+smalltalk.ASTInterpreter);
+
+smalltalk.addMethod(
+"_messageFromSendNode_do_",
+smalltalk.method({
+selector: "messageFromSendNode:do:",
+category: 'private',
+fn: function (aSendNode,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
+_st(self)._interpretAll_continue_(_st(aSendNode)._arguments(),(function(args){
+return smalltalk.withContext(function($ctx2) {
$1=_st((smalltalk.Message || Message))._new();
+_st($1)._selector_(_st(aSendNode)._selector());
+_st($1)._arguments_(args);
+$2=_st($1)._yourself();
+return _st(aBlock)._value_($2);
+}, function($ctx2) {$ctx2.fillBlock({args:args},$ctx1)})}));
+return self}, function($ctx1) {$ctx1.fill(self,"messageFromSendNode:do:",{aSendNode:aSendNode,aBlock:aBlock}, smalltalk.ASTInterpreter)})},
+args: ["aSendNode", "aBlock"],
+source: "messageFromSendNode: aSendNode do: aBlock\x0a\x09self interpretAll: aSendNode arguments continue: [ :args |\x0a    \x09aBlock value: (Message new\x0a    \x09\x09selector: aSendNode selector;\x0a        \x09arguments: args;\x0a        \x09yourself) ]",
+messageSends: ["interpretAll:continue:", "arguments", "value:", "selector:", "selector", "new", "arguments:", "yourself"],
+referencedClasses: ["Message"]
+}),
+smalltalk.ASTInterpreter);
+
+smalltalk.addMethod(
+"_result",
+smalltalk.method({
+selector: "result",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@result"];
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"result",{}, smalltalk.ASTInterpreter)})},
+args: [],
+source: "result\x0a\x09^ result",
+messageSends: [],
 referencedClasses: []
 }),
 smalltalk.ASTInterpreter);
@@ -754,3 +809,273 @@ smalltalk.ASTDebugger);
 
 
 
+smalltalk.addMethod(
+"_interpreter_continue_",
+smalltalk.method({
+selector: "interpreter:continue:",
+category: '*Compiler-Interpreter',
+fn: function (anInterpreter,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(anInterpreter)._interpretNode_continue_(self,aBlock);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"interpreter:continue:",{anInterpreter:anInterpreter,aBlock:aBlock}, smalltalk.Node)})},
+args: ["anInterpreter", "aBlock"],
+source: "interpreter: anInterpreter continue: aBlock\x0a\x09^ anInterpreter interpretNode: self continue: aBlock",
+messageSends: ["interpretNode:continue:"],
+referencedClasses: []
+}),
+smalltalk.Node);
+
+smalltalk.addMethod(
+"_interpreter_continue_",
+smalltalk.method({
+selector: "interpreter:continue:",
+category: '*Compiler-Interpreter',
+fn: function (anInterpreter,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(anInterpreter)._interpretAssignmentNode_continue_(self,aBlock);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"interpreter:continue:",{anInterpreter:anInterpreter,aBlock:aBlock}, smalltalk.AssignmentNode)})},
+args: ["anInterpreter", "aBlock"],
+source: "interpreter: anInterpreter continue: aBlock\x0a\x09^ anInterpreter interpretAssignmentNode: self continue: aBlock",
+messageSends: ["interpretAssignmentNode:continue:"],
+referencedClasses: []
+}),
+smalltalk.AssignmentNode);
+
+smalltalk.addMethod(
+"_interpreter_continue_",
+smalltalk.method({
+selector: "interpreter:continue:",
+category: '*Compiler-Interpreter',
+fn: function (anInterpreter,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(anInterpreter)._interpretBlockNode_continue_(self,aBlock);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"interpreter:continue:",{anInterpreter:anInterpreter,aBlock:aBlock}, smalltalk.BlockNode)})},
+args: ["anInterpreter", "aBlock"],
+source: "interpreter: anInterpreter continue: aBlock\x0a\x09^ anInterpreter interpretBlockNode: self continue: aBlock",
+messageSends: ["interpretBlockNode:continue:"],
+referencedClasses: []
+}),
+smalltalk.BlockNode);
+
+smalltalk.addMethod(
+"_interpreter_continue_",
+smalltalk.method({
+selector: "interpreter:continue:",
+category: '*Compiler-Interpreter',
+fn: function (anInterpreter,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(anInterpreter)._interpretCascadeNode_continue_(self,aBlock);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"interpreter:continue:",{anInterpreter:anInterpreter,aBlock:aBlock}, smalltalk.CascadeNode)})},
+args: ["anInterpreter", "aBlock"],
+source: "interpreter: anInterpreter continue: aBlock\x0a\x09^ anInterpreter interpretCascadeNode: self continue: aBlock",
+messageSends: ["interpretCascadeNode:continue:"],
+referencedClasses: []
+}),
+smalltalk.CascadeNode);
+
+smalltalk.addMethod(
+"_interpreter_continue_",
+smalltalk.method({
+selector: "interpreter:continue:",
+category: '*Compiler-Interpreter',
+fn: function (anInterpreter,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(anInterpreter)._interpretDynamicArrayNode_continue_(self,aBlock);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"interpreter:continue:",{anInterpreter:anInterpreter,aBlock:aBlock}, smalltalk.DynamicArrayNode)})},
+args: ["anInterpreter", "aBlock"],
+source: "interpreter: anInterpreter continue: aBlock\x0a\x09^ anInterpreter interpretDynamicArrayNode: self continue: aBlock",
+messageSends: ["interpretDynamicArrayNode:continue:"],
+referencedClasses: []
+}),
+smalltalk.DynamicArrayNode);
+
+smalltalk.addMethod(
+"_interpreter_continue_",
+smalltalk.method({
+selector: "interpreter:continue:",
+category: '*Compiler-Interpreter',
+fn: function (anInterpreter,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(anInterpreter)._interpretDynamicDictionaryNode_continue_(self,aBlock);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"interpreter:continue:",{anInterpreter:anInterpreter,aBlock:aBlock}, smalltalk.DynamicDictionaryNode)})},
+args: ["anInterpreter", "aBlock"],
+source: "interpreter: anInterpreter continue: aBlock\x0a\x09^ anInterpreter interpretDynamicDictionaryNode: self continue: aBlock",
+messageSends: ["interpretDynamicDictionaryNode:continue:"],
+referencedClasses: []
+}),
+smalltalk.DynamicDictionaryNode);
+
+smalltalk.addMethod(
+"_interpreter_continue_",
+smalltalk.method({
+selector: "interpreter:continue:",
+category: '*Compiler-Interpreter',
+fn: function (anInterpreter,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(anInterpreter)._interpretJSStatementNode_continue_(self,aBlock);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"interpreter:continue:",{anInterpreter:anInterpreter,aBlock:aBlock}, smalltalk.JSStatementNode)})},
+args: ["anInterpreter", "aBlock"],
+source: "interpreter: anInterpreter continue: aBlock\x0a\x09^ anInterpreter interpretJSStatementNode: self continue: aBlock",
+messageSends: ["interpretJSStatementNode:continue:"],
+referencedClasses: []
+}),
+smalltalk.JSStatementNode);
+
+smalltalk.addMethod(
+"_interpreter_continue_",
+smalltalk.method({
+selector: "interpreter:continue:",
+category: '*Compiler-Interpreter',
+fn: function (anInterpreter,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(anInterpreter)._interpretMethodNode_continue_(self,aBlock);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"interpreter:continue:",{anInterpreter:anInterpreter,aBlock:aBlock}, smalltalk.MethodNode)})},
+args: ["anInterpreter", "aBlock"],
+source: "interpreter: anInterpreter continue: aBlock\x0a\x09^ anInterpreter interpretMethodNode: self continue: aBlock",
+messageSends: ["interpretMethodNode:continue:"],
+referencedClasses: []
+}),
+smalltalk.MethodNode);
+
+smalltalk.addMethod(
+"_interpreter_continue_",
+smalltalk.method({
+selector: "interpreter:continue:",
+category: '*Compiler-Interpreter',
+fn: function (anInterpreter,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(anInterpreter)._interpretReturnNode_continue_(self,aBlock);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"interpreter:continue:",{anInterpreter:anInterpreter,aBlock:aBlock}, smalltalk.ReturnNode)})},
+args: ["anInterpreter", "aBlock"],
+source: "interpreter: anInterpreter continue: aBlock\x0a\x09^ anInterpreter interpretReturnNode: self continue: aBlock",
+messageSends: ["interpretReturnNode:continue:"],
+referencedClasses: []
+}),
+smalltalk.ReturnNode);
+
+smalltalk.addMethod(
+"_interpreter_continue_",
+smalltalk.method({
+selector: "interpreter:continue:",
+category: '*Compiler-Interpreter',
+fn: function (anInterpreter,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(anInterpreter)._interpretSendNode_continue_(self,aBlock);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"interpreter:continue:",{anInterpreter:anInterpreter,aBlock:aBlock}, smalltalk.SendNode)})},
+args: ["anInterpreter", "aBlock"],
+source: "interpreter: anInterpreter continue: aBlock\x0a\x09^ anInterpreter interpretSendNode: self continue: aBlock",
+messageSends: ["interpretSendNode:continue:"],
+referencedClasses: []
+}),
+smalltalk.SendNode);
+
+smalltalk.addMethod(
+"_interpreter_continue_",
+smalltalk.method({
+selector: "interpreter:continue:",
+category: '*Compiler-Interpreter',
+fn: function (anInterpreter,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(anInterpreter)._interpretSequenceNode_continue_(self,aBlock);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"interpreter:continue:",{anInterpreter:anInterpreter,aBlock:aBlock}, smalltalk.SequenceNode)})},
+args: ["anInterpreter", "aBlock"],
+source: "interpreter: anInterpreter continue: aBlock\x0a\x09^ anInterpreter interpretSequenceNode: self continue: aBlock",
+messageSends: ["interpretSequenceNode:continue:"],
+referencedClasses: []
+}),
+smalltalk.SequenceNode);
+
+smalltalk.addMethod(
+"_interpreter_continue_",
+smalltalk.method({
+selector: "interpreter:continue:",
+category: '*Compiler-Interpreter',
+fn: function (anInterpreter,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(anInterpreter)._interpretBlockSequenceNode_continue_(self,aBlock);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"interpreter:continue:",{anInterpreter:anInterpreter,aBlock:aBlock}, smalltalk.BlockSequenceNode)})},
+args: ["anInterpreter", "aBlock"],
+source: "interpreter: anInterpreter continue: aBlock\x0a\x09^ anInterpreter interpretBlockSequenceNode: self continue: aBlock",
+messageSends: ["interpretBlockSequenceNode:continue:"],
+referencedClasses: []
+}),
+smalltalk.BlockSequenceNode);
+
+smalltalk.addMethod(
+"_interpreter_continue_",
+smalltalk.method({
+selector: "interpreter:continue:",
+category: '*Compiler-Interpreter',
+fn: function (anInterpreter,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(anInterpreter)._interpretValueNode_continue_(self,aBlock);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"interpreter:continue:",{anInterpreter:anInterpreter,aBlock:aBlock}, smalltalk.ValueNode)})},
+args: ["anInterpreter", "aBlock"],
+source: "interpreter: anInterpreter continue: aBlock\x0a\x09^ anInterpreter interpretValueNode: self continue: aBlock",
+messageSends: ["interpretValueNode:continue:"],
+referencedClasses: []
+}),
+smalltalk.ValueNode);
+
+smalltalk.addMethod(
+"_interpreter_continue_",
+smalltalk.method({
+selector: "interpreter:continue:",
+category: '*Compiler-Interpreter',
+fn: function (anInterpreter,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(anInterpreter)._interpretVariableNode_continue_(self,aBlock);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"interpreter:continue:",{anInterpreter:anInterpreter,aBlock:aBlock}, smalltalk.VariableNode)})},
+args: ["anInterpreter", "aBlock"],
+source: "interpreter: anInterpreter continue: aBlock\x0a\x09^ anInterpreter interpretVariableNode: self continue: aBlock",
+messageSends: ["interpretVariableNode:continue:"],
+referencedClasses: []
+}),
+smalltalk.VariableNode);
+
+smalltalk.addMethod(
+"_interpreter_continue_",
+smalltalk.method({
+selector: "interpreter:continue:",
+category: '*Compiler-Interpreter',
+fn: function (anInterpreter,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(anInterpreter)._interpretClassReferenceNode_continue_(self,aBlock);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"interpreter:continue:",{anInterpreter:anInterpreter,aBlock:aBlock}, smalltalk.ClassReferenceNode)})},
+args: ["anInterpreter", "aBlock"],
+source: "interpreter: anInterpreter continue: aBlock\x0a\x09^ anInterpreter interpretClassReferenceNode: self continue: aBlock",
+messageSends: ["interpretClassReferenceNode:continue:"],
+referencedClasses: []
+}),
+smalltalk.ClassReferenceNode);
+

+ 1 - 1
js/Compiler-Tests.deploy.js

@@ -43,7 +43,7 @@ return smalltalk.withContext(function($ctx2) {
return _st(ctx)._localAt_put_(key
 $2=_st(self)._interpreter();
 _st($2)._context_(ctx);
 _st($2)._interpret_(_st(_st(_st(self)._parse_forClass_(aString,_st(anObject)._class()))._nodes())._first());
-$3=_st($2)._currentValue();
+$3=_st($2)._result();
 $1=$3;
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"interpret:receiver:withArguments:",{aString:aString,anObject:anObject,aDictionary:aDictionary,ctx:ctx}, smalltalk.ASTInterpreterTest)})}

+ 3 - 3
js/Compiler-Tests.js

@@ -54,13 +54,13 @@ return smalltalk.withContext(function($ctx2) {
return _st(ctx)._localAt_put_(key
 $2=_st(self)._interpreter();
 _st($2)._context_(ctx);
 _st($2)._interpret_(_st(_st(_st(self)._parse_forClass_(aString,_st(anObject)._class()))._nodes())._first());
-$3=_st($2)._currentValue();
+$3=_st($2)._result();
 $1=$3;
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"interpret:receiver:withArguments:",{aString:aString,anObject:anObject,aDictionary:aDictionary,ctx:ctx}, smalltalk.ASTInterpreterTest)})},
 args: ["aString", "anObject", "aDictionary"],
-source: "interpret: aString receiver: anObject withArguments: aDictionary\x0a\x09\x22The food is a methodNode. Interpret the sequenceNode only\x22\x0a    \x0a    | ctx |\x0a    \x0a    ctx := AIContext new.\x0a    ctx receiver: anObject.\x0a    aDictionary keysAndValuesDo: [ :key :value |\x0a    \x09ctx localAt: key put: value ].\x0a    \x0a    ^ self interpreter\x0a    \x09context: ctx;\x0a    \x09interpret: (self parse: aString forClass: anObject class) \x0a        \x09nodes first;\x0a        currentValue",
-messageSends: ["new", "receiver:", "keysAndValuesDo:", "localAt:put:", "context:", "interpreter", "interpret:", "first", "nodes", "parse:forClass:", "class", "currentValue"],
+source: "interpret: aString receiver: anObject withArguments: aDictionary\x0a\x09\x22The food is a methodNode. Interpret the sequenceNode only\x22\x0a    \x0a    | ctx |\x0a    \x0a    ctx := AIContext new.\x0a    ctx receiver: anObject.\x0a    aDictionary keysAndValuesDo: [ :key :value |\x0a    \x09ctx localAt: key put: value ].\x0a    \x0a    ^ self interpreter\x0a    \x09context: ctx;\x0a    \x09interpret: (self parse: aString forClass: anObject class) \x0a        \x09nodes first;\x0a        result",
+messageSends: ["new", "receiver:", "keysAndValuesDo:", "localAt:put:", "context:", "interpreter", "interpret:", "first", "nodes", "parse:forClass:", "class", "result"],
 referencedClasses: ["AIContext"]
 }),
 smalltalk.ASTInterpreterTest);

+ 214 - 93
st/Compiler-Interpreter.st

@@ -53,9 +53,12 @@ initializeFromMethodContext: aMethodContext
     	self locals at: key put: value ]
 ! !
 
-NodeVisitor subclass: #ASTInterpreter
-	instanceVariableNames: 'currentNode context shouldReturn currentValue'
+Object subclass: #ASTInterpreter
+	instanceVariableNames: 'currentNode context shouldReturn result'
 	package: 'Compiler-Interpreter'!
+!ASTInterpreter commentStamp!
+ASTIntepreter is like a `NodeVisitor`, interpreting nodes one after each other.
+It is built using Continuation Passing Style for stepping purposes.!
 
 !ASTInterpreter methodsFor: 'accessing'!
 
@@ -67,8 +70,8 @@ context: anAIContext
 	context := anAIContext
 !
 
-currentValue
-	^ currentValue
+result
+	^ result
 ! !
 
 !ASTInterpreter methodsFor: 'initialization'!
@@ -80,92 +83,43 @@ initialize
 
 !ASTInterpreter methodsFor: 'interpreting'!
 
-assign: aNode to: anObject
-	^ aNode binding isInstanceVar 
-    	ifTrue: [ self context receiver instVarAt: aNode value put: anObject ]
-      	ifFalse: [ self context localAt: aNode value put: anObject ]
-!
-
-continue: anObject
-	currentValue := anObject
-!
-
-eval: aString
-	"Evaluate aString as JS source inside an JS function. 
-    aString is not sandboxed."
-    
-    | source function |
-    
-    source := String streamContents: [ :str |
-    	str nextPutAll: '(function('.
-        self context locals keys 
-        	do: [ :each | str nextPutAll: each ]
-          	separatedBy: [ str nextPutAll: ',' ].
-        str 
-        	nextPutAll: '){ return (function() {';
-        	nextPutAll: aString;
-            nextPutAll: '})() })' ].
-            
-	function := Compiler new eval: source.
-    
-	^ function valueWithPossibleArguments: self context locals values
-!
-
 interpret: aNode
 	shouldReturn := false.
     self interpret: aNode continue: [ :value |
-    	currentValue := value ]
+    	result := value ]
 !
 
 interpret: aNode continue: aBlock
 	shouldReturn ifTrue: [ ^ self ].
 
 	aNode isNode 
-    	ifTrue: [ self visit: aNode ]
-        ifFalse: [ currentValue := aNode ].
-	aBlock value: self currentValue
+    	ifTrue: [ 	
+        	currentNode := aNode.
+            self interpretNode: aNode continue: [ :value |
+  				self continue: aBlock value: value] ]
+        ifFalse: [ self continue: aBlock value: aNode ]
 !
 
-interpretAll: aCollection continue: aBlock
-	self 
-    	interpretAll: aCollection 
-        continue: aBlock 
-        result: OrderedCollection new
-!
-
-interpretAll: nodes continue: aBlock result: aCollection
-	nodes isEmpty 
-    	ifTrue: [ aBlock value: aCollection ]
-    	ifFalse: [
-    		self interpret: nodes first continue: [:value |
-    			self 
-                	interpretAll: nodes allButFirst 
-                    continue: aBlock
-  					result: aCollection, { value } ] ]
-!
-
-messageFromSendNode: aSendNode do: aBlock
-	self interpretAll: aSendNode arguments continue: [ :args |
-    	aBlock value: (Message new
-    		selector: aSendNode selector;
-        	arguments: args;
-        	yourself) ]
-! !
-
-!ASTInterpreter methodsFor: 'visiting'!
-
-visitAssignmentNode: aNode
+interpretAssignmentNode: aNode continue: aBlock
 	self interpret: aNode right continue: [ :value |
-    	self continue: (self assign: aNode left to: value) ]
+    	self 
+        	continue: aBlock
+            value: (self assign: aNode left to: value) ]
 !
 
-visitBlockNode: aNode
+interpretBlockNode: aNode continue: aBlock
 	"TODO: Context should be set"
     
-    self continue: [ self interpret: aNode nodes first; currentValue ]
+    self 
+    	continue: aBlock 
+        value: [ self interpret: aNode nodes first; result ]
+!
+
+interpretBlockSequenceNode: aNode continue: aBlock
+	self interpretSequenceNode: aNode continue: aBlock
 !
 
-visitCascadeNode: aNode
+interpretCascadeNode: aNode continue: aBlock
 	"TODO: Handle super sends"
 	
     self interpret: aNode receiver continue: [ :receiver |
@@ -177,58 +131,135 @@ visitCascadeNode: aNode
     		continue: [
               	self 
                 	interpret: aNode nodes last
-                	continue: [ :val | self continue: val ] ] ]
+                	continue: [ :val | self continue: aBlock value: val ] ] ]
 !
 
-visitClassReferenceNode: aNode
-	self continue: (Smalltalk current at: aNode value)
+interpretClassReferenceNode: aNode continue: aBlock
+	self continue: aBlock value: (Smalltalk current at: aNode value)
 !
 
-visitDynamicArrayNode: aNode
+interpretDynamicArrayNode: aNode continue: aBlock
 	self interpretAll: aNode nodes continue: [ :array |
-    	self continue: array ]
+    	self 
+        	continue: aBlock
+			value: array ]
 !
 
-visitDynamicDictionaryNode: aNode
+interpretDynamicDictionaryNode: aNode continue: aBlock
     self interpretAll: aNode nodes continue: [ :array | | hashedCollection |
     	hashedCollection := HashedCollection new.
         array do: [ :each | hashedCollection add: each ].
-        self continue: hashedCollection ]
+        self 	
+        	continue: aBlock
+            value: hashedCollection ]
 !
 
-visitJSStatementNode: aNode
+interpretJSStatementNode: aNode continue: aBlock
 	shouldReturn := true.
-	self continue: (self eval: aNode source)
+	self continue: aBlock value: (self eval: aNode source)
+!
+
+interpretMethodNode: aNode continue: aBlock
+	self interpretAll: aNode nodes continue: [ :array |
+    	self continue: aBlock value: array first ]
 !
 
-visitReturnNode: aNode
+interpretNode: aNode continue: aBlock
+    aNode interpreter: self continue: aBlock
+!
+
+interpretReturnNode: aNode continue: aBlock
     self interpret: aNode nodes first continue: [ :value |
     	shouldReturn := true.
-		self continue: value ]
+		self continue: aBlock value: value ]
 !
 
-visitSendNode: aNode
+interpretSendNode: aNode continue: aBlock
 	"TODO: Handle super sends"
     
     self interpret: aNode receiver continue: [ :receiver |
     	self messageFromSendNode: aNode do: [ :message |
         	self context pc: self context pc + 1.
-        	self continue: (message sendTo: receiver) ] ]
+        	self 
+            	continue: aBlock 
+                value: (message sendTo: receiver) ] ]
 !
 
-visitSequenceNode: aNode
+interpretSequenceNode: aNode continue: aBlock
 	self interpretAll: aNode nodes continue: [ :array |
-    	self continue: array last ]
+    	self continue: aBlock value: array last ]
+!
+
+interpretValueNode: aNode continue: aBlock
+	self continue: aBlock value: aNode value
+!
+
+interpretVariableNode: aNode continue: aBlock
+    self 
+    	continue: aBlock
+        value: (aNode binding isInstanceVar
+			ifTrue: [ self context receiver instVarAt: aNode value ]
+			ifFalse: [ self context localAt: aNode value ])
+! !
+
+!ASTInterpreter methodsFor: 'private'!
+
+assign: aNode to: anObject
+	^ aNode binding isInstanceVar 
+    	ifTrue: [ self context receiver instVarAt: aNode value put: anObject ]
+      	ifFalse: [ self context localAt: aNode value put: anObject ]
+!
+
+continue: aBlock value: anObject
+	result := anObject.
+    aBlock value: anObject
+!
+
+eval: aString
+	"Evaluate aString as JS source inside an JS function. 
+    aString is not sandboxed."
+    
+    | source function |
+    
+    source := String streamContents: [ :str |
+    	str nextPutAll: '(function('.
+        self context locals keys 
+        	do: [ :each | str nextPutAll: each ]
+          	separatedBy: [ str nextPutAll: ',' ].
+        str 
+        	nextPutAll: '){ return (function() {';
+        	nextPutAll: aString;
+            nextPutAll: '})() })' ].
+            
+	function := Compiler new eval: source.
+    
+	^ function valueWithPossibleArguments: self context locals values
+!
+
+interpretAll: aCollection continue: aBlock
+	self 
+    	interpretAll: aCollection 
+        continue: aBlock 
+        result: OrderedCollection new
 !
 
-visitValueNode: aNode
-	self continue: aNode value
+interpretAll: nodes continue: aBlock result: aCollection
+	nodes isEmpty 
+    	ifTrue: [ aBlock value: aCollection ]
+    	ifFalse: [
+    		self interpret: nodes first continue: [:value |
+    			self 
+                	interpretAll: nodes allButFirst 
+                    continue: aBlock
+  					result: aCollection, { value } ] ]
 !
 
-visitVariableNode: aNode
-    self continue: (aNode binding isInstanceVar
-		ifTrue: [ self context receiver instVarAt: aNode value ]
-		ifFalse: [ self context localAt: aNode value ])
+messageFromSendNode: aSendNode do: aBlock
+	self interpretAll: aSendNode arguments continue: [ :args |
+    	aBlock value: (Message new
+    		selector: aSendNode selector;
+        	arguments: args;
+        	yourself) ]
 ! !
 
 ASTInterpreter subclass: #ASTDebugger
@@ -254,3 +285,93 @@ stepOver
 	continuation value
 ! !
 
+!Node methodsFor: '*Compiler-Interpreter'!
+
+interpreter: anInterpreter continue: aBlock
+	^ anInterpreter interpretNode: self continue: aBlock
+! !
+
+!AssignmentNode methodsFor: '*Compiler-Interpreter'!
+
+interpreter: anInterpreter continue: aBlock
+	^ anInterpreter interpretAssignmentNode: self continue: aBlock
+! !
+
+!BlockNode methodsFor: '*Compiler-Interpreter'!
+
+interpreter: anInterpreter continue: aBlock
+	^ anInterpreter interpretBlockNode: self continue: aBlock
+! !
+
+!CascadeNode methodsFor: '*Compiler-Interpreter'!
+
+interpreter: anInterpreter continue: aBlock
+	^ anInterpreter interpretCascadeNode: self continue: aBlock
+! !
+
+!DynamicArrayNode methodsFor: '*Compiler-Interpreter'!
+
+interpreter: anInterpreter continue: aBlock
+	^ anInterpreter interpretDynamicArrayNode: self continue: aBlock
+! !
+
+!DynamicDictionaryNode methodsFor: '*Compiler-Interpreter'!
+
+interpreter: anInterpreter continue: aBlock
+	^ anInterpreter interpretDynamicDictionaryNode: self continue: aBlock
+! !
+
+!JSStatementNode methodsFor: '*Compiler-Interpreter'!
+
+interpreter: anInterpreter continue: aBlock
+	^ anInterpreter interpretJSStatementNode: self continue: aBlock
+! !
+
+!MethodNode methodsFor: '*Compiler-Interpreter'!
+
+interpreter: anInterpreter continue: aBlock
+	^ anInterpreter interpretMethodNode: self continue: aBlock
+! !
+
+!ReturnNode methodsFor: '*Compiler-Interpreter'!
+
+interpreter: anInterpreter continue: aBlock
+	^ anInterpreter interpretReturnNode: self continue: aBlock
+! !
+
+!SendNode methodsFor: '*Compiler-Interpreter'!
+
+interpreter: anInterpreter continue: aBlock
+	^ anInterpreter interpretSendNode: self continue: aBlock
+! !
+
+!SequenceNode methodsFor: '*Compiler-Interpreter'!
+
+interpreter: anInterpreter continue: aBlock
+	^ anInterpreter interpretSequenceNode: self continue: aBlock
+! !
+
+!BlockSequenceNode methodsFor: '*Compiler-Interpreter'!
+
+interpreter: anInterpreter continue: aBlock
+	^ anInterpreter interpretBlockSequenceNode: self continue: aBlock
+! !
+
+!ValueNode methodsFor: '*Compiler-Interpreter'!
+
+interpreter: anInterpreter continue: aBlock
+	^ anInterpreter interpretValueNode: self continue: aBlock
+! !
+
+!VariableNode methodsFor: '*Compiler-Interpreter'!
+
+interpreter: anInterpreter continue: aBlock
+	^ anInterpreter interpretVariableNode: self continue: aBlock
+! !
+
+!ClassReferenceNode methodsFor: '*Compiler-Interpreter'!
+
+interpreter: anInterpreter continue: aBlock
+	^ anInterpreter interpretClassReferenceNode: self continue: aBlock
+! !
+

+ 1 - 1
st/Compiler-Tests.st

@@ -30,7 +30,7 @@ interpret: aString receiver: anObject withArguments: aDictionary
     	context: ctx;
     	interpret: (self parse: aString forClass: anObject class) 
         	nodes first;
-        currentValue
+        result
 !
 
 interpret: aString withArguments: aDictionary