From ab18b12165c4302dc535e9444d7541d100d989ca Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Tue, 11 Sep 2012 19:08:52 +0400 Subject: [PATCH] DFS utility class factored out of CommonSupertypes --- compiler/frontend/frontend.iml | 1 + .../jet/lang/types/CommonSupertypes.java | 122 +++++++-------- .../util/src/org/jetbrains/jet/utils/DFS.java | 148 ++++++++++++++++++ 3 files changed, 204 insertions(+), 67 deletions(-) create mode 100644 compiler/util/src/org/jetbrains/jet/utils/DFS.java 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); + } + } +}