diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java index 804d74050da..73393e1f740 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java @@ -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 reportedDiagnosticMap = Maps.newHashMap(); - PseudocodeTraverser.traverse(pseudocode, FORWARD, initializers, new InstructionDataAnalyzeStrategy>() { + PseudocodeTraverserPackage.traverse( + pseudocode, FORWARD, initializers, + new InstructionDataAnalyzeStrategyJ>() { @Override public void execute(@NotNull Instruction instruction, @Nullable Map in, @@ -497,7 +501,7 @@ public class JetFlowInformationProvider { Set 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>> variableStatusData = pseudocodeVariablesData.getVariableUseStatusData(); final Map reportedDiagnosticMap = Maps.newHashMap(); InstructionDataAnalyzeStrategy> variableStatusAnalyzeStrategy = - new InstructionDataAnalyzeStrategy>() { + new InstructionDataAnalyzeStrategyJ>() { @Override public void execute(@NotNull Instruction instruction, @Nullable Map 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 reportedDiagnosticMap = Maps.newHashMap(); - PseudocodeTraverser.traverse( - pseudocode, FORWARD, new InstructionAnalyzeStrategy() { + PseudocodeTraverserPackage.traverse( + pseudocode, FORWARD, new FunctionVoid1() { @Override public void execute(@NotNull Instruction instruction) { if (!(instruction instanceof ReadValueInstruction)) return; @@ -642,11 +646,10 @@ public class JetFlowInformationProvider { } } final Map calls = new HashMap(); - PseudocodeTraverser.traverse( + PseudocodeTraverserPackage.traverse( pseudocode, FORWARD, - new InstructionAnalyzeStrategy() { - @Override + new FunctionVoid1() { 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(), 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 implements InstructionDataAnalyzeStrategy { + @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

implements Function1 { + @Override + public Unit invoke(P p) { + execute(p); + return Unit.VALUE; + } + + public abstract void execute(P p); + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.kt b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.kt index a2b174491a0..24057bef9cf 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.kt @@ -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 getInstructions(@NotNull Pseudocode pseudocode, @NotNull TraversalOrder traversalOrder) { - return traversalOrder == FORWARD ? pseudocode.getInstructions() : pseudocode.getReversedInstructions(); - } - - @NotNull - /*packge*/ static Collection 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 instructions = getInstructions(pseudocode, traversalOrder); - for (Instruction instruction : instructions) { - if (instruction instanceof LocalFunctionDeclarationInstruction) { - traverse(((LocalFunctionDeclarationInstruction) instruction).getBody(), traversalOrder, instructionAnalyzeStrategy); - } - instructionAnalyzeStrategy.execute(instruction); - } - } - - public static void traverse( - @NotNull Pseudocode pseudocode, TraversalOrder traversalOrder, - @NotNull Map> edgesMap, - @NotNull InstructionDataAnalyzeStrategy instructionDataAnalyzeStrategy) { - - List instructions = getInstructions(pseudocode, traversalOrder); - for (Instruction instruction : instructions) { - if (instruction instanceof LocalFunctionDeclarationInstruction) { - traverse(((LocalFunctionDeclarationInstruction) instruction).getBody(), traversalOrder, edgesMap, - instructionDataAnalyzeStrategy); - } - Edges edges = edgesMap.get(instruction); - instructionDataAnalyzeStrategy.execute(instruction, edges != null ? edges.in : null, edges != null ? edges.out : null); - } - } - - public interface InstructionDataMergeStrategy { - @NotNull - Edges execute(@NotNull Instruction instruction, @NotNull Collection incomingEdgesData); - } - - public interface InstructionDataAnalyzeStrategy { - void execute(@NotNull Instruction instruction, @Nullable D enterData, @Nullable D exitData); - } - - public interface InstructionAnalyzeStrategy { - void execute(@NotNull Instruction instruction); - } - - public static class Edges { - @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 Edges create(@NotNull T in, @NotNull T out) { - return new Edges(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 visited, - @NotNull TraversalOrder order, - @Nullable InstructionHandler handler - ) { - Deque stack = Queues.newArrayDeque(); - stack.push(rootInstruction); - - while (!stack.isEmpty()) { - Instruction instruction = stack.pop(); - visited.add(instruction); - - Collection 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 = + if (traversalOrder == FORWARD) getInstructions() else getReversedInstructions() + +fun Instruction.getNextInstructions(traversalOrder: TraversalOrder): Collection = + if (traversalOrder == FORWARD) getNextInstructions() else getPreviousInstructions() + +fun Instruction.getPreviousInstructions(traversalOrder: TraversalOrder): Collection = + 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 Pseudocode.traverse( + traversalOrder: TraversalOrder, + edgesMap: Map>, + instructionDataAnalyzeStrategy: InstructionDataAnalyzeStrategy +) { + 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 : (Instruction, Collection) -> Edges +trait InstructionDataAnalyzeStrategy : (Instruction, D, D) -> Unit + +data class Edges(val `in`: T, val out: T) +fun createEdges(`in`: T, out: T) = Edges(`in`, out) + + +// returns false when interrupted by handler +fun traverseFollowingInstructions( + rootInstruction: Instruction, + visited: MutableSet, + order: TraversalOrder, + // true to continue traversal + handler: ((Instruction)->Boolean)? +): Boolean { + val stack = ArrayDeque() + 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 } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariableDataCollector.kt b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariableDataCollector.kt index a528075eb90..e27c00fd774 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariableDataCollector.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariableDataCollector.kt @@ -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 = Collections.emptyMap() val edgesMap = LinkedHashMap>>() 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 - val previousInstructions = getPreviousInstruction(instruction, traversalOrder) - - if (instruction == startInstruction && !previousSubGraphInstructions.isEmpty()) { - allPreviousInstructions = ArrayList(previousInstructions) - allPreviousInstructions.addAll(previousSubGraphInstructions) - } - else { - allPreviousInstructions = previousInstructions + 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>?, @@ -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>() - 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) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariablesData.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariablesData.java index b48d4c63452..d9c999970af 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariablesData.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariablesData.java @@ -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 usedVariables = usedVariablesForDeclaration.get(pseudocode); if (usedVariables == null) { final Set result = Sets.newHashSet(); - PseudocodeTraverser.traverse(pseudocode, FORWARD, new InstructionAnalyzeStrategy() { + PseudocodeTraverserPackage.traverse(pseudocode, FORWARD, new Function1() { @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>() { @NotNull @Override - public Edges> execute( + public Edges> invoke( @NotNull Instruction instruction, - @NotNull Collection> incomingEdgesData + @NotNull Collection> incomingEdgesData ) { Map enterInstructionData = mergeIncomingEdgesDataForInitializers(incomingEdgesData); Map 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 mergeIncomingEdgesDataForInitializers( - @NotNull Collection> incomingEdgesData + @NotNull Collection> incomingEdgesData ) { Set variablesInScope = Sets.newHashSet(); for (Map edgeData : incomingEdgesData) { @@ -238,9 +242,9 @@ public class PseudocodeVariablesData { new InstructionDataMergeStrategy>() { @NotNull @Override - public Edges> execute( + public Edges> invoke( @NotNull Instruction instruction, - @NotNull Collection> incomingEdgesData + @NotNull Collection> incomingEdgesData ) { Map 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 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); } } ); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/TailRecursionDetector.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/TailRecursionDetector.java index 7bde7418b86..fa9db0cf31a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/TailRecursionDetector.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/TailRecursionDetector.java @@ -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 implements PseudocodeTraverser.InstructionHandler { +public class TailRecursionDetector extends InstructionVisitorWithResult implements Function1 { private final JetElement subroutine; private final Instruction start; @@ -30,7 +31,7 @@ public class TailRecursionDetector extends InstructionVisitorWithResult } @Override - public boolean handle(@NotNull Instruction instruction) { + public Boolean invoke(@NotNull Instruction instruction) { return instruction == start || instruction.accept(this); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeImpl.java index c68bec22e43..d75761cb4b0 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeImpl.java @@ -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 getReversedInstructions() { LinkedHashSet traversedInstructions = Sets.newLinkedHashSet(); - PseudocodeTraverser.traverseFollowingInstructions(sinkInstruction, traversedInstructions, BACKWARD, null); + PseudocodeTraverserPackage.traverseFollowingInstructions(sinkInstruction, traversedInstructions, BACKWARD, null); if (traversedInstructions.size() < instructions.size()) { List 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 collectReachableInstructions() { Set visited = Sets.newHashSet(); - PseudocodeTraverser.traverseFollowingInstructions(getEnterInstruction(), visited, FORWARD, null); + PseudocodeTraverserPackage.traverseFollowingInstructions(getEnterInstruction(), visited, FORWARD, null); if (!visited.contains(getExitInstruction())) { visited.add(getExitInstruction()); } diff --git a/compiler/tests/org/jetbrains/jet/cfg/AbstractDataFlowTest.java b/compiler/tests/org/jetbrains/jet/cfg/AbstractDataFlowTest.java index c07e0a425a4..c5f2879f38c 100644 --- a/compiler/tests/org/jetbrains/jet/cfg/AbstractDataFlowTest.java +++ b/compiler/tests/org/jetbrains/jet/cfg/AbstractDataFlowTest.java @@ -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 String dumpEdgesData(String prefix, @NotNull Edges> edges) { return prefix + - " in: " + renderVariableMap(edges.in) + - " out: " + renderVariableMap(edges.out); + " in: " + renderVariableMap(edges.getIn()) + + " out: " + renderVariableMap(edges.getOut()); } private String renderVariableMap(Map map) {