1
0
ソースを参照

Merge branch 'message_send' into ast-interpreter

Nicolas Petton 12 年 前
コミット
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(
 "_accept_",
 smalltalk.method({
@@ -605,6 +605,28 @@ return self}
 }),
 smalltalk.MethodNode);
 
+smalltalk.addMethod(
+"_superSends",
+smalltalk.method({
+selector: "superSends",
+fn: function (){
+var self=this;
+return self["@superSends"];
+}
+}),
+smalltalk.MethodNode);
+
+smalltalk.addMethod(
+"_superSends_",
+smalltalk.method({
+selector: "superSends:",
+fn: function (aCollection){
+var self=this;
+self["@superSends"]=aCollection;
+return self}
+}),
+smalltalk.MethodNode);
+
 
 
 smalltalk.addClass('ReturnNode', smalltalk.Node, ['scope'], 'Compiler-AST');

+ 33 - 1
js/Compiler-AST.js

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

+ 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,"_selector_",[smalltalk.send(aNode,"_selector",[])]);
 smalltalk.send($1,"_messageSends_",[smalltalk.send(aNode,"_messageSends",[])]);
+smalltalk.send($1,"_superSends_",[smalltalk.send(aNode,"_superSends",[])]);
 smalltalk.send($1,"_classReferences_",[smalltalk.send(aNode,"_classReferences",[])]);
 smalltalk.send($1,"_scope_",[smalltalk.send(aNode,"_scope",[])]);
 $2=smalltalk.send($1,"_yourself",[]);
@@ -845,7 +846,7 @@ smalltalk.IRClosure);
 
 
 
-smalltalk.addClass('IRMethod', smalltalk.IRScopedInstruction, ['source', 'selector', 'classReferences', 'messageSends', 'arguments', 'internalVariables'], 'Compiler-IR');
+smalltalk.addClass('IRMethod', smalltalk.IRScopedInstruction, ['source', 'selector', 'classReferences', 'messageSends', 'superSends', 'arguments', 'internalVariables'], 'Compiler-IR');
 smalltalk.addMethod(
 "_accept_",
 smalltalk.method({
@@ -999,6 +1000,28 @@ return self}
 }),
 smalltalk.IRMethod);
 
+smalltalk.addMethod(
+"_superSends",
+smalltalk.method({
+selector: "superSends",
+fn: function (){
+var self=this;
+return self["@superSends"];
+}
+}),
+smalltalk.IRMethod);
+
+smalltalk.addMethod(
+"_superSends_",
+smalltalk.method({
+selector: "superSends:",
+fn: function (aCollection){
+var self=this;
+self["@superSends"]=aCollection;
+return self}
+}),
+smalltalk.IRMethod);
+
 
 
 smalltalk.addClass('IRReturn', smalltalk.IRScopedInstruction, [], 'Compiler-IR');
@@ -1197,6 +1220,24 @@ return true;
 }),
 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(
 "_selector",
 smalltalk.method({
@@ -1871,6 +1912,43 @@ smalltalk.method({
 selector: "visitIRSend:",
 fn: function (anIRSend){
 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;
 smalltalk.send(smalltalk.send(self,"_stream",[]),"_nextPutAll_",["smalltalk.send("]);
 smalltalk.send(self,"_visit_",[smalltalk.send(smalltalk.send(anIRSend,"_instructions",[]),"_first",[])]);
@@ -2052,6 +2130,23 @@ return self}
 }),
 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(
 "_nextPutFunctionWith_arguments_",
 smalltalk.method({
@@ -2119,28 +2214,28 @@ selector: "nextPutMethodDeclaration:with:",
 fn: function (aMethod,aBlock){
 var self=this;
 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(){
-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}
 }),
 smalltalk.JSStream);
@@ -2201,25 +2296,6 @@ return self}
 }),
 smalltalk.JSStream);
 
