ソースを参照

Fixes #190.

SInce the complete expression is long:
```
smalltalk.Foo||typeof Foo=="undefined"?nil:Foo
```
it is put as inner function $Foo into method and called as `$Foo()`
whenever the global is accessed.
Herbert Vojčík 11 年 前
コミット
0ff2b2c7bb

+ 26 - 1
js/Compiler-IR.deploy.js

@@ -1999,6 +1999,9 @@ return smalltalk.withContext(function($ctx2) {
return _st(_st(self)._stream())._
 return smalltalk.withContext(function($ctx3) {
_st(_st(self)._stream())._nextPutVars_(_st(_st(anIRMethod)._tempDeclarations())._collect_((function(each){
 return smalltalk.withContext(function($ctx4) {
return _st(_st(each)._name())._asVariableName();
 }, function($ctx4) {$ctx4.fillBlock({each:each},$ctx1)})})));
+_st(_st(anIRMethod)._classReferences())._do_((function(each){
+return smalltalk.withContext(function($ctx4) {
return _st(_st(self)._stream())._nextPutClassRefFunction_(each);
+}, function($ctx4) {$ctx4.fillBlock({each:each},$ctx1)})}));
 return _st(_st(self)._stream())._nextPutContextFor_during_(anIRMethod,(function(){
 return smalltalk.withContext(function($ctx4) {
$1=_st(_st(anIRMethod)._internalVariables())._notEmpty();
 if(smalltalk.assert($1)){
@@ -2018,7 +2021,7 @@ return smalltalk.IRVisitor.fn.prototype._visitIRMethod_.apply(_st(self), [anIRMe
 }, function($ctx3) {$ctx3.fillBlock({},$ctx1)})}),_st(anIRMethod)._arguments());
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"visitIRMethod:",{anIRMethod:anIRMethod},smalltalk.IRJSTranslator)})},
-messageSends: ["nextPutMethodDeclaration:with:", "nextPutFunctionWith:arguments:", "nextPutVars:", "collect:", "asVariableName", "name", "tempDeclarations", "stream", "nextPutContextFor:during:", "ifTrue:", "alias", "variable", "asArray", "internalVariables", "notEmpty", "ifTrue:ifFalse:", "nextPutNonLocalReturnHandlingWith:", "visitIRMethod:", "hasNonLocalReturn", "scope", "arguments"]}),
+messageSends: ["nextPutMethodDeclaration:with:", "nextPutFunctionWith:arguments:", "nextPutVars:", "collect:", "asVariableName", "name", "tempDeclarations", "stream", "do:", "nextPutClassRefFunction:", "classReferences", "nextPutContextFor:during:", "ifTrue:", "alias", "variable", "asArray", "internalVariables", "notEmpty", "ifTrue:ifFalse:", "nextPutNonLocalReturnHandlingWith:", "visitIRMethod:", "hasNonLocalReturn", "scope", "arguments"]}),
 smalltalk.IRJSTranslator);
 
 smalltalk.addMethod(
@@ -2252,6 +2255,28 @@ return self}, function($ctx1) {$ctx1.fill(self,"nextPutBlockContextFor:during:",
 messageSends: ["nextPutAll:", ",", "alias", "scope", "cr", "value", "do:separatedBy:", "asVariableName", "locals", "method"]}),
 smalltalk.JSStream);
 
