ソースを参照

Merge branch 'master' into ast-interpreter

Conflicts:
	js/Compiler-IR.deploy.js
	js/Compiler-IR.js
	js/Compiler-Semantic.deploy.js
	js/Compiler-Semantic.js
	js/Kernel-Objects.deploy.js
	js/Kernel-Objects.js
Nicolas Petton 11 年 前
コミット
b65cf751ff

+ 35 - 0
js/Compiler-AST.deploy.js

@@ -57,6 +57,17 @@ return smalltalk.withContext(function($ctx1) { 
return false;
 }),
 smalltalk.Node);
 
+smalltalk.addMethod(
+"_isImmutable",
+smalltalk.method({
+selector: "isImmutable",
+fn: function (){
+var self=this;
+return false;
+}
+}),
+smalltalk.Node);
+
 smalltalk.addMethod(
 "_isReturnNode",
 smalltalk.method({
@@ -1057,6 +1068,19 @@ return $1;
 }),
 smalltalk.ValueNode);
 
+smalltalk.addMethod(
+"_isImmutable",
+smalltalk.method({
+selector: "isImmutable",
+fn: function (){
+var self=this;
+var $1;
+$1=true;
+return $1;
+}
+}),
+smalltalk.ValueNode);
+
 smalltalk.addMethod(
 "_isValueNode",
 smalltalk.method({
@@ -1181,6 +1205,17 @@ return self}, self, "binding:", [aScopeVar], smalltalk.VariableNode)}
 }),
 smalltalk.VariableNode);
 
+smalltalk.addMethod(
+"_isImmutable",
+smalltalk.method({
+selector: "isImmutable",
+fn: function (){
+var self=this;
+return false;
+}
+}),
+smalltalk.VariableNode);
+
 
 
 smalltalk.addClass('ClassReferenceNode', smalltalk.VariableNode, [], 'Compiler-AST');

+ 50 - 0
js/Compiler-AST.js

@@ -83,6 +83,22 @@ referencedClasses: []
 }),
 smalltalk.Node);
 
+smalltalk.addMethod(
+"_isImmutable",
+smalltalk.method({
+selector: "isImmutable",
+category: 'testing',
+fn: function (){
+var self=this;
+return false;
+},
+args: [],
+source: "isImmutable\x0a\x09^false",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Node);
+
 smalltalk.addMethod(
 "_isReturnNode",
 smalltalk.method({
@@ -1463,6 +1479,24 @@ referencedClasses: []
 }),
 smalltalk.ValueNode);
 
+smalltalk.addMethod(
+"_isImmutable",
+smalltalk.method({
+selector: "isImmutable",
+category: 'testing',
+fn: function (){
+var self=this;
+var $1;
+$1=true;
+return $1;
+},
+args: [],
+source: "isImmutable\x0a\x09^true",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.ValueNode);
+
 smalltalk.addMethod(
 "_isValueNode",
 smalltalk.method({
@@ -1637,6 +1671,22 @@ referencedClasses: []
 }),
 smalltalk.VariableNode);
 
+smalltalk.addMethod(
+"_isImmutable",
+smalltalk.method({
+selector: "isImmutable",
+category: 'testing',
+fn: function (){
+var self=this;
+return false;
+},
+args: [],
+source: "isImmutable\x0a\x09^false",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.VariableNode);
+
 
 
 smalltalk.addClass('ClassReferenceNode', smalltalk.VariableNode, [], 'Compiler-AST');

+ 217 - 129
js/Compiler-IR.deploy.js

@@ -7,8 +7,8 @@ selector: "alias:",
 fn: function (aNode){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3,$4,$5,$6;
-$ctx1.variable=nil;
-$1=_st(aNode)._isValueNode();
+$ctx1.locals.variable=nil;
+$1=_st(aNode)._isImmutable();
 if(smalltalk.assert($1)){
 $2=_st(self)._visit_(aNode);
 return $2;
@@ -114,6 +114,41 @@ return self}, self, "source:", [aString], smalltalk.IRASTTranslator)}
 }),
 smalltalk.IRASTTranslator);
 
+smalltalk.addMethod(
+"_temporallyDependentList_",
+smalltalk.method({
+selector: "temporallyDependentList:",
+fn: function (nodes){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1,$3,$2,$4;
+$ctx1.locals.threshold=nil;
+$ctx1.locals.result=nil;
+$ctx1.locals.threshold=(0);
+_st(nodes)._withIndexDo_((function(each,i){
+return smalltalk.withContext(function($ctx2) { 
$1=_st(_st(each)._shouldBeInlined())._or_((function(){
+return smalltalk.withContext(function($ctx3) { 
return _st(each)._shouldBeAliased();
+})}));
+if(smalltalk.assert($1)){
+$ctx1.locals.threshold=i;
+return $ctx1.locals.threshold;
+};
+})}));
+$ctx1.locals.result=_st((smalltalk.OrderedCollection || OrderedCollection))._new();
+_st(nodes)._withIndexDo_((function(each,i){
+return smalltalk.withContext(function($ctx2) { 
$3=_st(i).__lt_eq($ctx1.locals.threshold);
+if(smalltalk.assert($3)){
+$2=_st(self)._alias_(each);
+} else {
+$2=_st(self)._visit_(each);
+};
+return _st($ctx1.locals.result)._add_($2);
+})}));
+$4=$ctx1.locals.result;
+return $4;
+}, self, "temporallyDependentList:", [nodes], smalltalk.IRASTTranslator)}
+}),
+smalltalk.IRASTTranslator);
+
 smalltalk.addMethod(
 "_theClass",
 smalltalk.method({
@@ -142,10 +177,10 @@ smalltalk.method({
 selector: "visitAssignmentNode:",
 fn: function (aNode){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2;
-$ctx1.left=nil;
-$ctx1.right=nil;
-$ctx1.assignment=nil;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3;
+$ctx1.locals.left=nil;
+$ctx1.locals.right=nil;
+$ctx1.locals.assignment=nil;
 $ctx1.locals.right=_st(self)._visit_(_st(aNode)._right());
 $ctx1.locals.left=_st(self)._visit_(_st(aNode)._left());
 $1=_st((smalltalk.IRAssignment || IRAssignment))._new();
@@ -153,7 +188,8 @@ _st($1)._add_($ctx1.locals.left);
 _st($1)._add_($ctx1.locals.right);
 $2=_st($1)._yourself();
 _st(_st(self)._sequence())._add_($2);
-return $ctx1.locals.left;
+$3=$ctx1.locals.left;
+return $3;
 }, self, "visitAssignmentNode:", [aNode], smalltalk.IRASTTranslator)}
 }),
 smalltalk.IRASTTranslator);
@@ -164,8 +200,8 @@ smalltalk.method({
 selector: "visitBlockNode:",
 fn: function (aNode){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3,$4;
-$ctx1.closure=nil;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3,$4,$5;
+$ctx1.locals.closure=nil;
 $1=_st((smalltalk.IRClosure || IRClosure))._new();
 _st($1)._arguments_(_st(aNode)._parameters());
 _st($1)._scope_(_st(aNode)._scope());
@@ -181,7 +217,8 @@ return _st($ctx1.locals.closure)._add_($4);
 _st(_st(aNode)._nodes())._do_((function(each){
 return smalltalk.withContext(function($ctx2) { 
return _st($ctx1.locals.closure)._add_(_st(self)._visit_(each));
 })}));
-return $ctx1.locals.closure;
+$5=$ctx1.locals.closure;
+return $5;
 }, self, "visitBlockNode:", [aNode], smalltalk.IRASTTranslator)}
 }),
 smalltalk.IRASTTranslator);
@@ -221,8 +258,8 @@ selector: "visitCascadeNode:",
 fn: function (aNode){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
var $1,$2;
-$ctx1.alias=nil;
-$1=_st(_st(aNode)._receiver())._isValueNode();
+$ctx1.locals.alias=nil;
+$1=_st(_st(aNode)._receiver())._isImmutable();
 if(! smalltalk.assert($1)){
 $ctx1.locals.alias=_st(self)._alias_(_st(aNode)._receiver());
 $ctx1.locals.alias;
@@ -245,12 +282,14 @@ smalltalk.method({
 selector: "visitDynamicArrayNode:",
 fn: function (aNode){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
$ctx1.array=nil;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$ctx1.locals.array=nil;
 $ctx1.locals.array=_st((smalltalk.IRDynamicArray || IRDynamicArray))._new();
 _st(_st(aNode)._nodes())._do_((function(each){
 return smalltalk.withContext(function($ctx2) { 
return _st($ctx1.locals.array)._add_(_st(self)._visit_(each));
 })}));
-return $ctx1.locals.array;
+$1=$ctx1.locals.array;
+return $1;
 }, self, "visitDynamicArrayNode:", [aNode], smalltalk.IRASTTranslator)}
 }),
 smalltalk.IRASTTranslator);
@@ -261,12 +300,14 @@ smalltalk.method({
 selector: "visitDynamicDictionaryNode:",
 fn: function (aNode){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
$ctx1.dictionary=nil;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$ctx1.locals.dictionary=nil;
 $ctx1.locals.dictionary=_st((smalltalk.IRDynamicDictionary || IRDynamicDictionary))._new();
 _st(_st(aNode)._nodes())._do_((function(each){
 return smalltalk.withContext(function($ctx2) { 
return _st($ctx1.locals.dictionary)._add_(_st(self)._visit_(each));
 })}));
-return $ctx1.locals.dictionary;
+$1=$ctx1.locals.dictionary;
+return $1;
 }, self, "visitDynamicDictionaryNode:", [aNode], smalltalk.IRASTTranslator)}
 }),
 smalltalk.IRASTTranslator);
@@ -334,8 +375,8 @@ smalltalk.method({
 selector: "visitReturnNode:",
 fn: function (aNode){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
-$ctx1.return=nil;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
+$ctx1.locals.return=nil;
 $1=_st(aNode)._nonLocalReturn();
 if(smalltalk.assert($1)){
 $ctx1.locals.return_=_st((smalltalk.IRNonLocalReturn || IRNonLocalReturn))._new();
@@ -346,7 +387,8 @@ _st($ctx1.locals.return_)._scope_(_st(aNode)._scope());
 _st(_st(aNode)._nodes())._do_((function(each){
 return smalltalk.withContext(function($ctx2) { 
return _st($ctx1.locals.return_)._add_(_st(self)._alias_(each));
 })}));
-return $ctx1.locals.return_;
+$2=$ctx1.locals.return_;
+return $2;
 }, self, "visitReturnNode:", [aNode], smalltalk.IRASTTranslator)}
 }),
 smalltalk.IRASTTranslator);
@@ -358,37 +400,27 @@ selector: "visitSendNode:",
 fn: function (aNode){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3,$4;
-$ctx1.send=nil;
-$ctx1.receiver=nil;
-$ctx1.arguments=nil;
+$ctx1.locals.send=nil;
+$ctx1.locals.all=nil;
+$ctx1.locals.receiver=nil;
+$ctx1.locals.arguments=nil;
 $ctx1.locals.send=_st((smalltalk.IRSend || IRSend))._new();
-_st($ctx1.locals.send)._selector_(_st(aNode)._selector());
-$1=_st($ctx1.locals.send)._index_(_st(aNode)._index());
-$2=_st(aNode)._superSend();
-if(smalltalk.assert($2)){
-_st($ctx1.locals.send)._classSend_(_st(_st(self)._theClass())._superclass());
-};
-$3=_st(_st(_st(aNode)._receiver())._shouldBeInlined())._or_((function(){
-return smalltalk.withContext(function($ctx2) { 
return _st(_st(aNode)._receiver())._shouldBeAliased();
-})}));
+$1=$ctx1.locals.send;
+_st($1)._selector_(_st(aNode)._selector());
+$2=_st($1)._index_(_st(aNode)._index());
+$3=_st(aNode)._superSend();
 if(smalltalk.assert($3)){
-$ctx1.locals.receiver=_st(self)._alias_(_st(aNode)._receiver());
-} else {
-$ctx1.locals.receiver=_st(self)._visit_(_st(aNode)._receiver());
-};
-$ctx1.locals.arguments=_st(_st(aNode)._arguments())._collect_((function(each){
-return smalltalk.withContext(function($ctx2) { 
$4=_st(each)._shouldBeInlined();
-if(smalltalk.assert($4)){
-return _st(self)._alias_(each);
-} else {
-return _st(self)._visit_(each);
+_st($ctx1.locals.send)._classSend_(_st(_st(self)._theClass())._superclass());
 };
-})}));
+$ctx1.locals.all=_st(self)._temporallyDependentList_(_st([_st(aNode)._receiver()]).__comma(_st(aNode)._arguments()));
+$ctx1.locals.receiver=_st($ctx1.locals.all)._first();
+$ctx1.locals.arguments=_st($ctx1.locals.all)._allButFirst();
 _st($ctx1.locals.send)._add_($ctx1.locals.receiver);
 _st($ctx1.locals.arguments)._do_((function(each){
 return smalltalk.withContext(function($ctx2) { 
return _st($ctx1.locals.send)._add_(each);
 })}));
-return $ctx1.locals.send;
+$4=$ctx1.locals.send;
+return $4;
 }, self, "visitSendNode:", [aNode], smalltalk.IRASTTranslator)}
 }),
 smalltalk.IRASTTranslator);
