Skip to content

Commit

Permalink
now output module name in minify/assembly/compile errors. Also compil…
Browse files Browse the repository at this point in the history
…e inline C and JS in modules.
  • Loading branch information
gfwilliams committed Jun 21, 2018
1 parent 59fda8f commit 16c3ab8
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 57 deletions.
10 changes: 5 additions & 5 deletions core/modules.js
Expand Up @@ -123,19 +123,19 @@
}
}

var loadProcessedModule = function (moduleCode) {
var loadProcessedModule = function (module) {
// add the module to the beginning of our array
if (Espruino.Config.MODULE_AS_FUNCTION)
loadedModuleData.unshift("Modules.addCached(" + JSON.stringify(modName) + ",function(){" + moduleCode + "});");
loadedModuleData.unshift("Modules.addCached(" + JSON.stringify(module.name) + ",function(){" + module.code + "});");
else
loadedModuleData.unshift("Modules.addCached(" + JSON.stringify(modName) + "," + JSON.stringify(moduleCode) + ");");
loadedModuleData.unshift("Modules.addCached(" + JSON.stringify(module.name) + "," + JSON.stringify(module.code) + ");");
// if we needed to load something, wait until we have all promises complete before resolving our promise!
Promise.all(newPromises).then(function(){ resolve(); });
}
if (alreadyMinified)
loadProcessedModule(data);
loadProcessedModule({code:data,name:modName});
else
Espruino.callProcessor("transformModuleForEspruino", data, loadProcessedModule);
Espruino.callProcessor("transformModuleForEspruino", {code:data,name:modName}, loadProcessedModule);
}

