aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/analyzer.js55
1 files changed, 26 insertions, 29 deletions
diff --git a/src/analyzer.js b/src/analyzer.js
index b5f03167..33238e8a 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -907,14 +907,10 @@ function analyzer(data) {
return ret;
}
- if (canReturn) return makeLoop();
+ if (entries.length === 1 && canReturn) return makeLoop();
// === handle multiple branches from the entry with a 'multiple' ===
//
- // We cannot loop back to the entries, but aside from that we know nothing. We
- // try to create as much structure as possible, leaving subblocks to be |emulated|
- // if we can't do any better.
-
// For each entry, try to 'build it out' as much as possible. Add labels, until
// * hit a post label
// * hit a label reachable by another actual entry
@@ -957,33 +953,34 @@ function analyzer(data) {
dprint('relooping', ' Considering multiple, canHandle: ' + getLabelIds(handlingNow));
- if (handlingNow.length == 0) {
- // Spaghetti - cannot even find a single label to do before the rest. What a mess.
- throw "Spaghetti encountered in relooping.";
- }
-
- // This is a 'multiple'
+ if (handlingNow.length > 0) {
+ // This is a 'multiple'
- var actualEntries = getLabelIds(actualEntryLabels);
- dprint('relooping', ' Creating multiple, with entries: ' + actualEntries + ', post entries: ' + dump(postEntryLabels));
- actualEntryLabels.forEach(function(actualEntryLabel) {
- dprint('relooping', ' creating sub-block in multiple for ' + actualEntryLabel.ident + ' : ' + getLabelIds(actualEntryLabel.blockChildren) + ' ::: ' + actualEntryLabel.blockChildren.length);
+ var actualEntries = getLabelIds(actualEntryLabels);
+ dprint('relooping', ' Creating multiple, with entries: ' + actualEntries + ', post entries: ' + dump(postEntryLabels));
+ actualEntryLabels.forEach(function(actualEntryLabel) {
+ dprint('relooping', ' creating sub-block in multiple for ' + actualEntryLabel.ident + ' : ' + getLabelIds(actualEntryLabel.blockChildren) + ' ::: ' + actualEntryLabel.blockChildren.length);
- keys(postEntryLabels).forEach(function(post) {
- replaceLabelLabels(actualEntryLabel.blockChildren, set(post), 'BREAK|' + blockId);
+ keys(postEntryLabels).forEach(function(post) {
+ replaceLabelLabels(actualEntryLabel.blockChildren, set(post), 'BREAK|' + blockId);
+ });
+ // Create child block
+ actualEntryLabel.block = makeBlock(actualEntryLabel.blockChildren, [actualEntryLabel.blockChildren[0].ident], labelsDict);
});
- // Create child block
- actualEntryLabel.block = makeBlock(actualEntryLabel.blockChildren, [actualEntryLabel.blockChildren[0].ident], labelsDict);
- });
- return {
- type: 'multiple',
- id: blockId,
- needBlockId: true,
- entries: actualEntries,
- entryLabels: actualEntryLabels,
- labels: handlingNow,
- next: makeBlock(labels.filter(function(label) { return handlingNow.indexOf(label) == -1 }), keys(postEntryLabels), labelsDict)
- };
+ return {
+ type: 'multiple',
+ id: blockId,
+ needBlockId: true,
+ entries: actualEntries,
+ entryLabels: actualEntryLabels,
+ labels: handlingNow,
+ next: makeBlock(labels.filter(function(label) { return handlingNow.indexOf(label) == -1 }), keys(postEntryLabels), labelsDict)
+ };
+ }
+
+ assert(canReturn, 'If not a multiple, must be able to create a loop');
+
+ return makeLoop();
}
// TODO: each of these can be run in parallel