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 // Other
void unsupported(JetElement element); void unsupported(JetElement element);
void repeatPseudocode(@NotNull Label startLabel, @NotNull Label finishLabel);
} }
@@ -222,4 +222,10 @@ public class JetControlFlowBuilderAdapter implements JetControlFlowBuilder {
assert builder != null; assert builder != null;
builder.declare(property); 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); 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 @Override
public void visitTryExpression(JetTryExpression expression) { public void visitTryExpression(JetTryExpression expression) {
builder.read(expression); builder.read(expression);
final JetFinallySection finallyBlock = expression.getFinallyBlock(); final JetFinallySection finallyBlock = expression.getFinallyBlock();
final FinallyBlockGenerator finallyBlockGenerator = new FinallyBlockGenerator(finallyBlock);
if (finallyBlock != null) { if (finallyBlock != null) {
builder.enterTryFinally(new GenerationTrigger() { builder.enterTryFinally(new GenerationTrigger() {
private boolean working = false; 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}' // This checks are needed for the case of having e.g. return inside finally: 'try {return} finally{return}'
if (working) return; if (working) return;
working = true; working = true;
value(finallyBlock.getFinalExpression(), inCondition); finallyBlockGenerator.generate();
working = false; working = false;
} }
}); });
@@ -425,11 +452,11 @@ public class JetControlFlowProcessor {
Label skipFinallyToErrorBlock = builder.createUnboundLabel("skipFinallyToErrorBlock"); Label skipFinallyToErrorBlock = builder.createUnboundLabel("skipFinallyToErrorBlock");
builder.jump(skipFinallyToErrorBlock); builder.jump(skipFinallyToErrorBlock);
builder.bindLabel(onExceptionToFinallyBlock); builder.bindLabel(onExceptionToFinallyBlock);
value(finallyBlock.getFinalExpression(), inCondition); finallyBlockGenerator.generate();
builder.jumpToError(); builder.jumpToError();
builder.bindLabel(skipFinallyToErrorBlock); builder.bindLabel(skipFinallyToErrorBlock);
value(finallyBlock.getFinalExpression(), inCondition); finallyBlockGenerator.generate();
} }
builder.stopAllowDead(allowDeadLabels); builder.stopAllowDead(allowDeadLabels);
} }
@@ -328,6 +328,11 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
public void unsupported(JetElement element) { public void unsupported(JetElement element) {
add(new UnsupportedElementInstruction(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 { public static class TryFinallyBlockInfo extends BlockInfo {
@@ -16,9 +16,8 @@
package org.jetbrains.jet.lang.cfg.pseudocode; package org.jetbrains.jet.lang.cfg.pseudocode;
import com.google.common.collect.Lists; import com.google.common.collect.*;
import com.google.common.collect.Maps; import com.intellij.util.containers.MultiMap;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.cfg.Label; import org.jetbrains.jet.lang.cfg.Label;
@@ -79,6 +78,9 @@ public class PseudocodeImpl implements Pseudocode {
return mutableInstructionList.get(targetInstructionIndex); return mutableInstructionList.get(targetInstructionIndex);
} }
public Label copy() {
return new PseudocodeLabel("copy " + name, allowDead);
}
} }
private final List<Instruction> mutableInstructionList = new ArrayList<Instruction>(); 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 Map<JetExpression, LoopInfo> loopInfo = Maps.newHashMap();
private final List<PseudocodeLabel> labels = new ArrayList<PseudocodeLabel>(); 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 final JetElement correspondingElement;
private SubroutineExitInstruction exitInstruction; private SubroutineExitInstruction exitInstruction;
@@ -398,8 +400,8 @@ public class PseudocodeImpl implements Pseudocode {
@NotNull @NotNull
private Map<Instruction, Collection<Label>> prepareAllowDeadStoppers() { private Map<Instruction, Collection<Label>> prepareAllowDeadStoppers() {
Map<Instruction, Collection<Label>> stopAllowedDeadInstructions = Maps.newHashMap(); Map<Instruction, Collection<Label>> stopAllowedDeadInstructions = Maps.newHashMap();
for (Map.Entry<PseudocodeLabel, Collection<Label>> entry : stopAllowDeadLabels.entrySet()) { for (Map.Entry<Label, Collection<Label>> entry : stopAllowDeadLabels.entrySet()) {
PseudocodeLabel stopAllowedDeadLabel = entry.getKey(); Label stopAllowedDeadLabel = entry.getKey();
Instruction stopAllowDeadInsruction = getJumpTarget(stopAllowedDeadLabel); Instruction stopAllowDeadInsruction = getJumpTarget(stopAllowedDeadLabel);
if (((InstructionImpl)stopAllowDeadInsruction).isDead()) { if (((InstructionImpl)stopAllowDeadInsruction).isDead()) {
stopAllowedDeadInstructions.put(stopAllowDeadInsruction, entry.getValue()); stopAllowedDeadInstructions.put(stopAllowDeadInsruction, entry.getValue());
@@ -458,4 +460,68 @@ public class PseudocodeImpl implements Pseudocode {
assert targetPosition < mutableInstructionList.size() : currentPosition; assert targetPosition < mutableInstructionList.size() : currentPosition;
return mutableInstructionList.get(targetPosition); 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;
}
} }