Browse Source

Merge branch 'up' into branching-sends

# Conflicts:
#	src/Compiler-AST.js
#	src/Compiler-AST.st
Herbert Vojčík 8 years ago
parent
commit
146a2baeb2

+ 107 - 0
src/Compiler-AST.js

@@ -1921,6 +1921,90 @@ $globals.MethodNode);
 
 
 
 
 
 
+$core.addClass('RefNode', $globals.Node, ['node'], 'Compiler-AST');
+//>>excludeStart("ide", pragmas.excludeIdeData);
+$globals.RefNode.comment="I reference other `node`, which may be used more times,\x0aeach time getting separate instance of me.\x0a\x0aI have my own `parent`, but delegate visitors to `node`.\x0a\x0aDuring semantic analysis, analyzer does `node shouldBeAliased: true`\x0abecause of the fact it may be used more times.";
+//>>excludeEnd("ide");
+$core.addMethod(
+$core.method({
+selector: "accept:",
+protocol: 'visiting',
+fn: function (aVisitor){
+var self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $recv(aVisitor)._visitRefNode_(self);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"accept:",{aVisitor:aVisitor},$globals.RefNode)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aVisitor"],
+source: "accept: aVisitor\x0a\x09^ aVisitor visitRefNode: self",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["visitRefNode:"]
+}),
+$globals.RefNode);
+
+$core.addMethod(
+$core.method({
+selector: "isImmutable",
+protocol: 'testing',
+fn: function (){
+var self=this;
+return true;
+
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "isImmutable\x0a\x09^ true",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: []
+}),
+$globals.RefNode);
+
+$core.addMethod(
+$core.method({
+selector: "node",
+protocol: 'accessing',
+fn: function (){
+var self=this;
+return self["@node"];
+
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "node\x0a\x09^ node",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: []
+}),
+$globals.RefNode);
+
+$core.addMethod(
+$core.method({
+selector: "node:",
+protocol: 'accessing',
+fn: function (anObject){
+var self=this;
+self["@node"]=anObject;
+return self;
+
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["anObject"],
+source: "node: anObject\x0a\x09node := anObject",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: []
+}),
+$globals.RefNode);
+
+
+
 $core.addClass('QuasiSendNode', $globals.Node, ['receiver'], 'Compiler-AST');
 $core.addClass('QuasiSendNode', $globals.Node, ['receiver'], 'Compiler-AST');
 //>>excludeStart("ide", pragmas.excludeIdeData);
 //>>excludeStart("ide", pragmas.excludeIdeData);
 $globals.QuasiSendNode.comment="I am a node that has a receiver.\x0a\x0aMy subclasses are `SendNode`, `CascadeNode` and `BranchSendNode`.";
 $globals.QuasiSendNode.comment="I am a node that has a receiver.\x0a\x0aMy subclasses are `SendNode`, `CascadeNode` and `BranchSendNode`.";
@@ -3593,6 +3677,29 @@ messageSends: ["visitAll:", "nodes"]
 }),
 }),
 $globals.NodeVisitor);
 $globals.NodeVisitor);
 
 
