Преглед изворни кода

Merge branch 'master' into dag

# Conflicts:
#	src/Compiler-Inlining.js
#	src/Compiler-Inlining.st
Herbert Vojčík пре 8 година
родитељ
комит
900534c25f
6 измењених фајлова са 179 додато и 406 уклоњено
  1. 108 278
      src/Compiler-Inlining.js
  2. 34 82
      src/Compiler-Inlining.st
  3. 18 25
      src/Kernel-Collections.js
  4. 3 3
      src/Kernel-Collections.st
  5. 12 14
      src/Kernel-Objects.js
  6. 4 4
      src/Kernel-Objects.st

+ 108 - 278
src/Compiler-Inlining.js

@@ -6,53 +6,6 @@ $core.addPackage('Compiler-Inlining');
 $core.packages["Compiler-Inlining"].innerEval = function (expr) { return eval(expr); };
 $core.packages["Compiler-Inlining"].transport = {"type":"amd","amdNamespace":"amber_core"};
 
-$core.addClass('IRInlinedAssignment', $globals.IRAssignment, [], 'Compiler-Inlining');
-//>>excludeStart("ide", pragmas.excludeIdeData);
-$globals.IRInlinedAssignment.comment="I represent an inlined assignment instruction.";
-//>>excludeEnd("ide");
-$core.addMethod(
-$core.method({
-selector: "acceptDagVisitor:",
-protocol: 'visiting',
-fn: function (aVisitor){
-var self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-return $recv(aVisitor)._visitIRInlinedAssignment_(self);
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"acceptDagVisitor:",{aVisitor:aVisitor},$globals.IRInlinedAssignment)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["aVisitor"],
-source: "acceptDagVisitor: aVisitor\x0a\x09^ aVisitor visitIRInlinedAssignment: self",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["visitIRInlinedAssignment:"]
-}),
-$globals.IRInlinedAssignment);
-
-$core.addMethod(
-$core.method({
-selector: "isInlined",
-protocol: 'testing',
-fn: function (){
-var self=this;
-return true;
-
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: [],
-source: "isInlined\x0a\x09^ true",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: []
-}),
-$globals.IRInlinedAssignment);
-
-
-
 $core.addClass('IRInlinedClosure', $globals.IRClosure, [], 'Compiler-Inlining');
 //>>excludeStart("ide", pragmas.excludeIdeData);
 $globals.IRInlinedClosure.comment="I represent an inlined closure instruction.";
@@ -101,53 +54,6 @@ $globals.IRInlinedClosure);
 
 
 
