Browse Source

merge with master

Laurent Laffont 12 years ago
parent
commit
7caa3af0a4
31 changed files with 2598 additions and 837 deletions
  1. 2 1
      .gitignore
  2. 1 1
      examples/presentation/index.html
  3. 1 0
      js/Benchfib.deploy.js
  4. 4 3
      js/Benchfib.js
  5. 34 33
      js/Canvas.deploy.js
  6. 55 54
      js/Canvas.js
  7. 3 13
      js/Compiler.deploy.js
  8. 5 20
      js/Compiler.js
  9. 1 0
      js/Examples.deploy.js
  10. 10 9
      js/Examples.js
  11. 74 1
      js/IDE.deploy.js
  12. 128 25
      js/IDE.js
  13. 1 0
      js/Kernel-Tests.deploy.js
  14. 5 4
      js/Kernel-Tests.js
  15. 645 37
      js/Kernel.deploy.js
  16. 380 99
      js/Kernel.js
  17. 1 0
      js/SUnit.deploy.js
  18. 5 4
      js/SUnit.js
  19. 417 415
      js/boot.js
  20. 130 22
      js/parser.js
  21. 7 1
      js/parser.pegjs
  22. 1 1
      server/Makefile
  23. 258 37
      server/server.js
  24. 1 0
      st/Benchfib.st
  25. 1 0
      st/Canvas.st
  26. 46 30
      st/Compiler.st
  27. 1 0
      st/Examples.st
  28. 18 3
      st/IDE.st
  29. 1 0
      st/Kernel-Tests.st
  30. 361 24
      st/Kernel.st
  31. 1 0
      st/SUnit.st

+ 2 - 1
.gitignore

@@ -1,6 +1,7 @@
-# Ignoring compiled files in examples
+# Ignoring compiled files in examples etc
 examples/nodejs/**/*.js
 examples/webos/**/*.js
