aboutsummaryrefslogtreecommitdiff
path: root/src/parser.js
diff options
context:
space:
mode:
authoralon@honor <none@none>2010-09-05 13:46:37 -0700
committeralon@honor <none@none>2010-09-05 13:46:37 -0700
commit9b1f6f9cf2b769f32178bebf46dc5390f82355c9 (patch)
treedf0f62a58523622ccb8be98d04881b0886d0c22f /src/parser.js
parent545cad31eb074cc5040bb8a81ea3d9b7814587de (diff)
optimize FunctionReconstructor
Diffstat (limited to 'src/parser.js')
-rw-r--r--src/parser.js171
1 files changed, 89 insertions, 82 deletions
diff --git a/src/parser.js b/src/parser.js
index c231e538..0a8c063c 100644
--- a/src/parser.js
+++ b/src/parser.js
@@ -1968,100 +1968,107 @@ function JSify(data) {
},
});
// function reconstructor & post-JS optimizer
- // TODO: optimize to prevent multiple loops, one per function. See processPairs
substrate.addZyme('FunctionReconstructor', {
select: function(items) {
- var func = items.filter(function(item) { return item.intertype == 'function' && item.passes.splitted })[0];
- if (!func) return [];
- var lines = items.filter(function(item) { return item.JS && item.func === func.ident });
- if (lines.length === 0) return [];
- return [func].concat(lines);
+ var funcs = items.filter(function(item) { return item.intertype == 'function' && item.passes.splitted });
+ return funcs.map(function(func) {
+ var lines = items.filter(function(item) { return item.JS && item.func === func.ident });
+ if (lines.length === 0) return [];
+ return [func].concat(lines);
+ }).reduce(concatenator, []);
},
- process: function(items) {
- var func = items[0];
- var lines = items.slice(1);
-
- lines.forEach(function(line) {
- delete line.funcData; // clean up
-
- var label = func.labels.filter(function(label) { return label.ident == line.parentLabel })[0];
- label.lines = label.lines.map(function(line2) {
- return (line2.lineNum !== line.lineNum) ? line2 : line;
+ process: function(allItems) {
+ var ret = [];
+ for (var i = 0; i < allItems.length;) {
+ var func = allItems[i];
+ var j = i+1;
+ while (j < allItems.length && allItems[j].intertype != 'function') j++;
+ var lines = allItems.slice(i+1, j);
+ i = j;
+
+ lines.forEach(function(line) {
+ delete line.funcData; // clean up
+
+ var label = func.labels.filter(function(label) { return label.ident == line.parentLabel })[0];
+ label.lines = label.lines.map(function(line2) {
+ return (line2.lineNum !== line.lineNum) ? line2 : line;
+ });
});
- });
- func.splitItems -= lines.length;
- if (func.splitItems === 0) {
- postJSOptimize(func);
+ func.splitItems -= lines.length;
+ if (func.splitItems === 0) {
+ postJSOptimize(func);
- // Final recombination
- //print('zz params::::: ' + JSON.stringify(func.params));
- //print('zz params::::: ' + JSON.stringify(parseParamTokens(func.params.item[0].tokens)));
+ // Final recombination
+ //print('zz params::::: ' + JSON.stringify(func.params));
+ //print('zz params::::: ' + JSON.stringify(parseParamTokens(func.params.item[0].tokens)));
- var hasVarArgs = false;
- var params = parseParamTokens(func.params.item[0].tokens).map(function(param) {
- if (param.intertype == 'varargs') {
- hasVarArgs = true;
- return null;
- }
- return toNiceIdent(param.ident);
- }).filter(function(param) { return param != null }).join(', ');
-
- func.JS = '\nfunction ' + func.ident + '(' + params + ') {\n';
- if (LINEDEBUG) func.JS += " print(INDENT + 'Entering: " + func.ident + "'); INDENT += ' ';\n";
-
- // Walk function blocks and generate JS
- function walkBlock(block, indent) {
- if (!block) return '';
- //print('block: ' + dump(block) + ' ::: ' + dump(getLabelIds(block.labels)));
- function getLabelLines(label, indent) {
- //print('LABELLINES HAS INDENT ' + indent.length + ' ::' + label.lines[0].JS);
- return label.lines.map(function(line) { return indent + line.JS + (line.comment ? ' // ' + line.comment : '') }).join('\n');
- }
- var ret = '';
- if (block.type == 'emulated' || block.type == 'simple') {
- //print('BLOCK HAS INDENT ' + indent.length);
- //print('block has: ' + block.entry + ' :: ' + getLabelIds(block.labels));
- if (block.labels.length > 1) {
- ret += indent + 'var __label__ = ' + getLabelId(block.entry) + '; /* ' + block.entry + ' */\n';
- ret += indent + 'while(1) switch(__label__) {\n';
- ret += block.labels.map(function(label) {
- return indent + ' case ' + getLabelId(label.ident) + ':\n' + getLabelLines(label, indent + ' ');
- }).join('\n');
- ret += '\n' + indent + '}';
+ var hasVarArgs = false;
+ var params = parseParamTokens(func.params.item[0].tokens).map(function(param) {
+ if (param.intertype == 'varargs') {
+ hasVarArgs = true;
+ return null;
+ }
+ return toNiceIdent(param.ident);
+ }).filter(function(param) { return param != null }).join(', ');
+
+ func.JS = '\nfunction ' + func.ident + '(' + params + ') {\n';
+ if (LINEDEBUG) func.JS += " print(INDENT + 'Entering: " + func.ident + "'); INDENT += ' ';\n";
+
+ // Walk function blocks and generate JS
+ function walkBlock(block, indent) {
+ if (!block) return '';
+ //print('block: ' + dump(block) + ' ::: ' + dump(getLabelIds(block.labels)));
+ function getLabelLines(label, indent) {
+ //print('LABELLINES HAS INDENT ' + indent.length + ' ::' + label.lines[0].JS);
+ return label.lines.map(function(line) { return indent + line.JS + (line.comment ? ' // ' + line.comment : '') }).join('\n');
+ }
+ var ret = '';
+ if (block.type == 'emulated' || block.type == 'simple') {
+ //print('BLOCK HAS INDENT ' + indent.length);
+ //print('block has: ' + block.entry + ' :: ' + getLabelIds(block.labels));
+ if (block.labels.length > 1) {
+ ret += indent + 'var __label__ = ' + getLabelId(block.entry) + '; /* ' + block.entry + ' */\n';
+ ret += indent + 'while(1) switch(__label__) {\n';
+ ret += block.labels.map(function(label) {
+ return indent + ' case ' + getLabelId(label.ident) + ':\n' + getLabelLines(label, indent + ' ');
+ }).join('\n');
+ ret += '\n' + indent + '}';
+ } else {
+ ret += getLabelLines(block.labels[0], indent);
+ }
+ ret += '\n';
+ } else if (block.type == 'loop') {
+ // if (mustGetTo(first.outLabels[0], [first.ident, first.outLabels[1]])) { /* left branch must return here, or go to right branch */
+ ret += indent + block.entry + ': while(1) {\n';
+ ret += walkBlock(block.inc, indent + ' ');
+ ret += walkBlock(block.rest, indent + ' ');
+ ret += indent + '}\n';
+ } else if (block.type == 'breakingif') {
+ ret += walkBlock(block.check, indent);
+ ret += indent + block.entry + ': do { if (' + block.ifVar + ') {\n';
+ ret += walkBlock(block.ifTrue, indent + ' ');
+ ret += indent + '} } while(0);\n';
+ } else if (block.type == 'if') {
+ ret += walkBlock(block.check, indent);
+ ret += indent + 'if (' + block.ifVar + ') {\n';
+ ret += walkBlock(block.ifTrue, indent + ' ');
+ ret += indent + '}\n';
} else {
- ret += getLabelLines(block.labels[0], indent);
+ ret = 'XXXXXXXXX!';
}
- ret += '\n';
- } else if (block.type == 'loop') {
-// if (mustGetTo(first.outLabels[0], [first.ident, first.outLabels[1]])) { /* left branch must return here, or go to right branch */
- ret += indent + block.entry + ': while(1) {\n';
- ret += walkBlock(block.inc, indent + ' ');
- ret += walkBlock(block.rest, indent + ' ');
- ret += indent + '}\n';
- } else if (block.type == 'breakingif') {
- ret += walkBlock(block.check, indent);
- ret += indent + block.entry + ': do { if (' + block.ifVar + ') {\n';
- ret += walkBlock(block.ifTrue, indent + ' ');
- ret += indent + '} } while(0);\n';
- } else if (block.type == 'if') {
- ret += walkBlock(block.check, indent);
- ret += indent + 'if (' + block.ifVar + ') {\n';
- ret += walkBlock(block.ifTrue, indent + ' ');
- ret += indent + '}\n';
- } else {
- ret = 'XXXXXXXXX!';
+ return ret + walkBlock(block.next, indent);
}
- return ret + walkBlock(block.next, indent);
+ func.JS += walkBlock(func.block, ' ');
+ // Finalize function
+ if (LINEDEBUG) func.JS += " INDENT = INDENT.substr(0, INDENT.length-2);\n";
+ func.JS += '}\n';
+ func.__result__ = true;
}
- func.JS += walkBlock(func.block, ' ');
- // Finalize function
- if (LINEDEBUG) func.JS += " INDENT = INDENT.substr(0, INDENT.length-2);\n";
- func.JS += '}\n';
- func.__result__ = true;
- }
- return [func];
+ ret.push(func);
+ }
+ return ret;
},
});
function postJSOptimize(func) {