Browse Source

Merge branch 'master' of github.com:amber-smalltalk/amber into class-ast-node

Conflicts:
	st/Compiler-Tests.st
Matthias Springer 10 years ago
parent
commit
0322b3550e
14 changed files with 617 additions and 171 deletions
  1. 84 2
      CHANGELOG
  2. 1 26
      bin/amberc
  3. 4 103
      bin/amberc.js
  4. BIN
      browser.png
  5. 24 14
      grunt/tasks/grunt-amberc.js
  6. 2 1
      js/Compiler-Tests.js
  7. 240 2
      js/Kernel-Objects.js
  8. 82 2
      js/Kernel-Tests.js
  9. 12 11
      st/Compiler-Tests.st
  10. 68 6
      st/Kernel-Objects.st
  11. 32 0
      st/Kernel-Tests.st
  12. 1 0
      support/deploy.js
  13. 64 3
      support/parser.js
  14. 3 1
      support/parser.pegjs

+ 84 - 2
CHANGELOG

@@ -1,5 +1,87 @@
-13th March 2013 - Release 0.10
-==============================
+ 2013 - Release 0.12.0
+===============================
+
+Some numbers about this release:
+
+*  commits
+*  committers
+* increasing the number of core committers to 
+*  unit tests added to the kernel
+*  unit tests in total
+
+Commits
+https://github.com/amber-smalltalk/amber/compare/0.11.0...0.12.0
+Issues
+https://github.com/amber-smalltalk/amber/issues?direction=desc&milestone=8&page=1&sort=updated&state=closed
+
+* Helios IDE, release candidate
+* Use of require [1] to load amber packages in the browser
+* Restructuring of boot.js, use of the brickz[2] reconfigurable micro composition system
+* Enhanced REPL
+
+[1] http://requirejs.org/
+[2] https://github.com/amber-smalltalk/brikz
+
+For API related changes see the file API-CHANGES.txt.
+
+
+
+
+09th July 2013 - Release 0.11.0
+===============================
+
+Three months have passed and we are happy to announce the release
+of Amber 0.11.0!
+
+Some numbers about this release:
+
+* 494 commits
+* 13 committers
+* increasing the number of core committers to 25
+* 50 unit tests added to the kernel
+* 313 unit tests in total
+
+Since the last release 60 issues were closed, bringing us to 499
+issues closed.
+
+This release includes a lot of bug fixes, improvements to the
+CLI, as well as a preview of the next IDE, named Helios. Amber
+now also uses a CI server [1].
+
+To try the Helios, the new IDE, open the helios.html page, or
+evaluate in any other amber page `amber.loadHelios()`.
+
+The compiler also received some improvements, especially
+regarding message send optimisations and super sends.
+
+Here's the list of commits and closed issues: 
+https://github.com/amber-smalltalk/amber/compare/0.10.0...0.11.0
+https://github.com/amber-smalltalk/amber/issues?direction=desc&milestone=6&page=1&sort=updated&state=closed
+
+There is a lot more to come with Helios, a stepping debugger
+based on the AST is in progress and currently in the 'debugger'
+branch on GitHub.
+
+* Installing Amber from NPM
+
+To install amber from NPM, run
+    
+    npm install amber
+
+
+* Migration from Amber 0.10.0
+
+Amber compiled code should be compatible with Amber 0.10.0, but
+recompiling is needed in order to get contexts working:
+
+    Compiler new recompile: (Package named: 'MyPackage') classes.
+    (Package named: 'MyPackage') commit
+
+For API related changes see the file API-CHANGES.txt.
+
+
+13th March 2013 - Release 0.10.0
+================================
 
 Here's a summary of change since the 0.9.1 release:
 

+ 1 - 26
bin/amberc