-$core.addClass('IRInlinedReturn', $globals.IRReturn, [], 'Compiler-Inlining');
-//>>excludeStart("ide", pragmas.excludeIdeData);
-$globals.IRInlinedReturn.comment="I represent an inlined local return instruction.";
-//>>excludeEnd("ide");
-$core.addMethod(
-$core.method({
-selector: "acceptDagVisitor:",
-protocol: 'visiting',
-fn: function (aVisitor){
-var self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-return $recv(aVisitor)._visitIRInlinedReturn_(self);
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"acceptDagVisitor:",{aVisitor:aVisitor},$globals.IRInlinedReturn)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["aVisitor"],
-source: "acceptDagVisitor: aVisitor\x0a\x09^ aVisitor visitIRInlinedReturn: self",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["visitIRInlinedReturn:"]
-}),
-$globals.IRInlinedReturn);
-
-$core.addMethod(
-$core.method({
-selector: "isInlined",
-protocol: 'testing',
-fn: function (){
-var self=this;
-return true;
-
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: [],
-source: "isInlined\x0a\x09^ true",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: []
-}),
-$globals.IRInlinedReturn);
-
-
-
 $core.addClass('IRInlinedSend', $globals.IRSend, [], 'Compiler-Inlining');
 //>>excludeStart("ide", pragmas.excludeIdeData);
 $globals.IRInlinedSend.comment="I am the abstract super class of inlined message send instructions.";
@@ -842,30 +748,6 @@ $core.addClass('IRInliningJSTranslator', $globals.IRJSTranslator, [], 'Compiler-
 //>>excludeStart("ide", pragmas.excludeIdeData);
 $globals.IRInliningJSTranslator.comment="I am a specialized JavaScript translator able to write inlined IR instructions to JavaScript stream (`JSStream` instance).";
 //>>excludeEnd("ide");
-$core.addMethod(
-$core.method({
-selector: "visitIRInlinedAssignment:",
-protocol: 'visiting',
-fn: function (anIRInlinedAssignment){
-var self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-self._visit_($recv(anIRInlinedAssignment)._right());
-return self;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"visitIRInlinedAssignment:",{anIRInlinedAssignment:anIRInlinedAssignment},$globals.IRInliningJSTranslator)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["anIRInlinedAssignment"],
-source: "visitIRInlinedAssignment: anIRInlinedAssignment\x0a\x09self visit: anIRInlinedAssignment right",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["visit:", "right"]
-}),
-$globals.IRInliningJSTranslator);
-
 $core.addMethod(
 $core.method({
 selector: "visitIRInlinedClosure:",
@@ -1195,30 +1077,6 @@ messageSends: ["nextPutIf:then:else:", "stream", "nextPutAll:", "visit:", "first
 }),
 $globals.IRInliningJSTranslator);
 
-$core.addMethod(
-$core.method({
-selector: "visitIRInlinedReturn:",
-protocol: 'visiting',
-fn: function (anIRInlinedReturn){
-var self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-self._visit_($recv(anIRInlinedReturn)._expression());
-return self;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"visitIRInlinedReturn:",{anIRInlinedReturn:anIRInlinedReturn},$globals.IRInliningJSTranslator)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["anIRInlinedReturn"],
-source: "visitIRInlinedReturn: anIRInlinedReturn\x0a\x09self visit: anIRInlinedReturn expression",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: ["visit:", "expression"]
-}),
-$globals.IRInliningJSTranslator);
-
 $core.addMethod(
 $core.method({
 selector: "visitIRInlinedSequence:",
@@ -1690,6 +1548,31 @@ messageSends: ["send:", "perform:withArguments:", "selector", "send", "arguments
 }),
 $globals.IRSendInliner);
 
+$core.addMethod(
+$core.method({
+selector: "inlineSend:andReplace:",
+protocol: 'private',
+fn: function (anIRSend,anIRInstruction){
+var self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+$recv(anIRInstruction)._replaceWith_(anIRSend);
+self._inlineSend_(anIRSend);
+return anIRSend;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"inlineSend:andReplace:",{anIRSend:anIRSend,anIRInstruction:anIRInstruction},$globals.IRSendInliner)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["anIRSend", "anIRInstruction"],
+source: "inlineSend: anIRSend andReplace: anIRInstruction\x0a\x09anIRInstruction replaceWith: anIRSend.\x0a\x09self inlineSend: anIRSend.\x0a\x09^ anIRSend",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["replaceWith:", "inlineSend:"]
+}),
+$globals.IRSendInliner);
+
 $core.addMethod(
 $core.method({
 selector: "inlinedClosure",
@@ -1716,7 +1599,7 @@ $globals.IRSendInliner);
 $core.addMethod(
 $core.method({
 selector: "inlinedSend:withBlock:",
-protocol: 'inlining',
+protocol: 'private',
 fn: function (inlinedSend,anIRInstruction){
 var self=this;
 var inlinedClosure;
@@ -1769,7 +1652,7 @@ $globals.IRSendInliner);
 $core.addMethod(
 $core.method({
 selector: "inlinedSend:withBlock:withBlock:",
-protocol: 'inlining',
+protocol: 'private',
 fn: function (inlinedSend,anIRInstruction,anotherIRInstruction){
 var self=this;
 var inlinedClosure1,inlinedClosure2;
@@ -2015,81 +1898,31 @@ messageSends: ["ifFalse:", "includes:", "inlinedSelectors", "selector", "allSati
 $globals.IRSendInliner.klass);
 
 
-$core.addClass('IRAssignmentInliner', $globals.IRSendInliner, ['assignment'], 'Compiler-Inlining');
+$core.addClass('IRAssignmentInliner', $globals.IRSendInliner, ['target'], 'Compiler-Inlining');
 //>>excludeStart("ide", pragmas.excludeIdeData);
 $globals.IRAssignmentInliner.comment="I inline message sends together with assignments by moving them around into the inline closure instructions.\x0a\x0a##Example\x0a\x0a\x09foo\x0a\x09\x09| a |\x0a\x09\x09a := true ifTrue: [ 1 ]\x0a\x0aWill produce:\x0a\x0a\x09if($core.assert(true) {\x0a\x09\x09a = 1;\x0a\x09};";
 //>>excludeEnd("ide");
-$core.addMethod(
-$core.method({
-selector: "assignment",
-protocol: 'accessing',
-fn: function (){
-var self=this;
-return self["@assignment"];
-
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: [],
-source: "assignment\x0a\x09^ assignment",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: []
-}),
-$globals.IRAssignmentInliner);
-
-$core.addMethod(
-$core.method({
-selector: "assignment:",
-protocol: 'accessing',
-fn: function (aNode){
-var self=this;
-self["@assignment"]=aNode;
-return self;
-
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: ["aNode"],
-source: "assignment: aNode\x0a\x09assignment := aNode",
-referencedClasses: [],
-//>>excludeEnd("ide");
-messageSends: []
-}),
-$globals.IRAssignmentInliner);
-
 $core.addMethod(
 $core.method({
 selector: "inlineAssignment:",
 protocol: 'inlining',
 fn: function (anIRAssignment){
 var self=this;
-var inlinedAssignment;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
-self._assignment_(anIRAssignment);
-inlinedAssignment=$recv($globals.IRInlinedAssignment)._new();
-$recv($recv(anIRAssignment)._dagChildren())._do_((function(each){
+self._target_($recv(anIRAssignment)._left());
+return self._inlineSend_andReplace_($recv(anIRAssignment)._right(),anIRAssignment);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx2) {
-//>>excludeEnd("ctx");
-return $recv(inlinedAssignment)._add_(each);
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)});
-//>>excludeEnd("ctx");
-}));
-$recv(anIRAssignment)._replaceWith_(inlinedAssignment);
-self._inlineSend_($recv(inlinedAssignment)._right());
-return inlinedAssignment;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"inlineAssignment:",{anIRAssignment:anIRAssignment,inlinedAssignment:inlinedAssignment},$globals.IRAssignmentInliner)});
+}, function($ctx1) {$ctx1.fill(self,"inlineAssignment:",{anIRAssignment:anIRAssignment},$globals.IRAssignmentInliner)});
 //>>excludeEnd("ctx");
 },
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["anIRAssignment"],
-source: "inlineAssignment: anIRAssignment\x0a\x09| inlinedAssignment |\x0a\x09self assignment: anIRAssignment.\x0a\x09inlinedAssignment := IRInlinedAssignment new.\x0a\x09anIRAssignment dagChildren do: [ :each |\x0a\x09\x09inlinedAssignment add: each ].\x0a\x09anIRAssignment replaceWith: inlinedAssignment.\x0a\x09self inlineSend: inlinedAssignment right.\x0a\x09^ inlinedAssignment",
-referencedClasses: ["IRInlinedAssignment"],
+source: "inlineAssignment: anIRAssignment\x0a\x09self target: anIRAssignment left.\x0a\x09^ self inlineSend: anIRAssignment right andReplace: anIRAssignment",
+referencedClasses: [],
 //>>excludeEnd("ide");
-messageSends: ["assignment:", "new", "do:", "dagChildren", "add:", "replaceWith:", "inlineSend:", "right"]
+messageSends: ["target:", "left", "inlineSend:andReplace:", "right"]
 }),
 $globals.IRAssignmentInliner);
 
@@ -2099,11 +1932,11 @@ selector: "inlineClosure:",
 protocol: 'inlining',
 fn: function (anIRClosure){
 var self=this;
-var closure,statements;
+var closure,sequence,statements;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
-var $2,$1,$3,$5,$4;
+var $1,$2,$3,$5,$4;
 closure=(
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 $ctx1.supercall = true,
@@ -2112,45 +1945,80 @@ $ctx1.supercall = true,
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 $ctx1.supercall = false;
 //>>excludeEnd("ctx");;
-statements=$recv($recv(closure)._sequence())._dagChildren();
+sequence=$recv(closure)._sequence();
+statements=$recv(sequence)._dagChildren();
 $recv(statements)._ifNotEmpty_((function(){
+var final;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx2) {
 //>>excludeEnd("ctx");
-$2=$recv(statements)._last();
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-$ctx2.sendIdx["last"]=1;
-//>>excludeEnd("ctx");
-$1=$recv($2)._yieldsValue();
+final=$recv(statements)._last();
+final;
+$1=$recv(final)._yieldsValue();
 if($core.assert($1)){
-$3=$recv(statements)._last();
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-$ctx2.sendIdx["last"]=2;
-//>>excludeEnd("ctx");
+$2=sequence;
+$3=final;
 $5=$recv($globals.IRAssignment)._new();
-$recv($5)._add_($recv(self._assignment())._left());
+$recv($5)._add_(self._target());
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 $ctx2.sendIdx["add:"]=1;
 //>>excludeEnd("ctx");
-$recv($5)._add_($recv($recv(statements)._last())._copy());
+$recv($5)._add_($recv(final)._copy());
 $4=$recv($5)._yourself();
-return $recv($3)._replaceWith_($4);
+return $recv($2)._replace_with_($3,$4);
 };
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)});
+}, function($ctx2) {$ctx2.fillBlock({final:final},$ctx1,1)});
 //>>excludeEnd("ctx");
 }));
 return closure;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"inlineClosure:",{anIRClosure:anIRClosure,closure:closure,statements:statements},$globals.IRAssignmentInliner)});
+}, function($ctx1) {$ctx1.fill(self,"inlineClosure:",{anIRClosure:anIRClosure,closure:closure,sequence:sequence,statements:statements},$globals.IRAssignmentInliner)});
 //>>excludeEnd("ctx");
 },
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["anIRClosure"],
-source: "inlineClosure: anIRClosure\x0a\x09| closure statements |\x0a\x0a\x09closure := super inlineClosure: anIRClosure.\x0a\x09statements := closure sequence dagChildren.\x0a\x09\x0a\x09statements ifNotEmpty: [\x0a\x09\x09statements last yieldsValue ifTrue: [\x0a\x09\x09\x09statements last replaceWith: (IRAssignment new\x0a\x09\x09\x09\x09add: self assignment left;\x0a\x09\x09\x09\x09add: statements last copy;\x0a\x09\x09\x09\x09yourself) ] ].\x0a\x0a\x09^ closure",
+source: "inlineClosure: anIRClosure\x0a\x09| closure sequence statements |\x0a\x0a\x09closure := super inlineClosure: anIRClosure.\x0a\x09sequence := closure sequence.\x0a\x09statements := sequence dagChildren.\x0a\x09\x0a\x09statements ifNotEmpty: [\x0a\x09\x09| final |\x0a\x09\x09final := statements last.\x0a\x09\x09final yieldsValue ifTrue: [\x0a\x09\x09\x09sequence replace: final with: (IRAssignment new\x0a\x09\x09\x09\x09add: self target;\x0a\x09\x09\x09\x09add: final copy;\x0a\x09\x09\x09\x09yourself) ] ].\x0a\x0a\x09^ closure",
 referencedClasses: ["IRAssignment"],
 //>>excludeEnd("ide");
