Browse Source

pass receiver in cascaded messages

making ready for branching sends
Herbert Vojčík 8 years ago
parent
commit
a878a63eee
4 changed files with 38 additions and 52 deletions
  1. 21 30
      src/Compiler-IR.js
  2. 10 10
      src/Compiler-IR.st
  3. 5 9
      src/Compiler-Interpreter.js
  4. 2 3
      src/Compiler-Interpreter.st

+ 21 - 30
src/Compiler-IR.js

@@ -555,51 +555,42 @@ selector: "visitCascadeNode:",
 protocol: 'visiting',
 fn: function (aNode){
 var self=this;
-var alias,receiver;
 function $VariableNode(){return $globals.VariableNode||(typeof VariableNode=="undefined"?nil:VariableNode)}
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
-var $2,$1,$3,$5,$4;
-$2=$recv(aNode)._receiver();
+var $1,$2,$4,$3;
+$1=$recv(aNode)._nodes();
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-$ctx1.sendIdx["receiver"]=1;
+$ctx1.sendIdx["nodes"]=1;
 //>>excludeEnd("ctx");
-$1=$recv($2)._isImmutable();
-if($core.assert($1)){
-receiver=$recv(aNode)._receiver();
+$recv($1)._inject_into_($recv(aNode)._receiver(),(function(previous,each){
+var receiver;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-$ctx1.sendIdx["receiver"]=2;
+return $core.withContext(function($ctx2) {
 //>>excludeEnd("ctx");
-receiver;
+$2=$recv(previous)._isImmutable();
+if($core.assert($2)){
+receiver=previous;
 } else {
-alias=self._alias_($recv(aNode)._receiver());
+var alias;
+alias=self._alias_(previous);
 alias;
 receiver=$recv($recv($VariableNode())._new())._binding_($recv(alias)._variable());
-receiver;
 };
-$3=$recv(aNode)._nodes();
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-$ctx1.sendIdx["nodes"]=1;
-//>>excludeEnd("ctx");
-$recv($3)._do_((function(each){
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx2) {
-//>>excludeEnd("ctx");
-return $recv(each)._receiver_(receiver);
+receiver;
+$recv(each)._receiver_(receiver);
+return receiver;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,3)});
+}, function($ctx2) {$ctx2.fillBlock({previous:previous,each:each,receiver:receiver},$ctx1,1)});
 //>>excludeEnd("ctx");
 }));
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-$ctx1.sendIdx["do:"]=1;
-//>>excludeEnd("ctx");
-$5=$recv(aNode)._nodes();
+$4=$recv(aNode)._nodes();
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 $ctx1.sendIdx["nodes"]=2;
 //>>excludeEnd("ctx");
-$4=$recv($5)._allButLast();
-$recv($4)._do_((function(each){
+$3=$recv($4)._allButLast();
+$recv($3)._do_((function(each){
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx2) {
 //>>excludeEnd("ctx");
@@ -610,15 +601,15 @@ return $recv(self._sequence())._add_(self._visit_(each));
 }));
 return self._visitOrAlias_($recv($recv(aNode)._nodes())._last());
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"visitCascadeNode:",{aNode:aNode,alias:alias,receiver:receiver},$globals.IRASTTranslator)});
+}, function($ctx1) {$ctx1.fill(self,"visitCascadeNode:",{aNode:aNode},$globals.IRASTTranslator)});
 //>>excludeEnd("ctx");
 },
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["aNode"],
-source: "visitCascadeNode: aNode\x0a\x09| alias receiver |\x0a\x0a\x09aNode receiver isImmutable \x0a\x09\x09ifTrue: [ receiver := aNode receiver ]\x0a\x09\x09ifFalse: [\x0a\x09\x09\x09alias := self alias: aNode receiver.\x0a\x09\x09\x09receiver := VariableNode new binding: alias variable ].\x0a\x09\x0a\x09aNode nodes do: [ :each |\x0a\x09\x09\x09each receiver: receiver ].\x0a\x0a\x09aNode nodes allButLast do: [ :each |\x0a\x09\x09self sequence add: (self visit: each) ].\x0a\x0a\x09^ self visitOrAlias: aNode nodes last",
+source: "visitCascadeNode: aNode\x0a\x09aNode nodes inject: aNode receiver into: [ :previous :each |\x0a\x09\x09| receiver |\x0a\x09\x09receiver := previous isImmutable \x0a\x09\x09\x09ifTrue: [ previous ]\x0a\x09\x09\x09ifFalse: [\x0a\x09\x09\x09\x09| alias |\x0a\x09\x09\x09\x09alias := self alias: previous.\x0a\x09\x09\x09\x09VariableNode new binding: alias variable ].\x0a\x09\x09each receiver: receiver.\x0a\x09\x09receiver ].\x0a\x0a\x09aNode nodes allButLast do: [ :each |\x0a\x09\x09self sequence add: (self visit: each) ].\x0a\x0a\x09^ self visitOrAlias: aNode nodes last",
 referencedClasses: ["VariableNode"],
 //>>excludeEnd("ide");
