added repeat pseudocode method

repeat from startLabel to finishLabel
(logic is inside PseudocodeImpl)
This commit is contained in:
Svetlana Isakova
2012-12-11 18:29:15 +04:00
parent 93327a3e31
commit bd31f36836
5 changed files with 115 additions and 9 deletions
@@ -88,4 +88,6 @@ public interface JetControlFlowBuilder {
// Other
void unsupported(JetElement element);
void repeatPseudocode(@NotNull Label startLabel, @NotNull Label finishLabel);
}
@@ -222,4 +222,10 @@ public class JetControlFlowBuilderAdapter implements JetControlFlowBuilder {
assert builder != null;
builder.declare(property);
}
@Override
public void repeatPseudocode(@NotNull Label startLabel, @NotNull Label finishLabel) {
assert builder != null;
builder.repeatPseudocode(startLabel, finishLabel);
}
}
@@ -345,11 +345,38 @@ public class JetControlFlowProcessor {
}
builder.bindLabel(resultLabel);
}
private class FinallyBlockGenerator {
private final JetFinallySection finallyBlock;
private Label startFinally = null;
private Label finishFinally = null;
private FinallyBlockGenerator(JetFinallySection block) {
finallyBlock = block;
}
public void generate() {
JetBlockExpression finalExpression = finallyBlock.getFinalExpression();
if (finalExpression == null) return;
if (startFinally != null) {
assert finishFinally != null;
builder.repeatPseudocode(startFinally, finishFinally);
return;
}
startFinally = builder.createUnboundLabel("start finally");
builder.bindLabel(startFinally);
value(finalExpression, inCondition);
finishFinally = builder.createUnboundLabel("finish finally");
builder.bindLabel(finishFinally);
}
}
@Override
public void visitTryExpression(JetTryExpression expression) {
builder.read(expression);
final JetFinallySection finallyBlock = expression.getFinallyBlock();
final FinallyBlockGenerator finallyBlockGenerator = new FinallyBlockGenerator(finallyBlock);
if (finallyBlock != null) {
builder.enterTryFinally(new GenerationTrigger() {
private boolean working = false;
@@ -359,7 +386,7 @@ public class JetControlFlowProcessor {
// This checks are needed for the case of having e.g. return inside finally: 'try {return} finally{return}'
if (working) return;
working = true;
value(finallyBlock.getFinalExpression(), inCondition);
finallyBlockGenerator.generate();
working = false;
}
});
@@ -425,11 +452,11 @@ public class JetControlFlowProcessor {
Label skipFinallyToErrorBlock = builder.createUnboundLabel("skipFinallyToErrorBlock");
builder.jump(skipFinallyToErrorBlock);
builder.bindLabel(onExceptionToFinallyBlock);
value(finallyBlock.getFinalExpression(), inCondition);
finallyBlockGenerator.generate();
builder.jumpToError();
builder.bindLabel(skipFinallyToErrorBlock);
value(finallyBlock.getFinalExpression(), inCondition);
finallyBlockGenerator.generate();
}
builder.stopAllowDead(allowDeadLabels);
}
@@ -328,6 +328,11 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
public void unsupported(JetElement element) {
add(new UnsupportedElementInstruction(element));
}
@Override
public void repeatPseudocode(@NotNull Label startLabel, @NotNull Label finishLabel) {
pseudocode.repeatPart(startLabel, finishLabel);
}
}
public static class TryFinallyBlockInfo extends BlockInfo {
@@ -16,9 +16,8 @@
package org.jetbrains.jet.lang.cfg.pseudocode;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.collect.*;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.cfg.Label;
@@ -79,6 +78,9 @@ public class PseudocodeImpl implements Pseudocode {
return mutableInstructionList.get(targetInstructionIndex);
}
public Label copy() {
return new PseudocodeLabel("copy " + name, allowDead);
}
}
private final List<Instruction> mutableInstructionList = new ArrayList<Instruction>();
@@ -92,7 +94,7 @@ public class PseudocodeImpl implements Pseudocode {
private final Map<JetExpression, LoopInfo> loopInfo = Maps.newHashMap();
private final List<PseudocodeLabel> labels = new ArrayList<PseudocodeLabel>();
private final Map<PseudocodeLabel, Collection<Label>> stopAllowDeadLabels = Maps.newHashMap();
private final Map<Label, Collection<Label>> stopAllowDeadLabels = Maps.newHashMap();
private final JetElement correspondingElement;
private SubroutineExitInstruction exitInstruction;
@@ -398,8 +400,8 @@ public class PseudocodeImpl implements Pseudocode {
@NotNull
private Map<Instruction, Collection<Label>> prepareAllowDeadStoppers() {
Map<Instruction, Collection<Label>> stopAllowedDeadInstructions = Maps.newHashMap();
for (Map.Entry<PseudocodeLabel, Collection<Label>> entry : stopAllowDeadLabels.entrySet()) {
PseudocodeLabel stopAllowedDeadLabel = entry.getKey();
for (Map.Entry<Label, Collection<Label>> entry : stopAllowDeadLabels.entrySet()) {
Label stopAllowedDeadLabel = entry.getKey();
Instruction stopAllowDeadInsruction = getJumpTarget(stopAllowedDeadLabel);
if (((InstructionImpl)stopAllowDeadInsruction).isDead()) {
stopAllowedDeadInstructions.put(stopAllowDeadInsruction, entry.getValue());
@@ -458,4 +460,68 @@ public class PseudocodeImpl implements Pseudocode {
assert targetPosition < mutableInstructionList.size() : currentPosition;
return mutableInstructionList.get(targetPosition);
}
public void repeatPart(@NotNull Label startLabel, @NotNull Label finishLabel) {
Integer startIndex = ((PseudocodeLabel) startLabel).getTargetInstructionIndex();
assert startIndex != null;
Integer finishIndex = ((PseudocodeLabel) finishLabel).getTargetInstructionIndex();
assert finishIndex != null;
Map<Label, Label> originalToCopy = Maps.newHashMap();
Multimap<Instruction, Label> originalLabelsForInstruction = HashMultimap.create();
for (PseudocodeLabel label : labels) {
Integer index = label.getTargetInstructionIndex();
if (index == null) continue; //label is not bounded yet
if (label == startLabel || label == finishLabel) continue;
if (startIndex <= index && index <= finishIndex) {
originalToCopy.put(label, label.copy());
originalLabelsForInstruction.put(getJumpTarget(label), label);
}
}
for (int index = startIndex; index < finishIndex; index++) {
Instruction oldInstruction = mutableInstructionList.get(index);
Instruction newInstruction = copyInstruction(oldInstruction, originalToCopy);
if (originalLabelsForInstruction.containsKey(oldInstruction)) {
Collection<Label> oldLabels = originalLabelsForInstruction.get(oldInstruction);
for (Label oldLabel : oldLabels) {
bindLabel(originalToCopy.get(oldLabel));
}
}
addInstruction(newInstruction);
}
for (Map.Entry<Label, Label> entry : originalToCopy.entrySet()) {
Label oldLabel = entry.getKey();
Label newLabel = entry.getValue();
Collection<Label> stopAllowDead = stopAllowDeadLabels.get(oldLabel);
if (stopAllowDead != null) {
stopAllowDeadLabels.put(newLabel, copyLabels(stopAllowDead, originalToCopy));
}
}
}
private Instruction copyInstruction(@NotNull Instruction instruction, @NotNull Map<Label, Label> originalToCopy) {
if (instruction instanceof AbstractJumpInstruction) {
Label originalTarget = ((AbstractJumpInstruction) instruction).getTargetLabel();
if (originalToCopy.containsKey(originalTarget)) {
return ((AbstractJumpInstruction)instruction).copy(originalToCopy.get(originalTarget));
}
}
if (instruction instanceof NondeterministicJumpInstruction) {
List<Label> originalTargets = ((NondeterministicJumpInstruction) instruction).getTargetLabels();
List<Label> copyTargets = copyLabels(originalTargets, originalToCopy);
return ((NondeterministicJumpInstruction) instruction).copy(copyTargets);
}
return ((InstructionImpl)instruction).copy();
}
@NotNull
private List<Label> copyLabels(Collection<Label> labels, Map<Label, Label> originalToCopy) {
List<Label> newLabels = Lists.newArrayList();
for (Label label : labels) {
Label newLabel = originalToCopy.get(label);
newLabels.add(newLabel != null ? newLabel : label);
}
return newLabels;
}
}