Преглед изворни кода

- Working inheritence, method linking and class initialization

Nicolas Petton пре 11 година
родитељ
комит
eb57f240ca

+ 23 - 1
js/Compiler-AST.deploy.js

@@ -453,7 +453,7 @@ smalltalk.JSStatementNode);
 
 
 
-smalltalk.addClass('MethodNode', smalltalk.Node, ['selector', 'arguments', 'source', 'scope', 'classReferences', 'messageSends'], 'Compiler-AST');
+smalltalk.addClass('MethodNode', smalltalk.Node, ['selector', 'arguments', 'source', 'scope', 'classReferences', 'messageSends', 'superSends'], 'Compiler-AST');
 smalltalk.addMethod(
 "_accept_",
 smalltalk.method({
@@ -605,6 +605,28 @@ return self}
 }),
 smalltalk.MethodNode);
 
+smalltalk.addMethod(
+"_superSends",
+smalltalk.method({
+selector: "superSends",
+fn: function (){
+var self=this;
+return self["@superSends"];
+}
+}),
+smalltalk.MethodNode);
+
+smalltalk.addMethod(
+"_superSends_",
+smalltalk.method({
+selector: "superSends:",
+fn: function (aCollection){
+var self=this;
+self["@superSends"]=aCollection;
+return self}
+}),
+smalltalk.MethodNode);
+
 
 
 smalltalk.addClass('ReturnNode', smalltalk.Node, ['scope'], 'Compiler-AST');

+ 33 - 1
js/Compiler-AST.js

@@ -629,7 +629,7 @@ smalltalk.JSStatementNode);
 
 
 
-smalltalk.addClass('MethodNode', smalltalk.Node, ['selector', 'arguments', 'source', 'scope', 'classReferences', 'messageSends'], 'Compiler-AST');
+smalltalk.addClass('MethodNode', smalltalk.Node, ['selector', 'arguments', 'source', 'scope', 'classReferences', 'messageSends', 'superSends'], 'Compiler-AST');
 smalltalk.addMethod(
 "_accept_",
 smalltalk.method({
@@ -846,6 +846,38 @@ referencedClasses: []
 }),
 smalltalk.MethodNode);
 
+smalltalk.addMethod(
+"_superSends",
+smalltalk.method({
+selector: "superSends",
+category: 'accessing',
+fn: function (){
+var self=this;
+return self["@superSends"];
+},
+args: [],
+source: "superSends\x0a\x09^ superSends",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.MethodNode);
+
+smalltalk.addMethod(
+"_superSends_",
+smalltalk.method({
+selector: "superSends:",
+category: 'accessing',
+fn: function (aCollection){
+var self=this;
+self["@superSends"]=aCollection;
+return self},
+args: ["aCollection"],
+source: "superSends: aCollection\x0a\x09superSends := aCollection",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.MethodNode);
+
 
 
 smalltalk.addClass('ReturnNode', smalltalk.Node, ['scope'], 'Compiler-AST');

+ 27 - 20
js/Compiler-IR.deploy.js

@@ -298,6 +298,7 @@ smalltalk.send($1,"_source_",[smalltalk.send(self,"_source",[])]);
 smalltalk.send($1,"_arguments_",[smalltalk.send(aNode,"_arguments",[])]);
 smalltalk.send($1,"_selector_",[smalltalk.send(aNode,"_selector",[])]);
 smalltalk.send($1,"_messageSends_",[smalltalk.send(aNode,"_messageSends",[])]);
+smalltalk.send($1,"_superSends_",[smalltalk.send(aNode,"_superSends",[])]);
 smalltalk.send($1,"_classReferences_",[smalltalk.send(aNode,"_classReferences",[])]);
 smalltalk.send($1,"_scope_",[smalltalk.send(aNode,"_scope",[])]);
 $2=smalltalk.send($1,"_yourself",[]);
@@ -845,7 +846,7 @@ smalltalk.IRClosure);
 
 
 
-smalltalk.addClass('IRMethod', smalltalk.IRScopedInstruction, ['source', 'selector', 'classReferences', 'messageSends', 'arguments', 'internalVariables'], 'Compiler-IR');
+smalltalk.addClass('IRMethod', smalltalk.IRScopedInstruction, ['source', 'selector', 'classReferences', 'messageSends', 'superSends', 'arguments', 'internalVariables'], 'Compiler-IR');
 smalltalk.addMethod(
 "_accept_",
 smalltalk.method({
@@ -999,6 +1000,28 @@ return self}
 }),
 smalltalk.IRMethod);
 
+smalltalk.addMethod(
+"_superSends",
+smalltalk.method({
+selector: "superSends",
+fn: function (){
+var self=this;
+return self["@superSends"];
+}
+}),
+smalltalk.IRMethod);
+
+smalltalk.addMethod(
+"_superSends_",
+smalltalk.method({
+selector: "superSends:",
+fn: function (aCollection){
+var self=this;
+self["@superSends"]=aCollection;
+return self}
+}),
+smalltalk.IRMethod);
+
 
 
 smalltalk.addClass('IRReturn', smalltalk.IRScopedInstruction, [], 'Compiler-IR');
@@ -2129,6 +2152,9 @@ smalltalk.send(aBlock,"_value",[]);
 smalltalk.send(self["@stream"],"_nextPutAll_",[smalltalk.send(smalltalk.send(",","__comma",[smalltalk.send((smalltalk.String || String),"_lf",[])]),"__comma",["messageSends: "])]);
 smalltalk.send(self["@stream"],"_nextPutAll_",[smalltalk.send(smalltalk.send(smalltalk.send(smalltalk.send(aMethod,"_messageSends",[]),"_asArray",[]),"_asJavascript",[]),"__comma",[","])]);
 smalltalk.send(self["@stream"],"_lf",[]);
+smalltalk.send(self["@stream"],"_nextPutAll_",["superSends: "]);
+smalltalk.send(self["@stream"],"_nextPutAll_",[smalltalk.send(smalltalk.send(smalltalk.send(smalltalk.send(aMethod,"_superSends",[]),"_asArray",[]),"_asJavascript",[]),"__comma",[","])]);
+smalltalk.send(self["@stream"],"_lf",[]);
 smalltalk.send(self["@stream"],"_nextPutAll_",[smalltalk.send(smalltalk.send("args: ","__comma",[smalltalk.send(smalltalk.send(smalltalk.send(smalltalk.send(aMethod,"_arguments",[]),"_collect_",[(function(each){
 return smalltalk.send(each,"_value",[]);
 })]),"_asArray",[]),"_asJavascript",[])]),"__comma",[","])]);
@@ -2201,25 +2227,6 @@ return self}
 }),
 smalltalk.JSStream);
 
