mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[CSSolver] Add skeleton of iterative solve
The idea so to split solving into non-recursive steps, represented by `SolverStep`, each of the steps is resposible for a unit of work e.g. attempting type variable or disjunction bindings/choices. Each step could produce more work via "follow-up" steps, complete "partial" solution when it's done, or error which terminates solver loop.
This commit is contained in:
71
lib/Sema/CSStep.cpp
Normal file
71
lib/Sema/CSStep.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
#include "CSStep.h"
|
||||
#include "ConstraintSystem.h"
|
||||
#include "swift/AST/Types.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include <list>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace swift;
|
||||
using namespace constraints;
|
||||
|
||||
SolverStep SolverStep::create(ConstraintSystem &cs,
|
||||
ArrayRef<TypeVariableType *> typeVars,
|
||||
ConstraintList &constraints,
|
||||
SmallVectorImpl<Solution> &solutions) {
|
||||
SolverStep step(cs, solutions);
|
||||
|
||||
for (auto *typeVar : typeVars)
|
||||
step.record(typeVar);
|
||||
|
||||
for (auto &constraint : constraints)
|
||||
step.record(&constraint);
|
||||
|
||||
return step;
|
||||
}
|
||||
|
||||
SolverStep::StepResult SolverStep::advance() {
|
||||
if (!ActiveScope)
|
||||
ActiveScope = new (CS.getAllocator()) Scope(*this);
|
||||
|
||||
auto *disjunction = CS.selectDisjunction();
|
||||
auto bestBindings = CS.determineBestBindings();
|
||||
|
||||
// TODO: Add expression too complex into the mix
|
||||
// TODO: This is where the generator comes in.
|
||||
|
||||
if (bestBindings && (!disjunction || (!bestBindings->InvolvesTypeVariables &&
|
||||
!bestBindings->FullyBound))) {
|
||||
// Attempt given "best" binding and record the current scope,
|
||||
// we'll have to come back to this step later on when follow-up
|
||||
// steps are solved.
|
||||
return computeFollowupSteps();
|
||||
}
|
||||
|
||||
// For disjunctions we need to figure out what all of the already
|
||||
// attempted choices are, and try the next one.
|
||||
auto choices = disjunction->getNestedConstraints();
|
||||
for (unsigned i = ActiveScope->CurrChoice, n = choices.size(); i != n; ++i) {
|
||||
auto *choice = choices[i];
|
||||
if (choice->isDisabled())
|
||||
continue;
|
||||
|
||||
// Attempt the choice and record it in the scope.
|
||||
ActiveScope->CurrChoice = i;
|
||||
return computeFollowupSteps();
|
||||
}
|
||||
|
||||
// Since we are done with this step, it's a good time to
|
||||
// roll-up all of the solutions produced by follow-up steps.
|
||||
auto result = mergePartialSolutions() ? ConstraintSystem::SolutionKind::Solved
|
||||
: ConstraintSystem::SolutionKind::Error;
|
||||
|
||||
return {result, {}};
|
||||
}
|
||||
|
||||
SolverStep::StepResult SolverStep::computeFollowupSteps() const {
|
||||
std::list<SolverStep> nextSteps;
|
||||
// Compute next steps based on that connected components
|
||||
// algorithm tells us is splittable.
|
||||
return {ConstraintSystem::SolutionKind::Unsolved, std::move(nextSteps)};
|
||||
}
|
||||
Reference in New Issue
Block a user