@@ -402,7 +434,7 @@ var self=this;
 return smalltalk.withContext(function($ctx1) { 
var $2,$1;
 $1=_st(self)._withSequence_do_(_st((smalltalk.IRSequence || IRSequence))._new(),(function(){
 return smalltalk.withContext(function($ctx2) { 
return _st(_st(aNode)._nodes())._do_((function(each){
-return smalltalk.withContext(function($ctx3) { 
$ctx3.instruction=nil;
+return smalltalk.withContext(function($ctx3) { 
$ctx3.locals.instruction=nil;
 $ctx3.locals.instruction=_st(self)._visit_(each);
 $ctx3.locals.instruction;
 $2=_st($ctx3.locals.instruction)._isVariable();
@@ -454,7 +486,7 @@ smalltalk.method({
 selector: "withSequence:do:",
 fn: function (aSequence,aBlock){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
$ctx1.outerSequence=nil;
+return smalltalk.withContext(function($ctx1) { 
$ctx1.locals.outerSequence=nil;
 $ctx1.locals.outerSequence=_st(self)._sequence();
 _st(self)._sequence_(aSequence);
 _st(aBlock)._value();
@@ -617,7 +649,9 @@ smalltalk.method({
 selector: "parent",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@parent"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@parent"];
+return $1;
 }, self, "parent", [], smalltalk.IRInstruction)}
 }),
 smalltalk.IRInstruction);
@@ -751,7 +785,9 @@ smalltalk.method({
 selector: "scope",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@scope"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@scope"];
+return $1;
 }, self, "scope", [], smalltalk.IRScopedInstruction)}
 }),
 smalltalk.IRScopedInstruction);
@@ -869,7 +905,9 @@ smalltalk.method({
 selector: "arguments",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@arguments"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@arguments"];
+return $1;
 }, self, "arguments", [], smalltalk.IRMethod)}
 }),
 smalltalk.IRMethod);
@@ -891,7 +929,9 @@ smalltalk.method({
 selector: "classReferences",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@classReferences"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@classReferences"];
+return $1;
 }, self, "classReferences", [], smalltalk.IRMethod)}
 }),
 smalltalk.IRMethod);
@@ -931,7 +971,9 @@ smalltalk.method({
 selector: "messageSends",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@messageSends"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@messageSends"];
+return $1;
 }, self, "messageSends", [], smalltalk.IRMethod)}
 }),
 smalltalk.IRMethod);
@@ -965,7 +1007,9 @@ smalltalk.method({
 selector: "selector",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@selector"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@selector"];
+return $1;
 }, self, "selector", [], smalltalk.IRMethod)}
 }),
 smalltalk.IRMethod);
@@ -987,7 +1031,9 @@ smalltalk.method({
 selector: "source",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@source"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@source"];
+return $1;
 }, self, "source", [], smalltalk.IRMethod)}
 }),
 smalltalk.IRMethod);
@@ -1009,7 +1055,9 @@ smalltalk.method({
 selector: "superSends",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@superSends"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@superSends"];
+return $1;
 }, self, "superSends", [], smalltalk.IRMethod)}
 }),
 smalltalk.IRMethod);
@@ -1031,7 +1079,9 @@ smalltalk.method({
 selector: "theClass",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@theClass"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@theClass"];
+return $1;
 }, self, "theClass", [], smalltalk.IRMethod)}
 }),
 smalltalk.IRMethod);
@@ -1196,7 +1246,9 @@ smalltalk.method({
 selector: "name",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@name"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@name"];
+return $1;
 }, self, "name", [], smalltalk.IRTempDeclaration)}
 }),
 smalltalk.IRTempDeclaration);
@@ -1234,7 +1286,9 @@ smalltalk.method({
 selector: "classSend",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@classSend"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@classSend"];
+return $1;
 }, self, "classSend", [], smalltalk.IRSend)}
 }),
 smalltalk.IRSend);
@@ -1256,7 +1310,9 @@ smalltalk.method({
 selector: "index",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@index"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@index"];
+return $1;
 }, self, "index", [], smalltalk.IRSend)}
 }),
 smalltalk.IRSend);
@@ -1307,7 +1363,9 @@ smalltalk.method({
 selector: "selector",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@selector"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@selector"];
+return $1;
 }, self, "selector", [], smalltalk.IRSend)}
 }),
 smalltalk.IRSend);
@@ -1388,7 +1446,9 @@ smalltalk.method({
 selector: "value",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@value"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@value"];
+return $1;
 }, self, "value", [], smalltalk.IRValue)}
 }),
 smalltalk.IRValue);
@@ -1437,7 +1497,9 @@ smalltalk.method({
 selector: "variable",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@variable"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@variable"];
+return $1;
 }, self, "variable", [], smalltalk.IRVariable)}
 }),
 smalltalk.IRVariable);
@@ -1475,7 +1537,9 @@ smalltalk.method({
 selector: "source",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@source"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@source"];
+return $1;
 }, self, "source", [], smalltalk.IRVerbatim)}
 }),
 smalltalk.IRVerbatim);
@@ -1617,10 +1681,12 @@ smalltalk.method({
 selector: "visitIRInstruction:",
 fn: function (anIRInstruction){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
_st(_st(anIRInstruction)._instructions())._do_((function(each){
+return smalltalk.withContext(function($ctx1) { 
var $1;
+_st(_st(anIRInstruction)._instructions())._do_((function(each){
 return smalltalk.withContext(function($ctx2) { 
return _st(self)._visit_(each);
 })}));
-return anIRInstruction;
+$1=anIRInstruction;
+return $1;
 }, self, "visitIRInstruction:", [anIRInstruction], smalltalk.IRVisitor)}
 }),
 smalltalk.IRVisitor);
@@ -1789,7 +1855,9 @@ smalltalk.method({
 selector: "stream",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@stream"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@stream"];
+return $1;
 }, self, "stream", [], smalltalk.IRJSTranslator)}
 }),
 smalltalk.IRJSTranslator);
@@ -2109,9 +2177,10 @@ smalltalk.method({
 selector: "nextPutBlockContextFor:during:",
 fn: function (anIRClosure,aBlock){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
-_st(self)._nextPutAll_(_st(_st("return smalltalk.withContext(function(").__comma(_st(_st(anIRClosure)._scope())._alias())).__comma(") { "));
-$1=_st(self)._nextPutAll_(_st((smalltalk.String || String))._cr());
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
+$1=self;
+_st($1)._nextPutAll_(_st(_st("return smalltalk.withContext(function(").__comma(_st(_st(anIRClosure)._scope())._alias())).__comma(") { "));
+$2=_st($1)._nextPutAll_(_st((smalltalk.String || String))._cr());
 _st(aBlock)._value();
 _st(self)._nextPutAll_("})");
 return self}, self, "nextPutBlockContextFor:during:", [anIRClosure,aBlock], smalltalk.JSStream)}
@@ -2124,15 +2193,16 @@ smalltalk.method({
 selector: "nextPutClosureWith:arguments:",
 fn: function (aBlock,anArray){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
 _st(self["@stream"])._nextPutAll_("(function(");
 _st(anArray)._do_separatedBy_((function(each){
 return smalltalk.withContext(function($ctx2) { 
return _st(self["@stream"])._nextPutAll_(_st(each)._asVariableName());
 })}),(function(){
 return smalltalk.withContext(function($ctx2) { 
return _st(self["@stream"])._nextPut_(",");
 })}));
-_st(self["@stream"])._nextPutAll_("){");
-$1=_st(self["@stream"])._lf();
+$1=self["@stream"];
+_st($1)._nextPutAll_("){");
+$2=_st($1)._lf();
 _st(aBlock)._value();
 _st(self["@stream"])._nextPutAll_("})");
 return self}, self, "nextPutClosureWith:arguments:", [aBlock,anArray], smalltalk.JSStream)}
@@ -2145,20 +2215,23 @@ smalltalk.method({
 selector: "nextPutContextFor:during:",
 fn: function (aMethod,aBlock){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3;
-_st(self)._nextPutAll_(_st(_st("return smalltalk.withContext(function(").__comma(_st(_st(aMethod)._scope())._alias())).__comma(") { "));
-$1=_st(self)._nextPutAll_(_st((smalltalk.String || String))._cr());
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3,$4,$5,$6;
+$1=self;
+_st($1)._nextPutAll_(_st(_st("return smalltalk.withContext(function(").__comma(_st(_st(aMethod)._scope())._alias())).__comma(") { "));
+$2=_st($1)._nextPutAll_(_st((smalltalk.String || String))._cr());
 _st(aBlock)._value();
-_st(self)._nextPutAll_("}, self, ");
-$2=_st(self)._nextPutAll_(_st(_st(_st(aMethod)._selector())._asJavascript()).__comma(", ["));
+$3=self;
+_st($3)._nextPutAll_("}, self, ");
+$4=_st($3)._nextPutAll_(_st(_st(_st(aMethod)._selector())._asJavascript()).__comma(", ["));
 _st(_st(aMethod)._arguments())._do_separatedBy_((function(each){
 return smalltalk.withContext(function($ctx2) { 
return _st(self)._nextPutAll_(_st(each)._asVariableName());
 })}),(function(){
 return smalltalk.withContext(function($ctx2) { 
return _st(self)._nextPutAll_(",");
 })}));
-_st(self)._nextPutAll_("], ");
-_st(self)._nextPutAll_(_st(_st(aMethod)._theClass())._asJavascript());
-$3=_st(self)._nextPutAll_(")");
+$5=self;
+_st($5)._nextPutAll_("], ");
+_st($5)._nextPutAll_(_st(_st(aMethod)._theClass())._asJavascript());
+$6=_st($5)._nextPutAll_(")");
 return self}, self, "nextPutContextFor:during:", [aMethod,aBlock], smalltalk.JSStream)}
 }),
 smalltalk.JSStream);
@@ -2169,17 +2242,19 @@ smalltalk.method({
 selector: "nextPutFunctionWith:arguments:",
 fn: function (aBlock,anArray){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3,$4;
 _st(self["@stream"])._nextPutAll_("fn: function(");
 _st(anArray)._do_separatedBy_((function(each){
 return smalltalk.withContext(function($ctx2) { 
return _st(self["@stream"])._nextPutAll_(_st(each)._asVariableName());
 })}),(function(){
 return smalltalk.withContext(function($ctx2) { 
return _st(self["@stream"])._nextPut_(",");
 })}));
-_st(self["@stream"])._nextPutAll_("){");
-$1=_st(self["@stream"])._lf();
-_st(self["@stream"])._nextPutAll_("var self=this;");
-$2=_st(self["@stream"])._lf();
+$1=self["@stream"];
+_st($1)._nextPutAll_("){");
+$2=_st($1)._lf();
+$3=self["@stream"];
+_st($3)._nextPutAll_("var self=this;");
+$4=_st($3)._lf();
 _st(aBlock)._value();
 _st(self["@stream"])._nextPutAll_("}");
 return self}, self, "nextPutFunctionWith:arguments:", [aBlock,anArray], smalltalk.JSStream)}
@@ -2192,11 +2267,12 @@ smalltalk.method({
 selector: "nextPutIf:with:",
 fn: function (aBlock,anotherBlock){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
 _st(self["@stream"])._nextPutAll_("if(");
 _st(aBlock)._value();
-_st(self["@stream"])._nextPutAll_("){");
-$1=_st(self["@stream"])._lf();
+$1=self["@stream"];
+_st($1)._nextPutAll_("){");
+$2=_st($1)._lf();
 _st(anotherBlock)._value();
 _st(self["@stream"])._nextPutAll_("}");
 return self}, self, "nextPutIf:with:", [aBlock,anotherBlock], smalltalk.JSStream)}
@@ -2209,14 +2285,16 @@ smalltalk.method({
 selector: "nextPutIfElse:with:with:",
 fn: function (aBlock,ifBlock,elseBlock){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3,$4;
 _st(self["@stream"])._nextPutAll_("if(");
 _st(aBlock)._value();
-_st(self["@stream"])._nextPutAll_("){");
-$1=_st(self["@stream"])._lf();
+$1=self["@stream"];
+_st($1)._nextPutAll_("){");
+$2=_st($1)._lf();
 _st(ifBlock)._value();
-_st(self["@stream"])._nextPutAll_("} else {");
-$2=_st(self["@stream"])._lf();
+$3=self["@stream"];
+_st($3)._nextPutAll_("} else {");
+$4=_st($3)._lf();
 _st(elseBlock)._value();
 _st(self["@stream"])._nextPutAll_("}");
 return self}, self, "nextPutIfElse:with:with:", [aBlock,ifBlock,elseBlock], smalltalk.JSStream)}