+smalltalk.addMethod(
+"_nextPutClassRefFunction_",
+smalltalk.method({
+selector: "nextPutClassRefFunction:",
+fn: function (aString){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
+$1=self["@stream"];
+_st($1)._nextPutAll_("function $");
+_st($1)._nextPutAll_(aString);
+_st($1)._nextPutAll_("(){return smalltalk.");
+_st($1)._nextPutAll_(aString);
+_st($1)._nextPutAll_("||(typeof ");
+_st($1)._nextPutAll_(aString);
+_st($1)._nextPutAll_("==\x22undefined\x22?nil:");
+_st($1)._nextPutAll_(aString);
+_st($1)._nextPutAll_(")}");
+$2=_st($1)._lf();
+return self}, function($ctx1) {$ctx1.fill(self,"nextPutClassRefFunction:",{aString:aString},smalltalk.JSStream)})},
+messageSends: ["nextPutAll:", "lf"]}),
+smalltalk.JSStream);
+
 smalltalk.addMethod(
 "_nextPutClosureWith_arguments_",
 smalltalk.method({

+ 32 - 2
js/Compiler-IR.js

@@ -2699,6 +2699,9 @@ return smalltalk.withContext(function($ctx2) {
return _st(_st(self)._stream())._
 return smalltalk.withContext(function($ctx3) {
_st(_st(self)._stream())._nextPutVars_(_st(_st(anIRMethod)._tempDeclarations())._collect_((function(each){
 return smalltalk.withContext(function($ctx4) {
return _st(_st(each)._name())._asVariableName();
 }, function($ctx4) {$ctx4.fillBlock({each:each},$ctx1)})})));
+_st(_st(anIRMethod)._classReferences())._do_((function(each){
+return smalltalk.withContext(function($ctx4) {
return _st(_st(self)._stream())._nextPutClassRefFunction_(each);
+}, function($ctx4) {$ctx4.fillBlock({each:each},$ctx1)})}));
 return _st(_st(self)._stream())._nextPutContextFor_during_(anIRMethod,(function(){
 return smalltalk.withContext(function($ctx4) {
$1=_st(_st(anIRMethod)._internalVariables())._notEmpty();
 if(smalltalk.assert($1)){
@@ -2719,8 +2722,8 @@ return smalltalk.IRVisitor.fn.prototype._visitIRMethod_.apply(_st(self), [anIRMe
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"visitIRMethod:",{anIRMethod:anIRMethod},smalltalk.IRJSTranslator)})},
 args: ["anIRMethod"],
-source: "visitIRMethod: anIRMethod\x0a\x0a\x09self stream\x0a\x09\x09nextPutMethodDeclaration: anIRMethod\x0a\x09\x09with: [ self stream\x0a\x09\x09\x09nextPutFunctionWith: [\x0a\x09\x09\x09\x09self stream nextPutVars: (anIRMethod tempDeclarations collect: [ :each |\x0a\x09\x09\x09\x09\x09each name asVariableName ]).\x0a\x09\x09\x09\x09self stream nextPutContextFor: anIRMethod during: [\x0a\x09\x09\x09\x09anIRMethod internalVariables notEmpty ifTrue: [\x0a\x09\x09\x09\x09\x09self stream nextPutVars: (anIRMethod internalVariables asArray collect: [ :each |\x0a\x09\x09\x09\x09\x09\x09each variable alias ]) ].\x0a\x09\x09\x09\x09anIRMethod scope hasNonLocalReturn\x0a\x09\x09\x09\x09\x09ifTrue: [\x0a\x09\x09\x09\x09\x09\x09self stream nextPutNonLocalReturnHandlingWith: [\x0a\x09\x09\x09\x09\x09\x09\x09super visitIRMethod: anIRMethod ]]\x0a\x09\x09\x09\x09\x09ifFalse: [ super visitIRMethod: anIRMethod ]]]\x0a\x09\x09\x09arguments: anIRMethod arguments ]",
-messageSends: ["nextPutMethodDeclaration:with:", "nextPutFunctionWith:arguments:", "nextPutVars:", "collect:", "asVariableName", "name", "tempDeclarations", "stream", "nextPutContextFor:during:", "ifTrue:", "alias", "variable", "asArray", "internalVariables", "notEmpty", "ifTrue:ifFalse:", "nextPutNonLocalReturnHandlingWith:", "visitIRMethod:", "hasNonLocalReturn", "scope", "arguments"],
+source: "visitIRMethod: anIRMethod\x0a\x0a\x09self stream\x0a\x09\x09nextPutMethodDeclaration: anIRMethod\x0a\x09\x09with: [ self stream\x0a\x09\x09\x09nextPutFunctionWith: [\x0a\x09\x09\x09\x09self stream nextPutVars: (anIRMethod tempDeclarations collect: [ :each |\x0a\x09\x09\x09\x09\x09each name asVariableName ]).\x0a\x09\x09\x09\x09anIRMethod classReferences do: [ :each | self stream nextPutClassRefFunction: each ].\x0a\x09\x09\x09\x09self stream nextPutContextFor: anIRMethod during: [\x0a\x09\x09\x09\x09anIRMethod internalVariables notEmpty ifTrue: [\x0a\x09\x09\x09\x09\x09self stream nextPutVars: (anIRMethod internalVariables asArray collect: [ :each |\x0a\x09\x09\x09\x09\x09\x09each variable alias ]) ].\x0a\x09\x09\x09\x09anIRMethod scope hasNonLocalReturn\x0a\x09\x09\x09\x09\x09ifTrue: [\x0a\x09\x09\x09\x09\x09\x09self stream nextPutNonLocalReturnHandlingWith: [\x0a\x09\x09\x09\x09\x09\x09\x09super visitIRMethod: anIRMethod ]]\x0a\x09\x09\x09\x09\x09ifFalse: [ super visitIRMethod: anIRMethod ]]]\x0a\x09\x09\x09arguments: anIRMethod arguments ]",
+messageSends: ["nextPutMethodDeclaration:with:", "nextPutFunctionWith:arguments:", "nextPutVars:", "collect:", "asVariableName", "name", "tempDeclarations", "stream", "do:", "nextPutClassRefFunction:", "classReferences", "nextPutContextFor:during:", "ifTrue:", "alias", "variable", "asArray", "internalVariables", "notEmpty", "ifTrue:ifFalse:", "nextPutNonLocalReturnHandlingWith:", "visitIRMethod:", "hasNonLocalReturn", "scope", "arguments"],
 referencedClasses: []
 }),
 smalltalk.IRJSTranslator);
@@ -3031,6 +3034,33 @@ referencedClasses: ["String"]
 }),
 smalltalk.JSStream);
 
+smalltalk.addMethod(
+"_nextPutClassRefFunction_",
+smalltalk.method({
+selector: "nextPutClassRefFunction:",
+category: 'streaming',
+fn: function (aString){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
+$1=self["@stream"];
+_st($1)._nextPutAll_("function $");
+_st($1)._nextPutAll_(aString);
+_st($1)._nextPutAll_("(){return smalltalk.");
+_st($1)._nextPutAll_(aString);
+_st($1)._nextPutAll_("||(typeof ");
+_st($1)._nextPutAll_(aString);
+_st($1)._nextPutAll_("==\x22undefined\x22?nil:");
+_st($1)._nextPutAll_(aString);
+_st($1)._nextPutAll_(")}");
+$2=_st($1)._lf();
+return self}, function($ctx1) {$ctx1.fill(self,"nextPutClassRefFunction:",{aString:aString},smalltalk.JSStream)})},
+args: ["aString"],
+source: "nextPutClassRefFunction: aString\x0a\x09stream\x0a\x09\x09nextPutAll: 'function $';\x0a\x09\x09nextPutAll: aString;\x0a\x09\x09nextPutAll: '(){return smalltalk.';\x0a\x09\x09nextPutAll: aString;\x0a\x09\x09nextPutAll: '||(typeof ';\x0a\x09\x09nextPutAll: aString;\x0a\x09\x09nextPutAll: '==\x22undefined\x22?nil:';\x0a\x09\x09nextPutAll: aString;\x0a\x09\x09nextPutAll: ')}';\x0a\x09\x09lf",
+messageSends: ["nextPutAll:", "lf"],
+referencedClasses: []
+}),
+smalltalk.JSStream);
+
 smalltalk.addMethod(
 "_nextPutClosureWith_arguments_",
 smalltalk.method({

+ 1 - 1
js/Compiler-Semantic.deploy.js

@@ -776,7 +776,7 @@ selector: "alias",
 fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
var $1;
-$1=_st(_st(_st(_st("(smalltalk.").__comma(_st(self)._name())).__comma(" || ")).__comma(_st(self)._name())).__comma(")");
+$1=_st(_st("$").__comma(_st(self)._name())).__comma("()");
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"alias",{},smalltalk.ClassRefVar)})},
 messageSends: [",", "name"]}),

