Bladeren bron

Merge branch 'message_send' into ast-interpreter

Nicolas Petton 12 jaren geleden
bovenliggende
commit
51b72bebd8

+ 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(
 smalltalk.addMethod(
 "_accept_",
 "_accept_",
 smalltalk.method({
 smalltalk.method({
@@ -605,6 +605,28 @@ return self}
 }),
 }),
 smalltalk.MethodNode);
 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');
 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(
 smalltalk.addMethod(
 "_accept_",
 "_accept_",
 smalltalk.method({
 smalltalk.method({
@@ -846,6 +846,38 @@ referencedClasses: []
 }),
 }),
 smalltalk.MethodNode);
 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');
 smalltalk.addClass('ReturnNode', smalltalk.Node, ['scope'], 'Compiler-AST');

+ 117 - 41
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,"_arguments_",[smalltalk.send(aNode,"_arguments",[])]);
 smalltalk.send($1,"_selector_",[smalltalk.send(aNode,"_selector",[])]);
 smalltalk.send($1,"_selector_",[smalltalk.send(aNode,"_selector",[])]);
 smalltalk.send($1,"_messageSends_",[smalltalk.send(aNode,"_messageSends",[])]);
 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,"_classReferences_",[smalltalk.send(aNode,"_classReferences",[])]);
 smalltalk.send($1,"_scope_",[smalltalk.send(aNode,"_scope",[])]);
 smalltalk.send($1,"_scope_",[smalltalk.send(aNode,"_scope",[])]);
 $2=smalltalk.send($1,"_yourself",[]);
 $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(
 smalltalk.addMethod(
 "_accept_",
 "_accept_",
 smalltalk.method({
 smalltalk.method({
@@ -999,6 +1000,28 @@ return self}
 }),
 }),
 smalltalk.IRMethod);
 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');
 smalltalk.addClass('IRReturn', smalltalk.IRScopedInstruction, [], 'Compiler-IR');
@@ -1197,6 +1220,24 @@ return true;
 }),
 }),
 smalltalk.IRSend);
 smalltalk.IRSend);
 
 
+smalltalk.addMethod(
+"_javascriptSelector",
+smalltalk.method({
+selector: "javascriptSelector",
+fn: function (){
+var self=this;
+var $2,$1;
+$2=smalltalk.send(self,"_classSend",[]);
+if(($receiver = $2) == nil || $receiver == undefined){
+$1=smalltalk.send(smalltalk.send(self,"_selector",[]),"_asSelector",[]);
+} else {
+$1=smalltalk.send(smalltalk.send(self,"_selector",[]),"_asSuperSelector",[]);
+};
+return $1;
+}
+}),
+smalltalk.IRSend);
+
 smalltalk.addMethod(
 smalltalk.addMethod(
 "_selector",
 "_selector",
 smalltalk.method({
 smalltalk.method({
@@ -1871,6 +1912,43 @@ smalltalk.method({
 selector: "visitIRSend:",
 selector: "visitIRSend:",
 fn: function (anIRSend){
 fn: function (anIRSend){
 var self=this;
 var self=this;
+var $1,$2,$3;
+$1=_st(anIRSend)._classSend();
+if(($receiver = $1) == nil || $receiver == undefined){
+_st(_st(self)._stream())._nextPutAll_("_st(");
+_st(self)._visit_(_st(_st(anIRSend)._instructions())._first());
+_st(_st(self)._stream())._nextPutAll_(_st(_st(").").__comma(_st(_st(anIRSend)._selector())._asSelector())).__comma("("));
+_st(_st(_st(anIRSend)._instructions())._allButFirst())._do_separatedBy_((function(each){
+return _st(self)._visit_(each);
+}),(function(){
+return _st(_st(self)._stream())._nextPutAll_(",");
+}));
+_st(_st(self)._stream())._nextPutAll_(")");
+} else {
+$2=_st(self)._stream();
+_st($2)._nextPutAll_(_st(_st(_st(anIRSend)._classSend())._asJavascript()).__comma(".fn.prototype."));
+_st($2)._nextPutAll_(_st(_st(_st(anIRSend)._selector())._asSelector()).__comma(".apply("));
+$3=_st($2)._nextPutAll_("_st(");
+$3;
+_st(self)._visit_(_st(_st(anIRSend)._instructions())._first());
+_st(_st(self)._stream())._nextPutAll_("), [");
+_st(_st(_st(anIRSend)._instructions())._allButFirst())._do_separatedBy_((function(each){
+return _st(self)._visit_(each);
+}),(function(){
+return _st(_st(self)._stream())._nextPutAll_(",");
+}));
+_st(_st(self)._stream())._nextPutAll_("])");
+};
+return self}
+}),
+smalltalk.IRJSTranslator);
+
+smalltalk.addMethod(
+"_visitIRSendOld_",
+smalltalk.method({
+selector: "visitIRSendOld:",
+fn: function (anIRSend){
+var self=this;
 var $1;
 var $1;
 smalltalk.send(smalltalk.send(self,"_stream",[]),"_nextPutAll_",["smalltalk.send("]);
 smalltalk.send(smalltalk.send(self,"_stream",[]),"_nextPutAll_",["smalltalk.send("]);
 smalltalk.send(self,"_visit_",[smalltalk.send(smalltalk.send(anIRSend,"_instructions",[]),"_first",[])]);
 smalltalk.send(self,"_visit_",[smalltalk.send(smalltalk.send(anIRSend,"_instructions",[]),"_first",[])]);
@@ -2052,6 +2130,23 @@ return self}
 }),
 }),
 smalltalk.JSStream);
 smalltalk.JSStream);
 
 
+smalltalk.addMethod(
+"_nextPutContextFor_during_",
+smalltalk.method({
+selector: "nextPutContextFor:during:",
+fn: function (aMethod,aBlock){
+var self=this;
+var $1;
+_st(self)._nextPutAll_("return smalltalk.withContext(function() {");
+_st(aBlock)._value();
+_st(self)._nextPutAll_("}, self, ");
+_st(self)._nextPutAll_(_st(_st(_st(aMethod)._selector())._asJavascript()).__comma(", "));
+_st(self)._nextPutAll_(_st(_st(aMethod)._arguments())._asJavascript());
+$1=_st(self)._nextPutAll_(")");
+return self}
+}),
+smalltalk.JSStream);
+
 smalltalk.addMethod(
 smalltalk.addMethod(
 "_nextPutFunctionWith_arguments_",
 "_nextPutFunctionWith_arguments_",
 smalltalk.method({
 smalltalk.method({
@@ -2119,28 +2214,28 @@ selector: "nextPutMethodDeclaration:with:",
 fn: function (aMethod,aBlock){
 fn: function (aMethod,aBlock){
 var self=this;
 var self=this;
 var $1,$2,$3;
 var $1,$2,$3;
-smalltalk.send(self["@stream"],"_nextPutAll_",["smalltalk.method({"]);
-smalltalk.send(self["@stream"],"_lf",[]);
-smalltalk.send(self["@stream"],"_nextPutAll_",[smalltalk.send(smalltalk.send("selector: \x22","__comma",[smalltalk.send(aMethod,"_selector",[])]),"__comma",["\x22,"])]);
-smalltalk.send(self["@stream"],"_lf",[]);
-smalltalk.send(self["@stream"],"_nextPutAll_",[smalltalk.send(smalltalk.send("source: ","__comma",[smalltalk.send(smalltalk.send(aMethod,"_source",[]),"_asJavascript",[])]),"__comma",[","])]);
-$1=smalltalk.send(self["@stream"],"_lf",[]);
-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_",[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",[","])]);
-smalltalk.send(self["@stream"],"_lf",[]);
-$2=smalltalk.send(self["@stream"],"_nextPutAll_",["referencedClasses: ["]);
-smalltalk.send(smalltalk.send(aMethod,"_classReferences",[]),"_do_separatedBy_",[(function(each){
-return smalltalk.send(self["@stream"],"_nextPutAll_",[smalltalk.send(each,"_asJavascript",[])]);
+_st(self["@stream"])._nextPutAll_("smalltalk.method({");
+_st(self["@stream"])._lf();
+_st(self["@stream"])._nextPutAll_(_st(_st("selector: \x22").__comma(_st(aMethod)._selector())).__comma("\x22,"));
+_st(self["@stream"])._lf();
+_st(self["@stream"])._nextPutAll_(_st(_st("source: ").__comma(_st(_st(aMethod)._source())._asJavascript())).__comma(","));
+$1=_st(self["@stream"])._lf();
+_st(aBlock)._value();
+_st(self["@stream"])._nextPutAll_(_st(_st(",").__comma(_st((smalltalk.String || String))._lf())).__comma("messageSends: "));
+_st(self["@stream"])._nextPutAll_(_st(_st(_st(_st(aMethod)._messageSends())._asArray())._asJavascript()).__comma(","));
+_st(self["@stream"])._lf();
+_st(self["@stream"])._nextPutAll_(_st(_st("args: ").__comma(_st(_st(_st(_st(aMethod)._arguments())._collect_((function(each){
+return _st(each)._value();
+})))._asArray())._asJavascript())).__comma(","));
+_st(self["@stream"])._lf();
+$2=_st(self["@stream"])._nextPutAll_("referencedClasses: [");
+_st(_st(aMethod)._classReferences())._do_separatedBy_((function(each){
+return _st(self["@stream"])._nextPutAll_(_st(each)._asJavascript());
 }),(function(){
 }),(function(){
-return smalltalk.send(self["@stream"],"_nextPutAll_",[","]);
-})]);
-smalltalk.send(self["@stream"],"_nextPutAll_",["]"]);
-$3=smalltalk.send(self["@stream"],"_nextPutAll_",["})"]);
+return _st(self["@stream"])._nextPutAll_(",");
+}));
+_st(self["@stream"])._nextPutAll_("]");
+$3=_st(self["@stream"])._nextPutAll_("})");
 return self}
 return self}
 }),
 }),
 smalltalk.JSStream);
 smalltalk.JSStream);