+$core.addMethod(
+$core.method({
+selector: "visitRefNode:",
+protocol: 'visiting',
+fn: function (aNode){
+var self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return self._visit_($recv(aNode)._node());
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"visitRefNode:",{aNode:aNode},$globals.NodeVisitor)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aNode"],
+source: "visitRefNode: aNode\x0a\x09^ self visit: aNode node",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["visit:", "node"]
+}),
+$globals.NodeVisitor);
+
 $core.addMethod(
 $core.addMethod(
 $core.method({
 $core.method({
 selector: "visitReturnNode:",
 selector: "visitReturnNode:",

+ 38 - 0
src/Compiler-AST.st

@@ -436,6 +436,40 @@ accept: aVisitor
 	^ aVisitor visitMethodNode: self
 	^ aVisitor visitMethodNode: self
 ! !
 ! !
 
 
+Node subclass: #RefNode
+	instanceVariableNames: 'node'
+	package: 'Compiler-AST'!
+!RefNode commentStamp!
+I reference other `node`, which may be used more times,
+each time getting separate instance of me.
+
+I have my own `parent`, but delegate visitors to `node`.
+
+During semantic analysis, analyzer does `node shouldBeAliased: true`
+because of the fact it may be used more times.!
+
+!RefNode methodsFor: 'accessing'!
+
+node
+	^ node
+!
+
+node: anObject
+	node := anObject
+! !
+
+!RefNode methodsFor: 'testing'!
+
+isImmutable
+	^ true
+! !
+
+!RefNode methodsFor: 'visiting'!
+
+accept: aVisitor
+	^ aVisitor visitRefNode: self
+! !
+
 Node subclass: #QuasiSendNode
 Node subclass: #QuasiSendNode
 	instanceVariableNames: 'receiver'
 	instanceVariableNames: 'receiver'
 	package: 'Compiler-AST'!
 	package: 'Compiler-AST'!
@@ -865,6 +899,10 @@ visitNode: aNode
 	^ self visitAll: aNode nodes
 	^ self visitAll: aNode nodes
 !
 !
 
 
+visitRefNode: aNode
+	^ self visit: aNode node
+!
+
 visitReturnNode: aNode
 visitReturnNode: aNode
 	^ self visitNode: aNode
 	^ self visitNode: aNode
 !
 !

+ 31 - 34
src/Compiler-IR.js

@@ -660,48 +660,22 @@ selector: "visitCascadeNode:",
 protocol: 'visiting',
 protocol: 'visiting',
 fn: function (aNode){
 fn: function (aNode){
 var self=this;
 var self=this;
-function $VariableNode(){return $globals.VariableNode||(typeof VariableNode=="undefined"?nil:VariableNode)}
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
 //>>excludeEnd("ctx");
-var $1,$2,$4,$3;
-$1=$recv(aNode)._nodes();
+var $2,$1;
+$2=$recv(aNode)._nodes();
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 $ctx1.sendIdx["nodes"]=1;
 $ctx1.sendIdx["nodes"]=1;
 //>>excludeEnd("ctx");
 //>>excludeEnd("ctx");
-$recv($1)._inject_into_($recv(aNode)._receiver(),(function(previous,each){
-var receiver;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx2) {
-//>>excludeEnd("ctx");
-$2=$recv(previous)._isImmutable();
-if($core.assert($2)){
-receiver=previous;
-} else {
-var alias;
-alias=self._alias_(previous);
-alias;
-receiver=$recv($recv($VariableNode())._new())._binding_($recv(alias)._variable());
-};
-receiver;
-$recv(each)._receiver_(receiver);
-return receiver;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx2) {$ctx2.fillBlock({previous:previous,each:each,receiver:receiver},$ctx1,1)});
-//>>excludeEnd("ctx");
-}));
-$4=$recv(aNode)._nodes();
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-$ctx1.sendIdx["nodes"]=2;
-//>>excludeEnd("ctx");
-$3=$recv($4)._allButLast();
-$recv($3)._do_((function(each){
+$1=$recv($2)._allButLast();
+$recv($1)._do_((function(each){
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx2) {
 return $core.withContext(function($ctx2) {
 //>>excludeEnd("ctx");
 //>>excludeEnd("ctx");
 return $recv(self._sequence())._add_(self._visit_(each));
 return $recv(self._sequence())._add_(self._visit_(each));
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,4)});
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)});
 //>>excludeEnd("ctx");
 //>>excludeEnd("ctx");
 }));
 }));
 return self._visitOrAlias_($recv($recv(aNode)._nodes())._last());
 return self._visitOrAlias_($recv($recv(aNode)._nodes())._last());
@@ -711,10 +685,10 @@ return self._visitOrAlias_($recv($recv(aNode)._nodes())._last());
 },
 },
 //>>excludeStart("ide", pragmas.excludeIdeData);
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["aNode"],
 args: ["aNode"],
-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"],
+source: "visitCascadeNode: aNode\x0a\x09aNode nodes allButLast do: [ :each |\x0a\x09\x09self sequence add: (self visit: each) ].\x0a\x0a\x09^ self visitOrAlias: aNode nodes last",
+referencedClasses: [],
 //>>excludeEnd("ide");
 //>>excludeEnd("ide");
-messageSends: ["inject:into:", "nodes", "receiver", "ifTrue:ifFalse:", "isImmutable", "alias:", "binding:", "new", "variable", "receiver:", "do:", "allButLast", "add:", "sequence", "visit:", "visitOrAlias:", "last"]
+messageSends: ["do:", "allButLast", "nodes", "add:", "sequence", "visit:", "visitOrAlias:", "last"]
 }),
 }),
 $globals.IRASTTranslator);
 $globals.IRASTTranslator);
 
 
@@ -997,6 +971,29 @@ messageSends: ["ifTrue:ifFalse:", "shouldBeAliased", "alias:", "visit:"]
 }),
 }),
 $globals.IRASTTranslator);
 $globals.IRASTTranslator);
 
 
