From 66e3743cc55e1494dbcbe375cd5bc2d8621f6b86 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Thu, 5 Dec 2013 15:36:26 +0400 Subject: [PATCH] Useful method extracted + visiting strategy added --- .../jet/lang/cfg/PseudocodeTraverser.java | 39 +++++++++++++++++-- .../lang/cfg/pseudocode/PseudocodeImpl.java | 33 ++++------------ 2 files changed, 42 insertions(+), 30 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java index 83a87050e56..3997bced6df 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java @@ -18,15 +18,13 @@ package org.jetbrains.jet.lang.cfg; 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.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import java.util.*; import static org.jetbrains.jet.lang.cfg.PseudocodeTraverser.TraversalOrder.FORWARD; @@ -236,4 +234,37 @@ public class PseudocodeTraverser { 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; + } + } 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 6dd42109889..0d7eb5d3a79 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,11 +21,15 @@ 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.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; + public class PseudocodeImpl implements Pseudocode { public class PseudocodeLabel implements Label { @@ -134,13 +138,13 @@ public class PseudocodeImpl implements Pseudocode { @Override public List getReversedInstructions() { LinkedHashSet traversedInstructions = Sets.newLinkedHashSet(); - traverseFollowingInstructions(sinkInstruction, traversedInstructions, false); + PseudocodeTraverser.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)) { - traverseFollowingInstructions(instruction, traversedInstructions, false); + PseudocodeTraverser.traverseFollowingInstructions(instruction, traversedInstructions, BACKWARD, null); } } } @@ -311,7 +315,7 @@ public class PseudocodeImpl implements Pseudocode { private Set collectReachableInstructions() { Set visited = Sets.newHashSet(); - traverseFollowingInstructions(getEnterInstruction(), visited, true); + PseudocodeTraverser.traverseFollowingInstructions(getEnterInstruction(), visited, FORWARD, null); if (!visited.contains(getExitInstruction())) { visited.add(getExitInstruction()); } @@ -323,29 +327,6 @@ public class PseudocodeImpl implements Pseudocode { } return visited; } - - private static void traverseFollowingInstructions( - @NotNull Instruction rootInstruction, - @NotNull Set visited, - boolean directOrder - ) { - Deque stack = Queues.newArrayDeque(); - stack.push(rootInstruction); - - while (!stack.isEmpty()) { - Instruction instruction = stack.pop(); - visited.add(instruction); - - Collection followingInstructions = - directOrder ? instruction.getNextInstructions() : instruction.getPreviousInstructions(); - - for (Instruction followingInstruction : followingInstructions) { - if (followingInstruction != null && !visited.contains(followingInstruction)) { - stack.push(followingInstruction); - } - } - } - } private void markDeadInstructions() { Set instructionSet = Sets.newHashSet(instructions);