+server/FileServer*.js
 
 # Ignoring compiled files in st
 st/*.js

+ 1 - 1
examples/presentation/index.html

@@ -7,7 +7,7 @@
 
 <script type="text/javascript"> 
 	loadAmber({
-		files: ['Presentation.js'],
+		files: ['Presentation.js', 'Presentation-IAE.js'],
 		prefix: 'examples/presentation/js',
 		ready: function() {smalltalk.Browser._openOn_(smalltalk.ESUG2011Presentation)} 
 	}); 

+ 1 - 0
js/Benchfib.deploy.js

@@ -1,3 +1,4 @@
+smalltalk.addPackage('Benchfib', {});
 smalltalk.addClass('Benchfib', smalltalk.Object, [], 'Benchfib');
 
 smalltalk.addMethod(

+ 4 - 3
js/Benchfib.js

@@ -1,3 +1,4 @@
+smalltalk.addPackage('Benchfib', {});
 smalltalk.addClass('Benchfib', smalltalk.Object, [], 'Benchfib');
 
 smalltalk.addMethod(
@@ -54,7 +55,7 @@ return self;},
 args: [],
 source: unescape('benchmark%20%0A%09%22Handy%20bytecode-heavy%20benchmark%22%0A%09%22%28500000%20//%20time%20to%20run%29%20%3D%20approx%20bytecodes%20per%20second%22%0A%09%225000000%20//%20%28Time%20millisecondsToRun%3A%20%5B10%20benchmark%5D%29%20*%201000%22%0A%09%223059000%20on%20a%20Mac%208100/100%22%0A%20%20%20%20%7C%20size%20flags%20prime%20k%20count%20%7C%0A%20%20%20%20size%20%3A%3D%208190.%0A%20%20%20%201%20to%3A%20self%20do%3A%0A%20%20%20%20%20%20%20%20%5B%3Aiter%20%7C%0A%20%20%20%20%20%20%20%20count%20%3A%3D%200.%0A%20%20%20%20%20%20%20%20flags%20%3A%3D%20Array%20new.%0A%20%20%20%20%20%20%20%20size%20timesRepeat%3A%20%5B%20flags%20add%3A%20true%5D.%0A%20%20%20%20%20%20%20%201%20to%3A%20size%20do%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%5B%3Ai%20%7C%20%28flags%20at%3A%20i%29%20ifTrue%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5Bprime%20%3A%3D%20i+1.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20k%20%3A%3D%20i%20+%20prime.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5Bk%20%3C%3D%20size%5D%20whileTrue%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5Bflags%20at%3A%20k%20put%3A%20false.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20k%20%3A%3D%20k%20+%20prime%5D.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20count%20%3A%3D%20count%20+%201%5D%5D%5D.%0A%20%20%20%20%5E%20count'),
 messageSends: ["to:do:", "new", "timesRepeat:", "add:", "ifTrue:", "at:", unescape("+"), "whileTrue:", unescape("%3C%3D"), "at:put:"],
-referencedClasses: [smalltalk.Array]
+referencedClasses: ["Array"]
 }),
 smalltalk.Number);
 
@@ -79,7 +80,7 @@ return self;},
 args: [],
 source: unescape('tinyBenchmarks%20%0A%09%22Report%20the%20results%20of%20running%20the%20two%20tiny%20Squeak%20benchmarks.%0A%09ar%209/10/1999%3A%20Adjusted%20to%20run%20at%20least%201%20sec%20to%20get%20more%20stable%20results%22%0A%09%220%20tinyBenchmarks%22%0A%09%22On%20a%20292%20MHz%20G3%20Mac%3A%2022727272%20bytecodes/sec%3B%20984169%20sends/sec%22%0A%09%22On%20a%20400%20MHz%20PII/Win98%3A%20%2018028169%20bytecodes/sec%3B%201081272%20sends/sec%22%0A%09%7C%20t1%20t2%20r%20n1%20n2%20%7C%0A%09n1%20%3A%3D%201.%0A%09%5Bt1%20%3A%3D%20Date%20millisecondsToRun%3A%20%5Bn1%20benchmark%5D.%0A%09t1%20%3C%201000%5D%20whileTrue%3A%5Bn1%20%3A%3D%20n1%20*%202%5D.%20%22Note%3A%20%23benchmark%27s%20runtime%20is%20about%20O%28n%29%22%0A%0A%09n2%20%3A%3D%2016.%0A%09%5Bt2%20%3A%3D%20Date%20millisecondsToRun%3A%20%5Br%20%3A%3D%20n2%20benchFib%5D.%0A%09t2%20%3C%201000%5D%20whileTrue%3A%5Bn2%20%3A%3D%20n2%20+%201%5D.%20%0A%09%22Note%3A%20%23benchFib%27s%20runtime%20is%20about%20O%28k%5En%29%2C%0A%09%09where%20k%20is%20the%20golden%20number%20%3D%20%281%20+%205%20sqrt%29%20/%202%20%3D%201.618....%22%0A%0A%09%5E%20%28%28n1%20*%20500000%20*%201000%29%20/%20t1%29%20printString%2C%20%27%20bytecodes/sec%3B%20%27%2C%0A%09%20%20%28%28r%20*%201000%29%20/%20t2%29%20printString%2C%20%27%20sends/sec%27'),
 messageSends: ["whileTrue:", "millisecondsToRun:", "benchmark", unescape("%3C"), unescape("*"), "benchFib", unescape("+"), unescape("%2C"), "printString", unescape("/")],
-referencedClasses: [smalltalk.Date]
+referencedClasses: ["Date"]
 }),
 smalltalk.Number);
 
@@ -160,7 +161,7 @@ return self;},
 args: [],
 source: unescape('jstinyBenchmarks%0A%09%220%20jstinyBenchmarks%22%0A%0A%09%7C%20t1%20t2%20r%20n1%20n2%20%7C%0A%09n1%20%3A%3D%201.%0A%09%5Bt1%20%3A%3D%20Date%20millisecondsToRun%3A%20%5Bn1%20jsbenchmark%5D.%0A%09t1%20%3C%201000%5D%20whileTrue%3A%5Bn1%20%3A%3D%20n1%20*%202%5D.%20%22Note%3A%20%23benchmark%27s%20runtime%20is%20about%20O%28n%29%22%0A%0A%09n2%20%3A%3D%2028.%0A%09%5Bt2%20%3A%3D%20Date%20millisecondsToRun%3A%20%5Br%20%3A%3D%20n2%20jsbenchFib%5D.%0A%09t2%20%3C%201000%5D%20whileTrue%3A%5Bn2%20%3A%3D%20n2%20+%201%5D.%20%0A%09%22Note%3A%20%23jsbenchFib%27s%20runtime%20is%20about%20O%28k%5En%29%2C%0A%09%09where%20k%20is%20the%20golden%20number%20%3D%20%281%20+%205%20sqrt%29%20/%202%20%3D%201.618....%22%0A%0A%09%5E%20%28%28n1%20*%20500000%20*%201000%29%20/%20t1%29%20printString%2C%20%27%20bytecodes/sec%3B%20%27%2C%0A%09%20%20%28%28r%20*%201000%29%20/%20t2%29%20printString%2C%20%27%20sends/sec%27'),
 messageSends: ["whileTrue:", "millisecondsToRun:", "jsbenchmark", unescape("%3C"), unescape("*"), "jsbenchFib", unescape("+"), unescape("%2C"), "printString", unescape("/")],
-referencedClasses: [smalltalk.Date]
+referencedClasses: ["Date"]
 }),
 smalltalk.Number);
 

+ 34 - 33
js/Canvas.deploy.js

@@ -1,3 +1,4 @@
+smalltalk.addPackage('Canvas', {});
 smalltalk.addClass('HTMLCanvas', smalltalk.Object, ['root'], 'Canvas');
 smalltalk.addMethod(
 '_root_',
@@ -838,6 +839,39 @@ return self;}
 }),
 smalltalk.TagBrush);
 
+smalltalk.addMethod(
+'_width_',
+smalltalk.method({
+selector: 'width:',
+fn: function (aString){
+var self=this;
+smalltalk.send(self, "_at_put_", ["width", aString]);
+return self;}
+}),
+smalltalk.TagBrush);
+
+smalltalk.addMethod(
+'_height_',
+smalltalk.method({
+selector: 'height:',
+fn: function (aString){
+var self=this;
+smalltalk.send(self, "_at_put_", ["height", aString]);
+return self;}
+}),
+smalltalk.TagBrush);
+
+smalltalk.addMethod(
+'_value_',
+smalltalk.method({
+selector: 'value:',
+fn: function (aString){
+var self=this;
+smalltalk.send(self, "_at_put_", ["value", aString]);
+return self;}
+}),
+smalltalk.TagBrush);
+
 smalltalk.addMethod(
 '_asJQuery',
 smalltalk.method({
@@ -972,39 +1006,6 @@ return self;}
 }),
 smalltalk.TagBrush);
 
-smalltalk.addMethod(
-'_width_',
-smalltalk.method({
-selector: 'width:',
-fn: function (aString){
-var self=this;
-smalltalk.send(self, "_at_put_", ["width", aString]);
-return self;}
-}),
-smalltalk.TagBrush);
-
-smalltalk.addMethod(
-'_height_',
-smalltalk.method({
-selector: 'height:',
-fn: function (aString){
-var self=this;
-smalltalk.send(self, "_at_put_", ["height", aString]);
-return self;}
-}),
-smalltalk.TagBrush);
-
-smalltalk.addMethod(
-'_value_',
-smalltalk.method({
-selector: 'value:',
-fn: function (aString){
-var self=this;
-smalltalk.send(self, "_at_put_", ["value", aString]);
-return self;}
-}),
-smalltalk.TagBrush);
-
 
 smalltalk.addMethod(
 '_fromString_canvas_',

+ 55 - 54
js/Canvas.js

@@ -1,3 +1,4 @@
+smalltalk.addPackage('Canvas', {});
 smalltalk.addClass('HTMLCanvas', smalltalk.Object, ['root'], 'Canvas');
 smalltalk.addMethod(
 unescape('_root_'),
@@ -60,7 +61,7 @@ return self;},
 args: [],
 source: unescape('initialize%0A%20%20%20%20super%20initialize.%0A%20%20%20%20root%20ifNil%3A%20%5Broot%20%3A%3D%20TagBrush%20fromString%3A%20%27div%27%20canvas%3A%20self%5D'),
 messageSends: ["initialize", "ifNil:", "fromString:canvas:"],
-referencedClasses: []
+referencedClasses: ["TagBrush"]
 }),
 smalltalk.HTMLCanvas);
 
@@ -76,7 +77,7 @@ return self;},
 args: ["aJQuery"],
 source: unescape('initializeFromJQuery%3A%20aJQuery%0A%20%20%20%20root%20%3A%3D%20TagBrush%20fromJQuery%3A%20aJQuery%20canvas%3A%20self'),
 messageSends: ["fromJQuery:canvas:"],
-referencedClasses: []
+referencedClasses: ["TagBrush"]
 }),
 smalltalk.HTMLCanvas);
 
@@ -92,7 +93,7 @@ return self;},
 args: ["aString"],
 source: unescape('newTag%3A%20aString%0A%20%20%20%20%5ETagBrush%20fromString%3A%20aString%20canvas%3A%20self'),
 messageSends: ["fromString:canvas:"],
-referencedClasses: []
+referencedClasses: ["TagBrush"]
 }),
 smalltalk.HTMLCanvas);
 
@@ -842,7 +843,7 @@ var self=this;
 return (function($rec){smalltalk.send($rec, "_with_", [aString]);return smalltalk.send($rec, "_yourself", []);})(smalltalk.send(self, "_style", []));
 return self;},
 args: ["aString"],
-source: unescape('style%3A%20aString%0A%09%5E%20self%20style%20with%3A%20aString%3B%20yourself%20'),
+source: unescape('style%3A%20aString%0A%09%5E%20self%20style%20with%3A%20aString%3B%20yourself'),
 messageSends: ["with:", "yourself", "style"],
 referencedClasses: []
 }),
@@ -1213,6 +1214,54 @@ referencedClasses: []
 }),
 smalltalk.TagBrush);
 
+smalltalk.addMethod(
+unescape('_width_'),
+smalltalk.method({
+selector: unescape('width%3A'),
+category: 'attributes',
+fn: function (aString){
+var self=this;
+smalltalk.send(self, "_at_put_", ["width", aString]);
+return self;},
+args: ["aString"],
+source: unescape('width%3A%20aString%0A%20%20%20%20self%20%20at%3A%20%27width%27%20put%3A%20aString'),
+messageSends: ["at:put:"],
+referencedClasses: []
+}),
+smalltalk.TagBrush);
+
+smalltalk.addMethod(
+unescape('_height_'),
+smalltalk.method({
+selector: unescape('height%3A'),
+category: 'attributes',
+fn: function (aString){
+var self=this;
+smalltalk.send(self, "_at_put_", ["height", aString]);
+return self;},
+args: ["aString"],
+source: unescape('height%3A%20aString%0A%20%20%20%20self%20%20at%3A%20%27height%27%20put%3A%20aString'),
+messageSends: ["at:put:"],
+referencedClasses: []
+}),
+smalltalk.TagBrush);
+
+smalltalk.addMethod(
+unescape('_value_'),
+smalltalk.method({
+selector: unescape('value%3A'),
+category: 'attributes',
+fn: function (aString){
+var self=this;
+smalltalk.send(self, "_at_put_", ["value", aString]);
+return self;},
+args: ["aString"],
+source: unescape('value%3A%20aString%0A%20%20%20%20self%20%20at%3A%20%27value%27%20put%3A%20aString'),
+messageSends: ["at:put:"],
+referencedClasses: []
+}),
+smalltalk.TagBrush);
+
 smalltalk.addMethod(
 unescape('_asJQuery'),
 smalltalk.method({
@@ -1407,54 +1456,6 @@ referencedClasses: []
 }),
 smalltalk.TagBrush);
 
-smalltalk.addMethod(
-unescape('_width_'),
-smalltalk.method({
-selector: unescape('width%3A'),
-category: 'attributes',
-fn: function (aString){
-var self=this;
-smalltalk.send(self, "_at_put_", ["width", aString]);
-return self;},
-args: ["aString"],
-source: unescape('width%3A%20aString%0A%20%20%20%20self%20%20at%3A%20%27width%27%20put%3A%20aString'),
-messageSends: ["at:put:"],
-referencedClasses: []
-}),
-smalltalk.TagBrush);
-
-smalltalk.addMethod(
-unescape('_height_'),
-smalltalk.method({
-selector: unescape('height%3A'),
-category: 'attributes',
-fn: function (aString){
-var self=this;
-smalltalk.send(self, "_at_put_", ["height", aString]);
-return self;},
-args: ["aString"],
-source: unescape('height%3A%20aString%0A%20%20%20%20self%20%20at%3A%20%27height%27%20put%3A%20aString'),
-messageSends: ["at:put:"],
-referencedClasses: []
-}),
-smalltalk.TagBrush);
-
-smalltalk.addMethod(
-unescape('_value_'),
-smalltalk.method({
-selector: unescape('value%3A'),
-category: 'attributes',
-fn: function (aString){
-var self=this;
-smalltalk.send(self, "_at_put_", ["value", aString]);
-return self;},
-args: ["aString"],
-source: unescape('value%3A%20aString%0A%20%20%20%20self%20%20at%3A%20%27value%27%20put%3A%20aString'),
-messageSends: ["at:put:"],
-referencedClasses: []
-}),
-smalltalk.TagBrush);
-
 
 smalltalk.addMethod(
 unescape('_fromString_canvas_'),
@@ -1518,7 +1519,7 @@ return self;},
 args: ["aJQuery"],
 source: unescape('appendToJQuery%3A%20aJQuery%0A%20%20%20self%20renderOn%3A%20%28HTMLCanvas%20onJQuery%3A%20aJQuery%29'),
 messageSends: ["renderOn:", "onJQuery:"],
-referencedClasses: [smalltalk.HTMLCanvas]
+referencedClasses: ["HTMLCanvas"]
 }),
 smalltalk.Widget);
 
@@ -1584,7 +1585,7 @@ return self;},
 args: ["aJQuery"],
 source: unescape('appendToJQuery%3A%20aJQuery%0A%20%20%20%20self%20value%3A%20%28HTMLCanvas%20onJQuery%3A%20aJQuery%29'),
 messageSends: ["value:", "onJQuery:"],
-referencedClasses: [smalltalk.HTMLCanvas]
+referencedClasses: ["HTMLCanvas"]
 }),
 smalltalk.BlockClosure);
 

File diff suppressed because it is too large
+ 3 - 13
js/Compiler.deploy.js


File diff suppressed because it is too large
+ 5 - 20
js/Compiler.js


+ 1 - 0
js/Examples.deploy.js

@@ -1,3 +1,4 @@
+smalltalk.addPackage('Examples', {});
 smalltalk.addClass('Counter', smalltalk.Widget, ['count', 'header'], 'Examples');
 smalltalk.addMethod(
 '_increase',

+ 10 - 9
js/Examples.js

@@ -1,3 +1,4 @@
+smalltalk.addPackage('Examples', {});
 smalltalk.addClass('Counter', smalltalk.Widget, ['count', 'header'], 'Examples');
 smalltalk.addMethod(
 unescape('_increase'),
@@ -288,7 +289,7 @@ return self;},
 args: [],
 source: unescape('newPiece%0A%09movingPiece%20%3A%3D%20TetrisPiece%20atRandom'),
 messageSends: ["atRandom"],
-referencedClasses: []
+referencedClasses: ["TetrisPiece"]
 }),
 smalltalk.Tetris);
 
@@ -506,7 +507,7 @@ return self;},
 args: [],
 source: unescape('position%0A%09%5Eposition%20ifNil%3A%20%5B%28Tetris%20squares%20x%20/%202%29%20-1%20@%200%5D'),
 messageSends: ["ifNil:", unescape("@"), unescape("-"), unescape("/"), "x", "squares"],
-referencedClasses: [smalltalk.Tetris]
+referencedClasses: ["Tetris"]
 }),
 smalltalk.TetrisPiece);
 
@@ -589,7 +590,7 @@ return self;},
 args: ["aRenderingContext"],
 source: unescape('drawOn%3A%20aRenderingContext%0A%09aRenderingContext%20fillStyle%3A%20self%20color.%0A%09self%20bounds%20do%3A%20%5B%3Aeach%20%7C%7C%20from%20to%20%7C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20from%20%3A%3D%20each%20+%20self%20position*%20Tetris%20squareSize.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20to%20%3A%3D%201@1%20*%20Tetris%20squareSize.%0A%09%09aRenderingContext%20%0A%09%09%09fillRect%3A%20from%20x%20y%3A%20from%20y%20to%3A%20to%20x%20y%3A%20to%20y%3B%0A%09%09%09strokeStyle%3A%20%27%23999%27%3B%0A%09%09%09lineWidth%3A%202%3B%0A%09%09%09strokeRect%3A%20from%20x%20y%3A%20from%20y%20to%3A%20to%20x%20y%3A%20to%20y%5D'),
 messageSends: ["fillStyle:", "color", "do:", "bounds", unescape("*"), unescape("+"), "position", "squareSize", unescape("@"), "fillRect:y:to:y:", "x", "y", "strokeStyle:", "lineWidth:", "strokeRect:y:to:y:"],
-referencedClasses: [smalltalk.Tetris]
+referencedClasses: ["Tetris"]
 }),
 smalltalk.TetrisPiece);
 
@@ -605,7 +606,7 @@ return self;},
 args: [],
 source: unescape('canMove%0A%09%5Eself%20position%20y%20%3C%20%28Tetris%20squares%20y%20-%20self%20height%29'),
 messageSends: [unescape("%3C"), "y", "position", unescape("-"), "squares", "height"],
-referencedClasses: [smalltalk.Tetris]
+referencedClasses: ["Tetris"]
 }),
 smalltalk.TetrisPiece);
 
@@ -656,7 +657,7 @@ return self;},
 args: [],
 source: unescape('bounds%0A%09%5EArray%20new%0A%09%09add%3A%200@0%3B%0A%09%09add%3A%200@1%3B%0A%09%09add%3A%201@0%3B%0A%09%09add%3A%201@1%3B%0A%09%09yourself'),
 messageSends: ["add:", unescape("@"), "yourself", "new"],
-referencedClasses: [smalltalk.Array]
+referencedClasses: ["Array"]
 }),
 smalltalk.TetrisPieceO);
 
@@ -675,7 +676,7 @@ return self;},
 args: [],
 source: unescape('bounds%0A%09%5EArray%20new%0A%09%09add%3A%200@0%3B%0A%09%09add%3A%200@1%3B%0A%09%09add%3A%200@2%3B%0A%09%09add%3A%201@2%3B%0A%09%09yourself'),
 messageSends: ["add:", unescape("@"), "yourself", "new"],
-referencedClasses: [smalltalk.Array]
+referencedClasses: ["Array"]
 }),
 smalltalk.TetrisPieceL);
 
@@ -742,7 +743,7 @@ return self;},
 args: [],
 source: unescape('bounds%0A%09%5EArray%20new%0A%09%09add%3A%201@0%3B%0A%09%09add%3A%201@1%3B%0A%09%09add%3A%201@2%3B%0A%09%09add%3A%200@2%3B%0A%09%09yourself'),
 messageSends: ["add:", unescape("@"), "yourself", "new"],
-referencedClasses: [smalltalk.Array]
+referencedClasses: ["Array"]
 }),
 smalltalk.TetrisPieceJ);
 
@@ -793,7 +794,7 @@ return self;},
 args: [],
 source: unescape('bounds%0A%09%5EArray%20new%0A%09%09add%3A%200@0%3B%0A%09%09add%3A%200@1%3B%0A%09%09add%3A%200@2%3B%0A%09%09add%3A%200@3%3B%0A%09%09yourself'),
 messageSends: ["add:", unescape("@"), "yourself", "new"],
-referencedClasses: [smalltalk.Array]
+referencedClasses: ["Array"]
 }),
 smalltalk.TetrisPieceI);
 
@@ -828,7 +829,7 @@ return self;},
 args: [],
 source: unescape('bounds%0A%09%5EArray%20new%0A%09%09add%3A%200@0%3B%0A%09%09add%3A%201@0%3B%0A%09%09add%3A%202@0%3B%0A%09%09add%3A%201@1%3B%0A%09%09yourself'),
 messageSends: ["add:", unescape("@"), "yourself", "new"],
-referencedClasses: [smalltalk.Array]
+referencedClasses: ["Array"]
 }),
 smalltalk.TetrisPieceT);
 

File diff suppressed because it is too large
+ 74 - 1
js/IDE.deploy.js


File diff suppressed because it is too large
+ 128 - 25
js/IDE.js


+ 1 - 0
js/Kernel-Tests.deploy.js

@@ -1,3 +1,4 @@
+smalltalk.addPackage('Kernel-Tests', {});
 smalltalk.addClass('StringTest', smalltalk.TestCase, [], 'Kernel-Tests');
 smalltalk.addMethod(
 '_testJoin',

+ 5 - 4
js/Kernel-Tests.js

@@ -1,3 +1,4 @@
+smalltalk.addPackage('Kernel-Tests', {});
 smalltalk.addClass('StringTest', smalltalk.TestCase, [], 'Kernel-Tests');
 smalltalk.addMethod(
 unescape('_testJoin'),
@@ -27,7 +28,7 @@ return self;},
 args: [],
 source: unescape('testStreamContents%0A%09self%20%0A%09%09assert%3A%20%27hello%20world%27%20%0A%09%09equals%3A%20%28String%20streamContents%3A%20%5B%3AaStream%7C%20aStream%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%09%09%09%09%09nextPutAll%3A%20%27hello%27%3B%20space%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%09%09%09%09%09nextPutAll%3A%20%27world%27%5D%29'),
 messageSends: ["assert:equals:", "streamContents:", "nextPutAll:", "space"],
-referencedClasses: [smalltalk.String]
+referencedClasses: ["String"]
 }),
 smalltalk.StringTest);
 
@@ -99,7 +100,7 @@ return self;},
 args: [],
 source: unescape('testPrintString%0A%09self%0A%09%09assert%3A%20%27a%20Dictionary%28%27%27firstname%27%27%20-%3E%20%27%27James%27%27%20%2C%20%27%27lastname%27%27%20-%3E%20%27%27Bond%27%27%29%27%20%0A%09%09equals%3A%20%28Dictionary%20new%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%09at%3A%27firstname%27%20put%3A%20%27James%27%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%09at%3A%27lastname%27%20put%3A%20%27Bond%27%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%09printString%29'),
 messageSends: ["assert:equals:", "at:put:", "printString", "new"],
-referencedClasses: [smalltalk.Dictionary]
+referencedClasses: ["Dictionary"]
 }),
 smalltalk.DictionaryTest);
 
@@ -126,7 +127,7 @@ return self;},
 args: [],
 source: unescape('testEquality%0A%09%7C%20d1%20d2%20%7C%0A%0A%09self%20assert%3A%20Dictionary%20new%20%3D%20Dictionary%20new.%0A%09%09%0A%09d1%20%3A%3D%20Dictionary%20new%20at%3A%201%20put%3A%202%3B%20yourself.%0A%09d2%20%3A%3D%20Dictionary%20new%20at%3A%201%20put%3A%202%3B%20yourself.%0A%09self%20assert%3A%20d1%20%3D%20d2.%0A%0A%09d2%20%3A%3D%20Dictionary%20new%20at%3A%201%20put%3A%203%3B%20yourself.%0A%09self%20deny%3A%20d1%20%3D%20d2.%0A%0A%09d2%20%3A%3D%20Dictionary%20new%20at%3A%202%20put%3A%202%3B%20yourself.%0A%09self%20deny%3A%20d1%20%3D%20d2.%0A%0A%09d2%20%3A%3D%20Dictionary%20new%20at%3A%201%20put%3A%202%3B%20at%3A%203%20put%3A%204%3B%20yourself.%0A%09self%20deny%3A%20d1%20%3D%20d2.'),
 messageSends: ["assert:", unescape("%3D"), "new", "at:put:", "yourself", "deny:"],
-referencedClasses: [smalltalk.Dictionary]
+referencedClasses: ["Dictionary"]
 }),
 smalltalk.DictionaryTest);
 
@@ -142,7 +143,7 @@ return self;},
 args: [],
 source: unescape('testDynamicDictionaries%0A%09self%20assert%3A%20%23%7B1%20-%3E%20%27hello%27.%202%20-%3E%20%27world%27%7D%20%3D%20%28Dictionary%20with%3A%201%20-%3E%20%27hello%27%20with%3A%202%20-%3E%20%27world%27%29'),
 messageSends: ["assert:", unescape("%3D"), unescape("-%3E"), "with:with:"],
-referencedClasses: [smalltalk.Dictionary]
+referencedClasses: ["Dictionary"]
 }),
 smalltalk.DictionaryTest);
 

+ 645 - 37
js/Kernel.deploy.js

@@ -1,3 +1,4 @@
+smalltalk.addPackage('Kernel', {});
 smalltalk.addClass('Object', smalltalk.nil, [], 'Kernel');
 smalltalk.addMethod(
 '__eq',
@@ -559,6 +560,28 @@ return self;}
 }),
 smalltalk.Object);
 
+smalltalk.addMethod(
+'_storeString',
+smalltalk.method({
+selector: 'storeString',
+fn: function (){
+var self=this;
+return smalltalk.send((smalltalk.String || String), "_streamContents_", [(function(s){return smalltalk.send(self, "_storeOn_", [s]);})]);
+return self;}
+}),
+smalltalk.Object);
+
+smalltalk.addMethod(
+'_storeOn_',
+smalltalk.method({
+selector: 'storeOn:',
+fn: function (aStream){
+var self=this;
+smalltalk.send(aStream, "_nextPutAll_", [smalltalk.send(self, "_printString", [])]);
+return self;}
+}),
+smalltalk.Object);
+
 
 smalltalk.addMethod(
 '_initialize',
@@ -584,17 +607,6 @@ return self;}
 }),
 smalltalk.Smalltalk);
 
-smalltalk.addMethod(
-'_readJSON_',
-smalltalk.method({
-selector: 'readJSON:',
-fn: function (anObject){
-var self=this;
-return self.readJSObject(anObject);
-return self;}
-}),
-smalltalk.Smalltalk);
-
 smalltalk.addMethod(
 '_at_',
 smalltalk.method({
@@ -708,7 +720,7 @@ smalltalk.method({
 selector: 'createPackage:',
 fn: function (packageName){
 var self=this;
-return smalltalk.addPackage(packageName);
+return smalltalk.addPackage(packageName, nil);
 return self;}
 }),
 smalltalk.Smalltalk);
@@ -765,6 +777,31 @@ return self;}
 }),
 smalltalk.Smalltalk);
 
+smalltalk.addMethod(
+'_createPackage_properties_',
+smalltalk.method({
+selector: 'createPackage:properties:',
+fn: function (packageName, aDict){
+var self=this;
+var object=nil;
+object = {};;
+smalltalk.send(aDict, "_keysAndValuesDo_", [(function(key, value){return object[key] = value;})]);
+return smalltalk.addPackage(packageName, object);
+return self;}
+}),
+smalltalk.Smalltalk);
+
+smalltalk.addMethod(
+'_readJSObject_',
+smalltalk.method({
+selector: 'readJSObject:',
+fn: function (anObject){
+var self=this;
+return self.readJSObject(anObject);
+return self;}
+}),
+smalltalk.Smalltalk);
+
 
 smalltalk.Smalltalk.klass.iVarNames = ['current'];
 smalltalk.addMethod(
@@ -786,18 +823,7 @@ smalltalk.method({
 selector: 'name',
 fn: function (){
 var self=this;
-return self.pkgName || nil;
-return self;}
-}),
-smalltalk.Package);
-
-smalltalk.addMethod(
-'_requires',
-smalltalk.method({
-selector: 'requires',
-fn: function (){
-var self=this;
-return self.requires || nil;
+return self.pkgName;
 return self;}
 }),
 smalltalk.Package);
@@ -836,34 +862,114 @@ return self;}
 smalltalk.Package);
 
 smalltalk.addMethod(
-'_commitPathJs',
+'_dependencies',
 smalltalk.method({
-selector: 'commitPathJs',
+selector: 'dependencies',
 fn: function (){
 var self=this;
-return (($receiver = self['@commitPathJs']) == nil || $receiver == undefined) ? (function(){return smalltalk.send(smalltalk.send(self, "_class", []), "_defaultCommitPathJs", []);})() : $receiver;
+return smalltalk.send(self, "_propertyAt_ifAbsent_", ["dependencies", (function(){return [];})]);
 return self;}
 }),
 smalltalk.Package);
 
 smalltalk.addMethod(
-'_commitPathSt',
+'_dependencies_',
 smalltalk.method({
-selector: 'commitPathSt',
+selector: 'dependencies:',
+fn: function (anArray){
+var self=this;
+return smalltalk.send(self, "_propertyAt_put_", ["dependencies", anArray]);
+return self;}
+}),
+smalltalk.Package);
+
+smalltalk.addMethod(
+'_properties',
+smalltalk.method({
+selector: 'properties',
 fn: function (){
 var self=this;
-return (($receiver = self['@commitPathSt']) == nil || $receiver == undefined) ? (function(){return smalltalk.send(smalltalk.send(self, "_class", []), "_defaultCommitPathSt", []);})() : $receiver;
+return smalltalk.send(smalltalk.send((smalltalk.Smalltalk || Smalltalk), "_current", []), "_readJSObject_", [smalltalk.send(self, "_basicAt_", ["properties"])]);
 return self;}
 }),
 smalltalk.Package);
 
 smalltalk.addMethod(
-'_commitPathJs_',
+'_propertiesAsJSON',
 smalltalk.method({
-selector: 'commitPathJs:',
-fn: function (aString){
+selector: 'propertiesAsJSON',
+fn: function (){
 var self=this;
-self['@commitPathJs']=aString;
+return JSON.stringify(self.properties);
+return self;}
+}),
+smalltalk.Package);
+
+smalltalk.addMethod(
+'_properties_',
+smalltalk.method({
+selector: 'properties:',
+fn: function (aDict){
+var self=this;
+var object=nil;
+object = {};;
+smalltalk.send(aDict, "_keysAndValuesDo_", [(function(key, value){return object[key] = value;})]);
+return self.properties = object;
+return self;}
+}),
+smalltalk.Package);
+
+smalltalk.addMethod(
+'_jsProperties',
+smalltalk.method({
+selector: 'jsProperties',
+fn: function (){
+var self=this;
+return self.properties;
+return self;}
+}),
+smalltalk.Package);
+
+smalltalk.addMethod(
+'_jsProperties_',
+smalltalk.method({
+selector: 'jsProperties:',
+fn: function (aJSObject){
+var self=this;
+return self.properties = aJSObject;
+return self;}
+}),
+smalltalk.Package);
+
+smalltalk.addMethod(
+'_propertyAt_',
+smalltalk.method({
+selector: 'propertyAt:',
+fn: function (key){
+var self=this;
+return self.properties[key];
+return self;}
+}),
+smalltalk.Package);
+
+smalltalk.addMethod(
+'_propertyAt_put_',
+smalltalk.method({
+selector: 'propertyAt:put:',
+fn: function (key, value){
+var self=this;
+return self.properties[key] = value;
+return self;}
+}),
+smalltalk.Package);
+
+smalltalk.addMethod(
+'_propertyAt_ifAbsent_',
+smalltalk.method({
+selector: 'propertyAt:ifAbsent:',
+fn: function (key, block){
+var self=this;
+return (($receiver = smalltalk.send(self, "_propertyAt_", [key])) == nil || $receiver == undefined) ? (function(){return smalltalk.send(block, "_value", []);})() : $receiver;
 return self;}
 }),
 smalltalk.Package);
@@ -879,6 +985,39 @@ return self;}
 }),
 smalltalk.Package);
 
+smalltalk.addMethod(
+'_commitPathJs',
+smalltalk.method({
+selector: 'commitPathJs',
+fn: function (){
+var self=this;
+return (($receiver = self['@commitPathJs']) == nil || $receiver == undefined) ? (function(){return smalltalk.send(smalltalk.send(self, "_class", []), "_defaultCommitPathJs", []);})() : $receiver;
+return self;}
+}),
+smalltalk.Package);
+
+smalltalk.addMethod(
+'_commitPathSt',
+smalltalk.method({
+selector: 'commitPathSt',
+fn: function (){
+var self=this;
+return (($receiver = self['@commitPathSt']) == nil || $receiver == undefined) ? (function(){return smalltalk.send(smalltalk.send(self, "_class", []), "_defaultCommitPathSt", []);})() : $receiver;
+return self;}
+}),
+smalltalk.Package);
+
+smalltalk.addMethod(
+'_commitPathJs_',
+smalltalk.method({
+selector: 'commitPathJs:',
+fn: function (aString){
+var self=this;
+self['@commitPathJs']=aString;
+return self;}
+}),
+smalltalk.Package);
+
 
 smalltalk.Package.klass.iVarNames = ['defaultCommitPathJs','defaultCommitPathSt'];
 smalltalk.addMethod(
@@ -1925,9 +2064,9 @@ return self;}
 smalltalk.Number);
 
 smalltalk.addMethod(
-'_\\',
+'_\',
 smalltalk.method({
-selector: '\\',
+selector: '\',
 fn: function (aNumber){
 var self=this;
 return self % aNumber;
@@ -1990,6 +2129,39 @@ return self;}
 }),
 smalltalk.Number);
 
+smalltalk.addMethod(
+'_\\',
+smalltalk.method({
+selector: '\\',
+fn: function (aNumber){
+var self=this;
+return self % aNumber;
+return self;}
+}),
+smalltalk.Number);
+
+smalltalk.addMethod(
+'_sqrt',
+smalltalk.method({
+selector: 'sqrt',
+fn: function (){
+var self=this;
+return Math.sqrt(self);
+return self;}
+}),
+smalltalk.Number);
+
+smalltalk.addMethod(
+'_squared',
+smalltalk.method({
+selector: 'squared',
+fn: function (){
+var self=this;
+return self * self;
+return self;}
+}),
+smalltalk.Number);
+
 
 smalltalk.addMethod(
 '_pi',
@@ -2180,6 +2352,30 @@ return self;}
 }),
 smalltalk.BlockClosure);
 
+smalltalk.addMethod(
+'_numArgs',
+smalltalk.method({
+selector: 'numArgs',
+fn: function (){
+var self=this;
+return self.length;
+return self;}
+}),
+smalltalk.BlockClosure);
+
+smalltalk.addMethod(
+'_ensure_',
+smalltalk.method({
+selector: 'ensure:',
+fn: function (aBlock){
+var self=this;
+var success=nil;
+success=false;
+smalltalk.send((function(){smalltalk.send(self, "_value", []);success=true;return smalltalk.send(aBlock, "_value", []);}), "_on_do_", [(smalltalk.Error || Error), (function(ex){((($receiver = success).klass === smalltalk.Boolean) ? (! $receiver ? (function(){return smalltalk.send(aBlock, "_value", []);})() : nil) : smalltalk.send($receiver, "_ifFalse_", [(function(){return smalltalk.send(aBlock, "_value", []);})]));return smalltalk.send(ex, "_signal", []);})]);
+return self;}
+}),
+smalltalk.BlockClosure);
+
 
 
 smalltalk.addClass('Boolean', smalltalk.Object, [], 'Kernel');
@@ -4626,6 +4822,28 @@ return self;}
 }),
 smalltalk.Error);
 
+smalltalk.addMethod(
+'_jsStack',
+smalltalk.method({
+selector: 'jsStack',
+fn: function (){
+var self=this;
+return self.stack;
+return self;}
+}),
+smalltalk.Error);
+
+smalltalk.addMethod(
+'_isSmalltalkError',
+smalltalk.method({
+selector: 'isSmalltalkError',
+fn: function (){
+var self=this;
+return self.smalltalkError === true;
+return self;}
+}),
+smalltalk.Error);
+
 
 smalltalk.addMethod(
 '_signal_',
@@ -4764,6 +4982,19 @@ return self;}
 }),
 smalltalk.Association);
 
+smalltalk.addMethod(
+'_storeOn_',
+smalltalk.method({
+selector: 'storeOn:',
+fn: function (aStream){
+var self=this;
+smalltalk.send(self['@key'], "_storeOn_", [aStream]);
+smalltalk.send(aStream, "_nextPutAll_", [unescape("-%3E")]);
+smalltalk.send(self['@value'], "_storeOn_", [aStream]);
+return self;}
+}),
+smalltalk.Association);
+
 
 smalltalk.addMethod(
 '_key_value_',
@@ -5107,6 +5338,19 @@ return self;}
 }),
 smalltalk.Dictionary);
 
+smalltalk.addMethod(
+'_storeOn_',
+smalltalk.method({
+selector: 'storeOn:',
+fn: function (aStream){
+var self=this;
+smalltalk.send(aStream, "_nextPutAll_", [unescape("%23%7B")]);
+smalltalk.send(smalltalk.send(self, "_associations", []), "_do_separatedBy_", [(function(each){return smalltalk.send(each, "_storeOn_", [aStream]);}), (function(){return smalltalk.send(aStream, "_nextPutAll_", [". "]);})]);
+smalltalk.send(aStream, "_nextPutAll_", [unescape("%7D")]);
+return self;}
+}),
+smalltalk.Dictionary);
+
 
 smalltalk.addMethod(
 '_fromPairs_',
@@ -5208,6 +5452,23 @@ return self;}
 }),
 smalltalk.ClassBuilder);
 
+smalltalk.addMethod(
+'_copyClass_named_',
+smalltalk.method({
+selector: 'copyClass:named:',
+fn: function (aClass, aString){
+var self=this;
+var newClass=nil;
+newClass=smalltalk.send(self, "_addSubclassOf_named_instanceVariableNames_package_", [smalltalk.send(aClass, "_superclass", []), aString, smalltalk.send(aClass, "_instanceVariableNames", []), smalltalk.send(smalltalk.send(aClass, "_package", []), "_name", [])]);
+smalltalk.send(self, "_setupClass_", [newClass]);
+smalltalk.send(smalltalk.send(smalltalk.send(aClass, "_methodDictionary", []), "_values", []), "_do_", [(function(each){smalltalk.send(newClass, "_addCompiledMethod_", [smalltalk.send(smalltalk.send((smalltalk.Compiler || Compiler), "_new", []), "_load_forClass_", [smalltalk.send(each, "_source", []), newClass])]);return smalltalk.send(smalltalk.send(smalltalk.send(newClass, "_methodDictionary", []), "_at_", [smalltalk.send(each, "_selector", [])]), "_category_", [smalltalk.send(each, "_category", [])]);})]);
+smalltalk.send(smalltalk.send(smalltalk.send(smalltalk.send(aClass, "_class", []), "_methodDictionary", []), "_values", []), "_do_", [(function(each){smalltalk.send(smalltalk.send(newClass, "_class", []), "_addCompiledMethod_", [smalltalk.send(smalltalk.send((smalltalk.Compiler || Compiler), "_new", []), "_load_forClass_", [smalltalk.send(each, "_source", []), smalltalk.send(newClass, "_class", [])])]);return smalltalk.send(smalltalk.send(smalltalk.send(smalltalk.send(newClass, "_class", []), "_methodDictionary", []), "_at_", [smalltalk.send(each, "_selector", [])]), "_category_", [smalltalk.send(each, "_category", [])]);})]);
+smalltalk.send(self, "_setupClass_", [newClass]);
+return newClass;
+return self;}
+}),
+smalltalk.ClassBuilder);
+
 
 
 smalltalk.addClass('ClassCategoryReader', smalltalk.Object, ['class', 'category', 'chunkParser'], 'Kernel');
@@ -6382,7 +6643,9 @@ smalltalk.method({
 selector: 'show:',
 fn: function (anObject){
 var self=this;
-console.log(String(anObject._asString()));
+var string=nil;
+string=smalltalk.send(anObject, "_asString", []);
+console.log(String(string));
 return self;}
 }),
 smalltalk.ConsoleTranscript);
@@ -6411,3 +6674,348 @@ return self;}
 smalltalk.ConsoleTranscript.klass);
 
 
+smalltalk.addClass('Dictionary2', smalltalk.Dictionary, ['keys'], 'Kernel');
+smalltalk.addMethod(
+'__eq',
+smalltalk.method({
+selector: '=',
+fn: function (aDictionary){
+var self=this;
+try{((($receiver = smalltalk.send(smalltalk.send(self, "_class", []), "__eq", [smalltalk.send(aDictionary, "_class", [])])).klass === smalltalk.Boolean) ? (! $receiver ? (function(){return (function(){throw({name: 'stReturn', selector: '__eq', fn: function(){return false}})})();})() : nil) : smalltalk.send($receiver, "_ifFalse_", [(function(){return (function(){throw({name: 'stReturn', selector: '__eq', fn: function(){return false}})})();})]));
+((($receiver = smalltalk.send(smalltalk.send(self, "_size", []), "__eq", [smalltalk.send(aDictionary, "_size", [])])).klass === smalltalk.Boolean) ? (! $receiver ? (function(){return (function(){throw({name: 'stReturn', selector: '__eq', fn: function(){return false}})})();})() : nil) : smalltalk.send($receiver, "_ifFalse_", [(function(){return (function(){throw({name: 'stReturn', selector: '__eq', fn: function(){return false}})})();})]));
+(function(){throw({name: 'stReturn', selector: '__eq', fn: function(){return smalltalk.send(smalltalk.send(self, "_associations", []), "__eq", [smalltalk.send(aDictionary, "_associations", [])])}})})();
+return self;
+} catch(e) {if(e.name === 'stReturn' && e.selector === '__eq'){return e.fn()} throw(e)}}
+}),
+smalltalk.Dictionary2);
+
+smalltalk.addMethod(
+'_shallowCopy',
+smalltalk.method({
+selector: 'shallowCopy',
+fn: function (){
+var self=this;
+var copy=nil;
+copy=smalltalk.send(smalltalk.send(self, "_class", []), "_new", []);
+smalltalk.send(self, "_associationsDo_", [(function(each){return smalltalk.send(copy, "_at_put_", [smalltalk.send(each, "_key", []), smalltalk.send(each, "_value", [])]);})]);
+return copy;
+return self;}
+}),
+smalltalk.Dictionary2);
+
+smalltalk.addMethod(
+'_initialize',
+smalltalk.method({
+selector: 'initialize',
+fn: function (){
+var self=this;
+smalltalk.send(self, "_initialize", [], smalltalk.Dictionary);
+self['@keys']=[];
+return self;}
+}),
+smalltalk.Dictionary2);
+
+smalltalk.addMethod(
+'_size',
+smalltalk.method({
+selector: 'size',
+fn: function (){
+var self=this;
+return smalltalk.send(self['@keys'], "_size", []);
+return self;}
+}),
+smalltalk.Dictionary2);
+
+smalltalk.addMethod(
+'_associations',
+smalltalk.method({
+selector: 'associations',
+fn: function (){
+var self=this;
+var associations=nil;
+associations=[];
+smalltalk.send(self['@keys'], "_do_", [(function(each){return smalltalk.send(associations, "_add_", [smalltalk.send((smalltalk.Association || Association), "_key_value_", [each, smalltalk.send(self, "_at_", [each])])]);})]);
+return associations;
+return self;}
+}),
+smalltalk.Dictionary2);
+
+smalltalk.addMethod(
+'_keys',
+smalltalk.method({
+selector: 'keys',
+fn: function (){
+var self=this;
+return smalltalk.send(self['@keys'], "_copy", []);
+return self;}
+}),
+smalltalk.Dictionary2);
+
+smalltalk.addMethod(
+'_values',
+smalltalk.method({
+selector: 'values',
+fn: function (){
+var self=this;
+return smalltalk.send(self['@keys'], "_collect_", [(function(each){return smalltalk.send(self, "_at_", [each]);})]);
+return self;}
+}),
+smalltalk.Dictionary2);
+
+smalltalk.addMethod(
+'_at_put_',
+smalltalk.method({
+selector: 'at:put:',
+fn: function (aKey, aValue){
+var self=this;
+((($receiver = smalltalk.send(self['@keys'], "_includes_", [aKey])).klass === smalltalk.Boolean) ? (! $receiver ? (function(){return smalltalk.send(self['@keys'], "_add_", [aKey]);})() : nil) : smalltalk.send($receiver, "_ifFalse_", [(function(){return smalltalk.send(self['@keys'], "_add_", [aKey]);})]));
+return smalltalk.send(self, "_basicAt_put_", [aKey, aValue]);
+return self;}
+}),
+smalltalk.Dictionary2);
+
+smalltalk.addMethod(
+'_at_ifAbsent_',
+smalltalk.method({
+selector: 'at:ifAbsent:',
+fn: function (aKey, aBlock){
+var self=this;
+return smalltalk.send(smalltalk.send(smalltalk.send(self, "_keys", []), "_includes_", [aKey]), "_ifTrue_ifFalse_", [(function(){return smalltalk.send(self, "_basicAt_", [aKey]);}), aBlock]);
+return self;}
+}),
+smalltalk.Dictionary2);
+
+smalltalk.addMethod(
+'_at_ifAbsentPut_',
+smalltalk.method({
+selector: 'at:ifAbsentPut:',
+fn: function (aKey, aBlock){
+var self=this;
+return smalltalk.send(self, "_at_ifAbsent_", [aKey, (function(){return smalltalk.send(self, "_at_put_", [aKey, smalltalk.send(aBlock, "_value", [])]);})]);
+return self;}
+}),
+smalltalk.Dictionary2);
+
+smalltalk.addMethod(
+'_at_ifPresent_',
+smalltalk.method({
+selector: 'at:ifPresent:',
+fn: function (aKey, aBlock){
+var self=this;
+return (($receiver = smalltalk.send(self, "_basicAt_", [aKey])) != nil && $receiver != undefined) ? (function(){return smalltalk.send(aBlock, "_value_", [smalltalk.send(self, "_at_", [aKey])]);})() : nil;
+return self;}
+}),
+smalltalk.Dictionary2);
+
+smalltalk.addMethod(
+'_at_ifPresent_ifAbsent_',
+smalltalk.method({
+selector: 'at:ifPresent:ifAbsent:',
+fn: function (aKey, aBlock, anotherBlock){
+var self=this;
+return smalltalk.send(smalltalk.send(self, "_basicAt_", [aKey]), "_ifNil_ifNotNil_", [anotherBlock, (function(){return smalltalk.send(aBlock, "_value_", [smalltalk.send(self, "_at_", [aKey])]);})]);
+return self;}
+}),
+smalltalk.Dictionary2);
+
+smalltalk.addMethod(
+'_add_',
+smalltalk.method({
+selector: 'add:',
+fn: function (anAssociation){
+var self=this;
+smalltalk.send(self, "_at_put_", [smalltalk.send(anAssociation, "_key", []), smalltalk.send(anAssociation, "_value", [])]);
+return self;}
+}),
+smalltalk.Dictionary2);
+
+smalltalk.addMethod(
+'_addAll_',
+smalltalk.method({
+selector: 'addAll:',
+fn: function (aDictionary){
+var self=this;
+smalltalk.send(self, "_addAll_", [smalltalk.send(aDictionary, "_associations", [])], smalltalk.Dictionary);
+return aDictionary;
+return self;}
+}),
+smalltalk.Dictionary2);
+
+smalltalk.addMethod(
+'__comma',
+smalltalk.method({
+selector: ',',
+fn: function (aCollection){
+var self=this;
+smalltalk.send(self, "_shouldNotImplement", []);
+return self;}
+}),
+smalltalk.Dictionary2);
+
+smalltalk.addMethod(
+'_copyFrom_to_',
+smalltalk.method({
+selector: 'copyFrom:to:',
+fn: function (anIndex, anotherIndex){
+var self=this;
+smalltalk.send(self, "_shouldNotImplement", []);
+return self;}
+}),
+smalltalk.Dictionary2);
+
+smalltalk.addMethod(
+'_associationsDo_',
+smalltalk.method({
+selector: 'associationsDo:',
+fn: function (aBlock){
+var self=this;
+smalltalk.send(smalltalk.send(self, "_associations", []), "_do_", [aBlock]);
+return self;}
+}),
+smalltalk.Dictionary2);
+
+smalltalk.addMethod(
+'_keysAndValuesDo_',
+smalltalk.method({
+selector: 'keysAndValuesDo:',
+fn: function (aBlock){
+var self=this;
+smalltalk.send(self, "_associationsDo_", [(function(each){return smalltalk.send(aBlock, "_value_value_", [smalltalk.send(each, "_key", []), smalltalk.send(each, "_value", [])]);})]);
+return self;}
+}),
+smalltalk.Dictionary2);
+
+smalltalk.addMethod(
+'_do_',
+smalltalk.method({
+selector: 'do:',
+fn: function (aBlock){
+var self=this;
+smalltalk.send(smalltalk.send(self, "_values", []), "_do_", [aBlock]);
+return self;}
+}),
+smalltalk.Dictionary2);
+
+smalltalk.addMethod(
+'_select_',
+smalltalk.method({
+selector: 'select:',
+fn: function (aBlock){
+var self=this;
+var newDict=nil;
+newDict=smalltalk.send(smalltalk.send(self, "_class", []), "_new", []);
+smalltalk.send(self, "_keysAndValuesDo_", [(function(key, value){return ((($receiver = smalltalk.send(aBlock, "_value_", [value])).klass === smalltalk.Boolean) ? ($receiver ? (function(){return smalltalk.send(newDict, "_at_put_", [key, value]);})() : nil) : smalltalk.send($receiver, "_ifTrue_", [(function(){return smalltalk.send(newDict, "_at_put_", [key, value]);})]));})]);
+return newDict;
+return self;}
+}),
+smalltalk.Dictionary2);
+
+smalltalk.addMethod(
+'_collect_',
+smalltalk.method({
+selector: 'collect:',
+fn: function (aBlock){
+var self=this;
+var newDict=nil;
+newDict=smalltalk.send(smalltalk.send(self, "_class", []), "_new", []);
+smalltalk.send(self, "_keysAndValuesDo_", [(function(key, value){return smalltalk.send(newDict, "_at_put_", [key, smalltalk.send(aBlock, "_value_", [value])]);})]);
+return newDict;
+return self;}
+}),
+smalltalk.Dictionary2);
+
+smalltalk.addMethod(
+'_detect_ifNone_',
+smalltalk.method({
+selector: 'detect:ifNone:',
+fn: function (aBlock, anotherBlock){
+var self=this;
+return smalltalk.send(smalltalk.send(self, "_values", []), "_detect_ifNone_", [aBlock, anotherBlock]);
+return self;}
+}),
+smalltalk.Dictionary2);
+
+smalltalk.addMethod(
+'_includes_',
+smalltalk.method({
+selector: 'includes:',
+fn: function (anObject){
+var self=this;
+return smalltalk.send(smalltalk.send(self, "_values", []), "_includes_", [anObject]);
+return self;}
+}),
+smalltalk.Dictionary2);
+
+smalltalk.addMethod(
+'_remove_',
+smalltalk.method({
+selector: 'remove:',
+fn: function (aKey){
+var self=this;
+smalltalk.send(self, "_removeKey_", [aKey]);
+return self;}
+}),
+smalltalk.Dictionary2);
+
+smalltalk.addMethod(
+'_removeKey_',
+smalltalk.method({
+selector: 'removeKey:',
+fn: function (aKey){
+var self=this;
+smalltalk.send(self['@keys'], "_remove_", [aKey]);
+return self;}
+}),
+smalltalk.Dictionary2);
+
+smalltalk.addMethod(
+'_at_',
+smalltalk.method({
+selector: 'at:',
+fn: function (aKey){
+var self=this;
+return smalltalk.send(self, "_at_ifAbsent_", [aKey, (function(){return smalltalk.send(self, "_errorNotFound", []);})]);
+return self;}
+}),
+smalltalk.Dictionary2);
+
+smalltalk.addMethod(
+'_asJSONObject',
+smalltalk.method({
+selector: 'asJSONObject',
+fn: function (){
+var self=this;
+var object=nil;
+object=smalltalk.send((smalltalk.Object || Object), "_new", []);
+smalltalk.send(self, "_keysAndValuesDo_", [(function(key, value){return smalltalk.send(object, "_basicAt_put_", [key, smalltalk.send(value, "_asJSONObject", [])]);})]);
+return object;
+return self;}
+}),
+smalltalk.Dictionary2);
+
+smalltalk.addMethod(
+'_printString',
+smalltalk.method({
+selector: 'printString',
+fn: function (){
+var self=this;
+return smalltalk.send((smalltalk.String || String), "_streamContents_", [(function(aStream){(function($rec){smalltalk.send($rec, "_nextPutAll_", [smalltalk.send(self, "_printString", [], smalltalk.Dictionary)]);return smalltalk.send($rec, "_nextPutAll_", [unescape("%28")]);})(aStream);smalltalk.send(smalltalk.send(self, "_associations", []), "_do_separatedBy_", [(function(anAssociation){return (function($rec){smalltalk.send($rec, "_nextPutAll_", [smalltalk.send(smalltalk.send(anAssociation, "_key", []), "_printString", [])]);smalltalk.send($rec, "_nextPutAll_", [unescape("%20-%3E%20")]);return smalltalk.send($rec, "_nextPutAll_", [smalltalk.send(smalltalk.send(anAssociation, "_value", []), "_printString", [])]);})(aStream);}), (function(){return smalltalk.send(aStream, "_nextPutAll_", [unescape("%20%2C%20")]);})]);return smalltalk.send(aStream, "_nextPutAll_", [unescape("%29")]);})]);
+return self;}
+}),
+smalltalk.Dictionary2);
+
+smalltalk.addMethod(
+'_storeOn_',
+smalltalk.method({
+selector: 'storeOn:',
+fn: function (aStream){
+var self=this;
+smalltalk.send(aStream, "_nextPutAll_", [unescape("%23%7B")]);
+smalltalk.send(smalltalk.send(self, "_associations", []), "_do_separatedBy_", [(function(each){return smalltalk.send(each, "_storeOn_", [aStream]);}), (function(){return smalltalk.send(aStream, "_nextPutAll_", [". "]);})]);
+smalltalk.send(aStream, "_nextPutAll_", [unescape("%7D")]);
+return self;}
+}),
+smalltalk.Dictionary2);
+
+
+

File diff suppressed because it is too large
+ 380 - 99
js/Kernel.js


+ 1 - 0
js/SUnit.deploy.js

@@ -1,3 +1,4 @@
+smalltalk.addPackage('SUnit', {});
 smalltalk.addClass('TestCase', smalltalk.Object, ['testSelector'], 'SUnit');
 smalltalk.addMethod(
 '_setTestSelector_',

+ 5 - 4
js/SUnit.js

@@ -1,3 +1,4 @@
+smalltalk.addPackage('SUnit', {});
 smalltalk.addClass('TestCase', smalltalk.Object, ['testSelector'], 'SUnit');
 smalltalk.addMethod(
 unescape('_setTestSelector_'),
@@ -43,7 +44,7 @@ return self;},
 args: ["aString"],
 source: unescape('signalFailure%3A%20aString%0A%09TestFailure%20new%0A%09%09messageText%3A%20aString%3B%0A%09%09signal'),
 messageSends: ["messageText:", "signal", "new"],
-referencedClasses: []
+referencedClasses: ["TestFailure"]
 }),
 smalltalk.TestCase);
 
@@ -110,7 +111,7 @@ return self;},
 args: ["aResult"],
 source: unescape('performTestFor%3A%20aResult%0A%09%5B%5Bself%20perform%3A%20self%20selector%5D%0A%09%09on%3A%20TestFailure%20do%3A%20%5B%3Aex%20%7C%20aResult%20addFailure%3A%20self%5D%5D%0A%09%09on%3A%20Error%20do%3A%20%5B%3Aex%20%7C%20aResult%20addError%3A%20self%5D'),
 messageSends: ["on:do:", "perform:", "selector", "addFailure:", "addError:"],
-referencedClasses: [smalltalk.Error]
+referencedClasses: ["TestFailure", "Error"]
 }),
 smalltalk.TestCase);
 
@@ -223,7 +224,7 @@ return self;},
 args: [],
 source: unescape('lookupHierarchyRoot%0A%09%5ETestCase'),
 messageSends: [],
-referencedClasses: [smalltalk.TestCase]
+referencedClasses: ["TestCase"]
 }),
 smalltalk.TestCase.klass);
 
@@ -460,7 +461,7 @@ return self;},
 args: [],
 source: unescape('initialize%0A%09super%20initialize.%0A%09timestamp%20%3A%3D%20Date%20now.%0A%09runs%20%3A%3D%200.%0A%09errors%20%3A%3D%20Array%20new.%0A%09failures%20%3A%3D%20Array%20new.%0A%09total%20%3A%3D%200'),
 messageSends: ["initialize", "now", "new"],
-referencedClasses: [smalltalk.Date,smalltalk.Array]
+referencedClasses: ["Date", "Array"]
 }),
 smalltalk.TestResult);
 

+ 417 - 415
js/boot.js

@@ -36,13 +36,13 @@
 /* Make that console is defined */
 
 if (typeof console === "undefined") {
-    this.console = {
-	log: function() {},
-	warn: function() {},
-	info: function() {},
-	debug: function() {},
-	error: function() {}
-    };
+	this.console = {
+		log: function() {},
+		warn: function() {},
+		info: function() {},
+		debug: function() {},
+		error: function() {}
+	};
 }
 
 