+$core.addMethod(
+$core.method({
+selector: "visitRefNode:",
+protocol: 'visiting',
+fn: function (aNode){
+var self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return self._alias_($recv(aNode)._node());
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"visitRefNode:",{aNode:aNode},$globals.IRASTTranslator)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aNode"],
+source: "visitRefNode: aNode\x0a\x09^ self alias: aNode node",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["alias:", "node"]
+}),
+$globals.IRASTTranslator);
+
 $core.addMethod(
 $core.addMethod(
 $core.method({
 $core.method({
 selector: "visitReturnNode:",
 selector: "visitReturnNode:",

+ 4 - 11
src/Compiler-IR.st

@@ -159,17 +159,6 @@ visitBranchSendNode: aNode
 !
 !
 
 
 visitCascadeNode: aNode
 visitCascadeNode: aNode
-	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 |
 	aNode nodes allButLast do: [ :each |
 		self sequence add: (self visit: each) ].
 		self sequence add: (self visit: each) ].
 
 
@@ -234,6 +223,10 @@ visitOrAlias: aNode
 		ifFalse: [ self visit: aNode ]
 		ifFalse: [ self visit: aNode ]
 !
 !
 
 
+visitRefNode: aNode
+	^ self alias: aNode node
+!
+
 visitReturnNode: aNode
 visitReturnNode: aNode
 	| return |
 	| return |
 	return := aNode nonLocalReturn
 	return := aNode nonLocalReturn

+ 134 - 6
src/Compiler-Interpreter.js

@@ -2139,6 +2139,57 @@ messageSends: ["ifEmpty:ifNotEmpty:", "nodes", "visit:", "first"]
 }),
 }),
 $globals.ASTEnterNode);
 $globals.ASTEnterNode);
 
 
+$core.addMethod(
+$core.method({
+selector: "visitRefNode:",
+protocol: 'visiting',
+fn: function (aNode){
+var self=this;
+var ref;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+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(){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx2) {
+//>>excludeEnd("ctx");
+$recv(ref)._parent_(aNode);
+$1=(
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx2.supercall = true, 
+//>>excludeEnd("ctx");
+($globals.ASTEnterNode.superclass||$boot.dnu).fn.prototype._visitRefNode_.apply($recv(self), [aNode]));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx2.supercall = false;
+//>>excludeEnd("ctx");;
+throw $early=[$1];
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)});
+//>>excludeEnd("ctx");
+}));
+return self;
+}
+catch(e) {if(e===$early)return e[0]; throw e}
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"visitRefNode:",{aNode:aNode,ref:ref},$globals.ASTEnterNode)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+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: [],
+//>>excludeEnd("ide");
+messageSends: ["node", "at:ifPresent:ifAbsent:", "refResults", "interpreter", "nodeId", "parent:", "visitRefNode:"]
+}),
+$globals.ASTEnterNode);
+
 
 
 $core.addMethod(
 $core.addMethod(
 $core.method({
 $core.method({
@@ -2167,7 +2218,7 @@ messageSends: ["interpreter:", "new", "yourself"]
 $globals.ASTEnterNode.klass);
 $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');
 //>>excludeStart("ide", pragmas.excludeIdeData);
 //>>excludeStart("ide", pragmas.excludeIdeData);
 $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";
 $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";
 //>>excludeEnd("ide");
 //>>excludeEnd("ide");
@@ -2435,6 +2486,7 @@ $ctx1.supercall = true,
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 $ctx1.supercall = false;
 $ctx1.supercall = false;
 //>>excludeEnd("ctx");;
 //>>excludeEnd("ctx");;
+self["@refResults"]=$globals.HashedCollection._newFromPairs_([]);
 self["@forceAtEnd"]=false;
 self["@forceAtEnd"]=false;
 return self;
 return self;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
@@ -2443,7 +2495,7 @@ return self;
 },
 },
 //>>excludeStart("ide", pragmas.excludeIdeData);
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: [],
 args: [],
-source: "initialize\x0a\x09super initialize.\x0a\x0a\x09forceAtEnd := false",
+source: "initialize\x0a\x09super initialize.\x0a\x0a\x09refResults := #{}.\x0a\x09forceAtEnd := false",
 referencedClasses: [],
 referencedClasses: [],
 //>>excludeEnd("ide");
 //>>excludeEnd("ide");
 messageSends: ["initialize"]
 messageSends: ["initialize"]
@@ -2736,6 +2788,24 @@ messageSends: ["add:", "stack"]
 }),
 }),
 $globals.ASTInterpreter);
 $globals.ASTInterpreter);
 
 