@@ -2229,29 +2307,32 @@ smalltalk.method({
 selector: "nextPutMethodDeclaration:with:",
 fn: function (aMethod,aBlock){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3;
-_st(self["@stream"])._nextPutAll_("smalltalk.method({");
-_st(self["@stream"])._lf();
-_st(self["@stream"])._nextPutAll_(_st(_st("selector: \x22").__comma(_st(aMethod)._selector())).__comma("\x22,"));
-_st(self["@stream"])._lf();
-_st(self["@stream"])._nextPutAll_(_st(_st("source: ").__comma(_st(_st(aMethod)._source())._asJavascript())).__comma(","));
-$1=_st(self["@stream"])._lf();
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3,$4,$5,$6;
+$1=self["@stream"];
+_st($1)._nextPutAll_("smalltalk.method({");
+_st($1)._lf();
+_st($1)._nextPutAll_(_st(_st("selector: \x22").__comma(_st(aMethod)._selector())).__comma("\x22,"));
+_st($1)._lf();
+_st($1)._nextPutAll_(_st(_st("source: ").__comma(_st(_st(aMethod)._source())._asJavascript())).__comma(","));
+$2=_st($1)._lf();
 _st(aBlock)._value();
-_st(self["@stream"])._nextPutAll_(_st(_st(",").__comma(_st((smalltalk.String || String))._lf())).__comma("messageSends: "));
-_st(self["@stream"])._nextPutAll_(_st(_st(_st(_st(aMethod)._messageSends())._asArray())._asJavascript()).__comma(","));
-_st(self["@stream"])._lf();
-_st(self["@stream"])._nextPutAll_(_st(_st("args: ").__comma(_st(_st(_st(_st(aMethod)._arguments())._collect_((function(each){
+$3=self["@stream"];
+_st($3)._nextPutAll_(_st(_st(",").__comma(_st((smalltalk.String || String))._lf())).__comma("messageSends: "));
+_st($3)._nextPutAll_(_st(_st(_st(_st(aMethod)._messageSends())._asArray())._asJavascript()).__comma(","));
+_st($3)._lf();
+_st($3)._nextPutAll_(_st(_st("args: ").__comma(_st(_st(_st(_st(aMethod)._arguments())._collect_((function(each){
 return smalltalk.withContext(function($ctx2) { 
return _st(each)._value();
 })})))._asArray())._asJavascript())).__comma(","));
-_st(self["@stream"])._lf();
-$2=_st(self["@stream"])._nextPutAll_("referencedClasses: [");
+_st($3)._lf();
+$4=_st($3)._nextPutAll_("referencedClasses: [");
 _st(_st(aMethod)._classReferences())._do_separatedBy_((function(each){
 return smalltalk.withContext(function($ctx2) { 
return _st(self["@stream"])._nextPutAll_(_st(each)._asJavascript());
 })}),(function(){
 return smalltalk.withContext(function($ctx2) { 
return _st(self["@stream"])._nextPutAll_(",");
 })}));
-_st(self["@stream"])._nextPutAll_("]");
-$3=_st(self["@stream"])._nextPutAll_("})");
+$5=self["@stream"];
+_st($5)._nextPutAll_("]");
+$6=_st($5)._nextPutAll_("})");
 return self}, self, "nextPutMethodDeclaration:with:", [aMethod,aBlock], smalltalk.JSStream)}
 }),
 smalltalk.JSStream);
@@ -2262,16 +2343,18 @@ smalltalk.method({
 selector: "nextPutNonLocalReturnHandlingWith:",
 fn: function (aBlock){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2;
-_st(self["@stream"])._nextPutAll_("var $early={};");
-_st(self["@stream"])._lf();
-_st(self["@stream"])._nextPutAll_("try {");
-$1=_st(self["@stream"])._lf();
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3,$4;
+$1=self["@stream"];
+_st($1)._nextPutAll_("var $early={};");
+_st($1)._lf();
+_st($1)._nextPutAll_("try {");
+$2=_st($1)._lf();
 _st(aBlock)._value();
-_st(self["@stream"])._nextPutAll_("}");
-_st(self["@stream"])._lf();
-_st(self["@stream"])._nextPutAll_("catch(e) {if(e===$early)return e[0]; throw e}");
-$2=_st(self["@stream"])._lf();
+$3=self["@stream"];
+_st($3)._nextPutAll_("}");
+_st($3)._lf();
+_st($3)._nextPutAll_("catch(e) {if(e===$early)return e[0]; throw e}");
+$4=_st($3)._lf();
 return self}, self, "nextPutNonLocalReturnHandlingWith:", [aBlock], smalltalk.JSStream)}
 }),
 smalltalk.JSStream);
@@ -2329,12 +2412,14 @@ smalltalk.method({
 selector: "nextPutStatement:with:",
 fn: function (anInteger,aBlock){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2;
-_st(self["@stream"])._nextPutAll_(_st(_st("case ").__comma(_st(anInteger)._asString())).__comma(":"));
-$1=_st(self["@stream"])._lf();
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3,$4;
+$1=self["@stream"];
+_st($1)._nextPutAll_(_st(_st("case ").__comma(_st(anInteger)._asString())).__comma(":"));
+$2=_st($1)._lf();
 _st(self)._nextPutStatementWith_(aBlock);
-_st(self["@stream"])._nextPutAll_(_st(_st("smalltalk.thisContext.pc=").__comma(_st(_st(anInteger).__plus((1)))._asString())).__comma(";"));
-$2=_st(self["@stream"])._lf();
+$3=self["@stream"];
+_st($3)._nextPutAll_(_st(_st("smalltalk.thisContext.pc=").__comma(_st(_st(anInteger).__plus((1)))._asString())).__comma(";"));
+$4=_st($3)._lf();
 return self}, self, "nextPutStatement:with:", [anInteger,aBlock], smalltalk.JSStream)}
 }),
 smalltalk.JSStream);
@@ -2345,10 +2430,11 @@ smalltalk.method({
 selector: "nextPutStatementWith:",
 fn: function (aBlock){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
 _st(aBlock)._value();
-_st(self["@stream"])._nextPutAll_(";");
-$1=_st(self["@stream"])._lf();
+$1=self["@stream"];
+_st($1)._nextPutAll_(";");
+$2=_st($1)._lf();
 return self}, self, "nextPutStatementWith:", [aBlock], smalltalk.JSStream)}
 }),
 smalltalk.JSStream);
@@ -2359,9 +2445,10 @@ smalltalk.method({
 selector: "nextPutVar:",
 fn: function (aString){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
-_st(self["@stream"])._nextPutAll_(_st(_st("var ").__comma(aString)).__comma(";"));
-$1=_st(self["@stream"])._lf();
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
+$1=self["@stream"];
+_st($1)._nextPutAll_(_st(_st("var ").__comma(aString)).__comma(";"));
+$2=_st($1)._lf();
 return self}, self, "nextPutVar:", [aString], smalltalk.JSStream)}
 }),
 smalltalk.JSStream);
@@ -2372,15 +2459,16 @@ smalltalk.method({
 selector: "nextPutVars:",
 fn: function (aCollection){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
 _st(self["@stream"])._nextPutAll_("var ");
 _st(aCollection)._do_separatedBy_((function(each){
 return smalltalk.withContext(function($ctx2) { 
return _st(self["@stream"])._nextPutAll_(each);
 })}),(function(){
 return smalltalk.withContext(function($ctx2) { 
return _st(self["@stream"])._nextPutAll_(",");
 })}));
-_st(self["@stream"])._nextPutAll_(";");
-$1=_st(self["@stream"])._lf();
+$1=self["@stream"];
+_st($1)._nextPutAll_(";");
+$2=_st($1)._lf();
 return self}, self, "nextPutVars:", [aCollection], smalltalk.JSStream)}
 }),
 smalltalk.JSStream);

+ 230 - 137
js/Compiler-IR.js

@@ -9,8 +9,8 @@ category: 'visiting',
 fn: function (aNode){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3,$4,$5,$6;
-$ctx1.variable=nil;
-$1=_st(aNode)._isValueNode();
+$ctx1.locals.variable=nil;
+$1=_st(aNode)._isImmutable();
 if(smalltalk.assert($1)){
 $2=_st(self)._visit_(aNode);
 return $2;
@@ -28,8 +28,8 @@ _st(_st(_st(self)._method())._internalVariables())._add_($ctx1.locals.variable);
 return $ctx1.locals.variable;
 }, self, "alias:", [aNode], smalltalk.IRASTTranslator)},
 args: ["aNode"],
-source: "alias: aNode\x0a\x09| variable |\x0a\x0a\x09aNode isValueNode ifTrue: [ ^ self visit: aNode ].\x0a\x0a\x09variable := IRVariable new \x0a\x09\x09variable: (AliasVar new name: '$', self nextAlias); \x0a\x09\x09yourself.\x0a\x0a\x09self sequence add: (IRAssignment new\x0a\x09\x09add: variable;\x0a\x09\x09add: (self visit: aNode);\x0a\x09\x09yourself).\x0a\x0a\x09self method internalVariables add: variable.\x0a\x0a\x09^ variable",
-messageSends: ["ifTrue:", "visit:", "isValueNode", "variable:", "name:", ",", "nextAlias", "new", "yourself", "add:", "sequence", "internalVariables", "method"],
+source: "alias: aNode\x0a\x09| variable |\x0a\x0a\x09aNode isImmutable ifTrue: [ ^ self visit: aNode ].\x0a\x0a\x09variable := IRVariable new \x0a\x09\x09variable: (AliasVar new name: '$', self nextAlias); \x0a\x09\x09yourself.\x0a\x0a\x09self sequence add: (IRAssignment new\x0a\x09\x09add: variable;\x0a\x09\x09add: (self visit: aNode);\x0a\x09\x09yourself).\x0a\x0a\x09self method internalVariables add: variable.\x0a\x0a\x09^ variable",
+messageSends: ["ifTrue:", "visit:", "isImmutable", "variable:", "name:", ",", "nextAlias", "new", "yourself", "add:", "sequence", "internalVariables", "method"],
 referencedClasses: ["AliasVar", "IRVariable", "IRAssignment"]
 }),
 smalltalk.IRASTTranslator);
@@ -155,6 +155,46 @@ referencedClasses: []
 }),
 smalltalk.IRASTTranslator);
 
+smalltalk.addMethod(
+"_temporallyDependentList_",
+smalltalk.method({
+selector: "temporallyDependentList:",
+category: 'visiting',
+fn: function (nodes){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1,$3,$2,$4;
+$ctx1.locals.threshold=nil;
+$ctx1.locals.result=nil;
+$ctx1.locals.threshold=(0);
+_st(nodes)._withIndexDo_((function(each,i){
+return smalltalk.withContext(function($ctx2) { 
$1=_st(_st(each)._shouldBeInlined())._or_((function(){
+return smalltalk.withContext(function($ctx3) { 
return _st(each)._shouldBeAliased();
+})}));
+if(smalltalk.assert($1)){
+$ctx1.locals.threshold=i;
+return $ctx1.locals.threshold;
+};
+})}));
+$ctx1.locals.result=_st((smalltalk.OrderedCollection || OrderedCollection))._new();
+_st(nodes)._withIndexDo_((function(each,i){
+return smalltalk.withContext(function($ctx2) { 
$3=_st(i).__lt_eq($ctx1.locals.threshold);
+if(smalltalk.assert($3)){
+$2=_st(self)._alias_(each);
+} else {
+$2=_st(self)._visit_(each);
+};
+return _st($ctx1.locals.result)._add_($2);
+})}));
+$4=$ctx1.locals.result;
+return $4;
+}, self, "temporallyDependentList:", [nodes], smalltalk.IRASTTranslator)},
+args: ["nodes"],
+source: "temporallyDependentList: nodes\x0a\x09| threshold result |\x0a    threshold := 0.\x0a    \x0a    nodes withIndexDo: [ :each :i |\x0a        (each shouldBeInlined or: [ each shouldBeAliased ])\x0a\x09\x09    ifTrue: [ threshold := i ]].\x0a\x0a\x09result := OrderedCollection new.\x0a\x09nodes withIndexDo: [ :each :i | \x0a\x09\x09result add: (i <= threshold\x0a\x09\x09\x09ifTrue: [ self alias: each ]\x0a\x09\x09\x09ifFalse: [ self visit: each ])].\x0a\x0a    ^result",
+messageSends: ["withIndexDo:", "ifTrue:", "or:", "shouldBeAliased", "shouldBeInlined", "new", "add:", "ifTrue:ifFalse:", "alias:", "visit:", "<="],
+referencedClasses: ["OrderedCollection"]
+}),
+smalltalk.IRASTTranslator);
+
 smalltalk.addMethod(
 "_theClass",
 smalltalk.method({
@@ -194,10 +234,10 @@ selector: "visitAssignmentNode:",
 category: 'visiting',
 fn: function (aNode){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2;
-$ctx1.left=nil;
-$ctx1.right=nil;
-$ctx1.assignment=nil;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3;
+$ctx1.locals.left=nil;
+$ctx1.locals.right=nil;
+$ctx1.locals.assignment=nil;
 $ctx1.locals.right=_st(self)._visit_(_st(aNode)._right());
 $ctx1.locals.left=_st(self)._visit_(_st(aNode)._left());
 $1=_st((smalltalk.IRAssignment || IRAssignment))._new();
@@ -205,7 +245,8 @@ _st($1)._add_($ctx1.locals.left);
 _st($1)._add_($ctx1.locals.right);
 $2=_st($1)._yourself();
 _st(_st(self)._sequence())._add_($2);
-return $ctx1.locals.left;
+$3=$ctx1.locals.left;
+return $3;
 }, self, "visitAssignmentNode:", [aNode], smalltalk.IRASTTranslator)},
 args: ["aNode"],
 source: "visitAssignmentNode: aNode\x0a\x09| left right assignment |\x0a\x09right := self visit: aNode right.\x0a\x09left := self visit: aNode left.\x0a\x09self sequence add: (IRAssignment new \x0a\x09\x09add: left;\x0a\x09\x09add: right;\x0a\x09\x09yourself).\x0a\x09^ left",
@@ -221,8 +262,8 @@ selector: "visitBlockNode:",
 category: 'visiting',
 fn: function (aNode){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3,$4;
-$ctx1.closure=nil;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3,$4,$5;
+$ctx1.locals.closure=nil;
 $1=_st((smalltalk.IRClosure || IRClosure))._new();
 _st($1)._arguments_(_st(aNode)._parameters());
 _st($1)._scope_(_st(aNode)._scope());
@@ -238,7 +279,8 @@ return _st($ctx1.locals.closure)._add_($4);
 _st(_st(aNode)._nodes())._do_((function(each){
 return smalltalk.withContext(function($ctx2) { 
return _st($ctx1.locals.closure)._add_(_st(self)._visit_(each));
 })}));
-return $ctx1.locals.closure;
+$5=$ctx1.locals.closure;
+return $5;
 }, self, "visitBlockNode:", [aNode], smalltalk.IRASTTranslator)},
 args: ["aNode"],
 source: "visitBlockNode: aNode\x0a\x09| closure |\x0a\x09closure := IRClosure new\x0a\x09\x09arguments: aNode parameters;\x0a\x09\x09scope: aNode scope;\x0a\x09\x09yourself.\x0a\x09aNode scope temps do: [ :each |\x0a\x09\x09closure add: (IRTempDeclaration new \x0a\x09\x09\x09name: each name;\x0a            scope: aNode scope;\x0a\x09\x09\x09yourself) ].\x0a\x09aNode nodes do: [ :each | closure add: (self visit: each) ].\x0a\x09^ closure",
