|
@@ -2139,6 +2139,57 @@ messageSends: ["ifEmpty:ifNotEmpty:", "nodes", "visit:", "first"]
|
|
|
}),
|
|
|
$globals.ASTEnterNode);
|
|
|
|
|
|
+$core.addMethod(
|
|
|
+$core.method({
|
|
|
+selector: "visitRefNode:",
|
|
|
+protocol: 'visiting',
|
|
|
+fn: function (aNode){
|
|
|
+var self=this;
|
|
|
+var ref;
|
|
|
+
|
|
|
+return $core.withContext(function($ctx1) {
|
|
|
+
|
|
|
+var $1;
|
|
|
+var $early={};
|
|
|
+try {
|
|
|
+ref=$recv(aNode)._node();
|
|
|
+$recv($recv(self._interpreter())._refResults())._at_ifPresent_ifAbsent_($recv(ref)._nodeId(),(function(){
|
|
|
+throw $early=[aNode];
|
|
|
+
|
|
|
+}),(function(){
|
|
|
+
|
|
|
+return $core.withContext(function($ctx2) {
|
|
|
+
|
|
|
+$recv(ref)._parent_(aNode);
|
|
|
+$1=(
|
|
|
+
|
|
|
+$ctx2.supercall = true,
|
|
|
+
|
|
|
+($globals.ASTEnterNode.superclass||$boot.dnu).fn.prototype._visitRefNode_.apply($recv(self), [aNode]));
|
|
|
+
|
|
|
+$ctx2.supercall = false;
|
|
|
+
|
|
|
+throw $early=[$1];
|
|
|
+
|
|
|
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)});
|
|
|
+
|
|
|
+}));
|
|
|
+return self;
|
|
|
+}
|
|
|
+catch(e) {if(e===$early)return e[0]; throw e}
|
|
|
+
|
|
|
+}, function($ctx1) {$ctx1.fill(self,"visitRefNode:",{aNode:aNode,ref:ref},$globals.ASTEnterNode)});
|
|
|
+
|
|
|
+},
|
|
|
+
|
|
|
+args: ["aNode"],
|
|
|
+source: "visitRefNode: aNode\x0a\x09| ref |\x0a\x09ref := aNode node.\x0a\x09self interpreter refResults at: ref nodeId\x0a\x09\x09ifPresent: [ ^ aNode ]\x0a\x09\x09ifAbsent: [ ref parent: aNode. ^ super visitRefNode: aNode ]",
|
|
|
+referencedClasses: [],
|
|
|
+
|
|
|
+messageSends: ["node", "at:ifPresent:ifAbsent:", "refResults", "interpreter", "nodeId", "parent:", "visitRefNode:"]
|
|
|
+}),
|
|
|
+$globals.ASTEnterNode);
|
|
|
+
|
|
|
|
|
|
$core.addMethod(
|
|
|
$core.method({
|
|
@@ -2167,7 +2218,7 @@ messageSends: ["interpreter:", "new", "yourself"]
|
|
|
$globals.ASTEnterNode.klass);
|
|
|
|
|
|
|
|
|
-$core.addClass('ASTInterpreter', $globals.NodeVisitor, ['node', 'context', 'stack', 'returnValue', 'returned', 'forceAtEnd'], 'Compiler-Interpreter');
|
|
|
+$core.addClass('ASTInterpreter', $globals.NodeVisitor, ['node', 'context', 'stack', 'returnValue', 'returned', 'forceAtEnd', 'refResults'], 'Compiler-Interpreter');
|
|
|
|
|
|
$globals.ASTInterpreter.comment="I visit an AST, interpreting (evaluating) nodes one after the other, using a small stack machine.\x0a\x0a## API\x0a\x0aWhile my instances should be used from within an `ASTDebugger`, which provides a more high level interface,\x0ayou can use methods from the `interpreting` protocol:\x0a\x0a- `#step` evaluates the current `node` only\x0a- `#stepOver` evaluates the AST from the current `node` up to the next stepping node (most likely the next send node)\x0a- `#proceed` evaluates eagerly the AST\x0a- `#restart` select the first node of the AST\x0a- `#skip` skips the current node, moving to the next one if any";
|
|
|
|
|
@@ -2435,6 +2486,7 @@ $ctx1.supercall = true,
|
|
|
|
|
|
$ctx1.supercall = false;
|
|
|
|
|
|
+self["@refResults"]=$globals.HashedCollection._newFromPairs_([]);
|
|
|
self["@forceAtEnd"]=false;
|
|
|
return self;
|
|
|
|
|
@@ -2443,7 +2495,7 @@ return self;
|
|
|
},
|
|
|
|
|
|
args: [],
|
|
|
-source: "initialize\x0a\x09super initialize.\x0a\x0a\x09forceAtEnd := false",
|
|
|
+source: "initialize\x0a\x09super initialize.\x0a\x0a\x09refResults := #{}.\x0a\x09forceAtEnd := false",
|
|
|
referencedClasses: [],
|
|
|
|
|
|
messageSends: ["initialize"]
|
|
@@ -2736,6 +2788,24 @@ messageSends: ["add:", "stack"]
|
|
|
}),
|
|
|
$globals.ASTInterpreter);
|
|
|
|
|
|
+$core.addMethod(
|
|
|
+$core.method({
|
|
|
+selector: "refResults",
|
|
|
+protocol: 'accessing',
|
|
|
+fn: function (){
|
|
|
+var self=this;
|
|
|
+return self["@refResults"];
|
|
|
+
|
|
|
+},
|
|
|
+
|
|
|
+args: [],
|
|
|
+source: "refResults\x0a\x09^ refResults",
|
|
|
+referencedClasses: [],
|
|
|
+
|
|
|
+messageSends: []
|
|
|
+}),
|
|
|
+$globals.ASTInterpreter);
|
|
|
+
|
|
|
$core.addMethod(
|
|
|
$core.method({
|
|
|
selector: "restart",
|
|
@@ -3297,6 +3367,47 @@ messageSends: []
|
|
|
}),
|
|
|
$globals.ASTInterpreter);
|
|
|
|
|
|
+$core.addMethod(
|
|
|
+$core.method({
|
|
|
+selector: "visitRefNode:",
|
|
|
+protocol: 'visiting',
|
|
|
+fn: function (aNode){
|
|
|
+var self=this;
|
|
|
+var ref,refid;
|
|
|
+
|
|
|
+return $core.withContext(function($ctx1) {
|
|
|
+
|
|
|
+var $1;
|
|
|
+ref=$recv(aNode)._node();
|
|
|
+refid=$recv(ref)._nodeId();
|
|
|
+$1=self._refResults();
|
|
|
+
|
|
|
+$ctx1.sendIdx["refResults"]=1;
|
|
|
+
|
|
|
+$recv($1)._at_ifAbsentPut_(refid,(function(){
|
|
|
+
|
|
|
+return $core.withContext(function($ctx2) {
|
|
|
+
|
|
|
+return self._pop();
|
|
|
+
|
|
|
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)});
|
|
|
+
|
|
|
+}));
|
|
|
+self._push_($recv(self._refResults())._at_(refid));
|
|
|
+return self;
|
|
|
+
|
|
|
+}, function($ctx1) {$ctx1.fill(self,"visitRefNode:",{aNode:aNode,ref:ref,refid:refid},$globals.ASTInterpreter)});
|
|
|
+
|
|
|
+},
|
|
|
+
|
|
|
+args: ["aNode"],
|
|
|
+source: "visitRefNode: aNode\x0a\x09| ref refid |\x0a\x09ref := aNode node.\x0a\x09refid := ref nodeId.\x0a\x09self refResults at: refid ifAbsentPut: [ self pop ].\x0a\x09self push: (self refResults at: refid)",
|
|
|
+referencedClasses: [],
|
|
|
+
|
|
|
+messageSends: ["node", "nodeId", "at:ifAbsentPut:", "refResults", "pop", "push:", "at:"]
|
|
|
+}),
|
|
|
+$globals.ASTInterpreter);
|
|
|
+
|
|
|
$core.addMethod(
|
|
|
$core.method({
|
|
|
selector: "visitReturnNode:",
|
|
@@ -3345,7 +3456,7 @@ $ctx2.sendIdx["pop"]=1;
|
|
|
}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)});
|
|
|
|
|
|
}));
|
|
|
-receiver=self._peek();
|
|
|
+receiver=self._pop();
|
|
|
message=self._messageFromSendNode_arguments_(aNode,$recv(args)._reversed());
|
|
|
result=self._sendMessage_to_superSend_(message,receiver,$recv(aNode)._superSend());
|
|
|
$1=$recv($recv(aNode)._isCascadeSendNode())._and_((function(){
|
|
@@ -3358,7 +3469,6 @@ return $recv($recv(aNode)._isLastChild())._not();
|
|
|
|
|
|
}));
|
|
|
if(!$core.assert($1)){
|
|
|
-self._pop();
|
|
|
self._push_(result);
|
|
|
};
|
|
|
return self;
|
|
@@ -3368,10 +3478,10 @@ return self;
|
|
|
},
|
|
|
|
|
|
args: ["aNode"],
|
|
|
-source: "visitSendNode: aNode\x0a\x09| receiver args message result |\x0a\x09\x0a\x09args := aNode arguments collect: [ :each | self pop ].\x0a\x09receiver := self peek.\x0a\x09\x0a\x09message := self\x0a\x09\x09messageFromSendNode: aNode\x0a\x09\x09arguments: args reversed.\x0a\x09\x0a\x09result := self sendMessage: message to: receiver superSend: aNode superSend.\x0a\x09\x0a\x09\x22For cascade sends, push the reciever if the send is not the last one\x22\x0a\x09(aNode isCascadeSendNode and: [ aNode isLastChild not ])\x0a\x09\x09ifFalse: [ self pop; push: result ]",
|
|
|
+source: "visitSendNode: aNode\x0a\x09| receiver args message result |\x0a\x09\x0a\x09args := aNode arguments collect: [ :each | self pop ].\x0a\x09receiver := self pop.\x0a\x09\x0a\x09message := self\x0a\x09\x09messageFromSendNode: aNode\x0a\x09\x09arguments: args reversed.\x0a\x09\x0a\x09result := self sendMessage: message to: receiver superSend: aNode superSend.\x0a\x09\x0a\x09\x22For cascade sends, push the reciever if the send is not the last one\x22\x0a\x09(aNode isCascadeSendNode and: [ aNode isLastChild not ])\x0a\x09\x09ifFalse: [ self push: result ]",
|
|
|
referencedClasses: [],
|
|
|
|
|
|
-messageSends: ["collect:", "arguments", "pop", "peek", "messageFromSendNode:arguments:", "reversed", "sendMessage:to:superSend:", "superSend", "ifFalse:", "and:", "isCascadeSendNode", "not", "isLastChild", "push:"]
|
|
|
+messageSends: ["collect:", "arguments", "pop", "messageFromSendNode:arguments:", "reversed", "sendMessage:to:superSend:", "superSend", "ifFalse:", "and:", "isCascadeSendNode", "not", "isLastChild", "push:"]
|
|
|
}),
|
|
|
$globals.ASTInterpreter);
|
|
|
|
|
@@ -3935,6 +4045,24 @@ messageSends: ["at:ifAbsent:", "nodes", "+", "indexOf:"]
|
|
|
}),
|
|
|
$globals.Node);
|
|
|
|
|
|
+$core.addMethod(
|
|
|
+$core.method({
|
|
|
+selector: "nextSiblingNode:",
|
|
|
+protocol: '*Compiler-Interpreter',
|
|
|
+fn: function (aNode){
|
|
|
+var self=this;
|
|
|
+return nil;
|
|
|
+
|
|
|
+},
|
|
|
+
|
|
|
+args: ["aNode"],
|
|
|
+source: "nextSiblingNode: aNode\x0a\x09\x22no siblings in ref node\x22\x0a\x09^ nil",
|
|
|
+referencedClasses: [],
|
|
|
+
|
|
|
+messageSends: []
|
|
|
+}),
|
|
|
+$globals.RefNode);
|
|
|
+
|
|
|
$core.addMethod(
|
|
|
$core.method({
|
|
|
selector: "isSteppingNode",
|