-smalltalk.addMethod(
-"_nextPutSendTo_selector_arguments_",
-smalltalk.method({
-selector: "nextPutSendTo:selector:arguments:",
-fn: function (receiver,selector,arguments){
-var self=this;
-smalltalk.send(self["@stream"],"_nextPutAll_",["smalltalk.send("]);
-smalltalk.send(receiver,"_emitOn_",[self]);
-smalltalk.send(self["@stream"],"_nextPutAll_",[smalltalk.send(smalltalk.send(",\x22","__comma",[smalltalk.send(selector,"_asSelector",[])]),"__comma",["\x22,["])]);
-smalltalk.send(arguments,"_do_separatedBy_",[(function(each){
-return smalltalk.send(each,"_emitOn_",[self]);
-}),(function(){
-return smalltalk.send(self["@stream"],"_nextPutAll_",[","]);
-})]);
-smalltalk.send(self["@stream"],"_nextPutAll_",["])"]);
-return self}
-}),
-smalltalk.JSStream);
-
 smalltalk.addMethod(
 "_nextPutSequenceWith_",
 smalltalk.method({

+ 41 - 29
js/Compiler-IR.js

@@ -385,6 +385,7 @@ smalltalk.send($1,"_source_",[smalltalk.send(self,"_source",[])]);
 smalltalk.send($1,"_arguments_",[smalltalk.send(aNode,"_arguments",[])]);
 smalltalk.send($1,"_selector_",[smalltalk.send(aNode,"_selector",[])]);
 smalltalk.send($1,"_messageSends_",[smalltalk.send(aNode,"_messageSends",[])]);
+smalltalk.send($1,"_superSends_",[smalltalk.send(aNode,"_superSends",[])]);
 smalltalk.send($1,"_classReferences_",[smalltalk.send(aNode,"_classReferences",[])]);
 smalltalk.send($1,"_scope_",[smalltalk.send(aNode,"_scope",[])]);
 $2=smalltalk.send($1,"_yourself",[]);
@@ -409,8 +410,8 @@ $8=smalltalk.send(self,"_method",[]);
 return $8;
 },
 args: ["aNode"],
-source: "visitMethodNode: aNode\x0a\x0a\x09self method: (IRMethod new\x0a\x09\x09source: self source;\x0a\x09\x09arguments: aNode arguments;\x0a\x09\x09selector: aNode selector;\x0a\x09\x09messageSends: aNode messageSends;\x0a\x09\x09classReferences: aNode classReferences;\x0a\x09\x09scope: aNode scope;\x0a\x09\x09yourself).\x0a\x0a\x09aNode scope temps do: [ :each |\x0a\x09\x09self method add: (IRTempDeclaration new\x0a\x09\x09\x09name: each name;\x0a\x09\x09\x09yourself) ].\x0a\x0a\x09aNode nodes do: [ :each | self method add: (self visit: each) ].\x0a\x0a\x09aNode scope hasLocalReturn ifFalse: [\x0a\x09\x09(self method add: IRReturn new) add: (IRVariable new\x0a\x09\x09\x09variable: (aNode scope pseudoVars at: 'self');\x0a\x09\x09\x09yourself) ].\x0a\x0a\x09^ self method",
-messageSends: ["method:", "source:", "source", "new", "arguments:", "arguments", "selector:", "selector", "messageSends:", "messageSends", "classReferences:", "classReferences", "scope:", "scope", "yourself", "do:", "add:", "name:", "name", "method", "temps", "visit:", "nodes", "ifFalse:", "variable:", "at:", "pseudoVars", "hasLocalReturn"],
+source: "visitMethodNode: aNode\x0a\x0a\x09self method: (IRMethod new\x0a\x09\x09source: self source;\x0a\x09\x09arguments: aNode arguments;\x0a\x09\x09selector: aNode selector;\x0a\x09\x09messageSends: aNode messageSends;\x0a        superSends: aNode superSends;\x0a\x09\x09classReferences: aNode classReferences;\x0a\x09\x09scope: aNode scope;\x0a\x09\x09yourself).\x0a\x0a\x09aNode scope temps do: [ :each |\x0a\x09\x09self method add: (IRTempDeclaration new\x0a\x09\x09\x09name: each name;\x0a\x09\x09\x09yourself) ].\x0a\x0a\x09aNode nodes do: [ :each | self method add: (self visit: each) ].\x0a\x0a\x09aNode scope hasLocalReturn ifFalse: [\x0a\x09\x09(self method add: IRReturn new) add: (IRVariable new\x0a\x09\x09\x09variable: (aNode scope pseudoVars at: 'self');\x0a\x09\x09\x09yourself) ].\x0a\x0a\x09^ self method",
+messageSends: ["method:", "source:", "source", "new", "arguments:", "arguments", "selector:", "selector", "messageSends:", "messageSends", "superSends:", "superSends", "classReferences:", "classReferences", "scope:", "scope", "yourself", "do:", "add:", "name:", "name", "method", "temps", "visit:", "nodes", "ifFalse:", "variable:", "at:", "pseudoVars", "hasLocalReturn"],
 referencedClasses: ["IRMethod", "IRTempDeclaration", "IRVariable", "IRReturn"]
 }),
 smalltalk.IRASTTranslator);
@@ -1117,7 +1118,7 @@ smalltalk.IRClosure);
 
 
 
-smalltalk.addClass('IRMethod', smalltalk.IRScopedInstruction, ['source', 'selector', 'classReferences', 'messageSends', 'arguments', 'internalVariables'], 'Compiler-IR');
+smalltalk.addClass('IRMethod', smalltalk.IRScopedInstruction, ['source', 'selector', 'classReferences', 'messageSends', 'superSends', 'arguments', 'internalVariables'], 'Compiler-IR');
 smalltalk.IRMethod.comment="I am a method instruction"
 smalltalk.addMethod(
 "_accept_",
@@ -1337,6 +1338,38 @@ referencedClasses: []
 }),
 smalltalk.IRMethod);
 
