added repeat pseudocode method
repeat from startLabel to finishLabel (logic is inside PseudocodeImpl)
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
+5
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user