+$core.addMethod(
+$core.method({
+selector: "refResults",
+protocol: 'accessing',
+fn: function (){
+var self=this;
+return self["@refResults"];
+
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "refResults\x0a\x09^ refResults",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: []
+}),
+$globals.ASTInterpreter);
+
 $core.addMethod(
 $core.addMethod(
 $core.method({
 $core.method({
 selector: "restart",
 selector: "restart",
@@ -3297,6 +3367,47 @@ messageSends: []
 }),
 }),
 $globals.ASTInterpreter);
 $globals.ASTInterpreter);
 
 
+$core.addMethod(
+$core.method({
+selector: "visitRefNode:",
+protocol: 'visiting',
+fn: function (aNode){
+var self=this;
+var ref,refid;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $1;
+ref=$recv(aNode)._node();
+refid=$recv(ref)._nodeId();
+$1=self._refResults();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["refResults"]=1;
+//>>excludeEnd("ctx");
+$recv($1)._at_ifAbsentPut_(refid,(function(){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx2) {
+//>>excludeEnd("ctx");
+return self._pop();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)});
+//>>excludeEnd("ctx");
+}));
+self._push_($recv(self._refResults())._at_(refid));
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"visitRefNode:",{aNode:aNode,ref:ref,refid:refid},$globals.ASTInterpreter)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+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: [],
+//>>excludeEnd("ide");
+messageSends: ["node", "nodeId", "at:ifAbsentPut:", "refResults", "pop", "push:", "at:"]
+}),
+$globals.ASTInterpreter);
+
 $core.addMethod(
 $core.addMethod(
 $core.method({
 $core.method({
 selector: "visitReturnNode:",
 selector: "visitReturnNode:",
@@ -3345,7 +3456,7 @@ $ctx2.sendIdx["pop"]=1;
 }, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)});
 }, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)});
 //>>excludeEnd("ctx");
 //>>excludeEnd("ctx");
 }));
 }));
-receiver=self._peek();
+receiver=self._pop();
 message=self._messageFromSendNode_arguments_(aNode,$recv(args)._reversed());
 message=self._messageFromSendNode_arguments_(aNode,$recv(args)._reversed());
 result=self._sendMessage_to_superSend_(message,receiver,$recv(aNode)._superSend());
 result=self._sendMessage_to_superSend_(message,receiver,$recv(aNode)._superSend());
 $1=$recv($recv(aNode)._isCascadeSendNode())._and_((function(){
 $1=$recv($recv(aNode)._isCascadeSendNode())._and_((function(){
@@ -3358,7 +3469,6 @@ return $recv($recv(aNode)._isLastChild())._not();
 //>>excludeEnd("ctx");
 //>>excludeEnd("ctx");
 }));
 }));
 if(!$core.assert($1)){
 if(!$core.assert($1)){
-self._pop();
 self._push_(result);
 self._push_(result);
 };
 };
 return self;
 return self;
@@ -3368,10 +3478,10 @@ return self;
 },
 },
 //>>excludeStart("ide", pragmas.excludeIdeData);
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["aNode"],
 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: [],
 referencedClasses: [],
 //>>excludeEnd("ide");
 //>>excludeEnd("ide");
-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);
 $globals.ASTInterpreter);
 
 
@@ -3935,6 +4045,24 @@ messageSends: ["at:ifAbsent:", "nodes", "+", "indexOf:"]
 }),
 }),
 $globals.Node);
 $globals.Node);
 
 