@@ -17,10 +17,8 @@ if (1 > parameters.length) {
 // Get Amber root directory from the location of this script so that
 // we can find the st and js directories etc.
 var amber_dir = path.normalize(path.join(path.dirname(process.argv[1]), '..'));
-// Get default location of compiler.jar
-var closure_jar = path.resolve(path.join(process.env['HOME'], 'compiler.jar'));
 
-var compiler = new amberc.Compiler(amber_dir, closure_jar);
+var compiler = new amberc.Compiler(amber_dir);
 
 var configuration = handle_options(parameters, amber_dir);
 
@@ -53,19 +51,6 @@ function handle_options(optionsArray, amber_dir) {
 			case '-n':
 				defaults.amd_namespace = optionsArray.shift();
 				break;
-			case '-o':
-				defaults.closure = true;
-				defaults.closure_parts = true;
-				break;
-			case '-O':
-				defaults.closure = true;
-				defaults.closure_full = true;
-				break;
-			case '-A':
-				defaults.closure = true;
-				defaults.closure_options = defaults.closure_options + ' --compilation_level ADVANCED_OPTIMIZATIONS';
-				defaults.closure_full = true;
-				break;
 			case '-D':
 				defaults.output_dir = optionsArray.shift();
 				break;
@@ -153,16 +138,6 @@ function print_usage() {
 	console.log('     Export packages with <amd_namespace> as the require.js namespace.');
 	console.log('     Default value is "amber_core".');
 	console.log('');
-	console.log('  -o');
-	console.log('     Optimize each .js file using the Google closure compiler.');
-	console.log('     Using Closure compiler found at ~/compiler.jar');
-	console.log('');
-	console.log('  -O');
-	console.log('     Optimize final <Program>.js using the Google closure compiler.');
-	console.log('     Using Closure compiler found at ~/compiler.jar');
-	console.log('');
-	console.log('  -A Same as -O but use --compilation_level ADVANCED_OPTIMIZATIONS');
-	console.log('');
 	console.log('  -D');
 	console.log('     Specifies the output directory for all generated .js files.');
 	console.log('     The hierarchy of the input files is not maintaned.');

+ 4 - 103
bin/amberc.js

@@ -128,9 +128,8 @@ var path = require('path'),
  * amber_dir: points to the location of an amber installation
  * closure_jar: location of compiler.jar (can be left undefined)
  */
-function AmberC(amber_dir, closure_jar) {
+function AmberC(amber_dir) {
 	this.amber_dir = amber_dir;
-	this.closure_jar = closure_jar || '';
 	this.kernel_libraries = ['@boot', '@smalltalk', '@nil', '@_st', 'Kernel-Objects', 'Kernel-Classes', 'Kernel-Methods',
 							'Kernel-Collections', 'Kernel-Infrastructure', 'Kernel-Exceptions', 'Kernel-Transcript',
 							'Kernel-Announcements'];
@@ -155,9 +154,6 @@ var createDefaults = function(amber_dir, finished_callback){
 		'jsFiles': [],
 		'jsGlobals': [],
 		'amd_namespace': 'amber_core',
-		'closure': false,
-		'closure_full': false,
-		'closure_options': ' --language_in=ECMASCRIPT5 ',
 		'suffix': '',
 		'loadsuffix': '',
 		'suffix_used': '',
@@ -196,10 +192,7 @@ AmberC.prototype.main = function(configuration, finished_callback) {
 	if (this.check_configuration_ok(configuration)) {
 		this.defaults = configuration;
 		this.defaults.smalltalk = {}; // the evaluated compiler will be stored in this variable (see create_compiler)
-		var self = this;
-		this.check_for_closure_compiler(function(){
-			self.collect_files(self.defaults.stFiles, self.defaults.jsFiles)
-		});
+		this.collect_files(this.defaults.stFiles, this.defaults.jsFiles)
 	}
 };
 
@@ -219,44 +212,6 @@ AmberC.prototype.check_configuration_ok = function(configuration) {
 };
 
 
-/**
- * Checks if the java executable exists and afterwards,
- * if compiler.jar exists at the path stored in this.closure_jar.
- * All closure related entries are set to false upon failure.
- *
- * callback gets called in any case.
- */
-AmberC.prototype.check_for_closure_compiler = function(callback) {
-	var defaults = this.defaults;
-	var self = this;
-	if (defaults.closure) {
-		exec('which java', function(error, stdout, stderr) {
-			// stdout contains path to java executable
-			if (null !== error) {
-				console.warn('java is not installed but is needed for running the Closure compiler (-O, -A or -o flags).');
-				defaults.closure = false;
-				defaults.closure_full = false;
-				callback();
-				return;
-			}
-			fs.exists(self.closure_jar, function(exists) {
-				if (!exists) {
-					console.warn('Can not find Closure compiler at: ' + self.closure_jar);
-					defaults.closure = false;
-					defaults.closure_full = false;
-				} else {
-					console.warn('Closure compiler found at: ' + self.closure_jar);
-				}
-				callback();
-				return;
-			});
-		});
-	} else {
-		callback();
-	}
-};
-
-
 /**
  * Check if the file given as parameter exists in the local directory or in $AMBER/js/.
  * '.js' is appended first.
@@ -543,7 +498,7 @@ AmberC.prototype.category_export = function() {
 
 /**
  * Verify if all .st files have been compiled.
- * Followed by compose_js_files() and optimize().
+ * Followed by compose_js_files().
  */
 AmberC.prototype.verify = function() {
 	console.log('Verifying if all .st files were compiled');
@@ -575,7 +530,6 @@ AmberC.prototype.compose_js_files = function() {
 	var self = this;
 	var programFile = defaults.program;
 	if (undefined === programFile) {
-		self.optimize();
 		return;
 	}
 	if (undefined !== defaults.output_dir) {
@@ -604,7 +558,7 @@ AmberC.prototype.compose_js_files = function() {
 	});
 
 	fileStream.on('close', function(){
-		self.optimize();
+		return;
 	});
 
 	var builder = createConcatenator();
@@ -651,59 +605,6 @@ AmberC.prototype.compose_js_files = function() {
 };
 
 
-/**
- * Optimize created JavaScript files with Google Closure compiler depending
- * on the flag: defaults.closure_full.
- */
-AmberC.prototype.optimize = function() {
-	var defaults = this.defaults;
-	var self = this;
-	var optimization_done = new Combo(function() {
-		console.log = console.ambercLog;
-		console.timeEnd('Compile Time');
-		if (undefined !== defaults.finished_callback) {
-			defaults.finished_callback();
-		}
-	});
-
-	if (defaults.closure_full && (undefined !== defaults.program)) {
-		var programFile = defaults.program;
-		if (undefined !== defaults.output_dir) {
-			programFile = path.join(defaults.output_dir, programFile);
-		}
-		console.log('Compiling ' + programFile + '.js file using Google closure compiler.');
-		self.closure_compile(programFile + '.js', programFile + '.min.js', optimization_done.add());
-	}
-
-	always_resolve(optimization_done.add());
-};
-
-
-/**
- * Compile sourceFile into minifiedFile with Google Closure compiler.
- * callback gets executed once finished.
- */
-AmberC.prototype.closure_compile = function(sourceFile, minifiedFile, callback) {
-	// exec is asynchronous
-	var self = this;
-	exec(
-		'java -jar ' +
-		self.closure_jar + ' ' +
-		self.defaults.closure_options +
-		' --js '+ sourceFile +
-		' --js_output_file '+ minifiedFile,
-		function (error, stdout, stderr) {
-			if (error) {
-				console.log(stderr);
-			} else {
-				console.log(stdout);
-				console.log('Minified: '+ minifiedFile);
-			}
-			callback();
-		}
-	);
-};
-
 module.exports.Compiler = AmberC;
 module.exports.createDefaults = createDefaults;
 module.exports.Combo = Combo;

BIN
browser.png


+ 24 - 14
grunt/tasks/grunt-amberc.js

@@ -5,14 +5,23 @@ module.exports = function(grunt) {
   var amberc = require('../../bin/amberc.js');
 
   /**
-     Full config looks like this:
+     A full example entry for a Gruntfile.js is available below.
+     Please note that the verbose level is either specified globally
+     or on a target specific level.
+     However, it can additionally be triggered on the commandline by
+     adding the '-v' or '--verbose' flag.
+
+     Example Gruntfile.js entry:
+
      amberc: {
-       _config: {
+       options: {
          amber_dir: process.cwd(),     // REQUIRED
-         closure_jar: '',              // optional
          verbose: true                 // optional
        },
        helloWorld: {
+         options: {                             // the 'options' object is optional
+           verbose: true
+         },
          src: ['projects/HelloWorld/st/HelloWorld.st'], // REQUIRED
          output_dir: 'projects/HelloWorld/js',  // optional
          libraries: 'Canvas',                   // optional
@@ -28,25 +37,27 @@ module.exports = function(grunt) {
 
    */
   grunt.registerMultiTask('amberc', 'Compile Smalltalk files with the amberc compiler', function() {
-    // mark required properties
-    this.requiresConfig('amberc.options.amber_dir');
-    this.requiresConfig(['amberc', this.target, 'src']);
+    // mark task as async task
+    var done = this.async();
 
     var options = this.options({
       amber_dir: undefined,
-      closure_jar: '',
-      verbose: false
+      verbose: grunt.option('verbose') || false
     });
     this.data.verbose = options.verbose;
 
-    // mark task as async task
-    var done = this.async();
+    // mark required properties
+    this.requiresConfig('amberc.options.amber_dir');
+    // raise error on missing source files
+    if (this.filesSrc.length === 0) {
+        grunt.fail.fatal('No source files to compile or link.');
+    }
 
     // create and initialize amberc
-    var compiler = new amberc.Compiler(grunt.config('amberc.options.amber_dir'), grunt.config('amberc.options.closure_jar'));
+    var compiler = new amberc.Compiler(grunt.config('amberc.options.amber_dir'));
 
     // generate the amberc configuration out of the given target properties
-    var configuration = generateCompilerConfiguration(this.data, grunt.config('amberc.options.amber_dir'));
+    var configuration = generateCompilerConfiguration(this.data, this.filesSrc, grunt.config('amberc.options.amber_dir'));
 
     // run the compiler and call the async callback once finished
     var self = this;
@@ -57,7 +68,7 @@ module.exports = function(grunt) {
   });
 
 
-  function generateCompilerConfiguration(data, amber_dir) {
+  function generateCompilerConfiguration(data, sourceFiles, amber_dir) {
     var configuration = amberc.createDefaults(amber_dir);
     var parameters = [];
 
@@ -83,7 +94,6 @@ module.exports = function(grunt) {
       configuration.loadsuffix = librarySuffix;
       configuration.suffix_used = librarySuffix;
     }
-    var sourceFiles = data.src;
     if (undefined !== sourceFiles) {
       sourceFiles.forEach(function(currentItem){
         var fileSuffix = path.extname(currentItem);

+ 2 - 1
js/Compiler-Tests.js

@@ -515,9 +515,10 @@ self._should_return_("foo ^ false",false);
 self._should_return_("foo ^ #{1->2. 3->4}",smalltalk.HashedCollection._from_([(1).__minus_gt((2)),(3).__minus_gt((4))]));
 self._should_return_("foo ^ #hello","hello");
 self._should_return_("foo ^ -123.456",(-123.456));
+self._should_return_("foo ^ -2.5e4",(-25000));
 return self}, function($ctx1) {$ctx1.fill(self,"testLiterals",{},smalltalk.CodeGeneratorTest)})},
 args: [],
-source: "testLiterals\x0a\x09self should: 'foo ^ 1' return: 1.\x0a\x09self should: 'foo ^ ''hello''' return: 'hello'.\x0a\x09self should: 'foo ^ #(1 2 3 4)' return: #(1 2 3 4).\x0a\x09self should: 'foo ^ {1. [:x | x ] value: 2. 3. [4] value}' return: #(1 2 3 4).\x0a\x09self should: 'foo ^ true' return: true.\x0a\x09self should: 'foo ^ false' return: false.\x0a\x09self should: 'foo ^ #{1->2. 3->4}' return: #{1->2. 3->4}.\x0a\x09self should: 'foo ^ #hello' return: #hello.\x0a\x09self should: 'foo ^ -123.456' return: -123.456",
+source: "testLiterals\x0a\x09self should: 'foo ^ 1' return: 1.\x0a\x09self should: 'foo ^ ''hello''' return: 'hello'.\x0a\x09self should: 'foo ^ #(1 2 3 4)' return: #(1 2 3 4).\x0a\x09self should: 'foo ^ {1. [:x | x ] value: 2. 3. [4] value}' return: #(1 2 3 4).\x0a\x09self should: 'foo ^ true' return: true.\x0a\x09self should: 'foo ^ false' return: false.\x0a\x09self should: 'foo ^ #{1->2. 3->4}' return: #{1->2. 3->4}.\x0a\x09self should: 'foo ^ #hello' return: #hello.\x0a\x09self should: 'foo ^ -123.456' return: -123.456.\x0a\x09self should: 'foo ^ -2.5e4' return: -25000.",
 messageSends: ["should:return:", "->"],
 referencedClasses: []
 }),

+ 240 - 2
js/Kernel-Objects.js

@@ -2229,6 +2229,24 @@ referencedClasses: []
 }),
 smalltalk.Number);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "**",
+category: 'mathematical functions',
+fn: function (exponent){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=self._raisedTo_(exponent);
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"**",{exponent:exponent},smalltalk.Number)})},
+args: ["exponent"],
+source: "** exponent\x0a\x09^self raisedTo: exponent",
+messageSends: ["raisedTo:"],
+referencedClasses: []
+}),
+smalltalk.Number);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "+",
@@ -2277,6 +2295,24 @@ referencedClasses: []
 }),
 smalltalk.Number);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "//",