-messageSends: ["inlineClosure:", "dagChildren", "sequence", "ifNotEmpty:", "ifTrue:", "yieldsValue", "last", "replaceWith:", "add:", "new", "left", "assignment", "copy", "yourself"]
+messageSends: ["inlineClosure:", "sequence", "dagChildren", "ifNotEmpty:", "last", "ifTrue:", "yieldsValue", "replace:with:", "add:", "new", "target", "copy", "yourself"]
+}),
+$globals.IRAssignmentInliner);
+
+$core.addMethod(
+$core.method({
+selector: "target",
+protocol: 'accessing',
+fn: function (){
+var self=this;
+return self["@target"];
+
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "target\x0a\x09^ target",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: []
+}),
+$globals.IRAssignmentInliner);
+
+$core.addMethod(
+$core.method({
+selector: "target:",
+protocol: 'accessing',
+fn: function (anObject){
+var self=this;
+self["@target"]=anObject;
+return self;
+
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["anObject"],
+source: "target: anObject\x0a\x09target := anObject",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: []
 }),
 $globals.IRAssignmentInliner);
 
@@ -2166,11 +2034,11 @@ selector: "inlineClosure:",
 protocol: 'inlining',
 fn: function (anIRClosure){
 var self=this;
-var closure,statements;
+var closure,sequence,statements;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
-var $2,$1,$3,$5,$4;
+var $1,$2,$3,$5,$4;
 closure=(
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 $ctx1.supercall = true,
@@ -2179,41 +2047,39 @@ $ctx1.supercall = true,
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 $ctx1.supercall = false;
 //>>excludeEnd("ctx");;
-statements=$recv($recv(closure)._sequence())._dagChildren();
+sequence=$recv(closure)._sequence();
+statements=$recv(sequence)._dagChildren();
 $recv(statements)._ifNotEmpty_((function(){
+var final;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx2) {
 //>>excludeEnd("ctx");
-$2=$recv(statements)._last();
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-$ctx2.sendIdx["last"]=1;
-//>>excludeEnd("ctx");
-$1=$recv($2)._yieldsValue();
+final=$recv(statements)._last();
+final;
+$1=$recv(final)._yieldsValue();
 if($core.assert($1)){
-$3=$recv(statements)._last();
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-$ctx2.sendIdx["last"]=2;
-//>>excludeEnd("ctx");
+$2=sequence;
+$3=final;
 $5=$recv($globals.IRReturn)._new();
-$recv($5)._add_($recv($recv(statements)._last())._copy());
+$recv($5)._add_($recv(final)._copy());
 $4=$recv($5)._yourself();
-return $recv($3)._replaceWith_($4);
+return $recv($2)._replace_with_($3,$4);
 };
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)});
+}, function($ctx2) {$ctx2.fillBlock({final:final},$ctx1,1)});
 //>>excludeEnd("ctx");
 }));
 return closure;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"inlineClosure:",{anIRClosure:anIRClosure,closure:closure,statements:statements},$globals.IRReturnInliner)});