@@ -2201,25 +2296,6 @@ return self}
 }),
 }),
 smalltalk.JSStream);
 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(
 smalltalk.addMethod(
 "_nextPutSequenceWith_",
 "_nextPutSequenceWith_",
 smalltalk.method({
 smalltalk.method({

+ 146 - 50
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,"_arguments_",[smalltalk.send(aNode,"_arguments",[])]);
 smalltalk.send($1,"_selector_",[smalltalk.send(aNode,"_selector",[])]);
 smalltalk.send($1,"_selector_",[smalltalk.send(aNode,"_selector",[])]);
 smalltalk.send($1,"_messageSends_",[smalltalk.send(aNode,"_messageSends",[])]);
 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,"_classReferences_",[smalltalk.send(aNode,"_classReferences",[])]);
 smalltalk.send($1,"_scope_",[smalltalk.send(aNode,"_scope",[])]);
 smalltalk.send($1,"_scope_",[smalltalk.send(aNode,"_scope",[])]);
 $2=smalltalk.send($1,"_yourself",[]);
 $2=smalltalk.send($1,"_yourself",[]);
@@ -409,8 +410,8 @@ $8=smalltalk.send(self,"_method",[]);
 return $8;
 return $8;
 },
 },
 args: ["aNode"],
 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"]
 referencedClasses: ["IRMethod", "IRTempDeclaration", "IRVariable", "IRReturn"]
 }),
 }),
 smalltalk.IRASTTranslator);
 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.IRMethod.comment="I am a method instruction"
 smalltalk.addMethod(
 smalltalk.addMethod(
 "_accept_",
 "_accept_",
@@ -1337,6 +1338,38 @@ referencedClasses: []
 }),
 }),
 smalltalk.IRMethod);
 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');
 smalltalk.addClass('IRReturn', smalltalk.IRScopedInstruction, [], 'Compiler-IR');
@@ -1619,6 +1652,29 @@ referencedClasses: []
 }),
 }),
 smalltalk.IRSend);
 smalltalk.IRSend);
 
 
+smalltalk.addMethod(
+"_javascriptSelector",
+smalltalk.method({
+selector: "javascriptSelector",
+category: 'accessing',
+fn: function (){
+var self=this;
+var $2,$1;
+$2=smalltalk.send(self,"_classSend",[]);
+if(($receiver = $2) == nil || $receiver == undefined){
+$1=smalltalk.send(smalltalk.send(self,"_selector",[]),"_asSelector",[]);
+} else {
+$1=smalltalk.send(smalltalk.send(self,"_selector",[]),"_asSuperSelector",[]);
+};
+return $1;
+},
+args: [],
+source: "javascriptSelector\x0a\x09^ self classSend \x0a    \x09ifNil: [ self selector asSelector ]\x0a      \x09ifNotNil: [ self selector asSuperSelector ]",
+messageSends: ["ifNil:ifNotNil:", "asSelector", "selector", "asSuperSelector", "classSend"],
+referencedClasses: []
+}),
+smalltalk.IRSend);
+
 smalltalk.addMethod(
 smalltalk.addMethod(
 "_selector",
 "_selector",
 smalltalk.method({
 smalltalk.method({
@@ -2547,6 +2603,48 @@ selector: "visitIRSend:",
 category: 'visiting',
 category: 'visiting',
 fn: function (anIRSend){
 fn: function (anIRSend){
 var self=this;
 var self=this;
+var $1,$2,$3;
+$1=_st(anIRSend)._classSend();
+if(($receiver = $1) == nil || $receiver == undefined){
+_st(_st(self)._stream())._nextPutAll_("_st(");
+_st(self)._visit_(_st(_st(anIRSend)._instructions())._first());
+_st(_st(self)._stream())._nextPutAll_(_st(_st(").").__comma(_st(_st(anIRSend)._selector())._asSelector())).__comma("("));
+_st(_st(_st(anIRSend)._instructions())._allButFirst())._do_separatedBy_((function(each){
+return _st(self)._visit_(each);
+}),(function(){
+return _st(_st(self)._stream())._nextPutAll_(",");
+}));
+_st(_st(self)._stream())._nextPutAll_(")");
+} else {
+$2=_st(self)._stream();
+_st($2)._nextPutAll_(_st(_st(_st(anIRSend)._classSend())._asJavascript()).__comma(".fn.prototype."));
+_st($2)._nextPutAll_(_st(_st(_st(anIRSend)._selector())._asSelector()).__comma(".apply("));
+$3=_st($2)._nextPutAll_("_st(");
+$3;
+_st(self)._visit_(_st(_st(anIRSend)._instructions())._first());
+_st(_st(self)._stream())._nextPutAll_("), [");
+_st(_st(_st(anIRSend)._instructions())._allButFirst())._do_separatedBy_((function(each){
+return _st(self)._visit_(each);
+}),(function(){
+return _st(_st(self)._stream())._nextPutAll_(",");
+}));
+_st(_st(self)._stream())._nextPutAll_("])");
+};
+return self},
+args: ["anIRSend"],
+source: "visitIRSend: anIRSend\x0a\x09anIRSend classSend \x0a    \x09ifNil: [\x0a\x09\x09\x09self stream nextPutAll: '_st('.\x0a\x09\x09\x09self visit: anIRSend instructions first.\x0a   \x09\x09 \x09self stream nextPutAll: ').', anIRSend selector asSelector, '('.\x0a\x09\x09\x09anIRSend instructions allButFirst\x0a\x09\x09\x09\x09do: [ :each | self visit: each ]\x0a\x09\x09\x09\x09separatedBy: [ self stream nextPutAll: ',' ].\x0a\x09\x09\x09self stream nextPutAll: ')' ]\x0a\x09\x09ifNotNil: [ \x0a\x09\x09\x09self stream \x0a            \x09nextPutAll: anIRSend classSend asJavascript, '.fn.prototype.';\x0a\x09\x09\x09\x09nextPutAll: anIRSend selector asSelector, '.apply(';\x0a\x09\x09\x09\x09nextPutAll: '_st('.\x0a\x09\x09\x09self visit: anIRSend instructions first.\x0a\x09\x09\x09self stream nextPutAll: '), ['.\x0a\x09\x09\x09anIRSend instructions allButFirst\x0a\x09\x09\x09\x09do: [ :each | self visit: each ]\x0a\x09\x09\x09\x09separatedBy: [ self stream nextPutAll: ',' ].\x0a\x09\x09\x09self stream nextPutAll: '])' ]",
+messageSends: ["ifNil:ifNotNil:", "nextPutAll:", "stream", "visit:", "first", "instructions", ",", "asSelector", "selector", "do:separatedBy:", "allButFirst", "asJavascript", "classSend"],
+referencedClasses: []
+}),
+smalltalk.IRJSTranslator);
+
+smalltalk.addMethod(
+"_visitIRSendOld_",
+smalltalk.method({
+selector: "visitIRSendOld:",
+category: 'visiting',
+fn: function (anIRSend){
+var self=this;
 var $1;
 var $1;
 smalltalk.send(smalltalk.send(self,"_stream",[]),"_nextPutAll_",["smalltalk.send("]);
 smalltalk.send(smalltalk.send(self,"_stream",[]),"_nextPutAll_",["smalltalk.send("]);
 smalltalk.send(self,"_visit_",[smalltalk.send(smalltalk.send(anIRSend,"_instructions",[]),"_first",[])]);
 smalltalk.send(self,"_visit_",[smalltalk.send(smalltalk.send(anIRSend,"_instructions",[]),"_first",[])]);
@@ -2566,7 +2664,7 @@ smalltalk.send(smalltalk.send(self,"_stream",[]),"_nextPutAll_",[smalltalk.send(
 smalltalk.send(smalltalk.send(self,"_stream",[]),"_nextPutAll_",[")"]);
 smalltalk.send(smalltalk.send(self,"_stream",[]),"_nextPutAll_",[")"]);
 return self},
 return self},
 args: ["anIRSend"],
 args: ["anIRSend"],
-source: "visitIRSend: anIRSend\x0a\x09self stream nextPutAll: 'smalltalk.send('.\x0a\x09self visit: anIRSend instructions first.\x0a\x09self stream nextPutAll:  ',\x22', anIRSend selector asSelector, '\x22,['.\x0a\x09anIRSend instructions allButFirst\x0a\x09\x09do: [ :each | self visit: each ]\x0a\x09\x09separatedBy: [ self stream nextPutAll: ',' ].\x0a\x09self stream nextPutAll: ']'.\x0a\x09\x22anIRSend index > 1 \x0a\x09\x09ifTrue: [\x0a\x09\x09\x09anIRSend classSend \x0a\x09\x09\x09\x09ifNil: [ self stream nextPutAll: ',undefined' ]\x0a\x09\x09\x09\x09ifNotNil: [ self stream nextPutAll: ',', anIRSend classSend asJavascript ].\x0a\x09\x09\x09self stream nextPutAll: ',', anIRSend index asString ]\x0a\x09\x09ifFalse: [\x22\x0a\x09\x09\x09anIRSend classSend ifNotNil: [  \x0a\x09\x09\x09\x09self stream nextPutAll: ',', anIRSend classSend asJavascript ]\x22]\x22.\x0a\x09self stream nextPutAll: ')'",
+source: "visitIRSendOld: anIRSend\x0a\x09self stream nextPutAll: 'smalltalk.send('.\x0a\x09self visit: anIRSend instructions first.\x0a\x09self stream nextPutAll:  ',\x22', anIRSend selector asSelector, '\x22,['.\x0a\x09anIRSend instructions allButFirst\x0a\x09\x09do: [ :each | self visit: each ]\x0a\x09\x09separatedBy: [ self stream nextPutAll: ',' ].\x0a\x09self stream nextPutAll: ']'.\x0a\x09\x22anIRSend index > 1 \x0a\x09\x09ifTrue: [\x0a\x09\x09\x09anIRSend classSend \x0a\x09\x09\x09\x09ifNil: [ self stream nextPutAll: ',undefined' ]\x0a\x09\x09\x09\x09ifNotNil: [ self stream nextPutAll: ',', anIRSend classSend asJavascript ].\x0a\x09\x09\x09self stream nextPutAll: ',', anIRSend index asString ]\x0a\x09\x09ifFalse: [\x22\x0a\x09\x09\x09anIRSend classSend ifNotNil: [  \x0a\x09\x09\x09\x09self stream nextPutAll: ',', anIRSend classSend asJavascript ]\x22]\x22.\x0a\x09self stream nextPutAll: ')'",
 messageSends: ["nextPutAll:", "stream", "visit:", "first", "instructions", ",", "asSelector", "selector", "do:separatedBy:", "allButFirst", "ifNotNil:", "asJavascript", "classSend"],
 messageSends: ["nextPutAll:", "stream", "visit:", "first", "instructions", ",", "asSelector", "selector", "do:separatedBy:", "allButFirst", "ifNotNil:", "asJavascript", "classSend"],
 referencedClasses: []
 referencedClasses: []
 }),
 }),
@@ -2792,6 +2890,28 @@ referencedClasses: []
 }),
 }),
 smalltalk.JSStream);
 smalltalk.JSStream);
 
 