+$core.addMethod(
+$core.method({
+selector: "nextSiblingNode:",
+protocol: '*Compiler-Interpreter',
+fn: function (aNode){
+var self=this;
+return nil;
+
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aNode"],
+source: "nextSiblingNode: aNode\x0a\x09\x22no siblings in ref node\x22\x0a\x09^ nil",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: []
+}),
+$globals.RefNode);
+
 $core.addMethod(
 $core.addMethod(
 $core.method({
 $core.method({
 selector: "isSteppingNode",
 selector: "isSteppingNode",

+ 31 - 3
src/Compiler-Interpreter.st

@@ -564,6 +564,14 @@ visitNode: aNode
 	aNode nodes
 	aNode nodes
 		ifEmpty: [ ^ aNode ]
 		ifEmpty: [ ^ aNode ]
 		ifNotEmpty: [ :nodes | ^ self visit: nodes first ]
 		ifNotEmpty: [ :nodes | ^ self visit: nodes first ]
+!
+
+visitRefNode: aNode
+	| ref |
+	ref := aNode node.
+	self interpreter refResults at: ref nodeId
+		ifPresent: [ ^ aNode ]
+		ifAbsent: [ ref parent: aNode. ^ super visitRefNode: aNode ]
 ! !
 ! !
 
 
 !ASTEnterNode class methodsFor: 'instance creation'!
 !ASTEnterNode class methodsFor: 'instance creation'!
@@ -575,7 +583,7 @@ on: anInterpreter
 ! !
 ! !
 
 
 NodeVisitor subclass: #ASTInterpreter
 NodeVisitor subclass: #ASTInterpreter
-	instanceVariableNames: 'node context stack returnValue returned forceAtEnd'
+	instanceVariableNames: 'node context stack returnValue returned forceAtEnd refResults'
 	package: 'Compiler-Interpreter'!
 	package: 'Compiler-Interpreter'!
 !ASTInterpreter commentStamp!
 !ASTInterpreter commentStamp!
 I visit an AST, interpreting (evaluating) nodes one after the other, using a small stack machine.
 I visit an AST, interpreting (evaluating) nodes one after the other, using a small stack machine.
@@ -611,6 +619,10 @@ node: aNode
 	node := aNode
 	node := aNode
 !
 !
 
 
+refResults
+	^ refResults
+!
+
 result
 result
 	^ self hasReturned 
 	^ self hasReturned 
 		ifTrue: [ self returnValue ] 
 		ifTrue: [ self returnValue ] 
@@ -634,6 +646,7 @@ stack
 initialize
 initialize
 	super initialize.
 	super initialize.
 
 
+	refResults := #{}.
 	forceAtEnd := false
 	forceAtEnd := false
 ! !
 ! !
 
 
@@ -858,6 +871,14 @@ visitNode: aNode
 	"Do nothing by default. Especially, do not visit children recursively."
 	"Do nothing by default. Especially, do not visit children recursively."
 !
 !
 
 
+visitRefNode: aNode
+	| ref refid |
+	ref := aNode node.
+	refid := ref nodeId.
+	self refResults at: refid ifAbsentPut: [ self pop ].
+	self push: (self refResults at: refid)
+!
+
 visitReturnNode: aNode
 visitReturnNode: aNode
 	returned := true.
 	returned := true.
 	self returnValue: self pop
 	self returnValue: self pop
@@ -867,7 +888,7 @@ visitSendNode: aNode
 	| receiver args message result |
 	| receiver args message result |
 	
 	
 	args := aNode arguments collect: [ :each | self pop ].
 	args := aNode arguments collect: [ :each | self pop ].
-	receiver := self peek.
+	receiver := self pop.
 	
 	
 	message := self
 	message := self
 		messageFromSendNode: aNode
 		messageFromSendNode: aNode
@@ -877,7 +898,7 @@ visitSendNode: aNode
 	
 	
 	"For cascade sends, push the reciever if the send is not the last one"
 	"For cascade sends, push the reciever if the send is not the last one"
 	(aNode isCascadeSendNode and: [ aNode isLastChild not ])
 	(aNode isCascadeSendNode and: [ aNode isLastChild not ])
-		ifFalse: [ self pop; push: result ]
+		ifFalse: [ self push: result ]
 !
 !
 
 
 visitSequenceNode: aNode
 visitSequenceNode: aNode
@@ -1025,6 +1046,13 @@ nextSiblingNode: aNode
 		ifAbsent: [ ^ nil ]
 		ifAbsent: [ ^ nil ]
 ! !
 ! !
 
 
+!RefNode methodsFor: '*Compiler-Interpreter'!
+
+nextSiblingNode: aNode
+	"no siblings in ref node"
+	^ nil
+! !
+
 !SendNode methodsFor: '*Compiler-Interpreter'!
 !SendNode methodsFor: '*Compiler-Interpreter'!
 
 
 isSteppingNode
 isSteppingNode

+ 106 - 6
src/Compiler-Semantic.js

@@ -1730,7 +1730,7 @@ $globals.UnknownVar);
 
 
 
 
 
 
-$core.addClass('SemanticAnalyzer', $globals.NodeVisitor, ['currentScope', 'blockIndex', 'thePackage', 'theClass', 'classReferences', 'messageSends'], 'Compiler-Semantic');
+$core.addClass('SemanticAnalyzer', $globals.NodeVisitor, ['currentScope', 'blockIndex', 'thePackage', 'theClass', 'classReferences', 'messageSends', 'visitedRefIds'], 'Compiler-Semantic');
 //>>excludeStart("ide", pragmas.excludeIdeData);
 //>>excludeStart("ide", pragmas.excludeIdeData);
 $globals.SemanticAnalyzer.comment="I semantically analyze the abstract syntax tree and annotate it with informations such as non local returns and variable scopes.";
 $globals.SemanticAnalyzer.comment="I semantically analyze the abstract syntax tree and annotate it with informations such as non local returns and variable scopes.";
 //>>excludeEnd("ide");
 //>>excludeEnd("ide");
@@ -1844,6 +1844,39 @@ messageSends: ["value", "ifTrue:ifFalse:", "and:", "not", "includes:", "globalJs
 }),
 }),
 $globals.SemanticAnalyzer);
 $globals.SemanticAnalyzer);
 
 
+$core.addMethod(
+$core.method({
+selector: "initialize",
+protocol: 'initialization',
+fn: function (){
+var self=this;
+function $Set(){return $globals.Set||(typeof Set=="undefined"?nil:Set)}
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+(
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.supercall = true, 
+//>>excludeEnd("ctx");
+($globals.SemanticAnalyzer.superclass||$boot.dnu).fn.prototype._initialize.apply($recv(self), []));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.supercall = false;
+//>>excludeEnd("ctx");;
+self["@visitedRefIds"]=$recv($Set())._new();
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"initialize",{},$globals.SemanticAnalyzer)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "initialize\x0a\x09super initialize.\x0a\x0a\x09visitedRefIds := Set new",
+referencedClasses: ["Set"],
+//>>excludeEnd("ide");
+messageSends: ["initialize", "new"]
+}),
+$globals.SemanticAnalyzer);
+
 $core.addMethod(
 $core.addMethod(
 $core.method({
 $core.method({
 selector: "isVariableUndefined:inPackage:",
 selector: "isVariableUndefined:inPackage:",
@@ -2298,10 +2331,33 @@ selector: "visitCascadeNode:",
 protocol: 'visiting',
 protocol: 'visiting',
 fn: function (aNode){
 fn: function (aNode){
 var self=this;
 var self=this;
+var recv;
+function $RefNode(){return $globals.RefNode||(typeof RefNode=="undefined"?nil:RefNode)}
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
 //>>excludeEnd("ctx");
-$recv(aNode)._receiver_($recv($recv($recv(aNode)._nodes())._first())._receiver());
+var $2,$1,$3;
+$2=$recv(aNode)._nodes();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["nodes"]=1;
+//>>excludeEnd("ctx");
+$1=$recv($2)._first();
+recv=$recv($1)._receiver();
+$recv($recv(aNode)._nodes())._do_((function(each){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx2) {
+//>>excludeEnd("ctx");
+$3=$recv($RefNode())._new();
+$recv($3)._node_(recv);
+return $recv(each)._receiver_($recv($3)._yourself());
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx2.sendIdx["receiver:"]=1;
+//>>excludeEnd("ctx");
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)});
+//>>excludeEnd("ctx");
+}));
+$recv(aNode)._receiver_(recv);
 (
 (
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 $ctx1.supercall = true, 
 $ctx1.supercall = true, 
@@ -2312,15 +2368,15 @@ $ctx1.supercall = false;
 //>>excludeEnd("ctx");;
 //>>excludeEnd("ctx");;
 return self;
 return self;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"visitCascadeNode:",{aNode:aNode},$globals.SemanticAnalyzer)});
+}, function($ctx1) {$ctx1.fill(self,"visitCascadeNode:",{aNode:aNode,recv:recv},$globals.SemanticAnalyzer)});
 //>>excludeEnd("ctx");
 //>>excludeEnd("ctx");
 },
 },
 //>>excludeStart("ide", pragmas.excludeIdeData);
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["aNode"],
 args: ["aNode"],
-source: "visitCascadeNode: aNode\x0a\x09aNode receiver: aNode nodes first receiver.\x0a\x09super visitCascadeNode: aNode",
-referencedClasses: [],
+source: "visitCascadeNode: aNode\x0a\x09| recv |\x0a\x09recv := aNode nodes first receiver.\x0a\x09aNode nodes do: [ :each | each receiver: (RefNode new node: recv; yourself) ].\x0a\x09aNode receiver: recv.\x0a\x09super visitCascadeNode: aNode",
+referencedClasses: ["RefNode"],
 //>>excludeEnd("ide");
 //>>excludeEnd("ide");
-messageSends: ["receiver:", "receiver", "first", "nodes", "visitCascadeNode:"]
+messageSends: ["receiver", "first", "nodes", "do:", "receiver:", "node:", "new", "yourself", "visitCascadeNode:"]
 }),
 }),
 $globals.SemanticAnalyzer);
 $globals.SemanticAnalyzer);
 
 
