Browse Source

- Many small fixed for grunt to compile amber.
- Recompiled all js files using grunt

Nicolas Petton 11 years ago
parent
commit
3ed8b38659

+ 16 - 1
js/Canvas.deploy.js

@@ -1736,12 +1736,27 @@ smalltalk.method({
 selector: "initialize",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
smalltalk.Object.klass.fn.prototype._initialize.apply(_st(self), []);
+return smalltalk.withContext(function($ctx1) { 
var $1;
+smalltalk.Object.klass.fn.prototype._initialize.apply(_st(self), []);
+$1=_st(self)._isDOMAvailable();
+if(smalltalk.assert($1)){
 _st(self)._ensureCurrent();
+};
 return self}, function($ctx1) {$ctx1.fill(self,"initialize",{}, smalltalk.HTMLSnippet.klass)})}
 }),
 smalltalk.HTMLSnippet.klass);
 
+smalltalk.addMethod(
+"_isDOMAvailable",
+smalltalk.method({
+selector: "isDOMAvailable",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
 return typeof document !== 'undefined' ;
+return self}, function($ctx1) {$ctx1.fill(self,"isDOMAvailable",{}, smalltalk.HTMLSnippet.klass)})}
+}),
+smalltalk.HTMLSnippet.klass);
+
 smalltalk.addMethod(
 "_new",
 smalltalk.method({

+ 25 - 5
js/Canvas.js

@@ -2186,7 +2186,7 @@ smalltalk.HTMLCanvas.klass);
 
 
 smalltalk.addClass('HTMLSnippet', smalltalk.Object, ['snippets'], 'Canvas');
-smalltalk.HTMLSnippet.comment="HTMLSnippet instance is the registry of html snippets.\x0aHTMLSnippet current is the public singleton instance.\x0a\x0aAt the beginning, it scans the document for any html elements\x0awith 'data-snippet=\x22foo\x22' attribute and takes them off the document,\x0aremembering them in the store under the specified name.\x0aIt also install method #foo into HTMLCanvas dynamically.\x0a\x0aEvery html snippet should mark a 'caret', a place where contents\x0acan be inserted, by 'data-snippet=\x22*\x22' (a special name for caret).\x0aFor example:\x0a\x0a<li data-snippet='menuelement' class='...'><a data-snippet='*'></a></li>\x0a\x0adefines a list element with a link inside; the link itself is marked as a caret.\x0a\x0aYou can later issue\x0a\x0ahtml menuelement href: '/foo'; with: 'A foo'\x0a\x0ato insert the whole snippet and directly manipulate the caret, so it renders:\x0a\x0a<li class='...'><a href='/foo'>A foo</a></li>\x0a\x0aFor a self-careting tags (not very useful, but you do not need to fill class etc.\x0ayou can use\x0a\x0a<div class='lots of classes' attr1='one' attr2='two' data-snippet='*bar'></div>\x0a\x0aand in code later do:\x0a\x0ahtml bar with: [ xxx ]\x0a\x0ato render\x0a\x0a<div class='lots of classes' attr1='one' attr2='two'>...added by xxx...</div>\x0a"
+smalltalk.HTMLSnippet.comment="HTMLSnippet instance is the registry of html snippets.\x0aHTMLSnippet current is the public singleton instance.\x0a\x0aAt the beginning, it scans the document for any html elements\x0awith 'data-snippet=\x22foo\x22' attribute and takes them off the document,\x0aremembering them in the store under the specified name.\x0aIt also install method #foo into HTMLCanvas dynamically.\x0a\x0aEvery html snippet should mark a 'caret', a place where contents\x0acan be inserted, by 'data-snippet=\x22*\x22' (a special name for caret).\x0aFor example:\x0a\x0a<li data-snippet='menuelement' class='...'><a data-snippet='*'></a></li>\x0a\x0adefines a list element with a link inside; the link itself is marked as a caret.\x0a\x0aYou can later issue\x0a\x0ahtml menuelement href: '/foo'; with: 'A foo'\x0a\x0ato insert the whole snippet and directly manipulate the caret, so it renders:\x0a\x0a<li class='...'><a href='/foo'>A foo</a></li>\x0a\x0aFor a self-careting tags (not very useful, but you do not need to fill class etc.\x0ayou can use\x0a\x0a<div class='lots of classes' attr1='one' attr2='two' data-snippet='*bar'></div>\x0a\x0aand in code later do:\x0a\x0ahtml bar with: [ xxx ]\x0a\x0ato render\x0a\x0a<div class='lots of classes' attr1='one' attr2='two'>...added by xxx...</div>"
 smalltalk.addMethod(
 "_initializeFromJQuery_",
 smalltalk.method({
@@ -2306,7 +2306,7 @@ $1=$2;
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"snippets",{}, smalltalk.HTMLSnippet)})},
 args: [],
-source: "snippets\x0a\x09^snippets ifNil: [ snippets := #{} ]\x0a",
+source: "snippets\x0a\x09^snippets ifNil: [ snippets := #{} ]",
 messageSends: ["ifNil:"],
 referencedClasses: []
 }),
@@ -2383,12 +2383,32 @@ selector: "initialize",
 category: 'initialization',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
smalltalk.Object.klass.fn.prototype._initialize.apply(_st(self), []);
+return smalltalk.withContext(function($ctx1) { 
var $1;
+smalltalk.Object.klass.fn.prototype._initialize.apply(_st(self), []);
+$1=_st(self)._isDOMAvailable();
+if(smalltalk.assert($1)){
 _st(self)._ensureCurrent();
+};
 return self}, function($ctx1) {$ctx1.fill(self,"initialize",{}, smalltalk.HTMLSnippet.klass)})},
 args: [],
-source: "initialize\x0a\x09super initialize.\x0a\x09self ensureCurrent",
-messageSends: ["initialize", "ensureCurrent"],
+source: "initialize\x0a\x09super initialize.\x0a    self isDOMAvailable ifTrue: [\x0a\x09\x09self ensureCurrent ]",
+messageSends: ["initialize", "ifTrue:", "ensureCurrent", "isDOMAvailable"],
+referencedClasses: []
+}),
+smalltalk.HTMLSnippet.klass);
+
+smalltalk.addMethod(
+"_isDOMAvailable",
+smalltalk.method({
+selector: "isDOMAvailable",
+category: 'instance creation',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
 return typeof document !== 'undefined' ;
+return self}, function($ctx1) {$ctx1.fill(self,"isDOMAvailable",{}, smalltalk.HTMLSnippet.klass)})},
+args: [],
+source: "isDOMAvailable\x0a\x09< return typeof document !== 'undefined' >",
+messageSends: [],
 referencedClasses: []
 }),
 smalltalk.HTMLSnippet.klass);

+ 9 - 11
js/Compiler-Core.deploy.js

