diff options
author | alon@honor <none@none> | 2010-10-04 20:27:31 -0700 |
---|---|---|
committer | alon@honor <none@none> | 2010-10-04 20:27:31 -0700 |
commit | f504a15e271ca84c768f93bebb12978fca550ce7 (patch) | |
tree | 9f7abd38ae7cfc05ffce077bd8a22542e047a93b /src/jsifier.js | |
parent | a20e4b9f8704fd5e18e2ccc4e23dac98ec1563d0 (diff) |
initial working version of 'multiple' block in relooper
Diffstat (limited to 'src/jsifier.js')
-rw-r--r-- | src/jsifier.js | 39 |
1 files changed, 30 insertions, 9 deletions
diff --git a/src/jsifier.js b/src/jsifier.js index a76db445..4aee5a7c 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -254,10 +254,13 @@ function JSify(data) { func.JS += ' __lastLabel__ = null;\n'; } + var usedLabels = {}; // We can get a loop and inside it a multiple, which will try to use the same + // label for their loops (until we remove loops from multiples! TODO). So, just + // do not use the label twice, that will prevent that // Walk function blocks and generate JS function walkBlock(block, indent) { if (!block) return ''; - block.entry = block.entries[0]; + block.entry = block.entries[0]; // convention: first entry is the representative dprint('relooping', 'walking block: ' + block.type + ',' + block.entries + ' : ' + block.labels.length); function getLabelLines(label, indent) { if (!label) return ''; @@ -295,6 +298,7 @@ function JSify(data) { } ret += '\n'; } else if (block.type == 'reloop') { + usedLabels[block.entry] = 1; ret += indent + block.entry + ': while(1) { // ' + block.entry + '\n'; ret += walkBlock(block.inner, indent + ' '); ret += indent + '}\n'; @@ -309,8 +313,20 @@ function JSify(data) { ret += indent + 'if (' + block.ifVar + ') {\n'; ret += walkBlock(block.ifTrue, indent + ' '); ret += indent + '}\n'; + } else if (block.type == 'multiple') { + // TODO: Remove the loop here + var first = true; + ret += indent + ((block.entry in usedLabels) ? '' : (block.entry+':')) + ' do { \n'; + block.entryLabels.forEach(function(entryLabel) { + ret += indent + (first ? '' : ' else ') + ' if (__label__ == ' + getLabelId(entryLabel.ident) + ') {\n'; + ret += walkBlock(entryLabel.block, indent + ' '); + ret += indent + ' }\n'; + first = false; + }); + ret += indent + ' else { throw "Bad multiple branching: " + __label__ + " : " + (new Error().stack); }\n'; + ret += indent + '} while(0);\n'; } else { - ret = 'XXXXXXXXX!'; + throw "Walked into an invalid block type: " + block.type; } return ret + walkBlock(block.next, indent); } @@ -428,17 +444,22 @@ function JSify(data) { return LABEL_IDs[label] = LABEL_ID_COUNTER ++; } + // TODO: remove 'oldLabel', store that inside the label: BXXX|Labeltobreak|Labeltogetto function makeBranch(label, oldLabel) { if (label[0] == 'B') { + var labelSetting = '__label__ = ' + getLabelId(oldLabel) + '; /* ' + cleanLabel(oldLabel) + ' */ '; // TODO: optimize away + var trueLabel = label.substr(5); + assert(oldLabel); if (label[1] == 'R') { - assert(oldLabel); - return '__label__ = ' + getLabelId(oldLabel) + '; /* ' + cleanLabel(oldLabel) + ' */ ' + // TODO: optimize away - 'break ' + label.substr(5) + ';'; - } else if (label[1] == 'C') { - return '__label__ = ' + getLabelId(oldLabel) + '; /* ' + cleanLabel(oldLabel) + ' */ ' + // TODO: optimize away - 'continue ' + label.substr(5) + ';'; - } else { // NOPP + return labelSetting + 'break ' + trueLabel + ';'; + } else if (label[1] == 'C') { // CONT + return labelSetting + 'continue ' + trueLabel + ';'; + } else if (label[1] == 'N') { // NOPP return ';'; // Returning no text might confuse this parser + } else if (label[1] == 'J') { // JSET + return labelSetting; + } else { + throw 'Invalid B-op in branch: ' + trueLabel + ',' + oldLabel; } } else { return '__label__ = ' + getLabelId(label) + '; /* ' + cleanLabel(label) + ' */ break;'; |