//also used by XPathPatternBuilder public static QilNode BuildOnePredicate(QilNode nodeset, QilNode predicate, bool isReverseStep, XPathQilFactory f, FixupVisitor fixupVisitor, ref int numFixupCurrent, ref int numFixupPosition, ref int numFixupLast) { nodeset = f.EnsureNodeSet(nodeset); // Mirgeing nodeset and predicate: // 1. Predicate contains 0 last() : // for $i in nodeset // where predicate // return $i // Note: Currently we are keepeing old output to minimize diff. // 2. Predicate contains 1 last() // let $cach := nodeset return // for $i in $cach // where predicate(length($cach)) // return $i // Suggestion: This is a little optimisation we can do or don't do. // 3. Predicate contains 2+ last() // let $cash := nodeset return // let $size := length($cash) return // for $i in $cash // where predicate($size) // return $i QilNode result; if (numFixupLast != 0 && fixupVisitor.CountUnfixedLast(predicate) != 0) { // this subtree has unfixed last() nodes QilIterator cash = f.Let(nodeset); QilIterator size = f.Let(f.XsltConvert(f.Length(cash), T.DoubleX)); QilIterator it = f.For(cash); predicate = fixupVisitor.Fixup(predicate, /*current:*/ it, /*last:*/ size); numFixupCurrent -= fixupVisitor.numCurrent; numFixupPosition -= fixupVisitor.numPosition; numFixupLast -= fixupVisitor.numLast; result = f.Loop(cash, f.Loop(size, f.Filter(it, predicate))); } else { QilIterator it = f.For(nodeset); predicate = fixupVisitor.Fixup(predicate, /*current:*/ it, /*last:*/ null); numFixupCurrent -= fixupVisitor.numCurrent; numFixupPosition -= fixupVisitor.numPosition; numFixupLast -= fixupVisitor.numLast; result = f.Filter(it, predicate); } if (isReverseStep) { result = f.DocOrderDistinct(result); } return(result); }
public virtual QilNode?EndBuild(QilNode?result) { if (result == null) { // special door to clean builder state in exception handlers _inTheBuild = false; return(result); } Debug.Assert(_inTheBuild, "StartBuild() wasn't called"); if (result.XmlType !.MaybeMany && result.XmlType.IsNode && result.XmlType.IsNotRtf) { result = _f.DocOrderDistinct(result); } result = _fixupVisitor.Fixup(result, /*environment:*/ _environment); numFixupCurrent -= _fixupVisitor.numCurrent; numFixupPosition -= _fixupVisitor.numPosition; numFixupLast -= _fixupVisitor.numLast; // All these variables will be positive for "false() and (. = position() + last())" // since QilPatternFactory eliminates the right operand of 'and' Debug.Assert(numFixupCurrent >= 0, "Context fixup error"); Debug.Assert(numFixupPosition >= 0, "Context fixup error"); Debug.Assert(numFixupLast >= 0, "Context fixup error"); _inTheBuild = false; return(result); }