+smalltalk.addMethod(
+"_nextPutContextFor_during_",
+smalltalk.method({
+selector: "nextPutContextFor:during:",
+category: 'streaming',
+fn: function (aMethod,aBlock){
+var self=this;
+var $1;
+_st(self)._nextPutAll_("return smalltalk.withContext(function() {");
+_st(aBlock)._value();
+_st(self)._nextPutAll_("}, self, ");
+_st(self)._nextPutAll_(_st(_st(_st(aMethod)._selector())._asJavascript()).__comma(", "));
+_st(self)._nextPutAll_(_st(_st(aMethod)._arguments())._asJavascript());
+$1=_st(self)._nextPutAll_(")");
+return self},
+args: ["aMethod", "aBlock"],
+source: "nextPutContextFor: aMethod during: aBlock\x0a\x09self nextPutAll: 'return smalltalk.withContext(function() {'.\x0a    aBlock value.\x0a    self \x0a    \x09nextPutAll: '}, self, ';\x0a        nextPutAll: aMethod selector asJavascript, ', ';\x0a        nextPutAll: aMethod arguments asJavascript;\x0a        nextPutAll: ')'",
+messageSends: ["nextPutAll:", "value", ",", "asJavascript", "selector", "arguments"],
+referencedClasses: []
+}),
+smalltalk.JSStream);
+
 smalltalk.addMethod(
 smalltalk.addMethod(
 "_nextPutFunctionWith_arguments_",
 "_nextPutFunctionWith_arguments_",
 smalltalk.method({
 smalltalk.method({
@@ -2875,31 +2995,31 @@ category: 'streaming',
 fn: function (aMethod,aBlock){
 fn: function (aMethod,aBlock){
 var self=this;
 var self=this;
 var $1,$2,$3;
 var $1,$2,$3;
-smalltalk.send(self["@stream"],"_nextPutAll_",["smalltalk.method({"]);
-smalltalk.send(self["@stream"],"_lf",[]);
-smalltalk.send(self["@stream"],"_nextPutAll_",[smalltalk.send(smalltalk.send("selector: \x22","__comma",[smalltalk.send(aMethod,"_selector",[])]),"__comma",["\x22,"])]);
-smalltalk.send(self["@stream"],"_lf",[]);
-smalltalk.send(self["@stream"],"_nextPutAll_",[smalltalk.send(smalltalk.send("source: ","__comma",[smalltalk.send(smalltalk.send(aMethod,"_source",[]),"_asJavascript",[])]),"__comma",[","])]);
-$1=smalltalk.send(self["@stream"],"_lf",[]);
-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_",[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",[","])]);
-smalltalk.send(self["@stream"],"_lf",[]);
-$2=smalltalk.send(self["@stream"],"_nextPutAll_",["referencedClasses: ["]);
-smalltalk.send(smalltalk.send(aMethod,"_classReferences",[]),"_do_separatedBy_",[(function(each){
-return smalltalk.send(self["@stream"],"_nextPutAll_",[smalltalk.send(each,"_asJavascript",[])]);
+_st(self["@stream"])._nextPutAll_("smalltalk.method({");
+_st(self["@stream"])._lf();
+_st(self["@stream"])._nextPutAll_(_st(_st("selector: \x22").__comma(_st(aMethod)._selector())).__comma("\x22,"));
+_st(self["@stream"])._lf();
+_st(self["@stream"])._nextPutAll_(_st(_st("source: ").__comma(_st(_st(aMethod)._source())._asJavascript())).__comma(","));
+$1=_st(self["@stream"])._lf();
+_st(aBlock)._value();
+_st(self["@stream"])._nextPutAll_(_st(_st(",").__comma(_st((smalltalk.String || String))._lf())).__comma("messageSends: "));
+_st(self["@stream"])._nextPutAll_(_st(_st(_st(_st(aMethod)._messageSends())._asArray())._asJavascript()).__comma(","));
+_st(self["@stream"])._lf();
+_st(self["@stream"])._nextPutAll_(_st(_st("args: ").__comma(_st(_st(_st(_st(aMethod)._arguments())._collect_((function(each){
+return _st(each)._value();
+})))._asArray())._asJavascript())).__comma(","));
+_st(self["@stream"])._lf();
+$2=_st(self["@stream"])._nextPutAll_("referencedClasses: [");
+_st(_st(aMethod)._classReferences())._do_separatedBy_((function(each){
+return _st(self["@stream"])._nextPutAll_(_st(each)._asJavascript());
 }),(function(){
 }),(function(){
-return smalltalk.send(self["@stream"],"_nextPutAll_",[","]);
-})]);
-smalltalk.send(self["@stream"],"_nextPutAll_",["]"]);
-$3=smalltalk.send(self["@stream"],"_nextPutAll_",["})"]);
+return _st(self["@stream"])._nextPutAll_(",");
+}));
+_st(self["@stream"])._nextPutAll_("]");
+$3=_st(self["@stream"])._nextPutAll_("})");
 return self},
 return self},
 args: ["aMethod", "aBlock"],
 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: '})'",
+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        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", "collect:", "arguments", "do:separatedBy:", "classReferences"],
 messageSends: ["nextPutAll:", "lf", ",", "selector", "asJavascript", "source", "value", "asArray", "messageSends", "collect:", "arguments", "do:separatedBy:", "classReferences"],
 referencedClasses: ["String"]
 referencedClasses: ["String"]
 }),
 }),
