'Pseudocode' interface improvements
This commit is contained in:
@@ -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));
|
||||
|
||||
|
||||
+7
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user