rewrote PseudocodeTraverser to kotlin

This commit is contained in:
Svetlana Isakova
2014-03-06 14:15:59 +04:00
parent 18eaf483d3
commit eed3dec539
7 changed files with 196 additions and 234 deletions
@@ -22,14 +22,17 @@ import com.google.common.collect.Sets;
import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import kotlin.Function1;
import kotlin.Unit;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.cfg.PseudocodeTraverser.Edges;
import org.jetbrains.jet.lang.cfg.PseudocodeTraverser.InstructionAnalyzeStrategy;
import org.jetbrains.jet.lang.cfg.PseudocodeTraverser.InstructionDataAnalyzeStrategy;
import org.jetbrains.jet.lang.cfg.pseudocodeTraverser.Edges;
import org.jetbrains.jet.lang.cfg.pseudocodeTraverser.InstructionDataAnalyzeStrategy;
import org.jetbrains.jet.lang.cfg.pseudocodeTraverser.PseudocodeTraverserPackage;
import org.jetbrains.jet.lang.cfg.PseudocodeVariablesData.VariableInitState;
import org.jetbrains.jet.lang.cfg.PseudocodeVariablesData.VariableUseState;
import org.jetbrains.jet.lang.cfg.pseudocode.*;
import org.jetbrains.jet.lang.cfg.pseudocodeTraverser.TraversalOrder;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory;
@@ -51,9 +54,8 @@ import org.jetbrains.jet.plugin.MainFunctionDetector;
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.pseudocodeTraverser.TraversalOrder.FORWARD;
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
import static org.jetbrains.jet.lang.resolve.calls.TailRecursionKind.*;
@@ -262,7 +264,9 @@ public class JetFlowInformationProvider {
final Map<Instruction, DiagnosticFactory> reportedDiagnosticMap = Maps.newHashMap();
PseudocodeTraverser.traverse(pseudocode, FORWARD, initializers, new InstructionDataAnalyzeStrategy<Map<VariableDescriptor, PseudocodeVariablesData.VariableInitState>>() {
PseudocodeTraverserPackage.traverse(
pseudocode, FORWARD, initializers,
new InstructionDataAnalyzeStrategyJ<Map<VariableDescriptor, PseudocodeVariablesData.VariableInitState>>() {
@Override
public void execute(@NotNull Instruction instruction,
@Nullable Map<VariableDescriptor, VariableInitState> in,
@@ -497,7 +501,7 @@ public class JetFlowInformationProvider {
Set<VariableDescriptor> declaredVariables = getPseudocodeVariablesData().getDeclaredVariables(pseudocode, false);
for (VariableDescriptor variable : declaredVariables) {
if (variable instanceof PropertyDescriptor) {
PseudocodeVariablesData.VariableInitState variableInitState = initializers.in.get(variable);
PseudocodeVariablesData.VariableInitState variableInitState = initializers.getIn().get(variable);
if (variableInitState == null) return;
trace.record(BindingContext.IS_INITIALIZED, (PropertyDescriptor) variable, variableInitState.isInitialized);
}
@@ -512,7 +516,7 @@ public class JetFlowInformationProvider {
Map<Instruction, Edges<Map<VariableDescriptor, VariableUseState>>> variableStatusData = pseudocodeVariablesData.getVariableUseStatusData();
final Map<Instruction, DiagnosticFactory> reportedDiagnosticMap = Maps.newHashMap();
InstructionDataAnalyzeStrategy<Map<VariableDescriptor, VariableUseState>> variableStatusAnalyzeStrategy =
new InstructionDataAnalyzeStrategy<Map<VariableDescriptor, PseudocodeVariablesData.VariableUseState>>() {
new InstructionDataAnalyzeStrategyJ<Map<VariableDescriptor, PseudocodeVariablesData.VariableUseState>>() {
@Override
public void execute(@NotNull Instruction instruction,
@Nullable Map<VariableDescriptor, VariableUseState> in,
@@ -586,7 +590,7 @@ public class JetFlowInformationProvider {
}
}
};
PseudocodeTraverser.traverse(pseudocode, BACKWARD, variableStatusData, variableStatusAnalyzeStrategy);
PseudocodeTraverserPackage.traverse(pseudocode, TraversalOrder.BACKWARD, variableStatusData, variableStatusAnalyzeStrategy);
}
////////////////////////////////////////////////////////////////////////////////
@@ -594,8 +598,8 @@ public class JetFlowInformationProvider {
public void markUnusedLiteralsInBlock() {
final Map<Instruction, DiagnosticFactory> reportedDiagnosticMap = Maps.newHashMap();
PseudocodeTraverser.traverse(
pseudocode, FORWARD, new InstructionAnalyzeStrategy() {
PseudocodeTraverserPackage.traverse(
pseudocode, FORWARD, new FunctionVoid1<Instruction>() {
@Override
public void execute(@NotNull Instruction instruction) {
if (!(instruction instanceof ReadValueInstruction)) return;
@@ -642,11 +646,10 @@ public class JetFlowInformationProvider {
}
}
final Map<JetElement, KindAndCall> calls = new HashMap<JetElement, KindAndCall>();
PseudocodeTraverser.traverse(
PseudocodeTraverserPackage.traverse(
pseudocode,
FORWARD,
new InstructionAnalyzeStrategy() {
@Override
new FunctionVoid1<Instruction>() {
public void execute(@NotNull Instruction instruction) {
if (!(instruction instanceof CallInstruction)) return;
CallInstruction callInstruction = (CallInstruction) instruction;
@@ -672,7 +675,7 @@ public class JetFlowInformationProvider {
return;
}
boolean isTail = PseudocodeTraverser.traverseFollowingInstructions(
boolean isTail = PseudocodeTraverserPackage.traverseFollowingInstructions(
callInstruction,
new HashSet<Instruction>(),
FORWARD,
@@ -879,4 +882,25 @@ public class JetFlowInformationProvider {
exitUseState = variableDescriptor != null ? out.get(variableDescriptor) : null;
}
}
//TODO after KT-4621 rewrite to Kotlin
public abstract static class InstructionDataAnalyzeStrategyJ<D> implements InstructionDataAnalyzeStrategy<D> {
@Override
public Unit invoke(Instruction instruction, D enterData, D exitData) {
execute(instruction, enterData, exitData);
return Unit.VALUE;
}
public abstract void execute(Instruction instruction, D enterData, D exitData);
}
public abstract static class FunctionVoid1<P> implements Function1<P, Unit> {
@Override
public Unit invoke(P p) {
execute(p);
return Unit.VALUE;
}
public abstract void execute(P p);
}
}
@@ -14,172 +14,107 @@
* limitations under the License.
*/
package org.jetbrains.jet.lang.cfg;
package org.jetbrains.jet.lang.cfg.pseudocodeTraverser
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Queues;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.cfg.pseudocode.*;
import java.util.*;
import static org.jetbrains.jet.lang.cfg.PseudocodeTraverser.TraversalOrder.FORWARD;
public class PseudocodeTraverser {
public static enum TraversalOrder {
FORWARD,
BACKWARD
}
@NotNull
/*package*/ static Instruction getStartInstruction(@NotNull Pseudocode pseudocode, @NotNull TraversalOrder traversalOrder) {
return traversalOrder == FORWARD ? pseudocode.getEnterInstruction() : pseudocode.getSinkInstruction();
}
@NotNull
/*package*/ static Instruction getLastInstruction(@NotNull Pseudocode pseudocode, @NotNull TraversalOrder traversalOrder) {
return traversalOrder == FORWARD ? pseudocode.getSinkInstruction() : pseudocode.getEnterInstruction();
}
@NotNull
/*package*/ static List<Instruction> getInstructions(@NotNull Pseudocode pseudocode, @NotNull TraversalOrder traversalOrder) {
return traversalOrder == FORWARD ? pseudocode.getInstructions() : pseudocode.getReversedInstructions();
}
@NotNull
/*packge*/ static Collection<Instruction> getPreviousInstruction(@NotNull Instruction instruction, @NotNull TraversalOrder traversalOrder) {
return traversalOrder == FORWARD ? instruction.getPreviousInstructions() : instruction.getNextInstructions();
}
/*package*/ static boolean isStartInstruction(@NotNull Instruction instruction, @NotNull TraversalOrder traversalOrder) {
return traversalOrder == FORWARD ? instruction instanceof SubroutineEnterInstruction
: instruction instanceof SubroutineSinkInstruction;
}
public static enum LookInsideStrategy {
ANALYSE_LOCAL_DECLARATIONS,
SKIP_LOCAL_DECLARATIONS
}
public static boolean shouldLookInside(Instruction instruction, LookInsideStrategy lookInside) {
return lookInside == LookInsideStrategy.ANALYSE_LOCAL_DECLARATIONS && instruction instanceof LocalFunctionDeclarationInstruction;
}
import org.jetbrains.jet.lang.cfg.pseudocode.*
import java.util.*
import org.jetbrains.jet.lang.cfg.pseudocodeTraverser.TraversalOrder.FORWARD
public static void traverse(
@NotNull Pseudocode pseudocode,
@NotNull TraversalOrder traversalOrder,
@NotNull InstructionAnalyzeStrategy instructionAnalyzeStrategy
) {
List<Instruction> instructions = getInstructions(pseudocode, traversalOrder);
for (Instruction instruction : instructions) {
if (instruction instanceof LocalFunctionDeclarationInstruction) {
traverse(((LocalFunctionDeclarationInstruction) instruction).getBody(), traversalOrder, instructionAnalyzeStrategy);
}
instructionAnalyzeStrategy.execute(instruction);
}
}
public static <D> void traverse(
@NotNull Pseudocode pseudocode, TraversalOrder traversalOrder,
@NotNull Map<Instruction, Edges<D>> edgesMap,
@NotNull InstructionDataAnalyzeStrategy<D> instructionDataAnalyzeStrategy) {
List<Instruction> instructions = getInstructions(pseudocode, traversalOrder);
for (Instruction instruction : instructions) {
if (instruction instanceof LocalFunctionDeclarationInstruction) {
traverse(((LocalFunctionDeclarationInstruction) instruction).getBody(), traversalOrder, edgesMap,
instructionDataAnalyzeStrategy);
}
Edges<D> edges = edgesMap.get(instruction);
instructionDataAnalyzeStrategy.execute(instruction, edges != null ? edges.in : null, edges != null ? edges.out : null);
}
}
public interface InstructionDataMergeStrategy<D> {
@NotNull
Edges<D> execute(@NotNull Instruction instruction, @NotNull Collection<D> incomingEdgesData);
}
public interface InstructionDataAnalyzeStrategy<D> {
void execute(@NotNull Instruction instruction, @Nullable D enterData, @Nullable D exitData);
}
public interface InstructionAnalyzeStrategy {
void execute(@NotNull Instruction instruction);
}
public static class Edges<T> {
@NotNull
public final T in;
@NotNull
public final T out;
Edges(@NotNull T in, @NotNull T out) {
this.in = in;
this.out = out;
}
@NotNull
public static <T> Edges<T> create(@NotNull T in, @NotNull T out) {
return new Edges<T>(in, out);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Edges)) return false;
Edges edges = (Edges) o;
if (in != null ? !in.equals(edges.in) : edges.in != null) return false;
if (out != null ? !out.equals(edges.out) : edges.out != null) return false;
return true;
}
@Override
public int hashCode() {
int result = in != null ? in.hashCode() : 0;
result = 31 * result + (out != null ? out.hashCode() : 0);
return result;
}
}
public interface InstructionHandler {
// true to continue traversal
boolean handle(@NotNull Instruction instruction);
}
// returns false when interrupted by handler
public static boolean traverseFollowingInstructions(
@NotNull Instruction rootInstruction,
@NotNull Set<Instruction> visited,
@NotNull TraversalOrder order,
@Nullable InstructionHandler handler
) {
Deque<Instruction> stack = Queues.newArrayDeque();
stack.push(rootInstruction);
while (!stack.isEmpty()) {
Instruction instruction = stack.pop();
visited.add(instruction);
Collection<Instruction> followingInstructions =
order == FORWARD ? instruction.getNextInstructions() : instruction.getPreviousInstructions();
for (Instruction followingInstruction : followingInstructions) {
if (followingInstruction != null && !visited.contains(followingInstruction)) {
if (handler != null && !handler.handle(instruction)) return false;
stack.push(followingInstruction);
}
}
}
return true;
}
enum class TraversalOrder {
FORWARD
BACKWARD
}
fun Pseudocode.getStartInstruction(traversalOrder: TraversalOrder): Instruction =
if (traversalOrder == FORWARD) getEnterInstruction() else getSinkInstruction()
fun Pseudocode.getLastInstruction(traversalOrder: TraversalOrder): Instruction =
if (traversalOrder == FORWARD) getSinkInstruction() else getEnterInstruction()
fun Pseudocode.getInstructions(traversalOrder: TraversalOrder): MutableList<Instruction> =
if (traversalOrder == FORWARD) getInstructions() else getReversedInstructions()
fun Instruction.getNextInstructions(traversalOrder: TraversalOrder): Collection<Instruction> =
if (traversalOrder == FORWARD) getNextInstructions() else getPreviousInstructions()
fun Instruction.getPreviousInstructions(traversalOrder: TraversalOrder): Collection<Instruction> =
if (traversalOrder == FORWARD) getPreviousInstructions() else getNextInstructions()
fun Instruction.isStartInstruction(traversalOrder: TraversalOrder): Boolean =
if (traversalOrder == FORWARD) this is SubroutineEnterInstruction else this is SubroutineSinkInstruction
enum class LookInsideStrategy {
ANALYSE_LOCAL_DECLARATIONS
SKIP_LOCAL_DECLARATIONS
}
fun Instruction.shouldLookInside(lookInside: LookInsideStrategy): Boolean =
lookInside == LookInsideStrategy.ANALYSE_LOCAL_DECLARATIONS && this is LocalFunctionDeclarationInstruction
fun Pseudocode.traverse(
traversalOrder: TraversalOrder,
analyzeInstruction: (Instruction) -> Unit
) {
val instructions = getInstructions(traversalOrder)
for (instruction in instructions) {
if (instruction is LocalFunctionDeclarationInstruction) {
instruction.getBody().traverse(traversalOrder, analyzeInstruction)
}
analyzeInstruction(instruction)
}
}
fun <D> Pseudocode.traverse(
traversalOrder: TraversalOrder,
edgesMap: Map<Instruction, Edges<D>>,
instructionDataAnalyzeStrategy: InstructionDataAnalyzeStrategy<D>
) {
val instructions = getInstructions(traversalOrder)
for (instruction in instructions) {
if (instruction is LocalFunctionDeclarationInstruction) {
instruction.getBody().traverse(traversalOrder, edgesMap, instructionDataAnalyzeStrategy)
}
val edges = edgesMap.get(instruction)
if (edges != null) {
instructionDataAnalyzeStrategy(instruction, edges.`in`, edges.out)
}
}
}
trait InstructionDataMergeStrategy<D> : (Instruction, Collection<D>) -> Edges<D>
trait InstructionDataAnalyzeStrategy<D> : (Instruction, D, D) -> Unit
data class Edges<T>(val `in`: T, val out: T)
fun <T> createEdges(`in`: T, out: T) = Edges(`in`, out)
// returns false when interrupted by handler
fun traverseFollowingInstructions(
rootInstruction: Instruction,
visited: MutableSet<Instruction>,
order: TraversalOrder,
// true to continue traversal
handler: ((Instruction)->Boolean)?
): Boolean {
val stack = ArrayDeque<Instruction>()
stack.push(rootInstruction)
while (!stack.isEmpty()) {
val instruction = stack.pop()
visited.add(instruction)
val followingInstructions = instruction.getNextInstructions(order)
for (followingInstruction in followingInstructions) {
if (!visited.contains(followingInstruction)) {
if (handler != null && !handler(instruction)) {
return false
}
stack.push(followingInstruction)
}
}
}
return true
}
@@ -21,7 +21,7 @@ import org.jetbrains.jet.lang.cfg.pseudocode.LocalFunctionDeclarationInstruction
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.cfg.PseudocodeTraverser.*
import org.jetbrains.jet.lang.cfg.pseudocodeTraverser.*
import org.jetbrains.jet.lang.cfg.pseudocode.LexicalScope
import org.jetbrains.jet.lang.cfg.pseudocode.VariableDeclarationInstruction
import org.jetbrains.jet.utils.addToStdlib.*
@@ -54,8 +54,7 @@ public class PseudocodeVariableDataCollector(
val initialDataValue : Map<VariableDescriptor, D> = Collections.emptyMap<VariableDescriptor, D>()
val edgesMap = LinkedHashMap<Instruction, Edges<Map<VariableDescriptor, D>>>()
initializeEdgesMap(pseudocode, edgesMap, initialDataValue)
edgesMap.put(getStartInstruction(pseudocode, traversalOrder),
Edges.create(initialDataValue, initialDataValue))
edgesMap.put(pseudocode.getStartInstruction(traversalOrder), Edges(initialDataValue, initialDataValue))
val changed = BooleanArray(1)
changed[0] = true
@@ -74,11 +73,11 @@ public class PseudocodeVariableDataCollector(
initialDataValue: M
) {
val instructions = pseudocode.getInstructions()
val initialEdge = Edges.create(initialDataValue, initialDataValue)
val initialEdge = Edges(initialDataValue, initialDataValue)
for (instruction in instructions) {
edgesMap.put(instruction, initialEdge)
if (PseudocodeTraverser.shouldLookInside(instruction, LookInsideStrategy.ANALYSE_LOCAL_DECLARATIONS)) {
initializeEdgesMap(((instruction as LocalFunctionDeclarationInstruction)).getBody(), edgesMap, initialDataValue)
if (instruction.shouldLookInside(LookInsideStrategy.ANALYSE_LOCAL_DECLARATIONS)) {
initializeEdgesMap((instruction as LocalFunctionDeclarationInstruction).getBody(), edgesMap, initialDataValue)
}
}
}
@@ -93,24 +92,24 @@ public class PseudocodeVariableDataCollector(
changed: BooleanArray,
isLocal: Boolean
) {
val instructions = getInstructions(pseudocode, traversalOrder)
val startInstruction = getStartInstruction(pseudocode, traversalOrder)
val instructions = pseudocode.getInstructions(traversalOrder)
val startInstruction = pseudocode.getStartInstruction(traversalOrder)
for (instruction in instructions) {
val isStart = isStartInstruction(instruction, traversalOrder)
val isStart = instruction.isStartInstruction(traversalOrder)
if (!isLocal && isStart)
continue
val allPreviousInstructions: MutableCollection<Instruction>
val previousInstructions = getPreviousInstruction(instruction, traversalOrder)
if (instruction == startInstruction && !previousSubGraphInstructions.isEmpty()) {
allPreviousInstructions = ArrayList(previousInstructions)
allPreviousInstructions.addAll(previousSubGraphInstructions)
}
else {
allPreviousInstructions = previousInstructions
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>>?,
@@ -122,19 +121,18 @@ public class PseudocodeVariableDataCollector(
}
}
if (shouldLookInside(instruction, lookInside)) {
if (instruction.shouldLookInside(lookInside)) {
val functionInstruction = (instruction as LocalFunctionDeclarationInstruction)
val subroutinePseudocode = functionInstruction.getBody()
collectDataFromSubgraph(
subroutinePseudocode, traversalOrder, lookInside, edgesMap, instructionDataMergeStrategy,
previousInstructions, changed, true)
val lastInstruction = getLastInstruction(subroutinePseudocode, traversalOrder)
val lastInstruction = subroutinePseudocode.getLastInstruction(traversalOrder)
val previousValue = edgesMap.get(instruction)
val newValue = edgesMap.get(lastInstruction)
val updatedValue = if (newValue == null) null else
Edges.create(
filterOutVariablesOutOfScope(lastInstruction, instruction, newValue.`in`),
filterOutVariablesOutOfScope(lastInstruction, instruction, newValue.out))
Edges(filterOutVariablesOutOfScope(lastInstruction, instruction, newValue.`in`),
filterOutVariablesOutOfScope(lastInstruction, instruction, newValue.out))
updateEdgeDataForInstruction(previousValue, updatedValue)
continue
}
@@ -142,14 +140,14 @@ public class PseudocodeVariableDataCollector(
val incomingEdgesData = HashSet<Map<VariableDescriptor, D>>()
for (previousInstruction in allPreviousInstructions) {
for (previousInstruction in previousInstructions) {
val previousData = edgesMap.get(previousInstruction)
if (previousData != null) {
incomingEdgesData.add(filterOutVariablesOutOfScope(
previousInstruction, instruction, previousData.out))
}
}
val mergedData = instructionDataMergeStrategy.execute(instruction, incomingEdgesData)
val mergedData = instructionDataMergeStrategy(instruction, incomingEdgesData)
updateEdgeDataForInstruction(previousDataValue, mergedData)
}
}
@@ -175,7 +173,7 @@ public class PseudocodeVariableDataCollector(
fun computeLexicalScopeVariableInfo(pseudocode: Pseudocode): LexicalScopeVariableInfo {
val lexicalScopeVariableInfo = LexicalScopeVariableInfoImpl()
PseudocodeTraverser.traverse(pseudocode, TraversalOrder.FORWARD, { instruction ->
pseudocode.traverse(TraversalOrder.FORWARD, { instruction ->
if (instruction is VariableDeclarationInstruction) {
val variableDeclarationElement = instruction.getVariableDeclarationElement()
val descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, variableDeclarationElement)
@@ -18,11 +18,13 @@ package org.jetbrains.jet.lang.cfg;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import kotlin.Function1;
import kotlin.Unit;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
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.pseudocodeTraverser.Edges;
import org.jetbrains.jet.lang.cfg.pseudocodeTraverser.InstructionDataMergeStrategy;
import org.jetbrains.jet.lang.cfg.pseudocodeTraverser.PseudocodeTraverserPackage;
import org.jetbrains.jet.lang.cfg.pseudocode.*;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
@@ -35,8 +37,9 @@ import java.util.Collections;
import java.util.Map;
import java.util.Set;
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.BACKWARD;
import static org.jetbrains.jet.lang.cfg.pseudocodeTraverser.TraversalOrder.FORWARD;
import static org.jetbrains.jet.lang.cfg.pseudocodeTraverser.PseudocodeTraverserPackage.createEdges;
public class PseudocodeVariablesData {
private final Pseudocode pseudocode;
@@ -64,14 +67,15 @@ public class PseudocodeVariablesData {
Set<VariableDescriptor> usedVariables = usedVariablesForDeclaration.get(pseudocode);
if (usedVariables == null) {
final Set<VariableDescriptor> result = Sets.newHashSet();
PseudocodeTraverser.traverse(pseudocode, FORWARD, new InstructionAnalyzeStrategy() {
PseudocodeTraverserPackage.traverse(pseudocode, FORWARD, new Function1<Instruction, Unit>() {
@Override
public void execute(@NotNull Instruction instruction) {
VariableDescriptor variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, false,
bindingContext);
public Unit invoke(@NotNull Instruction instruction) {
VariableDescriptor variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(
instruction, false, bindingContext);
if (variableDescriptor != null) {
result.add(variableDescriptor);
}
return Unit.VALUE;
}
});
usedVariables = Collections.unmodifiableSet(result);
@@ -142,16 +146,16 @@ public class PseudocodeVariablesData {
new InstructionDataMergeStrategy<Map<VariableDescriptor, VariableInitState>>() {
@NotNull
@Override
public Edges<Map<VariableDescriptor, VariableInitState>> execute(
public Edges<Map<VariableDescriptor, VariableInitState>> invoke(
@NotNull Instruction instruction,
@NotNull Collection<Map<VariableDescriptor, VariableInitState>> incomingEdgesData
@NotNull Collection<? extends Map<VariableDescriptor, VariableInitState>> incomingEdgesData
) {
Map<VariableDescriptor, VariableInitState> enterInstructionData =
mergeIncomingEdgesDataForInitializers(incomingEdgesData);
Map<VariableDescriptor, VariableInitState> exitInstructionData =
addVariableInitStateFromCurrentInstructionIfAny(instruction, enterInstructionData, declaredVariables);
return Edges.create(enterInstructionData, exitInstructionData);
return createEdges(enterInstructionData, exitInstructionData);
}
}
);
@@ -168,7 +172,7 @@ public class PseudocodeVariablesData {
@NotNull
private static Map<VariableDescriptor, VariableInitState> mergeIncomingEdgesDataForInitializers(
@NotNull Collection<Map<VariableDescriptor, VariableInitState>> incomingEdgesData
@NotNull Collection<? extends Map<VariableDescriptor, VariableInitState>> incomingEdgesData
) {
Set<VariableDescriptor> variablesInScope = Sets.newHashSet();
for (Map<VariableDescriptor, VariableInitState> edgeData : incomingEdgesData) {
@@ -238,9 +242,9 @@ public class PseudocodeVariablesData {
new InstructionDataMergeStrategy<Map<VariableDescriptor, VariableUseState>>() {
@NotNull
@Override
public Edges<Map<VariableDescriptor, VariableUseState>> execute(
public Edges<Map<VariableDescriptor, VariableUseState>> invoke(
@NotNull Instruction instruction,
@NotNull Collection<Map<VariableDescriptor, VariableUseState>> incomingEdgesData
@NotNull Collection<? extends Map<VariableDescriptor, VariableUseState>> incomingEdgesData
) {
Map<VariableDescriptor, VariableUseState> enterResult = Maps.newHashMap();
@@ -255,7 +259,7 @@ public class PseudocodeVariablesData {
instruction, true, bindingContext);
if (variableDescriptor == null ||
(!(instruction instanceof ReadValueInstruction) && !(instruction instanceof WriteValueInstruction))) {
return Edges.create(enterResult, enterResult);
return createEdges(enterResult, enterResult);
}
Map<VariableDescriptor, VariableUseState> exitResult = Maps.newHashMap(enterResult);
if (instruction instanceof ReadValueInstruction) {
@@ -276,7 +280,7 @@ public class PseudocodeVariablesData {
exitResult.put(variableDescriptor, VariableUseState.WRITTEN_AFTER_READ);
}
}
return Edges.create(enterResult, exitResult);
return createEdges(enterResult, exitResult);
}
}
);
@@ -16,11 +16,12 @@
package org.jetbrains.jet.lang.cfg;
import kotlin.Function1;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.cfg.pseudocode.*;
import org.jetbrains.jet.lang.psi.JetElement;
public class TailRecursionDetector extends InstructionVisitorWithResult<Boolean> implements PseudocodeTraverser.InstructionHandler {
public class TailRecursionDetector extends InstructionVisitorWithResult<Boolean> implements Function1<Instruction, Boolean> {
private final JetElement subroutine;
private final Instruction start;
@@ -30,7 +31,7 @@ public class TailRecursionDetector extends InstructionVisitorWithResult<Boolean>
}
@Override
public boolean handle(@NotNull Instruction instruction) {
public Boolean invoke(@NotNull Instruction instruction) {
return instruction == start || instruction.accept(this);
}
@@ -21,14 +21,14 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.cfg.Label;
import org.jetbrains.jet.lang.cfg.LoopInfo;
import org.jetbrains.jet.lang.cfg.PseudocodeTraverser;
import org.jetbrains.jet.lang.cfg.pseudocodeTraverser.PseudocodeTraverserPackage;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetExpression;
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.pseudocodeTraverser.TraversalOrder.BACKWARD;
import static org.jetbrains.jet.lang.cfg.pseudocodeTraverser.TraversalOrder.FORWARD;
public class PseudocodeImpl implements Pseudocode {
@@ -159,13 +159,13 @@ public class PseudocodeImpl implements Pseudocode {
@Override
public List<Instruction> getReversedInstructions() {
LinkedHashSet<Instruction> traversedInstructions = Sets.newLinkedHashSet();
PseudocodeTraverser.traverseFollowingInstructions(sinkInstruction, traversedInstructions, BACKWARD, null);
PseudocodeTraverserPackage.traverseFollowingInstructions(sinkInstruction, traversedInstructions, BACKWARD, null);
if (traversedInstructions.size() < instructions.size()) {
List<Instruction> simplyReversedInstructions = Lists.newArrayList(instructions);
Collections.reverse(simplyReversedInstructions);
for (Instruction instruction : simplyReversedInstructions) {
if (!traversedInstructions.contains(instruction)) {
PseudocodeTraverser.traverseFollowingInstructions(instruction, traversedInstructions, BACKWARD, null);
PseudocodeTraverserPackage.traverseFollowingInstructions(instruction, traversedInstructions, BACKWARD, null);
}
}
}
@@ -338,7 +338,7 @@ public class PseudocodeImpl implements Pseudocode {
private Set<Instruction> collectReachableInstructions() {
Set<Instruction> visited = Sets.newHashSet();
PseudocodeTraverser.traverseFollowingInstructions(getEnterInstruction(), visited, FORWARD, null);
PseudocodeTraverserPackage.traverseFollowingInstructions(getEnterInstruction(), visited, FORWARD, null);
if (!visited.contains(getExitInstruction())) {
visited.add(getExitInstruction());
}
@@ -30,7 +30,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import static org.jetbrains.jet.lang.cfg.PseudocodeTraverser.Edges;
import org.jetbrains.jet.lang.cfg.pseudocodeTraverser.Edges;
import static org.jetbrains.jet.lang.cfg.PseudocodeVariablesData.VariableInitState;
import static org.jetbrains.jet.lang.cfg.PseudocodeVariablesData.VariableUseState;
@@ -93,8 +93,8 @@ public abstract class AbstractDataFlowTest extends AbstractPseudocodeTest {
@NotNull
private <D> String dumpEdgesData(String prefix, @NotNull Edges<Map<VariableDescriptor, D>> edges) {
return prefix +
" in: " + renderVariableMap(edges.in) +
" out: " + renderVariableMap(edges.out);
" in: " + renderVariableMap(edges.getIn()) +
" out: " + renderVariableMap(edges.getOut());
}
private <D> String renderVariableMap(Map<VariableDescriptor, D> map) {