-smalltalk.addMethod(
-"_nextPutSendTo_selector_arguments_",
-smalltalk.method({
-selector: "nextPutSendTo:selector:arguments:",
-fn: function (receiver,selector,arguments){
-var self=this;
-smalltalk.send(self["@stream"],"_nextPutAll_",["smalltalk.send("]);
-smalltalk.send(receiver,"_emitOn_",[self]);
-smalltalk.send(self["@stream"],"_nextPutAll_",[smalltalk.send(smalltalk.send(",\x22","__comma",[smalltalk.send(selector,"_asSelector",[])]),"__comma",["\x22,["])]);
-smalltalk.send(arguments,"_do_separatedBy_",[(function(each){
-return smalltalk.send(each,"_emitOn_",[self]);
-}),(function(){
-return smalltalk.send(self["@stream"],"_nextPutAll_",[","]);
-})]);
-smalltalk.send(self["@stream"],"_nextPutAll_",["])"]);
-return self}
-}),
-smalltalk.JSStream);
-
 smalltalk.addMethod(
 "_nextPutSequenceWith_",
 smalltalk.method({

+ 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,"_selector_",[smalltalk.send(aNode,"_selector",[])]);
 smalltalk.send($1,"_messageSends_",[smalltalk.send(aNode,"_messageSends",[])]);
+smalltalk.send($1,"_superSends_",[smalltalk.send(aNode,"_superSends",[])]);
 smalltalk.send($1,"_classReferences_",[smalltalk.send(aNode,"_classReferences",[])]);
 smalltalk.send($1,"_scope_",[smalltalk.send(aNode,"_scope",[])]);
 $2=smalltalk.send($1,"_yourself",[]);
@@ -409,8 +410,8 @@ $8=smalltalk.send(self,"_method",[]);
 return $8;
 },
 args: ["aNode"],
-source: "visitMethodNode: aNode\x0a\x0a\x09self method: (IRMethod new\x0a\x09\x09source: self source;\x0a\x09\x09arguments: aNode arguments;\x0a\x09\x09selector: aNode selector;\x0a\x09\x09messageSends: aNode messageSends;\x0a\x09\x09classReferences: aNode classReferences;\x0a\x09\x09scope: aNode scope;\x0a\x09\x09yourself).\x0a\x0a\x09aNode scope temps do: [ :each |\x0a\x09\x09self method add: (IRTempDeclaration new\x0a\x09\x09\x09name: each name;\x0a\x09\x09\x09yourself) ].\x0a\x0a\x09aNode nodes do: [ :each | self method add: (self visit: each) ].\x0a\x0a\x09aNode scope hasLocalReturn ifFalse: [\x0a\x09\x09(self method add: IRReturn new) add: (IRVariable new\x0a\x09\x09\x09variable: (aNode scope pseudoVars at: 'self');\x0a\x09\x09\x09yourself) ].\x0a\x0a\x09^ self method",
-messageSends: ["method:", "source:", "source", "new", "arguments:", "arguments", "selector:", "selector", "messageSends:", "messageSends", "classReferences:", "classReferences", "scope:", "scope", "yourself", "do:", "add:", "name:", "name", "method", "temps", "visit:", "nodes", "ifFalse:", "variable:", "at:", "pseudoVars", "hasLocalReturn"],
+source: "visitMethodNode: aNode\x0a\x0a\x09self method: (IRMethod new\x0a\x09\x09source: self source;\x0a\x09\x09arguments: aNode arguments;\x0a\x09\x09selector: aNode selector;\x0a\x09\x09messageSends: aNode messageSends;\x0a        superSends: aNode superSends;\x0a\x09\x09classReferences: aNode classReferences;\x0a\x09\x09scope: aNode scope;\x0a\x09\x09yourself).\x0a\x0a\x09aNode scope temps do: [ :each |\x0a\x09\x09self method add: (IRTempDeclaration new\x0a\x09\x09\x09name: each name;\x0a\x09\x09\x09yourself) ].\x0a\x0a\x09aNode nodes do: [ :each | self method add: (self visit: each) ].\x0a\x0a\x09aNode scope hasLocalReturn ifFalse: [\x0a\x09\x09(self method add: IRReturn new) add: (IRVariable new\x0a\x09\x09\x09variable: (aNode scope pseudoVars at: 'self');\x0a\x09\x09\x09yourself) ].\x0a\x0a\x09^ self method",
+messageSends: ["method:", "source:", "source", "new", "arguments:", "arguments", "selector:", "selector", "messageSends:", "messageSends", "superSends:", "superSends", "classReferences:", "classReferences", "scope:", "scope", "yourself", "do:", "add:", "name:", "name", "method", "temps", "visit:", "nodes", "ifFalse:", "variable:", "at:", "pseudoVars", "hasLocalReturn"],
 referencedClasses: ["IRMethod", "IRTempDeclaration", "IRVariable", "IRReturn"]
 }),
 smalltalk.IRASTTranslator);