@@ -288,8 +330,8 @@ category: 'visiting',
 fn: function (aNode){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
var $1,$2;
-$ctx1.alias=nil;
-$1=_st(_st(aNode)._receiver())._isValueNode();
+$ctx1.locals.alias=nil;
+$1=_st(_st(aNode)._receiver())._isImmutable();
 if(! smalltalk.assert($1)){
 $ctx1.locals.alias=_st(self)._alias_(_st(aNode)._receiver());
 $ctx1.locals.alias;
@@ -304,8 +346,8 @@ $2=_st(self)._alias_(_st(_st(aNode)._nodes())._last());
 return $2;
 }, self, "visitCascadeNode:", [aNode], smalltalk.IRASTTranslator)},
 args: ["aNode"],
-source: "visitCascadeNode: aNode\x0a\x09| alias |\x0a\x0a\x09aNode receiver isValueNode ifFalse: [ \x0a\x09\x09alias := self alias: aNode receiver.\x0a\x09\x09aNode nodes do: [ :each |\x0a\x09\x09\x09each receiver: (VariableNode new binding: alias variable) ]].\x0a\x0a\x09aNode nodes allButLast do: [ :each |\x0a\x09\x09self sequence add: (self visit: each) ].\x0a\x0a\x09^ self alias: aNode nodes last",
-messageSends: ["ifFalse:", "alias:", "receiver", "do:", "receiver:", "binding:", "variable", "new", "nodes", "isValueNode", "add:", "visit:", "sequence", "allButLast", "last"],
+source: "visitCascadeNode: aNode\x0a\x09| alias |\x0a\x0a\x09aNode receiver isImmutable ifFalse: [ \x0a\x09\x09alias := self alias: aNode receiver.\x0a\x09\x09aNode nodes do: [ :each |\x0a\x09\x09\x09each receiver: (VariableNode new binding: alias variable) ]].\x0a\x0a\x09aNode nodes allButLast do: [ :each |\x0a\x09\x09self sequence add: (self visit: each) ].\x0a\x0a\x09^ self alias: aNode nodes last",
+messageSends: ["ifFalse:", "alias:", "receiver", "do:", "receiver:", "binding:", "variable", "new", "nodes", "isImmutable", "add:", "visit:", "sequence", "allButLast", "last"],
 referencedClasses: ["VariableNode"]
 }),
 smalltalk.IRASTTranslator);
@@ -317,12 +359,14 @@ selector: "visitDynamicArrayNode:",
 category: 'visiting',
 fn: function (aNode){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
$ctx1.array=nil;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$ctx1.locals.array=nil;
 $ctx1.locals.array=_st((smalltalk.IRDynamicArray || IRDynamicArray))._new();
 _st(_st(aNode)._nodes())._do_((function(each){
 return smalltalk.withContext(function($ctx2) { 
return _st($ctx1.locals.array)._add_(_st(self)._visit_(each));
 })}));
-return $ctx1.locals.array;
+$1=$ctx1.locals.array;
+return $1;
 }, self, "visitDynamicArrayNode:", [aNode], smalltalk.IRASTTranslator)},
 args: ["aNode"],
 source: "visitDynamicArrayNode: aNode\x0a\x09| array |\x0a\x09array := IRDynamicArray new.\x0a\x09aNode nodes do: [ :each | array add: (self visit: each) ].\x0a\x09^ array",
@@ -338,12 +382,14 @@ selector: "visitDynamicDictionaryNode:",
 category: 'visiting',
 fn: function (aNode){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
$ctx1.dictionary=nil;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$ctx1.locals.dictionary=nil;
 $ctx1.locals.dictionary=_st((smalltalk.IRDynamicDictionary || IRDynamicDictionary))._new();
 _st(_st(aNode)._nodes())._do_((function(each){
 return smalltalk.withContext(function($ctx2) { 
return _st($ctx1.locals.dictionary)._add_(_st(self)._visit_(each));
 })}));
-return $ctx1.locals.dictionary;
+$1=$ctx1.locals.dictionary;
+return $1;
 }, self, "visitDynamicDictionaryNode:", [aNode], smalltalk.IRASTTranslator)},
 args: ["aNode"],
 source: "visitDynamicDictionaryNode: aNode\x0a\x09| dictionary |\x0a\x09dictionary := IRDynamicDictionary new.\x0a\x09aNode nodes do: [ :each | dictionary add: (self visit: each) ].\x0a\x09^ dictionary",
@@ -426,8 +472,8 @@ selector: "visitReturnNode:",
 category: 'visiting',
 fn: function (aNode){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
-$ctx1.return=nil;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
+$ctx1.locals.return=nil;
 $1=_st(aNode)._nonLocalReturn();
 if(smalltalk.assert($1)){
 $ctx1.locals.return_=_st((smalltalk.IRNonLocalReturn || IRNonLocalReturn))._new();
@@ -438,7 +484,8 @@ _st($ctx1.locals.return_)._scope_(_st(aNode)._scope());
 _st(_st(aNode)._nodes())._do_((function(each){
 return smalltalk.withContext(function($ctx2) { 
return _st($ctx1.locals.return_)._add_(_st(self)._alias_(each));
 })}));
-return $ctx1.locals.return_;
+$2=$ctx1.locals.return_;
+return $2;
 }, self, "visitReturnNode:", [aNode], smalltalk.IRASTTranslator)},
 args: ["aNode"],
 source: "visitReturnNode: aNode\x0a\x09| return |\x0a\x09return := aNode nonLocalReturn \x0a\x09\x09ifTrue: [ IRNonLocalReturn new ]\x0a\x09\x09ifFalse: [ IRReturn new ].\x0a\x09return scope: aNode scope.\x0a\x09aNode nodes do: [ :each |\x0a\x09\x09return add: (self alias: each) ].\x0a\x09^ return",
@@ -455,41 +502,31 @@ category: 'visiting',
 fn: function (aNode){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3,$4;
-$ctx1.send=nil;
-$ctx1.receiver=nil;
-$ctx1.arguments=nil;
+$ctx1.locals.send=nil;
+$ctx1.locals.all=nil;
+$ctx1.locals.receiver=nil;
+$ctx1.locals.arguments=nil;
 $ctx1.locals.send=_st((smalltalk.IRSend || IRSend))._new();
-_st($ctx1.locals.send)._selector_(_st(aNode)._selector());
-$1=_st($ctx1.locals.send)._index_(_st(aNode)._index());
-$2=_st(aNode)._superSend();
-if(smalltalk.assert($2)){
-_st($ctx1.locals.send)._classSend_(_st(_st(self)._theClass())._superclass());
-};
-$3=_st(_st(_st(aNode)._receiver())._shouldBeInlined())._or_((function(){
-return smalltalk.withContext(function($ctx2) { 
return _st(_st(aNode)._receiver())._shouldBeAliased();
-})}));
+$1=$ctx1.locals.send;
+_st($1)._selector_(_st(aNode)._selector());
+$2=_st($1)._index_(_st(aNode)._index());
+$3=_st(aNode)._superSend();
 if(smalltalk.assert($3)){
-$ctx1.locals.receiver=_st(self)._alias_(_st(aNode)._receiver());
-} else {
-$ctx1.locals.receiver=_st(self)._visit_(_st(aNode)._receiver());
-};
-$ctx1.locals.arguments=_st(_st(aNode)._arguments())._collect_((function(each){
-return smalltalk.withContext(function($ctx2) { 
$4=_st(each)._shouldBeInlined();
-if(smalltalk.assert($4)){
-return _st(self)._alias_(each);
-} else {
-return _st(self)._visit_(each);
+_st($ctx1.locals.send)._classSend_(_st(_st(self)._theClass())._superclass());
 };
-})}));
+$ctx1.locals.all=_st(self)._temporallyDependentList_(_st([_st(aNode)._receiver()]).__comma(_st(aNode)._arguments()));
+$ctx1.locals.receiver=_st($ctx1.locals.all)._first();
+$ctx1.locals.arguments=_st($ctx1.locals.all)._allButFirst();
 _st($ctx1.locals.send)._add_($ctx1.locals.receiver);
 _st($ctx1.locals.arguments)._do_((function(each){
 return smalltalk.withContext(function($ctx2) { 
return _st($ctx1.locals.send)._add_(each);
 })}));
-return $ctx1.locals.send;
+$4=$ctx1.locals.send;
+return $4;
 }, self, "visitSendNode:", [aNode], smalltalk.IRASTTranslator)},
 args: ["aNode"],
-source: "visitSendNode: aNode\x0a\x09| send receiver arguments |\x0a\x09send := IRSend new.\x0a\x09send \x0a\x09\x09selector: aNode selector;\x0a\x09\x09index: aNode index.\x0a\x09aNode superSend ifTrue: [ send classSend: self theClass superclass ].\x0a\x0a\x09receiver := (aNode receiver shouldBeInlined or: [ aNode receiver shouldBeAliased ])\x0a\x09\x09ifTrue: [ self alias: aNode receiver ]\x0a\x09\x09ifFalse: [ self visit: aNode receiver ].\x0a\x0a\x09arguments := aNode arguments collect: [ :each | \x0a\x09\x09each shouldBeInlined\x0a\x09\x09\x09ifTrue: [ self alias: each ]\x0a\x09\x09\x09ifFalse: [ self visit: each ]].\x0a\x0a\x09send add: receiver.\x0a\x09arguments do: [ :each | send add: each ].\x0a\x0a\x09^ send",
-messageSends: ["new", "selector:", "selector", "index:", "index", "ifTrue:", "classSend:", "superclass", "theClass", "superSend", "ifTrue:ifFalse:", "alias:", "receiver", "visit:", "or:", "shouldBeAliased", "shouldBeInlined", "collect:", "arguments", "add:", "do:"],
+source: "visitSendNode: aNode\x0a\x09| send all receiver arguments |\x0a\x09send := IRSend new.\x0a\x09send \x0a\x09\x09selector: aNode selector;\x0a\x09\x09index: aNode index.\x0a\x09aNode superSend ifTrue: [ send classSend: self theClass superclass ].\x0a    \x0a    all := self temporallyDependentList: { aNode receiver }, aNode arguments.\x0a\x09receiver := all first.\x0a\x09arguments := all allButFirst.\x0a\x0a\x09send add: receiver.\x0a\x09arguments do: [ :each | send add: each ].\x0a\x0a\x09^ send",
+messageSends: ["new", "selector:", "selector", "index:", "index", "ifTrue:", "classSend:", "superclass", "theClass", "superSend", "temporallyDependentList:", ",", "arguments", "receiver", "first", "allButFirst", "add:", "do:"],
 referencedClasses: ["IRSend"]
 }),
 smalltalk.IRASTTranslator);