+smalltalk.addMethod(
+"_superSends",
+smalltalk.method({
+selector: "superSends",
+category: 'accessing',
+fn: function (){
+var self=this;
+return self["@superSends"];
+},
+args: [],
+source: "superSends\x0a\x09^ superSends",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.IRMethod);
+
+smalltalk.addMethod(
+"_superSends_",
+smalltalk.method({
+selector: "superSends:",
+category: 'accessing',
+fn: function (aCollection){
+var self=this;
+self["@superSends"]=aCollection;
+return self},
+args: ["aCollection"],
+source: "superSends: aCollection\x0a\x09superSends := aCollection",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.IRMethod);
+
 
 
 smalltalk.addClass('IRReturn', smalltalk.IRScopedInstruction, [], 'Compiler-IR');
@@ -2885,6 +2918,9 @@ smalltalk.send(aBlock,"_value",[]);
 smalltalk.send(self["@stream"],"_nextPutAll_",[smalltalk.send(smalltalk.send(",","__comma",[smalltalk.send((smalltalk.String || String),"_lf",[])]),"__comma",["messageSends: "])]);
 smalltalk.send(self["@stream"],"_nextPutAll_",[smalltalk.send(smalltalk.send(smalltalk.send(smalltalk.send(aMethod,"_messageSends",[]),"_asArray",[]),"_asJavascript",[]),"__comma",[","])]);
 smalltalk.send(self["@stream"],"_lf",[]);
+smalltalk.send(self["@stream"],"_nextPutAll_",["superSends: "]);
+smalltalk.send(self["@stream"],"_nextPutAll_",[smalltalk.send(smalltalk.send(smalltalk.send(smalltalk.send(aMethod,"_superSends",[]),"_asArray",[]),"_asJavascript",[]),"__comma",[","])]);
+smalltalk.send(self["@stream"],"_lf",[]);
 smalltalk.send(self["@stream"],"_nextPutAll_",[smalltalk.send(smalltalk.send("args: ","__comma",[smalltalk.send(smalltalk.send(smalltalk.send(smalltalk.send(aMethod,"_arguments",[]),"_collect_",[(function(each){
 return smalltalk.send(each,"_value",[]);
 })]),"_asArray",[]),"_asJavascript",[])]),"__comma",[","])]);
@@ -2899,8 +2935,8 @@ smalltalk.send(self["@stream"],"_nextPutAll_",["]"]);
 $3=smalltalk.send(self["@stream"],"_nextPutAll_",["})"]);
 return self},
 args: ["aMethod", "aBlock"],
-source: "nextPutMethodDeclaration: aMethod with: aBlock\x0a\x09stream \x0a\x09\x09nextPutAll: 'smalltalk.method({'; lf;\x0a\x09\x09nextPutAll: 'selector: \x22', aMethod selector, '\x22,'; lf;\x0a\x09\x09nextPutAll: 'source: ', aMethod source asJavascript, ',';lf.\x0a\x09aBlock value.\x0a\x09stream \x0a\x09\x09nextPutAll: ',', String lf, 'messageSends: ';\x0a\x09\x09nextPutAll: aMethod messageSends asArray asJavascript, ','; lf;\x0a          \x09nextPutAll: 'args: ', (aMethod arguments collect: [ :each | each value ]) asArray asJavascript, ','; lf;\x0a\x09\x09nextPutAll: 'referencedClasses: ['.\x0a\x09aMethod classReferences \x0a\x09\x09do: [:each | stream nextPutAll: each asJavascript]\x0a\x09\x09separatedBy: [stream nextPutAll: ','].\x0a\x09stream \x0a\x09\x09nextPutAll: ']';\x0a\x09\x09nextPutAll: '})'",
-messageSends: ["nextPutAll:", "lf", ",", "selector", "asJavascript", "source", "value", "asArray", "messageSends", "collect:", "arguments", "do:separatedBy:", "classReferences"],
+source: "nextPutMethodDeclaration: aMethod with: aBlock\x0a\x09stream \x0a\x09\x09nextPutAll: 'smalltalk.method({'; lf;\x0a\x09\x09nextPutAll: 'selector: \x22', aMethod selector, '\x22,'; lf;\x0a\x09\x09nextPutAll: 'source: ', aMethod source asJavascript, ',';lf.\x0a\x09aBlock value.\x0a\x09stream \x0a\x09\x09nextPutAll: ',', String lf, 'messageSends: ';\x0a\x09\x09nextPutAll: aMethod messageSends asArray asJavascript, ','; lf;\x0a\x09\x09nextPutAll: 'superSends: ';\x0a\x09\x09nextPutAll: aMethod superSends asArray asJavascript, ','; lf;\x0a        nextPutAll: 'args: ', (aMethod arguments collect: [ :each | each value ]) asArray asJavascript, ','; lf;\x0a\x09\x09nextPutAll: 'referencedClasses: ['.\x0a\x09aMethod classReferences \x0a\x09\x09do: [:each | stream nextPutAll: each asJavascript]\x0a\x09\x09separatedBy: [stream nextPutAll: ','].\x0a\x09stream \x0a\x09\x09nextPutAll: ']';\x0a\x09\x09nextPutAll: '})'",
+messageSends: ["nextPutAll:", "lf", ",", "selector", "asJavascript", "source", "value", "asArray", "messageSends", "superSends", "collect:", "arguments", "do:separatedBy:", "classReferences"],
 referencedClasses: ["String"]
 }),
 smalltalk.JSStream);
@@ -2981,30 +3017,6 @@ referencedClasses: []
 }),
 smalltalk.JSStream);
 