@@ -1117,7 +1118,7 @@ smalltalk.IRClosure);
 
 
 
-smalltalk.addClass('IRMethod', smalltalk.IRScopedInstruction, ['source', 'selector', 'classReferences', 'messageSends', 'arguments', 'internalVariables'], 'Compiler-IR');
+smalltalk.addClass('IRMethod', smalltalk.IRScopedInstruction, ['source', 'selector', 'classReferences', 'messageSends', 'superSends', 'arguments', 'internalVariables'], 'Compiler-IR');
 smalltalk.IRMethod.comment="I am a method instruction"
 smalltalk.addMethod(
 "_accept_",
@@ -1337,6 +1338,38 @@ referencedClasses: []
 }),
 smalltalk.IRMethod);
 
+smalltalk.addMethod(
+"_superSends",
+smalltalk.method({
+selector: "superSends",
+category: 'accessing',
+fn: function (){
+var self=this;
+return self["@superSends"];
+},
+args: [],
+source: "superSends\x0a\x09^ superSends",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.IRMethod);
+
+smalltalk.addMethod(
+"_superSends_",
+smalltalk.method({
+selector: "superSends:",
+category: 'accessing',
+fn: function (aCollection){
+var self=this;
+self["@superSends"]=aCollection;
+return self},
+args: ["aCollection"],
+source: "superSends: aCollection\x0a\x09superSends := aCollection",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.IRMethod);
+
 
 
 smalltalk.addClass('IRReturn', smalltalk.IRScopedInstruction, [], 'Compiler-IR');
@@ -1619,6 +1652,29 @@ referencedClasses: []
 }),
 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(
 "_selector",
 smalltalk.method({
@@ -2547,6 +2603,48 @@ selector: "visitIRSend:",
 category: 'visiting',
 fn: function (anIRSend){
 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;
 smalltalk.send(smalltalk.send(self,"_stream",[]),"_nextPutAll_",["smalltalk.send("]);
 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_",[")"]);
 return self},
 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"],
 referencedClasses: []
 }),
@@ -2792,6 +2890,28 @@ referencedClasses: []
 }),
 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(
 "_nextPutFunctionWith_arguments_",
 smalltalk.method({
@@ -2875,31 +2995,31 @@ category: 'streaming',
 fn: function (aMethod,aBlock){
 var self=this;
 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(){
-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},
 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"],
 referencedClasses: ["String"]
 }),
@@ -2981,30 +3101,6 @@ referencedClasses: []
 }),
 smalltalk.JSStream);
 