@@ -2383,6 +2439,50 @@ messageSends: ["pushScope:", "newMethodScope", "scope:", "node:", "do:", "allIns
 }),
 }),
 $globals.SemanticAnalyzer);
 $globals.SemanticAnalyzer);
 
 
+$core.addMethod(
+$core.method({
+selector: "visitRefNode:",
+protocol: 'visiting',
+fn: function (aNode){
+var self=this;
+var ref,aux;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $1,$2;
+ref=$recv(aNode)._node();
+aux=$recv(self["@visitedRefIds"])._size();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["size"]=1;
+//>>excludeEnd("ctx");
+$recv(self["@visitedRefIds"])._add_($recv(ref)._nodeId());
+$1=$recv(aux).__lt($recv(self["@visitedRefIds"])._size());
+if($core.assert($1)){
+$recv(ref)._shouldBeAliased_(true);
+$2=(
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.supercall = true, 
+//>>excludeEnd("ctx");
+($globals.SemanticAnalyzer.superclass||$boot.dnu).fn.prototype._visitRefNode_.apply($recv(self), [aNode]));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.supercall = false;
+//>>excludeEnd("ctx");;
+return $2;
+};
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"visitRefNode:",{aNode:aNode,ref:ref,aux:aux},$globals.SemanticAnalyzer)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["aNode"],
+source: "visitRefNode: aNode\x0a\x09| ref aux |\x0a\x09ref := aNode node.\x0a\x09aux := visitedRefIds size.\x0a\x09visitedRefIds add: ref nodeId.\x0a\x09aux < visitedRefIds size \x22added; not visited yet\x22 ifTrue: [\x0a\x09\x09ref shouldBeAliased: true.\x0a\x09\x09^ super visitRefNode: aNode ]",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["node", "size", "add:", "nodeId", "ifTrue:", "<", "shouldBeAliased:", "visitRefNode:"]
+}),
+$globals.SemanticAnalyzer);
+
 $core.addMethod(
 $core.addMethod(
 $core.method({
 $core.method({
 selector: "visitReturnNode:",
 selector: "visitReturnNode:",

+ 23 - 2
src/Compiler-Semantic.st

@@ -410,7 +410,7 @@ isUnknownVar
 ! !
 ! !
 
 
 NodeVisitor subclass: #SemanticAnalyzer
 NodeVisitor subclass: #SemanticAnalyzer
-	instanceVariableNames: 'currentScope blockIndex thePackage theClass classReferences messageSends'
+	instanceVariableNames: 'currentScope blockIndex thePackage theClass classReferences messageSends visitedRefIds'
 	package: 'Compiler-Semantic'!
 	package: 'Compiler-Semantic'!
 !SemanticAnalyzer commentStamp!
 !SemanticAnalyzer commentStamp!
 I semantically analyze the abstract syntax tree and annotate it with informations such as non local returns and variable scopes.!
 I semantically analyze the abstract syntax tree and annotate it with informations such as non local returns and variable scopes.!
@@ -487,6 +487,14 @@ newScopeOfClass: aLexicalScopeClass
 		yourself
 		yourself
 ! !
 ! !
 
 
+!SemanticAnalyzer methodsFor: 'initialization'!
+
+initialize
+	super initialize.
+
+	visitedRefIds := Set new
+! !
+
 !SemanticAnalyzer methodsFor: 'private'!
 !SemanticAnalyzer methodsFor: 'private'!
 
 
 nextBlockIndex
 nextBlockIndex
@@ -555,7 +563,10 @@ visitBranchSendNode: aNode
 !
 !
 
 
 visitCascadeNode: aNode
 visitCascadeNode: aNode
-	aNode receiver: aNode nodes first receiver.
+	| recv |
+	recv := aNode nodes first receiver.
+	aNode nodes do: [ :each | each receiver: (RefNode new node: recv; yourself) ].
+	aNode receiver: recv.
 	super visitCascadeNode: aNode
 	super visitCascadeNode: aNode
 !
 !
 
 
@@ -578,6 +589,16 @@ visitMethodNode: aNode
 	self popScope
 	self popScope
 !
 !
 
 
+visitRefNode: aNode
+	| ref aux |
+	ref := aNode node.
+	aux := visitedRefIds size.
+	visitedRefIds add: ref nodeId.
+	aux < visitedRefIds size "added; not visited yet" ifTrue: [
+		ref shouldBeAliased: true.
+		^ super visitRefNode: aNode ]
+!
+
 visitReturnNode: aNode
 visitReturnNode: aNode
 	aNode scope: currentScope.
 	aNode scope: currentScope.
 	currentScope isMethodScope
 	currentScope isMethodScope

+ 24 - 0
src/Compiler-Tests.js

@@ -939,6 +939,30 @@ messageSends: ["should:return:"]
 }),
 }),
 $globals.CodeGeneratorTest);
 $globals.CodeGeneratorTest);
 
 