@@ -504,7 +541,7 @@ var self=this;
 return smalltalk.withContext(function($ctx1) { 
var $2,$1;
 $1=_st(self)._withSequence_do_(_st((smalltalk.IRSequence || IRSequence))._new(),(function(){
 return smalltalk.withContext(function($ctx2) { 
return _st(_st(aNode)._nodes())._do_((function(each){
-return smalltalk.withContext(function($ctx3) { 
$ctx3.instruction=nil;
+return smalltalk.withContext(function($ctx3) { 
$ctx3.locals.instruction=nil;
 $ctx3.locals.instruction=_st(self)._visit_(each);
 $ctx3.locals.instruction;
 $2=_st($ctx3.locals.instruction)._isVariable();
@@ -571,7 +608,7 @@ selector: "withSequence:do:",
 category: 'accessing',
 fn: function (aSequence,aBlock){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
$ctx1.outerSequence=nil;
+return smalltalk.withContext(function($ctx1) { 
$ctx1.locals.outerSequence=nil;
 $ctx1.locals.outerSequence=_st(self)._sequence();
 _st(self)._sequence_(aSequence);
 _st(aBlock)._value();
@@ -588,7 +625,7 @@ smalltalk.IRASTTranslator);
 
 
 smalltalk.addClass('IRInstruction', smalltalk.Object, ['parent', 'instructions'], 'Compiler-IR');
-smalltalk.IRInstruction.comment="I am the abstract root class of the IR (intermediate representation) instructions class hierarchy.\x0aThe IR graph is used to emit JavaScript code using a JSStream. "
+smalltalk.IRInstruction.comment="I am the abstract root class of the IR (intermediate representation) instructions class hierarchy.\x0aThe IR graph is used to emit JavaScript code using a JSStream."
 smalltalk.addMethod(
 "_accept_",
 smalltalk.method({
@@ -800,7 +837,9 @@ selector: "parent",
 category: 'accessing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@parent"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@parent"];
+return $1;
 }, self, "parent", [], smalltalk.IRInstruction)},
 args: [],
 source: "parent\x0a\x09^ parent",
@@ -984,7 +1023,9 @@ selector: "scope",
 category: 'accessing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@scope"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@scope"];
+return $1;
 }, self, "scope", [], smalltalk.IRScopedInstruction)},
 args: [],
 source: "scope\x0a\x09^ scope",
@@ -1148,7 +1189,9 @@ selector: "arguments",
 category: 'accessing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@arguments"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@arguments"];
+return $1;
 }, self, "arguments", [], smalltalk.IRMethod)},
 args: [],
 source: "arguments\x0a\x09^ arguments",
@@ -1180,7 +1223,9 @@ selector: "classReferences",
 category: 'accessing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@classReferences"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@classReferences"];
+return $1;
 }, self, "classReferences", [], smalltalk.IRMethod)},
 args: [],
 source: "classReferences\x0a\x09^ classReferences",
@@ -1235,7 +1280,9 @@ selector: "messageSends",
 category: 'accessing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@messageSends"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@messageSends"];
+return $1;
 }, self, "messageSends", [], smalltalk.IRMethod)},
 args: [],
 source: "messageSends\x0a\x09^ messageSends",
@@ -1284,7 +1331,9 @@ selector: "selector",
 category: 'accessing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@selector"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@selector"];
+return $1;
 }, self, "selector", [], smalltalk.IRMethod)},
 args: [],
 source: "selector\x0a\x09^ selector",
@@ -1316,7 +1365,9 @@ selector: "source",
 category: 'accessing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@source"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@source"];
+return $1;
 }, self, "source", [], smalltalk.IRMethod)},
 args: [],
 source: "source\x0a\x09^ source",
@@ -1348,7 +1399,9 @@ selector: "superSends",
 category: 'accessing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@superSends"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@superSends"];
+return $1;
 }, self, "superSends", [], smalltalk.IRMethod)},
 args: [],
 source: "superSends\x0a\x09^ superSends",
@@ -1380,7 +1433,9 @@ selector: "theClass",
 category: 'accessing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@theClass"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@theClass"];
+return $1;
 }, self, "theClass", [], smalltalk.IRMethod)},
 args: [],
 source: "theClass\x0a\x09^ theClass",
@@ -1613,7 +1668,9 @@ selector: "name",
 category: 'accessing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@name"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@name"];
+return $1;
 }, self, "name", [], smalltalk.IRTempDeclaration)},
 args: [],
 source: "name\x0a\x09^ name",
@@ -1641,7 +1698,7 @@ smalltalk.IRTempDeclaration);
 
 
 smalltalk.addClass('IRSend', smalltalk.IRInstruction, ['selector', 'classSend', 'index'], 'Compiler-IR');
-smalltalk.IRSend.comment="I am a message send instruction. "
+smalltalk.IRSend.comment="I am a message send instruction."
 smalltalk.addMethod(
 "_accept_",
 smalltalk.method({
@@ -1667,7 +1724,9 @@ selector: "classSend",
 category: 'accessing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@classSend"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@classSend"];
+return $1;
 }, self, "classSend", [], smalltalk.IRSend)},
 args: [],
 source: "classSend\x0a\x09^ classSend",
@@ -1699,7 +1758,9 @@ selector: "index",
 category: 'accessing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@index"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@index"];
+return $1;
 }, self, "index", [], smalltalk.IRSend)},
 args: [],
 source: "index\x0a\x09^ index",
@@ -1770,7 +1831,9 @@ selector: "selector",
 category: 'accessing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@selector"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@selector"];
+return $1;
 }, self, "selector", [], smalltalk.IRSend)},
 args: [],
 source: "selector\x0a\x09^ selector",
@@ -1882,7 +1945,9 @@ selector: "value",
 category: 'accessing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@value"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@value"];
+return $1;
 }, self, "value", [], smalltalk.IRValue)},
 args: [],
 source: "value\x0a\x09^value",
@@ -1952,7 +2017,9 @@ selector: "variable",
 category: 'accessing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@variable"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@variable"];
+return $1;
 }, self, "variable", [], smalltalk.IRVariable)},
 args: [],
 source: "variable\x0a\x09^ variable",
@@ -2005,7 +2072,9 @@ selector: "source",
 category: 'accessing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@source"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@source"];
+return $1;
 }, self, "source", [], smalltalk.IRVerbatim)},
 args: [],
 source: "source\x0a\x09^ source",
@@ -2202,10 +2271,12 @@ selector: "visitIRInstruction:",
 category: 'visiting',
 fn: function (anIRInstruction){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
_st(_st(anIRInstruction)._instructions())._do_((function(each){
+return smalltalk.withContext(function($ctx1) { 
var $1;
+_st(_st(anIRInstruction)._instructions())._do_((function(each){
 return smalltalk.withContext(function($ctx2) { 
return _st(self)._visit_(each);
 })}));
-return anIRInstruction;
+$1=anIRInstruction;
+return $1;
 }, self, "visitIRInstruction:", [anIRInstruction], smalltalk.IRVisitor)},
 args: ["anIRInstruction"],
 source: "visitIRInstruction: anIRInstruction\x0a\x09anIRInstruction instructions do: [ :each | self visit: each ].\x0a\x09^ anIRInstruction",
@@ -2439,7 +2510,9 @@ selector: "stream",
 category: 'accessing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@stream"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@stream"];
+return $1;
 }, self, "stream", [], smalltalk.IRJSTranslator)},
 args: [],
 source: "stream\x0a\x09^ stream",
@@ -2864,9 +2937,10 @@ selector: "nextPutBlockContextFor:during:",
 category: 'streaming',
 fn: function (anIRClosure,aBlock){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
-_st(self)._nextPutAll_(_st(_st("return smalltalk.withContext(function(").__comma(_st(_st(anIRClosure)._scope())._alias())).__comma(") { "));
-$1=_st(self)._nextPutAll_(_st((smalltalk.String || String))._cr());
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
+$1=self;
+_st($1)._nextPutAll_(_st(_st("return smalltalk.withContext(function(").__comma(_st(_st(anIRClosure)._scope())._alias())).__comma(") { "));
+$2=_st($1)._nextPutAll_(_st((smalltalk.String || String))._cr());
 _st(aBlock)._value();
 _st(self)._nextPutAll_("})");
 return self}, self, "nextPutBlockContextFor:during:", [anIRClosure,aBlock], smalltalk.JSStream)},
@@ -2884,15 +2958,16 @@ selector: "nextPutClosureWith:arguments:",
 category: 'streaming',
 fn: function (aBlock,anArray){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
 _st(self["@stream"])._nextPutAll_("(function(");
 _st(anArray)._do_separatedBy_((function(each){
 return smalltalk.withContext(function($ctx2) { 
return _st(self["@stream"])._nextPutAll_(_st(each)._asVariableName());
 })}),(function(){
 return smalltalk.withContext(function($ctx2) { 
return _st(self["@stream"])._nextPut_(",");
 })}));
-_st(self["@stream"])._nextPutAll_("){");
-$1=_st(self["@stream"])._lf();
+$1=self["@stream"];
+_st($1)._nextPutAll_("){");
+$2=_st($1)._lf();
 _st(aBlock)._value();
 _st(self["@stream"])._nextPutAll_("})");
 return self}, self, "nextPutClosureWith:arguments:", [aBlock,anArray], smalltalk.JSStream)},
@@ -2910,20 +2985,23 @@ selector: "nextPutContextFor:during:",
 category: 'streaming',
 fn: function (aMethod,aBlock){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3;
-_st(self)._nextPutAll_(_st(_st("return smalltalk.withContext(function(").__comma(_st(_st(aMethod)._scope())._alias())).__comma(") { "));
-$1=_st(self)._nextPutAll_(_st((smalltalk.String || String))._cr());
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3,$4,$5,$6;
+$1=self;
+_st($1)._nextPutAll_(_st(_st("return smalltalk.withContext(function(").__comma(_st(_st(aMethod)._scope())._alias())).__comma(") { "));
+$2=_st($1)._nextPutAll_(_st((smalltalk.String || String))._cr());
 _st(aBlock)._value();
-_st(self)._nextPutAll_("}, self, ");
-$2=_st(self)._nextPutAll_(_st(_st(_st(aMethod)._selector())._asJavascript()).__comma(", ["));
+$3=self;
+_st($3)._nextPutAll_("}, self, ");
+$4=_st($3)._nextPutAll_(_st(_st(_st(aMethod)._selector())._asJavascript()).__comma(", ["));
 _st(_st(aMethod)._arguments())._do_separatedBy_((function(each){
 return smalltalk.withContext(function($ctx2) { 
return _st(self)._nextPutAll_(_st(each)._asVariableName());
 })}),(function(){
 return smalltalk.withContext(function($ctx2) { 
return _st(self)._nextPutAll_(",");
 })}));
-_st(self)._nextPutAll_("], ");
-_st(self)._nextPutAll_(_st(_st(aMethod)._theClass())._asJavascript());
-$3=_st(self)._nextPutAll_(")");
+$5=self;
+_st($5)._nextPutAll_("], ");
+_st($5)._nextPutAll_(_st(_st(aMethod)._theClass())._asJavascript());
+$6=_st($5)._nextPutAll_(")");
 return self}, self, "nextPutContextFor:during:", [aMethod,aBlock], smalltalk.JSStream)},
 args: ["aMethod", "aBlock"],
 source: "nextPutContextFor: aMethod during: aBlock\x0a\x09self \x0a    \x09nextPutAll: 'return smalltalk.withContext(function(', aMethod scope alias, ') { '; \x0a        nextPutAll: String cr.\x0a    aBlock value.\x0a    self \x0a    \x09nextPutAll: '}, self, ';\x0a        nextPutAll: aMethod selector asJavascript, ', ['.\x0a    aMethod arguments \x0a    \x09do: [ :each | self nextPutAll: each asVariableName ]\x0a      \x09separatedBy: [ self nextPutAll: ','  ].\x0a    self nextPutAll: '], ';\x0a        nextPutAll: aMethod theClass asJavascript;\x0a        nextPutAll: ')'",
@@ -2939,17 +3017,19 @@ selector: "nextPutFunctionWith:arguments:",
 category: 'streaming',
 fn: function (aBlock,anArray){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3,$4;
 _st(self["@stream"])._nextPutAll_("fn: function(");
 _st(anArray)._do_separatedBy_((function(each){
 return smalltalk.withContext(function($ctx2) { 
return _st(self["@stream"])._nextPutAll_(_st(each)._asVariableName());
 })}),(function(){
 return smalltalk.withContext(function($ctx2) { 
return _st(self["@stream"])._nextPut_(",");
 })}));
-_st(self["@stream"])._nextPutAll_("){");
-$1=_st(self["@stream"])._lf();
-_st(self["@stream"])._nextPutAll_("var self=this;");
-$2=_st(self["@stream"])._lf();
+$1=self["@stream"];
+_st($1)._nextPutAll_("){");
+$2=_st($1)._lf();
+$3=self["@stream"];
+_st($3)._nextPutAll_("var self=this;");
+$4=_st($3)._lf();
 _st(aBlock)._value();
 _st(self["@stream"])._nextPutAll_("}");
 return self}, self, "nextPutFunctionWith:arguments:", [aBlock,anArray], smalltalk.JSStream)},
@@ -2967,11 +3047,12 @@ selector: "nextPutIf:with:",
 category: 'streaming',
 fn: function (aBlock,anotherBlock){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
 _st(self["@stream"])._nextPutAll_("if(");
 _st(aBlock)._value();
-_st(self["@stream"])._nextPutAll_("){");
-$1=_st(self["@stream"])._lf();
+$1=self["@stream"];
+_st($1)._nextPutAll_("){");
+$2=_st($1)._lf();
 _st(anotherBlock)._value();
 _st(self["@stream"])._nextPutAll_("}");
 return self}, self, "nextPutIf:with:", [aBlock,anotherBlock], smalltalk.JSStream)},
