Browse Source

ScopeVar and children #isAssignable.

Herby Vojčík 4 years ago
parent
commit
6b1cbb2e43
4 changed files with 170 additions and 5 deletions
  1. 23 0
      lang/src/Compiler-AST.js
  2. 4 0
      lang/src/Compiler-AST.st
  3. 118 4
      lang/src/Compiler-Semantic.js
  4. 25 1
      lang/src/Compiler-Semantic.st

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

@@ -1561,6 +1561,29 @@ return self;
 }; }),
 $globals.VariableNode);
 
+$core.addMethod(
+$core.method({
+selector: "isAssignable",
+protocol: "testing",
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "isAssignable\x0a\x09^ self binding isAssignable",
+referencedClasses: [],
+//>>excludeEnd("ide");
+pragmas: [],
+messageSends: ["isAssignable", "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())._isAssignable();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"isAssignable",{})});
+//>>excludeEnd("ctx");
+}; }),
+$globals.VariableNode);
+
 $core.addMethod(
 $core.method({
 selector: "isImmutable",

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

@@ -404,6 +404,10 @@ value: anObject
 
 !VariableNode methodsFor: 'testing'!
 
+isAssignable
+	^ self binding isAssignable
+!
+
 isImmutable
 	^ self binding isImmutable
 !

+ 118 - 4
lang/src/Compiler-Semantic.js

@@ -1068,6 +1068,24 @@ return $recv($self._name())._asVariableName();
 }; }),
 $globals.ScopeVar);
 
