Browse Source

Semantic analyzer: fix referenced nodes visited multiple times

Herbert Vojčík 8 years ago
parent
commit
a547475e11
2 changed files with 68 additions and 11 deletions
  1. 52 8
      src/Compiler-Semantic.js
  2. 16 3
      src/Compiler-Semantic.st

+ 52 - 8
src/Compiler-Semantic.js

@@ -1730,7 +1730,7 @@ $globals.UnknownVar);
 
 
 
-$core.addClass('SemanticAnalyzer', $globals.NodeVisitor, ['currentScope', 'blockIndex', 'thePackage', 'theClass', 'classReferences', 'messageSends'], 'Compiler-Semantic');
+$core.addClass('SemanticAnalyzer', $globals.NodeVisitor, ['currentScope', 'blockIndex', 'thePackage', 'theClass', 'classReferences', 'messageSends', 'visitedRefIds'], 'Compiler-Semantic');
 //>>excludeStart("ide", pragmas.excludeIdeData);
 $globals.SemanticAnalyzer.comment="I semantically analyze the abstract syntax tree and annotate it with informations such as non local returns and variable scopes.";
 //>>excludeEnd("ide");
@@ -1844,6 +1844,39 @@ messageSends: ["value", "ifTrue:ifFalse:", "and:", "not", "includes:", "globalJs
 }),
 $globals.SemanticAnalyzer);
 
+$core.addMethod(
+$core.method({
+selector: "initialize",
+protocol: 'initialization',
+fn: function (){
+var self=this;
+function $Set(){return $globals.Set||(typeof Set=="undefined"?nil:Set)}
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+(
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.supercall = true, 
+//>>excludeEnd("ctx");
+($globals.SemanticAnalyzer.superclass||$boot.dnu).fn.prototype._initialize.apply($recv(self), []));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.supercall = false;
+//>>excludeEnd("ctx");;
+self["@visitedRefIds"]=$recv($Set())._new();
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"initialize",{},$globals.SemanticAnalyzer)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "initialize\x0a\x09super initialize.\x0a\x0a\x09visitedRefIds := Set new",
+referencedClasses: ["Set"],
+//>>excludeEnd("ide");
+messageSends: ["initialize", "new"]
+}),
+$globals.SemanticAnalyzer);
+
 $core.addMethod(
 $core.method({
 selector: "isVariableUndefined:inPackage:",
@@ -2380,12 +2413,21 @@ selector: "visitRefNode:",
 protocol: 'visiting',
 fn: function (aNode){
 var self=this;
+var ref,aux;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 return $core.withContext(function($ctx1) {
 //>>excludeEnd("ctx");
-var $1;
-$recv($recv(aNode)._node())._shouldBeAliased_(true);
-$1=(
+var $1,$2;
+ref=$recv(aNode)._node();
+aux=$recv(self["@visitedRefIds"])._size();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["size"]=1;
+//>>excludeEnd("ctx");
+$recv(self["@visitedRefIds"])._add_($recv(ref)._nodeId());
+$1=$recv(aux).__lt($recv(self["@visitedRefIds"])._size());
+if($core.assert($1)){
+$recv(ref)._shouldBeAliased_(true);
+$2=(
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 $ctx1.supercall = true, 
 //>>excludeEnd("ctx");
@@ -2393,17 +2435,19 @@ $ctx1.supercall = true,
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
 $ctx1.supercall = false;
 //>>excludeEnd("ctx");;
-return $1;
+return $2;
+};
+return self;
 //>>excludeStart("ctx", pragmas.excludeDebugContexts);
-}, function($ctx1) {$ctx1.fill(self,"visitRefNode:",{aNode:aNode},$globals.SemanticAnalyzer)});
+}, function($ctx1) {$ctx1.fill(self,"visitRefNode:",{aNode:aNode,ref:ref,aux:aux},$globals.SemanticAnalyzer)});
 //>>excludeEnd("ctx");
 },
 //>>excludeStart("ide", pragmas.excludeIdeData);
 args: ["aNode"],
-source: "visitRefNode: aNode\x0a\x09aNode node shouldBeAliased: true.\x0a\x09^ super visitRefNode: aNode",
+source: "visitRefNode: aNode\x0a\x09| ref aux |\x0a\x09ref := aNode node.\x0a\x09aux := visitedRefIds size.\x0a\x09visitedRefIds add: ref nodeId.\x0a\x09aux < visitedRefIds size \x22added; not visited yet\x22 ifTrue: [\x0a\x09\x09ref shouldBeAliased: true.\x0a\x09\x09^ super visitRefNode: aNode ]",
 referencedClasses: [],
 //>>excludeEnd("ide");
-messageSends: ["shouldBeAliased:", "node", "visitRefNode:"]
+messageSends: ["node", "size", "add:", "nodeId", "ifTrue:", "<", "shouldBeAliased:", "visitRefNode:"]
 }),
 $globals.SemanticAnalyzer);
 

+ 16 - 3
src/Compiler-Semantic.st

@@ -410,7 +410,7 @@ isUnknownVar
 ! !
 
 NodeVisitor subclass: #SemanticAnalyzer
-	instanceVariableNames: 'currentScope blockIndex thePackage theClass classReferences messageSends'
+	instanceVariableNames: 'currentScope blockIndex thePackage theClass classReferences messageSends visitedRefIds'
 	package: 'Compiler-Semantic'!
 !SemanticAnalyzer commentStamp!
 I semantically analyze the abstract syntax tree and annotate it with informations such as non local returns and variable scopes.!
@@ -487,6 +487,14 @@ newScopeOfClass: aLexicalScopeClass
 		yourself
 ! !
 
+!SemanticAnalyzer methodsFor: 'initialization'!
+
+initialize
+	super initialize.
+
+	visitedRefIds := Set new
+! !
+
 !SemanticAnalyzer methodsFor: 'private'!
 
 nextBlockIndex
@@ -577,8 +585,13 @@ visitMethodNode: aNode
 !
 
 visitRefNode: aNode
-	aNode node shouldBeAliased: true.
-	^ super visitRefNode: aNode
+	| ref aux |
+	ref := aNode node.
+	aux := visitedRefIds size.
+	visitedRefIds add: ref nodeId.
+	aux < visitedRefIds size "added; not visited yet" ifTrue: [
+		ref shouldBeAliased: true.
+		^ super visitRefNode: aNode ]
 !
 
 visitReturnNode: aNode