diff --git a/compiler/frontend/frontend.iml b/compiler/frontend/frontend.iml
index 921ffcfc8f7..178648aa7b8 100644
--- a/compiler/frontend/frontend.iml
+++ b/compiler/frontend/frontend.iml
@@ -10,6 +10,7 @@
+
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/CommonSupertypes.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/CommonSupertypes.java
index b11834aedc2..f977f335d72 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/types/CommonSupertypes.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/CommonSupertypes.java
@@ -16,6 +16,8 @@
package org.jetbrains.jet.lang.types;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
@@ -24,11 +26,11 @@ import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
+import org.jetbrains.jet.utils.DFS;
import java.util.*;
-import static org.jetbrains.jet.lang.types.Variance.IN_VARIANCE;
-import static org.jetbrains.jet.lang.types.Variance.OUT_VARIANCE;
+import static org.jetbrains.jet.lang.types.Variance.*;
/**
* @author abreslav
@@ -91,33 +93,8 @@ public class CommonSupertypes {
List order = null;
for (JetType type : types) {
- Set visited = new HashSet();
-
- order = dfs(type, visited, new DfsNodeHandler>() {
- public LinkedList list = new LinkedList();
-
- @Override
- public void beforeChildren(JetType current) {
- TypeConstructor constructor = current.getConstructor();
-
- Set instances = constructorToAllInstances.get(constructor);
- if (instances == null) {
- instances = new HashSet();
- constructorToAllInstances.put(constructor, instances);
- }
- instances.add(current);
- }
-
- @Override
- public void afterChildren(JetType current) {
- list.addFirst(current.getConstructor());
- }
-
- @Override
- public List result() {
- return list;
- }
- });
+ Set visited = Sets.newHashSet();
+ order = topologicallySortSuperclassesAndRecordAllInstances(type, constructorToAllInstances, visited);
if (commonSuperclasses == null) {
commonSuperclasses = visited;
@@ -144,6 +121,55 @@ public class CommonSupertypes {
return result;
}
+ private static List topologicallySortSuperclassesAndRecordAllInstances(
+ @NotNull JetType type,
+ @NotNull final Map> constructorToAllInstances,
+ @NotNull final Set visited
+ ) {
+ return DFS.dfs(
+ Collections.singletonList(type),
+ new DFS.Neighbors() {
+ @NotNull
+ @Override
+ public Iterable getNeighbors(JetType current) {
+ TypeSubstitutor substitutor = TypeSubstitutor.create(current);
+ List result = Lists.newArrayList();
+ for (JetType supertype : current.getConstructor().getSupertypes()) {
+ if (visited.contains(supertype.getConstructor())) {
+ continue;
+ }
+ result.add(substitutor.safeSubstitute(supertype, INVARIANT));
+ }
+ return result;
+ }
+ },
+ new DFS.Visited() {
+ @Override
+ public boolean checkAndMarkVisited(JetType current) {
+ return visited.add(current.getConstructor());
+ }
+ },
+ new DFS.NodeHandlerWithListResult() {
+ @Override
+ public void beforeChildren(JetType current) {
+ TypeConstructor constructor = current.getConstructor();
+
+ Set instances = constructorToAllInstances.get(constructor);
+ if (instances == null) {
+ instances = new HashSet();
+ constructorToAllInstances.put(constructor, instances);
+ }
+ instances.add(current);
+ }
+
+ @Override
+ public void afterChildren(JetType current) {
+ result.addFirst(current.getConstructor());
+ }
+ }
+ );
+ }
+
// constructor - type constructor of a supertype to be instantiated
// types - instantiations of constructor occurring as supertypes of classes we are trying to intersect
@NotNull
@@ -251,42 +277,4 @@ public class CommonSupertypes {
markAll(type.getConstructor(), markerSet);
}
}
-
- private static R dfs(@NotNull JetType current, @NotNull Set visited, @NotNull DfsNodeHandler handler) {
- doDfs(current, visited, handler);
- return handler.result();
- }
-
- private static void doDfs(@NotNull JetType current, @NotNull Set visited, @NotNull DfsNodeHandler> handler) {
- if (!visited.add(current.getConstructor())) {
- return;
- }
- handler.beforeChildren(current);
-// Map substitutionContext = TypeUtils.buildSubstitutionContext(current);
- TypeSubstitutor substitutor = TypeSubstitutor.create(current);
- for (JetType supertype : current.getConstructor().getSupertypes()) {
- TypeConstructor supertypeConstructor = supertype.getConstructor();
- if (visited.contains(supertypeConstructor)) {
- continue;
- }
- JetType substitutedSupertype = substitutor.safeSubstitute(supertype, Variance.INVARIANT);
- dfs(substitutedSupertype, visited, handler);
- }
- handler.afterChildren(current);
- }
-
- private static class DfsNodeHandler {
-
- public void beforeChildren(JetType current) {
-
- }
-
- public void afterChildren(JetType current) {
-
- }
-
- public R result() {
- return null;
- }
- }
}
diff --git a/compiler/util/src/org/jetbrains/jet/utils/DFS.java b/compiler/util/src/org/jetbrains/jet/utils/DFS.java
new file mode 100644
index 00000000000..284c931e3ee
--- /dev/null
+++ b/compiler/util/src/org/jetbrains/jet/utils/DFS.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2010-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jetbrains.jet.utils;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author abreslav
+ */
+public class DFS {
+ public static R dfs(@NotNull Collection nodes, @NotNull Neighbors neighbors, @NotNull Visited visited, @NotNull NodeHandler handler) {
+ for (N node : nodes) {
+ doDfs(node, neighbors, visited, handler);
+ }
+ return handler.result();
+ }
+
+ public static R dfs(
+ @NotNull Collection nodes,
+ @NotNull Neighbors neighbors,
+ @NotNull NodeHandler handler
+ ) {
+ return dfs(nodes, neighbors, new VisitedWithSet(), handler);
+ }
+
+ public static R dfsFromNode(@NotNull N node, @NotNull Neighbors neighbors, @NotNull Visited visited, @NotNull NodeHandler handler) {
+ doDfs(node, neighbors, visited, handler);
+ return handler.result();
+ }
+
+ public static void dfsFromNode(
+ @NotNull N node,
+ @NotNull Neighbors neighbors,
+ @NotNull Visited visited
+ ) {
+ dfsFromNode(node, neighbors, visited, new AbstractNodeHandler() {
+ @Override
+ public Void result() {
+ return null;
+ }
+ });
+ }
+
+ public static List topologicalOrder(@NotNull Iterable nodes, @NotNull Neighbors neighbors, @NotNull Visited visited) {
+ TopologicalOrder handler = new TopologicalOrder();
+ for (N node : nodes) {
+ doDfs(node, neighbors, visited, handler);
+ }
+ return handler.result();
+ }
+
+ public static List topologicalOrder(@NotNull Iterable nodes, @NotNull Neighbors neighbors) {
+ return topologicalOrder(nodes, neighbors, new VisitedWithSet());
+ }
+
+ private static void doDfs(@NotNull N current, @NotNull Neighbors neighbors, @NotNull Visited visited, @NotNull NodeHandler handler) {
+ if (!visited.checkAndMarkVisited(current)) {
+ return;
+ }
+ handler.beforeChildren(current);
+ for (N neighbor : neighbors.getNeighbors(current)) {
+ doDfs(neighbor, neighbors, visited, handler);
+ }
+ handler.afterChildren(current);
+ }
+
+ public interface NodeHandler {
+
+ void beforeChildren(N current);
+
+ void afterChildren(N current);
+
+ R result();
+ }
+
+ public interface Neighbors {
+ @NotNull
+ Iterable getNeighbors(N current);
+ }
+
+ public interface Visited {
+ boolean checkAndMarkVisited(N current);
+ }
+
+ public static abstract class AbstractNodeHandler implements NodeHandler {
+ @Override
+ public void beforeChildren(N current) {
+ }
+
+ @Override
+ public void afterChildren(N current) {
+ }
+ }
+
+ public static class VisitedWithSet implements Visited {
+ private final Set visited;
+
+ public VisitedWithSet() {
+ this(Sets.newHashSet());
+ }
+
+ public VisitedWithSet(@NotNull Set visited) {
+ this.visited = visited;
+ }
+
+ @Override
+ public boolean checkAndMarkVisited(N current) {
+ return visited.add(current);
+ }
+ }
+
+ public static abstract class NodeHandlerWithListResult extends AbstractNodeHandler> {
+ protected final LinkedList result = Lists.newLinkedList();
+
+ @Override
+ public List result() {
+ return result;
+ }
+ }
+
+ public static class TopologicalOrder extends NodeHandlerWithListResult {
+ @Override
+ public void afterChildren(N current) {
+ result.addFirst(current);
+ }
+ }
+}