[Constraint graph] Add preVisit hook for depth-first search.

Refactoring so we can use this in a moment.
This commit is contained in:
Doug Gregor
2019-08-14 11:49:14 -07:00
parent 0b7ef3445e
commit f19016b94b

View File

@@ -814,19 +814,29 @@ namespace {
} }
/// Perform a depth-first search to produce a from the given type variable, /// Perform a depth-first search to produce a from the given type variable,
/// notifying the function object \c postVisit after each reachable /// notifying the function object.
/// type variable has been visited. ///
/// \param getAdjacencies Called to retrieve the set of type variables
/// that are adjacent to the given type variable.
///
/// \param preVisit Called before visiting the adjacencies of the given
/// type variable. When it returns \c true, the adjacencies of this type
/// variable will be visited. When \c false, the adjacencies will not be
/// visited and \c postVisit will not be called.
///
/// \param postVisit Called after visiting the adjacencies of the given
/// type variable.
static void postorderDepthFirstSearchRec( static void postorderDepthFirstSearchRec(
TypeVariableType *typeVar, TypeVariableType *typeVar,
llvm::function_ref< llvm::function_ref<
ArrayRef<TypeVariableType *>(TypeVariableType *)> getAdjacencies, ArrayRef<TypeVariableType *>(TypeVariableType *)> getAdjacencies,
llvm::function_ref<void(TypeVariableType *)> postVisit, llvm::function_ref<bool(TypeVariableType *)> preVisit,
SmallPtrSet<TypeVariableType *, 4> &visited) { llvm::function_ref<void(TypeVariableType *)> postVisit) {
if (!visited.insert(typeVar).second) if (!preVisit(typeVar))
return; return;
for (auto adj : getAdjacencies(typeVar)) { for (auto adj : getAdjacencies(typeVar)) {
postorderDepthFirstSearchRec(adj, getAdjacencies, postVisit, visited); postorderDepthFirstSearchRec(adj, getAdjacencies, preVisit, postVisit);
} }
postVisit(typeVar); postVisit(typeVar);
@@ -855,14 +865,16 @@ namespace {
return oneWayComponent->second.inAdjacencies; return oneWayComponent->second.inAdjacencies;
}, },
[&](TypeVariableType *typeVar) {
return visited.insert(typeVar).second;
},
[&](TypeVariableType *dependsOn) { [&](TypeVariableType *dependsOn) {
// Don't record dependency on ourselves. // Don't record dependency on ourselves.
if (dependsOn == inAdj) if (dependsOn == inAdj)
return; return;
indirectlyReachable.insert(dependsOn); indirectlyReachable.insert(dependsOn);
}, });
visited);
// Remove any in-adjacency of this component that is indirectly // Remove any in-adjacency of this component that is indirectly
// reachable. // reachable.
@@ -922,13 +934,15 @@ namespace {
return oneWayComponent->second.outAdjacencies; return oneWayComponent->second.outAdjacencies;
}, },
[&](TypeVariableType *typeVar) {
return visited.insert(typeVar).second;
},
[&](TypeVariableType *typeVar) { [&](TypeVariableType *typeVar) {
// Record this type variable, if it's one of the representative // Record this type variable, if it's one of the representative
// type variables. // type variables.
if (validComponents.count(typeVar) > 0) if (validComponents.count(typeVar) > 0)
orderedReps.push_back(typeVar); orderedReps.push_back(typeVar);
}, });
visited);
} }
assert(orderedReps.size() == representativeTypeVars.size()); assert(orderedReps.size() == representativeTypeVars.size());