-smalltalk.addMethod(
-"_nextPutSendTo_selector_arguments_",
-smalltalk.method({
-selector: "nextPutSendTo:selector:arguments:",
-category: 'streaming',
-fn: function (receiver,selector,arguments){
-var self=this;
-smalltalk.send(self["@stream"],"_nextPutAll_",["smalltalk.send("]);
-smalltalk.send(receiver,"_emitOn_",[self]);
-smalltalk.send(self["@stream"],"_nextPutAll_",[smalltalk.send(smalltalk.send(",\x22","__comma",[smalltalk.send(selector,"_asSelector",[])]),"__comma",["\x22,["])]);
-smalltalk.send(arguments,"_do_separatedBy_",[(function(each){
-return smalltalk.send(each,"_emitOn_",[self]);
-}),(function(){
-return smalltalk.send(self["@stream"],"_nextPutAll_",[","]);
-})]);
-smalltalk.send(self["@stream"],"_nextPutAll_",["])"]);
-return self},
-args: ["receiver", "selector", "arguments"],
-source: "nextPutSendTo: receiver selector: selector arguments: arguments\x0a\x09stream nextPutAll: 'smalltalk.send('.\x0a\x09receiver emitOn: self. \x0a\x09stream nextPutAll: ',\x22', selector asSelector, '\x22,['.\x0a\x09arguments \x0a\x09\x09do: [ :each | each emitOn: self ]\x0a\x09\x09separatedBy: [ stream nextPutAll: ',' ].\x0a\x09stream nextPutAll: '])'",
-messageSends: ["nextPutAll:", "emitOn:", ",", "asSelector", "do:separatedBy:"],
-referencedClasses: []
-}),
-smalltalk.JSStream);
-
 smalltalk.addMethod(
 "_nextPutSequenceWith_",
 smalltalk.method({

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

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

+ 76 - 43
js/Compiler-Semantic.js

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

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

@@ -232,9 +232,10 @@ smalltalk.method({
 selector: "methodAt:",
 fn: function (aSymbol){
 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);
 
@@ -245,7 +246,7 @@ selector: "methodDictionary",
 fn: function (){
 var self=this;
 var dict = smalltalk.HashedCollection._new();
-	var methods = self.fn.prototype.methods;
+	var methods = self.methods;
 	for(var i in methods) {
 		if(methods[i].selector) {
 			dict._at_put_(methods[i].selector, methods[i]);

+ 8 - 7
js/Kernel-Classes.js

@@ -309,12 +309,13 @@ selector: "methodAt:",
 category: 'accessing',
 fn: function (aSymbol){
 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"],
-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: []
 }),
 smalltalk.Behavior);
@@ -327,7 +328,7 @@ category: 'accessing',
 fn: function (){
 var self=this;
 var dict = smalltalk.HashedCollection._new();
-	var methods = self.fn.prototype.methods;
+	var methods = self.methods;
 	for(var i in methods) {
 		if(methods[i].selector) {
 			dict._at_put_(methods[i].selector, methods[i]);
@@ -337,7 +338,7 @@ var dict = smalltalk.HashedCollection._new();
 ;
 return self},
 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: [],
 referencedClasses: []
 }),

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

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

+ 23 - 16
js/Kernel-Collections.js

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

+ 388 - 203
js/boot.js

@@ -13,29 +13,29 @@
    | Amber is released under the MIT license
    |
    | 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 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.
    |
-   | 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 */
 
-if (typeof console === "undefined") {
+if(typeof console === "undefined") {
 	this.console = {
 		log: 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() {
     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;
 
 	/* 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 */
 
 	st.thisContext = undefined;
@@ -97,26 +111,61 @@ function Smalltalk(){
 	/* List of all reserved words in JavaScript. They may not be used as variables
 	   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',
 		'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 */
 
-	symbolTable = {};
+	var symbolTable = {};
 	st.symbolFor = function(string) {
 		if(symbolTable[string] === undefined) {
 			symbolTable[string] = new SmalltalkSymbol(string);
-		};
+		}
 
 		return symbolTable[string];
 	};
 
 	/* Unique ID number generator */
 
-	oid = 0;
+	var oid = 0;
 	st.nextId = function() {
 		oid += 1;
 		return oid;
@@ -134,18 +183,22 @@ function Smalltalk(){
         that.organization = new SmalltalkOrganizer();
 		that.properties = spec.properties || {};
 		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) 
 	   should be added to the smalltalk object, see smalltalk.addClass().
 	   Superclass linking is *not* handled here, see smalltalk.init()  */
 
 	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';
 		if(spec.superclass) {
 			that.superclass = spec.superclass;
@@ -153,29 +206,36 @@ function Smalltalk(){
 		}
 		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,
 	   use smalltalk.addMethod() */
@@ -193,9 +253,9 @@ function Smalltalk(){
 		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. */
-	   
+
 	st.init = function(klass) {
 		st.initClass(klass);
 		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) {
-			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 */
+    // TODO: Remove this hack
 
 	st.packages.all = function() {
 		var 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]);
 		}
 		return packages
 	};
 
 	/* Answer all registered Smalltalk classes */
+    //TODO: remove the function and make smalltalk.classes an array
 
 	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;
 	};
 
-
-	/* 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. */
 
@@ -291,23 +382,32 @@ function Smalltalk(){
 		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. */
 
-	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);
 		st[className] = klass({
-			className:  className, 
+			className:  className,
 			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 */
+
 	st.alias = function(klass, alias) {
 		st[alias] = klass;
-	}
+	};
 
 	/* 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.
@@ -323,7 +423,7 @@ function Smalltalk(){
 		} else {
 			if(properties) {
 				st.packages[pkgName].properties = properties;
-			}	
+			}
 		}
 		return st.packages[pkgName];
 	};
@@ -333,58 +433,68 @@ function Smalltalk(){
 
 	st.addClass = function(className, superclass, iVarNames, pkgName) {
 		var pkg = st.addPackage(pkgName);
-		if(st[className]) {
+		if(st[className] && st[className].superclass === superclass) {
 			st[className].superclass = superclass;
 			st[className].iVarNames = iVarNames;
 			st[className].pkg = pkg || st[className].pkg;
 		} else {
+            if(st[className]) {
+                st.removeClass(st[className]);
+			}
 			st[className] = klass({
-				className: className, 
+				className: className,
 				superclass: superclass,
 				pkg: pkg,
 				iVarNames: iVarNames
 			});
 		}
 
-        pkg.organization.addElement(st[className]);
+        classes.addElement(st[className]);
+        pkg.organization.elements.addElement(st[className]);
 	};
 
     st.removeClass = function(klass) {
-        klass.pkg.organization.removeElement(klass);
+        klass.pkg.organization.elements.removeElement(klass);
+        classes.removeElement(klass);
         delete st[klass.className];
     };
 
 	/* Add/remove a method to/from a class */
 
 	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;
+		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) {
         var protocol = method.category;
         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;
-		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;
 				break;
             };
         };
         if(shouldDeleteProtocol) {
-            klass.organization.removeElement(protocol)
+            klass.organization.elements.removeElement(protocol)
         };
     };
 
@@ -400,6 +510,7 @@ function Smalltalk(){
 				st.thisContext = undefined;
 				if(error.smalltalkError) {
 					handleError(error);
+					return nil;
 				} else {
 					throw(error);
 				}
@@ -414,23 +525,46 @@ function Smalltalk(){
 		}
 		method = klass ? klass.fn.prototype[selector] : receiver.klass && receiver[selector];
 		if(method) {
-			var context = pushContext(receiver, selector, method, args);
+			var context = pushContext(receiver, selector, args);
 			call = method.apply(receiver, args);
 			popContext(context);
 			return call;
 		} else {
 			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 */
 
 	function handleError(error) {
-        if(!error.cc) {
-		    smalltalk.ErrorHandler._current()._handleError_(error);
-        }
-	};
+        st.ErrorHandler._current()._handleError_(error);
+	}
 
 	/* Handles #dnu: *and* JavaScript method calls.
 	   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);
 		}
 
-		/* Handles not understood messages. Also see the Amber counter-part 
+		/* Handles not understood messages. Also see the Amber counter-part
 		   Object>>doesNotUnderstand: */
 
 		return receiver._doesNotUnderstand_(
@@ -450,13 +584,13 @@ function Smalltalk(){
 				._selector_(st.convertSelector(selector))
 				._arguments_(args)
 				);
-	};
+	}
 
 	/* Call a method of a JS object, or answer a property if it exists.
 	   Else try wrapping a JSObjectProxy around the receiver.
 
        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).
 
 	   Converts keyword-based selectors by using the first
@@ -480,8 +614,7 @@ function Smalltalk(){
 		}
 
 		return st.send(st.JSObjectProxy._on_(receiver), selector, args);
-	};
-
+	}
 
 	/* Reuse one old context stored in oldContext */
 
@@ -491,31 +624,50 @@ function Smalltalk(){
 	/* Handle thisContext pseudo variable */
 
 	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;
-		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;
 		c.homeContext = tc;
         c.pc          = 1;
 		c.receiver    = receiver;
-        c.selector    = selector;
-		c.method      = method;
+        c.selector    = selector || "";
 		c.temps       = temps || {};
 		return st.thisContext = c;
-	};
+	}
 
 	function popContext(context) {
 		st.thisContext = context.homeContext;
 		context.homeContext = undefined;
 		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.
 	   if you modify the following functions, also change String>>asSelector
@@ -531,21 +683,25 @@ function Smalltalk(){
 
 	function convertKeywordSelector(selector) {
 		return selector.replace(/^_/, '').replace(/_/g, ':');
-	};
+	}
 
 	function convertBinarySelector(selector) {
 		return selector
 			.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 */
 	st.readJSObject = function(js) {
@@ -554,12 +710,12 @@ function Smalltalk(){
 		var readArray = (js.constructor === Array);
 
 		if(readObject) {
-			object = smalltalk.Dictionary._new();
+			object = st.Dictionary._new();
 		}
 		for(var i in js) {
 			if(readObject) {
 				object._at_put_(i, st.readJSObject(js[i]));
-			} 
+			}
 			if(readArray) {
 				object[i] = st.readJSObject(js[i]);
 			}
@@ -568,31 +724,49 @@ function Smalltalk(){
 	};
 
     /* Boolean assertion */
+
     st.assert = function(boolean) {
         if ((undefined !== boolean) && (boolean.klass === smalltalk.Boolean)) {
             return boolean;
         } 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.selector    = selector;
-	this.method      = method;
 	this.temps       = temps || {};
 	this.homeContext = home;
-};
+}
+
+inherits(SmalltalkMethodContext, SmalltalkObject);
 
 SmalltalkMethodContext.prototype.copy = function() {
 	var home = this.homeContext;
 	if(home) {home = home.copy()}
 	return new SmalltalkMethodContext(
-		this.receiver, 
+		this.receiver,
         this.selector,
-		this.method, 
-		this.temps, 
+		this.temps,
 		home
 	);
 };
@@ -612,39 +786,50 @@ if(this.jQuery) {
 	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.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("BlockClosure", "Kernel", Function, smalltalk.Object);
 smalltalk.wrapClassName("Boolean", "Kernel", Boolean, 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("Symbol", "Kernel", SmalltalkSymbol, smalltalk.CharacterArray);
+smalltalk.wrapClassName("Symbol", "Kernel", SmalltalkSymbol, smalltalk.CharacterArray, false);
 smalltalk.wrapClassName("Array", "Kernel", Array, smalltalk.SequenceableCollection);
 smalltalk.wrapClassName("RegularExpression", "Kernel", RegExp, smalltalk.String);
 
 smalltalk.wrapClassName("Error", "Kernel", Error, smalltalk.Object);
-smalltalk.wrapClassName("MethodContext", "Kernel", SmalltalkMethodContext, smalltalk.Object);
+smalltalk.wrapClassName("MethodContext", "Kernel", SmalltalkMethodContext, smalltalk.Object, false);
 
 /* 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() */
 

+ 9 - 1
st/Compiler-AST.st

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

+ 51 - 13
st/Compiler-IR.st

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

+ 11 - 3
st/Compiler-Semantic.st

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

+ 2 - 2
st/Kernel-Classes.st

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

+ 5 - 15
st/Kernel-Collections.st

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