-smalltalk.addMethod(
-"_nextPutSendTo_selector_arguments_",
-smalltalk.method({
-selector: "nextPutSendTo:selector:arguments:",
-category: 'streaming',
-fn: function (receiver,selector,arguments){
-var self=this;
-smalltalk.send(self["@stream"],"_nextPutAll_",["smalltalk.send("]);
-smalltalk.send(receiver,"_emitOn_",[self]);
-smalltalk.send(self["@stream"],"_nextPutAll_",[smalltalk.send(smalltalk.send(",\x22","__comma",[smalltalk.send(selector,"_asSelector",[])]),"__comma",["\x22,["])]);
-smalltalk.send(arguments,"_do_separatedBy_",[(function(each){
-return smalltalk.send(each,"_emitOn_",[self]);
-}),(function(){
-return smalltalk.send(self["@stream"],"_nextPutAll_",[","]);
-})]);
-smalltalk.send(self["@stream"],"_nextPutAll_",["])"]);
-return self},
-args: ["receiver", "selector", "arguments"],
-source: "nextPutSendTo: receiver selector: selector arguments: arguments\x0a\x09stream nextPutAll: 'smalltalk.send('.\x0a\x09receiver emitOn: self. \x0a\x09stream nextPutAll: ',\x22', selector asSelector, '\x22,['.\x0a\x09arguments \x0a\x09\x09do: [ :each | each emitOn: self ]\x0a\x09\x09separatedBy: [ stream nextPutAll: ',' ].\x0a\x09stream nextPutAll: '])'",
-messageSends: ["nextPutAll:", "emitOn:", ",", "asSelector", "do:separatedBy:"],
-referencedClasses: []
-}),
-smalltalk.JSStream);
-
 smalltalk.addMethod(
 "_nextPutSequenceWith_",
 smalltalk.method({

+ 66 - 38
js/Compiler-Semantic.deploy.js

@@ -827,7 +827,7 @@ smalltalk.UnknownVar);
 
 
 
-smalltalk.addClass('SemanticAnalyzer', smalltalk.NodeVisitor, ['currentScope', 'theClass', 'classReferences', 'messageSends'], 'Compiler-Semantic');
+smalltalk.addClass('SemanticAnalyzer', smalltalk.NodeVisitor, ['currentScope', 'theClass', 'classReferences', 'messageSends', 'superSends'], 'Compiler-Semantic');
 smalltalk.addMethod(
 "_classReferences",
 smalltalk.method({
@@ -975,6 +975,24 @@ fn: function (aScope) {
 }),
 smalltalk.SemanticAnalyzer);
 
+smalltalk.addMethod(
+"_superSends",
+smalltalk.method({
+selector: "superSends",
+fn: function (){
+var self=this;
+var $1;
+if(($receiver = self["@superSends"]) == nil || $receiver == undefined){
+self["@superSends"]=smalltalk.send((smalltalk.Dictionary || Dictionary),"_new",[]);
+$1=self["@superSends"];
+} else {
+$1=self["@superSends"];
+};
+return $1;
+}
+}),
+smalltalk.SemanticAnalyzer);
+
 smalltalk.addMethod(
 "_theClass",
 smalltalk.method({
@@ -1084,20 +1102,25 @@ smalltalk.addMethod(
 "_visitMethodNode_",
 smalltalk.method({
 selector: "visitMethodNode:",
-fn: function (aNode) {
-    var self = this;
-    var $1;
-    smalltalk.send(self, "_pushScope_", [smalltalk.send(self, "_newMethodScope", [])]);
-    smalltalk.send(aNode, "_scope_", [self['@currentScope']]);
-    smalltalk.send(self['@currentScope'], "_node_", [aNode]);
-    smalltalk.send(smalltalk.send(smalltalk.send(self, "_theClass", []), "_allInstanceVariableNames", []), "_do_", [function (each) {return smalltalk.send(self['@currentScope'], "_addIVar_", [each]);}]);
-    smalltalk.send(smalltalk.send(aNode, "_arguments", []), "_do_", [function (each) {smalltalk.send(self, "_validateVariableScope_", [each]);return smalltalk.send(self['@currentScope'], "_addArg_", [each]);}]);
-    smalltalk.send(self, "_visitMethodNode_", [aNode], smalltalk.NodeVisitor);
-    smalltalk.send(aNode, "_classReferences_", [smalltalk.send(self, "_classReferences", [])]);
-    $1 = smalltalk.send(aNode, "_messageSends_", [smalltalk.send(smalltalk.send(self, "_messageSends", []), "_keys", [])]);
-    smalltalk.send(self, "_popScope", []);
-    return self;
-}
+fn: function (aNode){
+var self=this;
+var $1;
+smalltalk.send(self,"_pushScope_",[smalltalk.send(self,"_newMethodScope",[])]);
+smalltalk.send(aNode,"_scope_",[self["@currentScope"]]);
+smalltalk.send(self["@currentScope"],"_node_",[aNode]);
+smalltalk.send(smalltalk.send(smalltalk.send(self,"_theClass",[]),"_allInstanceVariableNames",[]),"_do_",[(function(each){
+return smalltalk.send(self["@currentScope"],"_addIVar_",[each]);
+})]);
+smalltalk.send(smalltalk.send(aNode,"_arguments",[]),"_do_",[(function(each){
+smalltalk.send(self,"_validateVariableScope_",[each]);
+return smalltalk.send(self["@currentScope"],"_addArg_",[each]);
+})]);
+smalltalk.send(self,"_visitMethodNode_",[aNode],smalltalk.NodeVisitor);
+smalltalk.send(aNode,"_classReferences_",[smalltalk.send(self,"_classReferences",[])]);
+smalltalk.send(aNode,"_messageSends_",[smalltalk.send(smalltalk.send(self,"_messageSends",[]),"_keys",[])]);
+$1=smalltalk.send(aNode,"_superSends_",[smalltalk.send(smalltalk.send(self,"_superSends",[]),"_keys",[])]);
+smalltalk.send(self,"_popScope",[]);
+return self}
 }),
 smalltalk.SemanticAnalyzer);
 
@@ -1125,29 +1148,34 @@ smalltalk.addMethod(
 "_visitSendNode_",
 smalltalk.method({
 selector: "visitSendNode:",
-fn: function (aNode) {
-    var self = this;
-    var $1, $2, $3;
-    $1 = smalltalk.send(smalltalk.send(smalltalk.send(aNode, "_receiver", []), "_value", []), "__eq", ["super"]);
-    if (smalltalk.assert($1)) {
-        smalltalk.send(aNode, "_superSend_", [true]);
-        smalltalk.send(smalltalk.send(aNode, "_receiver", []), "_value_", ["self"]);
-    } else {
-        $2 = smalltalk.send(smalltalk.send(smalltalk.IRSendInliner || IRSendInliner, "_inlinedSelectors", []), "_includes_", [smalltalk.send(aNode, "_selector", [])]);
-        if (smalltalk.assert($2)) {
-            smalltalk.send(aNode, "_shouldBeInlined_", [true]);
-            $3 = smalltalk.send(smalltalk.send(aNode, "_receiver", []), "_isValueNode", []);
-            if (!smalltalk.assert($3)) {
-                smalltalk.send(smalltalk.send(aNode, "_receiver", []), "_shouldBeAliased_", [true]);
-            }
-        }
-    }
-    smalltalk.send(smalltalk.send(self, "_messageSends", []), "_at_ifAbsentPut_", [smalltalk.send(aNode, "_selector", []), function () {return smalltalk.send(smalltalk.Set || Set, "_new", []);}]);
-    smalltalk.send(smalltalk.send(smalltalk.send(self, "_messageSends", []), "_at_", [smalltalk.send(aNode, "_selector", [])]), "_add_", [aNode]);
-    smalltalk.send(aNode, "_index_", [smalltalk.send(smalltalk.send(smalltalk.send(self, "_messageSends", []), "_at_", [smalltalk.send(aNode, "_selector", [])]), "_size", [])]);
-    smalltalk.send(self, "_visitSendNode_", [aNode], smalltalk.NodeVisitor);
-    return self;
-}
+fn: function (aNode){
+var self=this;
+var $1,$2,$3;
+$1=smalltalk.send(smalltalk.send(smalltalk.send(aNode,"_receiver",[]),"_value",[]),"__eq",["super"]);
+if(smalltalk.assert($1)){
+smalltalk.send(aNode,"_superSend_",[true]);
+smalltalk.send(smalltalk.send(aNode,"_receiver",[]),"_value_",["self"]);
+smalltalk.send(smalltalk.send(self,"_superSends",[]),"_at_ifAbsentPut_",[smalltalk.send(aNode,"_selector",[]),(function(){
+return smalltalk.send((smalltalk.Set || Set),"_new",[]);
+})]);
+smalltalk.send(smalltalk.send(smalltalk.send(self,"_superSends",[]),"_at_",[smalltalk.send(aNode,"_selector",[])]),"_add_",[aNode]);
+} else {
+$2=smalltalk.send(smalltalk.send((smalltalk.IRSendInliner || IRSendInliner),"_inlinedSelectors",[]),"_includes_",[smalltalk.send(aNode,"_selector",[])]);
+if(smalltalk.assert($2)){
+smalltalk.send(aNode,"_shouldBeInlined_",[true]);
+$3=smalltalk.send(smalltalk.send(aNode,"_receiver",[]),"_isValueNode",[]);
+if(! smalltalk.assert($3)){
+smalltalk.send(smalltalk.send(aNode,"_receiver",[]),"_shouldBeAliased_",[true]);
+};
+};
+};
+smalltalk.send(smalltalk.send(self,"_messageSends",[]),"_at_ifAbsentPut_",[smalltalk.send(aNode,"_selector",[]),(function(){
+return smalltalk.send((smalltalk.Set || Set),"_new",[]);
+})]);
+smalltalk.send(smalltalk.send(smalltalk.send(self,"_messageSends",[]),"_at_",[smalltalk.send(aNode,"_selector",[])]),"_add_",[aNode]);
+smalltalk.send(aNode,"_index_",[smalltalk.send(smalltalk.send(smalltalk.send(self,"_messageSends",[]),"_at_",[smalltalk.send(aNode,"_selector",[])]),"_size",[])]);
+smalltalk.send(self,"_visitSendNode_",[aNode],smalltalk.NodeVisitor);
+return self}
 }),
 smalltalk.SemanticAnalyzer);
 

+ 76 - 43
js/Compiler-Semantic.js

@@ -1137,7 +1137,7 @@ smalltalk.UnknownVar);
 
 
 
-smalltalk.addClass('SemanticAnalyzer', smalltalk.NodeVisitor, ['currentScope', 'theClass', 'classReferences', 'messageSends'], 'Compiler-Semantic');
+smalltalk.addClass('SemanticAnalyzer', smalltalk.NodeVisitor, ['currentScope', 'theClass', 'classReferences', 'messageSends', 'superSends'], 'Compiler-Semantic');
 smalltalk.SemanticAnalyzer.comment="I semantically analyze the abstract syntax tree and annotate it with informations such as non local returns and variable scopes."
 smalltalk.addMethod(
 "_classReferences",
@@ -1331,6 +1331,29 @@ referencedClasses: []
 }),
 smalltalk.SemanticAnalyzer);
 
+smalltalk.addMethod(
+"_superSends",
+smalltalk.method({
+selector: "superSends",
+category: 'accessing',
+fn: function (){
+var self=this;
+var $1;
+if(($receiver = self["@superSends"]) == nil || $receiver == undefined){
+self["@superSends"]=smalltalk.send((smalltalk.Dictionary || Dictionary),"_new",[]);
+$1=self["@superSends"];
+} else {
+$1=self["@superSends"];
+};
+return $1;
+},
+args: [],
+source: "superSends\x0a\x09^ superSends ifNil: [ superSends := Dictionary new ]",
+messageSends: ["ifNil:", "new"],
+referencedClasses: ["Dictionary"]
+}),
+smalltalk.SemanticAnalyzer);
+
 smalltalk.addMethod(
 "_theClass",
 smalltalk.method({
@@ -1476,23 +1499,28 @@ smalltalk.addMethod(
 smalltalk.method({
 selector: "visitMethodNode:",
 category: 'visiting',
-fn: function (aNode) {
-    var self = this;
-    var $1;
-    smalltalk.send(self, "_pushScope_", [smalltalk.send(self, "_newMethodScope", [])]);
-    smalltalk.send(aNode, "_scope_", [self['@currentScope']]);
-    smalltalk.send(self['@currentScope'], "_node_", [aNode]);
-    smalltalk.send(smalltalk.send(smalltalk.send(self, "_theClass", []), "_allInstanceVariableNames", []), "_do_", [function (each) {return smalltalk.send(self['@currentScope'], "_addIVar_", [each]);}]);
-    smalltalk.send(smalltalk.send(aNode, "_arguments", []), "_do_", [function (each) {smalltalk.send(self, "_validateVariableScope_", [each]);return smalltalk.send(self['@currentScope'], "_addArg_", [each]);}]);
-    smalltalk.send(self, "_visitMethodNode_", [aNode], smalltalk.NodeVisitor);
-    smalltalk.send(aNode, "_classReferences_", [smalltalk.send(self, "_classReferences", [])]);
-    $1 = smalltalk.send(aNode, "_messageSends_", [smalltalk.send(smalltalk.send(self, "_messageSends", []), "_keys", [])]);
-    smalltalk.send(self, "_popScope", []);
-    return self;
-},
+fn: function (aNode){
+var self=this;
+var $1;
+smalltalk.send(self,"_pushScope_",[smalltalk.send(self,"_newMethodScope",[])]);
+smalltalk.send(aNode,"_scope_",[self["@currentScope"]]);
+smalltalk.send(self["@currentScope"],"_node_",[aNode]);
+smalltalk.send(smalltalk.send(smalltalk.send(self,"_theClass",[]),"_allInstanceVariableNames",[]),"_do_",[(function(each){
+return smalltalk.send(self["@currentScope"],"_addIVar_",[each]);
+})]);
+smalltalk.send(smalltalk.send(aNode,"_arguments",[]),"_do_",[(function(each){
+smalltalk.send(self,"_validateVariableScope_",[each]);
+return smalltalk.send(self["@currentScope"],"_addArg_",[each]);
+})]);
+smalltalk.send(self,"_visitMethodNode_",[aNode],smalltalk.NodeVisitor);
+smalltalk.send(aNode,"_classReferences_",[smalltalk.send(self,"_classReferences",[])]);
+smalltalk.send(aNode,"_messageSends_",[smalltalk.send(smalltalk.send(self,"_messageSends",[]),"_keys",[])]);
+$1=smalltalk.send(aNode,"_superSends_",[smalltalk.send(smalltalk.send(self,"_superSends",[]),"_keys",[])]);
+smalltalk.send(self,"_popScope",[]);
+return self},
 args: ["aNode"],
-source: "visitMethodNode: aNode\x0a\x09self pushScope: self newMethodScope.\x0a\x09aNode scope: currentScope.\x0a\x09currentScope node: aNode.\x0a\x0a\x09self theClass allInstanceVariableNames do: [:each | \x0a\x09\x09currentScope addIVar: each ].\x0a\x09aNode arguments do: [ :each | \x0a\x09\x09self validateVariableScope: each.\x0a\x09\x09currentScope addArg: each ].\x0a\x0a\x09super visitMethodNode: aNode.\x0a\x0a\x09aNode \x0a\x09\x09classReferences: self classReferences;\x0a\x09\x09messageSends: self messageSends keys.\x0a\x09self popScope",
-messageSends: ["pushScope:", "newMethodScope", "scope:", "node:", "do:", "addIVar:", "allInstanceVariableNames", "theClass", "validateVariableScope:", "addArg:", "arguments", "visitMethodNode:", "classReferences:", "classReferences", "messageSends:", "keys", "messageSends", "popScope"],
+source: "visitMethodNode: aNode\x0a\x09self pushScope: self newMethodScope.\x0a\x09aNode scope: currentScope.\x0a\x09currentScope node: aNode.\x0a\x0a\x09self theClass allInstanceVariableNames do: [:each | \x0a\x09\x09currentScope addIVar: each ].\x0a\x09aNode arguments do: [ :each | \x0a\x09\x09self validateVariableScope: each.\x0a\x09\x09currentScope addArg: each ].\x0a\x0a\x09super visitMethodNode: aNode.\x0a\x0a\x09aNode \x0a\x09\x09classReferences: self classReferences;\x0a\x09\x09messageSends: self messageSends keys;\x0a        superSends: self superSends keys.\x0a\x09self popScope",
+messageSends: ["pushScope:", "newMethodScope", "scope:", "node:", "do:", "addIVar:", "allInstanceVariableNames", "theClass", "validateVariableScope:", "addArg:", "arguments", "visitMethodNode:", "classReferences:", "classReferences", "messageSends:", "keys", "messageSends", "superSends:", "superSends", "popScope"],
 referencedClasses: []
 }),
 smalltalk.SemanticAnalyzer);
@@ -1527,33 +1555,38 @@ smalltalk.addMethod(
 smalltalk.method({
 selector: "visitSendNode:",
 category: 'visiting',
-fn: function (aNode) {
-    var self = this;
-    var $1, $2, $3;
-    $1 = smalltalk.send(smalltalk.send(smalltalk.send(aNode, "_receiver", []), "_value", []), "__eq", ["super"]);
-    if (smalltalk.assert($1)) {
-        smalltalk.send(aNode, "_superSend_", [true]);
-        smalltalk.send(smalltalk.send(aNode, "_receiver", []), "_value_", ["self"]);
-    } else {
-        $2 = smalltalk.send(smalltalk.send(smalltalk.IRSendInliner || IRSendInliner, "_inlinedSelectors", []), "_includes_", [smalltalk.send(aNode, "_selector", [])]);
-        if (smalltalk.assert($2)) {
-            smalltalk.send(aNode, "_shouldBeInlined_", [true]);
-            $3 = smalltalk.send(smalltalk.send(aNode, "_receiver", []), "_isValueNode", []);
-            if (!smalltalk.assert($3)) {
-                smalltalk.send(smalltalk.send(aNode, "_receiver", []), "_shouldBeAliased_", [true]);
-            }
-        }
-    }
-    smalltalk.send(smalltalk.send(self, "_messageSends", []), "_at_ifAbsentPut_", [smalltalk.send(aNode, "_selector", []), function () {return smalltalk.send(smalltalk.Set || Set, "_new", []);}]);
-    smalltalk.send(smalltalk.send(smalltalk.send(self, "_messageSends", []), "_at_", [smalltalk.send(aNode, "_selector", [])]), "_add_", [aNode]);
-    smalltalk.send(aNode, "_index_", [smalltalk.send(smalltalk.send(smalltalk.send(self, "_messageSends", []), "_at_", [smalltalk.send(aNode, "_selector", [])]), "_size", [])]);
-    smalltalk.send(self, "_visitSendNode_", [aNode], smalltalk.NodeVisitor);
-    return self;
-},
+fn: function (aNode){
+var self=this;
+var $1,$2,$3;
+$1=smalltalk.send(smalltalk.send(smalltalk.send(aNode,"_receiver",[]),"_value",[]),"__eq",["super"]);
+if(smalltalk.assert($1)){
+smalltalk.send(aNode,"_superSend_",[true]);
+smalltalk.send(smalltalk.send(aNode,"_receiver",[]),"_value_",["self"]);
+smalltalk.send(smalltalk.send(self,"_superSends",[]),"_at_ifAbsentPut_",[smalltalk.send(aNode,"_selector",[]),(function(){
+return smalltalk.send((smalltalk.Set || Set),"_new",[]);
+})]);
+smalltalk.send(smalltalk.send(smalltalk.send(self,"_superSends",[]),"_at_",[smalltalk.send(aNode,"_selector",[])]),"_add_",[aNode]);
+} else {
+$2=smalltalk.send(smalltalk.send((smalltalk.IRSendInliner || IRSendInliner),"_inlinedSelectors",[]),"_includes_",[smalltalk.send(aNode,"_selector",[])]);
+if(smalltalk.assert($2)){
+smalltalk.send(aNode,"_shouldBeInlined_",[true]);
+$3=smalltalk.send(smalltalk.send(aNode,"_receiver",[]),"_isValueNode",[]);
+if(! smalltalk.assert($3)){
+smalltalk.send(smalltalk.send(aNode,"_receiver",[]),"_shouldBeAliased_",[true]);
+};
+};
+};
+smalltalk.send(smalltalk.send(self,"_messageSends",[]),"_at_ifAbsentPut_",[smalltalk.send(aNode,"_selector",[]),(function(){
+return smalltalk.send((smalltalk.Set || Set),"_new",[]);
+})]);
+smalltalk.send(smalltalk.send(smalltalk.send(self,"_messageSends",[]),"_at_",[smalltalk.send(aNode,"_selector",[])]),"_add_",[aNode]);
+smalltalk.send(aNode,"_index_",[smalltalk.send(smalltalk.send(smalltalk.send(self,"_messageSends",[]),"_at_",[smalltalk.send(aNode,"_selector",[])]),"_size",[])]);
+smalltalk.send(self,"_visitSendNode_",[aNode],smalltalk.NodeVisitor);
+return self},
 args: ["aNode"],
-source: "visitSendNode: aNode\x0a\x0a\x09aNode receiver value = 'super' \x0a\x09\x09ifTrue: [\x0a\x09\x09\x09aNode superSend: true.\x0a\x09\x09\x09aNode receiver value: 'self' ]\x0a\x09\x09ifFalse: [ (IRSendInliner inlinedSelectors includes: aNode selector) ifTrue: [\x0a\x09\x09\x09aNode shouldBeInlined: true.\x0a\x09\x09\x09aNode receiver isValueNode ifFalse: [ aNode receiver shouldBeAliased: true ] ] ].\x0a\x0a\x09self messageSends at: aNode selector ifAbsentPut: [ Set new ].\x0a\x09(self messageSends at: aNode selector) add: aNode.\x0a\x0a\x09aNode index: (self messageSends at: aNode selector) size.\x0a\x0a\x09super visitSendNode: aNode",
-messageSends: ["ifTrue:ifFalse:", "superSend:", "value:", "receiver", "ifTrue:", "shouldBeInlined:", "ifFalse:", "shouldBeAliased:", "isValueNode", "includes:", "selector", "inlinedSelectors", "=", "value", "at:ifAbsentPut:", "new", "messageSends", "add:", "at:", "index:", "size", "visitSendNode:"],
-referencedClasses: ["IRSendInliner", "Set"]
+source: "visitSendNode: aNode\x0a\x0a\x09aNode receiver value = 'super' \x0a\x09\x09ifTrue: [\x0a\x09\x09\x09aNode superSend: true.\x0a\x09\x09\x09aNode receiver value: 'self'.\x0a\x09\x09\x09self superSends at: aNode selector ifAbsentPut: [ Set new ].\x0a\x09\x09\x09(self superSends at: aNode selector) add: aNode ]\x0a          \x0a\x09\x09ifFalse: [ (IRSendInliner inlinedSelectors includes: aNode selector) ifTrue: [\x0a\x09\x09\x09aNode shouldBeInlined: true.\x0a\x09\x09\x09aNode receiver isValueNode ifFalse: [ aNode receiver shouldBeAliased: true ] ] ].\x0a\x0a\x09self messageSends at: aNode selector ifAbsentPut: [ Set new ].\x0a\x09(self messageSends at: aNode selector) add: aNode.\x0a\x0a\x09aNode index: (self messageSends at: aNode selector) size.\x0a\x0a\x09super visitSendNode: aNode",
+messageSends: ["ifTrue:ifFalse:", "superSend:", "value:", "receiver", "at:ifAbsentPut:", "selector", "new", "superSends", "add:", "at:", "ifTrue:", "shouldBeInlined:", "ifFalse:", "shouldBeAliased:", "isValueNode", "includes:", "inlinedSelectors", "=", "value", "messageSends", "index:", "size", "visitSendNode:"],
+referencedClasses: ["Set", "IRSendInliner"]
 }),
 smalltalk.SemanticAnalyzer);
 

+ 28 - 14
js/Kernel-Collections.deploy.js

@@ -2312,20 +2312,9 @@ smalltalk.method({
 selector: "asSelector",
 fn: function (){
 var self=this;
-var selector;
-selector=smalltalk.send("_","__comma",[self]);
-selector=smalltalk.send(selector,"_replace_with_",[":","_"]);
-selector=smalltalk.send(selector,"_replace_with_",["[+]","_plus"]);
-selector=smalltalk.send(selector,"_replace_with_",["-","_minus"]);
-selector=smalltalk.send(selector,"_replace_with_",["[*]","_star"]);
-selector=smalltalk.send(selector,"_replace_with_",["[/]","_slash"]);
-selector=smalltalk.send(selector,"_replace_with_",[">","_gt"]);
-selector=smalltalk.send(selector,"_replace_with_",["<","_lt"]);
-selector=smalltalk.send(selector,"_replace_with_",["=","_eq"]);
-selector=smalltalk.send(selector,"_replace_with_",[",","_comma"]);
-selector=smalltalk.send(selector,"_replace_with_",["[@]","_at"]);
-return selector;
-}
+return smalltalk.selector(this);
+;
+return self}
 }),
 smalltalk.String);
 
@@ -2340,6 +2329,18 @@ return self;
 }),
 smalltalk.String);
 
+smalltalk.addMethod(
+"_asSuperSelector",
+smalltalk.method({
+selector: "asSuperSelector",
+fn: function (){
+var self=this;
+return smalltalk.superSelector(self);
+;
+return self}
+}),
+smalltalk.String);
+
 smalltalk.addMethod(
 "_asSymbol",
 smalltalk.method({
@@ -3073,6 +3074,19 @@ return self}
 }),
 smalltalk.Symbol);
 
