TraversalOrder enum instead of boolean flag
This commit is contained in:
@@ -44,6 +44,8 @@ import org.jetbrains.jet.plugin.JetMainDetector;
|
|||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import static org.jetbrains.jet.lang.cfg.PseudocodeTraverser.TraversalOrder.BACKWARD;
|
||||||
|
import static org.jetbrains.jet.lang.cfg.PseudocodeTraverser.TraversalOrder.FORWARD;
|
||||||
import static org.jetbrains.jet.lang.cfg.PseudocodeVariablesData.VariableUseState.*;
|
import static org.jetbrains.jet.lang.cfg.PseudocodeVariablesData.VariableUseState.*;
|
||||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||||
import static org.jetbrains.jet.lang.resolve.BindingContext.CAPTURED_IN_CLOSURE;
|
import static org.jetbrains.jet.lang.resolve.BindingContext.CAPTURED_IN_CLOSURE;
|
||||||
@@ -196,7 +198,7 @@ public class JetFlowInformationProvider {
|
|||||||
|
|
||||||
final Map<Instruction, AbstractDiagnosticFactory> reportedDiagnosticMap = Maps.newHashMap();
|
final Map<Instruction, AbstractDiagnosticFactory> reportedDiagnosticMap = Maps.newHashMap();
|
||||||
|
|
||||||
PseudocodeTraverser.traverseForward(pseudocode, true, initializers, new InstructionDataAnalyzeStrategy<Map<VariableDescriptor, PseudocodeVariablesData.VariableInitState>>() {
|
PseudocodeTraverser.traverse(pseudocode, FORWARD, true, initializers, new InstructionDataAnalyzeStrategy<Map<VariableDescriptor, PseudocodeVariablesData.VariableInitState>>() {
|
||||||
@Override
|
@Override
|
||||||
public void execute(@NotNull Instruction instruction,
|
public void execute(@NotNull Instruction instruction,
|
||||||
@Nullable Map<VariableDescriptor, VariableInitState> in,
|
@Nullable Map<VariableDescriptor, VariableInitState> in,
|
||||||
@@ -251,7 +253,8 @@ public class JetFlowInformationProvider {
|
|||||||
if (!isInitialized && !varWithUninitializedErrorGenerated.contains(ctxt.variableDescriptor)) {
|
if (!isInitialized && !varWithUninitializedErrorGenerated.contains(ctxt.variableDescriptor)) {
|
||||||
varWithUninitializedErrorGenerated.add(ctxt.variableDescriptor);
|
varWithUninitializedErrorGenerated.add(ctxt.variableDescriptor);
|
||||||
if (ctxt.variableDescriptor instanceof ValueParameterDescriptor) {
|
if (ctxt.variableDescriptor instanceof ValueParameterDescriptor) {
|
||||||
report(Errors.UNINITIALIZED_PARAMETER.on((JetSimpleNameExpression) element, (ValueParameterDescriptor) ctxt.variableDescriptor), ctxt);
|
report(Errors.UNINITIALIZED_PARAMETER.on((JetSimpleNameExpression) element,
|
||||||
|
(ValueParameterDescriptor) ctxt.variableDescriptor), ctxt);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
report(Errors.UNINITIALIZED_VARIABLE.on((JetSimpleNameExpression) element, ctxt.variableDescriptor), ctxt);
|
report(Errors.UNINITIALIZED_VARIABLE.on((JetSimpleNameExpression) element, ctxt.variableDescriptor), ctxt);
|
||||||
@@ -502,7 +505,7 @@ public class JetFlowInformationProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
PseudocodeTraverser.traverseBackward(pseudocode, true, variableStatusData, variableStatusAnalyzeStrategy);
|
PseudocodeTraverser.traverse(pseudocode, BACKWARD, true, variableStatusData, variableStatusAnalyzeStrategy);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -511,8 +514,8 @@ public class JetFlowInformationProvider {
|
|||||||
public void markUnusedLiteralsInBlock() {
|
public void markUnusedLiteralsInBlock() {
|
||||||
assert pseudocode != null;
|
assert pseudocode != null;
|
||||||
final Map<Instruction, AbstractDiagnosticFactory> reportedDiagnosticMap = Maps.newHashMap();
|
final Map<Instruction, AbstractDiagnosticFactory> reportedDiagnosticMap = Maps.newHashMap();
|
||||||
PseudocodeTraverser.traverseForward(
|
PseudocodeTraverser.traverse(
|
||||||
pseudocode, new InstructionAnalyzeStrategy() {
|
pseudocode, FORWARD, new InstructionAnalyzeStrategy() {
|
||||||
@Override
|
@Override
|
||||||
public void execute(@NotNull Instruction instruction) {
|
public void execute(@NotNull Instruction instruction) {
|
||||||
if (!(instruction instanceof ReadValueInstruction)) return;
|
if (!(instruction instanceof ReadValueInstruction)) return;
|
||||||
|
|||||||
@@ -28,29 +28,57 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.jetbrains.jet.lang.cfg.PseudocodeTraverser.TraversalOrder.FORWARD;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author svtk
|
* @author svtk
|
||||||
*/
|
*/
|
||||||
public class PseudocodeTraverser {
|
public class PseudocodeTraverser {
|
||||||
|
|
||||||
|
public static enum TraversalOrder {
|
||||||
|
FORWARD,
|
||||||
|
BACKWARD;
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static Instruction getStartInstruction(@NotNull Pseudocode pseudocode, boolean directOrder) {
|
private static Instruction getStartInstruction(@NotNull Pseudocode pseudocode, @NotNull TraversalOrder traversalOrder) {
|
||||||
return directOrder ? pseudocode.getEnterInstruction() : pseudocode.getSinkInstruction();
|
return traversalOrder == FORWARD ? pseudocode.getEnterInstruction() : pseudocode.getSinkInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static Instruction getLastInstruction(@NotNull Pseudocode pseudocode, @NotNull TraversalOrder traversalOrder) {
|
||||||
|
return traversalOrder == FORWARD ? pseudocode.getSinkInstruction() : pseudocode.getEnterInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static List<Instruction> getInstructions(@NotNull Pseudocode pseudocode, @NotNull TraversalOrder traversalOrder) {
|
||||||
|
return traversalOrder == FORWARD ? pseudocode.getInstructions() : pseudocode.getReversedInstructions();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static Collection<Instruction> getPreviousInstruction(@NotNull Instruction instruction, @NotNull TraversalOrder traversalOrder) {
|
||||||
|
return traversalOrder == FORWARD ? instruction.getPreviousInstructions() : instruction.getNextInstructions();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isStartInstruction(@NotNull Instruction instruction, @NotNull TraversalOrder traversalOrder) {
|
||||||
|
return traversalOrder == FORWARD ? instruction instanceof SubroutineEnterInstruction
|
||||||
|
: instruction instanceof SubroutineSinkInstruction;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <D> Map<Instruction, Edges<D>> collectData(
|
public static <D> Map<Instruction, Edges<D>> collectData(
|
||||||
@NotNull Pseudocode pseudocode, boolean directOrder, boolean lookInside,
|
@NotNull Pseudocode pseudocode, TraversalOrder traversalOrder, boolean lookInside,
|
||||||
@NotNull D initialDataValue, @NotNull D initialDataValueForEnterInstruction,
|
@NotNull D initialDataValue, @NotNull D initialDataValueForEnterInstruction,
|
||||||
@NotNull InstructionDataMergeStrategy<D> instructionDataMergeStrategy) {
|
@NotNull InstructionDataMergeStrategy<D> instructionDataMergeStrategy) {
|
||||||
|
|
||||||
Map<Instruction, Edges<D>> edgesMap = Maps.newLinkedHashMap();
|
Map<Instruction, Edges<D>> edgesMap = Maps.newLinkedHashMap();
|
||||||
initializeEdgesMap(pseudocode, lookInside, edgesMap, initialDataValue);
|
initializeEdgesMap(pseudocode, lookInside, edgesMap, initialDataValue);
|
||||||
edgesMap.put(getStartInstruction(pseudocode, directOrder), Edges.create(initialDataValueForEnterInstruction, initialDataValueForEnterInstruction));
|
edgesMap.put(getStartInstruction(pseudocode, traversalOrder), Edges.create(initialDataValueForEnterInstruction, initialDataValueForEnterInstruction));
|
||||||
|
|
||||||
boolean[] changed = new boolean[1];
|
boolean[] changed = new boolean[1];
|
||||||
changed[0] = true;
|
changed[0] = true;
|
||||||
while (changed[0]) {
|
while (changed[0]) {
|
||||||
changed[0] = false;
|
changed[0] = false;
|
||||||
collectDataFromSubgraph(pseudocode, directOrder, lookInside, edgesMap, instructionDataMergeStrategy,
|
collectDataFromSubgraph(pseudocode, traversalOrder, lookInside, edgesMap, instructionDataMergeStrategy,
|
||||||
Collections.<Instruction>emptyList(), changed, false);
|
Collections.<Instruction>emptyList(), changed, false);
|
||||||
}
|
}
|
||||||
return edgesMap;
|
return edgesMap;
|
||||||
@@ -71,21 +99,21 @@ public class PseudocodeTraverser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static <D> void collectDataFromSubgraph(
|
private static <D> void collectDataFromSubgraph(
|
||||||
@NotNull Pseudocode pseudocode, boolean directOrder, boolean lookInside,
|
@NotNull Pseudocode pseudocode, TraversalOrder traversalOrder, boolean lookInside,
|
||||||
@NotNull Map<Instruction, Edges<D>> edgesMap,
|
@NotNull Map<Instruction, Edges<D>> edgesMap,
|
||||||
@NotNull InstructionDataMergeStrategy<D> instructionDataMergeStrategy,
|
@NotNull InstructionDataMergeStrategy<D> instructionDataMergeStrategy,
|
||||||
@NotNull Collection<Instruction> previousSubGraphInstructions,
|
@NotNull Collection<Instruction> previousSubGraphInstructions,
|
||||||
boolean[] changed, boolean isLocal) {
|
boolean[] changed, boolean isLocal) {
|
||||||
|
|
||||||
List<Instruction> instructions = directOrder ? pseudocode.getInstructions() : pseudocode.getReversedInstructions();
|
List<Instruction> instructions = getInstructions(pseudocode, traversalOrder);
|
||||||
Instruction startInstruction = getStartInstruction(pseudocode, directOrder);
|
Instruction startInstruction = getStartInstruction(pseudocode, traversalOrder);
|
||||||
|
|
||||||
for (Instruction instruction : instructions) {
|
for (Instruction instruction : instructions) {
|
||||||
boolean isStart = directOrder ? instruction instanceof SubroutineEnterInstruction : instruction instanceof SubroutineSinkInstruction;
|
boolean isStart = isStartInstruction(instruction, traversalOrder);
|
||||||
if (!isLocal && isStart) continue;
|
if (!isLocal && isStart) continue;
|
||||||
|
|
||||||
Collection<Instruction> allPreviousInstructions;
|
Collection<Instruction> allPreviousInstructions;
|
||||||
Collection<Instruction> previousInstructions = directOrder ? instruction.getPreviousInstructions() : instruction.getNextInstructions();
|
Collection<Instruction> previousInstructions = getPreviousInstruction(instruction, traversalOrder);
|
||||||
|
|
||||||
if (instruction == startInstruction && !previousSubGraphInstructions.isEmpty()) {
|
if (instruction == startInstruction && !previousSubGraphInstructions.isEmpty()) {
|
||||||
allPreviousInstructions = Lists.newArrayList(previousInstructions);
|
allPreviousInstructions = Lists.newArrayList(previousInstructions);
|
||||||
@@ -97,10 +125,10 @@ public class PseudocodeTraverser {
|
|||||||
|
|
||||||
if (lookInside && instruction instanceof LocalDeclarationInstruction) {
|
if (lookInside && instruction instanceof LocalDeclarationInstruction) {
|
||||||
Pseudocode subroutinePseudocode = ((LocalDeclarationInstruction) instruction).getBody();
|
Pseudocode subroutinePseudocode = ((LocalDeclarationInstruction) instruction).getBody();
|
||||||
collectDataFromSubgraph(subroutinePseudocode, directOrder, lookInside, edgesMap, instructionDataMergeStrategy,
|
collectDataFromSubgraph(subroutinePseudocode, traversalOrder, lookInside, edgesMap, instructionDataMergeStrategy,
|
||||||
previousInstructions,
|
previousInstructions,
|
||||||
changed, true);
|
changed, true);
|
||||||
Instruction lastInstruction = directOrder ? subroutinePseudocode.getSinkInstruction() : subroutinePseudocode.getEnterInstruction();
|
Instruction lastInstruction = getLastInstruction(subroutinePseudocode, traversalOrder);
|
||||||
Edges<D> previousValue = edgesMap.get(instruction);
|
Edges<D> previousValue = edgesMap.get(instruction);
|
||||||
Edges<D> newValue = edgesMap.get(lastInstruction);
|
Edges<D> newValue = edgesMap.get(lastInstruction);
|
||||||
if (!previousValue.equals(newValue)) {
|
if (!previousValue.equals(newValue)) {
|
||||||
@@ -127,54 +155,28 @@ public class PseudocodeTraverser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void traverseForward(
|
public static void traverse(
|
||||||
@NotNull Pseudocode pseudocode,
|
@NotNull Pseudocode pseudocode, TraversalOrder traversalOrder,
|
||||||
@NotNull InstructionAnalyzeStrategy instructionAnalyzeStrategy) {
|
|
||||||
traverse(pseudocode, true, instructionAnalyzeStrategy);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void traverseBackward(
|
|
||||||
@NotNull Pseudocode pseudocode,
|
|
||||||
@NotNull InstructionAnalyzeStrategy instructionAnalyzeStrategy) {
|
|
||||||
traverse(pseudocode, false, instructionAnalyzeStrategy);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void traverse(
|
|
||||||
@NotNull Pseudocode pseudocode, boolean directOrder,
|
|
||||||
InstructionAnalyzeStrategy instructionAnalyzeStrategy) {
|
InstructionAnalyzeStrategy instructionAnalyzeStrategy) {
|
||||||
|
|
||||||
List<Instruction> instructions = directOrder ? pseudocode.getInstructions() : pseudocode.getReversedInstructions();
|
List<Instruction> instructions = getInstructions(pseudocode, traversalOrder);
|
||||||
for (Instruction instruction : instructions) {
|
for (Instruction instruction : instructions) {
|
||||||
if (instruction instanceof LocalDeclarationInstruction) {
|
if (instruction instanceof LocalDeclarationInstruction) {
|
||||||
traverse(((LocalDeclarationInstruction) instruction).getBody(), directOrder, instructionAnalyzeStrategy);
|
traverse(((LocalDeclarationInstruction) instruction).getBody(), traversalOrder, instructionAnalyzeStrategy);
|
||||||
}
|
}
|
||||||
instructionAnalyzeStrategy.execute(instruction);
|
instructionAnalyzeStrategy.execute(instruction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <D> void traverseForward(
|
public static <D> void traverse(
|
||||||
@NotNull Pseudocode pseudocode, boolean lookInside,
|
@NotNull Pseudocode pseudocode, TraversalOrder traversalOrder, boolean lookInside,
|
||||||
@NotNull Map<Instruction, Edges<D>> edgesMap,
|
|
||||||
@NotNull InstructionDataAnalyzeStrategy<D> instructionDataAnalyzeStrategy) {
|
|
||||||
traverse(pseudocode, true, lookInside, edgesMap, instructionDataAnalyzeStrategy);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <D> void traverseBackward(
|
|
||||||
@NotNull Pseudocode pseudocode, boolean lookInside,
|
|
||||||
@NotNull Map<Instruction, Edges<D>> edgesMap,
|
|
||||||
@NotNull InstructionDataAnalyzeStrategy<D> instructionDataAnalyzeStrategy) {
|
|
||||||
traverse(pseudocode, false, lookInside, edgesMap, instructionDataAnalyzeStrategy);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <D> void traverse(
|
|
||||||
@NotNull Pseudocode pseudocode, boolean directOrder, boolean lookInside,
|
|
||||||
@NotNull Map<Instruction, Edges<D>> edgesMap,
|
@NotNull Map<Instruction, Edges<D>> edgesMap,
|
||||||
@NotNull InstructionDataAnalyzeStrategy<D> instructionDataAnalyzeStrategy) {
|
@NotNull InstructionDataAnalyzeStrategy<D> instructionDataAnalyzeStrategy) {
|
||||||
|
|
||||||
List<Instruction> instructions = directOrder ? pseudocode.getInstructions() : pseudocode.getReversedInstructions();
|
List<Instruction> instructions = getInstructions(pseudocode, traversalOrder);
|
||||||
for (Instruction instruction : instructions) {
|
for (Instruction instruction : instructions) {
|
||||||
if (lookInside && instruction instanceof LocalDeclarationInstruction) {
|
if (lookInside && instruction instanceof LocalDeclarationInstruction) {
|
||||||
traverse(((LocalDeclarationInstruction) instruction).getBody(), directOrder, lookInside, edgesMap,
|
traverse(((LocalDeclarationInstruction) instruction).getBody(), traversalOrder, lookInside, edgesMap,
|
||||||
instructionDataAnalyzeStrategy);
|
instructionDataAnalyzeStrategy);
|
||||||
}
|
}
|
||||||
Edges<D> edges = edgesMap.get(instruction);
|
Edges<D> edges = edgesMap.get(instruction);
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ import java.util.Collections;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static org.jetbrains.jet.lang.cfg.PseudocodeTraverser.TraversalOrder.BACKWARD;
|
||||||
|
import static org.jetbrains.jet.lang.cfg.PseudocodeTraverser.TraversalOrder.FORWARD;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author svtk
|
* @author svtk
|
||||||
*/
|
*/
|
||||||
@@ -61,7 +64,7 @@ public class PseudocodeVariablesData {
|
|||||||
Set<VariableDescriptor> usedVariables = usedVariablesForDeclaration.get(pseudocode);
|
Set<VariableDescriptor> usedVariables = usedVariablesForDeclaration.get(pseudocode);
|
||||||
if (usedVariables == null) {
|
if (usedVariables == null) {
|
||||||
final Set<VariableDescriptor> result = Sets.newHashSet();
|
final Set<VariableDescriptor> result = Sets.newHashSet();
|
||||||
PseudocodeTraverser.traverseForward(pseudocode, new InstructionAnalyzeStrategy() {
|
PseudocodeTraverser.traverse(pseudocode, FORWARD, new InstructionAnalyzeStrategy() {
|
||||||
@Override
|
@Override
|
||||||
public void execute(@NotNull Instruction instruction) {
|
public void execute(@NotNull Instruction instruction) {
|
||||||
VariableDescriptor variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, false,
|
VariableDescriptor variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, false,
|
||||||
@@ -138,7 +141,7 @@ public class PseudocodeVariablesData {
|
|||||||
usedVariables, declaredVariables);
|
usedVariables, declaredVariables);
|
||||||
|
|
||||||
Map<Instruction, Edges<Map<VariableDescriptor, VariableInitState>>> variableInitializersMap = PseudocodeTraverser.collectData(
|
Map<Instruction, Edges<Map<VariableDescriptor, VariableInitState>>> variableInitializersMap = PseudocodeTraverser.collectData(
|
||||||
pseudocode, /* directOrder = */ true, /* lookInside = */ false,
|
pseudocode, FORWARD, /* lookInside = */ false,
|
||||||
initialMap, initialMapForStartInstruction, new PseudocodeTraverser.InstructionDataMergeStrategy<Map<VariableDescriptor, VariableInitState>>() {
|
initialMap, initialMapForStartInstruction, new PseudocodeTraverser.InstructionDataMergeStrategy<Map<VariableDescriptor, VariableInitState>>() {
|
||||||
@Override
|
@Override
|
||||||
public Edges<Map<VariableDescriptor, VariableInitState>> execute(
|
public Edges<Map<VariableDescriptor, VariableInitState>> execute(
|
||||||
@@ -289,7 +292,7 @@ public class PseudocodeVariablesData {
|
|||||||
return Edges.create(enterResult, exitResult);
|
return Edges.create(enterResult, exitResult);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
variableStatusMap = PseudocodeTraverser.collectData(pseudocode, false, true,
|
variableStatusMap = PseudocodeTraverser.collectData(pseudocode, BACKWARD, true,
|
||||||
Collections.<VariableDescriptor, VariableUseState>emptyMap(),
|
Collections.<VariableDescriptor, VariableUseState>emptyMap(),
|
||||||
sinkInstructionData, collectVariableUseStatusStrategy);
|
sinkInstructionData, collectVariableUseStatusStrategy);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user