TraversalOrder enum instead of boolean flag

This commit is contained in:
Svetlana Isakova
2012-12-13 17:58:00 +04:00
parent 7a03c85549
commit e91805a593
3 changed files with 62 additions and 54 deletions
@@ -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);
} }