@@ -537,20 +537,18 @@ smalltalk.method({
 selector: "classNameFor:",
 fn: function (aClass){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $2,$3,$5,$4,$1;
+return smalltalk.withContext(function($ctx1) { 
var $2,$3,$1;
 $2=_st(aClass)._isMetaclass();
-$3=(function(){
-return smalltalk.withContext(function($ctx2) {
return _st(_st(_st(aClass)._instanceClass())._name()).__comma(".klass");
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-$4=(function(){
-return smalltalk.withContext(function($ctx2) {
$5=_st(aClass)._isNil();
-if(smalltalk.assert($5)){
-return "nil";
+if(smalltalk.assert($2)){
+$1=_st(_st(_st(aClass)._instanceClass())._name()).__comma(".klass");
 } else {
-return _st(aClass)._name();
+$3=_st(aClass)._isNil();
+if(smalltalk.assert($3)){
+$1="nil";
+} else {
+$1=_st(aClass)._name();
+};
 };
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-$1=_st($2)._ifTrue_ifFalse_($3,$4);
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"classNameFor:",{aClass:aClass}, smalltalk.AbstractCodeGenerator)})}
 }),

+ 9 - 11
js/Compiler-Core.js

@@ -732,20 +732,18 @@ selector: "classNameFor:",
 category: 'accessing',
 fn: function (aClass){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $2,$3,$5,$4,$1;
+return smalltalk.withContext(function($ctx1) { 
var $2,$3,$1;
 $2=_st(aClass)._isMetaclass();
-$3=(function(){
-return smalltalk.withContext(function($ctx2) {
return _st(_st(_st(aClass)._instanceClass())._name()).__comma(".klass");
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-$4=(function(){
-return smalltalk.withContext(function($ctx2) {
$5=_st(aClass)._isNil();
-if(smalltalk.assert($5)){
-return "nil";
+if(smalltalk.assert($2)){
+$1=_st(_st(_st(aClass)._instanceClass())._name()).__comma(".klass");
 } else {
-return _st(aClass)._name();
+$3=_st(aClass)._isNil();
+if(smalltalk.assert($3)){
+$1="nil";
+} else {
+$1=_st(aClass)._name();
+};
 };
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-$1=_st($2)._ifTrue_ifFalse_($3,$4);
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"classNameFor:",{aClass:aClass}, smalltalk.AbstractCodeGenerator)})},
 args: ["aClass"],

+ 14 - 4
js/Compiler-Exceptions.deploy.js

@@ -132,16 +132,26 @@ smalltalk.UnknownVariableError);
 
 
 smalltalk.addClass('RethrowErrorHandler', smalltalk.ErrorHandler, [], 'Compiler-Exceptions');
+smalltalk.addMethod(
+"_basicSignal_",
+smalltalk.method({
+selector: "basicSignal:",
+fn: function (anError){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
throw anError;
+return self}, function($ctx1) {$ctx1.fill(self,"basicSignal:",{anError:anError}, smalltalk.RethrowErrorHandler)})}
+}),
+smalltalk.RethrowErrorHandler);
+
 smalltalk.addMethod(
 "_handleError_",
 smalltalk.method({
 selector: "handleError:",
 fn: function (anError){
 var self=this;
-smalltalk.send(self,"_handleError_",[anError],smalltalk.ErrorHandler);
-throw anError;
-;
-return self}
+return smalltalk.withContext(function($ctx1) { 
smalltalk.ErrorHandler.fn.prototype._handleError_.apply(_st(self), [anError]);
+_st(self)._basicSignal_(anError);
+return self}, function($ctx1) {$ctx1.fill(self,"handleError:",{anError:anError}, smalltalk.RethrowErrorHandler)})}
 }),
 smalltalk.RethrowErrorHandler);
 

+ 21 - 6
js/Compiler-Exceptions.js

@@ -185,6 +185,22 @@ smalltalk.UnknownVariableError);
 
 smalltalk.addClass('RethrowErrorHandler', smalltalk.ErrorHandler, [], 'Compiler-Exceptions');
 smalltalk.RethrowErrorHandler.comment="This class is used in the commandline version of the compiler.\x0aIt uses the handleError: message of ErrorHandler for printing the stacktrace and throws the error again as JS exception.\x0aAs a result Smalltalk errors are not swallowd by the Amber runtime and compilation can be aborted."
+smalltalk.addMethod(
+"_basicSignal_",
+smalltalk.method({
+selector: "basicSignal:",
+category: 'error handling',
+fn: function (anError){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
throw anError;
+return self}, function($ctx1) {$ctx1.fill(self,"basicSignal:",{anError:anError}, smalltalk.RethrowErrorHandler)})},
+args: ["anError"],
+source: "basicSignal: anError\x0a\x09<throw anError>",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.RethrowErrorHandler);
+
 smalltalk.addMethod(
 "_handleError_",
 smalltalk.method({
@@ -192,13 +208,12 @@ selector: "handleError:",
 category: 'error handling',
 fn: function (anError){
 var self=this;
-smalltalk.send(self,"_handleError_",[anError],smalltalk.ErrorHandler);
-throw anError;
-;
-return self},
+return smalltalk.withContext(function($ctx1) { 
smalltalk.ErrorHandler.fn.prototype._handleError_.apply(_st(self), [anError]);
+_st(self)._basicSignal_(anError);
+return self}, function($ctx1) {$ctx1.fill(self,"handleError:",{anError:anError}, smalltalk.RethrowErrorHandler)})},
 args: ["anError"],
-source: "handleError: anError\x0a\x09super handleError: anError.\x0a    <throw anError>",
-messageSends: ["handleError:"],
+source: "handleError: anError\x0a\x09super handleError: anError.\x0a    self basicSignal: anError",
+messageSends: ["handleError:", "basicSignal:"],
 referencedClasses: []
 }),
 smalltalk.RethrowErrorHandler);

+ 44 - 66
js/Compiler-IR.deploy.js

@@ -36,32 +36,28 @@ selector: "aliasTemporally:",
 fn: function (aCollection){
 var self=this;
 var threshold,result;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$2,$4,$6,$8,$7,$5,$9;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$4,$3,$5;
 threshold=(0);
-$1=aCollection;
-$2=(function(each,i){
-return smalltalk.withContext(function($ctx2) {
$3=_st(each)._subtreeNeedsAliasing();
-if(smalltalk.assert($3)){
+_st(aCollection)._withIndexDo_((function(each,i){
+return smalltalk.withContext(function($ctx2) {
$1=_st(each)._subtreeNeedsAliasing();
+if(smalltalk.assert($1)){
 threshold=i;
 return threshold;
 };
-}, function($ctx2) {$ctx2.fillBlock({each:each,i:i},$ctx1)})});
-_st($1)._withIndexDo_($2);
+}, function($ctx2) {$ctx2.fillBlock({each:each,i:i},$ctx1)})}));
 result=_st((smalltalk.OrderedCollection || OrderedCollection))._new();
-$4=aCollection;
-$5=(function(each,i){
-return smalltalk.withContext(function($ctx2) {
$6=result;
-$8=_st(i).__lt_eq(threshold);
-if(smalltalk.assert($8)){
-$7=_st(self)._alias_(each);
+_st(aCollection)._withIndexDo_((function(each,i){
+return smalltalk.withContext(function($ctx2) {
$2=result;
+$4=_st(i).__lt_eq(threshold);
+if(smalltalk.assert($4)){
+$3=_st(self)._alias_(each);
 } else {
-$7=_st(self)._visit_(each);
+$3=_st(self)._visit_(each);
 };
-return _st($6)._add_($7);
-}, function($ctx2) {$ctx2.fillBlock({each:each,i:i},$ctx1)})});
-_st($4)._withIndexDo_($5);
-$9=result;
-return $9;
+return _st($2)._add_($3);
+}, function($ctx2) {$ctx2.fillBlock({each:each,i:i},$ctx1)})}));
+$5=result;
+return $5;
 }, function($ctx1) {$ctx1.fill(self,"aliasTemporally:",{aCollection:aCollection,threshold:threshold,result:result}, smalltalk.IRASTTranslator)})}
 }),
 smalltalk.IRASTTranslator);
@@ -239,28 +235,23 @@ smalltalk.method({
 selector: "visitBlockSequenceNode:",
 fn: function (aNode){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $2,$3,$5,$7,$8,$9,$6,$4,$1;
-$2=self;
-$3=_st((smalltalk.IRBlockSequence || IRBlockSequence))._new();
-$4=(function(){
-return smalltalk.withContext(function($ctx2) {
$5=_st(aNode)._nodes();
-$6=(function(){
+return smalltalk.withContext(function($ctx1) { 
var $2,$3,$4,$1;
+$1=_st(self)._withSequence_do_(_st((smalltalk.IRBlockSequence || IRBlockSequence))._new(),(function(){
+return smalltalk.withContext(function($ctx2) {
return _st(_st(aNode)._nodes())._ifNotEmpty_((function(){
 return smalltalk.withContext(function($ctx3) {
_st(_st(_st(aNode)._nodes())._allButLast())._do_((function(each){
 return smalltalk.withContext(function($ctx4) {
return _st(_st(self)._sequence())._add_(_st(self)._visit_(each));
 }, function($ctx4) {$ctx4.fillBlock({each:each},$ctx1)})}));
-$7=_st(_st(_st(aNode)._nodes())._last())._isReturnNode();
-if(smalltalk.assert($7)){
+$2=_st(_st(_st(aNode)._nodes())._last())._isReturnNode();
+if(smalltalk.assert($2)){
 return _st(_st(self)._sequence())._add_(_st(self)._visit_(_st(_st(aNode)._nodes())._last()));
 } else {
-$8=_st((smalltalk.IRBlockReturn || IRBlockReturn))._new();
-_st($8)._add_(_st(self)._visit_(_st(_st(aNode)._nodes())._last()));
-$9=_st($8)._yourself();
-return _st(_st(self)._sequence())._add_($9);
+$3=_st((smalltalk.IRBlockReturn || IRBlockReturn))._new();
+_st($3)._add_(_st(self)._visit_(_st(_st(aNode)._nodes())._last()));
+$4=_st($3)._yourself();
+return _st(_st(self)._sequence())._add_($4);
 };
-}, function($ctx3) {$ctx3.fillBlock({},$ctx1)})});
-return _st($5)._ifNotEmpty_($6);
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-$1=_st($2)._withSequence_do_($3,$4);
+}, function($ctx3) {$ctx3.fillBlock({},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"visitBlockSequenceNode:",{aNode:aNode}, smalltalk.IRASTTranslator)})}
 }),
@@ -443,23 +434,18 @@ smalltalk.method({
 selector: "visitSequenceNode:",
 fn: function (aNode){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $2,$3,$5,$7,$6,$4,$1;
-$2=self;
-$3=_st((smalltalk.IRSequence || IRSequence))._new();
-$4=(function(){
-return smalltalk.withContext(function($ctx2) {
$5=_st(aNode)._nodes();
-$6=(function(each){
+return smalltalk.withContext(function($ctx1) { 
var $2,$1;
+$1=_st(self)._withSequence_do_(_st((smalltalk.IRSequence || IRSequence))._new(),(function(){
+return smalltalk.withContext(function($ctx2) {
return _st(_st(aNode)._nodes())._do_((function(each){
 var instruction;
 return smalltalk.withContext(function($ctx3) {
instruction=_st(self)._visit_(each);
 instruction;
-$7=_st(instruction)._isVariable();
-if(! smalltalk.assert($7)){
+$2=_st(instruction)._isVariable();
+if(! smalltalk.assert($2)){
 return _st(_st(self)._sequence())._add_(instruction);
 };
-}, function($ctx3) {$ctx3.fillBlock({each:each,instruction:instruction},$ctx1)})});
-return _st($5)._do_($6);
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-$1=_st($2)._withSequence_do_($3,$4);
+}, function($ctx3) {$ctx3.fillBlock({each:each,instruction:instruction},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"visitSequenceNode:",{aNode:aNode}, smalltalk.IRASTTranslator)})}
 }),
@@ -2025,38 +2011,30 @@ smalltalk.method({
 selector: "visitIRMethod:",
 fn: function (anIRMethod){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2,$4,$6,$7,$9,$10,$8,$5,$3;
-$1=_st(self)._stream();
-$2=anIRMethod;
-$3=(function(){
-return smalltalk.withContext(function($ctx2) {
$4=_st(self)._stream();
-$5=(function(){
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
+_st(_st(self)._stream())._nextPutMethodDeclaration_with_(anIRMethod,(function(){
+return smalltalk.withContext(function($ctx2) {
return _st(_st(self)._stream())._nextPutFunctionWith_arguments_((function(){
 return smalltalk.withContext(function($ctx3) {
_st(_st(self)._stream())._nextPutVars_(_st(_st(anIRMethod)._tempDeclarations())._collect_((function(each){
 return smalltalk.withContext(function($ctx4) {
return _st(_st(each)._name())._asVariableName();
 }, function($ctx4) {$ctx4.fillBlock({each:each},$ctx1)})})));
-$6=_st(self)._stream();
-$7=anIRMethod;
-$8=(function(){
-return smalltalk.withContext(function($ctx4) {
$9=_st(_st(anIRMethod)._internalVariables())._notEmpty();
-if(smalltalk.assert($9)){
+return _st(_st(self)._stream())._nextPutContextFor_during_(anIRMethod,(function(){
+return smalltalk.withContext(function($ctx4) {
$1=_st(_st(anIRMethod)._internalVariables())._notEmpty();
+if(smalltalk.assert($1)){
 _st(_st(self)._stream())._nextPutVars_(_st(_st(_st(anIRMethod)._internalVariables())._asArray())._collect_((function(each){
 return smalltalk.withContext(function($ctx5) {
return _st(_st(each)._variable())._alias();
 }, function($ctx5) {$ctx5.fillBlock({each:each},$ctx1)})})));
 };
-$10=_st(_st(anIRMethod)._scope())._hasNonLocalReturn();
-if(smalltalk.assert($10)){
+$2=_st(_st(anIRMethod)._scope())._hasNonLocalReturn();
+if(smalltalk.assert($2)){
 return _st(_st(self)._stream())._nextPutNonLocalReturnHandlingWith_((function(){
 return smalltalk.withContext(function($ctx5) {
return smalltalk.IRVisitor.fn.prototype._visitIRMethod_.apply(_st(self), [anIRMethod]);
 }, function($ctx5) {$ctx5.fillBlock({},$ctx1)})}));
 } else {
 return smalltalk.IRVisitor.fn.prototype._visitIRMethod_.apply(_st(self), [anIRMethod]);
 };
-}, function($ctx4) {$ctx4.fillBlock({},$ctx1)})});
-return _st($6)._nextPutContextFor_during_($7,$8);
-}, function($ctx3) {$ctx3.fillBlock({},$ctx1)})});
-return _st($4)._nextPutFunctionWith_arguments_($5,_st(anIRMethod)._arguments());
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-_st($1)._nextPutMethodDeclaration_with_($2,$3);
+}, function($ctx4) {$ctx4.fillBlock({},$ctx1)})}));
+}, function($ctx3) {$ctx3.fillBlock({},$ctx1)})}),_st(anIRMethod)._arguments());
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"visitIRMethod:",{anIRMethod:anIRMethod}, smalltalk.IRJSTranslator)})}
 }),
 smalltalk.IRJSTranslator);

+ 44 - 66
js/Compiler-IR.js

@@ -43,32 +43,28 @@ category: 'visiting',
 fn: function (aCollection){
 var self=this;
 var threshold,result;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$2,$4,$6,$8,$7,$5,$9;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$4,$3,$5;
 threshold=(0);
-$1=aCollection;
-$2=(function(each,i){
-return smalltalk.withContext(function($ctx2) {
$3=_st(each)._subtreeNeedsAliasing();
-if(smalltalk.assert($3)){
+_st(aCollection)._withIndexDo_((function(each,i){
+return smalltalk.withContext(function($ctx2) {
$1=_st(each)._subtreeNeedsAliasing();
+if(smalltalk.assert($1)){
 threshold=i;
 return threshold;
 };
-}, function($ctx2) {$ctx2.fillBlock({each:each,i:i},$ctx1)})});
-_st($1)._withIndexDo_($2);
+}, function($ctx2) {$ctx2.fillBlock({each:each,i:i},$ctx1)})}));
 result=_st((smalltalk.OrderedCollection || OrderedCollection))._new();
-$4=aCollection;
-$5=(function(each,i){
-return smalltalk.withContext(function($ctx2) {
$6=result;
-$8=_st(i).__lt_eq(threshold);
-if(smalltalk.assert($8)){
-$7=_st(self)._alias_(each);
+_st(aCollection)._withIndexDo_((function(each,i){
+return smalltalk.withContext(function($ctx2) {
$2=result;
+$4=_st(i).__lt_eq(threshold);
+if(smalltalk.assert($4)){
+$3=_st(self)._alias_(each);
 } else {
-$7=_st(self)._visit_(each);
+$3=_st(self)._visit_(each);
 };
-return _st($6)._add_($7);
-}, function($ctx2) {$ctx2.fillBlock({each:each,i:i},$ctx1)})});
-_st($4)._withIndexDo_($5);
-$9=result;
-return $9;
+return _st($2)._add_($3);
+}, function($ctx2) {$ctx2.fillBlock({each:each,i:i},$ctx1)})}));
+$5=result;
+return $5;
 }, function($ctx1) {$ctx1.fill(self,"aliasTemporally:",{aCollection:aCollection,threshold:threshold,result:result}, smalltalk.IRASTTranslator)})},
 args: ["aCollection"],
 source: "aliasTemporally: aCollection\x0a\x09\x22https://github.com/NicolasPetton/amber/issues/296\x0a    \x0a    If a node is aliased, all preceding ones are aliased as well.\x0a    The tree is iterated twice. First we get the aliasing dependency, \x0a    then the aliasing itself is done\x22\x0a\x0a\x09| threshold result |\x0a    threshold := 0.\x0a    \x0a    aCollection withIndexDo: [ :each :i |\x0a        each subtreeNeedsAliasing\x0a\x09\x09    ifTrue: [ threshold := i ]].\x0a\x0a\x09result := OrderedCollection new.\x0a\x09aCollection withIndexDo: [ :each :i | \x0a\x09\x09result add: (i <= threshold\x0a\x09\x09\x09ifTrue: [ self alias: each ]\x0a\x09\x09\x09ifFalse: [ self visit: each ])].\x0a\x0a    ^result",
@@ -306,28 +302,23 @@ selector: "visitBlockSequenceNode:",
 category: 'visiting',
 fn: function (aNode){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $2,$3,$5,$7,$8,$9,$6,$4,$1;
-$2=self;
-$3=_st((smalltalk.IRBlockSequence || IRBlockSequence))._new();
-$4=(function(){
-return smalltalk.withContext(function($ctx2) {
$5=_st(aNode)._nodes();
-$6=(function(){
+return smalltalk.withContext(function($ctx1) { 
var $2,$3,$4,$1;
+$1=_st(self)._withSequence_do_(_st((smalltalk.IRBlockSequence || IRBlockSequence))._new(),(function(){
+return smalltalk.withContext(function($ctx2) {
return _st(_st(aNode)._nodes())._ifNotEmpty_((function(){
 return smalltalk.withContext(function($ctx3) {
_st(_st(_st(aNode)._nodes())._allButLast())._do_((function(each){
 return smalltalk.withContext(function($ctx4) {
return _st(_st(self)._sequence())._add_(_st(self)._visit_(each));
 }, function($ctx4) {$ctx4.fillBlock({each:each},$ctx1)})}));
-$7=_st(_st(_st(aNode)._nodes())._last())._isReturnNode();
-if(smalltalk.assert($7)){
+$2=_st(_st(_st(aNode)._nodes())._last())._isReturnNode();
+if(smalltalk.assert($2)){
 return _st(_st(self)._sequence())._add_(_st(self)._visit_(_st(_st(aNode)._nodes())._last()));
 } else {
-$8=_st((smalltalk.IRBlockReturn || IRBlockReturn))._new();
-_st($8)._add_(_st(self)._visit_(_st(_st(aNode)._nodes())._last()));
-$9=_st($8)._yourself();
-return _st(_st(self)._sequence())._add_($9);
+$3=_st((smalltalk.IRBlockReturn || IRBlockReturn))._new();
+_st($3)._add_(_st(self)._visit_(_st(_st(aNode)._nodes())._last()));
+$4=_st($3)._yourself();
+return _st(_st(self)._sequence())._add_($4);
 };
-}, function($ctx3) {$ctx3.fillBlock({},$ctx1)})});
-return _st($5)._ifNotEmpty_($6);
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-$1=_st($2)._withSequence_do_($3,$4);
+}, function($ctx3) {$ctx3.fillBlock({},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"visitBlockSequenceNode:",{aNode:aNode}, smalltalk.IRASTTranslator)})},
 args: ["aNode"],
@@ -550,23 +541,18 @@ selector: "visitSequenceNode:",
 category: 'visiting',
 fn: function (aNode){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $2,$3,$5,$7,$6,$4,$1;
-$2=self;
-$3=_st((smalltalk.IRSequence || IRSequence))._new();
-$4=(function(){
-return smalltalk.withContext(function($ctx2) {
$5=_st(aNode)._nodes();
-$6=(function(each){
+return smalltalk.withContext(function($ctx1) { 
var $2,$1;
+$1=_st(self)._withSequence_do_(_st((smalltalk.IRSequence || IRSequence))._new(),(function(){
+return smalltalk.withContext(function($ctx2) {
return _st(_st(aNode)._nodes())._do_((function(each){
 var instruction;
 return smalltalk.withContext(function($ctx3) {
instruction=_st(self)._visit_(each);
 instruction;
-$7=_st(instruction)._isVariable();
-if(! smalltalk.assert($7)){
+$2=_st(instruction)._isVariable();
+if(! smalltalk.assert($2)){
 return _st(_st(self)._sequence())._add_(instruction);
 };
-}, function($ctx3) {$ctx3.fillBlock({each:each,instruction:instruction},$ctx1)})});
-return _st($5)._do_($6);
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-$1=_st($2)._withSequence_do_($3,$4);
+}, function($ctx3) {$ctx3.fillBlock({each:each,instruction:instruction},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"visitSequenceNode:",{aNode:aNode}, smalltalk.IRASTTranslator)})},
 args: ["aNode"],
@@ -2730,38 +2716,30 @@ selector: "visitIRMethod:",
 category: 'visiting',
 fn: function (anIRMethod){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2,$4,$6,$7,$9,$10,$8,$5,$3;
-$1=_st(self)._stream();
-$2=anIRMethod;
-$3=(function(){
-return smalltalk.withContext(function($ctx2) {
$4=_st(self)._stream();
-$5=(function(){
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
+_st(_st(self)._stream())._nextPutMethodDeclaration_with_(anIRMethod,(function(){
+return smalltalk.withContext(function($ctx2) {
return _st(_st(self)._stream())._nextPutFunctionWith_arguments_((function(){
 return smalltalk.withContext(function($ctx3) {
_st(_st(self)._stream())._nextPutVars_(_st(_st(anIRMethod)._tempDeclarations())._collect_((function(each){
 return smalltalk.withContext(function($ctx4) {
return _st(_st(each)._name())._asVariableName();
 }, function($ctx4) {$ctx4.fillBlock({each:each},$ctx1)})})));
-$6=_st(self)._stream();
-$7=anIRMethod;
-$8=(function(){
-return smalltalk.withContext(function($ctx4) {
$9=_st(_st(anIRMethod)._internalVariables())._notEmpty();
-if(smalltalk.assert($9)){
+return _st(_st(self)._stream())._nextPutContextFor_during_(anIRMethod,(function(){
+return smalltalk.withContext(function($ctx4) {
$1=_st(_st(anIRMethod)._internalVariables())._notEmpty();
+if(smalltalk.assert($1)){
 _st(_st(self)._stream())._nextPutVars_(_st(_st(_st(anIRMethod)._internalVariables())._asArray())._collect_((function(each){
 return smalltalk.withContext(function($ctx5) {
return _st(_st(each)._variable())._alias();
 }, function($ctx5) {$ctx5.fillBlock({each:each},$ctx1)})})));
 };
-$10=_st(_st(anIRMethod)._scope())._hasNonLocalReturn();
-if(smalltalk.assert($10)){
+$2=_st(_st(anIRMethod)._scope())._hasNonLocalReturn();
+if(smalltalk.assert($2)){
 return _st(_st(self)._stream())._nextPutNonLocalReturnHandlingWith_((function(){
 return smalltalk.withContext(function($ctx5) {
return smalltalk.IRVisitor.fn.prototype._visitIRMethod_.apply(_st(self), [anIRMethod]);
 }, function($ctx5) {$ctx5.fillBlock({},$ctx1)})}));
 } else {
 return smalltalk.IRVisitor.fn.prototype._visitIRMethod_.apply(_st(self), [anIRMethod]);
 };
-}, function($ctx4) {$ctx4.fillBlock({},$ctx1)})});
-return _st($6)._nextPutContextFor_during_($7,$8);
-}, function($ctx3) {$ctx3.fillBlock({},$ctx1)})});
-return _st($4)._nextPutFunctionWith_arguments_($5,_st(anIRMethod)._arguments());
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-_st($1)._nextPutMethodDeclaration_with_($2,$3);
+}, function($ctx4) {$ctx4.fillBlock({},$ctx1)})}));
+}, function($ctx3) {$ctx3.fillBlock({},$ctx1)})}),_st(anIRMethod)._arguments());
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"visitIRMethod:",{anIRMethod:anIRMethod}, smalltalk.IRJSTranslator)})},
 args: ["anIRMethod"],
 source: "visitIRMethod: anIRMethod\x0a\x0a\x09self stream\x0a\x09\x09nextPutMethodDeclaration: anIRMethod \x0a\x09\x09with: [ self stream \x0a\x09\x09\x09nextPutFunctionWith: [ \x0a            \x09self stream nextPutVars: (anIRMethod tempDeclarations collect: [ :each |\x0a    \x09\x09\x09\x09each name asVariableName ]).\x0a            \x09self stream nextPutContextFor: anIRMethod during: [\x0a\x09\x09\x09\x09anIRMethod internalVariables notEmpty ifTrue: [\x0a\x09\x09\x09\x09\x09self stream nextPutVars: (anIRMethod internalVariables asArray collect: [ :each |\x0a\x09\x09\x09\x09\x09\x09each variable alias ]) ].\x0a\x09\x09\x09\x09anIRMethod scope hasNonLocalReturn \x0a\x09\x09\x09\x09\x09ifTrue: [\x0a\x09\x09\x09\x09\x09\x09self stream nextPutNonLocalReturnHandlingWith: [\x0a\x09\x09\x09\x09\x09\x09\x09super visitIRMethod: anIRMethod ]]\x0a\x09\x09\x09\x09\x09ifFalse: [ super visitIRMethod: anIRMethod ]]]\x0a\x09\x09\x09arguments: anIRMethod arguments ]",

+ 39 - 49
js/Compiler-Inlining.deploy.js

@@ -711,37 +711,33 @@ selector: "inlineClosure:",
 fn: function (anIRClosure){
 var self=this;
 var inlinedClosure,sequence,statements;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$2,$4,$6,$5,$7;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3;
 inlinedClosure=_st(self)._inlinedClosure();
 _st(inlinedClosure)._scope_(_st(anIRClosure)._scope());
-$1=_st(anIRClosure)._instructions();
-$2=(function(each){
-return smalltalk.withContext(function($ctx2) {
$3=_st(each)._isSequence();
-if(! smalltalk.assert($3)){
+_st(_st(anIRClosure)._instructions())._do_((function(each){
+return smalltalk.withContext(function($ctx2) {
$1=_st(each)._isSequence();
+if(! smalltalk.assert($1)){
 return _st(inlinedClosure)._add_(each);
 };
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})});
-_st($1)._do_($2);
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
 sequence=_st(self)._inlinedSequence();
 _st(inlinedClosure)._add_(sequence);
 statements=_st(_st(_st(anIRClosure)._instructions())._last())._instructions();
-$4=statements;
-$5=(function(){
+_st(statements)._ifNotEmpty_((function(){
 return smalltalk.withContext(function($ctx2) {
_st(_st(statements)._allButLast())._do_((function(each){
 return smalltalk.withContext(function($ctx3) {
return _st(sequence)._add_(each);
 }, function($ctx3) {$ctx3.fillBlock({each:each},$ctx1)})}));
-$6=_st(_st(_st(statements)._last())._isReturn())._and_((function(){
+$2=_st(_st(_st(statements)._last())._isReturn())._and_((function(){
 return smalltalk.withContext(function($ctx3) {
return _st(_st(statements)._last())._isBlockReturn();
 }, function($ctx3) {$ctx3.fillBlock({},$ctx1)})}));
-if(smalltalk.assert($6)){
+if(smalltalk.assert($2)){
 return _st(sequence)._add_(_st(_st(_st(statements)._last())._instructions())._first());
 } else {
 return _st(sequence)._add_(_st(statements)._last());
 };
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-_st($4)._ifNotEmpty_($5);
-$7=inlinedClosure;
-return $7;
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+$3=inlinedClosure;
+return $3;
 }, function($ctx1) {$ctx1.fill(self,"inlineClosure:",{anIRClosure:anIRClosure,inlinedClosure:inlinedClosure,sequence:sequence,statements:statements}, smalltalk.IRSendInliner)})}
 }),
 smalltalk.IRSendInliner);
@@ -927,21 +923,19 @@ smalltalk.method({
 selector: "shouldInline:",
 fn: function (anIRInstruction){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2,$4,$3;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
 var $early={};
 try {
 $1=_st(_st(self)._inlinedSelectors())._includes_(_st(anIRInstruction)._selector());
 if(! smalltalk.assert($1)){
 return false;
 };
-$2=_st(_st(anIRInstruction)._instructions())._allButFirst();
-$3=(function(each){
-return smalltalk.withContext(function($ctx2) {
$4=_st(each)._isClosure();
-if(! smalltalk.assert($4)){
+_st(_st(_st(anIRInstruction)._instructions())._allButFirst())._do_((function(each){
+return smalltalk.withContext(function($ctx2) {
$2=_st(each)._isClosure();
+if(! smalltalk.assert($2)){
 throw $early=[false];
 };
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})});
-_st($2)._do_($3);
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
 return true;
 }
 catch(e) {if(e===$early)return e[0]; throw e}
@@ -1003,23 +997,21 @@ selector: "inlineClosure:",
 fn: function (anIRClosure){
 var self=this;
 var inlinedClosure,statements;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$4,$5,$2,$6;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3,$4;
 inlinedClosure=smalltalk.IRSendInliner.fn.prototype._inlineClosure_.apply(_st(self), [anIRClosure]);
 statements=_st(_st(_st(inlinedClosure)._instructions())._last())._instructions();
-$1=statements;
-$2=(function(){
-return smalltalk.withContext(function($ctx2) {
$3=_st(_st(statements)._last())._canBeAssigned();
-if(smalltalk.assert($3)){
-$4=_st((smalltalk.IRAssignment || IRAssignment))._new();
-_st($4)._add_(_st(_st(_st(self)._assignment())._instructions())._first());
-_st($4)._add_(_st(_st(statements)._last())._copy());
-$5=_st($4)._yourself();
-return _st(_st(statements)._last())._replaceWith_($5);
+_st(statements)._ifNotEmpty_((function(){
+return smalltalk.withContext(function($ctx2) {
$1=_st(_st(statements)._last())._canBeAssigned();
+if(smalltalk.assert($1)){
+$2=_st((smalltalk.IRAssignment || IRAssignment))._new();
+_st($2)._add_(_st(_st(_st(self)._assignment())._instructions())._first());
+_st($2)._add_(_st(_st(statements)._last())._copy());
+$3=_st($2)._yourself();
+return _st(_st(statements)._last())._replaceWith_($3);
 };
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-_st($1)._ifNotEmpty_($2);
-$6=inlinedClosure;
-return $6;
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+$4=inlinedClosure;
+return $4;
 }, function($ctx1) {$ctx1.fill(self,"inlineClosure:",{anIRClosure:anIRClosure,inlinedClosure:inlinedClosure,statements:statements}, smalltalk.IRAssignmentInliner)})}
 }),
 smalltalk.IRAssignmentInliner);
@@ -1063,22 +1055,20 @@ selector: "inlineClosure:",
 fn: function (anIRClosure){
 var self=this;
 var closure,statements;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$4,$5,$2,$6;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3,$4;
 closure=smalltalk.IRSendInliner.fn.prototype._inlineClosure_.apply(_st(self), [anIRClosure]);
 statements=_st(_st(_st(closure)._instructions())._last())._instructions();
-$1=statements;
-$2=(function(){
-return smalltalk.withContext(function($ctx2) {
$3=_st(_st(statements)._last())._isReturn();
-if(! smalltalk.assert($3)){
-$4=_st((smalltalk.IRReturn || IRReturn))._new();
-_st($4)._add_(_st(_st(statements)._last())._copy());
-$5=_st($4)._yourself();
-return _st(_st(statements)._last())._replaceWith_($5);
+_st(statements)._ifNotEmpty_((function(){
+return smalltalk.withContext(function($ctx2) {
$1=_st(_st(statements)._last())._isReturn();
+if(! smalltalk.assert($1)){
+$2=_st((smalltalk.IRReturn || IRReturn))._new();
+_st($2)._add_(_st(_st(statements)._last())._copy());
+$3=_st($2)._yourself();
+return _st(_st(statements)._last())._replaceWith_($3);
 };
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-_st($1)._ifNotEmpty_($2);
-$6=closure;
-return $6;
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+$4=closure;
+return $4;
 }, function($ctx1) {$ctx1.fill(self,"inlineClosure:",{anIRClosure:anIRClosure,closure:closure,statements:statements}, smalltalk.IRReturnInliner)})}
 }),
 smalltalk.IRReturnInliner);

+ 39 - 49
js/Compiler-Inlining.js

@@ -951,37 +951,33 @@ category: 'inlining',
 fn: function (anIRClosure){
 var self=this;
 var inlinedClosure,sequence,statements;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$2,$4,$6,$5,$7;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3;
 inlinedClosure=_st(self)._inlinedClosure();
 _st(inlinedClosure)._scope_(_st(anIRClosure)._scope());
-$1=_st(anIRClosure)._instructions();
-$2=(function(each){
-return smalltalk.withContext(function($ctx2) {
$3=_st(each)._isSequence();
-if(! smalltalk.assert($3)){
+_st(_st(anIRClosure)._instructions())._do_((function(each){
+return smalltalk.withContext(function($ctx2) {
$1=_st(each)._isSequence();
+if(! smalltalk.assert($1)){
 return _st(inlinedClosure)._add_(each);
 };
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})});
-_st($1)._do_($2);
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
 sequence=_st(self)._inlinedSequence();
 _st(inlinedClosure)._add_(sequence);
 statements=_st(_st(_st(anIRClosure)._instructions())._last())._instructions();
-$4=statements;
-$5=(function(){
+_st(statements)._ifNotEmpty_((function(){
 return smalltalk.withContext(function($ctx2) {
_st(_st(statements)._allButLast())._do_((function(each){
 return smalltalk.withContext(function($ctx3) {
return _st(sequence)._add_(each);
 }, function($ctx3) {$ctx3.fillBlock({each:each},$ctx1)})}));
-$6=_st(_st(_st(statements)._last())._isReturn())._and_((function(){
+$2=_st(_st(_st(statements)._last())._isReturn())._and_((function(){
 return smalltalk.withContext(function($ctx3) {
return _st(_st(statements)._last())._isBlockReturn();
 }, function($ctx3) {$ctx3.fillBlock({},$ctx1)})}));
-if(smalltalk.assert($6)){
+if(smalltalk.assert($2)){
 return _st(sequence)._add_(_st(_st(_st(statements)._last())._instructions())._first());
 } else {
 return _st(sequence)._add_(_st(statements)._last());
 };
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-_st($4)._ifNotEmpty_($5);
-$7=inlinedClosure;
-return $7;
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+$3=inlinedClosure;
+return $3;
 }, function($ctx1) {$ctx1.fill(self,"inlineClosure:",{anIRClosure:anIRClosure,inlinedClosure:inlinedClosure,sequence:sequence,statements:statements}, smalltalk.IRSendInliner)})},
 args: ["anIRClosure"],
 source: "inlineClosure: anIRClosure\x0a\x09| inlinedClosure sequence statements |\x0a\x0a\x09inlinedClosure := self inlinedClosure.\x0a\x09inlinedClosure scope: anIRClosure scope.\x0a\x0a\x09\x22Add the possible temp declarations\x22\x0a\x09anIRClosure instructions do: [ :each | \x0a\x09\x09each isSequence ifFalse: [\x0a\x09\x09\x09inlinedClosure add: each ]].\x0a\x0a\x09\x22Add a block sequence\x22\x0a\x09sequence := self inlinedSequence.\x0a\x09inlinedClosure add: sequence.\x0a\x0a\x09\x22Get all the statements\x22\x0a\x09statements := anIRClosure instructions last instructions.\x0a\x09\x0a\x09statements ifNotEmpty: [\x0a\x09\x09statements allButLast do: [ :each | sequence add: each ].\x0a\x0a\x09\x09\x22Inlined closures don't have implicit local returns\x22\x0a\x09\x09(statements last isReturn and: [ statements last isBlockReturn ])\x0a\x09\x09\x09ifTrue: [ sequence add: statements last instructions first ]\x0a\x09\x09\x09ifFalse: [ sequence add: statements last ] ].\x0a\x0a\x09^ inlinedClosure",
@@ -1227,21 +1223,19 @@ selector: "shouldInline:",
 category: 'accessing',
 fn: function (anIRInstruction){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2,$4,$3;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
 var $early={};
 try {
 $1=_st(_st(self)._inlinedSelectors())._includes_(_st(anIRInstruction)._selector());
 if(! smalltalk.assert($1)){
 return false;
 };
-$2=_st(_st(anIRInstruction)._instructions())._allButFirst();
-$3=(function(each){
-return smalltalk.withContext(function($ctx2) {
$4=_st(each)._isClosure();
-if(! smalltalk.assert($4)){
+_st(_st(_st(anIRInstruction)._instructions())._allButFirst())._do_((function(each){
+return smalltalk.withContext(function($ctx2) {
$2=_st(each)._isClosure();
+if(! smalltalk.assert($2)){
 throw $early=[false];
 };
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})});
-_st($2)._do_($3);
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
 return true;
 }
 catch(e) {if(e===$early)return e[0]; throw e}
@@ -1324,23 +1318,21 @@ category: 'inlining',
 fn: function (anIRClosure){
 var self=this;
 var inlinedClosure,statements;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$4,$5,$2,$6;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3,$4;
 inlinedClosure=smalltalk.IRSendInliner.fn.prototype._inlineClosure_.apply(_st(self), [anIRClosure]);
 statements=_st(_st(_st(inlinedClosure)._instructions())._last())._instructions();
-$1=statements;
-$2=(function(){
-return smalltalk.withContext(function($ctx2) {
$3=_st(_st(statements)._last())._canBeAssigned();
-if(smalltalk.assert($3)){
-$4=_st((smalltalk.IRAssignment || IRAssignment))._new();
-_st($4)._add_(_st(_st(_st(self)._assignment())._instructions())._first());
-_st($4)._add_(_st(_st(statements)._last())._copy());
-$5=_st($4)._yourself();
-return _st(_st(statements)._last())._replaceWith_($5);
+_st(statements)._ifNotEmpty_((function(){
+return smalltalk.withContext(function($ctx2) {
$1=_st(_st(statements)._last())._canBeAssigned();
+if(smalltalk.assert($1)){
+$2=_st((smalltalk.IRAssignment || IRAssignment))._new();
+_st($2)._add_(_st(_st(_st(self)._assignment())._instructions())._first());
+_st($2)._add_(_st(_st(statements)._last())._copy());
+$3=_st($2)._yourself();
+return _st(_st(statements)._last())._replaceWith_($3);
 };
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-_st($1)._ifNotEmpty_($2);
-$6=inlinedClosure;
-return $6;
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+$4=inlinedClosure;
+return $4;
 }, function($ctx1) {$ctx1.fill(self,"inlineClosure:",{anIRClosure:anIRClosure,inlinedClosure:inlinedClosure,statements:statements}, smalltalk.IRAssignmentInliner)})},
 args: ["anIRClosure"],
 source: "inlineClosure: anIRClosure\x0a\x09| inlinedClosure statements |\x0a\x0a\x09inlinedClosure := super inlineClosure: anIRClosure.\x0a\x09statements := inlinedClosure instructions last instructions.\x0a\x09\x0a\x09statements ifNotEmpty: [\x0a\x09\x09statements last canBeAssigned ifTrue: [\x0a\x09\x09\x09statements last replaceWith: (IRAssignment new\x0a\x09\x09\x09\x09add: self assignment instructions first;\x0a\x09\x09\x09\x09add: statements last copy;\x0a\x09\x09\x09\x09yourself) ] ].\x0a\x0a\x09^ inlinedClosure",
@@ -1400,22 +1392,20 @@ category: 'inlining',
 fn: function (anIRClosure){
 var self=this;
 var closure,statements;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$4,$5,$2,$6;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3,$4;
 closure=smalltalk.IRSendInliner.fn.prototype._inlineClosure_.apply(_st(self), [anIRClosure]);
 statements=_st(_st(_st(closure)._instructions())._last())._instructions();
-$1=statements;
-$2=(function(){
-return smalltalk.withContext(function($ctx2) {
$3=_st(_st(statements)._last())._isReturn();
-if(! smalltalk.assert($3)){
-$4=_st((smalltalk.IRReturn || IRReturn))._new();
-_st($4)._add_(_st(_st(statements)._last())._copy());
-$5=_st($4)._yourself();
-return _st(_st(statements)._last())._replaceWith_($5);
+_st(statements)._ifNotEmpty_((function(){
+return smalltalk.withContext(function($ctx2) {
$1=_st(_st(statements)._last())._isReturn();
+if(! smalltalk.assert($1)){
+$2=_st((smalltalk.IRReturn || IRReturn))._new();
+_st($2)._add_(_st(_st(statements)._last())._copy());
+$3=_st($2)._yourself();
+return _st(_st(statements)._last())._replaceWith_($3);
 };
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-_st($1)._ifNotEmpty_($2);
-$6=closure;
-return $6;
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+$4=closure;
+return $4;
 }, function($ctx1) {$ctx1.fill(self,"inlineClosure:",{anIRClosure:anIRClosure,closure:closure,statements:statements}, smalltalk.IRReturnInliner)})},
 args: ["anIRClosure"],
 source: "inlineClosure: anIRClosure\x0a\x09| closure statements |\x0a\x0a\x09closure := super inlineClosure: anIRClosure.\x0a\x09statements := closure instructions last instructions.\x0a\x09\x0a\x09statements ifNotEmpty: [\x0a\x09\x09statements last isReturn\x0a\x09\x09\x09ifFalse: [ statements last replaceWith: (IRReturn new\x0a\x09\x09\x09\x09add: statements last copy;\x0a\x09\x09\x09\x09yourself)] ].\x0a\x0a\x09^ closure",

+ 23 - 24
js/Compiler-Semantic.deploy.js

@@ -173,21 +173,22 @@ selector: "lookupVariable:",
 fn: function (aNode){
 var self=this;
 var lookup;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$2,$4;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3;
 lookup=_st(self)._bindingFor_(aNode);
 $1=lookup;
-$2=(function(){
-return smalltalk.withContext(function($ctx2) {
$3=_st(self)._outerScope();
-if(($receiver = $3) == nil || $receiver == undefined){
-lookup=$3;
+if(($receiver = $1) == nil || $receiver == undefined){
+$2=_st(self)._outerScope();
+if(($receiver = $2) == nil || $receiver == undefined){
+lookup=$2;
 } else {
 lookup=_st(_st(self)._outerScope())._lookupVariable_(aNode);
 };
-return lookup;
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-_st($1)._ifNil_($2);
-$4=lookup;
-return $4;
+lookup;
+} else {
+$1;
+};
+$3=lookup;
+return $3;
 }, function($ctx1) {$ctx1.fill(self,"lookupVariable:",{aNode:aNode,lookup:lookup}, smalltalk.LexicalScope)})}
 }),
 smalltalk.LexicalScope);
@@ -919,7 +920,7 @@ var self=this;
 var identifier;
 return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3;
 identifier=_st(aNode)._value();
-$1=_st(_st(_st(["jQuery", "window", "process", "global"])._includes_(identifier))._not())._and_((function(){
+$1=_st(_st(_st(["jQuery", "window", "document", "process", "global"])._includes_(identifier))._not())._and_((function(){
 return smalltalk.withContext(function($ctx2) {
return _st(self)._isVariableGloballyUndefined_(identifier);
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 if(smalltalk.assert($1)){
@@ -1216,24 +1217,22 @@ smalltalk.method({
 selector: "visitSendNode:",
 fn: function (aNode){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2,$4,$3;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
 $1=_st(_st(_st(aNode)._receiver())._value()).__eq("super");
-$2=(function(){
-return smalltalk.withContext(function($ctx2) {
_st(aNode)._superSend_(true);
+if(smalltalk.assert($1)){
+_st(aNode)._superSend_(true);
 _st(_st(aNode)._receiver())._value_("self");
 _st(_st(self)._superSends())._at_ifAbsentPut_(_st(aNode)._selector(),(function(){
-return smalltalk.withContext(function($ctx3) {
return _st((smalltalk.Set || Set))._new();
-}, function($ctx3) {$ctx3.fillBlock({},$ctx1)})}));
-return _st(_st(_st(self)._superSends())._at_(_st(aNode)._selector()))._add_(aNode);
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-$3=(function(){
-return smalltalk.withContext(function($ctx2) {
$4=_st(_st((smalltalk.IRSendInliner || IRSendInliner))._inlinedSelectors())._includes_(_st(aNode)._selector());
-if(smalltalk.assert($4)){
+return smalltalk.withContext(function($ctx2) {
return _st((smalltalk.Set || Set))._new();
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+_st(_st(_st(self)._superSends())._at_(_st(aNode)._selector()))._add_(aNode);
+} else {
+$2=_st(_st((smalltalk.IRSendInliner || IRSendInliner))._inlinedSelectors())._includes_(_st(aNode)._selector());
+if(smalltalk.assert($2)){
 _st(aNode)._shouldBeInlined_(true);
-return _st(_st(aNode)._receiver())._shouldBeAliased_(true);
+_st(_st(aNode)._receiver())._shouldBeAliased_(true);
+};
 };
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-_st($1)._ifTrue_ifFalse_($2,$3);
 _st(_st(self)._messageSends())._at_ifAbsentPut_(_st(aNode)._selector(),(function(){
 return smalltalk.withContext(function($ctx2) {
return _st((smalltalk.Set || Set))._new();
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));

+ 24 - 25
js/Compiler-Semantic.js

@@ -235,21 +235,22 @@ category: 'accessing',
 fn: function (aNode){
 var self=this;
 var lookup;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$2,$4;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3;
 lookup=_st(self)._bindingFor_(aNode);
 $1=lookup;
-$2=(function(){
-return smalltalk.withContext(function($ctx2) {
$3=_st(self)._outerScope();
-if(($receiver = $3) == nil || $receiver == undefined){
-lookup=$3;
+if(($receiver = $1) == nil || $receiver == undefined){
+$2=_st(self)._outerScope();
+if(($receiver = $2) == nil || $receiver == undefined){
+lookup=$2;
 } else {
 lookup=_st(_st(self)._outerScope())._lookupVariable_(aNode);
 };
-return lookup;
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-_st($1)._ifNil_($2);
-$4=lookup;
-return $4;
+lookup;
+} else {
+$1;
+};
+$3=lookup;
+return $3;
 }, function($ctx1) {$ctx1.fill(self,"lookupVariable:",{aNode:aNode,lookup:lookup}, smalltalk.LexicalScope)})},
 args: ["aNode"],
 source: "lookupVariable: aNode\x0a\x09| lookup |\x0a\x09lookup := (self bindingFor: aNode).\x0a\x09lookup ifNil: [\x0a\x09\x09lookup := self outerScope ifNotNil: [ \x0a\x09\x09\x09(self outerScope lookupVariable: aNode) ]].\x0a\x09^ lookup",
@@ -1246,7 +1247,7 @@ var self=this;
 var identifier;
 return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3;
 identifier=_st(aNode)._value();
-$1=_st(_st(_st(["jQuery", "window", "process", "global"])._includes_(identifier))._not())._and_((function(){
+$1=_st(_st(_st(["jQuery", "window", "document", "process", "global"])._includes_(identifier))._not())._and_((function(){
 return smalltalk.withContext(function($ctx2) {
return _st(self)._isVariableGloballyUndefined_(identifier);
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 if(smalltalk.assert($1)){
@@ -1259,7 +1260,7 @@ _st(_st(_st(self["@currentScope"])._methodScope())._unknownVariables())._add_(_s
 };
 return self}, function($ctx1) {$ctx1.fill(self,"errorUnknownVariable:",{aNode:aNode,identifier:identifier}, smalltalk.SemanticAnalyzer)})},
 args: ["aNode"],
-source: "errorUnknownVariable: aNode\x0a\x09\x22Throw an error if the variable is undeclared in the global JS scope (i.e. window).\x0a    We allow four variable names in addition: `jQuery`, `window`, `process` and `global` \x0a    for nodejs and browser environments. \x0a    \x0a    This is only to make sure compilation works on both browser-based and nodejs environments.\x0a    The ideal solution would be to use a pragma instead\x22\x0a\x0a\x09| identifier |\x0a    identifier := aNode value.\x0a    \x0a\x09((#('jQuery' 'window' 'process' 'global') includes: identifier) not \x0a        and: [ self isVariableGloballyUndefined: identifier ]) \x0a        \x09ifTrue: [\x0a\x09\x09\x09\x09UnknownVariableError new\x0a\x09\x09\x09\x09\x09variableName: aNode value;\x0a\x09\x09\x09\x09\x09signal ]\x0a\x09\x09\x09ifFalse: [\x0a\x09\x09\x09\x09currentScope methodScope unknownVariables add: aNode value ]",
+source: "errorUnknownVariable: aNode\x0a\x09\x22Throw an error if the variable is undeclared in the global JS scope (i.e. window).\x0a    We allow four variable names in addition: `jQuery`, `window`, `process` and `global` \x0a    for nodejs and browser environments. \x0a    \x0a    This is only to make sure compilation works on both browser-based and nodejs environments.\x0a    The ideal solution would be to use a pragma instead\x22\x0a\x0a\x09| identifier |\x0a    identifier := aNode value.\x0a    \x0a\x09((#('jQuery' 'window' 'document' 'process' 'global') includes: identifier) not \x0a        and: [ self isVariableGloballyUndefined: identifier ]) \x0a        \x09ifTrue: [\x0a\x09\x09\x09\x09UnknownVariableError new\x0a\x09\x09\x09\x09\x09variableName: aNode value;\x0a\x09\x09\x09\x09\x09signal ]\x0a\x09\x09\x09ifFalse: [\x0a\x09\x09\x09\x09currentScope methodScope unknownVariables add: aNode value ]",
 messageSends: ["value", "ifTrue:ifFalse:", "variableName:", "new", "signal", "add:", "unknownVariables", "methodScope", "and:", "isVariableGloballyUndefined:", "not", "includes:"],
 referencedClasses: ["UnknownVariableError"]
 }),
@@ -1633,24 +1634,22 @@ selector: "visitSendNode:",
 category: 'visiting',
 fn: function (aNode){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2,$4,$3;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
 $1=_st(_st(_st(aNode)._receiver())._value()).__eq("super");
-$2=(function(){
-return smalltalk.withContext(function($ctx2) {
_st(aNode)._superSend_(true);
+if(smalltalk.assert($1)){
+_st(aNode)._superSend_(true);
 _st(_st(aNode)._receiver())._value_("self");
 _st(_st(self)._superSends())._at_ifAbsentPut_(_st(aNode)._selector(),(function(){
-return smalltalk.withContext(function($ctx3) {
return _st((smalltalk.Set || Set))._new();
-}, function($ctx3) {$ctx3.fillBlock({},$ctx1)})}));
-return _st(_st(_st(self)._superSends())._at_(_st(aNode)._selector()))._add_(aNode);
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-$3=(function(){
-return smalltalk.withContext(function($ctx2) {
$4=_st(_st((smalltalk.IRSendInliner || IRSendInliner))._inlinedSelectors())._includes_(_st(aNode)._selector());
-if(smalltalk.assert($4)){
+return smalltalk.withContext(function($ctx2) {
return _st((smalltalk.Set || Set))._new();
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+_st(_st(_st(self)._superSends())._at_(_st(aNode)._selector()))._add_(aNode);
+} else {
+$2=_st(_st((smalltalk.IRSendInliner || IRSendInliner))._inlinedSelectors())._includes_(_st(aNode)._selector());
+if(smalltalk.assert($2)){
 _st(aNode)._shouldBeInlined_(true);
-return _st(_st(aNode)._receiver())._shouldBeAliased_(true);
+_st(_st(aNode)._receiver())._shouldBeAliased_(true);
+};
 };
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-_st($1)._ifTrue_ifFalse_($2,$3);
 _st(_st(self)._messageSends())._at_ifAbsentPut_(_st(aNode)._selector(),(function(){
 return smalltalk.withContext(function($ctx2) {
return _st((smalltalk.Set || Set))._new();
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));

+ 7 - 7
js/Compiler-Tests.js

@@ -407,7 +407,7 @@ _st(_st(self)._interpreter())._step();
 _st(self)._assert_equals_(_st(_st(self)._interpreter())._result(),(3));
 return self}, function($ctx1) {$ctx1.fill(self,"testMessageSend",{}, smalltalk.ASTSteppingInterpreterTest)})},
 args: [],
-source: "testMessageSend\x0a\x09self interpret: 'foo 1 + 2'.\x0a    \x0a    \x22SequenceNode\x22\x0a    self interpreter step.\x0a    \x0a    \x22SendNode\x22\x0a    self interpreter step.\x0a    \x0a     \x22ValueNode\x22\x0a    self interpreter step.\x0a    self assert: self interpreter currentNode value equals: 1.\x0a    \x0a    \x22ValueNode\x22\x0a    self interpreter step.\x0a    self assert: self interpreter currentNode value equals: 2.\x0a    \x0a    \x22Result\x22\x0a    self interpreter step.\x0a    self assert: self interpreter result equals: 3\x0a\x09",
+source: "testMessageSend\x0a\x09self interpret: 'foo 1 + 2'.\x0a    \x0a    \x22SequenceNode\x22\x0a    self interpreter step.\x0a    \x0a    \x22SendNode\x22\x0a    self interpreter step.\x0a    \x0a     \x22ValueNode\x22\x0a    self interpreter step.\x0a    self assert: self interpreter currentNode value equals: 1.\x0a    \x0a    \x22ValueNode\x22\x0a    self interpreter step.\x0a    self assert: self interpreter currentNode value equals: 2.\x0a    \x0a    \x22Result\x22\x0a    self interpreter step.\x0a    self assert: self interpreter result equals: 3",
 messageSends: ["interpret:", "step", "interpreter", "assert:equals:", "value", "currentNode", "result"],
 referencedClasses: []
 }),
@@ -427,7 +427,7 @@ _st(_st(self)._interpreter())._step();
 _st(self)._assert_equals_(_st(_st(self)._interpreter())._result(),(1));
 return self}, function($ctx1) {$ctx1.fill(self,"testSimpleStepping",{}, smalltalk.ASTSteppingInterpreterTest)})},
 args: [],
-source: "testSimpleStepping\x0a\x09self interpret: 'foo 1'.\x0a    \x0a    \x22SequenceNode\x22\x0a    self interpreter step.\x0a    \x0a    self assert: self interpreter result isNil.\x0a    \x0a    \x22ValueNode\x22\x0a    self interpreter step.\x0a    \x0a    self assert: self interpreter result equals: 1\x0a    \x0a\x09",
+source: "testSimpleStepping\x0a\x09self interpret: 'foo 1'.\x0a    \x0a    \x22SequenceNode\x22\x0a    self interpreter step.\x0a    \x0a    self assert: self interpreter result isNil.\x0a    \x0a    \x22ValueNode\x22\x0a    self interpreter step.\x0a    \x0a    self assert: self interpreter result equals: 1",
 messageSends: ["interpret:", "step", "interpreter", "assert:", "isNil", "result", "assert:equals:"],
 referencedClasses: []
 }),
@@ -556,7 +556,7 @@ _st(self)._should_return_("foo | a | a := false ifTrue: [ 1 ]. ^ a",nil);
 _st(self)._should_return_("foo | a | ^ a := true ifTrue: [ 1 ]",(1));
 return self}, function($ctx1) {$ctx1.fill(self,"testAssignment",{}, smalltalk.CodeGeneratorTest)})},
 args: [],
-source: "testAssignment\x0a\x09self should: 'foo | a | a := true ifTrue: [ 1 ]. ^ a' return: 1.\x0a\x09self should: 'foo | a | a := false ifTrue: [ 1 ]. ^ a' return: nil.\x0a\x0a\x09self should: 'foo | a | ^ a := true ifTrue: [ 1 ]' return: 1 ",
+source: "testAssignment\x0a\x09self should: 'foo | a | a := true ifTrue: [ 1 ]. ^ a' return: 1.\x0a\x09self should: 'foo | a | a := false ifTrue: [ 1 ]. ^ a' return: nil.\x0a\x0a\x09self should: 'foo | a | ^ a := true ifTrue: [ 1 ]' return: 1",
 messageSends: ["should:return:"],
 referencedClasses: []
 }),
@@ -606,7 +606,7 @@ var self=this;
 return smalltalk.withContext(function($ctx1) { 
_st(self)._should_return_("foo\x0a  | x |\x0a  x := 1.\x0a  ^ { x. true ifTrue: [ x := 2 ] }\x0a",[(1), (2)]);
 return self}, function($ctx1) {$ctx1.fill(self,"testDynamicArrayElementsOrdered",{}, smalltalk.CodeGeneratorTest)})},
 args: [],
-source: "testDynamicArrayElementsOrdered\x0a\x09self should: 'foo\x0a  | x |\x0a  x := 1.\x0a  ^ { x. true ifTrue: [ x := 2 ] }\x0a' return: #(1 2).\x0a",
+source: "testDynamicArrayElementsOrdered\x0a\x09self should: 'foo\x0a  | x |\x0a  x := 1.\x0a  ^ { x. true ifTrue: [ x := 2 ] }\x0a' return: #(1 2).",
 messageSends: ["should:return:"],
 referencedClasses: []
 }),
@@ -622,7 +622,7 @@ var self=this;
 return smalltalk.withContext(function($ctx1) { 
_st(self)._should_return_("foo\x0a  | x |\x0a  x := 'foo'->1.\x0a  ^ #{ x. (true ifTrue: [ x := 'bar'->2 ]) }\x0a",smalltalk.HashedCollection._fromPairs_([_st("foo").__minus_gt((1)),_st("bar").__minus_gt((2))]));
 return self}, function($ctx1) {$ctx1.fill(self,"testDynamicDictionaryElementsOrdered",{}, smalltalk.CodeGeneratorTest)})},
 args: [],
-source: "testDynamicDictionaryElementsOrdered\x0a\x09self should: 'foo\x0a  | x |\x0a  x := ''foo''->1.\x0a  ^ #{ x. (true ifTrue: [ x := ''bar''->2 ]) }\x0a' return: #{'foo'->1. 'bar'->2}.\x0a",
+source: "testDynamicDictionaryElementsOrdered\x0a\x09self should: 'foo\x0a  | x |\x0a  x := ''foo''->1.\x0a  ^ #{ x. (true ifTrue: [ x := ''bar''->2 ]) }\x0a' return: #{'foo'->1. 'bar'->2}.",
 messageSends: ["should:return:", "->"],
 referencedClasses: []
 }),
@@ -641,7 +641,7 @@ _st(self)._should_return_("foo\x0a  | x |\x0a  x := 1.\x0a  ^ { 'foo'->x. 'bar'-
 _st(self)._should_return_("foo\x0a  | x |\x0a  x := 1.\x0a  ^ #{ 'foo'->x. 'bar'->(true ifTrue: [ x := 2 ]) }\x0a",smalltalk.HashedCollection._fromPairs_([_st("foo").__minus_gt((1)),_st("bar").__minus_gt((2))]));
 return self}, function($ctx1) {$ctx1.fill(self,"testInnerTemporalDependentElementsOrdered",{}, smalltalk.CodeGeneratorTest)})},
 args: [],
-source: "testInnerTemporalDependentElementsOrdered\x0a\x09self should: 'foo\x0a  | x |\x0a  x := Array.\x0a  ^ x with: ''foo''->x with: ''bar''->(true ifTrue: [ x := 2 ])\x0a' return: {'foo'->Array. 'bar'->2}.\x0a\x09self should: 'foo\x0a  | x |\x0a  x := 1.\x0a  ^ Array with: ''foo''->x with: ''bar''->(true ifTrue: [ x := 2 ])\x0a' return: {'foo'->1. 'bar'->2}.\x0a\x09self should: 'foo\x0a  | x |\x0a  x := 1.\x0a  ^ { ''foo''->x. ''bar''->(true ifTrue: [ x := 2 ]) }\x0a' return: {'foo'->1. 'bar'->2}.\x0a\x09self should: 'foo\x0a  | x |\x0a  x := 1.\x0a  ^ #{ ''foo''->x. ''bar''->(true ifTrue: [ x := 2 ]) }\x0a' return: #{'foo'->1. 'bar'->2}.\x0a",
+source: "testInnerTemporalDependentElementsOrdered\x0a\x09self should: 'foo\x0a  | x |\x0a  x := Array.\x0a  ^ x with: ''foo''->x with: ''bar''->(true ifTrue: [ x := 2 ])\x0a' return: {'foo'->Array. 'bar'->2}.\x0a\x09self should: 'foo\x0a  | x |\x0a  x := 1.\x0a  ^ Array with: ''foo''->x with: ''bar''->(true ifTrue: [ x := 2 ])\x0a' return: {'foo'->1. 'bar'->2}.\x0a\x09self should: 'foo\x0a  | x |\x0a  x := 1.\x0a  ^ { ''foo''->x. ''bar''->(true ifTrue: [ x := 2 ]) }\x0a' return: {'foo'->1. 'bar'->2}.\x0a\x09self should: 'foo\x0a  | x |\x0a  x := 1.\x0a  ^ #{ ''foo''->x. ''bar''->(true ifTrue: [ x := 2 ]) }\x0a' return: #{'foo'->1. 'bar'->2}.",
 messageSends: ["should:return:", "->"],
 referencedClasses: ["Array"]
 }),
@@ -760,7 +760,7 @@ return smalltalk.withContext(function($ctx1) { 
_st(self)._should_return_("foo\x
 _st(self)._should_return_("foo\x0a  | x |\x0a  x := Array.\x0a  ^ x with: x with: (true ifTrue: [ x := 2 ])\x0a",[(smalltalk.Array || Array),(2)]);
 return self}, function($ctx1) {$ctx1.fill(self,"testSendReceiverAndArgumentsOrdered",{}, smalltalk.CodeGeneratorTest)})},
 args: [],
-source: "testSendReceiverAndArgumentsOrdered\x0a\x09self should: 'foo\x0a  | x |\x0a  x := 1.\x0a  ^ Array with: x with: (true ifTrue: [ x := 2 ])\x0a' return: #(1 2).\x0a\x0a\x09self should: 'foo\x0a  | x |\x0a  x := Array.\x0a  ^ x with: x with: (true ifTrue: [ x := 2 ])\x0a' return: {Array. 2}.\x0a",
+source: "testSendReceiverAndArgumentsOrdered\x0a\x09self should: 'foo\x0a  | x |\x0a  x := 1.\x0a  ^ Array with: x with: (true ifTrue: [ x := 2 ])\x0a' return: #(1 2).\x0a\x0a\x09self should: 'foo\x0a  | x |\x0a  x := Array.\x0a  ^ x with: x with: (true ifTrue: [ x := 2 ])\x0a' return: {Array. 2}.",
 messageSends: ["should:return:"],
 referencedClasses: ["Array"]
 }),

File diff suppressed because it is too large
+ 270 - 104
js/Documentation.deploy.js


File diff suppressed because it is too large
+ 288 - 122
js/Documentation.js


File diff suppressed because it is too large
+ 320 - 376
js/IDE.deploy.js


File diff suppressed because it is too large
+ 244 - 290
js/IDE.js


+ 78 - 112
js/Importer-Exporter.deploy.js

@@ -7,30 +7,27 @@ selector: "nextChunk",
 fn: function (){
 var self=this;
 var char,result,chunk;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$5,$6,$4,$2;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3;
 var $early={};
 try {
 result=_st("")._writeStream();
-$1=(function(){
+_st((function(){
 return smalltalk.withContext(function($ctx2) {
char=_st(self["@stream"])._next();
 char;
 return _st(char)._notNil();
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-$2=(function(){
-return smalltalk.withContext(function($ctx2) {
$3=_st(char).__eq("!");
-$4=(function(){
-return smalltalk.withContext(function($ctx3) {
$5=_st(_st(self["@stream"])._peek()).__eq("!");
-if(smalltalk.assert($5)){
-return _st(self["@stream"])._next();
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}))._whileTrue_((function(){
+return smalltalk.withContext(function($ctx2) {
$1=_st(char).__eq("!");
+if(smalltalk.assert($1)){
+$2=_st(_st(self["@stream"])._peek()).__eq("!");
+if(smalltalk.assert($2)){
+_st(self["@stream"])._next();
 } else {
-$6=_st(_st(result)._contents())._trimBoth();
-throw $early=[$6];
+$3=_st(_st(result)._contents())._trimBoth();
+throw $early=[$3];
+};
 };
-}, function($ctx3) {$ctx3.fillBlock({},$ctx1)})});
-_st($3)._ifTrue_($4);
 return _st(result)._nextPut_(char);
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-_st($1)._whileTrue_($2);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 return nil;
 }
 catch(e) {if(e===$early)return e[0]; throw e}
@@ -71,20 +68,18 @@ smalltalk.method({
 selector: "classNameFor:",
 fn: function (aClass){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $2,$3,$5,$4,$1;
+return smalltalk.withContext(function($ctx1) { 
var $2,$3,$1;
 $2=_st(aClass)._isMetaclass();
-$3=(function(){
-return smalltalk.withContext(function($ctx2) {
return _st(_st(_st(aClass)._instanceClass())._name()).__comma(".klass");
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-$4=(function(){
-return smalltalk.withContext(function($ctx2) {
$5=_st(aClass)._isNil();
-if(smalltalk.assert($5)){
-return "nil";
+if(smalltalk.assert($2)){
+$1=_st(_st(_st(aClass)._instanceClass())._name()).__comma(".klass");
+} else {
+$3=_st(aClass)._isNil();
+if(smalltalk.assert($3)){
+$1="nil";
 } else {
-return _st(aClass)._name();
+$1=_st(aClass)._name();
+};
 };
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-$1=_st($2)._ifTrue_ifFalse_($3,$4);
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"classNameFor:",{aClass:aClass}, smalltalk.Exporter)})}
 }),
@@ -230,17 +225,15 @@ smalltalk.method({
 selector: "exportMethodsOf:on:",
 fn: function (aClass,aStream){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$2;
-$1=_st(_st(_st(aClass)._methodDictionary())._values())._sorted_((function(a,b){
+return smalltalk.withContext(function($ctx1) { 
var $1;
+_st(_st(_st(_st(aClass)._methodDictionary())._values())._sorted_((function(a,b){
 return smalltalk.withContext(function($ctx2) {
return _st(_st(a)._selector()).__lt_eq(_st(b)._selector());
-}, function($ctx2) {$ctx2.fillBlock({a:a,b:b},$ctx1)})}));
-$2=(function(each){
-return smalltalk.withContext(function($ctx2) {
$3=_st(_st(each)._category())._match_("^\x5c*");
-if(! smalltalk.assert($3)){
+}, function($ctx2) {$ctx2.fillBlock({a:a,b:b},$ctx1)})})))._do_((function(each){
+return smalltalk.withContext(function($ctx2) {
$1=_st(_st(each)._category())._match_("^\x5c*");
+if(! smalltalk.assert($1)){
 return _st(self)._exportMethod_of_on_(each,aClass,aStream);
 };
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})});
-_st($1)._do_($2);
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
 _st(aStream)._lf();
 return self}, function($ctx1) {$ctx1.fill(self,"exportMethodsOf:on:",{aClass:aClass,aStream:aStream}, smalltalk.Exporter)})}
 }),
@@ -290,26 +283,20 @@ selector: "exportPackageExtensionsOf:on:",
 fn: function (package_,aStream){
 var self=this;
 var name;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$5,$7,$6,$4,$2;
+return smalltalk.withContext(function($ctx1) { 
var $1;
 name=_st(package_)._name();
-$1=_st((smalltalk.Package || Package))._sortedClasses_(_st(_st((smalltalk.Smalltalk || Smalltalk))._current())._classes());
-$2=(function(each){
-return smalltalk.withContext(function($ctx2) {
$3=[each,_st(each)._class()];
-$4=(function(aClass){
-return smalltalk.withContext(function($ctx3) {
$5=_st(_st(_st(aClass)._methodDictionary())._values())._sorted_((function(a,b){
+_st(_st((smalltalk.Package || Package))._sortedClasses_(_st(_st((smalltalk.Smalltalk || Smalltalk))._current())._classes()))._do_((function(each){
+return smalltalk.withContext(function($ctx2) {
return _st([each,_st(each)._class()])._do_((function(aClass){
+return smalltalk.withContext(function($ctx3) {
return _st(_st(_st(_st(aClass)._methodDictionary())._values())._sorted_((function(a,b){
 return smalltalk.withContext(function($ctx4) {
return _st(_st(a)._selector()).__lt_eq(_st(b)._selector());
-}, function($ctx4) {$ctx4.fillBlock({a:a,b:b},$ctx1)})}));
-$6=(function(method){
-return smalltalk.withContext(function($ctx4) {
$7=_st(_st(method)._category())._match_(_st("^\x5c*").__comma(name));
-if(smalltalk.assert($7)){
+}, function($ctx4) {$ctx4.fillBlock({a:a,b:b},$ctx1)})})))._do_((function(method){
+return smalltalk.withContext(function($ctx4) {
$1=_st(_st(method)._category())._match_(_st("^\x5c*").__comma(name));
+if(smalltalk.assert($1)){
 return _st(self)._exportMethod_of_on_(method,aClass,aStream);
 };
-}, function($ctx4) {$ctx4.fillBlock({method:method},$ctx1)})});
-return _st($5)._do_($6);
-}, function($ctx3) {$ctx3.fillBlock({aClass:aClass},$ctx1)})});
-return _st($3)._do_($4);
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})});
-_st($1)._do_($2);
+}, function($ctx4) {$ctx4.fillBlock({method:method},$ctx1)})}));
+}, function($ctx3) {$ctx3.fillBlock({aClass:aClass},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"exportPackageExtensionsOf:on:",{package_:package_,aStream:aStream,name:name}, smalltalk.Exporter)})}
 }),
 smalltalk.Exporter);
@@ -336,20 +323,18 @@ smalltalk.method({
 selector: "classNameFor:",
 fn: function (aClass){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $2,$3,$5,$4,$1;
+return smalltalk.withContext(function($ctx1) { 
var $2,$3,$1;
 $2=_st(aClass)._isMetaclass();
-$3=(function(){
-return smalltalk.withContext(function($ctx2) {
return _st(_st(_st(aClass)._instanceClass())._name()).__comma(" class");
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-$4=(function(){
-return smalltalk.withContext(function($ctx2) {
$5=_st(aClass)._isNil();
-if(smalltalk.assert($5)){
-return "nil";
+if(smalltalk.assert($2)){
+$1=_st(_st(_st(aClass)._instanceClass())._name()).__comma(" class");
 } else {
-return _st(aClass)._name();
+$3=_st(aClass)._isNil();
+if(smalltalk.assert($3)){
+$1="nil";
+} else {
+$1=_st(aClass)._name();
+};
 };
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-$1=_st($2)._ifTrue_ifFalse_($3,$4);
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"classNameFor:",{aClass:aClass}, smalltalk.ChunkExporter)})}
 }),
@@ -466,16 +451,14 @@ selector: "exportMethodsOf:on:",
 fn: function (aClass,aStream){
 var self=this;
 var map;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$2;
+return smalltalk.withContext(function($ctx1) { 
var $1;
 map=_st((smalltalk.Dictionary || Dictionary))._new();
-$1=aClass;
-$2=(function(category,methods){
-return smalltalk.withContext(function($ctx2) {
$3=_st(category)._match_("^\x5c*");
-if(! smalltalk.assert($3)){
+_st(aClass)._protocolsDo_((function(category,methods){
+return smalltalk.withContext(function($ctx2) {
$1=_st(category)._match_("^\x5c*");
+if(! smalltalk.assert($1)){
 return _st(map)._at_put_(category,methods);
 };
-}, function($ctx2) {$ctx2.fillBlock({category:category,methods:methods},$ctx1)})});
-_st($1)._protocolsDo_($2);
+}, function($ctx2) {$ctx2.fillBlock({category:category,methods:methods},$ctx1)})}));
 _st(_st(_st(map)._keys())._sorted_((function(a,b){
 return smalltalk.withContext(function($ctx2) {
return _st(a).__lt_eq(b);
 }, function($ctx2) {$ctx2.fillBlock({a:a,b:b},$ctx1)})})))._do_((function(category){
@@ -509,22 +492,18 @@ selector: "exportPackageExtensionsOf:on:",
 fn: function (package_,aStream){
 var self=this;
 var name,map;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$5,$7,$6,$4,$2;
+return smalltalk.withContext(function($ctx1) { 
var $1;
 name=_st(package_)._name();
-$1=_st((smalltalk.Package || Package))._sortedClasses_(_st(_st((smalltalk.Smalltalk || Smalltalk))._current())._classes());
-$2=(function(each){
-return smalltalk.withContext(function($ctx2) {
$3=[each,_st(each)._class()];
-$4=(function(aClass){
+_st(_st((smalltalk.Package || Package))._sortedClasses_(_st(_st((smalltalk.Smalltalk || Smalltalk))._current())._classes()))._do_((function(each){
+return smalltalk.withContext(function($ctx2) {
return _st([each,_st(each)._class()])._do_((function(aClass){
 return smalltalk.withContext(function($ctx3) {
map=_st((smalltalk.Dictionary || Dictionary))._new();
 map;
-$5=aClass;
-$6=(function(category,methods){
-return smalltalk.withContext(function($ctx4) {
$7=_st(category)._match_(_st("^\x5c*").__comma(name));
-if(smalltalk.assert($7)){
+_st(aClass)._protocolsDo_((function(category,methods){
+return smalltalk.withContext(function($ctx4) {
$1=_st(category)._match_(_st("^\x5c*").__comma(name));
+if(smalltalk.assert($1)){
 return _st(map)._at_put_(category,methods);
 };
-}, function($ctx4) {$ctx4.fillBlock({category:category,methods:methods},$ctx1)})});
-_st($5)._protocolsDo_($6);
+}, function($ctx4) {$ctx4.fillBlock({category:category,methods:methods},$ctx1)})}));
 return _st(_st(_st(map)._keys())._sorted_((function(a,b){
 return smalltalk.withContext(function($ctx4) {
return _st(a).__lt_eq(b);
 }, function($ctx4) {$ctx4.fillBlock({a:a,b:b},$ctx1)})})))._do_((function(category){
@@ -533,10 +512,8 @@ return smalltalk.withContext(function($ctx4) {
methods=_st(map)._at_(category);
 methods;
 return _st(self)._exportMethods_category_of_on_(methods,category,aClass,aStream);
 }, function($ctx4) {$ctx4.fillBlock({category:category,methods:methods},$ctx1)})}));
-}, function($ctx3) {$ctx3.fillBlock({aClass:aClass},$ctx1)})});
-return _st($3)._do_($4);
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})});
-_st($1)._do_($2);
+}, function($ctx3) {$ctx3.fillBlock({aClass:aClass},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"exportPackageExtensionsOf:on:",{package_:package_,aStream:aStream,name:name,map:map}, smalltalk.ChunkExporter)})}
 }),
 smalltalk.ChunkExporter);
@@ -608,33 +585,29 @@ selector: "import:",
 fn: function (aStream){
 var self=this;
 var chunk,result,parser,lastEmpty;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$4,$6,$5,$2;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
 parser=_st((smalltalk.ChunkParser || ChunkParser))._on_(aStream);
 lastEmpty=false;
-$1=(function(){
+_st((function(){
 return smalltalk.withContext(function($ctx2) {
chunk=_st(parser)._nextChunk();
 chunk;
 return _st(chunk)._isNil();
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-$2=(function(){
-return smalltalk.withContext(function($ctx2) {
$3=_st(chunk)._isEmpty();
-$4=(function(){
-return smalltalk.withContext(function($ctx3) {
lastEmpty=true;
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}))._whileFalse_((function(){
+return smalltalk.withContext(function($ctx2) {
$1=_st(chunk)._isEmpty();
+if(smalltalk.assert($1)){
+lastEmpty=true;
 return lastEmpty;
-}, function($ctx3) {$ctx3.fillBlock({},$ctx1)})});
-$5=(function(){
-return smalltalk.withContext(function($ctx3) {
result=_st(_st((smalltalk.Compiler || Compiler))._new())._evaluateExpression_(chunk);
+} else {
+result=_st(_st((smalltalk.Compiler || Compiler))._new())._evaluateExpression_(chunk);
 result;
-$6=lastEmpty;
-if(smalltalk.assert($6)){
+$2=lastEmpty;
+if(smalltalk.assert($2)){
 lastEmpty=false;
 lastEmpty;
 return _st(result)._scanFrom_(parser);
 };
-}, function($ctx3) {$ctx3.fillBlock({},$ctx1)})});
-return _st($3)._ifTrue_ifFalse_($4,$5);
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-_st($1)._whileFalse_($2);
+};
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"import:",{aStream:aStream,chunk:chunk,result:result,parser:parser,lastEmpty:lastEmpty}, smalltalk.Importer)})}
 }),
 smalltalk.Importer);
@@ -664,23 +637,16 @@ selector: "loadPackage:prefix:",
 fn: function (packageName,aString){
 var self=this;
 var url;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2,$4,$5,$8,$7,$6,$3;
+return smalltalk.withContext(function($ctx1) { 
var $1;
 url=_st(_st(_st(_st("/").__comma(aString)).__comma("/js/")).__comma(packageName)).__comma(".js");
-$1=jQuery;
-$2=url;
-$4=_st("type").__minus_gt("GET");
-$5=_st("dataType").__minus_gt("script");
-$7=(function(jqXHR,textStatus){
-return smalltalk.withContext(function($ctx2) {
$8=_st(_st(jqXHR)._readyState()).__eq((4));
-if(smalltalk.assert($8)){
+_st(jQuery)._ajax_options_(url,smalltalk.HashedCollection._fromPairs_([_st("type").__minus_gt("GET"),_st("dataType").__minus_gt("script"),_st("complete").__minus_gt((function(jqXHR,textStatus){
+return smalltalk.withContext(function($ctx2) {
$1=_st(_st(jqXHR)._readyState()).__eq((4));
+if(smalltalk.assert($1)){
 return _st(self)._initializePackageNamed_prefix_(packageName,aString);
 };
-}, function($ctx2) {$ctx2.fillBlock({jqXHR:jqXHR,textStatus:textStatus},$ctx1)})});
-$6=_st("complete").__minus_gt($7);
-$3=smalltalk.HashedCollection._fromPairs_([$4,$5,$6,_st("error").__minus_gt((function(){
+}, function($ctx2) {$ctx2.fillBlock({jqXHR:jqXHR,textStatus:textStatus},$ctx1)})})),_st("error").__minus_gt((function(){
 return smalltalk.withContext(function($ctx2) {
return _st(window)._alert_(_st("Could not load package at:  ").__comma(url));
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}))]);
-_st($1)._ajax_options_($2,$3);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}))]));
 return self}, function($ctx1) {$ctx1.fill(self,"loadPackage:prefix:",{packageName:packageName,aString:aString,url:url}, smalltalk.PackageLoader)})}
 }),
 smalltalk.PackageLoader);

+ 78 - 112
js/Importer-Exporter.js

@@ -8,30 +8,27 @@ category: 'reading',
 fn: function (){
 var self=this;
 var char,result,chunk;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$5,$6,$4,$2;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3;
 var $early={};
 try {
 result=_st("")._writeStream();
-$1=(function(){
+_st((function(){
 return smalltalk.withContext(function($ctx2) {
char=_st(self["@stream"])._next();
 char;
 return _st(char)._notNil();
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-$2=(function(){
-return smalltalk.withContext(function($ctx2) {
$3=_st(char).__eq("!");
-$4=(function(){
-return smalltalk.withContext(function($ctx3) {
$5=_st(_st(self["@stream"])._peek()).__eq("!");
-if(smalltalk.assert($5)){
-return _st(self["@stream"])._next();
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}))._whileTrue_((function(){
+return smalltalk.withContext(function($ctx2) {
$1=_st(char).__eq("!");
+if(smalltalk.assert($1)){
+$2=_st(_st(self["@stream"])._peek()).__eq("!");
+if(smalltalk.assert($2)){
+_st(self["@stream"])._next();
 } else {
-$6=_st(_st(result)._contents())._trimBoth();
-throw $early=[$6];
+$3=_st(_st(result)._contents())._trimBoth();
+throw $early=[$3];
+};
 };
-}, function($ctx3) {$ctx3.fillBlock({},$ctx1)})});
-_st($3)._ifTrue_($4);
 return _st(result)._nextPut_(char);
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-_st($1)._whileTrue_($2);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 return nil;
 }
 catch(e) {if(e===$early)return e[0]; throw e}
@@ -87,20 +84,18 @@ selector: "classNameFor:",
 category: 'private',
 fn: function (aClass){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $2,$3,$5,$4,$1;
+return smalltalk.withContext(function($ctx1) { 
var $2,$3,$1;
 $2=_st(aClass)._isMetaclass();
-$3=(function(){
-return smalltalk.withContext(function($ctx2) {
return _st(_st(_st(aClass)._instanceClass())._name()).__comma(".klass");
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-$4=(function(){
-return smalltalk.withContext(function($ctx2) {
$5=_st(aClass)._isNil();
-if(smalltalk.assert($5)){
-return "nil";
+if(smalltalk.assert($2)){
+$1=_st(_st(_st(aClass)._instanceClass())._name()).__comma(".klass");
+} else {
+$3=_st(aClass)._isNil();
+if(smalltalk.assert($3)){
+$1="nil";
 } else {
-return _st(aClass)._name();
+$1=_st(aClass)._name();
+};
 };
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-$1=_st($2)._ifTrue_ifFalse_($3,$4);
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"classNameFor:",{aClass:aClass}, smalltalk.Exporter)})},
 args: ["aClass"],
@@ -276,17 +271,15 @@ selector: "exportMethodsOf:on:",
 category: 'private',
 fn: function (aClass,aStream){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$2;
-$1=_st(_st(_st(aClass)._methodDictionary())._values())._sorted_((function(a,b){
+return smalltalk.withContext(function($ctx1) { 
var $1;
+_st(_st(_st(_st(aClass)._methodDictionary())._values())._sorted_((function(a,b){
 return smalltalk.withContext(function($ctx2) {
return _st(_st(a)._selector()).__lt_eq(_st(b)._selector());
-}, function($ctx2) {$ctx2.fillBlock({a:a,b:b},$ctx1)})}));
-$2=(function(each){
-return smalltalk.withContext(function($ctx2) {
$3=_st(_st(each)._category())._match_("^\x5c*");
-if(! smalltalk.assert($3)){
+}, function($ctx2) {$ctx2.fillBlock({a:a,b:b},$ctx1)})})))._do_((function(each){
+return smalltalk.withContext(function($ctx2) {
$1=_st(_st(each)._category())._match_("^\x5c*");
+if(! smalltalk.assert($1)){
 return _st(self)._exportMethod_of_on_(each,aClass,aStream);
 };
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})});
-_st($1)._do_($2);
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
 _st(aStream)._lf();
 return self}, function($ctx1) {$ctx1.fill(self,"exportMethodsOf:on:",{aClass:aClass,aStream:aStream}, smalltalk.Exporter)})},
 args: ["aClass", "aStream"],
@@ -351,26 +344,20 @@ category: 'private',
 fn: function (package_,aStream){
 var self=this;
 var name;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$5,$7,$6,$4,$2;
+return smalltalk.withContext(function($ctx1) { 
var $1;
 name=_st(package_)._name();
-$1=_st((smalltalk.Package || Package))._sortedClasses_(_st(_st((smalltalk.Smalltalk || Smalltalk))._current())._classes());
-$2=(function(each){
-return smalltalk.withContext(function($ctx2) {
$3=[each,_st(each)._class()];
-$4=(function(aClass){
-return smalltalk.withContext(function($ctx3) {
$5=_st(_st(_st(aClass)._methodDictionary())._values())._sorted_((function(a,b){
+_st(_st((smalltalk.Package || Package))._sortedClasses_(_st(_st((smalltalk.Smalltalk || Smalltalk))._current())._classes()))._do_((function(each){
+return smalltalk.withContext(function($ctx2) {
return _st([each,_st(each)._class()])._do_((function(aClass){
+return smalltalk.withContext(function($ctx3) {
return _st(_st(_st(_st(aClass)._methodDictionary())._values())._sorted_((function(a,b){
 return smalltalk.withContext(function($ctx4) {
return _st(_st(a)._selector()).__lt_eq(_st(b)._selector());
-}, function($ctx4) {$ctx4.fillBlock({a:a,b:b},$ctx1)})}));
-$6=(function(method){
-return smalltalk.withContext(function($ctx4) {
$7=_st(_st(method)._category())._match_(_st("^\x5c*").__comma(name));
-if(smalltalk.assert($7)){
+}, function($ctx4) {$ctx4.fillBlock({a:a,b:b},$ctx1)})})))._do_((function(method){
+return smalltalk.withContext(function($ctx4) {
$1=_st(_st(method)._category())._match_(_st("^\x5c*").__comma(name));
+if(smalltalk.assert($1)){
 return _st(self)._exportMethod_of_on_(method,aClass,aStream);
 };
-}, function($ctx4) {$ctx4.fillBlock({method:method},$ctx1)})});
-return _st($5)._do_($6);
-}, function($ctx3) {$ctx3.fillBlock({aClass:aClass},$ctx1)})});
-return _st($3)._do_($4);
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})});
-_st($1)._do_($2);
+}, function($ctx4) {$ctx4.fillBlock({method:method},$ctx1)})}));
+}, function($ctx3) {$ctx3.fillBlock({aClass:aClass},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"exportPackageExtensionsOf:on:",{package_:package_,aStream:aStream,name:name}, smalltalk.Exporter)})},
 args: ["package", "aStream"],
 source: "exportPackageExtensionsOf: package on: aStream\x0a\x09\x22Issue #143: sort classes and methods alphabetically\x22\x0a\x0a\x09| name |\x0a\x09name := package name.\x0a\x09(Package sortedClasses: Smalltalk current classes) do: [:each |\x0a\x09\x09{each. each class} do: [:aClass | \x0a\x09\x09\x09((aClass methodDictionary values) sorted: [:a :b | a selector <= b selector]) do: [:method |\x0a\x09\x09\x09\x09(method category match: '^\x5c*', name) ifTrue: [\x0a\x09\x09\x09\x09\x09self exportMethod: method of: aClass on: aStream ]]]]",
@@ -407,20 +394,18 @@ selector: "classNameFor:",
 category: 'not yet classified',
 fn: function (aClass){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $2,$3,$5,$4,$1;
+return smalltalk.withContext(function($ctx1) { 
var $2,$3,$1;
 $2=_st(aClass)._isMetaclass();
-$3=(function(){
-return smalltalk.withContext(function($ctx2) {
return _st(_st(_st(aClass)._instanceClass())._name()).__comma(" class");
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-$4=(function(){
-return smalltalk.withContext(function($ctx2) {
$5=_st(aClass)._isNil();
-if(smalltalk.assert($5)){
-return "nil";
+if(smalltalk.assert($2)){
+$1=_st(_st(_st(aClass)._instanceClass())._name()).__comma(" class");
 } else {
-return _st(aClass)._name();
+$3=_st(aClass)._isNil();
+if(smalltalk.assert($3)){
+$1="nil";
+} else {
+$1=_st(aClass)._name();
+};
 };
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-$1=_st($2)._ifTrue_ifFalse_($3,$4);
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"classNameFor:",{aClass:aClass}, smalltalk.ChunkExporter)})},
 args: ["aClass"],
@@ -562,16 +547,14 @@ category: 'not yet classified',
 fn: function (aClass,aStream){
 var self=this;
 var map;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$2;
+return smalltalk.withContext(function($ctx1) { 
var $1;
 map=_st((smalltalk.Dictionary || Dictionary))._new();
-$1=aClass;
-$2=(function(category,methods){
-return smalltalk.withContext(function($ctx2) {
$3=_st(category)._match_("^\x5c*");
-if(! smalltalk.assert($3)){
+_st(aClass)._protocolsDo_((function(category,methods){
+return smalltalk.withContext(function($ctx2) {
$1=_st(category)._match_("^\x5c*");
+if(! smalltalk.assert($1)){
 return _st(map)._at_put_(category,methods);
 };
-}, function($ctx2) {$ctx2.fillBlock({category:category,methods:methods},$ctx1)})});
-_st($1)._protocolsDo_($2);
+}, function($ctx2) {$ctx2.fillBlock({category:category,methods:methods},$ctx1)})}));
 _st(_st(_st(map)._keys())._sorted_((function(a,b){
 return smalltalk.withContext(function($ctx2) {
return _st(a).__lt_eq(b);
 }, function($ctx2) {$ctx2.fillBlock({a:a,b:b},$ctx1)})})))._do_((function(category){
@@ -615,22 +598,18 @@ category: 'not yet classified',
 fn: function (package_,aStream){
 var self=this;
 var name,map;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$5,$7,$6,$4,$2;
+return smalltalk.withContext(function($ctx1) { 
var $1;
 name=_st(package_)._name();
-$1=_st((smalltalk.Package || Package))._sortedClasses_(_st(_st((smalltalk.Smalltalk || Smalltalk))._current())._classes());
-$2=(function(each){
-return smalltalk.withContext(function($ctx2) {
$3=[each,_st(each)._class()];
-$4=(function(aClass){
+_st(_st((smalltalk.Package || Package))._sortedClasses_(_st(_st((smalltalk.Smalltalk || Smalltalk))._current())._classes()))._do_((function(each){
+return smalltalk.withContext(function($ctx2) {
return _st([each,_st(each)._class()])._do_((function(aClass){
 return smalltalk.withContext(function($ctx3) {
map=_st((smalltalk.Dictionary || Dictionary))._new();
 map;
-$5=aClass;
-$6=(function(category,methods){
-return smalltalk.withContext(function($ctx4) {
$7=_st(category)._match_(_st("^\x5c*").__comma(name));
-if(smalltalk.assert($7)){
+_st(aClass)._protocolsDo_((function(category,methods){
+return smalltalk.withContext(function($ctx4) {
$1=_st(category)._match_(_st("^\x5c*").__comma(name));
+if(smalltalk.assert($1)){
 return _st(map)._at_put_(category,methods);
 };
-}, function($ctx4) {$ctx4.fillBlock({category:category,methods:methods},$ctx1)})});
-_st($5)._protocolsDo_($6);
+}, function($ctx4) {$ctx4.fillBlock({category:category,methods:methods},$ctx1)})}));
 return _st(_st(_st(map)._keys())._sorted_((function(a,b){
 return smalltalk.withContext(function($ctx4) {
return _st(a).__lt_eq(b);
 }, function($ctx4) {$ctx4.fillBlock({a:a,b:b},$ctx1)})})))._do_((function(category){
@@ -639,10 +618,8 @@ return smalltalk.withContext(function($ctx4) {
methods=_st(map)._at_(category);
 methods;
 return _st(self)._exportMethods_category_of_on_(methods,category,aClass,aStream);
 }, function($ctx4) {$ctx4.fillBlock({category:category,methods:methods},$ctx1)})}));
-}, function($ctx3) {$ctx3.fillBlock({aClass:aClass},$ctx1)})});
-return _st($3)._do_($4);
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})});
-_st($1)._do_($2);
+}, function($ctx3) {$ctx3.fillBlock({aClass:aClass},$ctx1)})}));
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"exportPackageExtensionsOf:on:",{package_:package_,aStream:aStream,name:name,map:map}, smalltalk.ChunkExporter)})},
 args: ["package", "aStream"],
 source: "exportPackageExtensionsOf: package on: aStream\x0a\x09\x22We need to override this one too since we need to group\x0a\x09all methods in a given protocol under a leading methodsFor: chunk\x0a\x09for that class.\x22\x0a\x0a\x09\x22Issue #143: sort protocol alphabetically\x22\x0a\x0a\x09| name map |\x0a\x09name := package name.\x0a\x09(Package sortedClasses: Smalltalk current classes) do: [:each |\x0a\x09\x09{each. each class} do: [:aClass |\x0a\x09\x09\x09map := Dictionary new.\x0a\x09\x09\x09aClass protocolsDo: [:category :methods | \x0a\x09\x09\x09\x09(category match: '^\x5c*', name) ifTrue: [ map at: category put: methods ]].\x0a\x09\x09\x09(map keys sorted: [:a :b | a <= b ]) do: [:category | | methods |\x0a\x09\x09\x09\x09methods := map at: category.\x09\x0a\x09\x09\x09\x09self exportMethods: methods category: category of: aClass on: aStream ]]]",
@@ -729,33 +706,29 @@ category: 'fileIn',
 fn: function (aStream){
 var self=this;
 var chunk,result,parser,lastEmpty;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$4,$6,$5,$2;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
 parser=_st((smalltalk.ChunkParser || ChunkParser))._on_(aStream);
 lastEmpty=false;
-$1=(function(){
+_st((function(){
 return smalltalk.withContext(function($ctx2) {
chunk=_st(parser)._nextChunk();
 chunk;
 return _st(chunk)._isNil();
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-$2=(function(){
-return smalltalk.withContext(function($ctx2) {
$3=_st(chunk)._isEmpty();
-$4=(function(){
-return smalltalk.withContext(function($ctx3) {
lastEmpty=true;
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}))._whileFalse_((function(){
+return smalltalk.withContext(function($ctx2) {
$1=_st(chunk)._isEmpty();
+if(smalltalk.assert($1)){
+lastEmpty=true;
 return lastEmpty;
-}, function($ctx3) {$ctx3.fillBlock({},$ctx1)})});
-$5=(function(){
-return smalltalk.withContext(function($ctx3) {
result=_st(_st((smalltalk.Compiler || Compiler))._new())._evaluateExpression_(chunk);
+} else {
+result=_st(_st((smalltalk.Compiler || Compiler))._new())._evaluateExpression_(chunk);
 result;
-$6=lastEmpty;
-if(smalltalk.assert($6)){
+$2=lastEmpty;
+if(smalltalk.assert($2)){
 lastEmpty=false;
 lastEmpty;
 return _st(result)._scanFrom_(parser);
 };
-}, function($ctx3) {$ctx3.fillBlock({},$ctx1)})});
-return _st($3)._ifTrue_ifFalse_($4,$5);
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-_st($1)._whileFalse_($2);
+};
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"import:",{aStream:aStream,chunk:chunk,result:result,parser:parser,lastEmpty:lastEmpty}, smalltalk.Importer)})},
 args: ["aStream"],
 source: "import: aStream\x0a    | chunk result parser lastEmpty |\x0a    parser := ChunkParser on: aStream.\x0a    lastEmpty := false.\x0a    [chunk := parser nextChunk.\x0a     chunk isNil] whileFalse: [\x0a        chunk isEmpty\x0a       \x09\x09ifTrue: [lastEmpty := true]\x0a       \x09\x09ifFalse: [\x0a        \x09\x09result := Compiler new evaluateExpression: chunk.\x0a        \x09\x09lastEmpty \x0a            \x09\x09\x09ifTrue: [\x0a                                  \x09lastEmpty := false.\x0a                                  \x09result scanFrom: parser]]]",
@@ -795,23 +768,16 @@ category: 'laoding',
 fn: function (packageName,aString){
 var self=this;
 var url;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2,$4,$5,$8,$7,$6,$3;
+return smalltalk.withContext(function($ctx1) { 
var $1;
 url=_st(_st(_st(_st("/").__comma(aString)).__comma("/js/")).__comma(packageName)).__comma(".js");
-$1=jQuery;
-$2=url;
-$4=_st("type").__minus_gt("GET");
-$5=_st("dataType").__minus_gt("script");
-$7=(function(jqXHR,textStatus){
-return smalltalk.withContext(function($ctx2) {
$8=_st(_st(jqXHR)._readyState()).__eq((4));
-if(smalltalk.assert($8)){
+_st(jQuery)._ajax_options_(url,smalltalk.HashedCollection._fromPairs_([_st("type").__minus_gt("GET"),_st("dataType").__minus_gt("script"),_st("complete").__minus_gt((function(jqXHR,textStatus){
+return smalltalk.withContext(function($ctx2) {
$1=_st(_st(jqXHR)._readyState()).__eq((4));
+if(smalltalk.assert($1)){
 return _st(self)._initializePackageNamed_prefix_(packageName,aString);
 };
-}, function($ctx2) {$ctx2.fillBlock({jqXHR:jqXHR,textStatus:textStatus},$ctx1)})});
-$6=_st("complete").__minus_gt($7);
-$3=smalltalk.HashedCollection._fromPairs_([$4,$5,$6,_st("error").__minus_gt((function(){
+}, function($ctx2) {$ctx2.fillBlock({jqXHR:jqXHR,textStatus:textStatus},$ctx1)})})),_st("error").__minus_gt((function(){
 return smalltalk.withContext(function($ctx2) {
return _st(window)._alert_(_st("Could not load package at:  ").__comma(url));
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}))]);
-_st($1)._ajax_options_($2,$3);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}))]));
 return self}, function($ctx1) {$ctx1.fill(self,"loadPackage:prefix:",{packageName:packageName,aString:aString,url:url}, smalltalk.PackageLoader)})},
 args: ["packageName", "aString"],
 source: "loadPackage: packageName prefix: aString\x09\x0a\x09| url |\x0a    url := '/', aString, '/js/', packageName, '.js'.\x0a\x09jQuery \x0a\x09\x09ajax: url\x0a        options: #{\x0a\x09\x09\x09'type' -> 'GET'.\x0a\x09\x09\x09'dataType' -> 'script'.\x0a    \x09\x09'complete' -> [ :jqXHR :textStatus | \x0a\x09\x09\x09\x09jqXHR readyState = 4 \x0a                \x09ifTrue: [ self initializePackageNamed: packageName prefix: aString ] ].\x0a\x09\x09\x09'error' -> [ window alert: 'Could not load package at:  ', url ]\x0a\x09\x09}",

+ 28 - 25
js/Kernel-Classes.deploy.js

@@ -271,23 +271,21 @@ selector: "lookupSelector:",
 fn: function (selector){
 var self=this;
 var lookupClass;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$4,$2;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
 var $early={};
 try {
 lookupClass=self;
-$1=(function(){
+_st((function(){
 return smalltalk.withContext(function($ctx2) {
return _st(lookupClass).__eq(nil);
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-$2=(function(){
-return smalltalk.withContext(function($ctx2) {
$3=_st(lookupClass)._includesSelector_(selector);
-if(smalltalk.assert($3)){
-$4=_st(lookupClass)._methodAt_(selector);
-throw $early=[$4];
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}))._whileFalse_((function(){
+return smalltalk.withContext(function($ctx2) {
$1=_st(lookupClass)._includesSelector_(selector);
+if(smalltalk.assert($1)){
+$2=_st(lookupClass)._methodAt_(selector);
+throw $early=[$2];
 };
 lookupClass=_st(lookupClass)._superclass();
 return lookupClass;
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-_st($1)._whileFalse_($2);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 return nil;
 }
 catch(e) {if(e===$early)return e[0]; throw e}
@@ -856,17 +854,22 @@ smalltalk.method({
 selector: "addSubclassOf:named:instanceVariableNames:package:",
 fn: function (aClass,aString,aCollection,packageName){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3;
-$1=_st(_st((smalltalk.Smalltalk || Smalltalk))._current())._at_(aString);
+var theClass;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3,$4;
+theClass=_st(_st((smalltalk.Smalltalk || Smalltalk))._current())._at_(aString);
+$1=theClass;
 if(($receiver = $1) == nil || $receiver == undefined){
 $1;
 } else {
-$2=_st(self)._migrateClassNamed_superclass_instanceVariableNames_package_(aString,aClass,aCollection,packageName);
-return $2;
-};
-$3=_st(self)._basicAddSubclassOf_named_instanceVariableNames_package_(aClass,aString,aCollection,packageName);
+$2=_st(_st(theClass)._superclass()).__eq_eq(aClass);
+if(! smalltalk.assert($2)){
+$3=_st(self)._migrateClassNamed_superclass_instanceVariableNames_package_(aString,aClass,aCollection,packageName);
 return $3;
-}, function($ctx1) {$ctx1.fill(self,"addSubclassOf:named:instanceVariableNames:package:",{aClass:aClass,aString:aString,aCollection:aCollection,packageName:packageName}, smalltalk.ClassBuilder)})}
+};
+};
+$4=_st(self)._basicAddSubclassOf_named_instanceVariableNames_package_(aClass,aString,aCollection,packageName);
+return $4;
+}, function($ctx1) {$ctx1.fill(self,"addSubclassOf:named:instanceVariableNames:package:",{aClass:aClass,aString:aString,aCollection:aCollection,packageName:packageName,theClass:theClass}, smalltalk.ClassBuilder)})}
 }),
 smalltalk.ClassBuilder);
 
@@ -1026,7 +1029,8 @@ smalltalk.method({
 selector: "migrateClass:superclass:",
 fn: function (aClass,anotherClass){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
_st(self)._migrateClassNamed_superclass_instanceVariableNames_package_(_st(aClass)._name(),anotherClass,_st(aClass)._instanceVariableNames(),_st(_st(aClass)._package())._name());
+return smalltalk.withContext(function($ctx1) { 
_st(console)._log_(_st(aClass)._name());
+_st(self)._migrateClassNamed_superclass_instanceVariableNames_package_(_st(aClass)._name(),anotherClass,_st(aClass)._instanceVariableNames(),_st(_st(aClass)._package())._name());
 return self}, function($ctx1) {$ctx1.fill(self,"migrateClass:superclass:",{aClass:aClass,anotherClass:anotherClass}, smalltalk.ClassBuilder)})}
 }),
 smalltalk.ClassBuilder);
@@ -1039,6 +1043,7 @@ fn: function (aString,aClass,aCollection,packageName){
 var self=this;
 var oldClass,newClass;
 return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3;
+_st(console)._log_(_st("*** MIGRATING ").__comma(aString));
 oldClass=_st(_st((smalltalk.Smalltalk || Smalltalk))._current())._at_(aString);
 _st(self)._basicRenameClass_to_(oldClass,_st("Old").__comma(aString));
 newClass=_st(self)._addSubclassOf_named_instanceVariableNames_package_(aClass,aString,aCollection,packageName);
@@ -1250,19 +1255,17 @@ selector: "getNodesFrom:",
 fn: function (aCollection){
 var self=this;
 var children,others;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$2;
+return smalltalk.withContext(function($ctx1) { 
var $1;
 children=[];
 others=[];
-$1=aCollection;
-$2=(function(each){
-return smalltalk.withContext(function($ctx2) {
$3=_st(_st(each)._superclass()).__eq(_st(self)._theClass());
-if(smalltalk.assert($3)){
+_st(aCollection)._do_((function(each){
+return smalltalk.withContext(function($ctx2) {
$1=_st(_st(each)._superclass()).__eq(_st(self)._theClass());
+if(smalltalk.assert($1)){
 return _st(children)._add_(each);
 } else {
 return _st(others)._add_(each);
 };
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})});
-_st($1)._do_($2);
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
 self["@nodes"]=_st(children)._collect_((function(each){
 return smalltalk.withContext(function($ctx2) {
return _st((smalltalk.ClassSorterNode || ClassSorterNode))._on_classes_level_(each,others,_st(_st(self)._level()).__plus((1)));
 }, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));

+ 34 - 31
js/Kernel-Classes.js

@@ -363,23 +363,21 @@ category: 'accessing',
 fn: function (selector){
 var self=this;
 var lookupClass;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$4,$2;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
 var $early={};
 try {
 lookupClass=self;
-$1=(function(){
+_st((function(){
 return smalltalk.withContext(function($ctx2) {
return _st(lookupClass).__eq(nil);
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-$2=(function(){
-return smalltalk.withContext(function($ctx2) {
$3=_st(lookupClass)._includesSelector_(selector);
-if(smalltalk.assert($3)){
-$4=_st(lookupClass)._methodAt_(selector);
-throw $early=[$4];
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}))._whileFalse_((function(){
+return smalltalk.withContext(function($ctx2) {
$1=_st(lookupClass)._includesSelector_(selector);
+if(smalltalk.assert($1)){
+$2=_st(lookupClass)._methodAt_(selector);
+throw $early=[$2];
 };
 lookupClass=_st(lookupClass)._superclass();
 return lookupClass;
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-_st($1)._whileFalse_($2);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 return nil;
 }
 catch(e) {if(e===$early)return e[0]; throw e}
@@ -1151,20 +1149,25 @@ selector: "addSubclassOf:named:instanceVariableNames:package:",
 category: 'private',
 fn: function (aClass,aString,aCollection,packageName){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3;
-$1=_st(_st((smalltalk.Smalltalk || Smalltalk))._current())._at_(aString);
+var theClass;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3,$4;
+theClass=_st(_st((smalltalk.Smalltalk || Smalltalk))._current())._at_(aString);
+$1=theClass;
 if(($receiver = $1) == nil || $receiver == undefined){
 $1;
 } else {
-$2=_st(self)._migrateClassNamed_superclass_instanceVariableNames_package_(aString,aClass,aCollection,packageName);
-return $2;
-};
-$3=_st(self)._basicAddSubclassOf_named_instanceVariableNames_package_(aClass,aString,aCollection,packageName);
+$2=_st(_st(theClass)._superclass()).__eq_eq(aClass);
+if(! smalltalk.assert($2)){
+$3=_st(self)._migrateClassNamed_superclass_instanceVariableNames_package_(aString,aClass,aCollection,packageName);
 return $3;
-}, function($ctx1) {$ctx1.fill(self,"addSubclassOf:named:instanceVariableNames:package:",{aClass:aClass,aString:aString,aCollection:aCollection,packageName:packageName}, smalltalk.ClassBuilder)})},
+};
+};
+$4=_st(self)._basicAddSubclassOf_named_instanceVariableNames_package_(aClass,aString,aCollection,packageName);
+return $4;
+}, function($ctx1) {$ctx1.fill(self,"addSubclassOf:named:instanceVariableNames:package:",{aClass:aClass,aString:aString,aCollection:aCollection,packageName:packageName,theClass:theClass}, smalltalk.ClassBuilder)})},
 args: ["aClass", "aString", "aCollection", "packageName"],
-source: "addSubclassOf: aClass named: aString instanceVariableNames: aCollection package: packageName\x0a\x09\x0a    (Smalltalk current at: aString) ifNotNil: [ \x0a    \x09^ self \x0a        \x09migrateClassNamed: aString \x0a            superclass: aClass \x0a            instanceVariableNames: aCollection \x0a            package: packageName ].\x0a\x0a\x09^ self \x0a    \x09basicAddSubclassOf: aClass \x0a        named: aString \x0a        instanceVariableNames: aCollection \x0a        package: packageName",
-messageSends: ["ifNotNil:", "migrateClassNamed:superclass:instanceVariableNames:package:", "at:", "current", "basicAddSubclassOf:named:instanceVariableNames:package:"],
+source: "addSubclassOf: aClass named: aString instanceVariableNames: aCollection package: packageName\x0a    | theClass |\x0a    \x0a    theClass := Smalltalk current at: aString.\x0a    \x0a   \x09theClass ifNotNil: [ \x0a    \x09theClass superclass == aClass ifFalse: [\x0a    \x09\x09^ self \x0a        \x09\x09migrateClassNamed: aString \x0a           \x09 \x09superclass: aClass \x0a           \x09 \x09instanceVariableNames: aCollection \x0a            \x09package: packageName ] ].\x0a\x0a\x09^ self \x0a    \x09basicAddSubclassOf: aClass \x0a        named: aString \x0a        instanceVariableNames: aCollection \x0a        package: packageName",
+messageSends: ["at:", "current", "ifNotNil:", "ifFalse:", "migrateClassNamed:superclass:instanceVariableNames:package:", "==", "superclass", "basicAddSubclassOf:named:instanceVariableNames:package:"],
 referencedClasses: ["Smalltalk"]
 }),
 smalltalk.ClassBuilder);
@@ -1376,11 +1379,12 @@ selector: "migrateClass:superclass:",
 category: 'private',
 fn: function (aClass,anotherClass){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
_st(self)._migrateClassNamed_superclass_instanceVariableNames_package_(_st(aClass)._name(),anotherClass,_st(aClass)._instanceVariableNames(),_st(_st(aClass)._package())._name());
+return smalltalk.withContext(function($ctx1) { 
_st(console)._log_(_st(aClass)._name());
+_st(self)._migrateClassNamed_superclass_instanceVariableNames_package_(_st(aClass)._name(),anotherClass,_st(aClass)._instanceVariableNames(),_st(_st(aClass)._package())._name());
 return self}, function($ctx1) {$ctx1.fill(self,"migrateClass:superclass:",{aClass:aClass,anotherClass:anotherClass}, smalltalk.ClassBuilder)})},
 args: ["aClass", "anotherClass"],
-source: "migrateClass: aClass superclass: anotherClass\x0a\x09self \x0a    \x09migrateClassNamed: aClass name\x0a        superclass: anotherClass\x0a        instanceVariableNames: aClass instanceVariableNames\x0a        package: aClass package name",
-messageSends: ["migrateClassNamed:superclass:instanceVariableNames:package:", "name", "instanceVariableNames", "package"],
+source: "migrateClass: aClass superclass: anotherClass\x0a\x09console log: aClass name.\x0a\x09self \x0a    \x09migrateClassNamed: aClass name\x0a        superclass: anotherClass\x0a        instanceVariableNames: aClass instanceVariableNames\x0a        package: aClass package name",
+messageSends: ["log:", "name", "migrateClassNamed:superclass:instanceVariableNames:package:", "instanceVariableNames", "package"],
 referencedClasses: []
 }),
 smalltalk.ClassBuilder);
@@ -1394,6 +1398,7 @@ fn: function (aString,aClass,aCollection,packageName){
 var self=this;
 var oldClass,newClass;
 return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3;
+_st(console)._log_(_st("*** MIGRATING ").__comma(aString));
 oldClass=_st(_st((smalltalk.Smalltalk || Smalltalk))._current())._at_(aString);
 _st(self)._basicRenameClass_to_(oldClass,_st("Old").__comma(aString));
 newClass=_st(self)._addSubclassOf_named_instanceVariableNames_package_(aClass,aString,aCollection,packageName);
@@ -1414,8 +1419,8 @@ $3=newClass;
 return $3;
 }, function($ctx1) {$ctx1.fill(self,"migrateClassNamed:superclass:instanceVariableNames:package:",{aString:aString,aClass:aClass,aCollection:aCollection,packageName:packageName,oldClass:oldClass,newClass:newClass}, smalltalk.ClassBuilder)})},
 args: ["aString", "aClass", "aCollection", "packageName"],
-source: "migrateClassNamed: aString superclass: aClass instanceVariableNames: aCollection package: packageName\x0a\x09| oldClass newClass |\x0a    \x0a    oldClass := Smalltalk current at: aString.\x0a    \x0a    \x22Rename the old class for existing instances\x22\x0a\x09self basicRenameClass: oldClass to: 'Old', aString.\x0a    \x0a    newClass := self \x0a\x09\x09addSubclassOf: aClass\x0a\x09\x09named: aString \x0a\x09\x09instanceVariableNames: aCollection\x0a\x09\x09package: packageName.\x0a\x0a\x09oldClass subclasses do: [ :each |\x0a    \x09self migrateClass: each superclass: newClass ].\x0a\x0a    [ self copyClass: oldClass to: newClass ] \x0a    \x09on: Error\x0a        do: [ :exception |\x0a        \x09self \x0a            \x09basicRemoveClass: newClass;\x0a            \x09basicRenameClass: oldClass to: aString.\x0a            exception signal ].\x0a            \x0a    self basicRemoveClass: oldClass.\x0a\x09^newClass",
-messageSends: ["at:", "current", "basicRenameClass:to:", ",", "addSubclassOf:named:instanceVariableNames:package:", "do:", "migrateClass:superclass:", "subclasses", "on:do:", "basicRemoveClass:", "signal", "copyClass:to:"],
+source: "migrateClassNamed: aString superclass: aClass instanceVariableNames: aCollection package: packageName\x0a\x09| oldClass newClass |\x0a    \x0a    console log: '*** MIGRATING ', aString.\x0a    \x0a    oldClass := Smalltalk current at: aString.\x0a    \x0a    \x22Rename the old class for existing instances\x22\x0a\x09self basicRenameClass: oldClass to: 'Old', aString.\x0a    \x0a    newClass := self \x0a\x09\x09addSubclassOf: aClass\x0a\x09\x09named: aString \x0a\x09\x09instanceVariableNames: aCollection\x0a\x09\x09package: packageName.\x0a\x0a\x09oldClass subclasses do: [ :each |\x0a    \x09self migrateClass: each superclass: newClass ].\x0a\x0a    [ self copyClass: oldClass to: newClass ] \x0a    \x09on: Error\x0a        do: [ :exception |\x0a        \x09self \x0a            \x09basicRemoveClass: newClass;\x0a            \x09basicRenameClass: oldClass to: aString.\x0a            exception signal ].\x0a            \x0a    self basicRemoveClass: oldClass.\x0a\x09^newClass",
+messageSends: ["log:", ",", "at:", "current", "basicRenameClass:to:", "addSubclassOf:named:instanceVariableNames:package:", "do:", "migrateClass:superclass:", "subclasses", "on:do:", "basicRemoveClass:", "signal", "copyClass:to:"],
 referencedClasses: ["Smalltalk", "Error"]
 }),
 smalltalk.ClassBuilder);
@@ -1672,19 +1677,17 @@ category: 'accessing',
 fn: function (aCollection){
 var self=this;
 var children,others;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$2;
+return smalltalk.withContext(function($ctx1) { 
var $1;
 children=[];
 others=[];
-$1=aCollection;
-$2=(function(each){
-return smalltalk.withContext(function($ctx2) {
$3=_st(_st(each)._superclass()).__eq(_st(self)._theClass());
-if(smalltalk.assert($3)){
+_st(aCollection)._do_((function(each){
+return smalltalk.withContext(function($ctx2) {
$1=_st(_st(each)._superclass()).__eq(_st(self)._theClass());
+if(smalltalk.assert($1)){
 return _st(children)._add_(each);
 } else {
 return _st(others)._add_(each);
 };
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})});
-_st($1)._do_($2);
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
 self["@nodes"]=_st(children)._collect_((function(each){
 return smalltalk.withContext(function($ctx2) {
return _st((smalltalk.ClassSorterNode || ClassSorterNode))._on_classes_level_(each,others,_st(_st(self)._level()).__plus((1)));
 }, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));

File diff suppressed because it is too large
+ 144 - 152
js/Kernel-Collections.deploy.js


File diff suppressed because it is too large
+ 144 - 152
js/Kernel-Collections.js


+ 9 - 8
js/Kernel-Exceptions.deploy.js

@@ -357,17 +357,18 @@ smalltalk.method({
 selector: "logErrorContext:",
 fn: function (aContext){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$2;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
 $1=aContext;
-$2=(function(){
-return smalltalk.withContext(function($ctx2) {
$3=_st(aContext)._home();
-if(($receiver = $3) == nil || $receiver == undefined){
-return $3;
+if(($receiver = $1) == nil || $receiver == undefined){
+$1;
+} else {
+$2=_st(aContext)._home();
+if(($receiver = $2) == nil || $receiver == undefined){
+$2;
 } else {
-return _st(self)._logContext_(_st(aContext)._home());
+_st(self)._logContext_(_st(aContext)._home());
+};
 };
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-_st($1)._ifNotNil_($2);
 return self}, function($ctx1) {$ctx1.fill(self,"logErrorContext:",{aContext:aContext}, smalltalk.ErrorHandler)})}
 }),
 smalltalk.ErrorHandler);

+ 9 - 8
js/Kernel-Exceptions.js

@@ -498,17 +498,18 @@ selector: "logErrorContext:",
 category: 'private',
 fn: function (aContext){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$2;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
 $1=aContext;
-$2=(function(){
-return smalltalk.withContext(function($ctx2) {
$3=_st(aContext)._home();
-if(($receiver = $3) == nil || $receiver == undefined){
-return $3;
+if(($receiver = $1) == nil || $receiver == undefined){
+$1;
+} else {
+$2=_st(aContext)._home();
+if(($receiver = $2) == nil || $receiver == undefined){
+$2;
 } else {
-return _st(self)._logContext_(_st(aContext)._home());
+_st(self)._logContext_(_st(aContext)._home());
+};
 };
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-_st($1)._ifNotNil_($2);
 return self}, function($ctx1) {$ctx1.fill(self,"logErrorContext:",{aContext:aContext}, smalltalk.ErrorHandler)})},
 args: ["aContext"],
 source: "logErrorContext: aContext\x0a\x09aContext ifNotNil: [\x0a\x09\x09aContext home ifNotNil: [\x0a\x09\x09\x09self logContext: aContext home]]",

+ 5 - 5
js/Kernel-Methods.js

@@ -1016,7 +1016,7 @@ smalltalk.Message.klass);
 
 
 smalltalk.addClass('MethodContext', smalltalk.Object, [], 'Kernel-Methods');
-smalltalk.MethodContext.comment="MethodContext holds all the dynamic state associated with the execution of either a method activation resulting from a message send. That is used to build the call stack while debugging.\x0a  \x0aMethodContext instances are JavaScript `SmalltalkMethodContext` objects defined in boot.js "
+smalltalk.MethodContext.comment="MethodContext holds all the dynamic state associated with the execution of either a method activation resulting from a message send. That is used to build the call stack while debugging.\x0a  \x0aMethodContext instances are JavaScript `SmalltalkMethodContext` objects defined in boot.js"
 smalltalk.addMethod(
 "_asString",
 smalltalk.method({
@@ -1256,7 +1256,7 @@ return smalltalk.withContext(function($ctx1) {
 	;
 return self}, function($ctx1) {$ctx1.fill(self,"constructor:",{aString:aString}, smalltalk.NativeFunction.klass)})},
 args: ["aString"],
-source: "constructor: aString\x0a\x09<\x0a    \x09var native=eval(aString); \x0a        return new native();\x0a\x09>\x0a",
+source: "constructor: aString\x0a\x09<\x0a    \x09var native=eval(aString); \x0a        return new native();\x0a\x09>",
 messageSends: [],
 referencedClasses: []
 }),
@@ -1275,7 +1275,7 @@ return smalltalk.withContext(function($ctx1) {
 	;
 return self}, function($ctx1) {$ctx1.fill(self,"constructor:value:",{aString:aString,anObject:anObject}, smalltalk.NativeFunction.klass)})},
 args: ["aString", "anObject"],
-source: "constructor: aString value:anObject\x0a\x09<\x0a    \x09var native=eval(aString); \x0a        return new native(anObject);\x0a\x09>\x0a",
+source: "constructor: aString value:anObject\x0a\x09<\x0a    \x09var native=eval(aString); \x0a        return new native(anObject);\x0a\x09>",
 messageSends: [],
 referencedClasses: []
 }),
@@ -1294,7 +1294,7 @@ return smalltalk.withContext(function($ctx1) {
 	;
 return self}, function($ctx1) {$ctx1.fill(self,"constructor:value:value:",{aString:aString,anObject:anObject,anObject2:anObject2}, smalltalk.NativeFunction.klass)})},
 args: ["aString", "anObject", "anObject2"],
-source: "constructor: aString value:anObject value: anObject2\x0a\x09<\x0a    \x09var native=eval(aString); \x0a        return new native(anObject,anObject2);\x0a\x09>\x0a",
+source: "constructor: aString value:anObject value: anObject2\x0a\x09<\x0a    \x09var native=eval(aString); \x0a        return new native(anObject,anObject2);\x0a\x09>",
 messageSends: [],
 referencedClasses: []
 }),
@@ -1313,7 +1313,7 @@ return smalltalk.withContext(function($ctx1) {
 	;
 return self}, function($ctx1) {$ctx1.fill(self,"constructor:value:value:value:",{aString:aString,anObject:anObject,anObject2:anObject2,anObject3:anObject3}, smalltalk.NativeFunction.klass)})},
 args: ["aString", "anObject", "anObject2", "anObject3"],
-source: "constructor: aString value:anObject value: anObject2 value:anObject3\x0a\x09<\x0a    \x09var native=eval(aString); \x0a        return new native(anObject,anObject2, anObject3);\x0a\x09>\x0a",
+source: "constructor: aString value:anObject value: anObject2 value:anObject3\x0a\x09<\x0a    \x09var native=eval(aString); \x0a        return new native(anObject,anObject2, anObject3);\x0a\x09>",
 messageSends: [],
 referencedClasses: []
 }),

+ 12 - 16
js/Kernel-Objects.deploy.js

@@ -2724,19 +2724,17 @@ selector: "sortedClasses:",
 fn: function (classes){
 var self=this;
 var children,others,nodes,expandedClasses;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$2,$4;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
 children=[];
 others=[];
-$1=classes;
-$2=(function(each){
-return smalltalk.withContext(function($ctx2) {
$3=_st(classes)._includes_(_st(each)._superclass());
-if(smalltalk.assert($3)){
+_st(classes)._do_((function(each){
+return smalltalk.withContext(function($ctx2) {
$1=_st(classes)._includes_(_st(each)._superclass());
+if(smalltalk.assert($1)){
 return _st(others)._add_(each);
 } else {
 return _st(children)._add_(each);
 };
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})});
-_st($1)._do_($2);
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
 nodes=_st(children)._collect_((function(each){
 return smalltalk.withContext(function($ctx2) {
return _st((smalltalk.ClassSorterNode || ClassSorterNode))._on_classes_level_(each,others,(0));
 }, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
@@ -2747,8 +2745,8 @@ expandedClasses=_st((smalltalk.Array || Array))._new();
 _st(nodes)._do_((function(aNode){
 return smalltalk.withContext(function($ctx2) {
return _st(aNode)._traverseClassesWith_(expandedClasses);
 }, function($ctx2) {$ctx2.fillBlock({aNode:aNode},$ctx1)})}));
-$4=expandedClasses;
-return $4;
+$2=expandedClasses;
+return $2;
 }, function($ctx1) {$ctx1.fill(self,"sortedClasses:",{classes:classes,children:children,others:others,nodes:nodes,expandedClasses:expandedClasses}, smalltalk.Package.klass)})}
 }),
 smalltalk.Package.klass);
@@ -2841,19 +2839,17 @@ smalltalk.method({
 selector: "printString",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $2,$4,$3,$1;
-$2=(smalltalk.String || String);
-$3=(function(stream){
+return smalltalk.withContext(function($ctx1) { 
var $2,$1;
+$1=_st((smalltalk.String || String))._streamContents_((function(stream){
 return smalltalk.withContext(function($ctx2) {
_st(stream)._nextPutAll_(_st(_st(self["@x"])._printString()).__comma("@"));
-$4=_st(_st(self["@y"])._notNil())._and_((function(){
+$2=_st(_st(self["@y"])._notNil())._and_((function(){
 return smalltalk.withContext(function($ctx3) {
return _st(self["@y"])._negative();
 }, function($ctx3) {$ctx3.fillBlock({},$ctx1)})}));
-if(smalltalk.assert($4)){
+if(smalltalk.assert($2)){
 _st(stream)._space();
 };
 return _st(stream)._nextPutAll_(_st(self["@y"])._printString());
-}, function($ctx2) {$ctx2.fillBlock({stream:stream},$ctx1)})});
-$1=_st($2)._streamContents_($3);
+}, function($ctx2) {$ctx2.fillBlock({stream:stream},$ctx1)})}));
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"printString",{}, smalltalk.Point)})}
 }),

+ 12 - 16
js/Kernel-Objects.js

@@ -3766,19 +3766,17 @@ category: 'sorting',
 fn: function (classes){
 var self=this;
 var children,others,nodes,expandedClasses;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$2,$4;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
 children=[];
 others=[];
-$1=classes;
-$2=(function(each){
-return smalltalk.withContext(function($ctx2) {
$3=_st(classes)._includes_(_st(each)._superclass());
-if(smalltalk.assert($3)){
+_st(classes)._do_((function(each){
+return smalltalk.withContext(function($ctx2) {
$1=_st(classes)._includes_(_st(each)._superclass());
+if(smalltalk.assert($1)){
 return _st(others)._add_(each);
 } else {
 return _st(children)._add_(each);
 };
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})});
-_st($1)._do_($2);
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
 nodes=_st(children)._collect_((function(each){
 return smalltalk.withContext(function($ctx2) {
return _st((smalltalk.ClassSorterNode || ClassSorterNode))._on_classes_level_(each,others,(0));
 }, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
@@ -3789,8 +3787,8 @@ expandedClasses=_st((smalltalk.Array || Array))._new();
 _st(nodes)._do_((function(aNode){
 return smalltalk.withContext(function($ctx2) {
return _st(aNode)._traverseClassesWith_(expandedClasses);
 }, function($ctx2) {$ctx2.fillBlock({aNode:aNode},$ctx1)})}));
-$4=expandedClasses;
-return $4;
+$2=expandedClasses;
+return $2;
 }, function($ctx1) {$ctx1.fill(self,"sortedClasses:",{classes:classes,children:children,others:others,nodes:nodes,expandedClasses:expandedClasses}, smalltalk.Package.klass)})},
 args: ["classes"],
 source: "sortedClasses: classes\x0a\x09\x22Answer classes, sorted by superclass/subclasses and by class name for common subclasses (Issue #143)\x22\x0a\x0a\x09| children others nodes expandedClasses |\x0a\x09children := #().\x0a\x09others := #().\x0a\x09classes do: [:each |\x0a\x09\x09(classes includes: each superclass)\x0a\x09\x09\x09ifFalse: [children add: each]\x0a\x09\x09\x09ifTrue: [others add: each]].\x0a\x09nodes := children collect: [:each |\x0a\x09\x09ClassSorterNode on: each classes: others level: 0].\x0a\x09nodes := nodes sorted: [:a :b | a theClass name <= b theClass name ].\x0a\x09expandedClasses := Array new.\x0a\x09nodes do: [:aNode |\x0a\x09\x09aNode traverseClassesWith: expandedClasses].\x0a\x09^expandedClasses",
@@ -3919,19 +3917,17 @@ selector: "printString",
 category: 'printing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $2,$4,$3,$1;
-$2=(smalltalk.String || String);
-$3=(function(stream){
+return smalltalk.withContext(function($ctx1) { 
var $2,$1;
+$1=_st((smalltalk.String || String))._streamContents_((function(stream){
 return smalltalk.withContext(function($ctx2) {
_st(stream)._nextPutAll_(_st(_st(self["@x"])._printString()).__comma("@"));
-$4=_st(_st(self["@y"])._notNil())._and_((function(){
+$2=_st(_st(self["@y"])._notNil())._and_((function(){
 return smalltalk.withContext(function($ctx3) {
return _st(self["@y"])._negative();
 }, function($ctx3) {$ctx3.fillBlock({},$ctx1)})}));
-if(smalltalk.assert($4)){
+if(smalltalk.assert($2)){
 _st(stream)._space();
 };
 return _st(stream)._nextPutAll_(_st(self["@y"])._printString());
-}, function($ctx2) {$ctx2.fillBlock({stream:stream},$ctx1)})});
-$1=_st($2)._streamContents_($3);
+}, function($ctx2) {$ctx2.fillBlock({stream:stream},$ctx1)})}));
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"printString",{}, smalltalk.Point)})},
 args: [],

File diff suppressed because it is too large
+ 122 - 125
js/Kernel-Tests.js


+ 23 - 28
js/SUnit.deploy.js

@@ -408,29 +408,27 @@ selector: "execute:",
 fn: function (aBlock){
 var self=this;
 var failed;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$4,$2;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
 _st(self["@testCase"])._context_(self);
-$1=(function(){
+_st((function(){
 return smalltalk.withContext(function($ctx2) {
failed=true;
 failed;
 _st(aBlock)._value();
 failed=false;
 return failed;
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-$2=(function(){
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}))._ensure_((function(){
 return smalltalk.withContext(function($ctx2) {
_st(self["@testCase"])._context_(nil);
-$3=_st(failed)._and_((function(){
+$1=_st(failed)._and_((function(){
 return smalltalk.withContext(function($ctx3) {
return _st(self["@testCase"])._isAsync();
 }, function($ctx3) {$ctx3.fillBlock({},$ctx1)})}));
-if(smalltalk.assert($3)){
+if(smalltalk.assert($1)){
 _st(self["@testCase"])._finished();
 };
-$4=_st(self["@testCase"])._isAsync();
-if(! smalltalk.assert($4)){
+$2=_st(self["@testCase"])._isAsync();
+if(! smalltalk.assert($2)){
 return _st(self["@testCase"])._tearDown();
 };
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-_st($1)._ensure_($2);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"execute:",{aBlock:aBlock,failed:failed}, smalltalk.TestContext)})}
 }),
 smalltalk.TestContext);
@@ -485,20 +483,18 @@ smalltalk.method({
 selector: "execute:",
 fn: function (aBlock){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$2;
-$1=(function(){
+return smalltalk.withContext(function($ctx1) { 
var $1;
+_st((function(){
 return smalltalk.withContext(function($ctx2) {
return _st(self)._withErrorReporting_((function(){
 return smalltalk.withContext(function($ctx3) {
return smalltalk.TestContext.fn.prototype._execute_.apply(_st(self), [aBlock]);
 }, function($ctx3) {$ctx3.fillBlock({},$ctx1)})}));
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-$2=(function(){
-return smalltalk.withContext(function($ctx2) {
$3=_st(self["@testCase"])._isAsync();
-if(! smalltalk.assert($3)){
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}))._ensure_((function(){
+return smalltalk.withContext(function($ctx2) {
$1=_st(self["@testCase"])._isAsync();
+if(! smalltalk.assert($1)){
 _st(self["@result"])._increaseRuns();
 return _st(self["@finished"])._value();
 };
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-_st($1)._ensure_($2);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"execute:",{aBlock:aBlock}, smalltalk.ReportingTestContext)})}
 }),
 smalltalk.ReportingTestContext);
@@ -695,19 +691,18 @@ smalltalk.method({
 selector: "status",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $2,$4,$3,$1;
+return smalltalk.withContext(function($ctx1) { 
var $2,$3,$1;
 $2=_st(_st(self)._errors())._isEmpty();
-$3=(function(){
-return smalltalk.withContext(function($ctx2) {
$4=_st(_st(self)._failures())._isEmpty();
-if(smalltalk.assert($4)){
-return "success";
+if(smalltalk.assert($2)){
+$3=_st(_st(self)._failures())._isEmpty();
+if(smalltalk.assert($3)){
+$1="success";
 } else {
-return "failure";
+$1="failure";
+};
+} else {
+$1="error";
 };
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-$1=_st($2)._ifTrue_ifFalse_($3,(function(){
-return smalltalk.withContext(function($ctx2) {
return "error";
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"status",{}, smalltalk.TestResult)})}
 }),

+ 24 - 29
js/SUnit.js

@@ -556,29 +556,27 @@ category: 'running',
 fn: function (aBlock){
 var self=this;
 var failed;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$4,$2;
+return smalltalk.withContext(function($ctx1) { 
var $1,$2;
 _st(self["@testCase"])._context_(self);
-$1=(function(){
+_st((function(){
 return smalltalk.withContext(function($ctx2) {
failed=true;
 failed;
 _st(aBlock)._value();
 failed=false;
 return failed;
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-$2=(function(){
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}))._ensure_((function(){
 return smalltalk.withContext(function($ctx2) {
_st(self["@testCase"])._context_(nil);
-$3=_st(failed)._and_((function(){
+$1=_st(failed)._and_((function(){
 return smalltalk.withContext(function($ctx3) {
return _st(self["@testCase"])._isAsync();
 }, function($ctx3) {$ctx3.fillBlock({},$ctx1)})}));
-if(smalltalk.assert($3)){
+if(smalltalk.assert($1)){
 _st(self["@testCase"])._finished();
 };
-$4=_st(self["@testCase"])._isAsync();
-if(! smalltalk.assert($4)){
+$2=_st(self["@testCase"])._isAsync();
+if(! smalltalk.assert($2)){
 return _st(self["@testCase"])._tearDown();
 };
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-_st($1)._ensure_($2);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"execute:",{aBlock:aBlock,failed:failed}, smalltalk.TestContext)})},
 args: ["aBlock"],
 source: "execute: aBlock\x0a\x09| failed |\x0a    \x0a    testCase context: self.\x0a    [ \x0a    \x09failed := true. \x0a        aBlock value. \x0a        failed := false \x0a\x09] \x0a    \x09ensure: [\x0a        \x09testCase context: nil.\x0a            \x0a        \x09(failed and: [ testCase isAsync ]) ifTrue: [ \x0a            \x09testCase finished ].\x0a        \x09testCase isAsync ifFalse: [ \x0a        \x09\x09testCase tearDown ] ]",
@@ -654,20 +652,18 @@ selector: "execute:",
 category: 'running',
 fn: function (aBlock){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$2;
-$1=(function(){
+return smalltalk.withContext(function($ctx1) { 
var $1;
+_st((function(){
 return smalltalk.withContext(function($ctx2) {
return _st(self)._withErrorReporting_((function(){
 return smalltalk.withContext(function($ctx3) {
return smalltalk.TestContext.fn.prototype._execute_.apply(_st(self), [aBlock]);
 }, function($ctx3) {$ctx3.fillBlock({},$ctx1)})}));
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-$2=(function(){
-return smalltalk.withContext(function($ctx2) {
$3=_st(self["@testCase"])._isAsync();
-if(! smalltalk.assert($3)){
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}))._ensure_((function(){
+return smalltalk.withContext(function($ctx2) {
$1=_st(self["@testCase"])._isAsync();
+if(! smalltalk.assert($1)){
 _st(self["@result"])._increaseRuns();
 return _st(self["@finished"])._value();
 };
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-_st($1)._ensure_($2);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"execute:",{aBlock:aBlock}, smalltalk.ReportingTestContext)})},
 args: ["aBlock"],
 source: "execute: aBlock\x0a    [ \x0a    \x09self withErrorReporting: [ super execute: aBlock ] \x0a\x09]\x0a    \x09ensure: [ \x0a        \x09testCase isAsync ifFalse: [ \x0a            \x09result increaseRuns. finished value ] ]",
@@ -905,7 +901,7 @@ return smalltalk.withContext(function($ctx2) {
return _st(self)._addError_(aTest
 }, function($ctx2) {$ctx2.fillBlock({ex:ex},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"runCase:",{aTestCase:aTestCase}, smalltalk.TestResult)})},
 args: ["aTestCase"],
-source: "runCase: aTestCase\x0a\x09[[\x09self increaseRuns.\x0a    \x09aTestCase runCase]\x0a\x09on: TestFailure do: [:ex | self addFailure: aTestCase]]\x0a\x09on: Error do: [:ex | self addError: aTestCase]\x0a",
+source: "runCase: aTestCase\x0a\x09[[\x09self increaseRuns.\x0a    \x09aTestCase runCase]\x0a\x09on: TestFailure do: [:ex | self addFailure: aTestCase]]\x0a\x09on: Error do: [:ex | self addError: aTestCase]",
 messageSends: ["on:do:", "addError:", "addFailure:", "increaseRuns", "runCase"],
 referencedClasses: ["Error", "TestFailure"]
 }),
@@ -936,19 +932,18 @@ selector: "status",
 category: 'accessing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $2,$4,$3,$1;
+return smalltalk.withContext(function($ctx1) { 
var $2,$3,$1;
 $2=_st(_st(self)._errors())._isEmpty();
-$3=(function(){
-return smalltalk.withContext(function($ctx2) {
$4=_st(_st(self)._failures())._isEmpty();
-if(smalltalk.assert($4)){
-return "success";
+if(smalltalk.assert($2)){
+$3=_st(_st(self)._failures())._isEmpty();
+if(smalltalk.assert($3)){
+$1="success";
 } else {
-return "failure";
+$1="failure";
+};
+} else {
+$1="error";
 };
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-$1=_st($2)._ifTrue_ifFalse_($3,(function(){
-return smalltalk.withContext(function($ctx2) {
return "error";
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"status",{}, smalltalk.TestResult)})},
 args: [],

+ 6 - 1
st/Canvas.st

@@ -629,7 +629,8 @@ ensureCurrent
 
 initialize
 	super initialize.
-	self ensureCurrent
+    self isDOMAvailable ifTrue: [
+		self ensureCurrent ]
 ! !
 
 !HTMLSnippet class methodsFor: 'instance creation'!
@@ -638,6 +639,10 @@ current
 	^ current
 !
 
+isDOMAvailable
+	< return typeof document !!== 'undefined' >
+!
+
 new
 	self shouldNotImplement
 ! !

+ 5 - 1
st/Compiler-Exceptions.st

@@ -99,8 +99,12 @@ As a result Smalltalk errors are not swallowd by the Amber runtime and compilati
 
 !RethrowErrorHandler methodsFor: 'error handling'!
 
+basicSignal: anError
+	<throw anError>
+!
+
 handleError: anError
 	super handleError: anError.
-    <throw anError>
+    self basicSignal: anError
 ! !
 

+ 1 - 1
st/Compiler-Semantic.st

@@ -422,7 +422,7 @@ errorUnknownVariable: aNode
 	| identifier |
     identifier := aNode value.
     
-	((#('jQuery' 'window' 'process' 'global') includes: identifier) not 
+	((#('jQuery' 'window' 'document' 'process' 'global') includes: identifier) not 
         and: [ self isVariableGloballyUndefined: identifier ]) 
         	ifTrue: [
 				UnknownVariableError new

+ 451 - 451
st/Documentation.st

@@ -1,231 +1,53 @@
 Smalltalk current createPackage: 'Documentation' properties: #{}!
-Object subclass: #DocumentationBuilder
-	instanceVariableNames: 'chapters announcer widget'
-	category: 'Documentation'!
-
-!DocumentationBuilder methodsFor: 'accessing'!
-
-chapters
-	^chapters ifNil: [chapters := self buildChapters]
-!
-
-announcer
-	^announcer ifNil: [announcer := Announcer new]
-!
-
-widget
-	^widget ifNil: [widget := DocumentationWidget on: self]
-! !
-
-!DocumentationBuilder methodsFor: 'building'!
-
-buildChapters
-	^((self class methodDictionary values sorted: [:a :b | a selector < b selector])
-		select: [:each | each category = 'chapters'])
-		collect: [:each | self perform: each selector]
-!
+Object subclass: #ChapterSelectionAnnouncement
+	instanceVariableNames: 'id'
+	package: 'Documentation'!
 
-buildOn: aCanvas
-	aCanvas with: self widget.
-	self 
-		checkHashChange;
-		checkHash
-!
+!ChapterSelectionAnnouncement methodsFor: 'accessing'!
 
-buildOnJQuery: aJQuery
-	self buildOn: (HTMLCanvas onJQuery: aJQuery)
+id
+	^id
 !
 
-build
-	self buildOnJQuery: ('body' asJQuery)
+id: aString
+	id := aString
 ! !
 
-!DocumentationBuilder methodsFor: 'chapters'!
-
-ch1introduction
-	^DocChapter new
-		title: 'Introduction';
-		contents: '
-
-##Amber Smalltalk in a nutshell
-
-Amber is an implementation of the Smalltalk-80 language. It is designed to make client-side web development **faster, easier and more fun** as it allows developers to write HTML5 applications in a live Smalltalk environment!!
-
-Amber is written in itself, including the IDE and the compiler and it runs **directly inside your browser**. The IDE is fairly complete with a class browser, workspace, transcript, unit test runner, object inspectors, cross reference tools and even a debugger.
-
-Noteworthy features:
-
-- Amber is semantically and syntactically very close to [Pharo Smalltalk](http://www.pharo-project.org). Pharo is considered the reference implementation.
-- Amber **seamlessly interacts with JavaScript** and can use its full eco system of libraries without any glue code needed.
-- Amber **has no dependencies** and can be used in any JavaScript runtime, not only inside browsers. An important example is [Node.js](http://nodejs.org).
-- Amber is a live Smalltalk that **compiles incrementally into efficient JavaScript** often mapping one-to-one with JavaScript equivalents.
-- Amber has a **Seaside influenced canvas library** to dynamically generate HTML.
-
-## Arguments for using Amber
-In our humble opinion the main arguments for using Amber are:
-
-- JavaScript is quite a broken language with lots of traps and odd quirks. It is the assembler of the Internet which is cool, but we don''t want to write in it.
-- Smalltalk as a language is immensely cleaner and more mature, both syntactically and semantically.
-- Smalltalk has a simple class model with a lightweight syntax for closures, it is in many ways a perfect match for the Good Parts of JavaScript.
-- Having a true live interactive incremental development environment where you can build your application directly in the browser is unbeatable.
-
-## Disclaimer
-
-This documentation doesn''t aim to teach Smalltalk. 
-Knowledge of Smalltalk is needed to understand the topics covered in this documentation. 
-If you want to learn the Smalltalk language, you can read the excellent [Pharo By Example](http://www.pharobyexample.org) book.
-'
-!
-
-ch2differencesWithOtherSmalltalks
-	^DocChapter new
-		title: 'Differences with other Smalltalks';
-		contents: '
-Amber has some differences with other Smalltalk implementations. This makes porting code a non-trivial thing, but still quite manageable.
-Because it maps Smalltalk constructs one-to-one with the JavaScript equivalent, including Smalltalk classes to JavaScript constructors, the core class library is simplified compared to Pharo Smalltalk.
-And since we want Amber to be useful in building lean browser apps we can''t let it bloat too much.
-
-But apart from missing things other Smalltalks may have, there are also things that are plain different:
-
-- The collection class hierarchy is much simpler compared to most Smalltalk implementations. In part this is because we want to map reasonably well with JavaScript counter parts.
-- As of today, there is no SortedCollection. The size of arrays is dynamic, and they behave like an ordered collection. They can also be sorted with the `#sort*` methods.
-- The `Date` class behaves like the `Date` and `TimeStamp` classes in Pharo Smalltalk. Therefore both `Date today` and `Date now` are valid in Amber.
-- Amber does not have class Character, but `String` does implement some of Character behavior so a single character String can work as a Character.
-- Amber does support **class instance variables**, but not class variables.
-- Amber only has global classes and packages, but not arbitrary objects. Use classes instead like `Smalltalk current` instead of `Smalltalk` etc.
-- Amber does not support pool dictionaries.
-- Amber uses **< ...javascript code... >** to inline JavaScript code and does not have pragmas.
-- Amber does not have class categories. The left side in the browser lists real Packages, but they feel much the same.
-'
-!
-
-ch3GettingStarted
-	^DocChapter new
-		title: 'Getting started';
-		contents: '
-To get started hacking in Amber you can basically take three routes, independent of your platform:
-
-1. Just **try it out directly** at [www.amber-lang.net](http://www.amber-lang.net) - click the **Class browser** button there. But you will **not be able to save any code you write**!! 
-    Still, it works fine for looking at the IDE and playing around. Just **don''t press F5/reload** - it will lose any code you have written.
-2. Download an Amber zip-ball, install [Nodejs](http://www.nodejs.org), fire up the Amber server and then open Amber from localhost - then you **can save code**. Detailed instructions are below!!
-3. Same as above but install git first and get a proper clone from [http://github.com/NicolasPetton/amber](http://github.com/NicolasPetton/amber) instead of a zip/tar-ball. 
-    If you want to **contribute to Amber itself** this is really what you want to do. In fact, in most cases this is what you want to do. It requires installing git first, but it is quite simple - although we leave this bit as an "exercise to the reader" :)
-
-**PLEASE NOTE:** Amber core developers use Linux. 
-We do not want to introduce dependencies that aren''t cross platform - but currently amberc (the command line compiler) is a bash script and we also use Makefiles 
-(for building Amber itself and server side examples) written on Linux/Unix. So using Windows is currently a bit limited - you can''t run "make" in the .st directory to rebuild whole of Amber for example.
- BUT... if you only want to use Amber to build web client apps and not really get involved in hacking Amber itself - then you should be fine!!
-
-## Downloading Amber
-Currently you can download in zip or tar-ball format, either cutting edge or a release. [Downloads are available here](https://github.com/NicolasPetton/amber/archives/amber). 
-
-Unpack wherever you like, but I would rename the directory that is unpacked to something slightly shorter - like say "amber". :)
-And yes, at this point you can double click the index.html file in the amber directory to get the IDE up, but again, **you will not be able to save code**. So please continue below :)
-
-## Installing Node.js
-[Node](http://www.nodejs.org) (for short) is simply the V8 Javascript VM from Google (used in Chrome) hooked together with some hard core C-libraries for doing "evented I/O".
-Basically it''s JavaScript for the server - on asynch steroids. Amber runs fine in Node and we use it for several Amber tools, like amberc (the command line Amber compiler) or the Amber server (see below). 
-There are also several Amber-Node examples to look at if you want to play with running Amber programs server side. **In short - you really want to install Nodejs. :)**
-
-- Installing Node on Linux can be done using your package tool of choice (`apt-get install nodejs` for example) or any other way described at [the download page](http://nodejs.org/#download).
-- Installing Node on MacOS or Windows is probably done best by using the [installers available at Nodejs.org](http://nodejs.org/#download).
-
-## Starting Amber server
-Nicolas has written a minimal webDAV server that is the easiest way to get up and running Amber with the ability to save code. This little server is written in... Amber!! 
-And it runs on top of Node. So to start it up serving your brand new directory tree of sweet Amber you do:
-
-	cd amber	(or whatever you called the directory you unpackaged)
-	./bin/server	(in windows you type `node server\server.js` instead)
-
-It should say it is listening on port 4000. If it does, hooray!! That means both Node and Amber are good. In Windows you might get a question about opening that port in the local firewall - yep, do it!!
-
-## Firing up Amber
-The Amber IDE is written in... Amber. It uses [jQuery](http://jquery.com) and runs right in your browser as a ... well, a web page. 
-We could open it up just using a file url - but the reason we performed the previous steps is so that we can load the IDE web page from a server that can handle PUTs (webDAV) of source code. 
-According to web security Amber can only do PUT back to the same server it was loaded from. Thus we instead want to open it [through our little server now listening on port 4000](http://localhost:4000/index.html).
-Clicking that link and then pressing the **Class browser** should get your Amber IDE running with the ability to commit modified packages locally.
-
-To verify that you can indeed commit now - just select a Package in the browser, like say "Examples" and press the **Commit** button below. **If all goes well nothing happens :)**. 
-So in order to really know if it worked we can check the modified date on the files **amber/st/Examples.st**, **amber/js/Examples.js** and **amber/js/Examples.deploy.js** - they should be brand new.
-
-NOTE: We can use any webDAV server and Apache2 has been used earlier and works fine. But the Amber server is smaller and simpler to start.
-'
-!
-
-ch5Index
-	^ClassesIndexChapter new
-!
-
-ch6KernelObjects
-	^PackageDocChapter on: (Package named: 'Kernel-Objects')
-!
-
-ch7KernelClasses
-	^PackageDocChapter on: (Package named: 'Kernel-Classes')
-!
-
-ch4Tutorials
-	^TutorialsChapter new
-!
-
-ch8KernelCollection
-	^PackageDocChapter on: (Package named: 'Kernel-Collections')
-!
-
-ch9KernelMethods
-	^PackageDocChapter on: (Package named: 'Kernel-Methods')
-! !
+Object subclass: #ClassSelectionAnnouncement
+	instanceVariableNames: 'theClass'
+	package: 'Documentation'!
 
-!DocumentationBuilder methodsFor: 'routing'!
+!ClassSelectionAnnouncement methodsFor: 'accessing'!
 
-checkHashChange
-	(window jQuery: window) bind: 'hashchange' do: [self checkHash]
+theClass
+	^theClass
 !
 
-checkHash
-	| hash presentation |
-	hash := document location hash  replace: '^#' with: ''.
-	self announcer announce: (ChapterSelectionAnnouncement new 
-		id: hash; 
-		yourself)
-! !
-
-!DocumentationBuilder methodsFor: 'updating'!
-
-update
-	chapters := nil.
-	announcer := nil.
-	widget := nil.
-	(window jQuery: '.documentation') remove.
-	self build
-! !
-
-DocumentationBuilder class instanceVariableNames: 'current'!
-
-!DocumentationBuilder class methodsFor: 'accessing'!
-
-current
-	^current ifNil: [current := self new]
+theClass: aClass
+	theClass := aClass
 ! !
 
-!DocumentationBuilder class methodsFor: 'initialization'!
+!ClassSelectionAnnouncement class methodsFor: 'instance creation'!
 
-initialize
-	self current build
+on: aClass
+	^self new
+		theClass: aClass;
+		yourself
 ! !
 
 Widget subclass: #DocChapter
-	instanceVariableNames: 'title contents parent'
-	category: 'Documentation'!
+	instanceVariableNames: 'title contents parent level'
+	package: 'Documentation'!
 
 !DocChapter methodsFor: 'accessing'!
 
-title
-	^title ifNil: ['']
+announcer
+	^DocumentationBuilder current announcer
 !
 
-title: aString
-	title := aString
+chapters
+	"A doc chapter can contain sub chapters"
+	^#()
 !
 
 contents
@@ -236,17 +58,18 @@ contents: aString
 	contents := aString
 !
 
-htmlContents
-	^(Showdown at: #converter) new makeHtml: self contents
+cssClass
+	^'doc_chapter'
 !
 
-chapters
-	"A doc chapter can contain sub chapters"
-	^#()
+htmlContents
+	^(Showdown at: #converter) new makeHtml: self contents
 !
 
-cssClass
-	^'doc_chapter'
+id
+	"The id is used in url fragments. 
+	It must be unique amoung all chapters"
+	^self title replace: ' ' with: '-'
 !
 
 level
@@ -265,28 +88,26 @@ parent: aChapter
 	parent := aChapter
 !
 
-id
-	"The id is used in url fragments. 
-	It must be unique amoung all chapters"
-	^self title replace: ' ' with: '-'
+title
+	^title ifNil: ['']
 !
 
-announcer
-	^DocumentationBuilder current announcer
+title: aString
+	title := aString
 ! !
 
 !DocChapter methodsFor: 'actions'!
 
-selectClass: aClass
-	DocumentationBuilder current announcer announce: (ClassSelectionAnnouncement on: aClass)
+displayChapter: aChapter
+	DocumentationBuilder current widget displayChapter: aChapter
 !
 
 selectChapter: aChapter
 	document location hash: aChapter id
 !
 
-displayChapter: aChapter
-	DocumentationBuilder current widget displayChapter: aChapter
+selectClass: aClass
+	DocumentationBuilder current announcer announce: (ClassSelectionAnnouncement on: aClass)
 ! !
 
 !DocChapter methodsFor: 'initialization'!
@@ -298,14 +119,6 @@ initialize
 
 !DocChapter methodsFor: 'rendering'!
 
-renderOn: html
-	html div 
-		class: self cssClass;
-		with: [
-			self renderDocOn: html.
-			self renderLinksOn: html]
-!
-
 renderDocOn: html
 	| div |
 	html h1 with: self title.
@@ -314,6 +127,17 @@ renderDocOn: html
 	div asJQuery html: self htmlContents
 !
 
+renderLinksOn: html
+	html ul 
+		class: 'links';
+		with: [
+			self chapters do: [:each |
+				html li with: [
+					html a
+						with: each title;
+						onClick: [self selectChapter: each]]]]
+!
+
 renderNavigationOn: html
 	self parent ifNotNil: [
 		html div 
@@ -323,15 +147,12 @@ renderNavigationOn: html
 					onClick: [self selectChapter: self parent]]]
 !
 
-renderLinksOn: html
-	html ul 
-		class: 'links';
+renderOn: html
+	html div 
+		class: self cssClass;
 		with: [
-			self chapters do: [:each |
-				html li with: [
-					html a
-						with: each title;
-						onClick: [self selectChapter: each]]]]
+			self renderDocOn: html.
+			self renderLinksOn: html]
 ! !
 
 !DocChapter methodsFor: 'subscriptions'!
@@ -341,57 +162,12 @@ subscribe
 		ann id = self id ifTrue: [self displayChapter: self]]
 ! !
 
-DocChapter subclass: #PackageDocChapter
-	instanceVariableNames: 'package chapters'
-	category: 'Documentation'!
-
-!PackageDocChapter methodsFor: 'accessing'!
-
-package
-	^package
-!
-
-title
-	^'Package ', self package name
-!
-
-chapters
-	^chapters
-!
-
-contents
-	^'Classes in package ', self package name, ':'
-! !
-
-!PackageDocChapter methodsFor: 'initialization'!
-
-initializeWithPackage: aPackage
-	package := aPackage.
-	chapters := (aPackage classes sorted: [:a :b | a name < b name]) collect: [:each |
-		(ClassDocChapter on: each)
-			parent: self;
-			yourself]
-! !
-
-!PackageDocChapter class methodsFor: 'instance creation'!
-
-on: aPackage
-	^self basicNew
-		initializeWithPackage: aPackage;
-		initialize;
-		yourself
-! !
-
 DocChapter subclass: #ClassDocChapter
 	instanceVariableNames: 'theClass'
-	category: 'Documentation'!
+	package: 'Documentation'!
 
 !ClassDocChapter methodsFor: 'accessing'!
 
-theClass
-	^theClass
-!
-
 contents
 	^self theClass comment isEmpty
 		ifTrue: [self theClass name, ' is not documented yet.']
@@ -402,12 +178,16 @@ cssClass
 	^'doc_class ', super cssClass
 !
 
-title
-	^self theClass name
-!
-
 initializeWithClass: aClass
 	theClass := aClass
+!
+
+theClass
+	^theClass
+!
+
+title
+	^self theClass name
 ! !
 
 !ClassDocChapter methodsFor: 'rendering'!
@@ -440,106 +220,22 @@ on: aClass
 		yourself
 ! !
 
-Widget subclass: #DocumentationWidget
-	instanceVariableNames: 'builder selectedChapter chapterDiv'
-	category: 'Documentation'!
-
-!DocumentationWidget methodsFor: 'accessing'!
-
-builder
-	^builder
-!
-
-builder: aDocumentationBuilder
-	builder := aDocumentationBuilder
-!
-
-chapters
-	^self builder chapters
-!
-
-selectedChapter
-	^selectedChapter ifNil: [selectedChapter := self chapters first]
-!
-
-selectedChapter: aChapter
-	^selectedChapter := aChapter
-! !
-
-!DocumentationWidget methodsFor: 'actions'!
-
-displayChapter: aChapter
-	self selectedChapter: aChapter.
-	self updateChapterDiv
-!
-
-selectChapter: aChapter
-	document location hash: aChapter id
-! !
-
-!DocumentationWidget methodsFor: 'rendering'!
-
-renderOn: html
-	html div 
-		class: 'documentation';
-		with: [
-			self renderMenuOn: html.
-			chapterDiv := html div.
-			self updateChapterDiv]
-!
-
-renderMenuOn: html
-	html div 
-		class: 'menu';
-		with: [
-			html ol with: [
-				self chapters do: [:each |
-					html li with: [
-						self renderChapterMenu: each on: html]]]]
-!
-
-renderChapterMenu: aChapter on: html
-	html a
-		with: aChapter title;
-		onClick: [
-			self selectChapter: aChapter].
-	html ol with: [
-			aChapter chapters do: [:each |
-				html li with: [
-					self renderChapterMenu: each on: html]]]
-! !
-
-!DocumentationWidget methodsFor: 'updating'!
-
-updateChapterDiv
-	chapterDiv contents: [:html |
-		html with: self selectedChapter]
-! !
-
-!DocumentationWidget class methodsFor: 'instance creation'!
-
-on: aBuilder
-	^self new
-		builder: aBuilder;
-		yourself
-! !
-
 DocChapter subclass: #ClassesIndexChapter
 	instanceVariableNames: ''
-	category: 'Documentation'!
+	package: 'Documentation'!
 
 !ClassesIndexChapter methodsFor: 'accessing'!
 
+alphabet
+	^'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+!
+
 cssClass
 	^'index_doc ', super cssClass
 !
 
 title
 	^'Smalltalk classes by index'
-!
-
-alphabet
-	^'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
 ! !
 
 !ClassesIndexChapter methodsFor: 'rendering'!
@@ -557,74 +253,132 @@ renderDocOn: html
 						onClick: [self selectClass: each]]]]]
 ! !
 
-Object subclass: #ClassSelectionAnnouncement
-	instanceVariableNames: 'theClass'
-	category: 'Documentation'!
+DocChapter subclass: #PackageDocChapter
+	instanceVariableNames: 'package chapters'
+	package: 'Documentation'!
 
-!ClassSelectionAnnouncement methodsFor: 'accessing'!
+!PackageDocChapter methodsFor: 'accessing'!
 
-theClass
-	^theClass
+chapters
+	^chapters
 !
 
-theClass: aClass
-	theClass := aClass
-! !
+contents
+	^'Classes in package ', self package name, ':'
+!
 
-!ClassSelectionAnnouncement class methodsFor: 'instance creation'!
+package
+	^package
+!
 
-on: aClass
-	^self new
-		theClass: aClass;
-		yourself
+title
+	^'Package ', self package name
 ! !
 
-Object subclass: #ChapterSelectionAnnouncement
-	instanceVariableNames: 'id'
-	category: 'Documentation'!
+!PackageDocChapter methodsFor: 'initialization'!
 
-!ChapterSelectionAnnouncement methodsFor: 'accessing'!
+initializeWithPackage: aPackage
+	package := aPackage.
+	chapters := (aPackage classes sorted: [:a :b | a name < b name]) collect: [:each |
+		(ClassDocChapter on: each)
+			parent: self;
+			yourself]
+! !
 
-id
-	^id
-!
+!PackageDocChapter class methodsFor: 'instance creation'!
 
-id: aString
-	id := aString
+on: aPackage
+	^self basicNew
+		initializeWithPackage: aPackage;
+		initialize;
+		yourself
 ! !
 
 DocChapter subclass: #TutorialsChapter
 	instanceVariableNames: ''
-	category: 'Documentation'!
+	package: 'Documentation'!
 
 !TutorialsChapter methodsFor: 'accessing'!
 
-title
-	^'Tutorials'
+chapters
+	^{ self firstAppChapter. self counterChapter }
 !
 
 contents
 	^'Here''s a serie of tutorials. If you are new to Smalltalk, you can also learn Amber online with [ProfStef](http://www.amber-lang.net/learn.html)'
 !
 
-chapters
-	^{ self firstAppChapter. self counterChapter }
-!
-
-firstAppChapter
+counterChapter
 	^DocChapter new
-		title: 'A first application';
+		title: 'The counter application';
 		contents: '
 
-Let''s make Hello World in Amber.
+This tutorial will teach you how to build HTML with Amber using jQuery and the HTMLCanvas API. It is freely adapted from 
+the [Seaside counter example](http://www.seaside.st/about/examples/counter)
 
-First, you need a place for your new project. I made a new directory under amber:
+##The counter widget
 
-    amber/projects/hello
+The counter is the most basic example of a widget. It allows to increment and decrement a number by clicking a button.
 
-This will store your project files. To get started, add a new index.html file to this folder, as well as empty js and st folders.
+Amber already comes with a counter example in the `Examples` package. To avoid class name conflict, we''ll name our counter class `TCounter`.
 
-Your index.html can be really basic. The most important thing it does is include amber.js and run loadAmber. Here is a basic index.html you can use:
+    Widget subclass: #TCounter
+        instanceVariableNames: ''count header''
+        package: ''Tutorials''
+
+The first method is used to initialize the component with the default state, in this case we set the counter to 0:
+
+    initialize
+        super initialize.
+        count := 0
+
+The method used for rendering a widget is `#renderOn:`. It takes an instance of HTMLCanvas as parameter. 
+The `header` h1 kept as an instance variable, so when the count value change, we can update it''s contents accordingly.
+
+    renderOn: html
+        header := html h1 
+            with: count asString;
+            yourself.
+        html button
+            with: ''++'';
+            onClick: [self increase].
+        html button
+            with: ''--'';
+            onClick: [self decrease]
+
+The counter is almost ready. All we need now is to implement the two action methods `#increase` and `#decrease` to change the state 
+of our counter and update its header.
+
+    increase
+        count := count + 1.
+        header contents: [:html | html with: count asString]
+
+    decrease
+        count := count - 1.
+        header contents: [:html | html with: count asString]
+
+
+That''s it!! We can now display an instance of TCounter by rendering it on the page using jQuery:
+
+    TCounter new appendToJQuery: ''body'' asJQuery
+
+'
+!
+
+firstAppChapter
+	^DocChapter new
+		title: 'A first application';
+		contents: '
+
+Let''s make Hello World in Amber.
+
+First, you need a place for your new project. I made a new directory under amber:
+
+    amber/projects/hello
+
+This will store your project files. To get started, add a new index.html file to this folder, as well as empty js and st folders.
+
+Your index.html can be really basic. The most important thing it does is include amber.js and run loadAmber. Here is a basic index.html you can use:
 
 
     <!!DOCTYPE html>
@@ -699,60 +453,306 @@ From there, you can create new Smalltalk classes and messages to build up your a
 '
 !
 
-counterChapter
+title
+	^'Tutorials'
+! !
+
+Object subclass: #DocumentationBuilder
+	instanceVariableNames: 'chapters announcer widget'
+	package: 'Documentation'!
+
+!DocumentationBuilder methodsFor: 'accessing'!
+
+announcer
+	^announcer ifNil: [announcer := Announcer new]
+!
+
+chapters
+	^chapters ifNil: [chapters := self buildChapters]
+!
+
+widget
+	^widget ifNil: [widget := DocumentationWidget on: self]
+! !
+
+!DocumentationBuilder methodsFor: 'building'!
+
+build
+	self buildOnJQuery: ('body' asJQuery)
+!
+
+buildChapters
+	^((self class methodDictionary values sorted: [:a :b | a selector < b selector])
+		select: [:each | each category = 'chapters'])
+		collect: [:each | self perform: each selector]
+!
+
+buildOn: aCanvas
+	aCanvas with: self widget.
+	self 
+		checkHashChange;
+		checkHash
+!
+
+buildOnJQuery: aJQuery
+	self buildOn: (HTMLCanvas onJQuery: aJQuery)
+! !
+
+!DocumentationBuilder methodsFor: 'chapters'!
+
+ch1introduction
 	^DocChapter new
-		title: 'The counter application';
+		title: 'Introduction';
 		contents: '
 
-This tutorial will teach you how to build HTML with Amber using jQuery and the HTMLCanvas API. It is freely adapted from 
-the [Seaside counter example](http://www.seaside.st/about/examples/counter)
+##Amber Smalltalk in a nutshell
 
-##The counter widget
+Amber is an implementation of the Smalltalk-80 language. It is designed to make client-side web development **faster, easier and more fun** as it allows developers to write HTML5 applications in a live Smalltalk environment!!
 
-The counter is the most basic example of a widget. It allows to increment and decrement a number by clicking a button.
+Amber is written in itself, including the IDE and the compiler and it runs **directly inside your browser**. The IDE is fairly complete with a class browser, workspace, transcript, unit test runner, object inspectors, cross reference tools and even a debugger.
 
-Amber already comes with a counter example in the `Examples` package. To avoid class name conflict, we''ll name our counter class `TCounter`.
+Noteworthy features:
 
-    Widget subclass: #TCounter
-        instanceVariableNames: ''count header''
-        package: ''Tutorials''
+- Amber is semantically and syntactically very close to [Pharo Smalltalk](http://www.pharo-project.org). Pharo is considered the reference implementation.
+- Amber **seamlessly interacts with JavaScript** and can use its full eco system of libraries without any glue code needed.
+- Amber **has no dependencies** and can be used in any JavaScript runtime, not only inside browsers. An important example is [Node.js](http://nodejs.org).
+- Amber is a live Smalltalk that **compiles incrementally into efficient JavaScript** often mapping one-to-one with JavaScript equivalents.
+- Amber has a **Seaside influenced canvas library** to dynamically generate HTML.
 
-The first method is used to initialize the component with the default state, in this case we set the counter to 0:
+## Arguments for using Amber
+In our humble opinion the main arguments for using Amber are:
 
-    initialize
-        super initialize.
-        count := 0
+- JavaScript is quite a broken language with lots of traps and odd quirks. It is the assembler of the Internet which is cool, but we don''t want to write in it.
+- Smalltalk as a language is immensely cleaner and more mature, both syntactically and semantically.
+- Smalltalk has a simple class model with a lightweight syntax for closures, it is in many ways a perfect match for the Good Parts of JavaScript.
+- Having a true live interactive incremental development environment where you can build your application directly in the browser is unbeatable.
 
-The method used for rendering a widget is `#renderOn:`. It takes an instance of HTMLCanvas as parameter. 
-The `header` h1 kept as an instance variable, so when the count value change, we can update it''s contents accordingly.
+## Disclaimer
 
-    renderOn: html
-        header := html h1 
-            with: count asString;
-            yourself.
-        html button
-            with: ''++'';
-            onClick: [self increase].
-        html button
-            with: ''--'';
-            onClick: [self decrease]
+This documentation doesn''t aim to teach Smalltalk. 
+Knowledge of Smalltalk is needed to understand the topics covered in this documentation. 
+If you want to learn the Smalltalk language, you can read the excellent [Pharo By Example](http://www.pharobyexample.org) book.
+'
+!
 
-The counter is almost ready. All we need now is to implement the two action methods `#increase` and `#decrease` to change the state 
-of our counter and update its header.
+ch2differencesWithOtherSmalltalks
+	^DocChapter new
+		title: 'Differences with other Smalltalks';
+		contents: '
+Amber has some differences with other Smalltalk implementations. This makes porting code a non-trivial thing, but still quite manageable.
+Because it maps Smalltalk constructs one-to-one with the JavaScript equivalent, including Smalltalk classes to JavaScript constructors, the core class library is simplified compared to Pharo Smalltalk.
+And since we want Amber to be useful in building lean browser apps we can''t let it bloat too much.
 
-    increase
-        count := count + 1.
-        header contents: [:html | html with: count asString]
+But apart from missing things other Smalltalks may have, there are also things that are plain different:
 
-    decrease
-        count := count - 1.
-        header contents: [:html | html with: count asString]
+- The collection class hierarchy is much simpler compared to most Smalltalk implementations. In part this is because we want to map reasonably well with JavaScript counter parts.
+- As of today, there is no SortedCollection. The size of arrays is dynamic, and they behave like an ordered collection. They can also be sorted with the `#sort*` methods.
+- The `Date` class behaves like the `Date` and `TimeStamp` classes in Pharo Smalltalk. Therefore both `Date today` and `Date now` are valid in Amber.
+- Amber does not have class Character, but `String` does implement some of Character behavior so a single character String can work as a Character.
+- Amber does support **class instance variables**, but not class variables.
+- Amber only has global classes and packages, but not arbitrary objects. Use classes instead like `Smalltalk current` instead of `Smalltalk` etc.
+- Amber does not support pool dictionaries.
+- Amber uses **< ...javascript code... >** to inline JavaScript code and does not have pragmas.
+- Amber does not have class categories. The left side in the browser lists real Packages, but they feel much the same.
+'
+!
 
+ch3GettingStarted
+	^DocChapter new
+		title: 'Getting started';
+		contents: '
+To get started hacking in Amber you can basically take three routes, independent of your platform:
 
-That''s it!! We can now display an instance of TCounter by rendering it on the page using jQuery:
+1. Just **try it out directly** at [www.amber-lang.net](http://www.amber-lang.net) - click the **Class browser** button there. But you will **not be able to save any code you write**!! 
+    Still, it works fine for looking at the IDE and playing around. Just **don''t press F5/reload** - it will lose any code you have written.
+2. Download an Amber zip-ball, install [Nodejs](http://www.nodejs.org), fire up the Amber server and then open Amber from localhost - then you **can save code**. Detailed instructions are below!!
+3. Same as above but install git first and get a proper clone from [http://github.com/NicolasPetton/amber](http://github.com/NicolasPetton/amber) instead of a zip/tar-ball. 
+    If you want to **contribute to Amber itself** this is really what you want to do. In fact, in most cases this is what you want to do. It requires installing git first, but it is quite simple - although we leave this bit as an "exercise to the reader" :)
 
-    TCounter new appendToJQuery: ''body'' asJQuery
+**PLEASE NOTE:** Amber core developers use Linux. 
+We do not want to introduce dependencies that aren''t cross platform - but currently amberc (the command line compiler) is a bash script and we also use Makefiles 
+(for building Amber itself and server side examples) written on Linux/Unix. So using Windows is currently a bit limited - you can''t run "make" in the .st directory to rebuild whole of Amber for example.
+ BUT... if you only want to use Amber to build web client apps and not really get involved in hacking Amber itself - then you should be fine!!
+
+## Downloading Amber
+Currently you can download in zip or tar-ball format, either cutting edge or a release. [Downloads are available here](https://github.com/NicolasPetton/amber/archives/amber). 
+
+Unpack wherever you like, but I would rename the directory that is unpacked to something slightly shorter - like say "amber". :)
+And yes, at this point you can double click the index.html file in the amber directory to get the IDE up, but again, **you will not be able to save code**. So please continue below :)
+
+## Installing Node.js
+[Node](http://www.nodejs.org) (for short) is simply the V8 Javascript VM from Google (used in Chrome) hooked together with some hard core C-libraries for doing "evented I/O".
+Basically it''s JavaScript for the server - on asynch steroids. Amber runs fine in Node and we use it for several Amber tools, like amberc (the command line Amber compiler) or the Amber server (see below). 
+There are also several Amber-Node examples to look at if you want to play with running Amber programs server side. **In short - you really want to install Nodejs. :)**
 
+- Installing Node on Linux can be done using your package tool of choice (`apt-get install nodejs` for example) or any other way described at [the download page](http://nodejs.org/#download).
+- Installing Node on MacOS or Windows is probably done best by using the [installers available at Nodejs.org](http://nodejs.org/#download).
+
+## Starting Amber server
+Nicolas has written a minimal webDAV server that is the easiest way to get up and running Amber with the ability to save code. This little server is written in... Amber!! 
+And it runs on top of Node. So to start it up serving your brand new directory tree of sweet Amber you do:
+
+	cd amber	(or whatever you called the directory you unpackaged)
+	./bin/server	(in windows you type `node server\server.js` instead)
+
+It should say it is listening on port 4000. If it does, hooray!! That means both Node and Amber are good. In Windows you might get a question about opening that port in the local firewall - yep, do it!!
+
+## Firing up Amber
+The Amber IDE is written in... Amber. It uses [jQuery](http://jquery.com) and runs right in your browser as a ... well, a web page. 
+We could open it up just using a file url - but the reason we performed the previous steps is so that we can load the IDE web page from a server that can handle PUTs (webDAV) of source code. 
+According to web security Amber can only do PUT back to the same server it was loaded from. Thus we instead want to open it [through our little server now listening on port 4000](http://localhost:4000/index.html).
+Clicking that link and then pressing the **Class browser** should get your Amber IDE running with the ability to commit modified packages locally.
+
+To verify that you can indeed commit now - just select a Package in the browser, like say "Examples" and press the **Commit** button below. **If all goes well nothing happens :)**. 
+So in order to really know if it worked we can check the modified date on the files **amber/st/Examples.st**, **amber/js/Examples.js** and **amber/js/Examples.deploy.js** - they should be brand new.
+
+NOTE: We can use any webDAV server and Apache2 has been used earlier and works fine. But the Amber server is smaller and simpler to start.
 '
+!
+
+ch4Tutorials
+	^TutorialsChapter new
+!
+
+ch5Index
+	^ClassesIndexChapter new
+!
+
+ch6KernelObjects
+	^PackageDocChapter on: (Package named: 'Kernel-Objects')
+!
+
+ch7KernelClasses
+	^PackageDocChapter on: (Package named: 'Kernel-Classes')
+!
+
+ch8KernelCollection
+	^PackageDocChapter on: (Package named: 'Kernel-Collections')
+!
+
+ch9KernelMethods
+	^PackageDocChapter on: (Package named: 'Kernel-Methods')
+! !
+
+!DocumentationBuilder methodsFor: 'routing'!
+
+checkHash
+	| hash presentation |
+	hash := document location hash  replace: '^#' with: ''.
+	self announcer announce: (ChapterSelectionAnnouncement new 
+		id: hash; 
+		yourself)
+!
+
+checkHashChange
+	(window jQuery: window) bind: 'hashchange' do: [self checkHash]
+! !
+
+!DocumentationBuilder methodsFor: 'updating'!
+
+update
+	chapters := nil.
+	announcer := nil.
+	widget := nil.
+	(window jQuery: '.documentation') remove.
+	self build
+! !
+
+DocumentationBuilder class instanceVariableNames: 'current'!
+
+!DocumentationBuilder class methodsFor: 'accessing'!
+
+current
+	^current ifNil: [current := self new]
+! !
+
+!DocumentationBuilder class methodsFor: 'initialization'!
+
+initialize
+	self current build
+! !
+
+Widget subclass: #DocumentationWidget
+	instanceVariableNames: 'builder selectedChapter chapterDiv'
+	package: 'Documentation'!
+
+!DocumentationWidget methodsFor: 'accessing'!
+
+builder
+	^builder
+!
+
+builder: aDocumentationBuilder
+	builder := aDocumentationBuilder
+!
+
+chapters
+	^self builder chapters
+!
+
+selectedChapter
+	^selectedChapter ifNil: [selectedChapter := self chapters first]
+!
+
+selectedChapter: aChapter
+	^selectedChapter := aChapter
+! !
+
+!DocumentationWidget methodsFor: 'actions'!
+
+displayChapter: aChapter
+	self selectedChapter: aChapter.
+	self updateChapterDiv
+!
+
+selectChapter: aChapter
+	document location hash: aChapter id
+! !
+
+!DocumentationWidget methodsFor: 'rendering'!
+
+renderChapterMenu: aChapter on: html
+	html a
+		with: aChapter title;
+		onClick: [
+			self selectChapter: aChapter].
+	html ol with: [
+			aChapter chapters do: [:each |
+				html li with: [
+					self renderChapterMenu: each on: html]]]
+!
+
+renderMenuOn: html
+	html div 
+		class: 'menu';
+		with: [
+			html ol with: [
+				self chapters do: [:each |
+					html li with: [
+						self renderChapterMenu: each on: html]]]]
+!
+
+renderOn: html
+	html div 
+		class: 'documentation';
+		with: [
+			self renderMenuOn: html.
+			chapterDiv := html div.
+			self updateChapterDiv]
+! !
+
+!DocumentationWidget methodsFor: 'updating'!
+
+updateChapterDiv
+	chapterDiv contents: [:html |
+		html with: self selectedChapter]
+! !
+
+!DocumentationWidget class methodsFor: 'instance creation'!
+
+on: aBuilder
+	^self new
+		builder: aBuilder;
+		yourself
 ! !
 

+ 1 - 1
st/IDE.st

@@ -1205,7 +1205,7 @@ updateSourceAndButtons
                 currentProtocol := selectedProtocol.
                 (currentProtocol isNil and: [ selectedMethod notNil ])
                 	ifTrue: [ currentProtocol := selectedMethod category].
-				self protocols do: [:each |
+				self protocols do: [:each | | option |
 					option := html option with: each.
 					currentProtocol = each ifTrue: [ option at: 'selected' put: 'selected' ] ]].
 		selectedMethod isNil ifFalse: [

+ 14 - 7
st/Kernel-Classes.st

@@ -449,13 +449,17 @@ superclass: aClass subclass: aString instanceVariableNames: aString2 package: aS
 !ClassBuilder methodsFor: 'private'!
 
 addSubclassOf: aClass named: aString instanceVariableNames: aCollection package: packageName
-	
-    (Smalltalk current at: aString) ifNotNil: [ 
-    	^ self 
-        	migrateClassNamed: aString 
-            superclass: aClass 
-            instanceVariableNames: aCollection 
-            package: packageName ].
+    | theClass |
+    
+    theClass := Smalltalk current at: aString.
+    
+   	theClass ifNotNil: [ 
+    	theClass superclass == aClass ifFalse: [
+    		^ self 
+        		migrateClassNamed: aString 
+           	 	superclass: aClass 
+           	 	instanceVariableNames: aCollection 
+            	package: packageName ] ].
 
 	^ self 
     	basicAddSubclassOf: aClass 
@@ -527,6 +531,7 @@ instanceVariableNamesFor: aString
 !
 
 migrateClass: aClass superclass: anotherClass
+	console log: aClass name.
 	self 
     	migrateClassNamed: aClass name
         superclass: anotherClass
@@ -537,6 +542,8 @@ migrateClass: aClass superclass: anotherClass
 migrateClassNamed: aString superclass: aClass instanceVariableNames: aCollection package: packageName
 	| oldClass newClass |
     
+    console log: '*** MIGRATING ', aString.
+    
     oldClass := Smalltalk current at: aString.
     
     "Rename the old class for existing instances"

Some files were not shown because too many files changed in this diff