[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:
Pavel Yaskevich
2018-09-03 00:12:32 -07:00
parent 9bff72aa8d
commit daf4c2f3b5
5 changed files with 278 additions and 0 deletions

71
lib/Sema/CSStep.cpp Normal file
View 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)};
}