+}, function($ctx1) {$ctx1.fill(self,"inlineClosure:",{anIRClosure:anIRClosure,closure:closure,sequence:sequence,statements:statements},$globals.IRReturnInliner)});
 //>>excludeEnd("ctx");
 },
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["anIRClosure"],
-source: "inlineClosure: anIRClosure\x0a\x09| closure statements |\x0a\x0a\x09closure := super inlineClosure: anIRClosure.\x0a\x09statements := closure sequence dagChildren.\x0a\x09\x0a\x09statements ifNotEmpty: [\x0a\x09\x09statements last yieldsValue ifTrue: [\x0a\x09\x09\x09statements last replaceWith: (IRReturn new\x0a\x09\x09\x09\x09add: statements last copy;\x0a\x09\x09\x09\x09yourself)] ].\x0a\x0a\x09^ closure",
+source: "inlineClosure: anIRClosure\x0a\x09| closure sequence statements |\x0a\x0a\x09closure := super inlineClosure: anIRClosure.\x0a\x09sequence := closure sequence.\x0a\x09statements := sequence dagChildren.\x0a\x09\x0a\x09statements ifNotEmpty: [\x0a\x09\x09| final |\x0a\x09\x09final := statements last.\x0a\x09\x09final yieldsValue ifTrue: [\x0a\x09\x09\x09sequence replace: final with: (IRReturn new\x0a\x09\x09\x09\x09add: final copy;\x0a\x09\x09\x09\x09yourself) ] ].\x0a\x0a\x09^ closure",
 referencedClasses: ["IRReturn"],
 //>>excludeEnd("ide");
