Optional<ProjectionPath> ProjectionPath::subtractPaths(const ProjectionPath &LHS, const ProjectionPath &RHS) { // If RHS is greater than or equal to LHS in size, RHS can not be a prefix of // LHS. Return None. unsigned RHSSize = RHS.size(); unsigned LHSSize = LHS.size(); if (RHSSize >= LHSSize) return llvm::NoneType::None; // First make sure that the prefix matches. Optional<ProjectionPath> P = ProjectionPath(); for (unsigned i = 0; i < RHSSize; i++) { if (LHS.Path[i] != RHS.Path[i]) { P.reset(); return P; } } // Add the rest of LHS to P and return P. for (unsigned i = RHSSize, e = LHSSize; i != e; ++i) { P->Path.push_back(LHS.Path[i]); } return P; }
/// TODO: Integrate has empty non-symmetric difference into here. SubSeqRelation_t ProjectionPath:: computeSubSeqRelation(const ProjectionPath &RHS) const { // If either path is empty, we can not prove anything, return Unrelated. if (empty() || RHS.empty()) return SubSeqRelation_t::Unrelated; // We reverse the projection path to scan from the common object. auto LHSReverseIter = rbegin(); auto RHSReverseIter = RHS.rbegin(); unsigned MinPathSize = std::min(size(), RHS.size()); // For each index i until min path size... for (unsigned i = 0; i != MinPathSize; ++i) { // Grab the current projections. const Projection &LHSProj = *LHSReverseIter; const Projection &RHSProj = *RHSReverseIter; // If the two projections do not equal exactly, return Unrelated. // // TODO: If Index equals zero, then we know that the two lists have nothing // in common and should return unrelated. If Index is greater than zero, // then we know that the two projection paths have a common base but a // non-empty symmetric difference. For now we just return Unrelated since I // can not remember why I had the special check in the // hasNonEmptySymmetricDifference code. if (LHSProj != RHSProj) return SubSeqRelation_t::Unrelated; // Otherwise increment reverse iterators. LHSReverseIter++; RHSReverseIter++; } // Ok, we now know that one of the paths is a subsequence of the other. If // both size() and RHS.size() equal then we know that the entire sequences // equal. if (size() == RHS.size()) return SubSeqRelation_t::Equal; // If MinPathSize == size(), then we know that LHS is a strict subsequence of // RHS. if (MinPathSize == size()) return SubSeqRelation_t::LHSStrictSubSeqOfRHS; // Otherwise, we know that MinPathSize must be RHS.size() and RHS must be a // strict subsequence of LHS. Assert to check this and return. assert(MinPathSize == RHS.size() && "Since LHS and RHS don't equal and size() != MinPathSize, RHS.size() " "must equal MinPathSize"); return SubSeqRelation_t::RHSStrictSubSeqOfLHS; }
/// Returns true if the two paths have a non-empty symmetric difference. /// /// This means that the two objects have the same base but access different /// fields of the base object. bool ProjectionPath:: hasNonEmptySymmetricDifference(const ProjectionPath &RHS) const { // If either the LHS or RHS is empty, there is no common base class. Return // false. if (empty() || RHS.empty()) return false; // We reverse the projection path to scan from the common object. auto LHSReverseIter = Path.rbegin(); auto RHSReverseIter = RHS.Path.rbegin(); // For each index i until min path size... for (unsigned i = 0, e = std::min(size(), RHS.size()); i != e; ++i) { // Grab the current projections. const Projection &LHSProj = *LHSReverseIter; const Projection &RHSProj = *RHSReverseIter; // If we are accessing different fields of a common object, return // true. The two projection paths must have a non-empty symmetric // difference. if (areProjectionsToDifferentFields(LHSProj, RHSProj)) { DEBUG(llvm::dbgs() << " Path different at index: " << i << '\n'); return true; } // Otherwise, if the two projections equal exactly, they have no symmetric // difference. if (LHSProj == RHSProj) return false; // Continue if we are accessing the same field. LHSReverseIter++; RHSReverseIter++; } // We checked return false; }