@@ -2981,30 +3101,6 @@ referencedClasses: []
 }),
 }),
 smalltalk.JSStream);
 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(
 smalltalk.addMethod(
 "_nextPutSequenceWith_",
 "_nextPutSequenceWith_",
 smalltalk.method({
 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(
 smalltalk.addMethod(
 "_classReferences",
 "_classReferences",
 smalltalk.method({
 smalltalk.method({
@@ -975,6 +975,24 @@ fn: function (aScope) {
 }),
 }),
 smalltalk.SemanticAnalyzer);
 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(
 smalltalk.addMethod(
 "_theClass",
 "_theClass",
 smalltalk.method({
 smalltalk.method({
@@ -1084,20 +1102,25 @@ smalltalk.addMethod(
 "_visitMethodNode_",
 "_visitMethodNode_",
 smalltalk.method({
 smalltalk.method({
 selector: "visitMethodNode:",
 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);
 smalltalk.SemanticAnalyzer);
 
 
@@ -1125,29 +1148,34 @@ smalltalk.addMethod(
 "_visitSendNode_",
 "_visitSendNode_",
 smalltalk.method({
 smalltalk.method({
 selector: "visitSendNode:",
 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);
 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.SemanticAnalyzer.comment="I semantically analyze the abstract syntax tree and annotate it with informations such as non local returns and variable scopes."
 smalltalk.addMethod(
 smalltalk.addMethod(
 "_classReferences",
 "_classReferences",
@@ -1331,6 +1331,29 @@ referencedClasses: []
 }),
 }),
 smalltalk.SemanticAnalyzer);
 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(
 smalltalk.addMethod(
 "_theClass",
 "_theClass",
 smalltalk.method({
 smalltalk.method({
@@ -1476,23 +1499,28 @@ smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
 selector: "visitMethodNode:",
 selector: "visitMethodNode:",
 category: 'visiting',
 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"],
 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: []
 referencedClasses: []
 }),
 }),
 smalltalk.SemanticAnalyzer);
 smalltalk.SemanticAnalyzer);
@@ -1527,33 +1555,38 @@ smalltalk.addMethod(
 smalltalk.method({
 smalltalk.method({
 selector: "visitSendNode:",
 selector: "visitSendNode:",
 category: 'visiting',
 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"],
 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);
 smalltalk.SemanticAnalyzer);
 
 

+ 5 - 4
js/Kernel-Classes.deploy.js

@@ -232,9 +232,10 @@ smalltalk.method({
 selector: "methodAt:",
 selector: "methodAt:",
 fn: function (aSymbol){
 fn: function (aSymbol){
 var self=this;
 var self=this;
-return smalltalk.methods(self)[aSymbol._asString()];
-;
-return self}
+var $1;
+$1=_st(_st(self)._methodDictionary())._at_(_st(aSymbol)._asString());
+return $1;
+}
 }),
 }),
 smalltalk.Behavior);
 smalltalk.Behavior);
 
 
@@ -245,7 +246,7 @@ selector: "methodDictionary",
 fn: function (){
 fn: function (){
 var self=this;
 var self=this;
 var dict = smalltalk.HashedCollection._new();
 var dict = smalltalk.HashedCollection._new();
-	var methods = self.fn.prototype.methods;
+	var methods = self.methods;
 	for(var i in methods) {
 	for(var i in methods) {
 		if(methods[i].selector) {
 		if(methods[i].selector) {
 			dict._at_put_(methods[i].selector, methods[i]);
 			dict._at_put_(methods[i].selector, methods[i]);

+ 8 - 7
js/Kernel-Classes.js

@@ -309,12 +309,13 @@ selector: "methodAt:",
 category: 'accessing',
 category: 'accessing',
 fn: function (aSymbol){
 fn: function (aSymbol){
 var self=this;
 var self=this;
-return smalltalk.methods(self)[aSymbol._asString()];
-;
-return self},
+var $1;
+$1=_st(_st(self)._methodDictionary())._at_(_st(aSymbol)._asString());
+return $1;
+},
 args: ["aSymbol"],
 args: ["aSymbol"],
-source: "methodAt: aSymbol\x0a\x09<return smalltalk.methods(self)[aSymbol._asString()]>",
-messageSends: [],
+source: "methodAt: aSymbol\x0a\x09^ self methodDictionary at: aSymbol asString",
+messageSends: ["at:", "asString", "methodDictionary"],
 referencedClasses: []
 referencedClasses: []
 }),
 }),
 smalltalk.Behavior);
 smalltalk.Behavior);
@@ -327,7 +328,7 @@ category: 'accessing',
 fn: function (){
 fn: function (){
 var self=this;
 var self=this;
 var dict = smalltalk.HashedCollection._new();
 var dict = smalltalk.HashedCollection._new();
-	var methods = self.fn.prototype.methods;
+	var methods = self.methods;
 	for(var i in methods) {
 	for(var i in methods) {
 		if(methods[i].selector) {
 		if(methods[i].selector) {
 			dict._at_put_(methods[i].selector, methods[i]);
 			dict._at_put_(methods[i].selector, methods[i]);
@@ -337,7 +338,7 @@ var dict = smalltalk.HashedCollection._new();
 ;
 ;
 return self},
 return self},
 args: [],
 args: [],
-source: "methodDictionary\x0a\x09<var dict = smalltalk.HashedCollection._new();\x0a\x09var methods = self.fn.prototype.methods;\x0a\x09for(var i in methods) {\x0a\x09\x09if(methods[i].selector) {\x0a\x09\x09\x09dict._at_put_(methods[i].selector, methods[i]);\x0a\x09\x09}\x0a\x09};\x0a\x09return dict>",
+source: "methodDictionary\x0a\x09<var dict = smalltalk.HashedCollection._new();\x0a\x09var methods = self.methods;\x0a\x09for(var i in methods) {\x0a\x09\x09if(methods[i].selector) {\x0a\x09\x09\x09dict._at_put_(methods[i].selector, methods[i]);\x0a\x09\x09}\x0a\x09};\x0a\x09return dict>",
 messageSends: [],
 messageSends: [],
 referencedClasses: []
 referencedClasses: []
 }),
 }),

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

@@ -2312,20 +2312,9 @@ smalltalk.method({
 selector: "asSelector",
 selector: "asSelector",
 fn: function (){
 fn: function (){
 var self=this;
 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(self);
+;
+return self}
 }),
 }),
 smalltalk.String);
 smalltalk.String);
 
 
@@ -3073,6 +3062,19 @@ return self}
 }),
 }),
 smalltalk.Symbol);
 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(
 smalltalk.addMethod(
 "_asSymbol",
 "_asSymbol",
 smalltalk.method({
 smalltalk.method({

+ 23 - 16
js/Kernel-Collections.js

@@ -3104,23 +3104,12 @@ selector: "asSelector",
 category: 'converting',
 category: 'converting',
 fn: function (){
 fn: function (){
 var self=this;
 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(self);
+;
+return self},
 args: [],
 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(self)>",
+messageSends: [],
 referencedClasses: []
 referencedClasses: []
 }),
 }),
 smalltalk.String);
 smalltalk.String);
@@ -4134,6 +4123,24 @@ referencedClasses: []
 }),
 }),
 smalltalk.Symbol);
 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(
 smalltalk.addMethod(
 "_asSymbol",
 "_asSymbol",
 smalltalk.method({
 smalltalk.method({

+ 388 - 203
js/boot.js

@@ -13,29 +13,29 @@
    | Amber is released under the MIT license
    | Amber is released under the MIT license
    |
    |
    | Permission is hereby granted, free of charge, to any person obtaining
    | Permission is hereby granted, free of charge, to any person obtaining
-   | a copy of this software and associated documentation files (the 
-   | 'Software'), to deal in the Software without restriction, including 
-   | without limitation the rights to use, copy, modify, merge, publish, 
-   | distribute, sublicense, and/or sell copies of the Software, and to 
-   | permit persons to whom the Software is furnished to do so, subject to 
+   | a copy of this software and associated documentation files (the
+   | 'Software'), to deal in the Software without restriction, including
+   | without limitation the rights to use, copy, modify, merge, publish,
+   | distribute, sublicense, and/or sell copies of the Software, and to
+   | permit persons to whom the Software is furnished to do so, subject to
    | the following conditions:
    | the following conditions:
    |
    |
-   | The above copyright notice and this permission notice shall be 
+   | The above copyright notice and this permission notice shall be
    | included in all copies or substantial portions of the Software.
    | included in all copies or substantial portions of the Software.
    |
    |
-   | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 
-   | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
-   | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
-   | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
-   | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
-   | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
-   | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  
+   | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+   | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+   | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+   | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+   | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+   | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    |
    |
    ==================================================================== */
    ==================================================================== */
 
 
 /* Make sure that console is defined */
 /* Make sure that console is defined */
 
 
-if (typeof console === "undefined") {
+if(typeof console === "undefined") {
 	this.console = {
 	this.console = {
 		log: function() {},
 		log: function() {},
 		warn: function() {},
 		warn: function() {},
@@ -45,51 +45,65 @@ if (typeof console === "undefined") {
 	};
 	};
 }
 }
 
 
-/* Smalltalk constructors definition */
+/* Array extensions */
 
 
-function SmalltalkObject(){};
-function SmalltalkBehavior(){};
-function SmalltalkClass(){};
-function SmalltalkPackage(){};
-function SmalltalkMetaclass(){
-	this.meta = true;
+Array.prototype.addElement = function(el) {
+	if(typeof el === 'undefined') { return; }
+	if(this.indexOf(el) == -1) {
+        this.push(el);
+    }
 };
 };
-function SmalltalkMethod(){};
-function SmalltalkNil(){};
 
 
-function SmalltalkSymbol(string){
-	this.value = string;
+Array.prototype.removeElement = function(el) {
+    for(var i=0; i<this.length; i++) {
+        if(this[i] == el) {
+            this.splice(i, 1);
+            break;
+        }
+    }
 };
 };
 
 
+
+/* Smalltalk constructors definition */
+
+function SmalltalkObject() {}
+function SmalltalkBehavior() {}
+function SmalltalkClass() {}
+function SmalltalkMetaclass() {
+	this.meta = true;
+}
+function SmalltalkPackage() {}
+function SmalltalkMethod() {}
+function SmalltalkNil() {}
+function SmalltalkSymbol(string) {
+	this.value = string;
+}
 function SmalltalkOrganizer() {
 function SmalltalkOrganizer() {
     this.elements = [];
     this.elements = [];
-};
+}
 
 
-SmalltalkOrganizer.prototype.addElement = function(el) {
-    if(typeof el === 'undefined' || el === nil) {
-        return false;
-    }
-    if(this.elements.indexOf(el) == -1) {
-        this.elements.push(el);
-    }
-};
+function inherits(child, parent) {
+	child.prototype = Object.create(parent.prototype, {
+		constructor: { value: child,
+			enumerable: false, configurable: true, writable: true }
+	});
+}
 
 
-SmalltalkOrganizer.prototype.removeElement = function(el) {
-    for(var i=0; i<this.elements.length; i++) {
-        if(this.elements[i] == el) {
-            this.elements.splice(i, 1);
-            break;
-        }
-    }
-};
+inherits(SmalltalkBehavior, SmalltalkObject);
+inherits(SmalltalkClass, SmalltalkBehavior);
+inherits(SmalltalkMetaclass, SmalltalkBehavior);
+inherits(SmalltalkNil, SmalltalkObject);
+inherits(SmalltalkMethod, SmalltalkObject);
+inherits(SmalltalkPackage, SmalltalkObject);
+inherits(SmalltalkOrganizer, SmalltalkObject);
 
 
 
 
-function Smalltalk(){
+function Smalltalk() {
 
 
 	var st = this;
 	var st = this;
 
 
 	/* This is the current call context object. While it is publicly available,
 	/* This is the current call context object. While it is publicly available,
-	   Use smalltalk.getThisContext() instead which will answer a safe copy of 
+	   Use smalltalk.getThisContext() instead which will answer a safe copy of
 	   the current context */
 	   the current context */
 
 
 	st.thisContext = undefined;
 	st.thisContext = undefined;
@@ -97,26 +111,61 @@ function Smalltalk(){
 	/* List of all reserved words in JavaScript. They may not be used as variables
 	/* List of all reserved words in JavaScript. They may not be used as variables
 	   in Smalltalk. */
 	   in Smalltalk. */
 
 
-	st.reservedWords = ['break', 'case', 'catch', 'char', 'class', 'continue', 'debugger', 
-		'default', 'delete', 'do', 'else', 'finally', 'for', 'function', 
-		'if', 'in', 'instanceof', 'new', 'private', 'protected', 
+	st.reservedWords = ['break', 'case', 'catch', 'char', 'class', 'continue', 'debugger',
+		'default', 'delete', 'do', 'else', 'finally', 'for', 'function',
+		'if', 'in', 'instanceof', 'native', 'new', 'private', 'protected',
 		'public', 'return', 'static', 'switch', 'this', 'throw',
 		'public', 'return', 'static', 'switch', 'this', 'throw',
 		'try', 'typeof', 'var', 'void', 'while', 'with', 'yield'];
 		'try', 'typeof', 'var', 'void', 'while', 'with', 'yield'];
 
 
+    var initialized = false;
+
+    /* Smalltalk classes */
+
+    var classes = [];
+    var wrappedClasses = [];
+
+    /* Method not implemented handlers */
+
+	var dnu = {
+		methods: [],
+		selectors: [],
+
+		get: function (string) {
+			var index = this.selectors.indexOf(string);
+			if(index !== -1) {
+				return this.methods[index];
+			}
+			this.selectors.push(string);
+			var selector = st.selector(string);
+			var method = {jsSelector: selector, fn: this.createHandler(selector)};
+			this.methods.push(method);
+			return method;
+		},
+
+		/* Dnu handler method */
+
+		createHandler: function (selector) {
+			return function () {
+				var args = Array.prototype.slice.call(arguments);
+				return messageNotUnderstood(this, selector, args);
+			};
+		}
+	};
+
 	/* The symbol table ensures symbol unicity */
 	/* The symbol table ensures symbol unicity */
 
 
-	symbolTable = {};
+	var symbolTable = {};
 	st.symbolFor = function(string) {
 	st.symbolFor = function(string) {
 		if(symbolTable[string] === undefined) {
 		if(symbolTable[string] === undefined) {
 			symbolTable[string] = new SmalltalkSymbol(string);
 			symbolTable[string] = new SmalltalkSymbol(string);
-		};
+		}
 
 
 		return symbolTable[string];
 		return symbolTable[string];
 	};
 	};
 
 
 	/* Unique ID number generator */
 	/* Unique ID number generator */
 
 
-	oid = 0;
+	var oid = 0;
 	st.nextId = function() {
 	st.nextId = function() {
 		oid += 1;
 		oid += 1;
 		return oid;
 		return oid;
@@ -134,18 +183,22 @@ function Smalltalk(){
         that.organization = new SmalltalkOrganizer();
         that.organization = new SmalltalkOrganizer();
 		that.properties = spec.properties || {};
 		that.properties = spec.properties || {};
 		return that;
 		return that;
-	};
+	}
 
 
-	/* Smalltalk class creation. A class is an instance of an automatically 
+	/* Smalltalk class creation. A class is an instance of an automatically
 	   created metaclass object. Newly created classes (not their metaclass) 
 	   created metaclass object. Newly created classes (not their metaclass) 
 	   should be added to the smalltalk object, see smalltalk.addClass().
 	   should be added to the smalltalk object, see smalltalk.addClass().
 	   Superclass linking is *not* handled here, see smalltalk.init()  */
 	   Superclass linking is *not* handled here, see smalltalk.init()  */
 
 
 	function klass(spec) {
 	function klass(spec) {
-		var spec = spec || {};
-		var meta = metaclass();
-		var that = setupClass(meta.instanceClass, spec);
-		that.className = spec.className;
+		spec = spec || {};
+		var meta = metaclass(spec);
+		var that = meta.instanceClass;
+		that.fn = spec.fn || function() {};
+		setupClass(that, spec);
+
+        that.className = spec.className;
+        that.wrapped   = spec.wrapped || false;
 		meta.className = spec.className + ' class';
 		meta.className = spec.className + ' class';
 		if(spec.superclass) {
 		if(spec.superclass) {
 			that.superclass = spec.superclass;
 			that.superclass = spec.superclass;
@@ -153,29 +206,36 @@ function Smalltalk(){
 		}
 		}
 		return that;
 		return that;
 	}
 	}
-	
-	function metaclass() {
-		var meta = setupClass(new SmalltalkMetaclass(), {})
-		meta.instanceClass = new meta.fn;
-		return meta;
+
+	function metaclass(spec) {
+		spec = spec || {};
+		var that = new SmalltalkMetaclass();
+		inherits(
+			that.fn = function() {},
+			spec.superclass ? spec.superclass.klass.fn : SmalltalkClass
+		);
+		that.instanceClass = new that.fn();
+        setupClass(that);
+		return that;
 	}
 	}
-	
-	function setupClass(that, spec) {
-		that.fn = spec.fn || function(){};
-		that.iVarNames = spec.iVarNames || [];
-		Object.defineProperty(that, "toString", {
-			value: function() { return 'Smalltalk ' + this.className; }, 
-            configurable: true // no writable - in par with ES6 methods
+
+	function setupClass(klass, spec) {
+        spec = spec || {};
+		klass.iVarNames = spec.iVarNames || [];
+		klass.pkg = spec.pkg;
+
+        Object.defineProperty(klass, "toString", {
+			value: function() { return 'Smalltalk ' + this.className; },
+            enumerable:false, configurable: true, writable: false
 		});
 		});
-        that.organization = new SmalltalkOrganizer();
-		that.pkg = spec.pkg;
-		Object.defineProperties(that.fn.prototype, {
-			methods: { value: {}, enumerable: false, configurable: true, writable: true },
-			inheritedMethods: { value: {}, enumerable: false, configurable: true, writable: true },
-			klass: { value: that, enumerable: false, configurable: true, writable: true }
+
+		klass.organization = new SmalltalkOrganizer();
+		Object.defineProperty(klass, "methods", {
+			value: {},
+			enumerable: false, configurable: true, writable: true
 		});
 		});
-		return that;
-	};
+		wireKlass(klass);
+	}
 
 
 	/* Smalltalk method object. To add a method to a class,
 	/* Smalltalk method object. To add a method to a class,
 	   use smalltalk.addMethod() */
 	   use smalltalk.addMethod() */
@@ -193,9 +253,9 @@ function Smalltalk(){
 		return that;
 		return that;
 	};
 	};
 
 
-	/* Initialize a class in its class hierarchy. Handle both class and
+	/* Initialize a class in its class hierarchy. Handle both classes and
 	   metaclasses. */
 	   metaclasses. */
-	   
+
 	st.init = function(klass) {
 	st.init = function(klass) {
 		st.initClass(klass);
 		st.initClass(klass);
 		if(klass.klass && !klass.meta) {
 		if(klass.klass && !klass.meta) {
@@ -203,71 +263,102 @@ function Smalltalk(){
 		}
 		}
 	};
 	};
 
 
-	st.initClass = function(klass) {
-		var subclasses = st.subclasses(klass);
-		var methods, prototype = klass.fn.prototype;
+    st.initClass = function(klass) {
+        if(klass.wrapped) {
+            copySuperclass(klass);
+        }
+        else {
+            installSuperclass(klass);
+        }
+
+        if(klass === st.Object || klass.wrapped) {
+            installDnuHandlers(klass);
+        }
+    };
+
+	function wireKlass(klass) {
+		Object.defineProperty(klass.fn.prototype, "klass", {
+			value: klass,
+			enumerable: false, configurable: true, writable: true
+		});
+	}
+
+	function installSuperclass(klass) {
+        // only if the klass has not been initialized yet.
+		if(klass.fn.prototype._yourself) { return; }
 
 
 		if(klass.superclass && klass.superclass !== nil) {
 		if(klass.superclass && klass.superclass !== nil) {
-			methods = st.methods(klass.superclass);
-
-			//Methods linking
-			for(var keys = Object.keys(methods), i=0; i<keys.length; i++) {
-				var key = keys[i];
-				if(!prototype.methods[key]) {
-					prototype.inheritedMethods[key] = methods[key];
-					Object.defineProperty(prototype, methods[key].jsSelector, {
-						value: methods[key].fn, configurable: true, writable: true
-					});
-				}
+            inherits(klass.fn, klass.superclass.fn);
+			wireKlass(klass);
+			reinstallMethods(klass);
+        }
+	}
+
+	function copySuperclass(klass, superclass) {
+		for (superclass = superclass || klass.superclass;
+			 superclass && superclass !== nil;
+			 superclass = superclass.superclass) {
+			for (var keys = Object.keys(superclass.methods), i = 0; i < keys.length; i++) {
+				installMethodIfAbsent(superclass.methods[keys[i]], klass);
 			}
 			}
 		}
 		}
+	}
+
+	function installMethod(method, klass) {
+        Object.defineProperty(klass.fn.prototype, method.jsSelector, {
+			value: method.fn,
+			enumerable: false, configurable: true, writable: true
+		});
+	}
 
 
-		for(var i=0; i<subclasses.length; i++) {
-			st.initClass(subclasses[i]);
+	function installMethodIfAbsent(method, klass) {
+		if(!klass.fn.prototype[method.jsSelector]) {
+			installMethod(method, klass);
 		}
 		}
-	};
+	}
 
 
+	function reinstallMethods(klass) {
+        for(var keys = Object.keys(klass.methods), i=0; i<keys.length; i++) {
+            installMethod(klass.methods[keys[i]], klass);
+		}
+	}
+
+	function installDnuHandlers(klass) {
+		var m = dnu.methods;
+        for(var i=0; i<m.length; i++) {
+			installMethodIfAbsent(m[i], klass);
+        }
+	}
+
+	function installNewDnuHandler(newHandler) {
+		installMethodIfAbsent(newHandler, st.Object);
+		for(var i = 0; i < wrappedClasses.length; i++) {
+			installMethodIfAbsent(newHandler, wrappedClasses[i]);
+		}
+	}
 
 
 	/* Answer all registered Packages as Array */
 	/* Answer all registered Packages as Array */
+    // TODO: Remove this hack
 
 
 	st.packages.all = function() {
 	st.packages.all = function() {
 		var packages = [];
 		var packages = [];
 		for(var i in st.packages) {
 		for(var i in st.packages) {
-			if (!st.packages.hasOwnProperty(i) || typeof(st.packages[i]) === "function") continue;
+			if(!st.packages.hasOwnProperty(i) || typeof(st.packages[i]) === "function") continue;
 			packages.push(st.packages[i]);
 			packages.push(st.packages[i]);
 		}
 		}
 		return packages
 		return packages
 	};
 	};
 
 
 	/* Answer all registered Smalltalk classes */
 	/* Answer all registered Smalltalk classes */
+    //TODO: remove the function and make smalltalk.classes an array
 
 
 	st.classes = function() {
 	st.classes = function() {
-		var classes = [], names = Object.keys(st), l = names.length;
-		for (var i=0; i<l; i++) {
-			var name = names[i];
-			if (name.search(/^[A-Z]/) !== -1) {
-				classes.push(st[name]);
-			}
-		}
 		return classes;
 		return classes;
 	};
 	};
 
 
-
-	/* Answer all methods (included inherited ones) of klass. */
-
-	st.methods = function(klass) {
-		var methods = {};
-		inheritedMethods = klass.fn.prototype.inheritedMethods;
-		for(var i=0, keys=Object.keys(inheritedMethods); i<keys.length; i++) {
-			methods[keys[i]] = inheritedMethods[keys[i]];
-		}
-		var inheritedMethods = klass.fn.prototype.methods;
-		for(var i=0, keys=Object.keys(inheritedMethods); i<keys.length; i++) {
-			methods[keys[i]] = inheritedMethods[keys[i]];
-		}
-		return methods;
-	};
-
+    st.wrappedClasses = function() {
+        return wrappedClasses;
+    };
 
 
 	/* Answer the direct subclasses of klass. */
 	/* Answer the direct subclasses of klass. */
 
 
@@ -291,23 +382,32 @@ function Smalltalk(){
 		return subclasses;
 		return subclasses;
 	};
 	};
 
 
-	/* Create a new class wrapping a JavaScript constructor, and add it to the 
+	/* Create a new class wrapping a JavaScript constructor, and add it to the
 	   global smalltalk object. Package is lazily created if it does not exist with given name. */
 	   global smalltalk object. Package is lazily created if it does not exist with given name. */
 
 
-	st.wrapClassName = function(className, pkgName, fn, superclass) {
+	st.wrapClassName = function(className, pkgName, fn, superclass, wrapped) {
+        if(wrapped !== false) {
+            wrapped = true;
+        }
 		var pkg = st.addPackage(pkgName);
 		var pkg = st.addPackage(pkgName);
 		st[className] = klass({
 		st[className] = klass({
-			className:  className, 
+			className:  className,
 			superclass: superclass,
 			superclass: superclass,
-			pkg:        pkg, 
-			fn:         fn
+			pkg:        pkg,
+			fn:         fn,
+            wrapped:    wrapped
 		});
 		});
+
+        classes.addElement(st[className]);
+		if(wrapped) {wrappedClasses.addElement(st[className])}
+		pkg.organization.elements.addElement(st[className]);
 	};
 	};
 
 
 	/* Create an alias for an existing class */
 	/* Create an alias for an existing class */
+
 	st.alias = function(klass, alias) {
 	st.alias = function(klass, alias) {
 		st[alias] = klass;
 		st[alias] = klass;
-	}
+	};
 
 
 	/* Add a package to the smalltalk.packages object, creating a new one if needed.
 	/* Add a package to the smalltalk.packages object, creating a new one if needed.
 	   If pkgName is null or empty we return nil, which is an allowed package for a class.
 	   If pkgName is null or empty we return nil, which is an allowed package for a class.
@@ -323,7 +423,7 @@ function Smalltalk(){
 		} else {
 		} else {
 			if(properties) {
 			if(properties) {
 				st.packages[pkgName].properties = properties;
 				st.packages[pkgName].properties = properties;
-			}	
+			}
 		}
 		}
 		return st.packages[pkgName];
 		return st.packages[pkgName];
 	};
 	};
@@ -333,58 +433,68 @@ function Smalltalk(){
 
 
 	st.addClass = function(className, superclass, iVarNames, pkgName) {
 	st.addClass = function(className, superclass, iVarNames, pkgName) {
 		var pkg = st.addPackage(pkgName);
 		var pkg = st.addPackage(pkgName);
-		if(st[className]) {
+		if(st[className] && st[className].superclass === superclass) {
 			st[className].superclass = superclass;
 			st[className].superclass = superclass;
 			st[className].iVarNames = iVarNames;
 			st[className].iVarNames = iVarNames;
 			st[className].pkg = pkg || st[className].pkg;
 			st[className].pkg = pkg || st[className].pkg;
 		} else {
 		} else {
+            if(st[className]) {
+                st.removeClass(st[className]);
+			}
 			st[className] = klass({
 			st[className] = klass({
-				className: className, 
+				className: className,
 				superclass: superclass,
 				superclass: superclass,
 				pkg: pkg,
 				pkg: pkg,
 				iVarNames: iVarNames
 				iVarNames: iVarNames
 			});
 			});
 		}
 		}
 
 
-        pkg.organization.addElement(st[className]);
+        classes.addElement(st[className]);
+        pkg.organization.elements.addElement(st[className]);
 	};
 	};
 
 
     st.removeClass = function(klass) {
     st.removeClass = function(klass) {
-        klass.pkg.organization.removeElement(klass);
+        klass.pkg.organization.elements.removeElement(klass);
+        classes.removeElement(klass);
         delete st[klass.className];
         delete st[klass.className];
     };
     };
 
 
 	/* Add/remove a method to/from a class */
 	/* Add/remove a method to/from a class */
 
 
 	st.addMethod = function(jsSelector, method, klass) {
 	st.addMethod = function(jsSelector, method, klass) {
-		Object.defineProperty(klass.fn.prototype, jsSelector, {
-			value: method.fn, configurable: true, writable: true
-		});
-		klass.fn.prototype.methods[method.selector] = method;
-		method.methodClass = klass;
 		method.jsSelector = jsSelector;
 		method.jsSelector = jsSelector;
+		installMethod(method, klass);
+		klass.methods[method.selector] = method;
+		method.methodClass = klass;
+
+        klass.organization.elements.addElement(method.category);
 
 
-        klass.organization.addElement(method.category);
+        for(var i=0; i<method.messageSends.length; i++) {
+            var dnuHandler = dnu.get(method.messageSends[i]);
+            if(initialized) {
+                installNewDnuHandler(dnuHandler);
+			}
+		}
 	};
 	};
 
 
     st.removeMethod = function(method) {
     st.removeMethod = function(method) {
         var protocol = method.category;
         var protocol = method.category;
         var klass = method.methodClass;
         var klass = method.methodClass;
-		var methods = klass.fn.prototype.methods;
 
 
-		delete klass.fn.prototype[method.selector._asSelector()];
-		delete methods[method.selector];
+        delete klass.fn.prototype[st.selector(method.selector)];
+	    delete klass.methods[method.selector];
 
 
-		var selectors = Object.keys(methods);
+		var selectors = Object.keys(klass.methods);
 		var shouldDeleteProtocol = true;
 		var shouldDeleteProtocol = true;
-		for(var i= 0, l = selectors.length; i<l; i++) {
-            if(methods[selectors[i]].category === protocol) {
+
+		for(var i = 0, l = selectors.length; i<l; i++) {
+            if(klass.methods[selectors[i]].category === protocol) {
                 shouldDeleteProtocol = false;
                 shouldDeleteProtocol = false;
 				break;
 				break;
             };
             };
         };
         };
         if(shouldDeleteProtocol) {
         if(shouldDeleteProtocol) {
-            klass.organization.removeElement(protocol)
+            klass.organization.elements.removeElement(protocol)
         };
         };
     };
     };
 
 
@@ -400,6 +510,7 @@ function Smalltalk(){
 				st.thisContext = undefined;
 				st.thisContext = undefined;
 				if(error.smalltalkError) {
 				if(error.smalltalkError) {
 					handleError(error);
 					handleError(error);
+					return nil;
 				} else {
 				} else {
 					throw(error);
 					throw(error);
 				}
 				}
@@ -414,23 +525,46 @@ function Smalltalk(){
 		}
 		}
 		method = klass ? klass.fn.prototype[selector] : receiver.klass && receiver[selector];
 		method = klass ? klass.fn.prototype[selector] : receiver.klass && receiver[selector];
 		if(method) {
 		if(method) {
-			var context = pushContext(receiver, selector, method, args);
+			var context = pushContext(receiver, selector, args);
 			call = method.apply(receiver, args);
 			call = method.apply(receiver, args);
 			popContext(context);
 			popContext(context);
 			return call;
 			return call;
 		} else {
 		} else {
 			return messageNotUnderstood(receiver, selector, args);
 			return messageNotUnderstood(receiver, selector, args);
 		}
 		}
+	}
+
+	st.withContext = function(fn, receiver, selector, args) {
+		if(st.thisContext) {
+			return inContext(fn, receiver, selector, args);
+		} else {
+			try {return inContext(fn, receiver, selector, args)}
+			catch(error) {
+				// Reset the context stack in any case
+				st.thisContext = undefined;
+				if(error.smalltalkError) {
+					handleError(error);
+					return nil;
+				} else {
+					throw(error);
+				}
+			}
+		}
 	};
 	};
 
 
-	/* Handles Smalltalk errors. Triggers the registered ErrorHandler 
+	function inContext(fn, receiver, selector, args) {
+		var context = pushContext(receiver, selector, args);
+		var result = fn();
+		popContext(context);
+		return result;
+	}
+
+	/* Handles Smalltalk errors. Triggers the registered ErrorHandler
 	   (See the Smalltalk class ErrorHandler and its subclasses */
 	   (See the Smalltalk class ErrorHandler and its subclasses */
 
 
 	function handleError(error) {
 	function handleError(error) {
-        if(!error.cc) {
-		    smalltalk.ErrorHandler._current()._handleError_(error);
-        }
-	};
+        st.ErrorHandler._current()._handleError_(error);
+	}
 
 
 	/* Handles #dnu: *and* JavaScript method calls.
 	/* Handles #dnu: *and* JavaScript method calls.
 	   if the receiver has no klass, we consider it a JS object (outside of the
 	   if the receiver has no klass, we consider it a JS object (outside of the
@@ -442,7 +576,7 @@ function Smalltalk(){
 			return callJavaScriptMethod(receiver, selector, args);
 			return callJavaScriptMethod(receiver, selector, args);
 		}
 		}
 
 
-		/* Handles not understood messages. Also see the Amber counter-part 
+		/* Handles not understood messages. Also see the Amber counter-part
 		   Object>>doesNotUnderstand: */
 		   Object>>doesNotUnderstand: */
 
 
 		return receiver._doesNotUnderstand_(
 		return receiver._doesNotUnderstand_(
@@ -450,13 +584,13 @@ function Smalltalk(){
 				._selector_(st.convertSelector(selector))
 				._selector_(st.convertSelector(selector))
 				._arguments_(args)
 				._arguments_(args)
 				);
 				);
-	};
+	}
 
 
 	/* Call a method of a JS object, or answer a property if it exists.
 	/* Call a method of a JS object, or answer a property if it exists.
 	   Else try wrapping a JSObjectProxy around the receiver.
 	   Else try wrapping a JSObjectProxy around the receiver.
 
 
        If the object property is a function, then call it, except if it starts with
        If the object property is a function, then call it, except if it starts with
-       an uppercase character (we probably want to answer the function itself in this 
+       an uppercase character (we probably want to answer the function itself in this
        case and send it #new from Amber).
        case and send it #new from Amber).
 
 
 	   Converts keyword-based selectors by using the first
 	   Converts keyword-based selectors by using the first
@@ -480,8 +614,7 @@ function Smalltalk(){
 		}
 		}
 
 
 		return st.send(st.JSObjectProxy._on_(receiver), selector, args);
 		return st.send(st.JSObjectProxy._on_(receiver), selector, args);
-	};
-
+	}
 
 
 	/* Reuse one old context stored in oldContext */
 	/* Reuse one old context stored in oldContext */
 
 
@@ -491,31 +624,50 @@ function Smalltalk(){
 	/* Handle thisContext pseudo variable */
 	/* Handle thisContext pseudo variable */
 
 
 	st.getThisContext = function() {
 	st.getThisContext = function() {
-		if(st.thisContext) {
-			return st.thisContext.copy();
-		}
+		return st.thisContext ? st.thisContext.copy() : nil;
 	};
 	};
 
 
-	function pushContext(receiver, selector, method, temps) {
+	function pushContext(receiver, selector, temps) {
 		var c = st.oldContext, tc = st.thisContext;
 		var c = st.oldContext, tc = st.thisContext;
-		if (!c) {
-			return st.thisContext = new SmalltalkMethodContext(receiver, selector, method, temps, tc);
+		if(!c) {
+			return st.thisContext = new SmalltalkMethodContext(receiver, selector, temps, tc);
+
 		}
 		}
 		st.oldContext = null;
 		st.oldContext = null;
 		c.homeContext = tc;
 		c.homeContext = tc;
         c.pc          = 1;
         c.pc          = 1;
 		c.receiver    = receiver;
 		c.receiver    = receiver;
-        c.selector    = selector;
-		c.method      = method;
+        c.selector    = selector || "";
 		c.temps       = temps || {};
 		c.temps       = temps || {};
 		return st.thisContext = c;
 		return st.thisContext = c;
-	};
+	}
 
 
 	function popContext(context) {
 	function popContext(context) {
 		st.thisContext = context.homeContext;
 		st.thisContext = context.homeContext;
 		context.homeContext = undefined;
 		context.homeContext = undefined;
 		st.oldContext = context;
 		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, '_and');
+	    selector = selector.replace(/[\|]/g, '_or');
+	    selector = selector.replace(/[+]/g, '_plus');
+	    selector = selector.replace(/-/g, '_minus');
+	    selector = selector.replace(/[*]/g ,'_star');
+	    selector = selector.replace(/[\/]/g ,'_slash');
+	    selector = selector.replace(/[\\]/g ,'_backslash');
+	    selector = selector.replace(/[\~]/g ,'_tild');
+	    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
+    };
 
 
 	/* Convert a string to a valid smalltalk selector.
 	/* Convert a string to a valid smalltalk selector.
 	   if you modify the following functions, also change String>>asSelector
 	   if you modify the following functions, also change String>>asSelector
@@ -531,21 +683,25 @@ function Smalltalk(){
 
 
 	function convertKeywordSelector(selector) {
 	function convertKeywordSelector(selector) {
 		return selector.replace(/^_/, '').replace(/_/g, ':');
 		return selector.replace(/^_/, '').replace(/_/g, ':');
-	};
+	}
 
 
 	function convertBinarySelector(selector) {
 	function convertBinarySelector(selector) {
 		return selector
 		return selector
 			.replace(/^_/, '')
 			.replace(/^_/, '')
-			.replace(/_plus/, '+')
-			.replace(/_minus/, '-')
-			.replace(/_star/, '*')
-			.replace(/_slash/, '/')
-			.replace(/_gt/, '>')
-			.replace(/_lt/, '<')
-			.replace(/_eq/, '=')
-			.replace(/_comma/, ',')
-			.replace(/_at/, '@')
-	};
+			.replace(/_and/g, '&')
+			.replace(/_or/g, '|')
+			.replace(/_plus/g, '+')
+			.replace(/_minus/g, '-')
+			.replace(/_star/g, '*')
+			.replace(/_slash/g, '/')
+			.replace(/_backslash/g, '\\')
+			.replace(/_tild/g, '~')
+			.replace(/_gt/g, '>')
+			.replace(/_lt/g, '<')
+			.replace(/_eq/g, '=')
+			.replace(/_comma/g, ',')
+			.replace(/_at/g, '@')
+	}
 
 
 	/* Converts a JavaScript object to valid Smalltalk Object */
 	/* Converts a JavaScript object to valid Smalltalk Object */
 	st.readJSObject = function(js) {
 	st.readJSObject = function(js) {
@@ -554,12 +710,12 @@ function Smalltalk(){
 		var readArray = (js.constructor === Array);
 		var readArray = (js.constructor === Array);
 
 
 		if(readObject) {
 		if(readObject) {
-			object = smalltalk.Dictionary._new();
+			object = st.Dictionary._new();
 		}
 		}
 		for(var i in js) {
 		for(var i in js) {
 			if(readObject) {
 			if(readObject) {
 				object._at_put_(i, st.readJSObject(js[i]));
 				object._at_put_(i, st.readJSObject(js[i]));
-			} 
+			}
 			if(readArray) {
 			if(readArray) {
 				object[i] = st.readJSObject(js[i]);
 				object[i] = st.readJSObject(js[i]);
 			}
 			}
@@ -568,31 +724,49 @@ function Smalltalk(){
 	};
 	};
 
 
     /* Boolean assertion */
     /* Boolean assertion */
+
     st.assert = function(boolean) {
     st.assert = function(boolean) {
         if ((undefined !== boolean) && (boolean.klass === smalltalk.Boolean)) {
         if ((undefined !== boolean) && (boolean.klass === smalltalk.Boolean)) {
             return boolean;
             return boolean;
         } else {
         } else {
-            smalltalk.NonBooleanReceiver._new()._object_(boolean)._signal();
+            st.NonBooleanReceiver._new()._object_(boolean)._signal();
         }
         }
-    }
-};
+    };
 
 
-function SmalltalkMethodContext(receiver, selector, method, temps, home) {
+    /* Smalltalk initialization. Called on page load */
+
+    st.initialize = function() {
+		if(initialized) { return; }
+
+		classes.forEach(function(klass) {
+            st.init(klass);
+        });
+        classes.forEach(function(klass) {
+            klass._initialize();
+        });
+
+        initialized = true;
+    };
+}
+
+inherits(Smalltalk, SmalltalkObject);
+
+function SmalltalkMethodContext(receiver, selector, temps, home) {
 	this.receiver    = receiver;
 	this.receiver    = receiver;
     this.selector    = selector;
     this.selector    = selector;
-	this.method      = method;
 	this.temps       = temps || {};
 	this.temps       = temps || {};
 	this.homeContext = home;
 	this.homeContext = home;
-};
+}
+
+inherits(SmalltalkMethodContext, SmalltalkObject);
 
 
 SmalltalkMethodContext.prototype.copy = function() {
 SmalltalkMethodContext.prototype.copy = function() {
 	var home = this.homeContext;
 	var home = this.homeContext;
 	if(home) {home = home.copy()}
 	if(home) {home = home.copy()}
 	return new SmalltalkMethodContext(
 	return new SmalltalkMethodContext(
-		this.receiver, 
+		this.receiver,
         this.selector,
         this.selector,
-		this.method, 
-		this.temps, 
+		this.temps,
 		home
 		home
 	);
 	);
 };
 };
@@ -612,39 +786,50 @@ if(this.jQuery) {
 	this.jQuery.allowJavaScriptCalls = true;
 	this.jQuery.allowJavaScriptCalls = true;
 }
 }
 
 
-/****************************************************************************************/
+/*
+ * Answer the smalltalk representation of o.
+ * Used in message sends
+ */
 
 
+var _st = function(o) {
+	if(typeof o === 'undefined') {return nil}
+	if(o.klass) {return o}
+	return smalltalk.JSObjectProxy._on_(o);
+}; 
 
 
-/* Base classes wrapping. If you edit this part, do not forget to set the superclass of the
-   object metaclass to Class after the definition of Object */
 
 
-smalltalk.wrapClassName("Object", "Kernel", SmalltalkObject);
-smalltalk.wrapClassName("Smalltalk", "Kernel", Smalltalk, smalltalk.Object);
-smalltalk.wrapClassName("Package", "Kernel", SmalltalkPackage, smalltalk.Object);
-smalltalk.wrapClassName("Behavior", "Kernel", SmalltalkBehavior, smalltalk.Object);
-smalltalk.wrapClassName("Class", "Kernel", SmalltalkClass, smalltalk.Behavior);
-smalltalk.wrapClassName("Metaclass", "Kernel", SmalltalkMetaclass, smalltalk.Behavior);
-smalltalk.wrapClassName("CompiledMethod", "Kernel", SmalltalkMethod, smalltalk.Object);
-smalltalk.wrapClassName("Organizer", "Kernel-Objects", SmalltalkOrganizer, smalltalk.Object);
+/***************************************** BOOTSTRAP ******************************************/
+
+smalltalk.wrapClassName("Object", "Kernel-Objects", SmalltalkObject, undefined, false);
+smalltalk.wrapClassName("Behavior", "Kernel-Classes", SmalltalkBehavior, smalltalk.Object, false);
+smalltalk.wrapClassName("Metaclass", "Kernel-Classes", SmalltalkMetaclass, smalltalk.Behavior, false);
+smalltalk.wrapClassName("Class", "Kernel-Classes", SmalltalkClass, smalltalk.Behavior, false);
 
 
 smalltalk.Object.klass.superclass = smalltalk.Class;
 smalltalk.Object.klass.superclass = smalltalk.Class;
 
 
+
+smalltalk.wrapClassName("Smalltalk", "Kernel-Objects", Smalltalk, smalltalk.Object, false);
+smalltalk.wrapClassName("Package", "Kernel-Objects", SmalltalkPackage, smalltalk.Object, false);
+smalltalk.wrapClassName("CompiledMethod", "Kernel-Objects", SmalltalkMethod, smalltalk.Object, false);
+smalltalk.wrapClassName("Organizer", "Kernel-Objects", SmalltalkOrganizer, smalltalk.Object, false);
+
+
 smalltalk.wrapClassName("Number", "Kernel", Number, smalltalk.Object);
 smalltalk.wrapClassName("Number", "Kernel", Number, smalltalk.Object);
 smalltalk.wrapClassName("BlockClosure", "Kernel", Function, smalltalk.Object);
 smalltalk.wrapClassName("BlockClosure", "Kernel", Function, smalltalk.Object);
 smalltalk.wrapClassName("Boolean", "Kernel", Boolean, smalltalk.Object);
 smalltalk.wrapClassName("Boolean", "Kernel", Boolean, smalltalk.Object);
 smalltalk.wrapClassName("Date", "Kernel", Date, smalltalk.Object);
 smalltalk.wrapClassName("Date", "Kernel", Date, smalltalk.Object);
-smalltalk.wrapClassName("UndefinedObject", "Kernel", SmalltalkNil, smalltalk.Object);
+smalltalk.wrapClassName("UndefinedObject", "Kernel", SmalltalkNil, smalltalk.Object, false);
 
 
-smalltalk.wrapClassName("Collection", "Kernel", null, smalltalk.Object);
-smalltalk.wrapClassName("SequenceableCollection", "Kernel", null, smalltalk.Collection);
-smalltalk.wrapClassName("CharacterArray", "Kernel", null, smalltalk.SequenceableCollection);
+smalltalk.wrapClassName("Collection", "Kernel", null, smalltalk.Object, false);
+smalltalk.wrapClassName("SequenceableCollection", "Kernel", null, smalltalk.Collection, false);
+smalltalk.wrapClassName("CharacterArray", "Kernel", null, smalltalk.SequenceableCollection, false);
 smalltalk.wrapClassName("String", "Kernel", String, smalltalk.CharacterArray);
 smalltalk.wrapClassName("String", "Kernel", String, smalltalk.CharacterArray);
-smalltalk.wrapClassName("Symbol", "Kernel", SmalltalkSymbol, smalltalk.CharacterArray);
+smalltalk.wrapClassName("Symbol", "Kernel", SmalltalkSymbol, smalltalk.CharacterArray, false);
 smalltalk.wrapClassName("Array", "Kernel", Array, smalltalk.SequenceableCollection);
 smalltalk.wrapClassName("Array", "Kernel", Array, smalltalk.SequenceableCollection);
 smalltalk.wrapClassName("RegularExpression", "Kernel", RegExp, smalltalk.String);
 smalltalk.wrapClassName("RegularExpression", "Kernel", RegExp, smalltalk.String);
 
 
 smalltalk.wrapClassName("Error", "Kernel", Error, smalltalk.Object);
 smalltalk.wrapClassName("Error", "Kernel", Error, smalltalk.Object);
-smalltalk.wrapClassName("MethodContext", "Kernel", SmalltalkMethodContext, smalltalk.Object);
+smalltalk.wrapClassName("MethodContext", "Kernel", SmalltalkMethodContext, smalltalk.Object, false);
 
 
 /* Alias definitions */
 /* Alias definitions */
 
 

+ 1 - 3
js/init.js

@@ -1,6 +1,4 @@
-smalltalk.init(smalltalk.Object); //metaclasses are in through Class
-smalltalk.classes()._do_(function(each) {
-	each._initialize()});
+smalltalk.initialize();
 
 
 /* Similar to jQuery(document).ready() */
 /* Similar to jQuery(document).ready() */
 
 

+ 9 - 1
st/Compiler-AST.st

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

+ 51 - 13
st/Compiler-IR.st

@@ -154,6 +154,7 @@ visitMethodNode: aNode
 		arguments: aNode arguments;
 		arguments: aNode arguments;
 		selector: aNode selector;
 		selector: aNode selector;
 		messageSends: aNode messageSends;
 		messageSends: aNode messageSends;
+        superSends: aNode superSends;
 		classReferences: aNode classReferences;
 		classReferences: aNode classReferences;
 		scope: aNode scope;
 		scope: aNode scope;
 		yourself).
 		yourself).
@@ -408,7 +409,7 @@ accept: aVisitor
 ! !
 ! !
 
 
 IRScopedInstruction subclass: #IRMethod
 IRScopedInstruction subclass: #IRMethod
-	instanceVariableNames: 'source selector classReferences messageSends arguments internalVariables'
+	instanceVariableNames: 'source selector classReferences messageSends superSends arguments internalVariables'
 	package: 'Compiler-IR'!
 	package: 'Compiler-IR'!
 !IRMethod commentStamp!
 !IRMethod commentStamp!
 I am a method instruction!
 I am a method instruction!
@@ -462,6 +463,14 @@ source
 
 
 source: aString
 source: aString
 	source := aString
 	source := aString
+!
+
+superSends
+	^ superSends
+!
+
+superSends: aCollection
+	superSends := aCollection
 ! !
 ! !
 
 
 !IRMethod methodsFor: 'visiting'!
 !IRMethod methodsFor: 'visiting'!
@@ -567,6 +576,12 @@ index: anInteger
 	index := anInteger
 	index := anInteger
 !
 !
 
 
+javascriptSelector
+	^ self classSend 
+    	ifNil: [ self selector asSelector ]
+      	ifNotNil: [ self selector asSuperSelector ]
+!
+
 selector
 selector
 	^ selector
 	^ selector
 !
 !
@@ -878,6 +893,29 @@ visitIRReturn: anIRReturn
 !
 !
 
 
 visitIRSend: anIRSend
 visitIRSend: anIRSend
+	anIRSend classSend 
+    	ifNil: [
+			self stream nextPutAll: '_st('.
+			self visit: anIRSend instructions first.
+   		 	self stream nextPutAll: ').', anIRSend selector asSelector, '('.
+			anIRSend instructions allButFirst
+				do: [ :each | self visit: each ]
+				separatedBy: [ self stream nextPutAll: ',' ].
+			self stream nextPutAll: ')' ]
+		ifNotNil: [ 
+			self stream 
+            	nextPutAll: anIRSend classSend asJavascript, '.fn.prototype.';
+				nextPutAll: anIRSend selector asSelector, '.apply(';
+				nextPutAll: '_st('.
+			self visit: anIRSend instructions first.
+			self stream nextPutAll: '), ['.
+			anIRSend instructions allButFirst
+				do: [ :each | self visit: each ]
+				separatedBy: [ self stream nextPutAll: ',' ].
+			self stream nextPutAll: '])' ]
+!
+
+visitIRSendOld: anIRSend
 	self stream nextPutAll: 'smalltalk.send('.
 	self stream nextPutAll: 'smalltalk.send('.
 	self visit: anIRSend instructions first.
 	self visit: anIRSend instructions first.
 	self stream nextPutAll:  ',"', anIRSend selector asSelector, '",['.
 	self stream nextPutAll:  ',"', anIRSend selector asSelector, '",['.
@@ -967,6 +1005,16 @@ nextPutClosureWith: aBlock arguments: anArray
 	stream nextPutAll: '})'
 	stream nextPutAll: '})'
 !
 !
 
 
+nextPutContextFor: aMethod during: aBlock
+	self nextPutAll: 'return smalltalk.withContext(function() {'.
+    aBlock value.
+    self 
+    	nextPutAll: '}, self, ';
+        nextPutAll: aMethod selector asJavascript, ', ';
+        nextPutAll: aMethod arguments asJavascript;
+        nextPutAll: ')'
+!
+
 nextPutFunctionWith: aBlock arguments: anArray
 nextPutFunctionWith: aBlock arguments: anArray
 	stream nextPutAll: 'fn: function('.
 	stream nextPutAll: 'fn: function('.
 	anArray 
 	anArray 
@@ -1000,12 +1048,12 @@ nextPutMethodDeclaration: aMethod with: aBlock
 	stream 
 	stream 
 		nextPutAll: 'smalltalk.method({'; lf;
 		nextPutAll: 'smalltalk.method({'; lf;
 		nextPutAll: 'selector: "', aMethod selector, '",'; lf;
 		nextPutAll: 'selector: "', aMethod selector, '",'; lf;
-		nextPutAll: 'source: ', aMethod source asJavascript, ',';lf.
+		nextPutAll: 'source: ', aMethod source asJavascript, ',';lf. 
 	aBlock value.
 	aBlock value.
 	stream 
 	stream 
 		nextPutAll: ',', String lf, 'messageSends: ';
 		nextPutAll: ',', String lf, 'messageSends: ';
 		nextPutAll: aMethod messageSends asArray asJavascript, ','; lf;
 		nextPutAll: aMethod messageSends asArray asJavascript, ','; lf;
-          	nextPutAll: 'args: ', (aMethod arguments collect: [ :each | each value ]) asArray asJavascript, ','; lf;
+        nextPutAll: 'args: ', (aMethod arguments collect: [ :each | each value ]) asArray asJavascript, ','; lf;
 		nextPutAll: 'referencedClasses: ['.
 		nextPutAll: 'referencedClasses: ['.
 	aMethod classReferences 
 	aMethod classReferences 
 		do: [:each | stream nextPutAll: each asJavascript]
 		do: [:each | stream nextPutAll: each asJavascript]
@@ -1040,16 +1088,6 @@ nextPutReturnWith: aBlock
 	aBlock value
 	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
 nextPutSequenceWith: aBlock
 	"stream 
 	"stream 
 		nextPutAll: 'switch(smalltalk.thisContext.pc){'; lf."
 		nextPutAll: 'switch(smalltalk.thisContext.pc){'; lf."

+ 11 - 3
st/Compiler-Semantic.st

@@ -370,7 +370,7 @@ isUnknownVar
 ! !
 ! !
 
 
 NodeVisitor subclass: #SemanticAnalyzer
 NodeVisitor subclass: #SemanticAnalyzer
-	instanceVariableNames: 'currentScope theClass classReferences messageSends'
+	instanceVariableNames: 'currentScope theClass classReferences messageSends superSends'
 	package: 'Compiler-Semantic'!
 	package: 'Compiler-Semantic'!
 !SemanticAnalyzer commentStamp!
 !SemanticAnalyzer commentStamp!
 I semantically analyze the abstract syntax tree and annotate it with informations such as non local returns and variable scopes.!
 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 ]
 	^ messageSends ifNil: [ messageSends := Dictionary new ]
 !
 !
 
 
+superSends
+	^ superSends ifNil: [ superSends := Dictionary new ]
+!
+
 theClass
 theClass
 	^ theClass
 	^ theClass
 !
 !
@@ -501,7 +505,8 @@ visitMethodNode: aNode
 
 
 	aNode 
 	aNode 
 		classReferences: self classReferences;
 		classReferences: self classReferences;
-		messageSends: self messageSends keys.
+		messageSends: self messageSends keys;
+        superSends: self superSends keys.
 	self popScope
 	self popScope
 !
 !
 
 
@@ -518,7 +523,10 @@ visitSendNode: aNode
 	aNode receiver value = 'super' 
 	aNode receiver value = 'super' 
 		ifTrue: [
 		ifTrue: [
 			aNode superSend: true.
 			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: [
 		ifFalse: [ (IRSendInliner inlinedSelectors includes: aNode selector) ifTrue: [
 			aNode shouldBeInlined: true.
 			aNode shouldBeInlined: true.
 			aNode receiver isValueNode ifFalse: [ aNode receiver shouldBeAliased: true ] ] ].
 			aNode receiver isValueNode ifFalse: [ aNode receiver shouldBeAliased: true ] ] ].

+ 2 - 2
st/Kernel-Classes.st

@@ -69,12 +69,12 @@ instanceVariableNames
 !
 !
 
 
 methodAt: aSymbol
 methodAt: aSymbol
-	<return smalltalk.methods(self)[aSymbol._asString()]>
+	^ self methodDictionary at: aSymbol asString
 !
 !
 
 
 methodDictionary
 methodDictionary
 	<var dict = smalltalk.HashedCollection._new();
 	<var dict = smalltalk.HashedCollection._new();
-	var methods = self.fn.prototype.methods;
+	var methods = self.methods;
 	for(var i in methods) {
 	for(var i in methods) {
 		if(methods[i].selector) {
 		if(methods[i].selector) {
 			dict._at_put_(methods[i].selector, methods[i]);
 			dict._at_put_(methods[i].selector, methods[i]);

+ 5 - 15
st/Kernel-Collections.st

@@ -1039,21 +1039,7 @@ asNumber
 !
 !
 
 
 asSelector
 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(self)>
 !
 !
 
 
 asString
 asString
@@ -1343,6 +1329,10 @@ asString
 	<return self.value>
 	<return self.value>
 !
 !
 
 
+asSuperSelector
+	^self asString asSuperSelector
+!
+
 asSymbol
 asSymbol
 	^self
 	^self
 ! !
 ! !