'Pseudocode' interface improvements

This commit is contained in:
Svetlana Isakova
2012-05-26 13:34:05 +04:00
parent 7a02cfcd25
commit 5c7206ef49
7 changed files with 78 additions and 60 deletions
@@ -32,22 +32,22 @@ import java.util.*;
public class JetControlFlowGraphTraverser<D> {
private final Pseudocode pseudocode;
private final boolean lookInside;
private final boolean straightDirection;
private final boolean directOrder;
private final Map<Instruction, Pair<D, D>> dataMap = Maps.newLinkedHashMap();
public static <D> JetControlFlowGraphTraverser<D> create(@NotNull Pseudocode pseudocode, boolean lookInside, boolean straightDirection) {
return new JetControlFlowGraphTraverser<D>(pseudocode, lookInside, straightDirection);
}
private JetControlFlowGraphTraverser(@NotNull Pseudocode pseudocode, boolean lookInside, boolean straightDirection) {
private JetControlFlowGraphTraverser(@NotNull Pseudocode pseudocode, boolean lookInside, boolean directOrder) {
this.pseudocode = pseudocode;
this.lookInside = lookInside;
this.straightDirection = straightDirection;
this.directOrder = directOrder;
}
@NotNull
private Instruction getStartInstruction(@NotNull Pseudocode pseudocode) {
return straightDirection ? pseudocode.getEnterInstruction() : pseudocode.getSinkInstruction();
return directOrder ? pseudocode.getEnterInstruction() : pseudocode.getSinkInstruction();
}
@NotNull
@@ -84,42 +84,21 @@ public class JetControlFlowGraphTraverser<D> {
}
}
private static List<Instruction> reverseInstructions(@NotNull Pseudocode pseudocode) {
LinkedHashSet<Instruction> traversedInstructions = Sets.newLinkedHashSet();
Instruction sinkInstruction = pseudocode.getSinkInstruction();
traverseInstructions(sinkInstruction, traversedInstructions);
return Lists.newArrayList(traversedInstructions);
}
private static void traverseInstructions(@NotNull Instruction instruction, @NotNull LinkedHashSet<Instruction> instructions) {
if (((InstructionImpl)instruction).isDead()) return;
if (instructions.contains(instruction)) return;
instructions.add(instruction);
for (Instruction previousInstruction : instruction.getPreviousInstructions()) {
traverseInstructions(previousInstruction, instructions);
}
}
private void traverseSubGraph(
@NotNull Pseudocode pseudocode,
@NotNull InstructionDataMergeStrategy<D> instructionDataMergeStrategy,
@NotNull Collection<Instruction> previousSubGraphInstructions,
boolean[] changed,
boolean isLocal) {
List<Instruction> instructions = pseudocode.getInstructions();
List<Instruction> instructions = directOrder ? pseudocode.getInstructions() : pseudocode.getReversedInstructions();
Instruction startInstruction = getStartInstruction(pseudocode);
if (!straightDirection) {
instructions = reverseInstructions(pseudocode);
}
for (Instruction instruction : instructions) {
boolean isStart = straightDirection ? instruction instanceof SubroutineEnterInstruction : instruction instanceof SubroutineSinkInstruction;
boolean isStart = directOrder ? instruction instanceof SubroutineEnterInstruction : instruction instanceof SubroutineSinkInstruction;
if (!isLocal && isStart) continue;
Collection<Instruction> allPreviousInstructions;
Collection<Instruction> previousInstructions = straightDirection
? instruction.getPreviousInstructions()
: instruction.getNextInstructions();
Collection<Instruction> previousInstructions = directOrder ? instruction.getPreviousInstructions() : instruction.getNextInstructions();
if (instruction == startInstruction && !previousSubGraphInstructions.isEmpty()) {
allPreviousInstructions = Lists.newArrayList(previousInstructions);
@@ -132,7 +111,7 @@ public class JetControlFlowGraphTraverser<D> {
if (lookInside && instruction instanceof LocalDeclarationInstruction) {
Pseudocode subroutinePseudocode = ((LocalDeclarationInstruction) instruction).getBody();
traverseSubGraph(subroutinePseudocode, instructionDataMergeStrategy, previousInstructions, changed, true);
Instruction lastInstruction = straightDirection ? subroutinePseudocode.getSinkInstruction() : subroutinePseudocode.getEnterInstruction();
Instruction lastInstruction = directOrder ? subroutinePseudocode.getSinkInstruction() : subroutinePseudocode.getEnterInstruction();
Pair<D, D> previousValue = dataMap.get(instruction);
Pair<D, D> newValue = dataMap.get(lastInstruction);
if (!previousValue.equals(newValue)) {
@@ -168,7 +147,7 @@ public class JetControlFlowGraphTraverser<D> {
@NotNull Pseudocode pseudocode,
@NotNull InstructionDataAnalyzeStrategy<D> instructionDataAnalyzeStrategy) {
List<Instruction> instructions = pseudocode.getInstructions();
if (!straightDirection) {
if (!directOrder) {
instructions = Lists.newArrayList(instructions);
Collections.reverse(instructions);
}
@@ -21,6 +21,7 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.cfg.pseudocode.LocalDeclarationInstruction;
import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowInstructionsGenerator;
import org.jetbrains.jet.lang.cfg.pseudocode.PseudocodeImpl;
@@ -57,8 +58,8 @@ public class JetControlFlowProcessor {
public Pseudocode generatePseudocode(@NotNull JetDeclaration subroutine) {
Pseudocode pseudocode = generate(subroutine);
((PseudocodeImpl)pseudocode).postProcess();
for (Pseudocode localPseudocode : pseudocode.getLocalDeclarations()) {
((PseudocodeImpl)localPseudocode).postProcess();
for (LocalDeclarationInstruction localDeclarationInstruction : pseudocode.getLocalDeclarations()) {
((PseudocodeImpl)localDeclarationInstruction.getBody()).postProcess();
}
return pseudocode;
}
@@ -140,7 +140,7 @@ public class JetFlowInformationProvider {
}
final boolean blockBody = function.hasBlockBody();
final Set<JetElement> rootUnreachableElements = collectUnreachableCode(function.asElement());
final Set<JetElement> rootUnreachableElements = collectUnreachableCode();
for (JetElement element : rootUnreachableElements) {
trace.report(UNREACHABLE_CODE.on(element));
}
@@ -168,7 +168,7 @@ public class JetFlowInformationProvider {
}
}
private Set<JetElement> collectUnreachableCode(@NotNull JetElement subroutine) {
private Set<JetElement> collectUnreachableCode() {
Collection<JetElement> unreachableElements = Lists.newArrayList();
for (Instruction deadInstruction : pseudocode.getDeadInstructions()) {
if (deadInstruction instanceof JetElementInstruction &&
@@ -223,8 +223,8 @@ public class JetFlowInformationProvider {
Pseudocode pseudocode = pseudocodeData.getPseudocode();
recordInitializedVariables(pseudocodeData.getDeclarationData(pseudocode), pseudocodeData.getResultInfo(pseudocode));
for (Pseudocode localPseudocode : pseudocode.getLocalDeclarations()) {
recordInitializedVariables(pseudocodeData.getDeclarationData(localPseudocode), pseudocodeData.getResultInfo(localPseudocode));
for (LocalDeclarationInstruction instruction : pseudocode.getLocalDeclarations()) {
recordInitializedVariables(pseudocodeData.getDeclarationData(instruction.getBody()), pseudocodeData.getResultInfo(instruction.getBody()));
}
}
@@ -119,8 +119,8 @@ public class PseudocodeData {
DeclarationData declarationData = new DeclarationData(pseudocode.getCorrespondingElement(), this, collectDeclaredVariables(pseudocode), collectUsedVariables(pseudocode));
declarationDataMap.put(pseudocode, declarationData);
for (Pseudocode localPseudocode : pseudocode.getLocalDeclarations()) {
collectDeclarationData(localPseudocode);
for (LocalDeclarationInstruction localDeclarationInstruction : pseudocode.getLocalDeclarations()) {
collectDeclarationData(localDeclarationInstruction.getBody());
}
}
@@ -180,7 +180,9 @@ public class PseudocodeData {
Map<Instruction, Pair<Map<VariableDescriptor, VariableInitializers>, Map<VariableDescriptor, VariableInitializers>>> result =
traverser.getDataMap();
for (Pseudocode localPseudocode : pseudocode.getLocalDeclarations()) {
for (LocalDeclarationInstruction localDeclarationInstruction : pseudocode.getLocalDeclarations()) {
Pseudocode localPseudocode = localDeclarationInstruction.getBody();
Map<Instruction, Pair<Map<VariableDescriptor, VariableInitializers>, Map<VariableDescriptor, VariableInitializers>>> initializersForLocalDeclaration =
collectVariableInitializers(localPseudocode, declarationDataMap.get(localPseudocode));
@@ -19,6 +19,7 @@ package org.jetbrains.jet.lang.cfg.pseudocode;
import com.google.common.collect.Lists;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetDeclaration;
import org.jetbrains.jet.lang.psi.JetElement;
import java.util.ArrayList;
import java.util.Collection;
@@ -40,6 +41,12 @@ public class LocalDeclarationInstruction extends InstructionWithNext {
return body;
}
@NotNull
@Override
public JetDeclaration getElement() {
return (JetDeclaration) super.getElement();
}
@NotNull
@Override
public Collection<Instruction> getNextInstructions() {
@@ -30,11 +30,14 @@ public interface Pseudocode {
JetElement getCorrespondingElement();
@NotNull
Set<Pseudocode> getLocalDeclarations();
Set<LocalDeclarationInstruction> getLocalDeclarations();
@NotNull
List<Instruction> getInstructions();
@NotNull
List<Instruction> getReversedInstructions();
@NotNull
List<Instruction> getDeadInstructions();
@@ -76,10 +76,13 @@ public class PseudocodeImpl implements Pseudocode {
private final List<Instruction> mutableInstructionList = new ArrayList<Instruction>();
private final List<Instruction> instructions = new ArrayList<Instruction>();
private List<Instruction> reversedInstructions = null;
private List<Instruction> deadInstructions;
final Map<JetElement, Instruction> representativeInstructions = new HashMap<JetElement, Instruction>();
final Map<JetExpression, LoopInfo> loopInfo = Maps.newHashMap();
private Set<LocalDeclarationInstruction> localDeclarations = null;
//todo getters
private final Map<JetElement, Instruction> representativeInstructions = new HashMap<JetElement, Instruction>();
private final Map<JetExpression, LoopInfo> loopInfo = Maps.newHashMap();
private final List<PseudocodeLabel> labels = new ArrayList<PseudocodeLabel>();
private final List<PseudocodeLabel> allowedDeadLabels = new ArrayList<PseudocodeLabel>();
@@ -103,28 +106,30 @@ public class PseudocodeImpl implements Pseudocode {
@NotNull
@Override
public Set<Pseudocode> getLocalDeclarations() {
Set<Pseudocode> localDeclarations = Sets.newLinkedHashSet();
//todo look recursively inside local declarations
for (Instruction instruction : instructions) {
if (instruction instanceof LocalDeclarationInstruction) {
localDeclarations.add(((LocalDeclarationInstruction) instruction).getBody());
public Set<LocalDeclarationInstruction> getLocalDeclarations() {
if (localDeclarations == null) {
localDeclarations = Sets.newLinkedHashSet();
//todo look recursively inside local declarations
for (Instruction instruction : instructions) {
if (instruction instanceof LocalDeclarationInstruction) {
localDeclarations.add((LocalDeclarationInstruction) instruction);
}
}
}
return localDeclarations;
}
public PseudocodeLabel createLabel(String name) {
/*package*/ PseudocodeLabel createLabel(String name) {
PseudocodeLabel label = new PseudocodeLabel(name);
labels.add(label);
return label;
}
public void allowDead(Label label) {
/*package*/ void allowDead(Label label) {
allowedDeadLabels.add((PseudocodeLabel) label);
}
public void stopAllowDead(Label label) {
/*package*/ void stopAllowDead(Label label) {
stopAllowDeadLabels.add((PseudocodeLabel) label);
}
@@ -134,9 +139,30 @@ public class PseudocodeImpl implements Pseudocode {
return instructions;
}
@Deprecated //for tests only
@NotNull
public List<Instruction> getMutableInstructionList() {
@Override
public List<Instruction> getReversedInstructions() {
if (reversedInstructions == null) {
LinkedHashSet<Instruction> traversedInstructions = Sets.newLinkedHashSet();
traverseInstructionsInReverseOrder(sinkInstruction, traversedInstructions);
reversedInstructions = Lists.newArrayList(traversedInstructions);
}
return reversedInstructions;
}
private static void traverseInstructionsInReverseOrder(@NotNull Instruction instruction,
@NotNull LinkedHashSet<Instruction> instructions) {
if (instructions.contains(instruction)) return;
instructions.add(instruction);
for (Instruction previousInstruction : instruction.getPreviousInstructions()) {
traverseInstructionsInReverseOrder(previousInstruction, instructions);
}
}
//for tests only
@NotNull
public List<Instruction> getAllInstructions() {
return mutableInstructionList;
}
@@ -159,31 +185,31 @@ public class PseudocodeImpl implements Pseudocode {
return deadInstructions;
}
@Deprecated //for tests only
//for tests only
@NotNull
public List<PseudocodeLabel> getLabels() {
return labels;
}
public void addExitInstruction(SubroutineExitInstruction exitInstruction) {
/*package*/ void addExitInstruction(SubroutineExitInstruction exitInstruction) {
addInstruction(exitInstruction);
assert this.exitInstruction == null;
this.exitInstruction = exitInstruction;
}
public void addSinkInstruction(SubroutineSinkInstruction sinkInstruction) {
/*package*/ void addSinkInstruction(SubroutineSinkInstruction sinkInstruction) {
addInstruction(sinkInstruction);
assert this.sinkInstruction == null;
this.sinkInstruction = sinkInstruction;
}
public void addErrorInstruction(SubroutineExitInstruction errorInstruction) {
/*package*/ void addErrorInstruction(SubroutineExitInstruction errorInstruction) {
addInstruction(errorInstruction);
assert this.errorInstruction == null;
this.errorInstruction = errorInstruction;
}
public void addInstruction(Instruction instruction) {
/*package*/ void addInstruction(Instruction instruction) {
mutableInstructionList.add(instruction);
instruction.setOwner(this);
@@ -193,7 +219,7 @@ public class PseudocodeImpl implements Pseudocode {
}
}
public void recordLoopInfo(JetExpression expression, LoopInfo blockInfo) {
/*package*/ void recordLoopInfo(JetExpression expression, LoopInfo blockInfo) {
loopInfo.put(expression, blockInfo);
}
@@ -215,7 +241,7 @@ public class PseudocodeImpl implements Pseudocode {
return (SubroutineEnterInstruction) mutableInstructionList.get(0);
}
public void bindLabel(Label label) {
/*package*/ void bindLabel(Label label) {
((PseudocodeLabel) label).setTargetInstructionIndex(mutableInstructionList.size());
}