+category: 'arithmetic',
+fn: function (aNumber){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1;
+$1=_st(self.__slash(aNumber))._floor();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"//",{aNumber:aNumber},smalltalk.Number)})},
+args: ["aNumber"],
+source: "// aNumber\x0a\x09^(self / aNumber) floor",
+messageSends: ["floor", "/"],
+referencedClasses: []
+}),
+smalltalk.Number);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "<",
@@ -2413,6 +2449,54 @@ referencedClasses: []
 }),
 smalltalk.Number);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "arcCos",
+category: 'mathematical functions',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return Math.acos(self);;
+return self}, function($ctx1) {$ctx1.fill(self,"arcCos",{},smalltalk.Number)})},
+args: [],
+source: "arcCos\x0a\x09<return Math.acos(self);>",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Number);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "arcSin",
+category: 'mathematical functions',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return Math.asin(self);;
+return self}, function($ctx1) {$ctx1.fill(self,"arcSin",{},smalltalk.Number)})},
+args: [],
+source: "arcSin\x0a\x09<return Math.asin(self);>",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Number);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "arcTan",
+category: 'mathematical functions',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return Math.atan(self);;
+return self}, function($ctx1) {$ctx1.fill(self,"arcTan",{},smalltalk.Number)})},
+args: [],
+source: "arcTan\x0a\x09<return Math.atan(self);>",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Number);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "asJSON",
@@ -2555,6 +2639,22 @@ referencedClasses: []
 }),
 smalltalk.Number);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "cos",
