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