@@ -53,470 +53,472 @@ function SmalltalkBehavior(){};
 function SmalltalkClass(){};
 function SmalltalkPackage(){};
 function SmalltalkMetaclass(){
-    this.meta = true;
+	this.meta = true;
 };
 function SmalltalkMethod(){};
 function SmalltalkNil(){};
 
 function Smalltalk(){
 
-    var st = this;
-
-    /* This is the current call context object. While it is publicly available,
-       Use smalltalk.getThisContext() instead which will answer a safe copy of 
-       the current context */
-
-    st.thisContext = undefined;
-
-    /* List of all reserved words in JavaScript. They may not be used as variables
-       in Smalltalk. */
-
-    st.reservedWords = ['break', 'case', 'catch', 'class', 'continue', 'debugger', 
-			'default', 'delete', 'do', 'else', 'finally', 'for', 'function', 
-			'if', 'in', 'instanceof', 'new', 'private', 'protected', 
-			'public', 'return', 'static', 'switch', 'this', 'throw',
-			'try', 'typeof', 'var', 'void', 'while', 'with', 'yield'];
-    
-    /* We hold all Packages in a separate Object */
-
-    st.packages = {};
-
-    /* Smalltalk package creation. To add a Package, use smalltalk.addPackage() */
-
-    function pkg(spec) {
-	var that      = new SmalltalkPackage();
-	that.pkgName  = spec.pkgName;
-	that.requires = spec.requires || [];
-	return that;
-    };
-
-    /* Smalltalk class creation. A class is an instance of an automatically 
-       created metaclass object. Newly created classes (not their metaclass) 
-       should be added to the smalltalk object, see smalltalk.addClass().
-       Superclass linking is *not* handled here, see smalltalk.init()  */
-
-    function klass(spec) {
-	var spec = spec || {};
-	var that;
-	if(spec.meta) {
-	    that = new SmalltalkMetaclass();
-	} else {
-	    that = new (klass({meta: true})).fn;
-	    that.klass.instanceClass = that;
-	    that.className = spec.className;
-	    that.klass.className = that.className + ' class';
-	}
-	
-	that.fn = spec.fn || function(){};
-	that.superclass = spec.superclass;
-	that.iVarNames = spec.iVarNames || [];
-	if(that.superclass) {
-	    that.klass.superclass = that.superclass.klass;
-	}
-	that.pkg = spec.pkg;
-        // For a while we keep the category attribute...
-        if(!(spec.pkg === undefined)) {
-	    that.category = spec.pkg.pkgName;
-	}
-	that.fn.prototype.methods = {};
-	that.fn.prototype.inheritedMethods = {};
-	that.fn.prototype.klass = that;
-
-	return that;
-    };
-
-    /* Smalltalk method object. To add a method to a class,
-       use smalltalk.addMethod() */
-
-    st.method = function(spec) {
-	var that = new SmalltalkMethod();
-	that.selector          = spec.selector;
-	that.jsSelector        = spec.jsSelector;
-	that.args              = spec.args || {};
-	that.category          = spec.category;
-	that.source            = spec.source;
-	that.messageSends      = spec.messageSends || [];
-	that.referencedClasses = spec.referencedClasses || [];
-	that.fn                = spec.fn;
-	return that
-    };
-
-    /* Initialize a class in its class hierarchy. Handle both class and
-       metaclasses. */
-
-    st.init = function(klass) {
-	var subclasses = st.subclasses(klass);
-	var methods;
-
-	if(klass.superclass && klass.superclass !== nil) {
-	    methods = st.methods(klass.superclass);
-
-	    //Methods linking
-	    for(var i in methods) {
-		if(!klass.fn.prototype.methods[i]) {
-		    klass.fn.prototype.inheritedMethods[i] = methods[i];
-		    klass.fn.prototype[methods[i].jsSelector] = methods[i].fn;
+	var st = this;
+
+	/* This is the current call context object. While it is publicly available,
+	   Use smalltalk.getThisContext() instead which will answer a safe copy of 
+	   the current context */
+
+	st.thisContext = undefined;
+
+	/* List of all reserved words in JavaScript. They may not be used as variables
+	   in Smalltalk. */
+
+	st.reservedWords = ['break', 'case', 'catch', 'char', 'class', 'continue', 'debugger', 
+		'default', 'delete', 'do', 'else', 'finally', 'for', 'function', 
+		'if', 'in', 'instanceof', 'new', 'private', 'protected', 
+		'public', 'return', 'static', 'switch', 'this', 'throw',
+		'try', 'typeof', 'var', 'void', 'while', 'with', 'yield'];
+
+	/* We hold all Packages in a separate Object */
+
+	st.packages = {};
+
+	/* Smalltalk package creation. To add a Package, use smalltalk.addPackage() */
+
+	function pkg(spec) {
+		var that      = new SmalltalkPackage();
+		that.pkgName  = spec.pkgName;
+		that.properties = spec.properties || {};
+		return that;
+	};
+
+	/* Smalltalk class creation. A class is an instance of an automatically 
+	   created metaclass object. Newly created classes (not their metaclass) 
+	   should be added to the smalltalk object, see smalltalk.addClass().
+	   Superclass linking is *not* handled here, see smalltalk.init()  */
+
+	function klass(spec) {
+		var spec = spec || {};
+		var that;
+		if(spec.meta) {
+			that = new SmalltalkMetaclass();
+		} else {
+			that = new (klass({meta: true})).fn;
+			that.klass.instanceClass = that;
+			that.className = spec.className;
+			that.klass.className = that.className + ' class';
 		}
-	    }
-	}
 
-	for(var i=0;i<subclasses.length;i++) {
-     	    st.init(subclasses[i]);
-	}
-	if(klass.klass && !klass.meta) {
-	    st.init(klass.klass);
-	}
-    };
+		that.fn = spec.fn || function(){};
+		that.superclass = spec.superclass;
+		that.iVarNames = spec.iVarNames || [];
+		if(that.superclass) {
+			that.klass.superclass = that.superclass.klass;
+		}
+		that.pkg = spec.pkg;
+		that.fn.prototype.methods = {};
+		that.fn.prototype.inheritedMethods = {};
+		that.fn.prototype.klass = that;
+
+		return that;
+	};
+
+	/* Smalltalk method object. To add a method to a class,
+	   use smalltalk.addMethod() */
+
+	st.method = function(spec) {
+		var that = new SmalltalkMethod();
+		that.selector          = spec.selector;
+		that.jsSelector        = spec.jsSelector;
+		that.args              = spec.args || {};
+		that.category          = spec.category;
+		that.source            = spec.source;
+		that.messageSends      = spec.messageSends || [];
+		that.referencedClasses = spec.referencedClasses || [];
+		that.fn                = spec.fn;
+		return that
+	};
+
+	/* Initialize a class in its class hierarchy. Handle both class and
+	   metaclasses. */
+
+	st.init = function(klass) {
+		var subclasses = st.subclasses(klass);
+		var methods;
+
+		if(klass.superclass && klass.superclass !== nil) {
+			methods = st.methods(klass.superclass);
+
+			//Methods linking
+			for(var i in methods) {
+				if(!klass.fn.prototype.methods[i]) {
+					klass.fn.prototype.inheritedMethods[i] = methods[i];
+					klass.fn.prototype[methods[i].jsSelector] = methods[i].fn;
+				}
+			}
+		}
 
-    /* Answer all registered Packages as Array */
+		for(var i=0;i<subclasses.length;i++) {
+			st.init(subclasses[i]);
+		}
+		if(klass.klass && !klass.meta) {
+			st.init(klass.klass);
+		}
+	};
 
-    st.packages.all = function() {
-	var packages = [];
-	for(var i in st.packages) {
-          if (!st.packages.hasOwnProperty(i) || typeof(st.packages[i]) === "function") continue;
-	    packages.push(st.packages[i]);
-	}
-	return packages
-    };
+	/* Answer all registered Packages as Array */
 
-    /* Answer all registered Smalltalk classes */
+	st.packages.all = function() {
+		var packages = [];
+		for(var i in st.packages) {
+			if (!st.packages.hasOwnProperty(i) || typeof(st.packages[i]) === "function") continue;
+			packages.push(st.packages[i]);
+		}
+		return packages
+	};
 
-    st.classes = function() {
-	var classes = [];
-	for(var i in st) {
-	    if(i.search(/^[A-Z]/g) != -1) {
-		classes.push(st[i]);
-	    }
-	}
-	return classes
-    };
+	/* Answer all registered Smalltalk classes */
 
-    /* Answer all methods (included inherited ones) of klass. */
+	st.classes = function() {
+		var classes = [];
+		for(var i in st) {
+			if(i.search(/^[A-Z]/g) != -1) {
+				classes.push(st[i]);
+			}
+		}
+		return classes
+	};
 
-    st.methods = function(klass) {
-	var methods = {};
-	for(var i in klass.fn.prototype.methods) {
-	    methods[i] = klass.fn.prototype.methods[i]
-	}
-	for(var i in klass.fn.prototype.inheritedMethods) {
-	    methods[i] = klass.fn.prototype.inheritedMethods[i]
-	}
-	return methods;
-    }
-
-    /* Answer the direct subclasses of klass. */
-
-    st.subclasses = function(klass) {
-	var subclasses = [];
-	var classes = st.classes();
-	for(var i in classes) {
-	    if(classes[i].fn) {
-		//Metaclasses
-		if(classes[i].klass && classes[i].klass.superclass === klass) {
-		    subclasses.push(classes[i].klass);
+	/* Answer all methods (included inherited ones) of klass. */
+
+	st.methods = function(klass) {
+		var methods = {};
+		for(var i in klass.fn.prototype.methods) {
+			methods[i] = klass.fn.prototype.methods[i]
 		}
-		//Classes
-		if(classes[i].superclass === klass) {
-		    subclasses.push(classes[i]);
+		for(var i in klass.fn.prototype.inheritedMethods) {
+			methods[i] = klass.fn.prototype.inheritedMethods[i]
 		}
-	    }
-	}
-	return subclasses;
-    };
-
-    /* Create a new class wrapping a JavaScript constructor, and add it to the 
-       global smalltalk object. Package is lazily created if it does not exist with given name. */
-
-    st.mapClassName = function(className, pkgName, fn, superclass) {
-	var pkg = st.addPackage(pkgName);
-	st[className] = klass({
-	    className:  className, 
-	    superclass: superclass,
-	    pkg:        pkg, 
-	    fn:         fn
-	});
-    };
-
-    /* Add a package to the smalltalk.packages object, creating a new one if needed.
-       If pkgName is nil or empty we return nil, which is an allowed package for a class. */
-
-    st.addPackage = function(pkgName) {
-	if(!pkgName) {return nil;}
-	if(!(st.packages[pkgName])) {
-	    st.packages[pkgName] = pkg({
-		pkgName: pkgName
-	    });
+		return methods;
 	}
-	return st.packages[pkgName];
-    };
-
-    /* Add a class to the smalltalk object, creating a new one if needed.
-       Package is lazily created if it does not exist with given name.*/
-
-    st.addClass = function(className, superclass, iVarNames, pkgName) {
-	var pkg = st.addPackage(pkgName);
-	if(st[className]) {
-	    st[className].superclass = superclass;
-	    st[className].iVarNames = iVarNames;
-	    st[className].pkg = pkg || st[className].pkg;
-	} else {    
-	    st[className] = klass({
-		className: className, 
-		superclass: superclass,
-		pkg: pkg,
-		iVarNames: iVarNames
-	    });
-	}
-    };
 
-    /* Add a method to a class */
+	/* Answer the direct subclasses of klass. */
+
+	st.subclasses = function(klass) {
+		var subclasses = [];
+		var classes = st.classes();
+		for(var i in classes) {
+			if(classes[i].fn) {
+				//Metaclasses
+				if(classes[i].klass && classes[i].klass.superclass === klass) {
+					subclasses.push(classes[i].klass);
+				}
+				//Classes
+				if(classes[i].superclass === klass) {
+					subclasses.push(classes[i]);
+				}
+			}
+		}
+		return subclasses;
+	};
+
+	/* Create a new class wrapping a JavaScript constructor, and add it to the 
+	   global smalltalk object. Package is lazily created if it does not exist with given name. */
+
+	st.mapClassName = function(className, pkgName, fn, superclass) {
+		var pkg = st.addPackage(pkgName);
+		st[className] = klass({
+			className:  className, 
+			superclass: superclass,
+			pkg:        pkg, 
+			fn:         fn
+		});
+	};
+
+	/* Add a package to the smalltalk.packages object, creating a new one if needed.
+	   If pkgName is null or empty we return nil, which is an allowed package for a class.
+	   If package already exists we still update the properties of it. */
+
+	st.addPackage = function(pkgName, properties) {
+		if(!pkgName) {return nil;}
+		if(!(st.packages[pkgName])) {
+			st.packages[pkgName] = pkg({
+				pkgName: pkgName,
+				properties: properties
+			});
+		} else {
+			if(properties) {
+				st.packages[pkgName].properties = properties;
+			}	
+		}
+		return st.packages[pkgName];
+	};
+
+	/* Add a class to the smalltalk object, creating a new one if needed.
+	   Package is lazily created if it does not exist with given name.*/
+
+	st.addClass = function(className, superclass, iVarNames, pkgName) {
+		var pkg = st.addPackage(pkgName);
+		if(st[className]) {
+			st[className].superclass = superclass;
+			st[className].iVarNames = iVarNames;
+			st[className].pkg = pkg || st[className].pkg;
+		} else {    
+			st[className] = klass({
+				className: className, 
+				superclass: superclass,
+				pkg: pkg,
+				iVarNames: iVarNames
+			});
+		}
+	};
 
-    st.addMethod = function(jsSelector, method, klass) {
-	klass.fn.prototype[jsSelector] = method.fn;
-	klass.fn.prototype.methods[method.selector] = method;
-	method.methodClass = klass;
-	method.jsSelector = jsSelector;
-    };
+	/* Add a method to a class */
 
-    /* Handles Smalltalk message send. Automatically converts undefined to the nil object.
-       If the receiver does not understand the selector, call its #doesNotUnderstand: method */
+	st.addMethod = function(jsSelector, method, klass) {
+		klass.fn.prototype[jsSelector] = method.fn;
+		klass.fn.prototype.methods[method.selector] = method;
+		method.methodClass = klass;
+		method.jsSelector = jsSelector;
+	};
 
-    sendWithoutContext = function(receiver, selector, args, klass) {
-	if(receiver === undefined || receiver === null) {
-	    receiver = nil;
-	}
-	if(!klass && receiver.klass && receiver[selector]) {
-	    return receiver[selector].apply(receiver, args);
-	} else if(klass && klass.fn.prototype[selector]) {
-	    return klass.fn.prototype[selector].apply(receiver, args)
-	}
-	return messageNotUnderstood(receiver, selector, args);
-    };
+	/* Handles Smalltalk message send. Automatically converts undefined to the nil object.
+	   If the receiver does not understand the selector, call its #doesNotUnderstand: method */
 
+	sendWithoutContext = function(receiver, selector, args, klass) {
+		if(receiver === undefined || receiver === null) {
+			receiver = nil;
+		}
+		if(!klass && receiver.klass && receiver[selector]) {
+			return receiver[selector].apply(receiver, args);
+		} else if(klass && klass.fn.prototype[selector]) {
+			return klass.fn.prototype[selector].apply(receiver, args)
+		}
+		return messageNotUnderstood(receiver, selector, args);
+	};
 
-    /* Handles unhandled errors during message sends */
 
-    sendWithContext = function(receiver, selector, args, klass) {
-	if(st.thisContext) {
-	     return withContextSend(receiver, selector, args, klass);
-	} else {
-	    try {return withContextSend(receiver, selector, args, klass)}
-	    catch(error) {
-		// Reset the context stack in any case
-		st.thisContext = undefined;
-		if(error.smalltalkError) {
-		    handleError(error);
+	/* Handles unhandled errors during message sends */
+
+	sendWithContext = function(receiver, selector, args, klass) {
+		if(st.thisContext) {
+			return withContextSend(receiver, selector, args, klass);
 		} else {
-		    throw(error);
+			try {return withContextSend(receiver, selector, args, klass)}
+			catch(error) {
+				// Reset the context stack in any case
+				st.thisContext = undefined;
+				if(error.smalltalkError) {
+					handleError(error);
+				} else {
+					throw(error);
+				}
+			}
 		}
-	    }
-	}
-    };
+	};
 
-    /* Same as sendWithoutContext but creates a methodContext. */
+	/* Same as sendWithoutContext but creates a methodContext. */
 
-    withContextSend = function(receiver, selector, args, klass) {
-	var call, context;
-	if(receiver === undefined || receiver === null) {
-	    receiver = nil;
-	}
-	if(!klass && receiver.klass && receiver[selector]) {
-	    context = pushContext(receiver, selector, args);
-	    call = receiver[selector].apply(receiver, args);
-	    popContext(context);
-	    return call;
-	} else if(klass && klass.fn.prototype[selector]) {
-	    context = pushContext(receiver, selector, args);
-	    call = klass.fn.prototype[selector].apply(receiver, args);
-	    popContext(context);
-	    return call;
+	withContextSend = function(receiver, selector, args, klass) {
+		var call, context;
+		if(receiver === undefined || receiver === null) {
+			receiver = nil;
+		}
+		if(!klass && receiver.klass && receiver[selector]) {
+			context = pushContext(receiver, selector, args);
+			call = receiver[selector].apply(receiver, args);
+			popContext(context);
+			return call;
+		} else if(klass && klass.fn.prototype[selector]) {
+			context = pushContext(receiver, selector, args);
+			call = klass.fn.prototype[selector].apply(receiver, args);
+			popContext(context);
+			return call;
+		}
+		return messageNotUnderstood(receiver, selector, args);
+	};
+
+	/* Handles Smalltalk errors. Triggers the registered ErrorHandler 
+	   (See the Smalltalk class ErrorHandler and its subclasses */
+
+	function handleError(error) {
+		st.thisContext = undefined;
+		smalltalk.ErrorHandler._current()._handleError_(error);
 	}
-	return messageNotUnderstood(receiver, selector, args);
-    };
 
-    /* Handles Smalltalk errors. Triggers the registered ErrorHandler 
-       (See the Smalltalk class ErrorHandler and its subclasses */
-    
-    function handleError(error) {
-	st.thisContext = undefined;
-	smalltalk.ErrorHandler._current()._handleError_(error);
-    }
+	/* Handles #dnu: *and* JavaScript method calls.
+	   if the receiver has no klass, we consider it a JS object (outside of the
+	   Amber system). Else assume that the receiver understands #doesNotUnderstand: */
+
+	function messageNotUnderstood(receiver, selector, args) {
+		/* Handles JS method calls. */
+		if(receiver.klass === undefined || receiver.allowJavaScriptCalls) {
+			return callJavaScriptMethod(receiver, selector, args);
+		}
 
-    /* Handles #dnu: *and* JavaScript method calls.
-       if the receiver has no klass, we consider it a JS object (outside of the
-       Amber system). Else assume that the receiver understands #doesNotUnderstand: */
+		/* Handles not understood messages. Also see the Amber counter-part 
+		   Object>>doesNotUnderstand: */
 
-    function messageNotUnderstood(receiver, selector, args) {
-	/* Handles JS method calls. */
-	if(receiver.klass === undefined || receiver.allowJavaScriptCalls) {
-	    return callJavaScriptMethod(receiver, selector, args);
-	}
+		return receiver._doesNotUnderstand_(
+				st.Message._new()
+				._selector_(st.convertSelector(selector))
+				._arguments_(args)
+				);
+	};
 
-	/* Handles not understood messages. Also see the Amber counter-part 
-	   Object>>doesNotUnderstand: */
-	
-	return receiver._doesNotUnderstand_(
-	    st.Message._new()
-		._selector_(st.convertSelector(selector))
-		._arguments_(args)
-	);
-    };
-
-    function callJavaScriptMethod(receiver, selector, args) {
 	/* Call a method of a JS object, or answer a property if it exists.
 	   Else try wrapping a JSObjectProxy around the receiver.
- 
+
 	   Converts keyword-based selectors by using the first
 	   keyword only, but keeping all message arguments.
 
 	   Example:
 	   "self do: aBlock with: anObject" -> "self.do(aBlock, anObject)" */
 
-	var jsSelector = selector._asJavaScriptSelector();
-	var jsProperty = receiver[jsSelector];
-	if(typeof jsProperty === "function") {
-	    return jsProperty.apply(receiver, args);
-	} else if(jsProperty !== undefined) {
-	    if(args[0]) {
-		receiver[jsSelector] = args[0];
-		return nil;
-	    } else {
-		return jsProperty
-	    }
-	}
-	
-	return st.send(st.JSObjectProxy._on_(receiver), selector, args);
-    };
+	function callJavaScriptMethod(receiver, selector, args) {
+		var jsSelector = selector._asJavaScriptSelector();
+		var jsProperty = receiver[jsSelector];
+		if(typeof jsProperty === "function") {
+			return jsProperty.apply(receiver, args);
+		} else if(jsProperty !== undefined) {
+			if(args[0]) {
+				receiver[jsSelector] = args[0];
+				return nil;
+			} else {
+				return jsProperty
+			}
+		}
 
+		return st.send(st.JSObjectProxy._on_(receiver), selector, args);
+	};
 
-    /* Reuse old contexts stored in oldContexts */
 
-    st.oldContexts = [];
+	/* Reuse old contexts stored in oldContexts */
 
-	
-    /* Handle thisContext pseudo variable */
-    
-    st.getThisContext = function() {
-	if(st.thisContext) {
-	    return st.thisContext.copy();
-	} else {
-	    return undefined;
-	}
-    }
+	st.oldContexts = [];
 
-    pushContext = function(receiver, selector, temps) {
-	if(st.thisContext) {
-	    return st.thisContext = st.thisContext.newContext(receiver, selector, temps);
-	} else {
-	    return st.thisContext = new SmalltalkMethodContext(receiver, selector, temps);
-	}
-    };
 
-    popContext = function(context) {
-	if(context) {
-	    context.removeYourself();
+	/* Handle thisContext pseudo variable */
+
+	st.getThisContext = function() {
+		if(st.thisContext) {
+			return st.thisContext.copy();
+		} else {
+			return undefined;
+		}
 	}
-    };
 
-    /* Convert a string to a valid smalltalk selector.
-       if you modify the following functions, also change String>>asSelector
-       accordingly */
+	pushContext = function(receiver, selector, temps) {
+		if(st.thisContext) {
+			return st.thisContext = st.thisContext.newContext(receiver, selector, temps);
+		} else {
+			return st.thisContext = new SmalltalkMethodContext(receiver, selector, temps);
+		}
+	};
 
-    st.convertSelector = function(selector) {
-	if(selector.match(/__/)) {
-	    return convertBinarySelector(selector);
-	} else {
-	    return convertKeywordSelector(selector);
-	}
-    };
-
-    function convertKeywordSelector(selector) {
-	return selector.replace(/^_/, '').replace(/_/g, ':');
-    };
-
-    function convertBinarySelector(selector) {
-	return selector
-	    .replace(/^_/, '')
-	    .replace(/_plus/, '+')
-	    .replace(/_minus/, '-')
-	    .replace(/_star/, '*')
-	    .replace(/_slash/, '/')
-	    .replace(/_gt/, '>')
-	    .replace(/_lt/, '<')
-	    .replace(/_eq/, '=')
-	    .replace(/_comma/, ',')
-	    .replace(/_at/, '@')
-    };
-
-    /* Converts a JavaScript object to valid Smalltalk Object */
-    st.readJSObject = function(js) {
-	var object = js;
-	var readObject = (js.constructor === Object);
-	var readArray = (js.constructor === Array);
-	
-	if(readObject) {
-	    object = smalltalk.Dictionary._new();
-	}
-	for(var i in js) {
-	    if(readObject) {
-		object._at_put_(i, st.readJSObject(js[i]));
-	    } 
-	    if(readArray) {
-		object[i] = st.readJSObject(js[i]);
-	    }
-	}
-	return object;
-    };
+	popContext = function(context) {
+		if(context) {
+			context.removeYourself();
+		}
+	};
 
-    /* Toggle deployment mode (no context will be handled during message send */
-    st.setDeploymentMode = function() {
-	st.send = sendWithoutContext;
-    };
+	/* Convert a string to a valid smalltalk selector.
+	   if you modify the following functions, also change String>>asSelector
+	   accordingly */
 
-    st.setDevelopmentMode = function() {
-	st.send = sendWithContext;
-    }
+	st.convertSelector = function(selector) {
+		if(selector.match(/__/)) {
+			return convertBinarySelector(selector);
+		} else {
+			return convertKeywordSelector(selector);
+		}
+	};
+
+	function convertKeywordSelector(selector) {
+		return selector.replace(/^_/, '').replace(/_/g, ':');
+	};
+
+	function convertBinarySelector(selector) {
+		return selector
+			.replace(/^_/, '')
+			.replace(/_plus/, '+')
+			.replace(/_minus/, '-')
+			.replace(/_star/, '*')
+			.replace(/_slash/, '/')
+			.replace(/_gt/, '>')
+			.replace(/_lt/, '<')
+			.replace(/_eq/, '=')
+			.replace(/_comma/, ',')
+			.replace(/_at/, '@')
+	};
+
+	/* Converts a JavaScript object to valid Smalltalk Object */
+	st.readJSObject = function(js) {
+		var object = js;
+		var readObject = (js.constructor === Object);
+		var readArray = (js.constructor === Array);
+
+		if(readObject) {
+			object = smalltalk.Dictionary._new();
+		}
+		for(var i in js) {
+			if(readObject) {
+				object._at_put_(i, st.readJSObject(js[i]));
+			} 
+			if(readArray) {
+				object[i] = st.readJSObject(js[i]);
+			}
+		}
+		return object;
+	};
 
-    /* Set development mode by default */
-    st.setDevelopmentMode();
+	/* Toggle deployment mode (no context will be handled during message send */
+	st.setDeploymentMode = function() {
+		st.send = sendWithoutContext;
+	};
+
+	st.setDevelopmentMode = function() {
+		st.send = sendWithContext;
+	}
+
+	/* Set development mode by default */
+	st.setDevelopmentMode();
 }
 
 function SmalltalkMethodContext(receiver, selector, temps, home) {
-    var that = this;
-    that.receiver = receiver;
-    that.selector = selector;
-    that.temps = temps || {};
-    that.homeContext = home;
-
-    that.copy = function() {
-	var home = that.homeContext;
-	if(home) {home = home.copy()}
-	return new SmalltalkMethodContext(
-	    that.receiver, 
-	    that.selector, 
-	    that.temps, 
-	    home
-	);
-    }
-
-    that.newContext = function(receiver, selector, temps) {
-	var c = smalltalk.oldContexts.pop();
-	if(c) {
-	    c.homeContext = that;
-	    c.receiver = receiver;
-	    c.selector = selector;
-	    c.temps = temps || {};
-	} else {
-	    c = new SmalltalkMethodContext(receiver, selector, temps, that);
+	var that = this;
+	that.receiver = receiver;
+	that.selector = selector;
+	that.temps = temps || {};
+	that.homeContext = home;
+
+	that.copy = function() {
+		var home = that.homeContext;
+		if(home) {home = home.copy()}
+		return new SmalltalkMethodContext(
+				that.receiver, 
+				that.selector, 
+				that.temps, 
+				home
+				);
+	}
+
+	that.newContext = function(receiver, selector, temps) {
+		var c = smalltalk.oldContexts.pop();
+		if(c) {
+			c.homeContext = that;
+			c.receiver = receiver;
+			c.selector = selector;
+			c.temps = temps || {};
+		} else {
+			c = new SmalltalkMethodContext(receiver, selector, temps, that);
+		}
+		return c;
+	}
+
+	that.removeYourself = function() {
+		smalltalk.thisContext = that.homeContext;
+		that.homeContext = undefined;
+		smalltalk.oldContexts.push(that);
 	}
-	return c;
-    }
-
-    that.removeYourself = function() {
-	smalltalk.thisContext = that.homeContext;
-	that.homeContext = undefined;
-	smalltalk.oldContexts.push(that);
-    }
 }
 
 /* Global Smalltalk objects. */
@@ -525,7 +527,7 @@ var nil = new SmalltalkNil();
 var smalltalk = new Smalltalk();
 
 if(this.jQuery) {
-    this.jQuery.allowJavaScriptCalls = true;
+	this.jQuery.allowJavaScriptCalls = true;
 }
 
 /****************************************************************************************/

+ 130 - 22
js/parser.js

@@ -42,6 +42,7 @@ smalltalk.parser = (function(){
         "method": parse_method,
         "number": parse_number,
         "operand": parse_operand,
+        "pseudoVariable": parse_pseudoVariable,
         "reference": parse_reference,
         "ret": parse_ret,
         "separator": parse_separator,
@@ -1258,8 +1259,8 @@ smalltalk.parser = (function(){
         return result0;
       }
       
-      function parse_literal() {
-        var cacheKey = 'literal@' + pos;
+      function parse_pseudoVariable() {
+        var cacheKey = 'pseudoVariable@' + pos;
         var cachedResult = cache[cacheKey];
         if (cachedResult) {
           pos = cachedResult.nextPos;
@@ -1267,35 +1268,142 @@ smalltalk.parser = (function(){
         }
         
         
-        var result7 = parse_number();
-        if (result7 !== null) {
-          var result0 = result7;
+        var savedPos0 = pos;
+        var savedPos3 = pos;
+        if (input.substr(pos, 4) === "true") {
+          var result10 = "true";
+          pos += 4;
         } else {
-          var result6 = parse_literalArray();
+          var result10 = null;
+          if (reportMatchFailures) {
+            matchFailed("\"true\"");
+          }
+        }
+        var result11 = result10 !== null
+          ? (function() {return true})()
+          : null;
+        if (result11 !== null) {
+          var result9 = result11;
+        } else {
+          var result9 = null;
+          pos = savedPos3;
+        }
+        if (result9 !== null) {
+          var result1 = result9;
+        } else {
+          var savedPos2 = pos;
+          if (input.substr(pos, 5) === "false") {
+            var result7 = "false";
+            pos += 5;
+          } else {
+            var result7 = null;
+            if (reportMatchFailures) {
+              matchFailed("\"false\"");
+            }
+          }
+          var result8 = result7 !== null
+            ? (function() {return false})()
+            : null;
+          if (result8 !== null) {
+            var result6 = result8;
+          } else {
+            var result6 = null;
+            pos = savedPos2;
+          }
           if (result6 !== null) {
-            var result0 = result6;
+            var result1 = result6;
           } else {
-            var result5 = parse_dynamicDictionary();
+            var savedPos1 = pos;
+            if (input.substr(pos, 3) === "nil") {
+              var result4 = "nil";
+              pos += 3;
+            } else {
+              var result4 = null;
+              if (reportMatchFailures) {
+                matchFailed("\"nil\"");
+              }
+            }
+            var result5 = result4 !== null
+              ? (function() {return nil})()
+              : null;
             if (result5 !== null) {
-              var result0 = result5;
+              var result3 = result5;
+            } else {
+              var result3 = null;
+              pos = savedPos1;
+            }
+            if (result3 !== null) {
+              var result1 = result3;
             } else {
-              var result4 = parse_dynamicArray();
-              if (result4 !== null) {
-                var result0 = result4;
+              var result1 = null;;
+            };
+          };
+        }
+        var result2 = result1 !== null
+          ? (function(val) {
+          					return smalltalk.ValueNode._new()
+          						._value_(val)
+          				})(result1)
+          : null;
+        if (result2 !== null) {
+          var result0 = result2;
+        } else {
+          var result0 = null;
+          pos = savedPos0;
+        }
+        
+        
+        
+        cache[cacheKey] = {
+          nextPos: pos,
+          result:  result0
+        };
+        return result0;
+      }
+      
+      function parse_literal() {
+        var cacheKey = 'literal@' + pos;
+        var cachedResult = cache[cacheKey];
+        if (cachedResult) {
+          pos = cachedResult.nextPos;
+          return cachedResult.result;
+        }
+        
+        
+        var result8 = parse_pseudoVariable();
+        if (result8 !== null) {
+          var result0 = result8;
+        } else {
+          var result7 = parse_number();
+          if (result7 !== null) {
+            var result0 = result7;
+          } else {
+            var result6 = parse_literalArray();
+            if (result6 !== null) {
+              var result0 = result6;
+            } else {
+              var result5 = parse_dynamicDictionary();
+              if (result5 !== null) {
+                var result0 = result5;
               } else {
-                var result3 = parse_string();
-                if (result3 !== null) {
-                  var result0 = result3;
+                var result4 = parse_dynamicArray();
+                if (result4 !== null) {
+                  var result0 = result4;
                 } else {
-                  var result2 = parse_symbol();
-                  if (result2 !== null) {
-                    var result0 = result2;
+                  var result3 = parse_string();
+                  if (result3 !== null) {
+                    var result0 = result3;
                   } else {
-                    var result1 = parse_block();
-                    if (result1 !== null) {
-                      var result0 = result1;
+                    var result2 = parse_symbol();
+                    if (result2 !== null) {
+                      var result0 = result2;
                     } else {
-                      var result0 = null;;
+                      var result1 = parse_block();
+                      if (result1 !== null) {
+                        var result0 = result1;
+                      } else {
+                        var result0 = null;;
+                      };
                     };
                   };
                 };

+ 7 - 1
js/parser.pegjs

@@ -33,7 +33,13 @@ dynamicDictionary = "#{" ws expressions: expressions? ws "}" {
 	       	  return smalltalk.DynamicDictionaryNode._new()
 		        ._nodes_(expressions)
 		  }
-literal        = number / literalArray / dynamicDictionary / dynamicArray / string / symbol / block
+pseudoVariable = val:('true' {return true} 
+				/ 'false' {return false}
+				/ 'nil' {return nil} {
+					return smalltalk.ValueNode._new()
+						._value_(val)
+				}
+literal        = pseudoVariable / number / literalArray / dynamicDictionary / dynamicArray / string / symbol / block
 
 
 variable       = identifier:identifier {

+ 1 - 1
server/Makefile

@@ -5,4 +5,4 @@ run: server.js
 	./server
 
 clean:
-	rm -f FileServer.js server.js
+	rm -f FileServer.js

File diff suppressed because it is too large
+ 258 - 37
server/server.js


+ 1 - 0
st/Benchfib.st

@@ -1,3 +1,4 @@
+Smalltalk current createPackage: 'Benchfib' properties: #{}!
 Object subclass: #Benchfib
 	instanceVariableNames: ''
 	category: 'Benchfib'!

+ 1 - 0
st/Canvas.st

@@ -1,3 +1,4 @@
+Smalltalk current createPackage: 'Canvas' properties: #{}!
 Object subclass: #HTMLCanvas
 	instanceVariableNames: 'root'
 	category: 'Canvas'!

+ 46 - 30
st/Compiler.st

@@ -1,3 +1,4 @@
+Smalltalk current createPackage: 'Compiler' properties: #{}!
 Object subclass: #ChunkParser
 	instanceVariableNames: 'stream'
 	category: 'Compiler'!
@@ -67,24 +68,16 @@ Object subclass: #Exporter
 
 !Exporter methodsFor: 'fileOut'!
 
-export: aClass
-	"Export a single class. Subclasses override these methods."
-
-	^String streamContents: [:stream |
-		self exportDefinitionOf: aClass on: stream.
-		self exportMethodsOf: aClass on: stream.
-		self exportMetaDefinitionOf: aClass on: stream.
-		self exportMethodsOf: aClass class on: stream]
-!
-
 exportPackage: packageName
 	"Export a given package by name."
 
+	| package |
 	^String streamContents: [:stream |
-        	(Smalltalk current packageAt: packageName)
-	    		classes do: [:each |
-                                     stream nextPutAll: (self export: each)].
-		self exportPackageExtensions: packageName on: stream]
+                package := Smalltalk current packageAt: packageName.
+                self exportPackageDefinitionOf: package on: stream.
+	    	package classes do: [:each |
+                        stream nextPutAll: (self exportClass: each)].
+		self exportPackageExtensionsOf: package on: stream]
 !
 
 exportAll
@@ -93,6 +86,16 @@ exportAll
     ^String streamContents: [:stream |
     	Smalltalk current packages do: [:pkg |
 		stream nextPutAll: (self exportPackage: pkg name)]]
+!
+
+exportClass: aClass
+	"Export a single class. Subclasses override these methods."
+
+	^String streamContents: [:stream |
+		self exportDefinitionOf: aClass on: stream.
+		self exportMethodsOf: aClass on: stream.
+		self exportMetaDefinitionOf: aClass on: stream.
+		self exportMethodsOf: aClass class on: stream]
 ! !
 
 !Exporter methodsFor: 'private'!
@@ -158,22 +161,28 @@ exportMethod: aMethod of: aClass on: aStream
 		nextPutAll: 'args: ', aMethod arguments asJavascript, ','; lf;
 		nextPutAll: 'source: unescape(''', aMethod source escaped, '''),';lf;
 		nextPutAll: 'messageSends: ', aMethod messageSends asJavascript, ',';lf;
-		nextPutAll: 'referencedClasses: ['.
-	    		aMethod referencedClasses 
-				do: [:each | aStream nextPutAll: 'smalltalk.', (self classNameFor: each)]
-				separatedBy: [aStream nextPutAll: ','].
+		nextPutAll: 'referencedClasses: ', aMethod referencedClasses asJavascript.
 	aStream
-		nextPutAll: ']';lf;
+		lf;
 		nextPutAll: '}),';lf;
 		nextPutAll: 'smalltalk.', (self classNameFor: aClass);
 		nextPutAll: ');';lf;lf
 !
 
-exportPackageExtensions: packageName on: aStream
+exportPackageExtensionsOf: package on: aStream
+	| name |
+	name := package name.
 	Smalltalk current classes, (Smalltalk current classes collect: [:each | each class]) do: [:each |
 		each methodDictionary values do: [:method |
-			method category = ('*', packageName) ifTrue: [
+			method category = ('*', name) ifTrue: [
 				self exportMethod: method of: each on: aStream]]]
+!
+
+exportPackageDefinitionOf: package on: aStream
+	aStream 
+	    nextPutAll: 'smalltalk.addPackage(';
+	    nextPutAll: '''', package name, ''', ', package propertiesAsJSON , ');'.
+	aStream lf
 ! !
 
 Exporter subclass: #ChunkExporter
@@ -257,15 +266,25 @@ exportMethods: methods category: category of: aClass on: aStream
 	aStream nextPutAll: ' !!'; lf; lf
 !
 
-exportPackageExtensions: aString on: aStream
+exportPackageExtensionsOf: package on: aStream
 	"We need to override this one too since we need to group
 	all methods in a given protocol under a leading methodsFor: chunk
 	for that class."
 
+	| name |
+	name := package name.
 	Smalltalk current classes, (Smalltalk current classes collect: [:each | each class]) do: [:each |
 		each protocolsDo: [:category :methods |
-			category = ('*', aString) ifTrue: [
+			category = ('*', name) ifTrue: [
 				self exportMethods: methods category: category of: each on: aStream]]]
+!
+
+exportPackageDefinitionOf: package on: aStream
+	"Chunk format."
+
+	aStream 
+	    nextPutAll: 'Smalltalk current createPackage: ''', package name,
+		''' properties: ', package properties storeString, '!!'; lf.
 ! !
 
 Exporter subclass: #StrippedExporter
@@ -1171,7 +1190,7 @@ visitMethodNode: aNode
           	nextPutAll: 'args: ', argVariables asJavascript, ','; lf;
 		nextPutAll: 'referencedClasses: ['.
 	referencedClasses 
-		do: [:each | stream nextPutAll: each]
+		do: [:each | stream nextPutAll: each printString]
 		separatedBy: [stream nextPutAll: ','].
 	stream nextPutAll: ']'.
 	stream nextPutAll: '})'
@@ -1287,12 +1306,9 @@ visitAssignmentNode: aNode
 !
 
 visitClassReferenceNode: aNode
-	| klass |
-	klass := '(smalltalk.', aNode value, ' || ', aNode value, ')'.
-	(Smalltalk current at: aNode value) isClass ifTrue: [
-		(referencedClasses includes: klass)
-			ifFalse: [referencedClasses add: klass]].
-	stream nextPutAll: klass
+	(referencedClasses includes: aNode value) ifFalse: [
+		referencedClasses add: aNode value].
+	stream nextPutAll: '(smalltalk.', aNode value, ' || ', aNode value, ')'
 !
 
 visitVariableNode: aNode

+ 1 - 0
st/Examples.st

@@ -1,3 +1,4 @@
+Smalltalk current createPackage: 'Examples' properties: #{}!
 Widget subclass: #Counter
 	instanceVariableNames: 'count header'
 	category: 'Examples'!

+ 18 - 3
st/IDE.st

@@ -1,3 +1,4 @@
+Smalltalk current createPackage: 'IDE' properties: #{}!
 Widget subclass: #TabManager
 	instanceVariableNames: 'selectedTab tabs opened ul input'
 	category: 'IDE'!
@@ -470,7 +471,7 @@ selectedClass
 !
 
 classDeclarationTemplate
-	^'Object subclass: #nameOfSubclass
+	^'Object subclass: #NameOfSubclass
 	instanceVariableNames: ''''
 	package: ''', self selectedPackage, ''''
 !
@@ -748,6 +749,17 @@ addNewClass
 			resetClassesList;
 			updateClassesList.
 		self selectClass: (Smalltalk current at: className)]
+!
+
+copyClass
+	| className |
+	className := window prompt: 'Copy class'.
+	(className notNil and: [className notEmpty]) ifTrue: [
+		ClassBuilder new copyClass: self selectedClass named: className.
+          	 self 
+			resetClassesList;
+			updateClassesList.
+		self selectClass: (Smalltalk current at: className)]
 ! !
 
 !Browser methodsFor: 'initialization'!
@@ -943,6 +955,9 @@ updateSourceAndButtons
 		html button
 			with: 'Rename class';
 			onClick: [self renameClass].
+		html button
+			with: 'Copy class';
+			onClick: [self copyClass].
 		html button
 			with: 'Remove class';
 			onClick: [self removeClass].
@@ -1245,7 +1260,7 @@ search: aString
 searchReferencedClassesFor: aString
 	self classesAndMetaclasses do: [:each |
 		each methodDictionary values do: [:value |
-			(((value referencedClasses select: [:each | each notNil])collect: [:each | each name]) includes: selector) ifTrue: [
+			(value referencedClasses includes: selector) ifTrue: [
 				self referencedClasses add: value]]]
 !
 
@@ -1401,7 +1416,7 @@ setEditorOn: aTextarea
 	<self['@editor'] = CodeMirror.fromTextArea(aTextarea, {
 		theme: 'jtalk',
                 lineNumbers: true,
-                enterMode: 'classic',
+                enterMode: 'flat',
                 matchBrackets: true,
                 electricChars: false
 	})>

+ 1 - 0
st/Kernel-Tests.st

@@ -1,3 +1,4 @@
+Smalltalk current createPackage: 'Kernel-Tests' properties: #{}!
 TestCase subclass: #StringTest
 	instanceVariableNames: ''
 	category: 'Kernel-Tests'!

+ 361 - 24
st/Kernel.st

@@ -1,3 +1,4 @@
+Smalltalk current createPackage: 'Kernel' properties: #{}!
 nil subclass: #Object
 	instanceVariableNames: ''
 	category: 'Kernel'!
@@ -187,6 +188,17 @@ log: aString block: aBlock
 	| result |
 	console log:  aString,  ' time: ', (Date millisecondsToRun: [result := aBlock value]) printString.
 	^result
+!
+
+storeString
+	"Answer a String representation of the receiver from which the receiver 
+	can be reconstructed."
+
+	^ String streamContents: [:s | self storeOn: s]
+!
+
+storeOn: aStream
+	aStream nextPutAll: self printString
 ! !
 
 !Object methodsFor: 'testing'!
@@ -265,10 +277,6 @@ classes
 	<return self.classes()>
 !
 
-readJSON: anObject
-	<return self.readJSObject(anObject)>
-!
-
 at: aString
 	<return self[aString]>
 !
@@ -301,6 +309,10 @@ parseError: anException parsing: aString
 reservedWords
 	"JavaScript reserved words"
 	<return self.reservedWords>
+!
+
+readJSObject: anObject
+	<return self.readJSObject(anObject)>
 ! !
 
 !Smalltalk methodsFor: 'classes'!
@@ -356,7 +368,7 @@ renamePackage: packageName to: newName
 createPackage: packageName
 	"Create and bind a new package with given name and return it."
 
-       <return smalltalk.addPackage(packageName)>
+      <return smalltalk.addPackage(packageName, nil)>
 !
 
 deletePackage: packageName
@@ -364,6 +376,17 @@ deletePackage: packageName
 	To remove a package, use #removePackage instead."
 
        <delete smalltalk.packages[packageName]>
+!
+
+createPackage: packageName properties: aDict
+	"Create and bind a new package with given name and return it."
+
+	| object |
+	<object = {};>.
+	aDict keysAndValuesDo: [:key :value |
+		<object[key] = value>.
+	].
+       <return smalltalk.addPackage(packageName, object)>
 ! !
 
 Smalltalk class instanceVariableNames: 'current'!
@@ -396,11 +419,7 @@ String where the method category "*IDE" defines #inspectOn: which thus is a meth
 !Package methodsFor: 'accessing'!
 
 name
-	<return self.pkgName || nil>
-!
-
-requires
-	<return self.requires || nil>
+	<return self.pkgName>
 !
 
 name: aString
@@ -421,6 +440,29 @@ commitPathJs: aString
 
 commitPathSt: aString
 	commitPathSt := aString
+!
+
+dependencies
+	^self propertyAt: 'dependencies' ifAbsent: [#()]
+!
+
+dependencies: anArray
+	^self propertyAt: 'dependencies' put: anArray
+!
+
+properties
+	^Smalltalk current readJSObject: (self basicAt: 'properties')
+!
+
+properties: aDict
+	"We store it as a javascript object."
+	
+	| object |
+	<object = {};>.
+	aDict keysAndValuesDo: [:key :value |
+		<object[key] = value>.
+	].
+	<return self.properties = object>
 ! !
 
 !Package methodsFor: 'classes'!
@@ -438,6 +480,37 @@ printString
 
 Package class instanceVariableNames: 'defaultCommitPathJs defaultCommitPathSt'!
 
+!Package methodsFor: 'private'!
+
+propertiesAsJSON
+	<return JSON.stringify(self.properties)>
+!
+
+jsProperties
+	<return self.properties>
+!
+
+jsProperties: aJSObject
+	<return self.properties = aJSObject>
+! !
+
+!Package methodsFor: 'properties'!
+
+propertyAt: key
+
+	<return self.properties[key]>
+!
+
+propertyAt: key put: value
+
+	<return self.properties[key] = value>
+!
+
+propertyAt: key ifAbsent: block
+
+	^(self propertyAt: key) ifNil: [block value]
+! !
+
 !Package class methodsFor: 'accessing'!
 
 named: aPackageName
@@ -767,6 +840,11 @@ Object subclass: #Number
 	instanceVariableNames: ''
 	category: 'Kernel'!
 
+!Number methodsFor: ''!
+
+
+! !
+
 !Number methodsFor: 'arithmetic'!
 
 + aNumber
@@ -803,6 +881,14 @@ negated
 
 \\ aNumber
 	<return self % aNumber>
+!
+
+sqrt
+	<return Math.sqrt(self)>
+!
+
+squared
+	^self * self
 ! !
 
 !Number methodsFor: 'comparing'!
@@ -906,19 +992,6 @@ to: stop by: step
 	  			pos := pos + 1.
 	    			value := value + step]].
 	^array
-!
-
-to: stop by: step do: aBlock
-	| value |
-	value := self.
-	step = 0 ifTrue: [self error: 'step must be non-zero'].
-	step < 0
-		ifTrue: [[ value >= stop ] whileTrue: [
-	    			aBlock value: value.
-	    			value := value + step]]
-		ifFalse: [[ value <= stop ] whileTrue: [
-	    			aBlock value: value.
-	    			value := value + step]]
 ! !
 
 !Number methodsFor: 'copying'!
@@ -950,6 +1023,19 @@ to: stop do: aBlock
 		whileTrue: 
 			[aBlock value: nextValue.
 			nextValue := nextValue + 1]
+!
+
+to: stop by: step do: aBlock
+	| value |
+	value := self.
+	step = 0 ifTrue: [self error: 'step must be non-zero'].
+	step < 0
+		ifTrue: [[ value >= stop ] whileTrue: [
+	    			aBlock value: value.
+	    			value := value + step]]
+		ifFalse: [[ value <= stop ] whileTrue: [
+	    			aBlock value: value.
+	    			value := value + step]]
 ! !
 
 !Number methodsFor: 'printing'!
@@ -1000,6 +1086,10 @@ Object subclass: #BlockClosure
 
 compiledSource
 	<return self.toString()>
+!
+
+numArgs
+	<return self.length>
 ! !
 
 !BlockClosure methodsFor: 'controlling'!
@@ -1073,6 +1163,16 @@ timeToRun
 	"Answer the number of milliseconds taken to execute this block."
 
 	^ Date millisecondsToRun: self
+!
+
+ensure: aBlock
+	| success |
+	success := false.
+	[self value. success := true. aBlock value]
+		on: Error
+		do: [:ex |
+			success ifFalse: [aBlock value].
+			ex signal]
 ! !
 
 !BlockClosure methodsFor: 'timeout/interval'!
@@ -2269,6 +2369,10 @@ messageText: aString
 
 context
 	<return self.context>
+!
+
+jsStack
+	<return self.stack>
 ! !
 
 !Error methodsFor: 'signaling'!
@@ -2277,6 +2381,12 @@ signal
 	<self.context = smalltalk.getThisContext(); self.smalltalkError = true; throw(self)>
 ! !
 
+!Error methodsFor: 'testing'!
+
+isSmalltalkError
+	<return self.smalltalkError === true>
+! !
+
 !Error class methodsFor: 'instance creation'!
 
 signal: aString
@@ -2343,6 +2453,16 @@ value
 	^self class = anAssociation class and: [
 	    self key = anAssociation key and: [
 		self value = anAssociation value]]
+!
+
+storeOn: aStream
+	"Store in the format (key->value)"
+
+	"aStream nextPutAll: '('."
+	key storeOn: aStream.
+	aStream nextPutAll: '->'.
+	value storeOn: aStream.
+	"aStream nextPutAll: ')'"
 ! !
 
 !Association class methodsFor: 'instance creation'!
@@ -2528,6 +2648,14 @@ printString
                                  			separatedBy: [aStream nextPutAll: ' , '].
                                   		aStream nextPutAll: ')'.
                                  ]
+!
+
+storeOn: aStream
+	aStream nextPutAll: '#{'.
+	self associations
+		do: [:each | each storeOn: aStream]
+		separatedBy: [ aStream nextPutAll: '. '].
+	aStream nextPutAll: '}'
 ! !
 
 !Dictionary class methodsFor: 'instance creation'!
@@ -2582,6 +2710,29 @@ setupClass: aClass
 addSubclassOf: aClass named: aString instanceVariableNames: aCollection package: packageName
 	<smalltalk.addClass(aString, aClass, aCollection, packageName);
 	    return smalltalk[aString]>
+!
+
+copyClass: aClass named: aString
+	| newClass |
+
+	newClass := self 
+		addSubclassOf: aClass superclass
+		named: aString 
+		instanceVariableNames: aClass instanceVariableNames 
+		package: aClass package name.
+
+	self setupClass: newClass.
+
+	aClass methodDictionary values do: [:each |
+		newClass addCompiledMethod: (Compiler new load: each source forClass: newClass).
+		(newClass methodDictionary at: each selector) category: each category].
+
+	aClass class methodDictionary values do: [:each |
+		newClass class addCompiledMethod: (Compiler new load: each source forClass: newClass class).
+		(newClass class methodDictionary at: each selector) category: each category].
+
+	self setupClass: newClass.
+	^newClass
 ! !
 
 Object subclass: #ClassCategoryReader
@@ -3205,7 +3356,9 @@ cr
 !
 
 show: anObject
-	<console.log(String(anObject._asString()))>
+	| string |
+	string := anObject asString.
+	<console.log(String(string))>
 ! !
 
 !ConsoleTranscript class methodsFor: 'initialization'!
@@ -3214,3 +3367,187 @@ initialize
 	Transcript register: self new
 ! !
 
+Dictionary subclass: #Dictionary2
+	instanceVariableNames: 'keys'
+	category: 'Kernel'!
+
+!Dictionary2 methodsFor: 'accessing'!
+
+size
+	^keys size
+!
+
+associations
+	| associations |
+	associations := #().
+	keys do: [:each |
+	    associations add: (Association key: each value: (self at: each))].
+	^associations
+!
+
+keys
+	^keys copy
+!
+
+values
+    	^keys collect: [:each | self at: each]
+!
+
+at: aKey put: aValue
+	(keys includes: aKey) ifFalse: [keys add: aKey].
+	^self basicAt: aKey put: aValue
+!
+
+at: aKey ifAbsent: aBlock
+	^(self keys includes: aKey)
+		ifTrue: [self basicAt: aKey]
+		ifFalse: aBlock
+!
+
+at: aKey ifAbsentPut: aBlock
+    	^self at: aKey ifAbsent: [
+    	    self at: aKey put: aBlock value]
+!
+
+at: aKey ifPresent: aBlock
+	^(self basicAt: aKey) ifNotNil: [aBlock value: (self at: aKey)]
+!
+
+at: aKey ifPresent: aBlock ifAbsent: anotherBlock
+	^(self basicAt: aKey)
+	    ifNil: anotherBlock
+	    ifNotNil: [aBlock value: (self at: aKey)]
+!
+
+at: aKey
+	^self at: aKey ifAbsent: [self errorNotFound]
+! !
+
+!Dictionary2 methodsFor: 'adding/removing'!
+
+add: anAssociation
+    	self at: anAssociation key put: anAssociation value
+!
+
+addAll: aDictionary
+    	super addAll: aDictionary associations.
+    	^aDictionary
+!
+
+remove: aKey
+    self removeKey: aKey
+!
+
+removeKey: aKey
+    keys remove: aKey
+! !
+
+!Dictionary2 methodsFor: 'comparing'!
+
+= aDictionary
+	self class = aDictionary class ifFalse: [^false].
+	self size = aDictionary size ifFalse: [^false].
+	^self associations = aDictionary associations
+! !
+
+!Dictionary2 methodsFor: 'converting'!
+
+asJSONObject
+	| object |
+	object := Object new.
+	self keysAndValuesDo: [:key :value |
+		object basicAt: key put: value asJSONObject].
+	^object
+! !
+
+!Dictionary2 methodsFor: 'copying'!
+
+shallowCopy
+	| copy |
+	copy := self class new.
+	self associationsDo: [:each |
+	    copy at: each key  put: each value].
+	^copy
+!
+
+, aCollection
+	self shouldNotImplement
+!
+
+copyFrom: anIndex to: anotherIndex
+	self shouldNotImplement
+! !
+
+!Dictionary2 methodsFor: 'enumerating'!
+
+associationsDo: aBlock
+    	self associations do: aBlock
+!
+
+keysAndValuesDo: aBlock
+    	self associationsDo: [:each |
+    	    aBlock value: each key value: each value]
+!
+
+do: aBlock
+    	self values do: aBlock
+!
+
+select: aBlock
+    	| newDict |
+    	newDict := self class new.
+    	self keysAndValuesDo: [:key :value |
+    	    (aBlock value: value) ifTrue: [newDict at: key put: value]].
+    	^newDict
+!
+
+collect: aBlock
+    	| newDict |
+    	newDict := self class new.
+    	self keysAndValuesDo: [:key :value |
+    	    newDict at: key put: (aBlock value: value)].
+    	^newDict
+!
+
+detect: aBlock ifNone: anotherBlock
+	^self values detect: aBlock ifNone: anotherBlock
+!
+
+includes: anObject
+	^self values includes: anObject
+! !
+
+!Dictionary2 methodsFor: 'initialization'!
+
+initialize
+    	super initialize.
+    	keys := #()
+! !
+
+!Dictionary2 methodsFor: 'printing'!
+
+printString
+	^ String streamContents: [:aStream|  
+                                  		aStream 
+                                  			nextPutAll: super printString;
+                                  			nextPutAll: '('.
+                                  		self associations 
+                                  			do: [:anAssociation|  
+                                                                      	aStream 
+                                                                      		nextPutAll: anAssociation key printString;
+                                                                      		nextPutAll: ' -> ';
+                                                                      		nextPutAll: anAssociation value printString]
+                                  
+                                 			separatedBy: [aStream nextPutAll: ' , '].
+                                  		aStream nextPutAll: ')'.
+                                 ]
+!
+
+storeOn: aStream
+	aStream nextPutAll: '#{'.
+	self associations
+		do: [:each | each storeOn: aStream]
+		separatedBy: [ aStream nextPutAll: '. '].
+	aStream nextPutAll: '}'
+! !
+

+ 1 - 0
st/SUnit.st

@@ -1,3 +1,4 @@
+Smalltalk current createPackage: 'SUnit' properties: #{}!
 Object subclass: #TestCase
 	instanceVariableNames: 'testSelector'
 	category: 'SUnit'!

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