+category: 'mathematical functions',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return Math.cos(self);;
+return self}, function($ctx1) {$ctx1.fill(self,"cos",{},smalltalk.Number)})},
+args: [],
+source: "cos\x0a\x09<return Math.cos(self);>",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Number);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "deepCopy",
@@ -2675,6 +2775,54 @@ referencedClasses: []
 }),
 smalltalk.Number);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "ln",
+category: 'mathematical functions',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return Math.log(self);;
+return self}, function($ctx1) {$ctx1.fill(self,"ln",{},smalltalk.Number)})},
+args: [],
+source: "ln\x0a\x09<return Math.log(self);>",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Number);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "log",
+category: 'mathematical functions',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return Math.log(self) / Math.LN10;;
+return self}, function($ctx1) {$ctx1.fill(self,"log",{},smalltalk.Number)})},
+args: [],
+source: "log\x0a\x09<return Math.log(self) / Math.LN10;>",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Number);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "log:",
+category: 'mathematical functions',
+fn: function (aNumber){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return Math.log(self) / Math.log(aNumber);;
+return self}, function($ctx1) {$ctx1.fill(self,"log:",{aNumber:aNumber},smalltalk.Number)})},
+args: ["aNumber"],
+source: "log: aNumber\x0a\x09<return Math.log(self) / Math.log(aNumber);>",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Number);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "max:",
@@ -2811,6 +2959,22 @@ referencedClasses: []
 }),
 smalltalk.Number);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "raisedTo:",