-messageSends: ["inlineClosure:", "dagChildren", "sequence", "ifNotEmpty:", "ifTrue:", "yieldsValue", "last", "replaceWith:", "add:", "new", "copy", "yourself"]
+messageSends: ["inlineClosure:", "sequence", "dagChildren", "ifNotEmpty:", "last", "ifTrue:", "yieldsValue", "replace:with:", "add:", "new", "copy", "yourself"]
 }),
 $globals.IRReturnInliner);
 
@@ -2223,56 +2089,20 @@ selector: "inlineReturn:",
 protocol: 'inlining',
 fn: function (anIRReturn){
 var self=this;
-var return_;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
-return_=self._inlinedReturn();
-$recv($recv(anIRReturn)._dagChildren())._do_((function(each){
+return self._inlineSend_andReplace_($recv(anIRReturn)._expression(),anIRReturn);
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx2) {
-//>>excludeEnd("ctx");
-return $recv(return_)._add_(each);
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)});
-//>>excludeEnd("ctx");
-}));
-$recv(anIRReturn)._replaceWith_(return_);
-self._inlineSend_($recv(return_)._expression());
-return return_;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"inlineReturn:",{anIRReturn:anIRReturn,return_:return_},$globals.IRReturnInliner)});
+}, function($ctx1) {$ctx1.fill(self,"inlineReturn:",{anIRReturn:anIRReturn},$globals.IRReturnInliner)});
 //>>excludeEnd("ctx");
 },
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["anIRReturn"],
-source: "inlineReturn: anIRReturn\x0a\x09| return |\x0a\x09return := self inlinedReturn.\x0a\x09anIRReturn dagChildren do: [ :each |\x0a\x09\x09return add: each ].\x0a\x09anIRReturn replaceWith: return.\x0a\x09self inlineSend: return expression.\x0a\x09^ return",
+source: "inlineReturn: anIRReturn\x0a\x09^ self inlineSend: anIRReturn expression andReplace: anIRReturn",
 referencedClasses: [],
 //>>excludeEnd("ide");
-messageSends: ["inlinedReturn", "do:", "dagChildren", "add:", "replaceWith:", "inlineSend:", "expression"]
-}),
-$globals.IRReturnInliner);
-
-$core.addMethod(
-$core.method({
-selector: "inlinedReturn",
-protocol: 'factory',
-fn: function (){
-var self=this;
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx1) {
-//>>excludeEnd("ctx");
-return $recv($globals.IRInlinedReturn)._new();
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"inlinedReturn",{},$globals.IRReturnInliner)});
-//>>excludeEnd("ctx");
-},
-//>>excludeStart("ide", pragmas.excludeIdeData);
-args: [],
-source: "inlinedReturn\x0a\x09^ IRInlinedReturn new",
-referencedClasses: ["IRInlinedReturn"],
-//>>excludeEnd("ide");
-messageSends: ["new"]
+messageSends: ["inlineSend:andReplace:", "expression"]
 }),
 $globals.IRReturnInliner);
 

+ 34 - 82
src/Compiler-Inlining.st

@@ -1,22 +1,4 @@
 Smalltalk createPackage: 'Compiler-Inlining'!
-IRAssignment subclass: #IRInlinedAssignment
-	instanceVariableNames: ''
-	package: 'Compiler-Inlining'!
-!IRInlinedAssignment commentStamp!
-I represent an inlined assignment instruction.!
-
-!IRInlinedAssignment methodsFor: 'testing'!
-
-isInlined
-	^ true
-! !
-
-!IRInlinedAssignment methodsFor: 'visiting'!
-
-acceptDagVisitor: aVisitor
-	^ aVisitor visitIRInlinedAssignment: self
-! !
-
 IRClosure subclass: #IRInlinedClosure
 	instanceVariableNames: ''
 	package: 'Compiler-Inlining'!
@@ -35,24 +17,6 @@ acceptDagVisitor: aVisitor
 	aVisitor visitIRInlinedClosure: self
 ! !
 
