made PseudocodeVariableDataCollector know about variables

(not about abstract data)
This commit is contained in:
Svetlana Isakova
2014-02-24 14:16:53 +04:00
parent b79df51dab
commit 4a4e237539
2 changed files with 41 additions and 47 deletions
@@ -23,12 +23,10 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.cfg.pseudocode.Instruction; import org.jetbrains.jet.lang.cfg.pseudocode.Instruction;
import org.jetbrains.jet.lang.cfg.pseudocode.LocalFunctionDeclarationInstruction; import org.jetbrains.jet.lang.cfg.pseudocode.LocalFunctionDeclarationInstruction;
import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode; import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import java.util.Collection; import java.util.*;
import java.util.Collections;
import java.util.List;
import java.util.Map;
public class PseudocodeVariableDataCollector extends PseudocodeTraverser { public class PseudocodeVariableDataCollector extends PseudocodeTraverser {
private final BindingContext bindingContext; private final BindingContext bindingContext;
@@ -37,39 +35,37 @@ public class PseudocodeVariableDataCollector extends PseudocodeTraverser {
bindingContext = context; bindingContext = context;
} }
public <D> Map<Instruction, Edges<D>> collectData( public <D> Map<Instruction, Edges<Map<VariableDescriptor, D>>> collectData(
@NotNull Pseudocode pseudocode, @NotNull Pseudocode pseudocode,
@NotNull TraversalOrder traversalOrder, @NotNull TraversalOrder traversalOrder,
@NotNull LookInsideStrategy lookInside, @NotNull InstructionDataMergeStrategy<Map<VariableDescriptor, D>> instructionDataMergeStrategy
@NotNull D initialDataValue,
@NotNull D initialDataValueForEnterInstruction,
@NotNull InstructionDataMergeStrategy<D> instructionDataMergeStrategy
) { ) {
Map<VariableDescriptor, D> initialDataValue = Collections.emptyMap();
Map<Instruction, Edges<D>> edgesMap = Maps.newLinkedHashMap(); Map<Instruction, Edges<Map<VariableDescriptor, D>>> edgesMap = Maps.newLinkedHashMap();
initializeEdgesMap(pseudocode, lookInside, edgesMap, initialDataValue); initializeEdgesMap(pseudocode, edgesMap, initialDataValue);
edgesMap.put(getStartInstruction(pseudocode, traversalOrder), Edges.create(initialDataValueForEnterInstruction, initialDataValueForEnterInstruction)); edgesMap.put(getStartInstruction(pseudocode, traversalOrder), Edges.create(initialDataValue, initialDataValue));
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, traversalOrder, lookInside, edgesMap, instructionDataMergeStrategy, collectDataFromSubgraph(pseudocode, traversalOrder, LookInsideStrategy.ANALYSE_LOCAL_DECLARATIONS, edgesMap,
Collections.<Instruction>emptyList(), changed, false); instructionDataMergeStrategy, Collections.<Instruction>emptyList(), changed, false);
} }
return edgesMap; return edgesMap;
} }
private <D> void initializeEdgesMap( private static <M> void initializeEdgesMap(
@NotNull Pseudocode pseudocode, LookInsideStrategy lookInside, @NotNull Pseudocode pseudocode,
@NotNull Map<Instruction, Edges<D>> edgesMap, @NotNull Map<Instruction, Edges<M>> edgesMap,
@NotNull D initialDataValue) { @NotNull M initialDataValue
) {
List<Instruction> instructions = pseudocode.getInstructions(); List<Instruction> instructions = pseudocode.getInstructions();
Edges<D> initialEdge = Edges.create(initialDataValue, initialDataValue); Edges<M> initialEdge = Edges.create(initialDataValue, initialDataValue);
for (Instruction instruction : instructions) { for (Instruction instruction : instructions) {
edgesMap.put(instruction, initialEdge); edgesMap.put(instruction, initialEdge);
if (shouldLookInside(instruction, lookInside)) { if (shouldLookInside(instruction, LookInsideStrategy.ANALYSE_LOCAL_DECLARATIONS)) {
initializeEdgesMap(((LocalFunctionDeclarationInstruction) instruction).getBody(), lookInside, edgesMap, initialDataValue); initializeEdgesMap(((LocalFunctionDeclarationInstruction) instruction).getBody(), edgesMap, initialDataValue);
} }
} }
} }
@@ -78,8 +74,8 @@ public class PseudocodeVariableDataCollector extends PseudocodeTraverser {
@NotNull Pseudocode pseudocode, @NotNull Pseudocode pseudocode,
@NotNull TraversalOrder traversalOrder, @NotNull TraversalOrder traversalOrder,
@NotNull LookInsideStrategy lookInside, @NotNull LookInsideStrategy lookInside,
@NotNull Map<Instruction, Edges<D>> edgesMap, @NotNull Map<Instruction, Edges<Map<VariableDescriptor, D>>> edgesMap,
@NotNull InstructionDataMergeStrategy<D> instructionDataMergeStrategy, @NotNull InstructionDataMergeStrategy<Map<VariableDescriptor, D>> instructionDataMergeStrategy,
@NotNull Collection<Instruction> previousSubGraphInstructions, @NotNull Collection<Instruction> previousSubGraphInstructions,
boolean[] changed, boolean[] changed,
boolean isLocal boolean isLocal
@@ -109,25 +105,25 @@ public class PseudocodeVariableDataCollector extends PseudocodeTraverser {
previousInstructions, previousInstructions,
changed, true); changed, true);
Instruction lastInstruction = getLastInstruction(subroutinePseudocode, traversalOrder); Instruction lastInstruction = getLastInstruction(subroutinePseudocode, traversalOrder);
Edges<D> previousValue = edgesMap.get(instruction); Edges<Map<VariableDescriptor, D>> previousValue = edgesMap.get(instruction);
Edges<D> newValue = edgesMap.get(lastInstruction); Edges<Map<VariableDescriptor, D>> newValue = edgesMap.get(lastInstruction);
if (!previousValue.equals(newValue)) { if (!previousValue.equals(newValue)) {
changed[0] = true; changed[0] = true;
edgesMap.put(instruction, newValue); edgesMap.put(instruction, newValue);
} }
continue; continue;
} }
Edges<D> previousDataValue = edgesMap.get(instruction); Edges<Map<VariableDescriptor, D>> previousDataValue = edgesMap.get(instruction);
Collection<D> incomingEdgesData = Sets.newHashSet(); Collection<Map<VariableDescriptor, D>> incomingEdgesData = Sets.newHashSet();
for (Instruction previousInstruction : allPreviousInstructions) { for (Instruction previousInstruction : allPreviousInstructions) {
Edges<D> previousData = edgesMap.get(previousInstruction); Edges<Map<VariableDescriptor, D>> previousData = edgesMap.get(previousInstruction);
if (previousData != null) { if (previousData != null) {
incomingEdgesData.add(previousData.out); incomingEdgesData.add(previousData.out);
} }
} }
Edges<D> mergedData = instructionDataMergeStrategy.execute(instruction, incomingEdgesData); Edges<Map<VariableDescriptor, D>> mergedData = instructionDataMergeStrategy.execute(instruction, incomingEdgesData);
if (!mergedData.equals(previousDataValue)) { if (!mergedData.equals(previousDataValue)) {
changed[0] = true; changed[0] = true;
edgesMap.put(instruction, mergedData); edgesMap.put(instruction, mergedData);
@@ -20,16 +20,21 @@ import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
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.PseudocodeTraverser.*; import org.jetbrains.jet.lang.cfg.PseudocodeTraverser.Edges;
import org.jetbrains.jet.lang.cfg.PseudocodeTraverser.InstructionAnalyzeStrategy;
import org.jetbrains.jet.lang.cfg.PseudocodeTraverser.InstructionDataMergeStrategy;
import org.jetbrains.jet.lang.cfg.pseudocode.*; import org.jetbrains.jet.lang.cfg.pseudocode.*;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.psi.JetDeclaration; import org.jetbrains.jet.lang.psi.JetDeclaration;
import org.jetbrains.jet.lang.psi.JetProperty; import org.jetbrains.jet.lang.psi.JetProperty;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import java.util.*; import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import static org.jetbrains.jet.lang.cfg.PseudocodeTraverser.LookInsideStrategy.ANALYSE_LOCAL_DECLARATIONS;
import static org.jetbrains.jet.lang.cfg.PseudocodeTraverser.TraversalOrder.BACKWARD; 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.PseudocodeTraverser.TraversalOrder.FORWARD;
@@ -129,9 +134,9 @@ public class PseudocodeVariablesData {
private Map<Instruction, Edges<Map<VariableDescriptor, VariableInitState>>> getVariableInitializers(@NotNull Pseudocode pseudocode) { private Map<Instruction, Edges<Map<VariableDescriptor, VariableInitState>>> getVariableInitializers(@NotNull Pseudocode pseudocode) {
final Set<VariableDescriptor> declaredVariables = getDeclaredVariables(pseudocode, true); final Set<VariableDescriptor> declaredVariables = getDeclaredVariables(pseudocode, true);
Map<VariableDescriptor, VariableInitState> initialMap = Collections.emptyMap();
InstructionDataMergeStrategy<Map<VariableDescriptor, VariableInitState>> instructionDataMergeStrategy = return new PseudocodeVariableDataCollector(bindingContext).collectData(
pseudocode, FORWARD,
new InstructionDataMergeStrategy<Map<VariableDescriptor, VariableInitState>>() { new InstructionDataMergeStrategy<Map<VariableDescriptor, VariableInitState>>() {
@Override @Override
public Edges<Map<VariableDescriptor, VariableInitState>> execute( public Edges<Map<VariableDescriptor, VariableInitState>> execute(
@@ -145,11 +150,7 @@ public class PseudocodeVariablesData {
addVariableInitStateFromCurrentInstructionIfAny(instruction, enterInstructionData, declaredVariables); addVariableInitStateFromCurrentInstructionIfAny(instruction, enterInstructionData, declaredVariables);
return Edges.create(enterInstructionData, exitInstructionData); return Edges.create(enterInstructionData, exitInstructionData);
} }
}; });
return new PseudocodeVariableDataCollector(bindingContext).collectData(
pseudocode, FORWARD, ANALYSE_LOCAL_DECLARATIONS,
initialMap, initialMap, instructionDataMergeStrategy);
} }
public static VariableInitState getDefaultValueForInitializers( public static VariableInitState getDefaultValueForInitializers(
@@ -228,8 +229,8 @@ public class PseudocodeVariablesData {
@NotNull @NotNull
public Map<Instruction, Edges<Map<VariableDescriptor, VariableUseState>>> getVariableUseStatusData() { public Map<Instruction, Edges<Map<VariableDescriptor, VariableUseState>>> getVariableUseStatusData() {
Map<VariableDescriptor, VariableUseState> sinkInstructionData = Maps.newHashMap(); return new PseudocodeVariableDataCollector(bindingContext).collectData(
InstructionDataMergeStrategy<Map<VariableDescriptor, VariableUseState>> collectVariableUseStatusStrategy = pseudocode, BACKWARD,
new InstructionDataMergeStrategy<Map<VariableDescriptor, VariableUseState>>() { new InstructionDataMergeStrategy<Map<VariableDescriptor, VariableUseState>>() {
@Override @Override
public Edges<Map<VariableDescriptor, VariableUseState>> execute( public Edges<Map<VariableDescriptor, VariableUseState>> execute(
@@ -272,10 +273,7 @@ public class PseudocodeVariablesData {
} }
return Edges.create(enterResult, exitResult); return Edges.create(enterResult, exitResult);
} }
}; });
return new PseudocodeVariableDataCollector(bindingContext).collectData(
pseudocode, BACKWARD, ANALYSE_LOCAL_DECLARATIONS, Collections.<VariableDescriptor, VariableUseState>emptyMap(),
sinkInstructionData, collectVariableUseStatusStrategy);
} }
public static class VariableInitState { public static class VariableInitState {