Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.cfg.pseudocodeTraverser
import org.jetbrains.kotlin.cfg.ControlFlowInfo
import org.jetbrains.kotlin.cfg.pseudocode.*
import java.util.*
import org.jetbrains.kotlin.cfg.pseudocodeTraverser.TraversalOrder.FORWARD
import org.jetbrains.kotlin.cfg.pseudocode.instructions.special.SubroutineSinkInstruction
import org.jetbrains.kotlin.cfg.pseudocode.instructions.special.LocalFunctionDeclarationInstruction
import org.jetbrains.kotlin.cfg.pseudocode.instructions.Instruction
import org.jetbrains.kotlin.cfg.pseudocode.instructions.special.SubroutineEnterInstruction
fun Pseudocode.traverse(
traversalOrder: TraversalOrder,
analyzeInstruction: (Instruction) -> Unit
) {
val instructions = getInstructions(traversalOrder)
for (instruction in instructions) {
if (instruction is LocalFunctionDeclarationInstruction) {
instruction.body.traverse(traversalOrder, analyzeInstruction)
}
analyzeInstruction(instruction)
}
}
fun Pseudocode.traverse(
traversalOrder: TraversalOrder,
edgesMap: Map>,
analyzeInstruction: (Instruction, D, D) -> Unit
) {
val instructions = getInstructions(traversalOrder)
for (instruction in instructions) {
if (instruction is LocalFunctionDeclarationInstruction) {
instruction.body.traverse(traversalOrder, edgesMap, analyzeInstruction)
}
val edges = edgesMap.get(instruction)
if (edges != null) {
analyzeInstruction(instruction, edges.incoming, edges.outgoing)
}
}
}
fun > Pseudocode.collectData(
traversalOrder: TraversalOrder,
mergeDataWithLocalDeclarations: Boolean,
mergeEdges: (Instruction, Collection) -> Edges,
updateEdge: (Instruction, Instruction, I) -> I,
initialInfo: I
): Map> {
val edgesMap = LinkedHashMap>()
initializeEdgesMap(edgesMap, initialInfo)
edgesMap.put(getStartInstruction(traversalOrder), Edges(initialInfo, initialInfo))
val changed = BooleanArray(1)
changed[0] = true
while (changed[0]) {
changed[0] = false
collectDataFromSubgraph(
traversalOrder, mergeDataWithLocalDeclarations, edgesMap,
mergeEdges, updateEdge, Collections.emptyList(), changed, false)
}
return edgesMap
}
private fun Pseudocode.initializeEdgesMap(
edgesMap: MutableMap>,
initialInfo: I
) {
val instructions = instructions
val initialEdge = Edges(initialInfo, initialInfo)
for (instruction in instructions) {
edgesMap.put(instruction, initialEdge)
if (instruction is LocalFunctionDeclarationInstruction) {
instruction.body.initializeEdgesMap(edgesMap, initialInfo)
}
}
}
private fun > Pseudocode.collectDataFromSubgraph(
traversalOrder: TraversalOrder,
mergeDataWithLocalDeclarations: Boolean,
edgesMap: MutableMap>,
mergeEdges: (Instruction, Collection) -> Edges,
updateEdge: (Instruction, Instruction, I) -> I,
previousSubGraphInstructions: Collection,
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 {
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?,
newValue: Edges?
) {
if (previousValue != newValue && newValue != null) {
changed[0] = true
edgesMap.put(instruction, newValue)
}
}
if (instruction is LocalFunctionDeclarationInstruction) {
val subroutinePseudocode = instruction.body
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.incoming),
updateEdge(lastInstruction, instruction, newValue.outgoing))
updateEdgeDataForInstruction(previousValue, updatedValue)
continue
}
}
val previousDataValue = edgesMap.get(instruction)
val incomingEdgesData = HashSet()
for (previousInstruction in previousInstructions) {
val previousData = edgesMap.get(previousInstruction)
if (previousData != null) {
incomingEdgesData.add(updateEdge(
previousInstruction, instruction, previousData.outgoing))
}
}
val mergedData = mergeEdges(instruction, incomingEdgesData)
updateEdgeDataForInstruction(previousDataValue, mergedData)
}
}
data class Edges(val incoming: T, val outgoing: T)
enum class TraverseInstructionResult {
CONTINUE,
SKIP,
HALT
}
// returns false when interrupted by handler
fun traverseFollowingInstructions(
rootInstruction: Instruction,
visited: MutableSet,
order: TraversalOrder,
// true to continue traversal
handler: ((Instruction) -> TraverseInstructionResult)?
): Boolean {
val stack = ArrayDeque()
stack.push(rootInstruction)
while (!stack.isEmpty()) {
val instruction = stack.pop()
if (!visited.add(instruction)) continue
when (handler?.let { it(instruction) } ?: TraverseInstructionResult.CONTINUE) {
TraverseInstructionResult.CONTINUE -> instruction.getNextInstructions(order).forEach { stack.push(it) }
TraverseInstructionResult.SKIP -> {}
TraverseInstructionResult.HALT -> return false
}
}
return true
}
enum class TraversalOrder {
FORWARD,
BACKWARD
}
fun Pseudocode.getStartInstruction(traversalOrder: TraversalOrder): Instruction =
if (traversalOrder == FORWARD) enterInstruction else sinkInstruction
fun Pseudocode.getLastInstruction(traversalOrder: TraversalOrder): Instruction =
if (traversalOrder == FORWARD) sinkInstruction else enterInstruction
fun Pseudocode.getInstructions(traversalOrder: TraversalOrder): MutableList =
if (traversalOrder == FORWARD) instructions else reversedInstructions
fun Instruction.getNextInstructions(traversalOrder: TraversalOrder): Collection =
if (traversalOrder == FORWARD) nextInstructions else previousInstructions
fun Instruction.getPreviousInstructions(traversalOrder: TraversalOrder): Collection =
if (traversalOrder == FORWARD) previousInstructions else nextInstructions
fun Instruction.isStartInstruction(traversalOrder: TraversalOrder): Boolean =
if (traversalOrder == FORWARD) this is SubroutineEnterInstruction else this is SubroutineSinkInstruction