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