+smalltalk.addMethod(
+"_asSuperSelector",
+smalltalk.method({
+selector: "asSuperSelector",
+fn: function (){
+var self=this;
+var $1;
+$1=smalltalk.send(smalltalk.send(self,"_asString",[]),"_asSuperSelector",[]);
+return $1;
+}
+}),
+smalltalk.Symbol);
+
 smalltalk.addMethod(
 "_asSymbol",
 smalltalk.method({

+ 40 - 16
js/Kernel-Collections.js

@@ -3104,23 +3104,12 @@ selector: "asSelector",
 category: 'converting',
 fn: function (){
 var self=this;
-var selector;
-selector=smalltalk.send("_","__comma",[self]);
-selector=smalltalk.send(selector,"_replace_with_",[":","_"]);
-selector=smalltalk.send(selector,"_replace_with_",["[+]","_plus"]);
-selector=smalltalk.send(selector,"_replace_with_",["-","_minus"]);
-selector=smalltalk.send(selector,"_replace_with_",["[*]","_star"]);
-selector=smalltalk.send(selector,"_replace_with_",["[/]","_slash"]);
-selector=smalltalk.send(selector,"_replace_with_",[">","_gt"]);
-selector=smalltalk.send(selector,"_replace_with_",["<","_lt"]);
-selector=smalltalk.send(selector,"_replace_with_",["=","_eq"]);
-selector=smalltalk.send(selector,"_replace_with_",[",","_comma"]);
-selector=smalltalk.send(selector,"_replace_with_",["[@]","_at"]);
-return selector;
-},
+return smalltalk.selector(this);
+;
+return self},
 args: [],
-source: "asSelector\x0a\x09\x22If you change this method, change smalltalk.convertSelector too (see js/boot.js file)\x22\x0a\x0a\x09| selector |\x0a\x09selector := '_', self.\x0a\x09selector := selector replace: ':' with: '_'.\x0a\x09selector := selector replace: '[+]' with: '_plus'.\x0a\x09selector := selector replace: '-' with: '_minus'.\x0a\x09selector := selector replace: '[*]' with: '_star'.\x0a\x09selector := selector replace: '[/]' with: '_slash'.\x0a\x09selector := selector replace: '>' with: '_gt'.\x0a\x09selector := selector replace: '<' with: '_lt'.\x0a\x09selector := selector replace: '=' with: '_eq'.\x0a\x09selector := selector replace: ',' with: '_comma'.\x0a\x09selector := selector replace: '[@]' with: '_at'.\x0a\x09^selector",
-messageSends: [",", "replace:with:"],
+source: "asSelector\x0a\x09<return smalltalk.selector(this)>",
+messageSends: [],
 referencedClasses: []
 }),
 smalltalk.String);