+category: 'mathematical functions',
+fn: function (exponent){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return Math.pow(self, exponent);;
+return self}, function($ctx1) {$ctx1.fill(self,"raisedTo:",{exponent:exponent},smalltalk.Number)})},
+args: ["exponent"],
+source: "raisedTo: exponent\x0a\x09<return Math.pow(self, exponent);>",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Number);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "rounded",
@@ -2827,10 +2991,52 @@ referencedClasses: []
 }),
 smalltalk.Number);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "sign",
+category: 'mathematical functions',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+var $1,$2;
+$1=self._isZero();
+if(smalltalk.assert($1)){
+return (0);
+};
+$2=self._positive();
+if(smalltalk.assert($2)){
+return (1);
+} else {
+return (-1);
+};
+return self}, function($ctx1) {$ctx1.fill(self,"sign",{},smalltalk.Number)})},
+args: [],
+source: "sign\x0a\x09self isZero \x0a\x09\x09ifTrue: [ ^ 0 ].\x0a\x09self positive\x0a\x09\x09ifTrue: [ ^ 1 ]\x0a\x09\x09ifFalse: [ ^ -1 ].",
+messageSends: ["ifTrue:", "isZero", "ifTrue:ifFalse:", "positive"],
+referencedClasses: []
+}),
+smalltalk.Number);
+
+smalltalk.addMethod(
+smalltalk.method({
+selector: "sin",
+category: 'mathematical functions',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return Math.sin(self);;
+return self}, function($ctx1) {$ctx1.fill(self,"sin",{},smalltalk.Number)})},
+args: [],
+source: "sin\x0a\x09<return Math.sin(self);>",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Number);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "sqrt",
-category: 'arithmetic',
+category: 'mathematical functions',
 fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
@@ -2846,7 +3052,7 @@ smalltalk.Number);
 smalltalk.addMethod(
 smalltalk.method({
 selector: "squared",
-category: 'arithmetic',
+category: 'mathematical functions',
 fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
@@ -2861,6 +3067,22 @@ referencedClasses: []
 }),
 smalltalk.Number);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "tan",
+category: 'mathematical functions',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return Math.tan(self);;
+return self}, function($ctx1) {$ctx1.fill(self,"tan",{},smalltalk.Number)})},
+args: [],
+source: "tan\x0a\x09<return Math.tan(self);>",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Number);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "timesRepeat:",
@@ -3081,6 +3303,22 @@ referencedClasses: []
 smalltalk.Number);
 
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "e",
+category: 'instance creation',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+return Math.E;;
+return self}, function($ctx1) {$ctx1.fill(self,"e",{},smalltalk.Number.klass)})},
+args: [],
+source: "e\x0a\x09<return Math.E;>",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.Number.klass);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "heliosClass",

+ 82 - 2
js/Kernel-Tests.js

@@ -3478,12 +3478,14 @@ self._assert_equals_((2).__minus((1)),(1));
 self._assert_equals_((-2).__minus((1)),(-3));
 self._assert_equals_((12).__slash((2)),(6));
 self._assert_equals_((3).__star((4)),(12));
+self._assert_equals_((7).__slash_slash((2)),(3));
+self._assert_equals_((7).__backslash_backslash((2)),(1));
 self._assert_equals_(_st((1).__plus((2))).__star((3)),(9));
 self._assert_equals_((1).__plus((2).__star((3))),(7));
 return self}, function($ctx1) {$ctx1.fill(self,"testArithmetic",{},smalltalk.NumberTest)})},
 args: [],
-source: "testArithmetic\x0a\x09\x0a\x09\x22We rely on JS here, so we won't test complex behavior, just check if\x0a\x09message sends are corrects\x22\x0a\x0a\x09self assert: 1.5 + 1 equals: 2.5.\x0a\x09self assert: 2 - 1 equals: 1.\x0a\x09self assert: -2 - 1 equals: -3.\x0a\x09self assert: 12 / 2 equals: 6.\x0a\x09self assert: 3 * 4 equals: 12.\x0a\x0a\x09\x22Simple parenthesis and execution order\x22\x0a\x09self assert: 1 + 2 * 3 equals: 9.\x0a\x09self assert: 1 + (2 * 3) equals: 7",
-messageSends: ["assert:equals:", "+", "-", "/", "*"],
+source: "testArithmetic\x0a\x09\x0a\x09\x22We rely on JS here, so we won't test complex behavior, just check if\x0a\x09message sends are corrects\x22\x0a\x0a\x09self assert: 1.5 + 1 equals: 2.5.\x0a\x09self assert: 2 - 1 equals: 1.\x0a\x09self assert: -2 - 1 equals: -3.\x0a\x09self assert: 12 / 2 equals: 6.\x0a\x09self assert: 3 * 4 equals: 12.\x0a\x09self assert: 7 // 2 equals: 3.\x0a\x09self assert: 7 \x5c\x5c 2 equals: 1.\x0a\x0a\x09\x22Simple parenthesis and execution order\x22\x0a\x09self assert: 1 + 2 * 3 equals: 9.\x0a\x09self assert: 1 + (2 * 3) equals: 7",
+messageSends: ["assert:equals:", "+", "-", "/", "*", "//", "\x5c\x5c"],
 referencedClasses: []
 }),
 smalltalk.NumberTest);
