Browse Source

Merge pull request #476 from mkroehnert/compiler

Compiler updates
Nicolas Petton 11 years ago
parent
commit
97509e8cf7
4 changed files with 96 additions and 95 deletions
  1. 26 33
      Gruntfile.js
  2. 3 0
      bin/amberc
  3. 59 21
      bin/amberc.js
  4. 8 41
      grunt/tasks/grunt-amberc.js

+ 26 - 33
Gruntfile.js

@@ -33,73 +33,66 @@ module.exports = function(grunt) {
         closure_jar: ''
       },
       all: {
-        working_dir: 'st',
-        target_dir : 'js',
-        src: ['Kernel-Objects.st', 'Kernel-Classes.st', 'Kernel-Methods.st', 'Kernel-Collections.st',
-              'Kernel-Exceptions.st', 'Kernel-Transcript.st', 'Kernel-Announcements.st',
-              'Importer-Exporter.st', 'Compiler-Exceptions.st', 'Compiler-Core.st', 'Compiler-AST.st',
-              'Compiler-IR.st', 'Compiler-Inlining.st', 'Compiler-Semantic.st',
-              'Canvas.st', 'SUnit.st', 'IDE.st',
-              'Kernel-Tests.st', 'Compiler-Tests.st', 'SUnit-Tests.st'
+        output_dir : 'js',
+        src: ['st/Kernel-Objects.st', 'st/Kernel-Classes.st', 'st/Kernel-Methods.st', 'st/Kernel-Collections.st',
+              'st/Kernel-Exceptions.st', 'st/Kernel-Transcript.st', 'st/Kernel-Announcements.st',
+              'st/Importer-Exporter.st', 'st/Compiler-Exceptions.st', 'st/Compiler-Core.st', 'st/Compiler-AST.st',
+              'st/Compiler-IR.st', 'st/Compiler-Inlining.st', 'st/Compiler-Semantic.st',
+              'st/Canvas.st', 'st/SUnit.st', 'st/IDE.st',
+              'st/Kernel-Tests.st', 'st/Compiler-Tests.st', 'st/SUnit-Tests.st'
               ],
         deploy: true
       },
       amber_kernel: {
-        working_dir: 'st',
-        target_dir : 'js',
-        src: ['Kernel-Objects.st', 'Kernel-Classes.st', 'Kernel-Methods.st', 'Kernel-Collections.st',
-              'Kernel-Exceptions.st', 'Kernel-Transcript.st', 'Kernel-Announcements.st'],
+        output_dir : 'js',
+        src: ['st/Kernel-Objects.st', 'st/Kernel-Classes.st', 'st/Kernel-Methods.st', 'st/Kernel-Collections.st',
+              'st/Kernel-Exceptions.st', 'st/Kernel-Transcript.st', 'st/Kernel-Announcements.st'],
         deploy: true
       },
       amber_compiler: {
-        working_dir: 'st',
-        target_dir : 'js',
-        src: ['Importer-Exporter.st', 'Compiler-Exceptions.st', 'Compiler-Core.st', 'Compiler-AST.st',
-              'Compiler-IR.st', 'Compiler-Inlining.st', 'Compiler-Semantic.st'],
+        output_dir : 'js',
+        src: ['st/Importer-Exporter.st', 'st/Compiler-Exceptions.st', 'st/Compiler-Core.st', 'st/Compiler-AST.st',
+              'st/Compiler-IR.st', 'st/Compiler-Inlining.st', 'st/Compiler-Semantic.st'],
         output_name: 'Compiler',
         deploy: true
       },
       amber_canvas: {
-        working_dir: 'st',
-        target_dir : 'js',
-        src: ['Canvas.st', 'SUnit.st'],
-        deploy: true
+        output_dir : 'js',
+        src: ['st/Canvas.st', 'st/SUnit.st'],
+        deploy: true,
+        verbose: true
       },
       amber_IDE: {
-        working_dir: 'st',
-        target_dir : 'js',
-        src: ['IDE.st'],
+        output_dir : 'js',
+        src: ['st/IDE.st'],
         libraries: ['Canvas'],
         deploy: true
       },
       amber_tests: {
-        working_dir: 'st',
-        target_dir : 'js',
-        src: ['Kernel-Tests.st', 'Compiler-Tests.st', 'SUnit-Tests.st'],
+        output_dir : 'js',
+        src: ['st/Kernel-Tests.st', 'st/Compiler-Tests.st', 'st/SUnit-Tests.st'],
         libraries: ['SUnit']
       },
       amber_test_runner: {
-        working_dir: 'test',
-        src: ['Test.st'],
+        src: ['test/Test.st'],
         libraries: [
         'Compiler-Exceptions', 'Compiler-Core', 'Compiler-AST',
         'Compiler-IR', 'Compiler-Inlining', 'Compiler-Semantic', 'Compiler-Interpreter', 'parser',
         'SUnit',
         'Kernel-Tests', 'Compiler-Tests', 'SUnit-Tests'],
-        output_name: 'amber_test_runner'
+        output_name: 'test/amber_test_runner'
       },
       amber_dev: {
-        working_dir: 'js',
         src: [
               'Compiler-Exceptions.js', 'Compiler-Core.js', 'Compiler-AST.js',
               'Compiler-IR.js', 'Compiler-Inlining.js', 'Compiler-Semantic.js',
               'Canvas.js', 'IDE.js', 'SUnit.js',
               'Kernel-Tests.js', 'Compiler-Tests.js', 'SUnit-Tests.js'],
-        output_name: 'amber_dev'
+        output_name: 'js/amber_dev'
       },
       amber_cli: {
-        working_dir: 'cli/js',
-        src: ['../st/AmberCli.st'],
+        output_dir: 'cli/js',
+        src: ['cli/st/AmberCli.st'],
         main_class: 'AmberCli',
         output_name: 'amber-cli'
       }

+ 3 - 0
bin/amberc

@@ -66,6 +66,9 @@ function handle_options(optionsArray, amber_dir) {
 			case '-d':
 				defaults.deploy = true;
 				break;
+			case '-D':
+				defaults.output_dir = optionsArray.shift();
+				break;
 			case '-s':
 				defaults.suffix = optionsArray.shift();
 				defaults.suffix_used = defaults.suffix;

+ 59 - 21
bin/amberc.js

@@ -116,9 +116,9 @@ var createDefaults = function(amber_dir, finished_callback){
 		'deploy': false,
 		'libraries': [],
 		'compile': [],
-		'compiled_categories': [],
 		'compiled': [],
 		'program': undefined,
+		'output_dir': undefined,
 		'verbose': false,
 		'finished_callback': finished_callback
 	};
@@ -127,6 +127,9 @@ var createDefaults = function(amber_dir, finished_callback){
 
 /**
  * Main function for executing the compiler.
+ * If check_configuration_ok() returns successfully the configuration is set on the current compiler
+ * instance and check_for_closure_compiler() gets called.
+ * The last step is to call collect_files().
  */
 AmberC.prototype.main = function(configuration, finished_callback) {
 	console.time('Compile Time');
@@ -134,6 +137,10 @@ AmberC.prototype.main = function(configuration, finished_callback) {
 		configuration.finished_callback = finished_callback;
 	}
 
+	if (configuration.closure || configuration.closure_parts || configuration.closure_full) {
+		configuration.deploy = true;
+	}
+
 	console.ambercLog = console.log;
 	if (false === configuration.verbose) {
 		console.log = function() {};
@@ -182,7 +189,7 @@ AmberC.prototype.check_for_closure_compiler = function(callback) {
 		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 -O, -A or -o (Closure compiler).');
+				console.warn('java is not installed but is needed for running the Closure compiler (-O, -A or -o flags).');
 				defaults.closure = false;
 				defaults.closure_parts = false;
 				defaults.closure_full = false;
@@ -266,10 +273,7 @@ AmberC.prototype.collect_st_files = function(stFiles, callback) {
 	var collected_st_files = new Combo(function() {
 		Array.prototype.slice.call(arguments).forEach(function(data) {
 			var stFile = data[0];
-			var stCategory = data[1];
 			defaults.compile.push(stFile);
-			defaults.compiled_categories.push(stCategory);
-			defaults.compiled.push(stCategory + defaults.suffix_used + '.js');
 		});
 		callback();
 	});
@@ -277,15 +281,15 @@ AmberC.prototype.collect_st_files = function(stFiles, callback) {
 	stFiles.forEach(function(stFile) {
 		var _callback = collected_st_files.add();
 		console.log('Checking: ' + stFile);
-		var category = path.basename(stFile, '.st');
 		var amberStFile = path.join(self.amber_dir, 'st', stFile);
 		fs.exists(stFile, function(exists) {
 			if (exists) {
-				_callback(stFile, category);
+				_callback(stFile);
 			} else {
+				console.log('Checking: ' + amberStFile);
 				fs.exists(amberStFile, function(exists) {
 					if (exists) {
-						_callback(amberStFile, category);
+						_callback(amberStFile);
 					} else {
 						throw(new Error('Smalltalk file not found: ' + amberStFile));
 					}
@@ -470,9 +474,18 @@ AmberC.prototype.category_export = function() {
 	var defaults = this.defaults;
 	var self = this;
 	// export categories as .js
-	async_map(defaults.compiled_categories, function(category, callback) {
+	async_map(defaults.compile, function(stFile, callback) {
+		var category = path.basename(stFile, '.st');
+		var jsFilePath = defaults.output_dir;
+		if (undefined === jsFilePath) {
+			jsFilePath = path.dirname(stFile);
+		}
 		var jsFile = category + defaults.suffix_used + '.js';
+		jsFile = path.join(jsFilePath, jsFile);
+		defaults.compiled.push(jsFile);
 		var jsFileDeploy = category + defaults.suffix_used + '.deploy.js';
+		jsFileDeploy = path.join(jsFilePath, jsFileDeploy);
+
 		console.log('Exporting ' + (defaults.deploy ? '(debug + deploy)' : '(debug)')
 			+ ' category ' + category + ' as ' + jsFile
 			+ (defaults.deploy ? ' and ' + jsFileDeploy : ''));
@@ -496,7 +509,17 @@ AmberC.prototype.category_export = function() {
 AmberC.prototype.verify = function() {
 	console.log('Verifying if all .st files were compiled');
 	var self = this;
-	async_map(this.defaults.compiled, function(file, callback) {
+	// copy array
+	var compiledFiles = this.defaults.compiled.slice(0);
+	// append deploy files if necessary
+	if (true === this.defaults.deploy) {
+		this.defaults.compiled.forEach(function(file) {
+			compiledFiles.push(file.replace(/\.js/g, '.deploy.js'));
+		});
+	}
+
+	async_map(compiledFiles,
+		function(file, callback) {
 			fs.exists(file, function(exists) {
 				if (exists)
 					callback(null, null);
@@ -517,20 +540,30 @@ AmberC.prototype.verify = function() {
 AmberC.prototype.compose_js_files = function() {
 	var defaults = this.defaults;
 	var self = this;
-	if (undefined === defaults.program) {
+	var programFile = defaults.program;
+	if (undefined === programFile) {
 		self.optimize();
 		return;
 	}
-	var program_files = [];
+	if (undefined !== defaults.output_dir) {
+		programFile = path.join(defaults.output_dir, programFile);
+	}
 
+	var program_files = [];
 	if (0 !== defaults.libraries.length) {
 		console.log('Collecting libraries: ' + defaults.libraries);
 		program_files.push.apply(program_files, defaults.libraries);
 	}
 
 	if (0 !== defaults.compiled.length) {
-		console.log('Collecting compiled files: ' + defaults.compiled);
-		program_files.push.apply(program_files, defaults.compiled);
+		var compiledFiles = defaults.compiled.slice(0);
+		if (true === defaults.deploy) {
+			compiledFiles = compiledFiles.map(function(file) {
+				return file.replace(/\.js$/g, '.deploy.js');
+			});
+		}
+		console.log('Collecting compiled files: ' + compiledFiles);
+		program_files.push.apply(program_files, compiledFiles);
 	}
 
 	if (undefined !== defaults.init) {
@@ -538,9 +571,9 @@ AmberC.prototype.compose_js_files = function() {
 		program_files.push(defaults.init);
 	}
 
-	console.ambercLog('Writing program file: %s.js', defaults.program);
+	console.ambercLog('Writing program file: %s.js', programFile);
 
-	var fileStream = fs.createWriteStream(defaults.program + defaults.suffix_used + '.js');
+	var fileStream = fs.createWriteStream(programFile + defaults.suffix_used + '.js');
 	fileStream.on('error', function(error) {
 		fileStream.end();
 		console.ambercLog(error);
@@ -592,14 +625,19 @@ AmberC.prototype.optimize = function() {
 	if (defaults.closure_parts) {
 		console.log('Compiling all js files using Google closure compiler.');
 		defaults.compiled.forEach(function(file) {
-			console.log('Compiling ' + file + ' file using Google closure compiler.');
-			var minifiedName = path.basename(file, '.js') + '.min.js';
-			self.closure_compile(file, minifiedName, optimization_done.add());
+			var deployFile = file.replace(/\.js$/g, '.deploy.js');
+			console.log('Compiling ' + deployFile + ' file using Google closure compiler.');
+			var minifiedName = deployFile.replace(/\.js$/g, '.min.js');
+			self.closure_compile(deployFile, minifiedName, optimization_done.add());
 		});
 	}
 	if (defaults.closure_full && (undefined !== defaults.program)) {
-		console.log('Compiling ' + defaults.program + '.js file using Google closure compiler.');
-		self.closure_compile(defaults.program + '.js', defaults.program + '.min.js', optimization_done.add());
+		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());

+ 8 - 41
grunt/tasks/grunt-amberc.js

@@ -12,9 +12,8 @@ module.exports = function(grunt) {
          closure_jar: ''               // optional
        },
        helloWorld: {
-         src: ['HelloWorld.st'],                // REQUIRED
-         working_dir: 'projects/HelloWorld/st', // optional
-         target_dir: 'projects/HelloWorld/js',  // optional
+         src: ['projects/HelloWorld/st/HelloWorld.st'], // REQUIRED
+         output_dir: 'projects/HelloWorld/js',  // optional
          main_class: 'HelloWorld',              // optional
          output_name: 'helloWorld',            // optional
          libraries: 'Canvas',                  // optional
@@ -33,13 +32,6 @@ module.exports = function(grunt) {
     this.requiresConfig('amberc._config.amber_dir');
     this.requiresConfig(['amberc', this.target, 'src']);
 
-    // change working directory if the working_dir property is set on the target
-    var current_dir = process.cwd();
-    var working_dir = this.data.working_dir;
-    if (undefined !== working_dir) {
-      grunt.file.setBase(working_dir);
-    }
-
     // mark task as async task
     var done = this.async();
 
@@ -53,18 +45,6 @@ module.exports = function(grunt) {
     // change back to the old working directory and call the async callback once finished
     var self = this;
     compiler.main(configuration, function(){
-      if (undefined !== self.data.target_dir) {
-        var absolute_target_dir = path.join(current_dir, self.data.target_dir);
-        replaceFileSuffix_moveToTargetDir(self.data.src, absolute_target_dir);
-        // if deploy is set also copy the deploy files
-        if (self.data.deploy) {
-          var suffix = self.data.output_suffix || 'deploy';
-          suffix = '.' + suffix + '.js';
-          replaceFileSuffix_moveToTargetDir(self.data.src, absolute_target_dir, suffix);
-        }
-      }
-      // reset working directory
-      grunt.file.setBase(current_dir);
       // signal that task has finished
       done();
     });
@@ -122,25 +102,12 @@ module.exports = function(grunt) {
     if (undefined !== outputName) {
       configuration.program = outputName;
     }
+    if (undefined !== data.output_dir) {
+    	configuration.output_dir = data.output_dir;
+    }
+    if (true === data.verbose) {
+    	configuration.verbose = true;
+    }
     return configuration;
   }
-
-
-  /**
-   * Replace '.st' suffix of \p files with '.js' or with \p replace_suffix if this parameter is given.
-   * Afterwards move the files with replaced suffix to \p target_dir if the files exist.
-   */
-  function replaceFileSuffix_moveToTargetDir(files, target_dir, replace_suffix) {
-    var suffix = replace_suffix || '.js';
-    var compiledFiles = files.map(function(item) {
-      return item.replace(/.st$/g, suffix);
-    });
-
-    compiledFiles.forEach(function(file) {
-      if (fs.existsSync(file)) {
-        console.log('Move: ' + file + ' -> ' + path.join(target_dir, file));
-        fs.renameSync(file, path.join(target_dir, file));
-      }
-    });
-  }
 };