+$core.addMethod(
+$core.method({
+selector: "testInnerCascades",
+protocol: 'tests',
+fn: function (){
+var self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+self._should_return_("foo ^ Array new add: (3 squared; negated); add: (4 negated; squared); yourself",[(-3), (16)]);
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"testInnerCascades",{},$globals.CodeGeneratorTest)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "testInnerCascades\x0a\x09\x0a\x09self should: 'foo ^ Array new add: (3 squared; negated); add: (4 negated; squared); yourself' return: #(-3 16)",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["should:return:"]
+}),
+$globals.CodeGeneratorTest);
+
 $core.addMethod(
 $core.addMethod(
 $core.method({
 $core.method({
 selector: "testInnerTemporalDependentElementsOrdered",
 selector: "testInnerTemporalDependentElementsOrdered",

+ 5 - 0
src/Compiler-Tests.st

@@ -255,6 +255,11 @@ testGlobalVar
 	self should: 'foo ^ NonExistingVar' return: nil
 	self should: 'foo ^ NonExistingVar' return: nil
 !
 !
 
 
+testInnerCascades
+	
+	self should: 'foo ^ Array new add: (3 squared; negated); add: (4 negated; squared); yourself' return: #(-3 16)
+!
+
 testInnerTemporalDependentElementsOrdered
 testInnerTemporalDependentElementsOrdered
 	self should: 'foo
 	self should: 'foo
 	| x |
 	| x |

+ 8 - 10
src/Kernel-Tests.js

@@ -5301,7 +5301,7 @@ var self=this;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
 //>>excludeEnd("ctx");
-var $2,$3,$4,$1,$5,$7,$8,$9,$6,$10,$12,$11;
+var $2,$3,$4,$1,$5,$7,$8,$9,$6,$10,$11;
 (
 (
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 $ctx1.supercall = true, 
 $ctx1.supercall = true, 
@@ -5360,13 +5360,12 @@ self._assert_equals_($6,$10);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 $ctx1.sendIdx["assert:equals:"]=2;
 $ctx1.sendIdx["assert:equals:"]=2;
 //>>excludeEnd("ctx");
 //>>excludeEnd("ctx");
-$12=self._collectionWithNewValue();
+$11=self._collectionWithNewValue();
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 $ctx1.sendIdx["collectionWithNewValue"]=3;
 $ctx1.sendIdx["collectionWithNewValue"]=3;
 //>>excludeEnd("ctx");
 //>>excludeEnd("ctx");
-$recv($12)._addAll_(self._collection());
-$11=$recv($12)._yourself();
-self._assert_equals_($11,self._collectionWithNewValue());
+$recv($11)._addAll_(self._collection());
+self._assert_equals_($recv($11)._yourself(),self._collectionWithNewValue());
 return self;
 return self;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 }, function($ctx1) {$ctx1.fill(self,"testAddAll",{},$globals.AssociativeCollectionTest)});
 }, function($ctx1) {$ctx1.fill(self,"testAddAll",{},$globals.AssociativeCollectionTest)});
@@ -9168,7 +9167,7 @@ var self=this;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
 //>>excludeEnd("ctx");
-var $2,$3,$4,$1,$5,$7,$8,$9,$6,$10,$12,$11;
+var $2,$3,$4,$1,$5,$7,$8,$9,$6,$10,$11;
 (
 (
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 $ctx1.supercall = true, 
 $ctx1.supercall = true, 
@@ -9227,13 +9226,12 @@ self._assert_equals_($6,$10);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 $ctx1.sendIdx["assert:equals:"]=2;
 $ctx1.sendIdx["assert:equals:"]=2;
 //>>excludeEnd("ctx");
 //>>excludeEnd("ctx");
-$12=self._collectionWithNewValue();
+$11=self._collectionWithNewValue();
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 $ctx1.sendIdx["collectionWithNewValue"]=3;
 $ctx1.sendIdx["collectionWithNewValue"]=3;
 //>>excludeEnd("ctx");
 //>>excludeEnd("ctx");
-$recv($12)._addAll_(self._collection());
-$11=$recv($12)._yourself();
-self._assert_equals_($11,self._collectionWithNewValue());
+$recv($11)._addAll_(self._collection());
+self._assert_equals_($recv($11)._yourself(),self._collectionWithNewValue());
 return self;
 return self;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 }, function($ctx1) {$ctx1.fill(self,"testAddAll",{},$globals.SetTest)});
 }, function($ctx1) {$ctx1.fill(self,"testAddAll",{},$globals.SetTest)});