@@ -3829,6 +3831,25 @@ referencedClasses: ["MessageNotUnderstood"]
 }),
 smalltalk.NumberTest);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "testLog",
+category: 'tests',
+fn: function (){
+var self=this;
+function $Number(){return smalltalk.Number||(typeof Number=="undefined"?nil:Number)}
+return smalltalk.withContext(function($ctx1) { 
+self._assert_equals_((10000)._log(),(4));
+self._assert_equals_((512)._log_((2)),(9));
+self._assert_equals_(_st(_st($Number())._e())._ln(),(1));
+return self}, function($ctx1) {$ctx1.fill(self,"testLog",{},smalltalk.NumberTest)})},
+args: [],
+source: "testLog\x0a\x09self assert: 10000 log equals: 4.\x0a\x09self assert: (512 log: 2) equals: 9.\x0a\x09self assert: Number e ln equals: 1.",
+messageSends: ["assert:equals:", "log", "log:", "ln", "e"],
+referencedClasses: ["Number"]
+}),
+smalltalk.NumberTest);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "testMinMax",
@@ -3891,6 +3912,26 @@ referencedClasses: []
 }),
 smalltalk.NumberTest);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "testRaisedTo",
+category: 'tests',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self._assert_equals_((2)._raisedTo_((4)),(16));
+self._assert_equals_((2)._raisedTo_((0)),(1));
+self._assert_equals_((2)._raisedTo_((-3)),(0.125));
+self._assert_equals_((4)._raisedTo_((0.5)),(2));
+self._assert_equals_((2).__star_star((4)),(16));
+return self}, function($ctx1) {$ctx1.fill(self,"testRaisedTo",{},smalltalk.NumberTest)})},
+args: [],
+source: "testRaisedTo\x0a\x09self assert: (2 raisedTo: 4) equals: 16.\x0a\x09self assert: (2 raisedTo: 0) equals: 1.\x0a\x09self assert: (2 raisedTo: -3) equals: 0.125.\x0a\x09self assert: (4 raisedTo: 0.5) equals: 2.\x0a\x09\x0a\x09self assert: 2 ** 4 equals: 16.",
+messageSends: ["assert:equals:", "raisedTo:", "**"],
+referencedClasses: []
+}),
+smalltalk.NumberTest);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "testRounded",
@@ -3909,6 +3950,24 @@ referencedClasses: []
 }),
 smalltalk.NumberTest);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "testSign",
+category: 'tests',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self._assert_equals_((5)._sign(),(1));
+self._assert_equals_((0)._sign(),(0));
+self._assert_equals_((-1.4)._sign(),(-1));
+return self}, function($ctx1) {$ctx1.fill(self,"testSign",{},smalltalk.NumberTest)})},
+args: [],
+source: "testSign\x0a\x09self assert: 5 sign equals: 1.\x0a\x09self assert: 0 sign equals: 0.\x0a\x09self assert: -1.4 sign equals: -1.",
+messageSends: ["assert:equals:", "sign"],
+referencedClasses: []
+}),
+smalltalk.NumberTest);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "testSqrt",
@@ -4008,6 +4067,27 @@ referencedClasses: ["Error"]
 }),
 smalltalk.NumberTest);
 