-IRReturn subclass: #IRInlinedReturn
-	instanceVariableNames: ''
-	package: 'Compiler-Inlining'!
-!IRInlinedReturn commentStamp!
-I represent an inlined local return instruction.!
-
-!IRInlinedReturn methodsFor: 'testing'!
-
-isInlined
-	^ true
-! !
-
-!IRInlinedReturn methodsFor: 'visiting'!
-
-acceptDagVisitor: aVisitor
-	^ aVisitor visitIRInlinedReturn: self
-! !
-
 IRSend subclass: #IRInlinedSend
 	instanceVariableNames: ''
 	package: 'Compiler-Inlining'!
@@ -251,10 +215,6 @@ I am a specialized JavaScript translator able to write inlined IR instructions t
 
 !IRInliningJSTranslator methodsFor: 'visiting'!
 
-visitIRInlinedAssignment: anIRInlinedAssignment
-	self visit: anIRInlinedAssignment right
-!
-
 visitIRInlinedClosure: anIRInlinedClosure
 	self stream nextPutVars: (anIRInlinedClosure tempDeclarations collect: [ :each |
 		each name asVariableName ]).
@@ -299,10 +259,6 @@ visitIRInlinedIfTrueIfFalse: anIRInlinedIfTrueIfFalse
 		else: [ self visit: anIRInlinedIfTrueIfFalse dagChildren third ]
 !
 
-visitIRInlinedReturn: anIRInlinedReturn
-	self visit: anIRInlinedReturn expression
-!
-
 visitIRInlinedSequence: anIRInlinedSequence
 	anIRInlinedSequence dagChildren do: [ :each |
 		self stream nextPutStatementWith: [ self visit: each ]]
@@ -441,6 +397,14 @@ inlineSend: anIRSend
 	^ self
 		perform: self send selector
 		withArguments: self send arguments
+! !
+
+!IRSendInliner methodsFor: 'private'!
+
+inlineSend: anIRSend andReplace: anIRInstruction
+	anIRInstruction replaceWith: anIRSend.
+	self inlineSend: anIRSend.
+	^ anIRSend
 !
 
 inlinedSend: inlinedSend withBlock: anIRInstruction
@@ -495,7 +459,7 @@ shouldInline: anIRSend
 ! !
 
 IRSendInliner subclass: #IRAssignmentInliner
-	instanceVariableNames: 'assignment'
+	instanceVariableNames: 'target'
 	package: 'Compiler-Inlining'!
 !IRAssignmentInliner commentStamp!
 I inline message sends together with assignments by moving them around into the inline closure instructions.
@@ -514,38 +478,35 @@ Will produce:
 
 !IRAssignmentInliner methodsFor: 'accessing'!
 
-assignment
-	^ assignment
+target
+	^ target
 !
 
-assignment: aNode
-	assignment := aNode
+target: anObject
+	target := anObject
 ! !
 
 !IRAssignmentInliner methodsFor: 'inlining'!
 
 inlineAssignment: anIRAssignment
-	| inlinedAssignment |
-	self assignment: anIRAssignment.
-	inlinedAssignment := IRInlinedAssignment new.
-	anIRAssignment dagChildren do: [ :each |
-		inlinedAssignment add: each ].
-	anIRAssignment replaceWith: inlinedAssignment.
-	self inlineSend: inlinedAssignment right.
-	^ inlinedAssignment
+	self target: anIRAssignment left.
+	^ self inlineSend: anIRAssignment right andReplace: anIRAssignment
 !
 
 inlineClosure: anIRClosure
-	| closure statements |
+	| closure sequence statements |
 
 	closure := super inlineClosure: anIRClosure.
