// Constraints up to but not including iterator it have been unified. // The current solution is soln // The set of all solutions is in solns bool Constraints::doSolve(std::list<Exp*>::iterator it, ConstraintMap& soln, std::list<ConstraintMap>& solns) { LOG << "Begin doSolve at level " << ++level << "\n"; LOG << "Soln now: " << soln.prints() << "\n"; if (it == disjunctions.end()) { // We have gotten to the end with no unification failures // Copy the current set of constraints as a solution //if (soln.size() == 0) // Awkward. There is a trivial solution, but we have no constraints // So make a constraint of always-true //soln.insert(new Terminal(opTrue)); // Copy the fixed constraints soln.makeUnion(fixed); solns.push_back(soln); LOG << "Exiting doSolve at level " << level-- << " returning true\n"; return true; } Exp* dj = *it; // Iterate through each disjunction d of dj Exp* rem1 = dj; // Remainder bool anyUnified = false; Exp* d; while ((d = nextDisjunct(rem1)) != NULL) { LOG << " $$ d is " << d << ", rem1 is " << ((rem1==0)?"NULL":rem1->prints()) << " $$\n"; // Match disjunct d against the fixed types; it could be compatible, // compatible and generate an additional constraint, or be // incompatible ConstraintMap extra; // Just for this disjunct Exp* c; Exp* rem2 = d; bool unified = true; while ((c = nextConjunct(rem2)) != NULL) { LOG << " $$ c is " << c << ", rem2 is " << ((rem2==0)?"NULL":rem2->prints()) << " $$\n"; if (c->isFalse()) { unified = false; break; } assert(c->isEquality()); Exp* lhs = ((Binary*)c)->getSubExp1(); Exp* rhs = ((Binary*)c)->getSubExp2(); extra.insert(lhs, rhs); ConstraintMap::iterator kk; kk = fixed.find(lhs); if (kk != fixed.end()) { unified &= unify(rhs, kk->second, extra); LOG << "Unified now " << unified << "; extra now " << extra.prints() << "\n"; if (!unified) break; } } if (unified) // True if any disjuncts had all the conjuncts satisfied anyUnified = true; if (!unified) continue; // Use this disjunct // We can't just difference out extra if this fails; it may remove // elements from soln that should not be removed // So need a copy of the old set in oldSoln ConstraintMap oldSoln = soln; soln.makeUnion(extra); doSolve(++it, soln, solns); // Revert to the previous soln (whether doSolve returned true or not) // If this recursion did any good, it will have gotten to the end and // added the resultant soln to solns soln = oldSoln; LOG << "After doSolve returned: soln back to: " << soln.prints() << "\n"; // Back to the current disjunction it--; // Continue for more disjuncts this disjunction } // We have run out of disjuncts. Return true if any disjuncts had no // unification failures LOG << "Exiting doSolve at level " << level-- << " returning " << anyUnified << "\n"; return anyUnified; }