-messageSends: ["ifTrue:ifFalse:", "isImmutable", "receiver", "alias:", "binding:", "new", "variable", "do:", "nodes", "receiver:", "allButLast", "add:", "sequence", "visit:", "visitOrAlias:", "last"]
+messageSends: ["inject:into:", "nodes", "receiver", "ifTrue:ifFalse:", "isImmutable", "alias:", "binding:", "new", "variable", "receiver:", "do:", "allButLast", "add:", "sequence", "visit:", "visitOrAlias:", "last"]
 }),
 $globals.IRASTTranslator);
 

+ 10 - 10
src/Compiler-IR.st

@@ -138,16 +138,16 @@ visitBlockSequenceNode: aNode
 !
 
 visitCascadeNode: aNode
-	| alias receiver |
-
-	aNode receiver isImmutable 
-		ifTrue: [ receiver := aNode receiver ]
-		ifFalse: [
-			alias := self alias: aNode receiver.
-			receiver := VariableNode new binding: alias variable ].
-	
-	aNode nodes do: [ :each |
-			each receiver: receiver ].
+	aNode nodes inject: aNode receiver into: [ :previous :each |
+		| receiver |
+		receiver := previous isImmutable 
+			ifTrue: [ previous ]
+			ifFalse: [
+				| alias |
+				alias := self alias: previous.
+				VariableNode new binding: alias variable ].
+		each receiver: receiver.
+		receiver ].
 
 	aNode nodes allButLast do: [ :each |
 		self sequence add: (self visit: each) ].

+ 5 - 9
src/Compiler-Interpreter.js

@@ -3200,7 +3200,7 @@ $ctx2.sendIdx["pop"]=1;
 }, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)});
 //>>excludeEnd("ctx");
 }));
-receiver=self._pop();
+receiver=self._peek();
 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(){
@@ -3212,12 +3212,8 @@ return $recv($recv(aNode)._isLastChild())._not();
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)});
 //>>excludeEnd("ctx");
 }));
-if($core.assert($1)){
-self._push_(receiver);
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-$ctx1.sendIdx["push:"]=1;
-//>>excludeEnd("ctx");
-} else {
+if(!$core.assert($1)){
+self._pop();
 self._push_(result);
 };
 return self;
@@ -3227,10 +3223,10 @@ return self;
 },
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["aNode"],
-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\x09ifTrue: [ self push: receiver ]\x0a\x09\x09ifFalse: [ self push: result ]",
+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 ]",
 referencedClasses: [],
 //>>excludeEnd("ide");
-messageSends: ["collect:", "arguments", "pop", "messageFromSendNode:arguments:", "reversed", "sendMessage:to:superSend:", "superSend", "ifTrue:ifFalse:", "and:", "isCascadeSendNode", "not", "isLastChild", "push:"]
+messageSends: ["collect:", "arguments", "pop", "peek", "messageFromSendNode:arguments:", "reversed", "sendMessage:to:superSend:", "superSend", "ifFalse:", "and:", "isCascadeSendNode", "not", "isLastChild", "push:"]
 }),
 $globals.ASTInterpreter);
 

+ 2 - 3
src/Compiler-Interpreter.st

@@ -824,7 +824,7 @@ visitSendNode: aNode
 	| receiver args message result |
 	
 	args := aNode arguments collect: [ :each | self pop ].
-	receiver := self pop.
+	receiver := self peek.
 	
 	message := self
 		messageFromSendNode: aNode
@@ -834,8 +834,7 @@ visitSendNode: aNode
 	
 	"For cascade sends, push the reciever if the send is not the last one"
 	(aNode isCascadeSendNode and: [ aNode isLastChild not ])
-		ifTrue: [ self push: receiver ]
-		ifFalse: [ self push: result ]
+		ifFalse: [ self pop; push: result ]
 !
 
 visitSequenceNode: aNode