@@ -3141,6 +3130,23 @@ referencedClasses: []
 }),
 smalltalk.String);
 
+smalltalk.addMethod(
+"_asSuperSelector",
+smalltalk.method({
+selector: "asSuperSelector",
+category: 'converting',
+fn: function (){
+var self=this;
+return smalltalk.superSelector(self);
+;
+return self},
+args: [],
+source: "asSuperSelector\x0a\x09<return smalltalk.superSelector(self)>",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.String);
+
 smalltalk.addMethod(
 "_asSymbol",
 smalltalk.method({
@@ -4134,6 +4140,24 @@ referencedClasses: []
 }),
 smalltalk.Symbol);
 
+smalltalk.addMethod(
+"_asSuperSelector",
+smalltalk.method({
+selector: "asSuperSelector",
+category: 'converting',
+fn: function (){
+var self=this;
+var $1;
+$1=smalltalk.send(smalltalk.send(self,"_asString",[]),"_asSuperSelector",[]);
+return $1;
+},
+args: [],
+source: "asSuperSelector\x0a\x09^self asString asSuperSelector",
+messageSends: ["asSuperSelector", "asString"],
+referencedClasses: []
+}),
+smalltalk.Symbol);
+
 smalltalk.addMethod(
 "_asSymbol",
 smalltalk.method({

+ 72 - 13
js/boot.js

@@ -48,6 +48,7 @@ if (typeof console === "undefined") {
 /* Array extensions */
 
 Array.prototype.addElement = function(el) {
+    if(typeof el === 'undefined') { return false; };
     if(this.indexOf(el) == -1) {
         this.push(el);
     }
@@ -122,6 +123,8 @@ function Smalltalk(){
 		'public', 'return', 'static', 'switch', 'this', 'throw',
 		'try', 'typeof', 'var', 'void', 'while', 'with', 'yield'];
 
+    var initialized = false;
+
     /* Smalltalk classes */
 
     var classes = [];
@@ -322,28 +325,48 @@ function Smalltalk(){
 
     var reinstallMethods = function(klass) {
         for(var keys = Object.keys(klass.methods), i=0; i<keys.length; i++) {
-            installMethod(klass.methods[keys[i]], klass)
+            installMethod(klass.methods[keys[i]], klass);
 		}
     };
 
     var installDnuHandlers = function(klass) {
         for(var i=0; i<dnuHandlers.length; i++) {
-            var selector = dnuHandlers[i]._asSelector();
-            installDnuHandler(selector, klass);
+            installDnuHandler(dnuHandlers[i], klass);
         }
     };
 
-    var installDnuHandler = function(selector, klass) {
+    var installDnuHandler = function(string, klass) {
+        var selector = st.selector(string);
         if(!klass.fn.prototype[selector]) {
             Object.defineProperty(klass.fn.prototype, selector, {
                 value: dnu(selector), configurable: true, writable: true
-            })
+            });
+        }
+    };
+
+    var installNewDnuHandler = function(string) {
+        if(dnuHandlers.indexOf(string) === -1) {
+            addDnuHandler(string);
+            installDnuHandler(string, smalltalk.Object);
+            for(var i=0; i<wrappedClasses.length; i++) {
+                installDnuHandler(string, wrappedClasses[i]);
+            };
         }
     };
 
     /* Super sends handling */
-    // TODO
-    var installSuperSendHandler = function(selector, klass) {
+
+    var installSuperSendHandler = function(string, klass) {
+        var selector = st.selector(string);
+        var superSelector = st.superSelector(string);
+        var fn = klass.superclass[selector];
+        if(!fn) {
+            fn = dnu(selector);
+        };
+
+        Object.defineProperty(klass.fn.prototype, superSelector, {
+            value: fn, configurable: true, writable: true
+        });
     };
 
 	/* Answer all registered Packages as Array */
@@ -412,6 +435,7 @@ function Smalltalk(){
 	};
 
 	/* Create an alias for an existing class */
+
 	st.alias = function(klass, alias) {
 		st[alias] = klass;
 	}
@@ -478,12 +502,14 @@ function Smalltalk(){
 
         klass.organization.elements.addElement(method.category);
 
-        for(var i=0; i<method.messageSends.length; i++) {
-            addDnuHandler(method.messageSends[i]);
+        for(var i=0; i<method.superSends.length; i++) {
+            installSuperSendHandler(method.superSends[i], klass);
         };
 
-        for(var i=0; i<method.superSends.length; i++) {
-            addSuperSendHandler(method.superSends[i], klass);
+        if(initialized) {
+            for(var i=0; i<method.messageSends.length; i++) {
+                installNewDnuHandler(method.messageSends[i]);
+            };
         };
 	};
 
@@ -492,7 +518,7 @@ function Smalltalk(){
         var shouldDeleteProtocol;
         var klass = method.methodClass;
 
-        delete klass.fn.prototype[method.selector._asSelector()];
+        delete klass.fn.prototype[st.selector(method.selector)];
 	    delete klass.methods[method.selector];
 
         for(var i=0; i<klass.methods; i++) {
@@ -501,7 +527,7 @@ function Smalltalk(){
             };
         };
         if(shouldDeleteProtocol) {
-            klass.organization.elements.removeElement(protocol)
+            klass.organization.elements.removeElement(protocol);
         };
     };
 
@@ -657,6 +683,26 @@ function Smalltalk(){
 		st.oldContext = context;
 	};
 
+    /* Convert a Smalltalk selector into a JS selector */
+    st.selector = function(string) {
+        var selector = '_' + string;
+	    selector = selector.replace(/:/g, '_');
+	    selector = selector.replace(/[+]/g, '_plus');
+	    selector = selector.replace(/-/g, '_minus');
+	    selector = selector.replace(/[*]/g ,'_star');
+	    selector = selector.replace(/[\/]/g ,'_slash');
+	    selector = selector.replace(/>/g ,'_gt');
+	    selector = selector.replace(/</g ,'_lt');
+	    selector = selector.replace(/=/g ,'_eq');
+	    selector = selector.replace(/,/g ,'_comma');
+	    selector = selector.replace(/[@]/g ,'_at');
+        return selector
+    };
+
+    st.superSelector = function(string) {
+        return '$super' + st.selector(string);
+    };
+    
 	/* Convert a string to a valid smalltalk selector.
 	   if you modify the following functions, also change String>>asSelector
 	   accordingly */
@@ -715,6 +761,19 @@ function Smalltalk(){
             smalltalk.NonBooleanReceiver._new()._object_(boolean)._signal();
         }
     }
+
+    st.initialize = function() {
+        if(initialized) {return false};
+
+        classes.forEach(function(klass) {
+            st.init(klass);
+        });
+        classes.forEach(function(klass) {
+            klass._initialize();
+        });
+
+        initialized = true;
+    };
 };
 
 Smalltalk.prototype = new SmalltalkObject();

+ 1 - 6
js/init.js

@@ -1,9 +1,4 @@
-smalltalk.classes().forEach(function(each) {
-    smalltalk.init(each);
-});
-smalltalk.classes().forEach(function(each) {
-	each._initialize()
-});
+smalltalk.initialize();
 
 /* Similar to jQuery(document).ready() */
 

+ 9 - 1
st/Compiler-AST.st

@@ -202,7 +202,7 @@ accept: aVisitor
 ! !
 
 Node subclass: #MethodNode
-	instanceVariableNames: 'selector arguments source scope classReferences messageSends'
+	instanceVariableNames: 'selector arguments source scope classReferences messageSends superSends'
 	package: 'Compiler-AST'!
 
 !MethodNode methodsFor: 'accessing'!
@@ -253,6 +253,14 @@ source
 
 source: aString
 	source := aString
+!
+
+superSends
+	^ superSends
+!
+
+superSends: aCollection
+	superSends := aCollection
 ! !
 
 !MethodNode methodsFor: 'visiting'!

+ 13 - 12
st/Compiler-IR.st

@@ -154,6 +154,7 @@ visitMethodNode: aNode
 		arguments: aNode arguments;
 		selector: aNode selector;
 		messageSends: aNode messageSends;
+        superSends: aNode superSends;
 		classReferences: aNode classReferences;
 		scope: aNode scope;
 		yourself).
@@ -408,7 +409,7 @@ accept: aVisitor
 ! !
 
 IRScopedInstruction subclass: #IRMethod
-	instanceVariableNames: 'source selector classReferences messageSends arguments internalVariables'
+	instanceVariableNames: 'source selector classReferences messageSends superSends arguments internalVariables'
 	package: 'Compiler-IR'!
 !IRMethod commentStamp!
 I am a method instruction!
@@ -462,6 +463,14 @@ source
 
 source: aString
 	source := aString
+!
+
+superSends
+	^ superSends
+!
+
+superSends: aCollection
+	superSends := aCollection
 ! !
 
 !IRMethod methodsFor: 'visiting'!
@@ -1005,7 +1014,9 @@ nextPutMethodDeclaration: aMethod with: aBlock
 	stream 
 		nextPutAll: ',', String lf, 'messageSends: ';
 		nextPutAll: aMethod messageSends asArray asJavascript, ','; lf;
-          	nextPutAll: 'args: ', (aMethod arguments collect: [ :each | each value ]) asArray asJavascript, ','; lf;
+		nextPutAll: 'superSends: ';
+		nextPutAll: aMethod superSends asArray asJavascript, ','; lf;
+        nextPutAll: 'args: ', (aMethod arguments collect: [ :each | each value ]) asArray asJavascript, ','; lf;
 		nextPutAll: 'referencedClasses: ['.
 	aMethod classReferences 
 		do: [:each | stream nextPutAll: each asJavascript]
@@ -1040,16 +1051,6 @@ nextPutReturnWith: aBlock
 	aBlock value
 !
 
-nextPutSendTo: receiver selector: selector arguments: arguments
-	stream nextPutAll: 'smalltalk.send('.
-	receiver emitOn: self. 
-	stream nextPutAll: ',"', selector asSelector, '",['.
-	arguments 
-		do: [ :each | each emitOn: self ]
-		separatedBy: [ stream nextPutAll: ',' ].
-	stream nextPutAll: '])'
-!
-
 nextPutSequenceWith: aBlock
 	"stream 
 		nextPutAll: 'switch(smalltalk.thisContext.pc){'; lf."

+ 11 - 3
st/Compiler-Semantic.st

@@ -370,7 +370,7 @@ isUnknownVar
 ! !
 
 NodeVisitor subclass: #SemanticAnalyzer
-	instanceVariableNames: 'currentScope theClass classReferences messageSends'
+	instanceVariableNames: 'currentScope theClass classReferences messageSends superSends'
 	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.!
@@ -385,6 +385,10 @@ messageSends
 	^ messageSends ifNil: [ messageSends := Dictionary new ]
 !
 
+superSends
+	^ superSends ifNil: [ superSends := Dictionary new ]
+!
+
 theClass
 	^ theClass
 !
@@ -501,7 +505,8 @@ visitMethodNode: aNode
 
 	aNode 
 		classReferences: self classReferences;
-		messageSends: self messageSends keys.
+		messageSends: self messageSends keys;
+        superSends: self superSends keys.
 	self popScope
 !
 
@@ -518,7 +523,10 @@ visitSendNode: aNode
 	aNode receiver value = 'super' 
 		ifTrue: [
 			aNode superSend: true.
-			aNode receiver value: 'self' ]
+			aNode receiver value: 'self'.
+			self superSends at: aNode selector ifAbsentPut: [ Set new ].
+			(self superSends at: aNode selector) add: aNode ]
+          
 		ifFalse: [ (IRSendInliner inlinedSelectors includes: aNode selector) ifTrue: [
 			aNode shouldBeInlined: true.
 			aNode receiver isValueNode ifFalse: [ aNode receiver shouldBeAliased: true ] ] ].

+ 9 - 15
st/Kernel-Collections.st

@@ -1039,27 +1039,17 @@ asNumber
 !
 
 asSelector
-	"If you change this method, change smalltalk.convertSelector too (see js/boot.js file)"
-
-	| selector |
-	selector := '_', self.
-	selector := selector replace: ':' with: '_'.
-	selector := selector replace: '[+]' with: '_plus'.
-	selector := selector replace: '-' with: '_minus'.
-	selector := selector replace: '[*]' with: '_star'.
-	selector := selector replace: '[/]' with: '_slash'.
-	selector := selector replace: '>' with: '_gt'.
-	selector := selector replace: '<' with: '_lt'.
-	selector := selector replace: '=' with: '_eq'.
-	selector := selector replace: ',' with: '_comma'.
-	selector := selector replace: '[@]' with: '_at'.
-	^selector
+	<return smalltalk.selector(this)>
 !
 
 asString
 	^self
 !
 
+asSuperSelector
+	<return smalltalk.superSelector(self)>
+!
+
 asSymbol
 	^Symbol lookup: self
 !
@@ -1343,6 +1333,10 @@ asString
 	<return self.value>
 !
 
+asSuperSelector
+	^self asString asSuperSelector
+!
+
 asSymbol
 	^self
 ! !