+$core.addMethod(
+$core.method({
+selector: "isAssignable",
+protocol: "testing",
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "isAssignable\x0a\x09^ true",
+referencedClasses: [],
+//>>excludeEnd("ide");
+pragmas: [],
+messageSends: []
+}, function ($methodClass){ return function (){
+var self=this,$self=this;
+return true;
+
+}; }),
+$globals.ScopeVar);
+
 $core.addMethod(
 $core.method({
 selector: "isClassRefVar",
@@ -1300,6 +1318,30 @@ $core.addClass("AliasVar", $globals.ScopeVar, [], "Compiler-Semantic");
 //>>excludeStart("ide", pragmas.excludeIdeData);
 $globals.AliasVar.comment="I am an internally defined variable by the compiler";
 //>>excludeEnd("ide");
+$core.addMethod(
+$core.method({
+selector: "isAssignable",
+protocol: "testing",
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "isAssignable\x0a\x09self error: 'Alias variable is internal, it should never appear in normal variable context.'",
+referencedClasses: [],
+//>>excludeEnd("ide");
+pragmas: [],
+messageSends: ["error:"]
+}, function ($methodClass){ return function (){
+var self=this,$self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+$self._error_("Alias variable is internal, it should never appear in normal variable context.");
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"isAssignable",{})});
+//>>excludeEnd("ctx");
+}; }),
+$globals.AliasVar);
+
 $core.addMethod(
 $core.method({
 selector: "isImmutable",
@@ -1324,6 +1366,24 @@ $core.addClass("ArgVar", $globals.ScopeVar, [], "Compiler-Semantic");
 //>>excludeStart("ide", pragmas.excludeIdeData);
 $globals.ArgVar.comment="I am an argument of a method or block.";
 //>>excludeEnd("ide");
+$core.addMethod(
+$core.method({
+selector: "isAssignable",
+protocol: "testing",
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "isAssignable\x0a\x09^ false",
+referencedClasses: [],
+//>>excludeEnd("ide");
+pragmas: [],
+messageSends: []
+}, function ($methodClass){ return function (){
+var self=this,$self=this;
+return false;
+
+}; }),
+$globals.ArgVar);
+
 $core.addMethod(
 $core.method({
 selector: "isImmutable",
@@ -1371,6 +1431,24 @@ return "$globals.".__comma($self._name());
 }; }),
 $globals.ClassRefVar);
 
+$core.addMethod(
+$core.method({
+selector: "isAssignable",
+protocol: "testing",
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "isAssignable\x0a\x09^ false",
+referencedClasses: [],
+//>>excludeEnd("ide");
+pragmas: [],
+messageSends: []
+}, function ($methodClass){ return function (){
+var self=this,$self=this;
+return false;
+
+}; }),
+$globals.ClassRefVar);
+
 $core.addMethod(
 $core.method({
 selector: "isClassRefVar",
@@ -1413,6 +1491,24 @@ $core.addClass("ExternallyKnownVar", $globals.ScopeVar, [], "Compiler-Semantic")
 //>>excludeStart("ide", pragmas.excludeIdeData);
 $globals.ExternallyKnownVar.comment="I am a variable known externally (not in method scope).";
 //>>excludeEnd("ide");
+$core.addMethod(
+$core.method({
+selector: "isAssignable",
+protocol: "testing",
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "isAssignable\x0a\x09^ false",
+referencedClasses: [],
+//>>excludeEnd("ide");
+pragmas: [],
+messageSends: []
+}, function ($methodClass){ return function (){
+var self=this,$self=this;
+return false;
+
+}; }),
+$globals.ExternallyKnownVar);
+
 $core.addMethod(
 $core.method({
 selector: "isExternallyKnownVar",
@@ -1525,6 +1621,24 @@ return $self._name();
 }; }),
 $globals.PseudoVar);
 
+$core.addMethod(
+$core.method({
+selector: "isAssignable",
+protocol: "testing",
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "isAssignable\x0a\x09^ false",
+referencedClasses: [],
+//>>excludeEnd("ide");
+pragmas: [],
+messageSends: []
+}, function ($methodClass){ return function (){
+var self=this,$self=this;
+return false;
+
+}; }),
+$globals.PseudoVar);
+
 $core.addMethod(
 $core.method({
 selector: "isImmutable",
@@ -2261,11 +2375,11 @@ selector: "visitAssignmentNode:",
 protocol: "visiting",
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["aNode"],
-source: "visitAssignmentNode: aNode\x0a\x09| lhs |\x0a\x09super visitAssignmentNode: aNode.\x0a\x09lhs := aNode left.\x0a\x09lhs isImmutable ifTrue: [ self errorInvalidAssignment: lhs identifier ].\x0a\x09lhs assigned: true",
+source: "visitAssignmentNode: aNode\x0a\x09| lhs |\x0a\x09super visitAssignmentNode: aNode.\x0a\x09lhs := aNode left.\x0a\x09lhs isAssignable ifFalse: [ self errorInvalidAssignment: lhs identifier ].\x0a\x09lhs assigned: true",
 referencedClasses: [],
 //>>excludeEnd("ide");
 pragmas: [],
-messageSends: ["visitAssignmentNode:", "left", "ifTrue:", "isImmutable", "errorInvalidAssignment:", "identifier", "assigned:"]
+messageSends: ["visitAssignmentNode:", "left", "ifFalse:", "isAssignable", "errorInvalidAssignment:", "identifier", "assigned:"]
 }, function ($methodClass){ return function (aNode){
 var self=this,$self=this;
 var lhs;
@@ -2283,8 +2397,8 @@ $ctx1.supercall = true,
 //>>excludeEnd("ctx");
 ][0];
 lhs=$recv(aNode)._left();
-$1=$recv(lhs)._isImmutable();
-if($core.assert($1)){
+$1=$recv(lhs)._isAssignable();
+if(!$core.assert($1)){
 $self._errorInvalidAssignment_($recv(lhs)._identifier());
 }
 $recv(lhs)._assigned_(true);

+ 25 - 1
lang/src/Compiler-Semantic.st

@@ -233,6 +233,10 @@ scope: aScope
 
 !ScopeVar methodsFor: 'testing'!
 
+isAssignable
+	^ true
+!
+
 isClassRefVar
 	^ false
 !
@@ -277,6 +281,10 @@ I am an internally defined variable by the compiler!
 
 !AliasVar methodsFor: 'testing'!
 
+isAssignable
+	self error: 'Alias variable is internal, it should never appear in normal variable context.'
+!
+
 isImmutable
 	^ true
 ! !
@@ -289,6 +297,10 @@ I am an argument of a method or block.!
 
 !ArgVar methodsFor: 'testing'!
 
+isAssignable
+	^ false
+!
+
 isImmutable
 	^ true
 ! !
@@ -307,6 +319,10 @@ alias
 
 !ClassRefVar methodsFor: 'testing'!
 
+isAssignable
+	^ false
+!
+
 isClassRefVar
 	^ true
 !
@@ -323,6 +339,10 @@ I am a variable known externally (not in method scope).!
 
 !ExternallyKnownVar methodsFor: 'testing'!
 
+isAssignable
+	^ false
+!
+
 isExternallyKnownVar
 	^ true
 !
@@ -363,6 +383,10 @@ alias
 
 !PseudoVar methodsFor: 'testing'!
 
+isAssignable
+	^ false
+!
+
 isImmutable
 	^ true
 !
@@ -566,7 +590,7 @@ visitAssignmentNode: aNode
 	| lhs |
 	super visitAssignmentNode: aNode.
 	lhs := aNode left.
-	lhs isImmutable ifTrue: [ self errorInvalidAssignment: lhs identifier ].
+	lhs isAssignable ifFalse: [ self errorInvalidAssignment: lhs identifier ].
 	lhs assigned: true
 !