rollback: moved 'collectData' to PseudocodeTraverser
This commit is contained in:
@@ -74,6 +74,117 @@ fun <D> Pseudocode.traverse(
|
||||
}
|
||||
}
|
||||
|
||||
public fun <D> Pseudocode.collectData(
|
||||
traversalOrder: TraversalOrder,
|
||||
mergeDataWithLocalDeclarations: Boolean,
|
||||
mergeEdges: (Instruction, Collection<D>) -> Edges<D>,
|
||||
updateEdge: (Instruction, Instruction, D) -> D,
|
||||
initialDataValue: D
|
||||
): Map<Instruction, Edges<D>> {
|
||||
val edgesMap = LinkedHashMap<Instruction, Edges<D>>()
|
||||
initializeEdgesMap(edgesMap, initialDataValue)
|
||||
edgesMap.put(getStartInstruction(traversalOrder), Edges(initialDataValue, initialDataValue))
|
||||
|
||||
val changed = BooleanArray(1)
|
||||
changed[0] = true
|
||||
while (changed[0]) {
|
||||
changed[0] = false
|
||||
collectDataFromSubgraph(
|
||||
traversalOrder, mergeDataWithLocalDeclarations, edgesMap,
|
||||
mergeEdges, updateEdge, Collections.emptyList<Instruction>(), changed, false)
|
||||
}
|
||||
return edgesMap
|
||||
}
|
||||
|
||||
private fun <D> Pseudocode.initializeEdgesMap(
|
||||
edgesMap: MutableMap<Instruction, Edges<D>>,
|
||||
initialDataValue: D
|
||||
) {
|
||||
val instructions = getInstructions()
|
||||
val initialEdge = Edges(initialDataValue, initialDataValue)
|
||||
for (instruction in instructions) {
|
||||
edgesMap.put(instruction, initialEdge)
|
||||
if (instruction is LocalFunctionDeclarationInstruction) {
|
||||
instruction.getBody().initializeEdgesMap(edgesMap, initialDataValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun <D> Pseudocode.collectDataFromSubgraph(
|
||||
traversalOrder: TraversalOrder,
|
||||
mergeDataWithLocalDeclarations: Boolean,
|
||||
edgesMap: MutableMap<Instruction, Edges<D>>,
|
||||
mergeEdges: (Instruction, Collection<D>) -> Edges<D>,
|
||||
updateEdge: (Instruction, Instruction, D) -> D,
|
||||
previousSubGraphInstructions: Collection<Instruction>,
|
||||
changed: BooleanArray,
|
||||
isLocal: Boolean
|
||||
) {
|
||||
val instructions = getInstructions(traversalOrder)
|
||||
val startInstruction = getStartInstruction(traversalOrder)
|
||||
|
||||
for (instruction in instructions) {
|
||||
val isStart = instruction.isStartInstruction(traversalOrder)
|
||||
if (!isLocal && isStart)
|
||||
continue
|
||||
|
||||
fun getPreviousIncludingSubGraphInstructions(): Collection<Instruction> {
|
||||
val previous = instruction.getPreviousInstructions(traversalOrder)
|
||||
if (instruction != startInstruction || previousSubGraphInstructions.isEmpty()) {
|
||||
return previous
|
||||
}
|
||||
val result = ArrayList(previous)
|
||||
result.addAll(previousSubGraphInstructions)
|
||||
return result
|
||||
}
|
||||
val previousInstructions = getPreviousIncludingSubGraphInstructions()
|
||||
|
||||
fun updateEdgeDataForInstruction(
|
||||
previousValue: Edges<D>?,
|
||||
newValue: Edges<D>?
|
||||
) {
|
||||
if (previousValue != newValue && newValue != null) {
|
||||
changed[0] = true
|
||||
edgesMap.put(instruction, newValue)
|
||||
}
|
||||
}
|
||||
|
||||
if (instruction is LocalFunctionDeclarationInstruction) {
|
||||
val subroutinePseudocode = instruction.getBody()
|
||||
val previous = if (mergeDataWithLocalDeclarations) previousInstructions else Collections.emptyList()
|
||||
subroutinePseudocode.collectDataFromSubgraph(
|
||||
traversalOrder, mergeDataWithLocalDeclarations,
|
||||
edgesMap, mergeEdges, updateEdge, previous, changed, true)
|
||||
if (mergeDataWithLocalDeclarations) {
|
||||
val lastInstruction = subroutinePseudocode.getLastInstruction(traversalOrder)
|
||||
val previousValue = edgesMap.get(instruction)
|
||||
val newValue = edgesMap.get(lastInstruction)
|
||||
val updatedValue =
|
||||
if (newValue == null)
|
||||
null
|
||||
else
|
||||
Edges(updateEdge(lastInstruction, instruction, newValue.`in`),
|
||||
updateEdge(lastInstruction, instruction, newValue.out))
|
||||
updateEdgeDataForInstruction(previousValue, updatedValue)
|
||||
continue
|
||||
}
|
||||
}
|
||||
val previousDataValue = edgesMap.get(instruction)
|
||||
|
||||
val incomingEdgesData = HashSet<D>()
|
||||
|
||||
for (previousInstruction in previousInstructions) {
|
||||
val previousData = edgesMap.get(previousInstruction)
|
||||
if (previousData != null) {
|
||||
incomingEdgesData.add(updateEdge(
|
||||
previousInstruction, instruction, previousData.out))
|
||||
}
|
||||
}
|
||||
val mergedData = mergeEdges(instruction, incomingEdgesData)
|
||||
updateEdgeDataForInstruction(previousDataValue, mergedData)
|
||||
}
|
||||
}
|
||||
|
||||
trait InstructionDataMergeStrategy<D> : (Instruction, Collection<D>) -> Edges<D>
|
||||
trait InstructionDataAnalyzeStrategy<D> : (Instruction, D, D) -> Unit
|
||||
|
||||
@@ -87,7 +198,7 @@ fun traverseFollowingInstructions(
|
||||
visited: MutableSet<Instruction>,
|
||||
order: TraversalOrder,
|
||||
// true to continue traversal
|
||||
handler: ((Instruction)->Boolean)?
|
||||
handler: ((Instruction) -> Boolean)?
|
||||
): Boolean {
|
||||
val stack = ArrayDeque<Instruction>()
|
||||
stack.push(rootInstruction)
|
||||
|
||||
+7
-113
@@ -38,124 +38,18 @@ public class PseudocodeVariableDataCollector(
|
||||
val lexicalScopeVariableInfo = computeLexicalScopeVariableInfo(pseudocode)
|
||||
|
||||
suppress("UNCHECKED_CAST")
|
||||
public fun <D> collectDataJ(
|
||||
public fun <D> collectData(
|
||||
traversalOrder: TraversalOrder,
|
||||
mergeDataWithLocalDeclarations: Boolean,
|
||||
instructionDataMergeStrategy: InstructionDataMergeStrategy<MutableMap<VariableDescriptor, D>>
|
||||
): MutableMap<Instruction, Edges<MutableMap<VariableDescriptor, D>>> {
|
||||
//see KT-4605
|
||||
return collectData(
|
||||
val result = pseudocode.collectData(
|
||||
traversalOrder, mergeDataWithLocalDeclarations,
|
||||
instructionDataMergeStrategy as InstructionDataMergeStrategy<Map<VariableDescriptor, D>>
|
||||
) as MutableMap<Instruction, Edges<MutableMap<VariableDescriptor, D>>>
|
||||
}
|
||||
|
||||
public fun <D> collectData(
|
||||
traversalOrder: TraversalOrder,
|
||||
mergeDataWithLocalDeclarations: Boolean,
|
||||
instructionDataMergeStrategy: InstructionDataMergeStrategy<Map<VariableDescriptor, D>>
|
||||
): Map<Instruction, Edges<Map<VariableDescriptor, D>>> {
|
||||
val initialDataValue : Map<VariableDescriptor, D> = Collections.emptyMap<VariableDescriptor, D>()
|
||||
val edgesMap = LinkedHashMap<Instruction, Edges<Map<VariableDescriptor, D>>>()
|
||||
initializeEdgesMap(pseudocode, edgesMap, initialDataValue)
|
||||
edgesMap.put(pseudocode.getStartInstruction(traversalOrder), Edges(initialDataValue, initialDataValue))
|
||||
|
||||
val changed = BooleanArray(1)
|
||||
changed[0] = true
|
||||
while (changed[0]) {
|
||||
changed[0] = false
|
||||
collectDataFromSubgraph(
|
||||
pseudocode, traversalOrder, mergeDataWithLocalDeclarations, edgesMap,
|
||||
instructionDataMergeStrategy, Collections.emptyList<Instruction>(), changed, false)
|
||||
}
|
||||
return edgesMap
|
||||
}
|
||||
|
||||
private fun <M> initializeEdgesMap(
|
||||
pseudocode: Pseudocode,
|
||||
edgesMap: MutableMap<Instruction, Edges<M>>,
|
||||
initialDataValue: M
|
||||
) {
|
||||
val instructions = pseudocode.getInstructions()
|
||||
val initialEdge = Edges(initialDataValue, initialDataValue)
|
||||
for (instruction in instructions) {
|
||||
edgesMap.put(instruction, initialEdge)
|
||||
if (instruction is LocalFunctionDeclarationInstruction) {
|
||||
initializeEdgesMap(instruction.getBody(), edgesMap, initialDataValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun <D> collectDataFromSubgraph(
|
||||
pseudocode: Pseudocode,
|
||||
traversalOrder: TraversalOrder,
|
||||
mergeDataWithLocalDeclarations: Boolean,
|
||||
edgesMap: MutableMap<Instruction, Edges<Map<VariableDescriptor, D>>>,
|
||||
instructionDataMergeStrategy: InstructionDataMergeStrategy<Map<VariableDescriptor, D>>,
|
||||
previousSubGraphInstructions: Collection<Instruction>,
|
||||
changed: BooleanArray,
|
||||
isLocal: Boolean
|
||||
) {
|
||||
val instructions = pseudocode.getInstructions(traversalOrder)
|
||||
val startInstruction = pseudocode.getStartInstruction(traversalOrder)
|
||||
|
||||
for (instruction in instructions) {
|
||||
val isStart = instruction.isStartInstruction(traversalOrder)
|
||||
if (!isLocal && isStart)
|
||||
continue
|
||||
|
||||
fun getPreviousIncludingSubGraphInstructions(): Collection<Instruction> {
|
||||
val previous = instruction.getPreviousInstructions(traversalOrder)
|
||||
if (instruction != startInstruction || previousSubGraphInstructions.isEmpty()) {
|
||||
return previous
|
||||
}
|
||||
val result = ArrayList(previous)
|
||||
result.addAll(previousSubGraphInstructions)
|
||||
return result
|
||||
}
|
||||
val previousInstructions = getPreviousIncludingSubGraphInstructions()
|
||||
|
||||
fun updateEdgeDataForInstruction(
|
||||
previousValue: Edges<Map<VariableDescriptor, D>>?,
|
||||
newValue: Edges<Map<VariableDescriptor, D>>?
|
||||
) {
|
||||
if (previousValue != newValue && newValue != null) {
|
||||
changed[0] = true
|
||||
edgesMap.put(instruction, newValue)
|
||||
}
|
||||
}
|
||||
|
||||
if (instruction is LocalFunctionDeclarationInstruction) {
|
||||
val subroutinePseudocode = instruction.getBody()
|
||||
val previous = if (mergeDataWithLocalDeclarations) previousInstructions else Collections.emptyList()
|
||||
collectDataFromSubgraph(
|
||||
subroutinePseudocode, traversalOrder, mergeDataWithLocalDeclarations,
|
||||
edgesMap, instructionDataMergeStrategy, previous, changed, true)
|
||||
if (mergeDataWithLocalDeclarations) {
|
||||
val lastInstruction = subroutinePseudocode.getLastInstruction(traversalOrder)
|
||||
val previousValue = edgesMap.get(instruction)
|
||||
val newValue = edgesMap.get(lastInstruction)
|
||||
val updatedValue = if (newValue == null) null else
|
||||
Edges(filterOutVariablesOutOfScope(lastInstruction, instruction, newValue.`in`),
|
||||
filterOutVariablesOutOfScope(lastInstruction, instruction, newValue.out))
|
||||
updateEdgeDataForInstruction(previousValue, updatedValue)
|
||||
continue
|
||||
}
|
||||
}
|
||||
val previousDataValue = edgesMap.get(instruction)
|
||||
|
||||
val incomingEdgesData = HashSet<Map<VariableDescriptor, D>>()
|
||||
|
||||
for (previousInstruction in previousInstructions) {
|
||||
val previousData = edgesMap.get(previousInstruction)
|
||||
if (previousData != null) {
|
||||
incomingEdgesData.add(filterOutVariablesOutOfScope(
|
||||
previousInstruction, instruction, previousData.out))
|
||||
}
|
||||
}
|
||||
val mergedData = instructionDataMergeStrategy(instruction, incomingEdgesData)
|
||||
updateEdgeDataForInstruction(previousDataValue, mergedData)
|
||||
}
|
||||
instructionDataMergeStrategy as InstructionDataMergeStrategy<Map<VariableDescriptor, D>>,
|
||||
{ (from, to, data) -> filterOutVariablesOutOfScope(from, to, data)},
|
||||
Collections.emptyMap<VariableDescriptor, D>())
|
||||
//see KT-4605
|
||||
return result as MutableMap<Instruction, Edges<MutableMap<VariableDescriptor, D>>>
|
||||
}
|
||||
|
||||
private fun <D> filterOutVariablesOutOfScope(
|
||||
|
||||
@@ -146,7 +146,7 @@ public class PseudocodeVariablesData {
|
||||
|
||||
final LexicalScopeVariableInfo lexicalScopeVariableInfo = pseudocodeVariableDataCollector.getLexicalScopeVariableInfo();
|
||||
|
||||
return pseudocodeVariableDataCollector.collectDataJ(
|
||||
return pseudocodeVariableDataCollector.collectData(
|
||||
FORWARD, /*mergeDataWithLocalDeclarations=*/ false,
|
||||
new InstructionDataMergeStrategy<Map<VariableDescriptor, VariableInitState>>() {
|
||||
@NotNull
|
||||
@@ -159,7 +159,7 @@ public class PseudocodeVariablesData {
|
||||
Map<VariableDescriptor, VariableInitState> enterInstructionData =
|
||||
mergeIncomingEdgesDataForInitializers(incomingEdgesData);
|
||||
Map<VariableDescriptor, VariableInitState> exitInstructionData = addVariableInitStateFromCurrentInstructionIfAny(
|
||||
instruction, enterInstructionData, lexicalScopeVariableInfo);
|
||||
instruction, enterInstructionData, lexicalScopeVariableInfo);
|
||||
return createEdges(enterInstructionData, exitInstructionData);
|
||||
}
|
||||
}
|
||||
@@ -246,7 +246,7 @@ public class PseudocodeVariablesData {
|
||||
|
||||
@NotNull
|
||||
public Map<Instruction, Edges<Map<VariableDescriptor, VariableUseState>>> getVariableUseStatusData() {
|
||||
return pseudocodeVariableDataCollector.collectDataJ(
|
||||
return pseudocodeVariableDataCollector.collectData(
|
||||
BACKWARD, /*mergeDataWithLocalDeclarations=*/ true,
|
||||
new InstructionDataMergeStrategy<Map<VariableDescriptor, VariableUseState>>() {
|
||||
@NotNull
|
||||
|
||||
Reference in New Issue
Block a user