+ 2 - 2
js/Compiler-Semantic.js

@@ -1048,11 +1048,11 @@ category: 'accessing',
 fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
var $1;
-$1=_st(_st(_st(_st("(smalltalk.").__comma(_st(self)._name())).__comma(" || ")).__comma(_st(self)._name())).__comma(")");
+$1=_st(_st("$").__comma(_st(self)._name())).__comma("()");
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"alias",{},smalltalk.ClassRefVar)})},
 args: [],
-source: "alias\x0a\x09^ '(smalltalk.', self name, ' || ', self name, ')'",
+source: "alias\x0a\x09^ '$', self name, '()'",
 messageSends: [",", "name"],
 referencedClasses: []
 }),

+ 15 - 0
st/Compiler-IR.st

@@ -922,6 +922,7 @@ visitIRMethod: anIRMethod
 			nextPutFunctionWith: [
 				self stream nextPutVars: (anIRMethod tempDeclarations collect: [ :each |
 					each name asVariableName ]).
+				anIRMethod classReferences do: [ :each | self stream nextPutClassRefFunction: each ].
 				self stream nextPutContextFor: anIRMethod during: [
 				anIRMethod internalVariables notEmpty ifTrue: [
 					self stream nextPutVars: (anIRMethod internalVariables asArray collect: [ :each |
@@ -1053,6 +1054,20 @@ nextPutBlockContextFor: anIRClosure during: aBlock
 		nextPutAll: anIRClosure method scope alias, ')})'
 !
 
+nextPutClassRefFunction: aString
+	stream
+		nextPutAll: 'function $';
+		nextPutAll: aString;
+		nextPutAll: '(){return smalltalk.';
+		nextPutAll: aString;
+		nextPutAll: '||(typeof ';
+		nextPutAll: aString;
+		nextPutAll: '=="undefined"?nil:';
+		nextPutAll: aString;
+		nextPutAll: ')}';
+		lf
+!
+
 nextPutClosureWith: aBlock arguments: anArray
 	stream nextPutAll: '(function('.
 	anArray

+ 1 - 1
st/Compiler-Semantic.st

@@ -306,7 +306,7 @@ I am an class reference variable!
 !ClassRefVar methodsFor: 'accessing'!
 
 alias
-	^ '(smalltalk.', self name, ' || ', self name, ')'
+	^ '$', self name, '()'
 ! !
 
 !ClassRefVar methodsFor: 'testing'!