@@ -2989,14 +3070,16 @@ selector: "nextPutIfElse:with:with:",
 category: 'streaming',
 fn: function (aBlock,ifBlock,elseBlock){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3,$4;
 _st(self["@stream"])._nextPutAll_("if(");
 _st(aBlock)._value();
-_st(self["@stream"])._nextPutAll_("){");
-$1=_st(self["@stream"])._lf();
+$1=self["@stream"];
+_st($1)._nextPutAll_("){");
+$2=_st($1)._lf();
 _st(ifBlock)._value();
-_st(self["@stream"])._nextPutAll_("} else {");
-$2=_st(self["@stream"])._lf();
+$3=self["@stream"];
+_st($3)._nextPutAll_("} else {");
+$4=_st($3)._lf();
 _st(elseBlock)._value();
 _st(self["@stream"])._nextPutAll_("}");
 return self}, self, "nextPutIfElse:with:with:", [aBlock,ifBlock,elseBlock], smalltalk.JSStream)},
@@ -3014,29 +3097,32 @@ selector: "nextPutMethodDeclaration:with:",
 category: 'streaming',
 fn: function (aMethod,aBlock){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3;
-_st(self["@stream"])._nextPutAll_("smalltalk.method({");
-_st(self["@stream"])._lf();
-_st(self["@stream"])._nextPutAll_(_st(_st("selector: \x22").__comma(_st(aMethod)._selector())).__comma("\x22,"));
-_st(self["@stream"])._lf();
-_st(self["@stream"])._nextPutAll_(_st(_st("source: ").__comma(_st(_st(aMethod)._source())._asJavascript())).__comma(","));
-$1=_st(self["@stream"])._lf();
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3,$4,$5,$6;
+$1=self["@stream"];
+_st($1)._nextPutAll_("smalltalk.method({");
+_st($1)._lf();
+_st($1)._nextPutAll_(_st(_st("selector: \x22").__comma(_st(aMethod)._selector())).__comma("\x22,"));
+_st($1)._lf();
+_st($1)._nextPutAll_(_st(_st("source: ").__comma(_st(_st(aMethod)._source())._asJavascript())).__comma(","));
+$2=_st($1)._lf();
 _st(aBlock)._value();
-_st(self["@stream"])._nextPutAll_(_st(_st(",").__comma(_st((smalltalk.String || String))._lf())).__comma("messageSends: "));
-_st(self["@stream"])._nextPutAll_(_st(_st(_st(_st(aMethod)._messageSends())._asArray())._asJavascript()).__comma(","));
-_st(self["@stream"])._lf();
-_st(self["@stream"])._nextPutAll_(_st(_st("args: ").__comma(_st(_st(_st(_st(aMethod)._arguments())._collect_((function(each){
+$3=self["@stream"];
+_st($3)._nextPutAll_(_st(_st(",").__comma(_st((smalltalk.String || String))._lf())).__comma("messageSends: "));
+_st($3)._nextPutAll_(_st(_st(_st(_st(aMethod)._messageSends())._asArray())._asJavascript()).__comma(","));
+_st($3)._lf();
+_st($3)._nextPutAll_(_st(_st("args: ").__comma(_st(_st(_st(_st(aMethod)._arguments())._collect_((function(each){
 return smalltalk.withContext(function($ctx2) { 
return _st(each)._value();
 })})))._asArray())._asJavascript())).__comma(","));
-_st(self["@stream"])._lf();
-$2=_st(self["@stream"])._nextPutAll_("referencedClasses: [");
+_st($3)._lf();
+$4=_st($3)._nextPutAll_("referencedClasses: [");
 _st(_st(aMethod)._classReferences())._do_separatedBy_((function(each){
 return smalltalk.withContext(function($ctx2) { 
return _st(self["@stream"])._nextPutAll_(_st(each)._asJavascript());
 })}),(function(){
 return smalltalk.withContext(function($ctx2) { 
return _st(self["@stream"])._nextPutAll_(",");
 })}));
-_st(self["@stream"])._nextPutAll_("]");
-$3=_st(self["@stream"])._nextPutAll_("})");
+$5=self["@stream"];
+_st($5)._nextPutAll_("]");
+$6=_st($5)._nextPutAll_("})");
 return self}, self, "nextPutMethodDeclaration:with:", [aMethod,aBlock], smalltalk.JSStream)},
 args: ["aMethod", "aBlock"],
 source: "nextPutMethodDeclaration: aMethod with: aBlock\x0a\x09stream \x0a\x09\x09nextPutAll: 'smalltalk.method({'; lf;\x0a\x09\x09nextPutAll: 'selector: \x22', aMethod selector, '\x22,'; lf;\x0a\x09\x09nextPutAll: 'source: ', aMethod source asJavascript, ',';lf. \x0a\x09aBlock value.\x0a\x09stream \x0a\x09\x09nextPutAll: ',', String lf, 'messageSends: ';\x0a\x09\x09nextPutAll: aMethod messageSends asArray asJavascript, ','; lf;\x0a        nextPutAll: 'args: ', (aMethod arguments collect: [ :each | each value ]) asArray asJavascript, ','; lf;\x0a\x09\x09nextPutAll: 'referencedClasses: ['.\x0a\x09aMethod classReferences \x0a\x09\x09do: [:each | stream nextPutAll: each asJavascript]\x0a\x09\x09separatedBy: [stream nextPutAll: ','].\x0a\x09stream \x0a\x09\x09nextPutAll: ']';\x0a\x09\x09nextPutAll: '})'",
@@ -3052,16 +3138,18 @@ selector: "nextPutNonLocalReturnHandlingWith:",
 category: 'streaming',
 fn: function (aBlock){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2;
-_st(self["@stream"])._nextPutAll_("var $early={};");
-_st(self["@stream"])._lf();
-_st(self["@stream"])._nextPutAll_("try {");
-$1=_st(self["@stream"])._lf();
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3,$4;
+$1=self["@stream"];
+_st($1)._nextPutAll_("var $early={};");
+_st($1)._lf();
+_st($1)._nextPutAll_("try {");
+$2=_st($1)._lf();
 _st(aBlock)._value();
-_st(self["@stream"])._nextPutAll_("}");
-_st(self["@stream"])._lf();
-_st(self["@stream"])._nextPutAll_("catch(e) {if(e===$early)return e[0]; throw e}");
-$2=_st(self["@stream"])._lf();
+$3=self["@stream"];
+_st($3)._nextPutAll_("}");
+_st($3)._lf();
+_st($3)._nextPutAll_("catch(e) {if(e===$early)return e[0]; throw e}");
+$4=_st($3)._lf();
 return self}, self, "nextPutNonLocalReturnHandlingWith:", [aBlock], smalltalk.JSStream)},
 args: ["aBlock"],
 source: "nextPutNonLocalReturnHandlingWith: aBlock\x0a\x09stream \x0a\x09\x09nextPutAll: 'var $early={};'; lf;\x0a\x09\x09nextPutAll: 'try {'; lf.\x0a\x09aBlock value.\x0a\x09stream \x0a\x09\x09nextPutAll: '}'; lf;\x0a\x09\x09nextPutAll: 'catch(e) {if(e===$early)return e[0]; throw e}'; lf",
@@ -3144,12 +3232,14 @@ selector: "nextPutStatement:with:",
 category: 'streaming',
 fn: function (anInteger,aBlock){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2;
-_st(self["@stream"])._nextPutAll_(_st(_st("case ").__comma(_st(anInteger)._asString())).__comma(":"));
-$1=_st(self["@stream"])._lf();
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3,$4;
+$1=self["@stream"];
+_st($1)._nextPutAll_(_st(_st("case ").__comma(_st(anInteger)._asString())).__comma(":"));
+$2=_st($1)._lf();
 _st(self)._nextPutStatementWith_(aBlock);
-_st(self["@stream"])._nextPutAll_(_st(_st("smalltalk.thisContext.pc=").__comma(_st(_st(anInteger).__plus((1)))._asString())).__comma(";"));
-$2=_st(self["@stream"])._lf();
+$3=self["@stream"];
+_st($3)._nextPutAll_(_st(_st("smalltalk.thisContext.pc=").__comma(_st(_st(anInteger).__plus((1)))._asString())).__comma(";"));
+$4=_st($3)._lf();
 return self}, self, "nextPutStatement:with:", [anInteger,aBlock], smalltalk.JSStream)},
 args: ["anInteger", "aBlock"],
 source: "nextPutStatement: anInteger with: aBlock\x0a\x09stream nextPutAll: 'case ', anInteger asString, ':'; lf.\x0a\x09self nextPutStatementWith: aBlock.\x0a\x09stream nextPutAll: 'smalltalk.thisContext.pc=', (anInteger + 1) asString, ';'; lf",
@@ -3165,10 +3255,11 @@ selector: "nextPutStatementWith:",
 category: 'streaming',
 fn: function (aBlock){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
 _st(aBlock)._value();
-_st(self["@stream"])._nextPutAll_(";");
-$1=_st(self["@stream"])._lf();
+$1=self["@stream"];
+_st($1)._nextPutAll_(";");
+$2=_st($1)._lf();
 return self}, self, "nextPutStatementWith:", [aBlock], smalltalk.JSStream)},
 args: ["aBlock"],
 source: "nextPutStatementWith: aBlock\x0a\x09aBlock value.\x0a\x09stream nextPutAll: ';'; lf",
@@ -3184,9 +3275,10 @@ selector: "nextPutVar:",
 category: 'streaming',
 fn: function (aString){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
-_st(self["@stream"])._nextPutAll_(_st(_st("var ").__comma(aString)).__comma(";"));
-$1=_st(self["@stream"])._lf();
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
+$1=self["@stream"];
+_st($1)._nextPutAll_(_st(_st("var ").__comma(aString)).__comma(";"));
+$2=_st($1)._lf();
 return self}, self, "nextPutVar:", [aString], smalltalk.JSStream)},
 args: ["aString"],
 source: "nextPutVar: aString\x0a\x09stream nextPutAll: 'var ', aString, ';'; lf",
@@ -3202,15 +3294,16 @@ selector: "nextPutVars:",
 category: 'streaming',
 fn: function (aCollection){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
 _st(self["@stream"])._nextPutAll_("var ");
 _st(aCollection)._do_separatedBy_((function(each){
 return smalltalk.withContext(function($ctx2) { 
return _st(self["@stream"])._nextPutAll_(each);
 })}),(function(){
 return smalltalk.withContext(function($ctx2) { 
return _st(self["@stream"])._nextPutAll_(",");
 })}));
-_st(self["@stream"])._nextPutAll_(";");
-$1=_st(self["@stream"])._lf();
+$1=self["@stream"];
+_st($1)._nextPutAll_(";");
+$2=_st($1)._lf();
 return self}, self, "nextPutVars:", [aCollection], smalltalk.JSStream)},
 args: ["aCollection"],
 source: "nextPutVars: aCollection\x0a\x09stream nextPutAll: 'var '.\x0a\x09aCollection \x0a\x09\x09do: [ :each | stream nextPutAll: each ]\x0a\x09\x09separatedBy: [ stream nextPutAll: ',' ].\x0a\x09stream nextPutAll: ';'; lf",

+ 47 - 30
js/Compiler-Semantic.deploy.js

@@ -108,7 +108,9 @@ smalltalk.method({
 selector: "instruction",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@instruction"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@instruction"];
+return $1;
 }, self, "instruction", [], smalltalk.LexicalScope)}
 }),
 smalltalk.LexicalScope);
@@ -169,8 +171,8 @@ smalltalk.method({
 selector: "lookupVariable:",
 fn: function (aNode){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
-$ctx1.lookup=nil;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
+$ctx1.locals.lookup=nil;
 $ctx1.locals.lookup=_st(self)._bindingFor_(aNode);
 if(($receiver = $ctx1.locals.lookup) == nil || $receiver == undefined){
 $1=_st(self)._outerScope();
@@ -183,7 +185,8 @@ $ctx1.locals.lookup;
 } else {
 $ctx1.locals.lookup;
 };
-return $ctx1.locals.lookup;
+$2=$ctx1.locals.lookup;
+return $2;
 }, self, "lookupVariable:", [aNode], smalltalk.LexicalScope)}
 }),
 smalltalk.LexicalScope);
@@ -212,7 +215,9 @@ smalltalk.method({
 selector: "node",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@node"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@node"];
+return $1;
 }, self, "node", [], smalltalk.LexicalScope)}
 }),
 smalltalk.LexicalScope);
@@ -234,7 +239,9 @@ smalltalk.method({
 selector: "outerScope",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@outerScope"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@outerScope"];
+return $1;
 }, self, "outerScope", [], smalltalk.LexicalScope)}
 }),
 smalltalk.LexicalScope);
@@ -464,7 +471,9 @@ smalltalk.method({
 selector: "methodScope",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self;
+return $1;
 }, self, "methodScope", [], smalltalk.MethodLexicalScope)}
 }),
 smalltalk.MethodLexicalScope);
