rewrote PseudocodeVariableDataCollector to kotlin

This commit is contained in:
Svetlana Isakova
2014-02-22 17:33:07 +04:00
parent 1f37a2120e
commit 11c953c220
3 changed files with 100 additions and 82 deletions
@@ -101,6 +101,7 @@ public class PseudocodeTraverser {
} }
public interface InstructionDataMergeStrategy<D> { public interface InstructionDataMergeStrategy<D> {
@NotNull
Edges<D> execute(@NotNull Instruction instruction, @NotNull Collection<D> incomingEdgesData); Edges<D> execute(@NotNull Instruction instruction, @NotNull Collection<D> incomingEdgesData);
} }
@@ -113,7 +114,9 @@ public class PseudocodeTraverser {
} }
public static class Edges<T> { public static class Edges<T> {
@NotNull
public final T in; public final T in;
@NotNull
public final T out; public final T out;
Edges(@NotNull T in, @NotNull T out) { Edges(@NotNull T in, @NotNull T out) {
@@ -121,6 +124,7 @@ public class PseudocodeTraverser {
this.out = out; this.out = out;
} }
@NotNull
public static <T> Edges<T> create(@NotNull T in, @NotNull T out) { public static <T> Edges<T> create(@NotNull T in, @NotNull T out) {
return new Edges<T>(in, out); return new Edges<T>(in, out);
} }
@@ -14,119 +14,130 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.jet.lang.cfg; package org.jetbrains.jet.lang.cfg
import com.google.common.collect.Lists; import org.jetbrains.jet.lang.cfg.pseudocode.Instruction
import com.google.common.collect.Maps; import org.jetbrains.jet.lang.cfg.pseudocode.LocalFunctionDeclarationInstruction
import com.google.common.collect.Sets; import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode
import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor
import org.jetbrains.jet.lang.cfg.pseudocode.Instruction; import org.jetbrains.jet.lang.descriptors.VariableDescriptor
import org.jetbrains.jet.lang.cfg.pseudocode.LocalFunctionDeclarationInstruction; import org.jetbrains.jet.lang.psi.JetElement
import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode; import org.jetbrains.jet.lang.resolve.BindingContext
import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.resolve.DescriptorUtils
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.cfg.PseudocodeTraverser.*
import java.util.*; import java.util.*
public class PseudocodeVariableDataCollector extends PseudocodeTraverser { public class PseudocodeVariableDataCollector(private val bindingContext: BindingContext) : PseudocodeTraverser() {
private final BindingContext bindingContext;
public PseudocodeVariableDataCollector(@NotNull BindingContext context) { suppress("UNCHECKED_CAST")
bindingContext = context; public fun <D> collectDataJ(
pseudocode: Pseudocode,
traversalOrder: TraversalOrder,
instructionDataMergeStrategy: InstructionDataMergeStrategy<MutableMap<VariableDescriptor, D>>
): MutableMap<Instruction, Edges<MutableMap<VariableDescriptor, D>>> {
//see KT-4605
return collectData(
pseudocode, traversalOrder,
instructionDataMergeStrategy as InstructionDataMergeStrategy<Map<VariableDescriptor, D>>
) as MutableMap<Instruction, Edges<MutableMap<VariableDescriptor, D>>>
} }
public <D> Map<Instruction, Edges<Map<VariableDescriptor, D>>> collectData( public fun <D> collectData(
@NotNull Pseudocode pseudocode, pseudocode: Pseudocode,
@NotNull TraversalOrder traversalOrder, traversalOrder: TraversalOrder,
@NotNull InstructionDataMergeStrategy<Map<VariableDescriptor, D>> instructionDataMergeStrategy instructionDataMergeStrategy: InstructionDataMergeStrategy<Map<VariableDescriptor, D>>
) { ): Map<Instruction, Edges<Map<VariableDescriptor, D>>> {
Map<VariableDescriptor, D> initialDataValue = Collections.emptyMap(); val initialDataValue : Map<VariableDescriptor, D> = Collections.emptyMap<VariableDescriptor, D>()
Map<Instruction, Edges<Map<VariableDescriptor, D>>> edgesMap = Maps.newLinkedHashMap(); val edgesMap = LinkedHashMap<Instruction, Edges<Map<VariableDescriptor, D>>>()
initializeEdgesMap(pseudocode, edgesMap, initialDataValue); initializeEdgesMap(pseudocode, edgesMap, initialDataValue)
edgesMap.put(getStartInstruction(pseudocode, traversalOrder), Edges.create(initialDataValue, initialDataValue)); edgesMap.put(getStartInstruction(pseudocode, traversalOrder),
Edges.create(initialDataValue, initialDataValue))
boolean[] changed = new boolean[1]; val changed = BooleanArray(1)
changed[0] = true; changed[0] = true
while (changed[0]) { while (changed[0]) {
changed[0] = false; changed[0] = false
collectDataFromSubgraph(pseudocode, traversalOrder, LookInsideStrategy.ANALYSE_LOCAL_DECLARATIONS, edgesMap, collectDataFromSubgraph(
instructionDataMergeStrategy, Collections.<Instruction>emptyList(), changed, false); pseudocode, traversalOrder, LookInsideStrategy.ANALYSE_LOCAL_DECLARATIONS, edgesMap,
instructionDataMergeStrategy, Collections.emptyList<Instruction>(), changed, false)
} }
return edgesMap; return edgesMap
} }
private static <M> void initializeEdgesMap( private fun <M> initializeEdgesMap(
@NotNull Pseudocode pseudocode, pseudocode: Pseudocode,
@NotNull Map<Instruction, Edges<M>> edgesMap, edgesMap: MutableMap<Instruction, Edges<M>>,
@NotNull M initialDataValue initialDataValue: M
) { ) {
List<Instruction> instructions = pseudocode.getInstructions(); val instructions = pseudocode.getInstructions()
Edges<M> initialEdge = Edges.create(initialDataValue, initialDataValue); val initialEdge = Edges.create(initialDataValue, initialDataValue)
for (Instruction instruction : instructions) { for (instruction in instructions) {
edgesMap.put(instruction, initialEdge); edgesMap.put(instruction, initialEdge)
if (shouldLookInside(instruction, LookInsideStrategy.ANALYSE_LOCAL_DECLARATIONS)) { if (PseudocodeTraverser.shouldLookInside(instruction, LookInsideStrategy.ANALYSE_LOCAL_DECLARATIONS)) {
initializeEdgesMap(((LocalFunctionDeclarationInstruction) instruction).getBody(), edgesMap, initialDataValue); initializeEdgesMap(((instruction as LocalFunctionDeclarationInstruction)).getBody(), edgesMap, initialDataValue)
} }
} }
} }
private <D> void collectDataFromSubgraph( private fun <D> collectDataFromSubgraph(
@NotNull Pseudocode pseudocode, pseudocode: Pseudocode,
@NotNull TraversalOrder traversalOrder, traversalOrder: TraversalOrder,
@NotNull LookInsideStrategy lookInside, lookInside: LookInsideStrategy,
@NotNull Map<Instruction, Edges<Map<VariableDescriptor, D>>> edgesMap, edgesMap: MutableMap<Instruction, Edges<Map<VariableDescriptor, D>>>,
@NotNull InstructionDataMergeStrategy<Map<VariableDescriptor, D>> instructionDataMergeStrategy, instructionDataMergeStrategy: InstructionDataMergeStrategy<Map<VariableDescriptor, D>>,
@NotNull Collection<Instruction> previousSubGraphInstructions, previousSubGraphInstructions: Collection<Instruction>,
boolean[] changed, changed: BooleanArray,
boolean isLocal isLocal: Boolean
) { ) {
List<Instruction> instructions = getInstructions(pseudocode, traversalOrder); val instructions = getInstructions(pseudocode, traversalOrder)
Instruction startInstruction = getStartInstruction(pseudocode, traversalOrder); val startInstruction = getStartInstruction(pseudocode, traversalOrder)
for (Instruction instruction : instructions) { for (instruction in instructions) {
boolean isStart = isStartInstruction(instruction, traversalOrder); val isStart = isStartInstruction(instruction, traversalOrder)
if (!isLocal && isStart) continue; if (!isLocal && isStart)
continue
Collection<Instruction> allPreviousInstructions; val allPreviousInstructions: MutableCollection<Instruction>
Collection<Instruction> previousInstructions = getPreviousInstruction(instruction, traversalOrder); val previousInstructions = getPreviousInstruction(instruction, traversalOrder)
if (instruction == startInstruction && !previousSubGraphInstructions.isEmpty()) { if (instruction == startInstruction && !previousSubGraphInstructions.isEmpty()) {
allPreviousInstructions = Lists.newArrayList(previousInstructions); allPreviousInstructions = ArrayList(previousInstructions)
allPreviousInstructions.addAll(previousSubGraphInstructions); allPreviousInstructions.addAll(previousSubGraphInstructions)
} }
else { else {
allPreviousInstructions = previousInstructions; allPreviousInstructions = previousInstructions
} }
if (shouldLookInside(instruction, lookInside)) { if (shouldLookInside(instruction, lookInside)) {
LocalFunctionDeclarationInstruction functionInstruction = (LocalFunctionDeclarationInstruction) instruction; val functionInstruction = (instruction as LocalFunctionDeclarationInstruction)
Pseudocode subroutinePseudocode = functionInstruction.getBody(); val subroutinePseudocode = functionInstruction.getBody()
collectDataFromSubgraph(subroutinePseudocode, traversalOrder, lookInside, edgesMap, instructionDataMergeStrategy, collectDataFromSubgraph(
previousInstructions, subroutinePseudocode, traversalOrder, lookInside, edgesMap, instructionDataMergeStrategy,
changed, true); previousInstructions, changed, true)
Instruction lastInstruction = getLastInstruction(subroutinePseudocode, traversalOrder); val lastInstruction = getLastInstruction(subroutinePseudocode, traversalOrder)
Edges<Map<VariableDescriptor, D>> previousValue = edgesMap.get(instruction); val previousValue = edgesMap.get(instruction)
Edges<Map<VariableDescriptor, D>> newValue = edgesMap.get(lastInstruction); val newValue = edgesMap.get(lastInstruction)
if (!previousValue.equals(newValue)) { if (previousValue != newValue && newValue != null) {
changed[0] = true; changed[0] = true
edgesMap.put(instruction, newValue); edgesMap.put(instruction, newValue)
} }
continue; continue
} }
Edges<Map<VariableDescriptor, D>> previousDataValue = edgesMap.get(instruction); val previousDataValue = edgesMap.get(instruction)
Collection<Map<VariableDescriptor, D>> incomingEdgesData = Sets.newHashSet(); val incomingEdgesData = HashSet<Map<VariableDescriptor, D>>()
for (Instruction previousInstruction : allPreviousInstructions) { for (previousInstruction in allPreviousInstructions) {
Edges<Map<VariableDescriptor, D>> previousData = edgesMap.get(previousInstruction); val previousData = edgesMap.get(previousInstruction)
if (previousData != null) { if (previousData != null) {
incomingEdgesData.add(previousData.out); incomingEdgesData.add(previousData.out)
} }
} }
Edges<Map<VariableDescriptor, D>> mergedData = instructionDataMergeStrategy.execute(instruction, incomingEdgesData); val 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)
} }
} }
} }
@@ -135,9 +135,10 @@ public class PseudocodeVariablesData {
final Set<VariableDescriptor> declaredVariables = getDeclaredVariables(pseudocode, true); final Set<VariableDescriptor> declaredVariables = getDeclaredVariables(pseudocode, true);
return new PseudocodeVariableDataCollector(bindingContext).collectData( return new PseudocodeVariableDataCollector(bindingContext).collectDataJ(
pseudocode, FORWARD, pseudocode, FORWARD,
new InstructionDataMergeStrategy<Map<VariableDescriptor, VariableInitState>>() { new InstructionDataMergeStrategy<Map<VariableDescriptor, VariableInitState>>() {
@NotNull
@Override @Override
public Edges<Map<VariableDescriptor, VariableInitState>> execute( public Edges<Map<VariableDescriptor, VariableInitState>> execute(
@NotNull Instruction instruction, @NotNull Instruction instruction,
@@ -150,7 +151,8 @@ public class PseudocodeVariablesData {
addVariableInitStateFromCurrentInstructionIfAny(instruction, enterInstructionData, declaredVariables); addVariableInitStateFromCurrentInstructionIfAny(instruction, enterInstructionData, declaredVariables);
return Edges.create(enterInstructionData, exitInstructionData); return Edges.create(enterInstructionData, exitInstructionData);
} }
}); }
);
} }
public static VariableInitState getDefaultValueForInitializers( public static VariableInitState getDefaultValueForInitializers(
@@ -229,9 +231,10 @@ public class PseudocodeVariablesData {
@NotNull @NotNull
public Map<Instruction, Edges<Map<VariableDescriptor, VariableUseState>>> getVariableUseStatusData() { public Map<Instruction, Edges<Map<VariableDescriptor, VariableUseState>>> getVariableUseStatusData() {
return new PseudocodeVariableDataCollector(bindingContext).collectData( return new PseudocodeVariableDataCollector(bindingContext).collectDataJ(
pseudocode, BACKWARD, pseudocode, BACKWARD,
new InstructionDataMergeStrategy<Map<VariableDescriptor, VariableUseState>>() { new InstructionDataMergeStrategy<Map<VariableDescriptor, VariableUseState>>() {
@NotNull
@Override @Override
public Edges<Map<VariableDescriptor, VariableUseState>> execute( public Edges<Map<VariableDescriptor, VariableUseState>> execute(
@NotNull Instruction instruction, @NotNull Instruction instruction,