-	statements := closure sequence dagChildren.
+	sequence := closure sequence.
+	statements := sequence dagChildren.
 	
 	statements ifNotEmpty: [
-		statements last yieldsValue ifTrue: [
-			statements last replaceWith: (IRAssignment new
-				add: self assignment left;
-				add: statements last copy;
+		| final |
+		final := statements last.
+		final yieldsValue ifTrue: [
+			sequence replace: final with: (IRAssignment new
+				add: self target;
+				add: final copy;
 				yourself) ] ].
 
 	^ closure
@@ -557,37 +518,28 @@ IRSendInliner subclass: #IRReturnInliner
 !IRReturnInliner commentStamp!
 I inline message sends with inlined closure together with a return instruction.!
 
-!IRReturnInliner methodsFor: 'factory'!
-
-inlinedReturn
-	^ IRInlinedReturn new
-! !
-
 !IRReturnInliner methodsFor: 'inlining'!
 
 inlineClosure: anIRClosure
-	| closure statements |
+	| closure sequence statements |
 
 	closure := super inlineClosure: anIRClosure.
-	statements := closure sequence dagChildren.
+	sequence := closure sequence.
+	statements := sequence dagChildren.
 	
 	statements ifNotEmpty: [
-		statements last yieldsValue ifTrue: [
-			statements last replaceWith: (IRReturn new
-				add: statements last copy;
-				yourself)] ].
+		| final |
+		final := statements last.
+		final yieldsValue ifTrue: [
+			sequence replace: final with: (IRReturn new
+				add: final copy;
+				yourself) ] ].
 
 	^ closure
 !
 
 inlineReturn: anIRReturn
-	| return |
-	return := self inlinedReturn.
-	anIRReturn dagChildren do: [ :each |
-		return add: each ].
-	anIRReturn replaceWith: return.
-	self inlineSend: return expression.
-	^ return
+	^ self inlineSend: anIRReturn expression andReplace: anIRReturn
 ! !
 
 CodeGenerator subclass: #InliningCodeGenerator

+ 18 - 25
src/Kernel-Collections.js

@@ -1027,20 +1027,21 @@ return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
 var $1;
 $1=self._isEmpty();
-return $recv($1)._ifTrue_ifFalse_(aBlock,(function(){
+if($core.assert($1)){
+return $recv(aBlock)._value();
+} else {
 return self;
-
-}));
+};
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 }, function($ctx1) {$ctx1.fill(self,"ifEmpty:",{aBlock:aBlock},$globals.Collection)});
 //>>excludeEnd("ctx");
 },
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["aBlock"],
-source: "ifEmpty: aBlock\x0a\x09\x22Evaluate the given block with the receiver as argument, answering its value if the receiver is empty, otherwise answer the receiver. \x0a\x09Note that the fact that this method returns its argument in case the receiver is not empty allows one to write expressions like the following ones: \x0a\x09\x09self classifyMethodAs:\x0a\x09\x09\x09(myProtocol ifEmpty: ['As yet unclassified'])\x22\x0a\x09^ self isEmpty\x0a\x09\x09ifTrue: aBlock\x0a\x09\x09ifFalse: [ self ]",
+source: "ifEmpty: aBlock\x0a\x09\x22Evaluate the given block with the receiver as argument, answering its value if the receiver is empty, otherwise answer the receiver. \x0a\x09Note that the fact that this method returns its argument in case the receiver is not empty allows one to write expressions like the following ones: \x0a\x09\x09self classifyMethodAs:\x0a\x09\x09\x09(myProtocol ifEmpty: ['As yet unclassified'])\x22\x0a\x09^ self isEmpty\x0a\x09\x09ifTrue: \x22aBlock\x22 [ aBlock value ]\x0a\x09\x09ifFalse: [ self ]",
 referencedClasses: [],
 //>>excludeEnd("ide");
-messageSends: ["ifTrue:ifFalse:", "isEmpty"]
+messageSends: ["ifTrue:ifFalse:", "isEmpty", "value"]
 }),
 $globals.Collection);
 
@@ -1055,25 +1056,21 @@ return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
 var $1;
 $1=self._isEmpty();
-return $recv($1)._ifTrue_ifFalse_(aBlock,(function(){
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx2) {
-//>>excludeEnd("ctx");
+if($core.assert($1)){
+return $recv(aBlock)._value();
+} else {
 return $recv(anotherBlock)._value_(self);
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)});
-//>>excludeEnd("ctx");
-}));
+};
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 }, function($ctx1) {$ctx1.fill(self,"ifEmpty:ifNotEmpty:",{aBlock:aBlock,anotherBlock:anotherBlock},$globals.Collection)});
 //>>excludeEnd("ctx");
 },
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["aBlock", "anotherBlock"],
-source: "ifEmpty: aBlock ifNotEmpty: anotherBlock\x0a\x09^ self isEmpty\x0a\x09\x09ifTrue: aBlock\x0a\x09\x09ifFalse: [ anotherBlock value: self ]",
+source: "ifEmpty: aBlock ifNotEmpty: anotherBlock\x0a\x09^ self isEmpty\x0a\x09\x09ifTrue: \x22aBlock\x22 [ aBlock value ]\x0a\x09\x09ifFalse: [ anotherBlock value: self ]",
 referencedClasses: [],
 //>>excludeEnd("ide");
-messageSends: ["ifTrue:ifFalse:", "isEmpty", "value:"]
+messageSends: ["ifTrue:ifFalse:", "isEmpty", "value", "value:"]
 }),
 $globals.Collection);
 
@@ -1117,25 +1114,21 @@ return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
 var $1;
 $1=self._notEmpty();