@@ -493,7 +502,7 @@ smalltalk.method({
 selector: "pseudoVars",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3;
 if(($receiver = self["@pseudoVars"]) == nil || $receiver == undefined){
 self["@pseudoVars"]=_st((smalltalk.Dictionary || Dictionary))._new();
 self["@pseudoVars"];
@@ -506,7 +515,8 @@ return _st(self["@pseudoVars"])._at_put_(each,$2);
 } else {
 self["@pseudoVars"];
 };
-return self["@pseudoVars"];
+$3=self["@pseudoVars"];
+return $3;
 }, self, "pseudoVars", [], smalltalk.MethodLexicalScope)}
 }),
 smalltalk.MethodLexicalScope);
@@ -629,7 +639,9 @@ smalltalk.method({
 selector: "name",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@name"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@name"];
+return $1;
 }, self, "name", [], smalltalk.ScopeVar)}
 }),
 smalltalk.ScopeVar);
@@ -651,7 +663,9 @@ smalltalk.method({
 selector: "scope",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@scope"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@scope"];
+return $1;
 }, self, "scope", [], smalltalk.ScopeVar)}
 }),
 smalltalk.ScopeVar);
@@ -712,7 +726,9 @@ smalltalk.method({
 selector: "node",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@node"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@node"];
+return $1;
 }, self, "node", [], smalltalk.AliasVar)}
 }),
 smalltalk.AliasVar);
@@ -1043,7 +1059,9 @@ smalltalk.method({
 selector: "theClass",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@theClass"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@theClass"];
+return $1;
 }, self, "theClass", [], smalltalk.SemanticAnalyzer)}
 }),
 smalltalk.SemanticAnalyzer);
@@ -1150,7 +1168,7 @@ smalltalk.method({
 selector: "visitMethodNode:",
 fn: function (aNode){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
 _st(self)._pushScope_(_st(self)._newMethodScope());
 _st(aNode)._scope_(self["@currentScope"]);
 _st(self["@currentScope"])._node_(aNode);
@@ -1162,9 +1180,10 @@ return smalltalk.withContext(function($ctx2) { 
_st(self)._validateVariableScope
 return _st(self["@currentScope"])._addArg_(each);
 })}));
 smalltalk.NodeVisitor.fn.prototype._visitMethodNode_.apply(_st(self), [aNode]);
-_st(aNode)._classReferences_(_st(self)._classReferences());
-_st(aNode)._messageSends_(_st(_st(self)._messageSends())._keys());
-$1=_st(aNode)._superSends_(_st(_st(self)._superSends())._keys());
+$1=aNode;
+_st($1)._classReferences_(_st(self)._classReferences());
+_st($1)._messageSends_(_st(_st(self)._messageSends())._keys());
+$2=_st($1)._superSends_(_st(_st(self)._superSends())._keys());
 _st(self)._popScope();
 return self}, self, "visitMethodNode:", [aNode], smalltalk.SemanticAnalyzer)}
 }),
@@ -1195,7 +1214,7 @@ smalltalk.method({
 selector: "visitSendNode:",
 fn: function (aNode){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
 $1=_st(_st(_st(aNode)._receiver())._value()).__eq("super");
 if(smalltalk.assert($1)){
 _st(aNode)._superSend_(true);
@@ -1208,12 +1227,9 @@ _st(_st(_st(self)._superSends())._at_(_st(aNode)._selector()))._add_(aNode);
 $2=_st(_st((smalltalk.IRSendInliner || IRSendInliner))._inlinedSelectors())._includes_(_st(aNode)._selector());
 if(smalltalk.assert($2)){
 _st(aNode)._shouldBeInlined_(true);
-$3=_st(_st(aNode)._receiver())._isValueNode();
-if(! smalltalk.assert($3)){
 _st(_st(aNode)._receiver())._shouldBeAliased_(true);
 };
 };
-};
 _st(_st(self)._messageSends())._at_ifAbsentPut_(_st(aNode)._selector(),(function(){
 return smalltalk.withContext(function($ctx2) { 
return _st((smalltalk.Set || Set))._new();
 })}));
@@ -1245,18 +1261,19 @@ smalltalk.method({
 selector: "visitVariableNode:",
 fn: function (aNode){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $2,$3,$4,$1;
-$2=_st(self["@currentScope"])._lookupVariable_(aNode);
-if(($receiver = $2) == nil || $receiver == undefined){
+return smalltalk.withContext(function($ctx1) { 
var $1,$3,$4,$5,$2;
+$1=aNode;
+$3=_st(self["@currentScope"])._lookupVariable_(aNode);
+if(($receiver = $3) == nil || $receiver == undefined){
 _st(self)._errorUnknownVariable_(aNode);
-$3=_st((smalltalk.UnknownVar || UnknownVar))._new();
-_st($3)._name_(_st(aNode)._value());
-$4=_st($3)._yourself();
-$1=$4;
+$4=_st((smalltalk.UnknownVar || UnknownVar))._new();
+_st($4)._name_(_st(aNode)._value());
+$5=_st($4)._yourself();
+$2=$5;
 } else {
-$1=$2;
+$2=$3;
 };
-_st(aNode)._binding_($1);
+_st($1)._binding_($2);
 return self}, self, "visitVariableNode:", [aNode], smalltalk.SemanticAnalyzer)}
 }),
 smalltalk.SemanticAnalyzer);

+ 49 - 32
js/Compiler-Semantic.js

@@ -145,7 +145,9 @@ selector: "instruction",
 category: 'accessing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@instruction"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@instruction"];
+return $1;
 }, self, "instruction", [], smalltalk.LexicalScope)},
 args: [],
 source: "instruction\x0a\x09^ instruction",
@@ -231,8 +233,8 @@ selector: "lookupVariable:",
 category: 'accessing',
 fn: function (aNode){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
-$ctx1.lookup=nil;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
+$ctx1.locals.lookup=nil;
 $ctx1.locals.lookup=_st(self)._bindingFor_(aNode);
 if(($receiver = $ctx1.locals.lookup) == nil || $receiver == undefined){
 $1=_st(self)._outerScope();
@@ -245,7 +247,8 @@ $ctx1.locals.lookup;
 } else {
 $ctx1.locals.lookup;
 };
-return $ctx1.locals.lookup;
+$2=$ctx1.locals.lookup;
+return $2;
 }, self, "lookupVariable:", [aNode], smalltalk.LexicalScope)},
 args: ["aNode"],
 source: "lookupVariable: aNode\x0a\x09| lookup |\x0a\x09lookup := (self bindingFor: aNode).\x0a\x09lookup ifNil: [\x0a\x09\x09lookup := self outerScope ifNotNil: [ \x0a\x09\x09\x09(self outerScope lookupVariable: aNode) ]].\x0a\x09^ lookup",
@@ -284,7 +287,9 @@ selector: "node",
 category: 'accessing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@node"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@node"];
+return $1;
 }, self, "node", [], smalltalk.LexicalScope)},
 args: [],
 source: "node\x0a\x09\x22Answer the node in which I am defined\x22\x0a\x09\x0a\x09^ node",
@@ -316,7 +321,9 @@ selector: "outerScope",
 category: 'accessing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@outerScope"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@outerScope"];
+return $1;
 }, self, "outerScope", [], smalltalk.LexicalScope)},
 args: [],
 source: "outerScope\x0a\x09^ outerScope",
@@ -627,7 +634,9 @@ selector: "methodScope",
 category: 'accessing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self;
+return $1;
 }, self, "methodScope", [], smalltalk.MethodLexicalScope)},
 args: [],
 source: "methodScope\x0a\x09^ self",
@@ -666,7 +675,7 @@ selector: "pseudoVars",
 category: 'accessing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3;
 if(($receiver = self["@pseudoVars"]) == nil || $receiver == undefined){
 self["@pseudoVars"]=_st((smalltalk.Dictionary || Dictionary))._new();
 self["@pseudoVars"];
@@ -679,7 +688,8 @@ return _st(self["@pseudoVars"])._at_put_(each,$2);
 } else {
 self["@pseudoVars"];
 };
-return self["@pseudoVars"];
+$3=self["@pseudoVars"];
+return $3;
 }, self, "pseudoVars", [], smalltalk.MethodLexicalScope)},
 args: [],
 source: "pseudoVars\x0a\x09pseudoVars ifNil: [\x0a\x09\x09pseudoVars := Dictionary new.\x0a\x09\x09Smalltalk current pseudoVariableNames do: [ :each |\x0a\x09\x09\x09pseudoVars at: each put: ((PseudoVar on: each)\x0a\x09\x09\x09\x09scope: self methodScope;\x0a\x09\x09\x09\x09yourself) ]].\x0a\x09^ pseudoVars",
@@ -853,7 +863,9 @@ selector: "name",
 category: 'accessing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@name"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@name"];
+return $1;
 }, self, "name", [], smalltalk.ScopeVar)},
 args: [],
 source: "name\x0a\x09^ name",
@@ -885,7 +897,9 @@ selector: "scope",
 category: 'accessing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@scope"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@scope"];
+return $1;
 }, self, "scope", [], smalltalk.ScopeVar)},
 args: [],
 source: "scope\x0a\x09^ scope",
@@ -967,7 +981,9 @@ selector: "node",
 category: 'accessing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@node"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@node"];
+return $1;
 }, self, "node", [], smalltalk.AliasVar)},
 args: [],
 source: "node\x0a\x09^ node",
@@ -1420,7 +1436,9 @@ selector: "theClass",
 category: 'accessing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return self["@theClass"];
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@theClass"];
+return $1;
 }, self, "theClass", [], smalltalk.SemanticAnalyzer)},
 args: [],
 source: "theClass\x0a\x09^ theClass",
@@ -1562,7 +1580,7 @@ selector: "visitMethodNode:",
 category: 'visiting',
 fn: function (aNode){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
 _st(self)._pushScope_(_st(self)._newMethodScope());
 _st(aNode)._scope_(self["@currentScope"]);
 _st(self["@currentScope"])._node_(aNode);
@@ -1574,9 +1592,10 @@ return smalltalk.withContext(function($ctx2) { 
_st(self)._validateVariableScope
 return _st(self["@currentScope"])._addArg_(each);
 })}));
 smalltalk.NodeVisitor.fn.prototype._visitMethodNode_.apply(_st(self), [aNode]);
-_st(aNode)._classReferences_(_st(self)._classReferences());
-_st(aNode)._messageSends_(_st(_st(self)._messageSends())._keys());
-$1=_st(aNode)._superSends_(_st(_st(self)._superSends())._keys());
+$1=aNode;
+_st($1)._classReferences_(_st(self)._classReferences());
+_st($1)._messageSends_(_st(_st(self)._messageSends())._keys());
+$2=_st($1)._superSends_(_st(_st(self)._superSends())._keys());
 _st(self)._popScope();
 return self}, self, "visitMethodNode:", [aNode], smalltalk.SemanticAnalyzer)},
 args: ["aNode"],
@@ -1617,7 +1636,7 @@ selector: "visitSendNode:",
 category: 'visiting',
 fn: function (aNode){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
 $1=_st(_st(_st(aNode)._receiver())._value()).__eq("super");
 if(smalltalk.assert($1)){
 _st(aNode)._superSend_(true);
@@ -1630,12 +1649,9 @@ _st(_st(_st(self)._superSends())._at_(_st(aNode)._selector()))._add_(aNode);
 $2=_st(_st((smalltalk.IRSendInliner || IRSendInliner))._inlinedSelectors())._includes_(_st(aNode)._selector());
 if(smalltalk.assert($2)){
 _st(aNode)._shouldBeInlined_(true);
-$3=_st(_st(aNode)._receiver())._isValueNode();
-if(! smalltalk.assert($3)){
 _st(_st(aNode)._receiver())._shouldBeAliased_(true);
 };
 };
-};
 _st(_st(self)._messageSends())._at_ifAbsentPut_(_st(aNode)._selector(),(function(){
 return smalltalk.withContext(function($ctx2) { 
return _st((smalltalk.Set || Set))._new();
 })}));
@@ -1644,8 +1660,8 @@ _st(aNode)._index_(_st(_st(_st(self)._messageSends())._at_(_st(aNode)._selector(
 smalltalk.NodeVisitor.fn.prototype._visitSendNode_.apply(_st(self), [aNode]);
 return self}, self, "visitSendNode:", [aNode], smalltalk.SemanticAnalyzer)},
 args: ["aNode"],
-source: "visitSendNode: aNode\x0a\x0a\x09aNode receiver value = 'super' \x0a\x09\x09ifTrue: [\x0a\x09\x09\x09aNode superSend: true.\x0a\x09\x09\x09aNode receiver value: 'self'.\x0a\x09\x09\x09self superSends at: aNode selector ifAbsentPut: [ Set new ].\x0a\x09\x09\x09(self superSends at: aNode selector) add: aNode ]\x0a          \x0a\x09\x09ifFalse: [ (IRSendInliner inlinedSelectors includes: aNode selector) ifTrue: [\x0a\x09\x09\x09aNode shouldBeInlined: true.\x0a\x09\x09\x09aNode receiver isValueNode ifFalse: [ aNode receiver shouldBeAliased: true ] ] ].\x0a\x0a\x09self messageSends at: aNode selector ifAbsentPut: [ Set new ].\x0a\x09(self messageSends at: aNode selector) add: aNode.\x0a\x0a\x09aNode index: (self messageSends at: aNode selector) size.\x0a\x0a\x09super visitSendNode: aNode",
-messageSends: ["ifTrue:ifFalse:", "superSend:", "value:", "receiver", "at:ifAbsentPut:", "selector", "new", "superSends", "add:", "at:", "ifTrue:", "shouldBeInlined:", "ifFalse:", "shouldBeAliased:", "isValueNode", "includes:", "inlinedSelectors", "=", "value", "messageSends", "index:", "size", "visitSendNode:"],
+source: "visitSendNode: aNode\x0a\x0a\x09aNode receiver value = 'super' \x0a\x09\x09ifTrue: [\x0a\x09\x09\x09aNode superSend: true.\x0a\x09\x09\x09aNode receiver value: 'self'.\x0a\x09\x09\x09self superSends at: aNode selector ifAbsentPut: [ Set new ].\x0a\x09\x09\x09(self superSends at: aNode selector) add: aNode ]\x0a          \x0a\x09\x09ifFalse: [ (IRSendInliner inlinedSelectors includes: aNode selector) ifTrue: [\x0a\x09\x09\x09aNode shouldBeInlined: true.\x0a\x09\x09\x09aNode receiver shouldBeAliased: true ] ].\x0a\x0a\x09self messageSends at: aNode selector ifAbsentPut: [ Set new ].\x0a\x09(self messageSends at: aNode selector) add: aNode.\x0a\x0a\x09aNode index: (self messageSends at: aNode selector) size.\x0a\x0a\x09super visitSendNode: aNode",
+messageSends: ["ifTrue:ifFalse:", "superSend:", "value:", "receiver", "at:ifAbsentPut:", "selector", "new", "superSends", "add:", "at:", "ifTrue:", "shouldBeInlined:", "shouldBeAliased:", "includes:", "inlinedSelectors", "=", "value", "messageSends", "index:", "size", "visitSendNode:"],
 referencedClasses: ["Set", "IRSendInliner"]
 }),
 smalltalk.SemanticAnalyzer);
