소스 검색

fix the interpreter to correctly interpret JS globals

Nicolas Petton 11 년 전
부모
커밋
d664d913c2
6개의 변경된 파일67개의 추가작업 그리고 19개의 파일을 삭제
  1. 16 8
      js/Compiler-Interpreter.deploy.js
  2. 17 9
      js/Compiler-Interpreter.js
  3. 11 0
      js/Compiler-Tests.deploy.js
  4. 16 0
      js/Compiler-Tests.js
  5. 3 2
      st/Compiler-Interpreter.st
  6. 4 0
      st/Compiler-Tests.st

+ 16 - 8
js/Compiler-Interpreter.deploy.js

@@ -2029,17 +2029,25 @@ selector: "visitVariableNode:",
 fn: function (aNode){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-var $1,$3,$2;
-$1=self;
-$3=_st(_st(aNode)._binding())._isInstanceVar();
-if(smalltalk.assert($3)){
-$2=_st(_st(self._context())._receiver())._instVarAt_(_st(aNode)._value());
+var $1,$2,$3,$5,$4;
+$1=_st(_st(aNode)._binding())._isUnknownVar();
+if(smalltalk.assert($1)){
+$2=self._push_(_st(window)._at_ifAbsent_(_st(aNode)._value(),(function(){
+return smalltalk.withContext(function($ctx2) {
+return self._error_("Unknown variable");
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})})));
+return $2;
+};
+$3=self;
+$5=_st(_st(aNode)._binding())._isInstanceVar();
+if(smalltalk.assert($5)){
+$4=_st(_st(self._context())._receiver())._instVarAt_(_st(aNode)._value());
 } else {
-$2=_st(self._context())._localAt_(_st(aNode)._value());
+$4=_st(self._context())._localAt_(_st(aNode)._value());
 };
-_st($1)._push_($2);
+_st($3)._push_($4);
 return self}, function($ctx1) {$ctx1.fill(self,"visitVariableNode:",{aNode:aNode},smalltalk.Interpreter)})},
-messageSends: ["push:", "ifTrue:ifFalse:", "instVarAt:", "value", "receiver", "context", "localAt:", "isInstanceVar", "binding"]}),
+messageSends: ["ifTrue:", "isUnknownVar", "binding", "push:", "at:ifAbsent:", "value", "error:", "ifTrue:ifFalse:", "isInstanceVar", "instVarAt:", "receiver", "context", "localAt:"]}),
 smalltalk.Interpreter);
 
 

+ 17 - 9
js/Compiler-Interpreter.js

@@ -2675,19 +2675,27 @@ category: 'visiting',
 fn: function (aNode){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
-var $1,$3,$2;
-$1=self;
-$3=_st(_st(aNode)._binding())._isInstanceVar();
-if(smalltalk.assert($3)){
-$2=_st(_st(self._context())._receiver())._instVarAt_(_st(aNode)._value());
+var $1,$2,$3,$5,$4;
+$1=_st(_st(aNode)._binding())._isUnknownVar();
+if(smalltalk.assert($1)){
+$2=self._push_(_st(window)._at_ifAbsent_(_st(aNode)._value(),(function(){
+return smalltalk.withContext(function($ctx2) {
+return self._error_("Unknown variable");
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})})));
+return $2;
+};
+$3=self;
+$5=_st(_st(aNode)._binding())._isInstanceVar();
+if(smalltalk.assert($5)){
+$4=_st(_st(self._context())._receiver())._instVarAt_(_st(aNode)._value());
 } else {
-$2=_st(self._context())._localAt_(_st(aNode)._value());
+$4=_st(self._context())._localAt_(_st(aNode)._value());
 };
-_st($1)._push_($2);
+_st($3)._push_($4);
 return self}, function($ctx1) {$ctx1.fill(self,"visitVariableNode:",{aNode:aNode},smalltalk.Interpreter)})},
 args: ["aNode"],
-source: "visitVariableNode: aNode\x0a\x09\x22TODO: what about other vars (JS globals for instance)?\x22\x0a\x09\x0a\x09self push: (aNode binding isInstanceVar\x0a\x09\x09ifTrue: [ self context receiver instVarAt: aNode value ]\x0a\x09\x09ifFalse: [ self context localAt: aNode value ])",
-messageSends: ["push:", "ifTrue:ifFalse:", "instVarAt:", "value", "receiver", "context", "localAt:", "isInstanceVar", "binding"],
+source: "visitVariableNode: aNode\x0a\x09aNode binding isUnknownVar ifTrue: [\x0a\x09\x09^ self push: (window at: aNode value ifAbsent: [ self error: 'Unknown variable' ]) ].\x0a\x09\x09\x0a\x09self push: (aNode binding isInstanceVar\x0a\x09\x09ifTrue: [ self context receiver instVarAt: aNode value ]\x0a\x09\x09ifFalse: [ self context localAt: aNode value ])",
+messageSends: ["ifTrue:", "isUnknownVar", "binding", "push:", "at:ifAbsent:", "value", "error:", "ifTrue:ifFalse:", "isInstanceVar", "instVarAt:", "receiver", "context", "localAt:"],
 referencedClasses: []
 }),
 smalltalk.Interpreter);

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

@@ -590,6 +590,17 @@ return self}, function($ctx1) {$ctx1.fill(self,"testDynamicDictionary",{},smallt
 messageSends: ["assert:equals:", "interpret:", "->"]}),
 smalltalk.InterpreterTest);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "testGlobalVar",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self._assert_equals_(self._interpret_("foo ^ window document title"),_st(_st(window)._document())._title());
+return self}, function($ctx1) {$ctx1.fill(self,"testGlobalVar",{},smalltalk.InterpreterTest)})},
+messageSends: ["assert:equals:", "interpret:", "title", "document"]}),
+smalltalk.InterpreterTest);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "testInlinedJSStatement",

+ 16 - 0
js/Compiler-Tests.js

@@ -785,6 +785,22 @@ referencedClasses: []
 }),
 smalltalk.InterpreterTest);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "testGlobalVar",
+category: 'tests',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self._assert_equals_(self._interpret_("foo ^ window document title"),_st(_st(window)._document())._title());
+return self}, function($ctx1) {$ctx1.fill(self,"testGlobalVar",{},smalltalk.InterpreterTest)})},
+args: [],
+source: "testGlobalVar\x0a\x09self assert: (self interpret: 'foo ^ window document title') equals: window document title",
+messageSends: ["assert:equals:", "interpret:", "title", "document"],
+referencedClasses: []
+}),
+smalltalk.InterpreterTest);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "testInlinedJSStatement",

+ 3 - 2
st/Compiler-Interpreter.st

@@ -967,8 +967,9 @@ visitValueNode: aNode
 !
 
 visitVariableNode: aNode
-	"TODO: what about other vars (JS globals for instance)?"
-	
+	aNode binding isUnknownVar ifTrue: [
+		^ self push: (window at: aNode value ifAbsent: [ self error: 'Unknown variable' ]) ].
+		
 	self push: (aNode binding isInstanceVar
 		ifTrue: [ self context receiver instVarAt: aNode value ]
 		ifFalse: [ self context localAt: aNode value ])

+ 4 - 0
st/Compiler-Tests.st

@@ -345,6 +345,10 @@ testDynamicDictionary
 	self assert: (self interpret: 'foo ^ #{1->1. 2->3}') equals: #{1->1. 2->3}
 !
 
+testGlobalVar
+	self assert: (self interpret: 'foo ^ window document title') equals: window document title
+!
+
 testInlinedJSStatement
 	self assert: (self interpret: 'foo <return 2+3>') equals: 5.