// Convert analyzed data to javascript. Everything has already been calculated
// before this stage, which just does the final conversion to JavaScript.
// Main function
function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
var mainPass = !functionsOnly;
// Add additional necessary items for the main pass
if (mainPass) {
LibraryManager.load();
var libFuncsToInclude;
if (INCLUDE_FULL_LIBRARY) {
assert(!BUILD_AS_SHARED_LIB, 'Cannot have both INCLUDE_FULL_LIBRARY and BUILD_AS_SHARED_LIB set.')
libFuncsToInclude = [];
for (var key in LibraryManager.library) {
if (!key.match(/__(deps|postset)$/)) {
libFuncsToInclude.push(key);
}
}
} else {
libFuncsToInclude = ['memset', 'malloc', 'free'];
}
libFuncsToInclude.forEach(function(ident) {
data.functionStubs.push({
intertype: 'functionStub',
ident: '_' + ident
});
});
}
// Does simple 'macro' substitution, using Django-like syntax,
// {{{ code }}} will be replaced with |eval(code)|.
function processMacros(text) {
return text.replace(/{{{[^}]+}}}/g, function(str) {
str = str.substr(3, str.length-6);
return eval(str).toString();
});
}
substrate = new Substrate('JSifyer');
var GLOBAL_VARIABLES = !mainPass ? givenGlobalVariables : data.globalVariables;
Functions.currFunctions = !mainPass ? givenFunctions.currFunctions : {};
Functions.currExternalFunctions = !mainPass ? givenFunctions.currExternalFunctions : {};
// Now that first-pass analysis has completed (so we have basic types, etc.), we can get around to handling unparsedFunctions
(!mainPass ? data.functions : data.unparsedFunctions.concat(data.functions)).forEach(function(func) {
// Save just what we need, to save memory
Functions.currFunctions[func.ident] = {
hasVarArgs: func.hasVarArgs,
numParams: func.params.length,
labelIds: func.labelIds // TODO: We need this for globals, but perhaps we can calculate them early and free this
};
});
data.functionStubs.forEach(function(func) {
// Don't overwrite stubs that have more info.
if (!Functions.currExternalFunctions.hasOwnProperty(func.ident) ||
!Functions.currExternalFunctions[func.ident].numParams === undefined) {
Functions.currExternalFunctions[func.ident] = {
hasVarArgs: func.hasVarArgs,
numParams: func.params && func.params.length
};
}
});
for (var i = 0; i < data.unparsedFunctions.length; i++) {
var func = data.unparsedFunctions[i];
dprint('unparsedFunctions', '====================\n// Processing |' + func.ident + '|, ' + i + '/' + data.unparsedFunctions.length);
//var t = Date.now();
func.JS = JSify(analyzer(intertyper(func.lines, true, func.lineNum-1)), true, Functions, GLOBAL_VARIABLES);
//t = (Date.now()-t)/1000;
//dprint('unparsedFunctions', 'unparsedFunction took ' + t + ' seconds.');
delete func.lines; // clean up memory as much as possible
}
if (data.unparsedFunctions.length > 0) {
// We are now doing the final JS generation
dprint('unparsedFunctions', '== Completed unparsedFunctions ==\n');
// Save some memory, before the final heavy lifting
//Functions.currFunctions = null;
//Functions.currExternalFunctions = null;
//Debugging.clear();
}
// Actors
// type
substrate.addActor('Type', {
processItem: function(item) {
var type = Types.types[item.name_];
var niceName = toNiceIdent(item.name_);
// We might export all of Types.types, cleaner that way, but do not want slowdowns in accessing flatteners
item.JS = 'var ' + niceName + '___SIZE = ' + Types.types[item.name_].flatSize + '; // ' + item.name_ + '\n';
if (type.needsFlattening && !type.flatFactor) {
item.JS += 'var ' + niceName + '___FLATTENER = ' + JSON.stringify(Types.types[item.name_].flatIndexes) + ';';
}
return [item];
}
});
function makeEmptyStruct(type) {
var ret = [];
var typeData = Types.types[type];
assertTrue(typeData);
for (var i = 0; i < typeData.flatSize; i++) {
ret.push(0);
}
return ret;
}
function alignStruct(values, type) {
var typeData = Types.types[type];
assertTrue(typeData);
var ret = [];
var i = 0,