/** Given a module name (which could be a URL), try and find it. Return
Expand Down
23 changes: 13 additions & 10 deletions plugins/assembler.js
Expand Up @@ -374,37 +374,40 @@
function init() {
// When code is sent to Espruino, search it for bits of assembler and then assemble them
Espruino.addProcessor("transformForEspruino", function(code, callback) {
findASMBlocks(code, callback);
findASMBlocks(code, "", callback);
});
// When a module is sent to Espruino...
Espruino.addProcessor("transformModuleForEspruino", function(code, callback) {
findASMBlocks(code, callback);
Espruino.addProcessor("transformModuleForEspruino", function(module, callback) {
findASMBlocks(module.code, " in "+module.name, function(code) {
module.code = code;
callback(module);
});
});
}

function assembleBlock(asmLines) {
function assembleBlock(asmLines, description) {
var machineCode = [];
try {
assemble(asmLines, function(word) { machineCode.push("0x"+word.toString(16)); });
} catch (err) {
console.log("Assembler failed: "+err);
Espruino.Core.Notifications.error("Assembler failed: "+err);
console.log("Assembler failed: "+err+description);
Espruino.Core.Notifications.error("Assembler failed: "+err+description);
return undefined;
}

return machineCode;
}

/* Finds instances of 'E.asm' and replaces them */
function findASMBlocks(code, callback){
function findASMBlocks(code, description, callback){

function match(str, type) {
if (str!==undefined && tok.str!=str) {
Espruino.Core.Notifications.error("Expecting '"+str+"' but got '"+tok.str+"'. Should have E.asm('arg spec', 'asmline1', ..., 'asmline2'");
Espruino.Core.Notifications.error("Expecting '"+str+"' but got '"+tok.str+description+"'. Should have E.asm('arg spec', 'asmline1', ..., 'asmline2'");
return false;
}
if (type!==undefined && tok.type!=type) {
Espruino.Core.Notifications.error("Expecting a "+type+" but got "+tok.type+". Should have E.asm('arg spec', 'asmline1', ..., 'asmline2'");
Espruino.Core.Notifications.error("Expecting a "+type+" but got "+tok.type+description+". Should have E.asm('arg spec', 'asmline1', ..., 'asmline2'");
return false;
}
tok = lex.next();
Expand Down Expand Up @@ -444,7 +447,7 @@
if (!match(")",undefined)) return;
var endIndex = tok.endIdx;

var machineCode = assembleBlock(asmLines);
var machineCode = assembleBlock(asmLines, description);
//console.log(machineCode);
if (machineCode===undefined) return; // There was an error - just leave and don't try to flash
var raw = "";
Expand Down
25 changes: 14 additions & 11 deletions plugins/compiler.js
Expand Up @@ -36,22 +36,24 @@
if (Espruino.Config.COMPILATION_URL == "http://www.espruino.com:32766")
Espruino.Config.COMPILATION_URL = "https://www.espruino.com/service/compiler";

// When code is sent to Espruino, search it for modules and add extra code required to load them
// When code is sent to Espruino, search it for compiled js/inline c
Espruino.addProcessor("transformForEspruino", function(code, callback) {
compileCode(code, callback);
compileCode(code, "", callback);
});
// When a module is sent to Espruino...
Espruino.addProcessor("transformModuleForEspruino", function(module, callback) {
compileCode(module.code, " in "+module.name, function(code) {
module.code = code;
callback(module);
});
});
}

function compileCode(code, callback) {
function compileCode(code, description, callback) {
if (!Espruino.Config.COMPILATION)
return callback(code);

var board = Espruino.Core.Env.getBoardData();
if (board == undefined) {
Espruino.Core.Notifications.error("Current board not known - please connect to the Espruino board first");
return callback(code);
}

var tasks = 0;
try {
var ast = acorn.parse(code, { ecmaVersion : 6 });
Expand Down Expand Up @@ -92,7 +94,8 @@
}
});
if (tasks.length) {
if (typeof board.EXPORTS != "object" &&
if (!board ||
typeof board.EXPORTS != "object" &&
typeof board.EXPTR != "number" ) {
Espruino.Core.Notifications.error("Compiler not active as no process.env.EXPORTS/EXPTR available.<br/>Is your board supported and firmware up to date?");
return callback(code);
Expand Down Expand Up @@ -137,15 +140,15 @@
if (taskCount==0)
callback(code);
}).fail(function() {
Espruino.Core.Notifications.error( "Error contacting server. Unable to compile code right now." );
Espruino.Core.Notifications.error("Error contacting server. Unable to compile code"+description+" right now.");
taskCount--;
if (taskCount==0) callback(code);
});
});

} catch (err) {
console.log(err);
Espruino.Core.Notifications.error("Error parsing JavaScript, but uploading anyway.<br/>"+err.toString());
Espruino.Core.Notifications.error("Error parsing JavaScript"+description+", but uploading anyway.<br/>"+err.toString());
}
if (tasks==0)
callback(code);
Expand Down
65 changes: 34 additions & 31 deletions plugins/minify.js
Expand Up @@ -4,24 +4,24 @@
This Source Code is subject to the terms of the Mozilla Public
License, v2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
------------------------------------------------------------------
Automatically minify code before it is sent to Espruino
------------------------------------------------------------------
**/
"use strict";
(function(){

var minifyUrl = "https://closure-compiler.appspot.com/compile";
var minifyCache = [];

function init() {
Espruino.Core.Config.addSection("Minification", {
sortOrder:600,
description: "Minification takes your JavaScript code and makes it smaller by removing comments and whitespace. "+
"It can make your code execute faster and will save memory, but it will also make it harder to debug.\n"+
"Esprima is a minifier built in to the Web IDE, so it can be used without an internet connection. "+
"The Closure Compiler is an online service offered by Google. It produces more efficient code, but you need an internet connection to use it."
"The Closure Compiler is an online service offered by Google. It produces more efficient code, but you need an internet connection to use it."
});

Espruino.Core.Config.add("MINIFICATION_LEVEL", {
Expand All @@ -47,7 +47,7 @@
defaultValue : "ESPRIMA"
});


Espruino.Core.Config.add("MINIFICATION_Mangle",{
section : "Minification",
name : "Esprima: Mangle",
Expand All @@ -60,43 +60,46 @@
name : "Esprima: Unreachable branches",
description : "Remove unreachable branches",
type : "boolean",
defaultValue : true
defaultValue : true
});
Espruino.Core.Config.add("MINIFICATION_Unused",{
section : "Minification",
name : "Esprima: Unused variables",
description : "Remove unused variables",
type : "boolean",
defaultValue : true
defaultValue : true
});
Espruino.Core.Config.add("MINIFICATION_Literal",{
section : "Minification",
name : "Esprima: Fold constants",
description : "Fold (literal) constants",
type : "boolean",
defaultValue : true
defaultValue : true
});
Espruino.Core.Config.add("MINIFICATION_DeadCode",{
section : "Minification",
name : "Esprima: Dead Code",
description : "Eliminate dead code",
type : "boolean",
defaultValue : true
defaultValue : true
});

// When code is sent to Espruino, search it for modules and add extra code required to load them
// When code is sent to Espruino, search it for modules and add extra code required to load them
Espruino.addProcessor("transformForEspruino", function(code, callback) {
minify(code, callback, Espruino.Config.MINIFICATION_LEVEL, false);
minify(code, callback, Espruino.Config.MINIFICATION_LEVEL, false, "");
});
// When code is sent to Espruino, search it for modules and add extra code required to load them
Espruino.addProcessor("transformModuleForEspruino", function(code, callback) {
minify(code, callback, Espruino.Config.MODULE_MINIFICATION_LEVEL, true);
// When code is sent to Espruino, search it for modules and add extra code required to load them
Espruino.addProcessor("transformModuleForEspruino", function(module, callback) {
minify(module.code, function(code) {
module.code = code;
callback(module);
}, Espruino.Config.MODULE_MINIFICATION_LEVEL, true, " in "+module.name);
});
}


// Use the 'offline' Esprima compile
function minifyCodeEsprima(code,callback) {
function minifyCodeEsprima(code,callback,description) {
if ((typeof esprima == "undefined") ||
(typeof esmangle == "undefined") ||
(typeof escodegen == "undefined")) {
Expand All @@ -120,13 +123,13 @@
code = escodegen.generate(syntax, option);
after = code.length;
if (before > after) {
Espruino.Core.Notifications.info('No error. Minified ' + before + ' bytes to ' + after + ' bytes.');
Espruino.Core.Notifications.info('No errors'+description+'. Minified ' + before + ' bytes to ' + after + ' bytes.');
} else {
Espruino.Core.Notifications.info('Can not minify further, code is already optimized.');
Espruino.Core.Notifications.info('Can not minify further'+description+', code is already optimized.');
}
callback(code);
} catch (e) {
Espruino.Core.Notifications.error(e.toString());
Espruino.Core.Notifications.error(e.toString()+description);
console.error(e.stack);
callback(code);
} finally { }
Expand Down Expand Up @@ -187,11 +190,11 @@
}

// Use the 'online' Closure compiler
function minifyCodeGoogle(code, callback, minificationLevel){
function minifyCodeGoogle(code, callback, minificationLevel, description){
for (var i in minifyCache) {
var item = minifyCache[i];
if (item.code==code && item.level==minificationLevel) {
console.log("Found code in minification cache - using that");
console.log("Found code in minification cache - using that"+description);
// move to front of cache
minifyCache.splice(i,1); // remove old
minifyCache.push(item); // add at front
Expand All @@ -202,19 +205,19 @@
}
closureCompilerGoogle(code, minificationLevel, 'compiled_code', function(minified) {
if (minified.trim()!="") {
Espruino.Core.Notifications.info('No error. Minifying ' + code.length + ' bytes to ' + minified.length + ' bytes.');
Espruino.Core.Notifications.info('No errors'+description+'. Minifying ' + code.length + ' bytes to ' + minified.length + ' bytes');
if (minifyCache.length>100)
minifyCache = minifyCache.slice(-100);
minifyCache.push({ level : minificationLevel, code : code, minified : minified });
callback(minified);
} else {
Espruino.Core.Notifications.warning("Errors while minifying - sending unminified code.");
Espruino.Core.Notifications.warning("Errors while minifying"+description+" - sending unminified code.");
callback(code);
// get errors...
closureCompilerGoogle(code, minificationLevel, 'errors',function(errors) {
errors.split("\n").forEach(function (err) {
if (err.trim()!="")
Espruino.Core.Notifications.error(err.trim());
Espruino.Core.Notifications.error(err.trim()+description);
});
});
}
Expand All @@ -229,12 +232,12 @@
js_code: code,
language : "ECMASCRIPT6", // so no need to mess with binary numbers now. \o/
language_out : "ECMASCRIPT5" // ES6 output uses some now features now that Espruino doesn't like
});
$.post(minifyUrl, minifyObj, function(minifiedCode) {
code = minifiedCode;
});
$.post(minifyUrl, minifyObj, function(minifiedCode) {
code = minifiedCode;
},"text")
.error(function() {
Espruino.Core.Notifications.error("HTTP error while minifying.");
.error(function() {
Espruino.Core.Notifications.error("HTTP error while minifying");
})
.complete(function() {
// ensure we call the callback even if minification failes
Expand All @@ -243,7 +246,7 @@
}
}

function minify(code, callback, level, isModule) {
function minify(code, callback, level, isModule, description) {
var minifyCode = code;
var minifyCallback = callback;
if (isModule) {
Expand All @@ -260,8 +263,8 @@
switch(level){
case "WHITESPACE_ONLY":
case "SIMPLE_OPTIMIZATIONS":
case "ADVANCED_OPTIMIZATIONS": minifyCodeGoogle(code, callback, level); break;
case "ESPRIMA": minifyCodeEsprima(code, callback); break;
case "ADVANCED_OPTIMIZATIONS": minifyCodeGoogle(code, callback, level, description); break;
case "ESPRIMA": minifyCodeEsprima(code, callback, description); break;
default: callback(code); break;
}
}
Expand Down

0 comments on commit 16c3ab8

Please sign in to comment.