Browse Source

ScopeVar / ExpressionNode subtree #isIdempotent.

Treat ClassRefVar and ExternallyKnownVar
(in essence, out of scope 'global' vars)
as non-idempotent, so a few aliasings added.
Herby Vojčík 4 years ago
parent
commit
a9b97168d2

+ 8 - 4
cli/src/AmberCli.js

@@ -3111,7 +3111,9 @@ var self=this,$self=this;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
-$recv($globals.Transcript)._show_([$recv([$recv([$recv($recv(varName).__comma(": ")).__comma($recv($recv(value)._class())._name())
+var $1;
+$1=$globals.Transcript;
+$recv($1)._show_([$recv([$recv([$recv($recv(varName).__comma(": ")).__comma($recv($recv(value)._class())._name())
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 ,$ctx1.sendIdx[","]=3
 //>>excludeEnd("ctx");
@@ -3124,7 +3126,7 @@ $recv($globals.Transcript)._show_([$recv([$recv([$recv($recv(varName).__comma(":
 ,$ctx1.sendIdx[","]=1
 //>>excludeEnd("ctx");
 ][0]);
-$recv($globals.Transcript)._cr();
+$recv($1)._cr();
 $recv($self.interface)._prompt();
 return self;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
@@ -3149,8 +3151,10 @@ var self=this,$self=this;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
-$recv($globals.Transcript)._show_("Type :q to exit.");
-$recv($globals.Transcript)._cr();
+var $1;
+$1=$globals.Transcript;
+$recv($1)._show_("Type :q to exit.");
+$recv($1)._cr();
 return self;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 }, function($ctx1) {$ctx1.fill(self,"printWelcome",{})});

+ 64 - 0
lang/src/Compiler-AST.js

@@ -404,6 +404,24 @@ $core.addClass("ExpressionNode", $globals.ASTNode, ["shouldBeAliased"], "Compile
 //>>excludeStart("ide", pragmas.excludeIdeData);
 $globals.ExpressionNode.comment="I am the abstract root class for expression nodes.";
 //>>excludeEnd("ide");
+$core.addMethod(
+$core.method({
+selector: "isIdempotent",
+protocol: "testing",
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "isIdempotent\x0a\x09^ false",
+referencedClasses: [],
+//>>excludeEnd("ide");
+pragmas: [],
+messageSends: []
+}, function ($methodClass){ return function (){
+var self=this,$self=this;
+return false;
+
+}; }),
+$globals.ExpressionNode);
+
 $core.addMethod(
 $core.method({
 selector: "isImmutable",
@@ -1327,6 +1345,29 @@ return $recv(aVisitor)._visitValueNode_(self);
 }; }),
 $globals.ValueNode);
 
+$core.addMethod(
+$core.method({
+selector: "isIdempotent",
+protocol: "testing",
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "isIdempotent\x0a\x09^ self value isImmutable",
+referencedClasses: [],
+//>>excludeEnd("ide");
+pragmas: [],
+messageSends: ["isImmutable", "value"]
+}, function ($methodClass){ return function (){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $recv($self._value())._isImmutable();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"isIdempotent",{})});
+//>>excludeEnd("ctx");
+}; }),
+$globals.ValueNode);
+
 $core.addMethod(
 $core.method({
 selector: "isImmutable",
@@ -1584,6 +1625,29 @@ return $recv($self._binding())._isAssignable();
 }; }),
 $globals.VariableNode);
 
+$core.addMethod(
+$core.method({
+selector: "isIdempotent",
+protocol: "testing",
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "isIdempotent\x0a\x09^ self binding isIdempotent",
+referencedClasses: [],
+//>>excludeEnd("ide");
+pragmas: [],
+messageSends: ["isIdempotent", "binding"]
+}, function ($methodClass){ return function (){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+return $recv($self._binding())._isIdempotent();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"isIdempotent",{})});
+//>>excludeEnd("ctx");
+}; }),
+$globals.VariableNode);
+
 $core.addMethod(
 $core.method({
 selector: "isImmutable",

+ 12 - 0
lang/src/Compiler-AST.st

@@ -120,6 +120,10 @@ withTail: aCollection
 
 !ExpressionNode methodsFor: 'testing'!
 
+isIdempotent
+	^ false
+!
+
 isImmutable
 	^ false
 !
@@ -342,6 +346,10 @@ value: anObject
 
 !ValueNode methodsFor: 'testing'!
 
+isIdempotent
+	^ self value isImmutable
+!
+
 isImmutable
 	^ self value isImmutable
 ! !
@@ -408,6 +416,10 @@ isAssignable
 	^ self binding isAssignable
 !
 
+isIdempotent
+	^ self binding isIdempotent
+!
+
 isImmutable
 	^ self binding isImmutable
 !

+ 6 - 6
lang/src/Compiler-IR.js

@@ -46,11 +46,11 @@ selector: "alias:",
 protocol: "visiting",
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["anExpressionNode"],
-source: "alias: anExpressionNode\x0a\x09| variable |\x0a\x0a\x09anExpressionNode isImmutable ifTrue: [ ^ self visit: anExpressionNode ].\x0a\x0a\x09variable := IRVariable new\x0a\x09\x09variable: (AliasVar new name: '$', self nextAlias);\x0a\x09\x09yourself.\x0a\x0a\x09self addToSequence: (IRAssignment new\x0a\x09\x09add: variable;\x0a\x09\x09add: (self visit: anExpressionNode);\x0a\x09\x09yourself).\x0a\x0a\x09self method internalVariables add: variable.\x0a\x0a\x09^ variable",
+source: "alias: anExpressionNode\x0a\x09| variable |\x0a\x0a\x09anExpressionNode isIdempotent ifTrue: [ ^ self visit: anExpressionNode ].\x0a\x0a\x09variable := IRVariable new\x0a\x09\x09variable: (AliasVar new name: '$', self nextAlias);\x0a\x09\x09yourself.\x0a\x0a\x09self addToSequence: (IRAssignment new\x0a\x09\x09add: variable;\x0a\x09\x09add: (self visit: anExpressionNode);\x0a\x09\x09yourself).\x0a\x0a\x09self method internalVariables add: variable.\x0a\x0a\x09^ variable",
 referencedClasses: ["IRVariable", "AliasVar", "IRAssignment"],
 //>>excludeEnd("ide");
 pragmas: [],
-messageSends: ["ifTrue:", "isImmutable", "visit:", "variable:", "new", "name:", ",", "nextAlias", "yourself", "addToSequence:", "add:", "internalVariables", "method"]
+messageSends: ["ifTrue:", "isIdempotent", "visit:", "variable:", "new", "name:", ",", "nextAlias", "yourself", "addToSequence:", "add:", "internalVariables", "method"]
 }, function ($methodClass){ return function (anExpressionNode){
 var self=this,$self=this;
 var variable;
@@ -58,7 +58,7 @@ var variable;
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
 var $1,$2,$4,$3;
-$1=$recv(anExpressionNode)._isImmutable();
+$1=$recv(anExpressionNode)._isIdempotent();
 if($core.assert($1)){
 return [$self._visit_(anExpressionNode)
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
@@ -556,11 +556,11 @@ selector: "visitCascadeNode:",
 protocol: "visiting",
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["aNode"],
-source: "visitCascadeNode: aNode\x0a\x09| receiver |\x0a\x09receiver := aNode receiver.\x0a\x09receiver isImmutable ifFalse: [\x0a\x09\x09| alias |\x0a\x09\x09alias := self alias: receiver.\x0a\x09\x09receiver := VariableNode new binding: alias variable ].\x0a\x09aNode dagChildren do: [ :each | each receiver: receiver ].\x0a\x0a\x09aNode dagChildren allButLast do: [ :each |\x0a\x09\x09self addToSequence: (self visit: each) ].\x0a\x0a\x09^ self visitOrAlias: aNode dagChildren last",
+source: "visitCascadeNode: aNode\x0a\x09| receiver |\x0a\x09receiver := aNode receiver.\x0a\x09receiver isIdempotent ifFalse: [\x0a\x09\x09| alias |\x0a\x09\x09alias := self alias: receiver.\x0a\x09\x09receiver := VariableNode new binding: alias variable ].\x0a\x09aNode dagChildren do: [ :each | each receiver: receiver ].\x0a\x0a\x09aNode dagChildren allButLast do: [ :each |\x0a\x09\x09self addToSequence: (self visit: each) ].\x0a\x0a\x09^ self visitOrAlias: aNode dagChildren last",
 referencedClasses: ["VariableNode"],
 //>>excludeEnd("ide");
 pragmas: [],
-messageSends: ["receiver", "ifFalse:", "isImmutable", "alias:", "binding:", "new", "variable", "do:", "dagChildren", "receiver:", "allButLast", "addToSequence:", "visit:", "visitOrAlias:", "last"]
+messageSends: ["receiver", "ifFalse:", "isIdempotent", "alias:", "binding:", "new", "variable", "do:", "dagChildren", "receiver:", "allButLast", "addToSequence:", "visit:", "visitOrAlias:", "last"]
 }, function ($methodClass){ return function (aNode){
 var self=this,$self=this;
 var receiver;
@@ -569,7 +569,7 @@ return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
 var $1;
 receiver=$recv(aNode)._receiver();
-$1=$recv(receiver)._isImmutable();
+$1=$recv(receiver)._isIdempotent();
 if(!$core.assert($1)){
 var alias;
 alias=$self._alias_(receiver);

+ 2 - 2
lang/src/Compiler-IR.st

@@ -66,7 +66,7 @@ addToSequence: anInstruction
 alias: anExpressionNode
 	| variable |
 
-	anExpressionNode isImmutable ifTrue: [ ^ self visit: anExpressionNode ].
+	anExpressionNode isIdempotent ifTrue: [ ^ self visit: anExpressionNode ].
 
 	variable := IRVariable new
 		variable: (AliasVar new name: '$', self nextAlias);
@@ -143,7 +143,7 @@ visitBlockSequenceNode: aNode
 visitCascadeNode: aNode
 	| receiver |
 	receiver := aNode receiver.
-	receiver isImmutable ifFalse: [
+	receiver isIdempotent ifFalse: [
 		| alias |
 		alias := self alias: receiver.
 		receiver := VariableNode new binding: alias variable ].

+ 72 - 0
lang/src/Compiler-Semantic.js

@@ -1122,6 +1122,24 @@ return false;
 }; }),
 $globals.ScopeVar);
 
+$core.addMethod(
+$core.method({
+selector: "isIdempotent",
+protocol: "testing",
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "isIdempotent\x0a\x09^ false",
+referencedClasses: [],
+//>>excludeEnd("ide");
+pragmas: [],
+messageSends: []
+}, function ($methodClass){ return function (){
+var self=this,$self=this;
+return false;
+
+}; }),
+$globals.ScopeVar);
+
 $core.addMethod(
 $core.method({
 selector: "isImmutable",
@@ -1342,6 +1360,24 @@ return self;
 }; }),
 $globals.AliasVar);
 
+$core.addMethod(
+$core.method({
+selector: "isIdempotent",
+protocol: "testing",
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "isIdempotent\x0a\x09^ true",
+referencedClasses: [],
+//>>excludeEnd("ide");
+pragmas: [],
+messageSends: []
+}, function ($methodClass){ return function (){
+var self=this,$self=this;
+return true;
+
+}; }),
+$globals.AliasVar);
+
 $core.addMethod(
 $core.method({
 selector: "isImmutable",
@@ -1384,6 +1420,24 @@ return false;
 }; }),
 $globals.ArgVar);
 
+$core.addMethod(
+$core.method({
+selector: "isIdempotent",
+protocol: "testing",
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "isIdempotent\x0a\x09^ true",
+referencedClasses: [],
+//>>excludeEnd("ide");
+pragmas: [],
+messageSends: []
+}, function ($methodClass){ return function (){
+var self=this,$self=this;
+return true;
+
+}; }),
+$globals.ArgVar);
+
 $core.addMethod(
 $core.method({
 selector: "isImmutable",
@@ -1639,6 +1693,24 @@ return false;
 }; }),
 $globals.PseudoVar);
 
+$core.addMethod(
+$core.method({
+selector: "isIdempotent",
+protocol: "testing",
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "isIdempotent\x0a\x09^ true",
+referencedClasses: [],
+//>>excludeEnd("ide");
+pragmas: [],
+messageSends: []
+}, function ($methodClass){ return function (){
+var self=this,$self=this;
+return true;
+
+}; }),
+$globals.PseudoVar);
+
 $core.addMethod(
 $core.method({
 selector: "isImmutable",

+ 16 - 0
lang/src/Compiler-Semantic.st

@@ -245,6 +245,10 @@ isExternallyKnownVar
 	^ false
 !
 
+isIdempotent
+	^ false
+!
+
 isImmutable
 	^ false
 !
@@ -285,6 +289,10 @@ isAssignable
 	self error: 'Alias variable is internal, it should never appear in normal variable context.'
 !
 
+isIdempotent
+	^ true
+!
+
 isImmutable
 	^ true
 ! !
@@ -301,6 +309,10 @@ isAssignable
 	^ false
 !
 
+isIdempotent
+	^ true
+!
+
 isImmutable
 	^ true
 ! !
@@ -387,6 +399,10 @@ isAssignable
 	^ false
 !
 
+isIdempotent
+	^ true
+!
+
 isImmutable
 	^ true
 !

+ 10 - 8
lang/src/Kernel-Classes.js

@@ -3394,12 +3394,13 @@ var self=this,$self=this;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
-var $1,$receiver;
-if(($receiver = $globals.Smalltalk) == null || $receiver.a$nil){
-$globals.Smalltalk;
-} else {
-$1=$self._basicAt_("category");
+var $1,$2,$receiver;
+$1=$globals.Smalltalk;
 if(($receiver = $1) == null || $receiver.a$nil){
+$1;
+} else {
+$2=$self._basicAt_("category");
+if(($receiver = $2) == null || $receiver.a$nil){
 [$self._basicPackage_(nil)
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 ,$ctx1.sendIdx["basicPackage:"]=1
@@ -3435,9 +3436,10 @@ var self=this,$self=this;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
-var $receiver;
-if(($receiver = $globals.Smalltalk) == null || $receiver.a$nil){
-$globals.Smalltalk;
+var $1,$receiver;
+$1=$globals.Smalltalk;
+if(($receiver = $1) == null || $receiver.a$nil){
+$1;
 } else {
 $recv($recv($self._package())._organization())._removeElement_(self);
 }

+ 3 - 2
lang/src/Platform-Browser.js

@@ -124,8 +124,9 @@ var self=this,$self=this;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
-var $receiver;
-if(($receiver = $globals.XMLHttpRequest) == null || $receiver.a$nil){
+var $1,$receiver;
+$1=$globals.XMLHttpRequest;
+if(($receiver = $1) == null || $receiver.a$nil){
 $self._error_("XMLHttpRequest not available.");
 } else {
 return $recv($globals.NativeFunction)._constructorOf_($globals.XMLHttpRequest);

+ 3 - 2
lang/src/Platform-Node.js

@@ -124,8 +124,9 @@ var self=this,$self=this;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
-var $receiver;
-if(($receiver = $globals.XMLHttpRequest) == null || $receiver.a$nil){
+var $1,$receiver;
+$1=$globals.XMLHttpRequest;
+if(($receiver = $1) == null || $receiver.a$nil){
 $self._error_("XMLHttpRequest not available.");
 } else {
 return $recv($globals.XMLHttpRequest)._new();