@@ -1677,18 +1693,19 @@ selector: "visitVariableNode:",
 category: 'visiting',
 fn: function (aNode){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $2,$3,$4,$1;
-$2=_st(self["@currentScope"])._lookupVariable_(aNode);
-if(($receiver = $2) == nil || $receiver == undefined){
+return smalltalk.withContext(function($ctx1) { 
var $1,$3,$4,$5,$2;
+$1=aNode;
+$3=_st(self["@currentScope"])._lookupVariable_(aNode);
+if(($receiver = $3) == nil || $receiver == undefined){
 _st(self)._errorUnknownVariable_(aNode);
-$3=_st((smalltalk.UnknownVar || UnknownVar))._new();
-_st($3)._name_(_st(aNode)._value());
-$4=_st($3)._yourself();
-$1=$4;
+$4=_st((smalltalk.UnknownVar || UnknownVar))._new();
+_st($4)._name_(_st(aNode)._value());
+$5=_st($4)._yourself();
+$2=$5;
 } else {
-$1=$2;
+$2=$3;
 };
-_st(aNode)._binding_($1);
+_st($1)._binding_($2);
 return self}, self, "visitVariableNode:", [aNode], smalltalk.SemanticAnalyzer)},
 args: ["aNode"],
 source: "visitVariableNode: aNode\x0a\x09\x22Bind a ScopeVar to aNode by doing a lookup in the current scope.\x0a\x09If no ScopeVar is found, bind a UnknowVar and throw an error\x22\x0a\x0a\x09aNode binding: ((currentScope lookupVariable: aNode) ifNil: [ \x0a\x09\x09self errorUnknownVariable: aNode.\x0a\x09\x09UnknownVar new name: aNode value; yourself ])",

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

@@ -189,6 +189,18 @@ return self}, self, "testNonLocalReturn", [], smalltalk.CodeGeneratorTest)}
 }),
 smalltalk.CodeGeneratorTest);
 
+smalltalk.addMethod(
+"_testSendReceiverAndArgumentsOrdered",
+smalltalk.method({
+selector: "testSendReceiverAndArgumentsOrdered",
+fn: function (){
+var self=this;
+smalltalk.send(self,"_should_return_",["foo\x0a  | x |\x0a  x := 1.\x0a  ^ Array with: x with: (true ifTrue: [ x := 2 ])\x0a",[(1), (2)]]);
+smalltalk.send(self,"_should_return_",["foo\x0a  | x |\x0a  x := Array.\x0a  ^ x with: x with: (true ifTrue: [ x := 2 ])\x0a",[(smalltalk.Array || Array),(2)]]);
+return self}
+}),
+smalltalk.CodeGeneratorTest);
+
 smalltalk.addMethod(
 "_testifFalse",
 smalltalk.method({

+ 17 - 0
js/Compiler-Tests.js

@@ -259,6 +259,23 @@ referencedClasses: []
 }),
 smalltalk.CodeGeneratorTest);
 
+smalltalk.addMethod(
+"_testSendReceiverAndArgumentsOrdered",
+smalltalk.method({
+selector: "testSendReceiverAndArgumentsOrdered",
+category: 'tests',
+fn: function (){
+var self=this;
+smalltalk.send(self,"_should_return_",["foo\x0a  | x |\x0a  x := 1.\x0a  ^ Array with: x with: (true ifTrue: [ x := 2 ])\x0a",[(1), (2)]]);
+smalltalk.send(self,"_should_return_",["foo\x0a  | x |\x0a  x := Array.\x0a  ^ x with: x with: (true ifTrue: [ x := 2 ])\x0a",[(smalltalk.Array || Array),(2)]]);
+return self},
+args: [],
+source: "testSendReceiverAndArgumentsOrdered\x0a\x09self should: 'foo\x0a  | x |\x0a  x := 1.\x0a  ^ Array with: x with: (true ifTrue: [ x := 2 ])\x0a' return: #(1 2).\x0a\x0a\x09self should: 'foo\x0a  | x |\x0a  x := Array.\x0a  ^ x with: x with: (true ifTrue: [ x := 2 ])\x0a' return: {Array. 2}.\x0a",
+messageSends: ["should:return:"],
+referencedClasses: ["Array"]
+}),
+smalltalk.CodeGeneratorTest);
+
 smalltalk.addMethod(
 "_testifFalse",
 smalltalk.method({

+ 2 - 3
js/Kernel-Objects.deploy.js

@@ -657,8 +657,7 @@ smalltalk.method({
 selector: "try:catch:",
 fn: function (aBlock,anotherBlock){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
try{result = aBlock()} catch(e) {result = anotherBlock(e)};
-	return result;;
+return smalltalk.withContext(function($ctx1) { 
try{return aBlock()} catch(e) {return anotherBlock(e)};
 ;
 return self}, self, "try:catch:", [aBlock,anotherBlock], smalltalk.Object)}
 }),
@@ -980,7 +979,7 @@ selector: "category:",
 fn: function (aString){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
var $1;
-$ctx1.oldCategory=nil;
+$ctx1.locals.oldCategory=nil;
 $ctx1.locals.oldCategory=_st(self)._category();
 _st(self)._basicAt_put_("category",aString);
 $1=_st(self)._methodClass();

+ 3 - 4
js/Kernel-Objects.js

@@ -914,12 +914,11 @@ selector: "try:catch:",
 category: 'error handling',
 fn: function (aBlock,anotherBlock){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
try{result = aBlock()} catch(e) {result = anotherBlock(e)};
-	return result;;
+return smalltalk.withContext(function($ctx1) { 
try{return aBlock()} catch(e) {return anotherBlock(e)};
 ;
 return self}, self, "try:catch:", [aBlock,anotherBlock], smalltalk.Object)},
 args: ["aBlock", "anotherBlock"],
-source: "try: aBlock catch: anotherBlock\x0a\x09<try{result = aBlock()} catch(e) {result = anotherBlock(e)};\x0a\x09return result;>",
+source: "try: aBlock catch: anotherBlock\x0a\x09<try{return aBlock()} catch(e) {return anotherBlock(e)}>",
 messageSends: [],
 referencedClasses: []
 }),
@@ -1354,7 +1353,7 @@ category: 'accessing',
 fn: function (aString){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
var $1;
-$ctx1.oldCategory=nil;
+$ctx1.locals.oldCategory=nil;
 $ctx1.locals.oldCategory=_st(self)._category();
 _st(self)._basicAt_put_("category",aString);
 $1=_st(self)._methodClass();

+ 14 - 0
st/Compiler-AST.st

@@ -61,6 +61,10 @@ isBlockSequenceNode
 	^false
 !
 
+isImmutable
+	^false
+!
+
 isReturnNode
 	^false
 !
@@ -464,6 +468,10 @@ value: anObject
 
 !ValueNode methodsFor: 'testing'!
 
+isImmutable
+	^true
+!
+
 isValueNode
 	^true
 ! !
@@ -505,6 +513,12 @@ binding: aScopeVar
 	binding := aScopeVar
 ! !
 
+!VariableNode methodsFor: 'testing'!
+
+isImmutable
+	^false
+! !
+
 !VariableNode methodsFor: 'visiting'!
 
 accept: aVisitor

+ 24 - 12
st/Compiler-IR.st

@@ -60,7 +60,7 @@ withSequence: aSequence do: aBlock
 alias: aNode
 	| variable |
 
-	aNode isValueNode ifTrue: [ ^ self visit: aNode ].
+	aNode isImmutable ifTrue: [ ^ self visit: aNode ].
 
 	variable := IRVariable new 
 		variable: (AliasVar new name: '$', self nextAlias); 
@@ -76,6 +76,23 @@ alias: aNode
 	^ variable
 !
 
+temporallyDependentList: nodes
+	| threshold result |
+    threshold := 0.
+    
+    nodes withIndexDo: [ :each :i |
+        (each shouldBeInlined or: [ each shouldBeAliased ])
+		    ifTrue: [ threshold := i ]].
+
+	result := OrderedCollection new.
+	nodes withIndexDo: [ :each :i | 
+		result add: (i <= threshold
+			ifTrue: [ self alias: each ]
+			ifFalse: [ self visit: each ])].
+
+    ^result
+!
+
 visitAssignmentNode: aNode
 	| left right assignment |
 	right := self visit: aNode right.
@@ -117,7 +134,7 @@ visitBlockSequenceNode: aNode
 visitCascadeNode: aNode
 	| alias |
 
-	aNode receiver isValueNode ifFalse: [ 
+	aNode receiver isImmutable ifFalse: [ 
 		alias := self alias: aNode receiver.
 		aNode nodes do: [ :each |
 			each receiver: (VariableNode new binding: alias variable) ]].
@@ -189,21 +206,16 @@ visitReturnNode: aNode
 !
 
 visitSendNode: aNode
-	| send receiver arguments |
+	| send all receiver arguments |
 	send := IRSend new.
 	send 
 		selector: aNode selector;
 		index: aNode index.
 	aNode superSend ifTrue: [ send classSend: self theClass superclass ].
-
-	receiver := (aNode receiver shouldBeInlined or: [ aNode receiver shouldBeAliased ])
-		ifTrue: [ self alias: aNode receiver ]
-		ifFalse: [ self visit: aNode receiver ].
-
-	arguments := aNode arguments collect: [ :each | 
-		each shouldBeInlined
-			ifTrue: [ self alias: each ]
-			ifFalse: [ self visit: each ]].
+    
+    all := self temporallyDependentList: { aNode receiver }, aNode arguments.
+	receiver := all first.
+	arguments := all allButFirst.
 
 	send add: receiver.
 	arguments do: [ :each | send add: each ].

+ 1 - 1
st/Compiler-Semantic.st

@@ -543,7 +543,7 @@ visitSendNode: aNode
           
 		ifFalse: [ (IRSendInliner inlinedSelectors includes: aNode selector) ifTrue: [
 			aNode shouldBeInlined: true.
-			aNode receiver isValueNode ifFalse: [ aNode receiver shouldBeAliased: true ] ] ].
+			aNode receiver shouldBeAliased: true ] ].
 
 	self messageSends at: aNode selector ifAbsentPut: [ Set new ].
 	(self messageSends at: aNode selector) add: aNode.

+ 14 - 0
st/Compiler-Tests.st

@@ -107,6 +107,20 @@ testNonLocalReturn
 	self should: 'foo [ :x | ^ x + x ] value: 4. ^ 2' return: 8
 !
 
+testSendReceiverAndArgumentsOrdered
+	self should: 'foo
+  | x |
+  x := 1.
+  ^ Array with: x with: (true ifTrue: [ x := 2 ])
+' return: #(1 2).
+
+	self should: 'foo
+  | x |
+  x := Array.
+  ^ x with: x with: (true ifTrue: [ x := 2 ])
+' return: {Array. 2}.
+!
+
 testifFalse
 	self should: 'foo true ifFalse: [ ^ 1 ]' return: receiver.
 	self should: 'foo false ifFalse: [ ^ 2 ]' return: 2.

+ 1 - 2
st/Kernel-Objects.st

@@ -201,8 +201,7 @@ throw: anObject
 !
 
 try: aBlock catch: anotherBlock
-	<try{result = aBlock()} catch(e) {result = anotherBlock(e)};
-	return result;>
+	<try{return aBlock()} catch(e) {return anotherBlock(e)}>
 ! !
 
 !Object methodsFor: 'initialization'!