+smalltalk.addMethod(
+smalltalk.method({
+selector: "testTrigonometry",
+category: 'tests',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
+self._assert_equals_((0)._cos(),(1));
+self._assert_equals_((0)._sin(),(0));
+self._assert_equals_((0)._tan(),(0));
+self._assert_equals_((1)._arcCos(),(0));
+self._assert_equals_((0)._arcSin(),(0));
+self._assert_equals_((0)._arcTan(),(0));
+return self}, function($ctx1) {$ctx1.fill(self,"testTrigonometry",{},smalltalk.NumberTest)})},
+args: [],
+source: "testTrigonometry\x0a\x09self assert: 0 cos equals: 1.\x0a\x09self assert: 0 sin equals: 0.\x0a\x09self assert: 0 tan equals: 0.\x0a\x09self assert: 1 arcCos equals: 0.\x0a\x09self assert: 0 arcSin equals: 0.\x0a\x09self assert: 0 arcTan equals: 0.",
+messageSends: ["assert:equals:", "cos", "sin", "tan", "arcCos", "arcSin", "arcTan"],
+referencedClasses: []
+}),
+smalltalk.NumberTest);
+
 smalltalk.addMethod(
 smalltalk.method({
 selector: "testTruncated",

+ 12 - 11
st/Compiler-Tests.st

@@ -222,7 +222,8 @@ testLiterals
 	self should: 'foo ^ false' return: false.
 	self should: 'foo ^ #{1->2. 3->4}' return: #{1->2. 3->4}.
 	self should: 'foo ^ #hello' return: #hello.
-	self should: 'foo ^ -123.456' return: -123.456
+	self should: 'foo ^ -123.456' return: -123.456.
+	self should: 'foo ^ -2.5e4' return: -25000.
 !
 
 testLocalReturn
@@ -301,6 +302,16 @@ testSuperSend
 		return: false
 !
 
+testTempVariables
+	self should: 'foo | a | ^ a' return: nil.
+	self should: 'foo | AVariable | ^ AVariable' return: nil.
+	self should: 'foo | a b c | ^ c' return: nil.
+	self should: 'foo | a | [ | d | ^ d ] value' return: nil.
+	
+	self should: 'foo | a | a:= 1. ^ a' return: 1.
+	self should: 'foo | AVariable | AVariable := 1. ^ AVariable' return: 1.
+!
+
 testThisContext
 	self should: 'foo ^ [ thisContext ] value outerContext == thisContext' return: true
 !
@@ -370,16 +381,6 @@ testifTrueIfFalse
 	
 	self should: 'foo ^ false ifTrue: [ 2 ] ifFalse: [ 1 ]' return: 1.
 	self should: 'foo ^ true ifTrue: [ 2 ] ifFalse: [ 1 ]' return: 2.
-!
-
-testTempVariables
-	self should: 'foo | a | ^ a' return: nil.
-	self should: 'foo | AVariable | ^ AVariable' return: nil.
-	self should: 'foo | a b c | ^ c' return: nil.
-	self should: 'foo | a | [ | d | ^ d ] value' return: nil.
-	
-	self should: 'foo | a | a:= 1. ^ a' return: 1.
-	self should: 'foo | AVariable | AVariable := 1. ^ AVariable' return: 1.
 ! !
 
 CodeGeneratorTest subclass: #InliningCodeGeneratorTest

+ 68 - 6
st/Kernel-Objects.st

@@ -775,12 +775,8 @@ negated
 	^0 - self
 !
 
-sqrt
-	<return Math.sqrt(self)>
-!
-
-squared
-	^self * self
+// aNumber
+	^(self / aNumber) floor
 ! !
 
 !Number methodsFor: 'comparing'!
@@ -948,6 +944,68 @@ to: stop do: aBlock
 			nextValue := nextValue + 1]
 ! !
 
+!Number methodsFor: 'mathematical functions'!
+
+sqrt
+	<return Math.sqrt(self)>
+!
+
+squared
+	^self * self
+!
+
+cos
+	<return Math.cos(self);>
+!
+
+sin
+	<return Math.sin(self);>
+!
+
+tan
+	<return Math.tan(self);>
+!
+
+arcCos
+	<return Math.acos(self);>
+!
+
+arcSin
+	<return Math.asin(self);>
+!
+
+arcTan
+	<return Math.atan(self);>
+!
+
+log
+	<return Math.log(self) / Math.LN10;>
+!
+
+log: aNumber
+	<return Math.log(self) / Math.log(aNumber);>
+!
+
+raisedTo: exponent
+	<return Math.pow(self, exponent);>
+!
+
+sign
+	self isZero 
+		ifTrue: [ ^ 0 ].
+	self positive
+		ifTrue: [ ^ 1 ]
+		ifFalse: [ ^ -1 ].
+!
+
+** exponent
+	^self raisedTo: exponent
+!
+
+ln
+	<return Math.log(self);>
+! !
+
 !Number methodsFor: 'printing'!
 
 printOn: aStream
@@ -1002,6 +1060,10 @@ heliosClass
 
 pi
 	<return Math.PI>
+!
+
+e
+	<return Math.E;>
 ! !
 
 Object subclass: #Point

+ 32 - 0
st/Kernel-Tests.st

@@ -1309,6 +1309,8 @@ testArithmetic
 	self assert: -2 - 1 equals: -3.
 	self assert: 12 / 2 equals: 6.
 	self assert: 3 * 4 equals: 12.
+	self assert: 7 // 2 equals: 3.
+	self assert: 7 \\ 2 equals: 1.
 
 	"Simple parenthesis and execution order"
 	self assert: 1 + 2 * 3 equals: 9.
@@ -1504,6 +1506,36 @@ testTruncated
 	self assert: 3 truncated equals: 3.
 	self assert: 3.212 truncated equals: 3.
 	self assert: 3.51 truncated equals: 3
+!
+
+testTrigonometry
+	self assert: 0 cos equals: 1.
+	self assert: 0 sin equals: 0.
+	self assert: 0 tan equals: 0.
+	self assert: 1 arcCos equals: 0.
+	self assert: 0 arcSin equals: 0.
+	self assert: 0 arcTan equals: 0.
+!
+
+testLog
+	self assert: 10000 log equals: 4.
+	self assert: (512 log: 2) equals: 9.
+	self assert: Number e ln equals: 1.
+!
+
+testRaisedTo
+	self assert: (2 raisedTo: 4) equals: 16.
+	self assert: (2 raisedTo: 0) equals: 1.
+	self assert: (2 raisedTo: -3) equals: 0.125.
+	self assert: (4 raisedTo: 0.5) equals: 2.
+	
+	self assert: 2 ** 4 equals: 16.
+!
+
+testSign
+	self assert: 5 sign equals: 1.
+	self assert: 0 sign equals: 0.
+	self assert: -1.4 sign equals: -1.
 ! !
 
 Object subclass: #ObjectMock

+ 1 - 0
support/deploy.js

@@ -1,6 +1,7 @@
 define([
     'amber_vm/smalltalk',
     './helpers',
+    'jquery',
     'amber_core/Kernel-Objects',
     'amber_core/Kernel-Classes',
     'amber_core/Kernel-Methods',

+ 64 - 3
support/parser.js

@@ -49,6 +49,7 @@ smalltalk.parser = (function(){
         "symbol": parse_symbol,
         "bareSymbol": parse_bareSymbol,
         "number": parse_number,
+        "numberExp": parse_numberExp,
         "hex": parse_hex,
         "float": parse_float,
         "integer": parse_integer,
@@ -875,11 +876,14 @@ smalltalk.parser = (function(){
         var pos0;
         
         pos0 = clone(pos);
-        result0 = parse_hex();
+        result0 = parse_numberExp();
         if (result0 === null) {
-          result0 = parse_float();
+          result0 = parse_hex();
           if (result0 === null) {
-            result0 = parse_integer();
+            result0 = parse_float();
+            if (result0 === null) {
+              result0 = parse_integer();
+            }
           }
         }
         if (result0 !== null) {
@@ -900,6 +904,63 @@ smalltalk.parser = (function(){
         return result0;
       }
       
+      function parse_numberExp() {
+        var cacheKey = "numberExp@" + pos.offset;
+        var cachedResult = cache[cacheKey];
+        if (cachedResult) {
+          pos = clone(cachedResult.nextPos);
+          return cachedResult.result;
+        }
+        
+        var result0, result1, result2;
+        var pos0, pos1;
+        
+        pos0 = clone(pos);
+        pos1 = clone(pos);
+        result0 = parse_float();
+        if (result0 === null) {
+          result0 = parse_integer();
+        }
+        if (result0 !== null) {
+          if (input.charCodeAt(pos.offset) === 101) {
+            result1 = "e";
+            advance(pos, 1);
+          } else {
+            result1 = null;
+            if (reportFailures === 0) {
+              matchFailed("\"e\"");
+            }
+          }
+          if (result1 !== null) {
+            result2 = parse_integer();
+            if (result2 !== null) {
+              result0 = [result0, result1, result2];
+            } else {
+              result0 = null;
+              pos = clone(pos1);
+            }
+          } else {
+            result0 = null;
+            pos = clone(pos1);
+          }
+        } else {
+          result0 = null;
+          pos = clone(pos1);
+        }
+        if (result0 !== null) {
+          result0 = (function(offset, line, column, n) {return parseFloat(n.join(""));})(pos0.offset, pos0.line, pos0.column, result0);
+        }
+        if (result0 === null) {
+          pos = clone(pos0);
+        }
+        
+        cache[cacheKey] = {
+          nextPos: clone(pos),
+          result:  result0
+        };
+        return result0;
+      }
+      
       function parse_hex() {
         var cacheKey = "hex@" + pos.offset;
         var cachedResult = cache[cacheKey];

+ 3 - 1
support/parser.pegjs

@@ -20,14 +20,16 @@ bareSymbol         = val:(selector / binarySelector / node:string {return node._
                              ._position_((line).__at(column))
                              ._value_(val);
                   }
-number         = n:(hex / float / integer) {
+number         = n:(numberExp / hex / float / integer) {
                      return smalltalk.ValueNode._new()
                             ._position_((line).__at(column))
                             ._value_(n);
                  }
+numberExp      = n:((float / integer) "e" integer) {return parseFloat(n.join(""));}
 hex            = neg:[-]? "16r" num:[0-9a-fA-F]+ {return parseInt((neg + num.join("")), 16);}
 float          = neg:[-]?digits:[0-9]+ "." dec:[0-9]+ {return parseFloat((neg + digits.join("") + "." + dec.join("")), 10);}
 integer        = neg:[-]?digits:[0-9]+ {return (parseInt(neg+digits.join(""), 10));}
+
 literalArray   = "#(" rest:literalArrayRest {return rest;}
 bareLiteralArray   = "(" rest:literalArrayRest {return rest;}
 literalArrayRest   = ws lits:(lit:(parseTimeLiteral / bareLiteralArray / bareSymbol) ws {return lit._value();})* ws ")" {