-return $recv($1)._ifTrue_ifFalse_((function(){
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-return $core.withContext(function($ctx2) {
-//>>excludeEnd("ctx");
+if($core.assert($1)){
 return $recv(aBlock)._value_(self);
-//>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)});
-//>>excludeEnd("ctx");
-}),anotherBlock);
+} else {
+return $recv(anotherBlock)._value();
+};
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 }, function($ctx1) {$ctx1.fill(self,"ifNotEmpty:ifEmpty:",{aBlock:aBlock,anotherBlock:anotherBlock},$globals.Collection)});
 //>>excludeEnd("ctx");
 },
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["aBlock", "anotherBlock"],
-source: "ifNotEmpty: aBlock ifEmpty: anotherBlock\x0a\x09^ self notEmpty\x0a\x09\x09ifTrue: [ aBlock value: self ]\x0a\x09\x09ifFalse: anotherBlock",
+source: "ifNotEmpty: aBlock ifEmpty: anotherBlock\x0a\x09^ self notEmpty\x0a\x09\x09ifTrue: [ aBlock value: self ]\x0a\x09\x09ifFalse: \x22anotherBlock\x22 [ anotherBlock value ]",
 referencedClasses: [],
 //>>excludeEnd("ide");
-messageSends: ["ifTrue:ifFalse:", "notEmpty", "value:"]
+messageSends: ["ifTrue:ifFalse:", "notEmpty", "value:", "value"]
 }),
 $globals.Collection);
 

+ 3 - 3
src/Kernel-Collections.st

@@ -375,13 +375,13 @@ ifEmpty: aBlock
 		self classifyMethodAs:
 			(myProtocol ifEmpty: ['As yet unclassified'])"
 	^ self isEmpty
-		ifTrue: aBlock
+		ifTrue: "aBlock" [ aBlock value ]
 		ifFalse: [ self ]
 !
 
 ifEmpty: aBlock ifNotEmpty: anotherBlock
 	^ self isEmpty
-		ifTrue: aBlock
+		ifTrue: "aBlock" [ aBlock value ]
 		ifFalse: [ anotherBlock value: self ]
 !
 
@@ -394,7 +394,7 @@ ifNotEmpty: aBlock
 ifNotEmpty: aBlock ifEmpty: anotherBlock
 	^ self notEmpty
 		ifTrue: [ aBlock value: self ]
-		ifFalse: anotherBlock
+		ifFalse: "anotherBlock" [ anotherBlock value ]
 !
 
 includes: anObject

+ 12 - 14
src/Kernel-Objects.js

@@ -1765,22 +1765,21 @@ var self=this;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
-var $1;
-$1=self.__eq(true);
-return $recv($1)._ifTrue_ifFalse_(aBlock,(function(){
+if($core.assert(self)){
+return $recv(aBlock)._value();
+} else {
 return false;
-
-}));
+};
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 }, function($ctx1) {$ctx1.fill(self,"and:",{aBlock:aBlock},$globals.Boolean)});
 //>>excludeEnd("ctx");
 },
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["aBlock"],
-source: "and: aBlock\x0a\x09^ self = true\x0a\x09\x09ifTrue: aBlock\x0a\x09\x09ifFalse: [ false ]",
+source: "and: aBlock\x0a\x09^ self\x0a\x09\x09ifTrue: \x22aBlock\x22 [ aBlock value ]\x0a\x09\x09ifFalse: [ false ]",
 referencedClasses: [],
 //>>excludeEnd("ide");
-messageSends: ["ifTrue:ifFalse:", "="]
+messageSends: ["ifTrue:ifFalse:", "value"]
 }),
 $globals.Boolean);
 
@@ -2042,22 +2041,21 @@ var self=this;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
-var $1;
-$1=self.__eq(true);
-return $recv($1)._ifTrue_ifFalse_((function(){
+if($core.assert(self)){
 return true;
-
-}),aBlock);
+} else {
+return $recv(aBlock)._value();
+};
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 }, function($ctx1) {$ctx1.fill(self,"or:",{aBlock:aBlock},$globals.Boolean)});
 //>>excludeEnd("ctx");
 },
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["aBlock"],
-source: "or: aBlock\x0a\x09^ self = true\x0a\x09\x09ifTrue: [ true ]\x0a\x09\x09ifFalse: aBlock",
+source: "or: aBlock\x0a\x09^ self\x0a\x09\x09ifTrue: [ true ]\x0a\x09\x09ifFalse: \x22aBlock\x22 [ aBlock value ]",
 referencedClasses: [],
 //>>excludeEnd("ide");
-messageSends: ["ifTrue:ifFalse:", "="]
+messageSends: ["ifTrue:ifFalse:", "value"]
 }),
 $globals.Boolean);
 

+ 4 - 4
src/Kernel-Objects.st

@@ -451,8 +451,8 @@ I am directly mapped to JavaScript Boolean. The `true` and `false` objects are t
 !
 
 and: aBlock
-	^ self = true
-		ifTrue: aBlock
+	^ self
+		ifTrue: "aBlock" [ aBlock value ]
 		ifFalse: [ false ]
 !
 
@@ -487,9 +487,9 @@ not
 !
 
 or: aBlock
-	^ self = true
+	^ self
 		ifTrue: [ true ]
-		ifFalse: aBlock
+		ifFalse: "aBlock" [ aBlock value ]
 !
 
 | aBoolean