public void AddTemplateMatch(Template template, QilLoop filter) { List<TemplateMatch> matchesForMode; if (!TemplateMatches.TryGetValue(template.Mode, out matchesForMode)) { matchesForMode = TemplateMatches[template.Mode] = new List<TemplateMatch>(); } matchesForMode.Add(new TemplateMatch(template, filter)); }
//----------------------------------------------- // sorting //----------------------------------------------- public QilLoop Sort(QilNode variable, QilNode body) { QilLoop n = new QilLoop(QilNodeType.Sort, variable, body); n.XmlType = this.typeCheck.CheckSort(n); TraceNode(n); return(n); }
//----------------------------------------------- // loops //----------------------------------------------- public QilLoop Loop(QilNode variable, QilNode body) { QilLoop n = new QilLoop(QilNodeType.Loop, variable, body); n.XmlType = _typeCheck.CheckLoop(n); TraceNode(n); return(n); }
public QilLoop Filter(QilNode variable, QilNode body) { QilLoop n = new QilLoop(QilNodeType.Filter, variable, body); n.XmlType = this.typeCheck.CheckFilter(n); TraceNode(n); return(n); }
//----------------------------------------------- // sorting //----------------------------------------------- public XmlQueryType CheckSort(QilLoop node) { XmlQueryType varType = node.Variable.Binding.XmlType; CheckClassAndNodeType(node[0], typeof(QilIterator), QilNodeType.For); CheckClassAndNodeType(node[1], typeof(QilList), QilNodeType.SortKeyList); // Sort does not preserve DocOrderDistinct return(XmlQueryTypeFactory.PrimeProduct(varType, varType.Cardinality)); }
//----------------------------------------------- // loops //----------------------------------------------- public XmlQueryType CheckLoop(QilLoop node) { CheckClass(node[0], typeof(QilIterator)); Check(node.Variable.NodeType == QilNodeType.For || node.Variable.NodeType == QilNodeType.Let, node, "Loop variable must be a For or Let iterator"); XmlQueryType bodyType = node.Body.XmlType; XmlQueryCardinality variableCard = node.Variable.NodeType == QilNodeType.Let ? XmlQueryCardinality.One : node.Variable.Binding.XmlType.Cardinality; // Loops do not preserve DocOrderDistinct return(XmlQueryTypeFactory.PrimeProduct(bodyType, variableCard * bodyType.Cardinality)); }
public XmlQueryType CheckFilter(QilLoop node) { CheckClass(node[0], typeof(QilIterator)); Check(node.Variable.NodeType == QilNodeType.For || node.Variable.NodeType == QilNodeType.Let, node, "Filter variable must be a For or Let iterator"); CheckXmlType(node.Body, XmlQueryTypeFactory.BooleanX); // Attempt to restrict filter's type by checking condition XmlQueryType filterType = FindFilterType(node.Variable, node.Body); if (filterType != null) { return(filterType); } return(XmlQueryTypeFactory.AtMost(node.Variable.Binding.XmlType, node.Variable.Binding.XmlType.Cardinality)); }
protected override QilNode VisitSort(QilLoop n) { return(NoReplace(n)); }
protected override QilNode VisitSort(QilLoop local0) { QilNode local1 = local0[0]; QilNode local2 = local0[1]; if (this[XmlILOptimization.FoldNone]) { if ( (object) ( (local1).XmlType ) == (object) XmlQueryTypeFactory.None ) { if (AllowReplace(XmlILOptimization.FoldNone, local0)) { return Replace(XmlILOptimization.FoldNone, local0, VisitNop(f.Nop( (QilNode) (local1)[0] ))); } } } if (this[XmlILOptimization.EliminateSort]) { if (local1.NodeType == QilNodeType.For) { QilNode local3 = local1[0]; if ( ( (local3).XmlType ).IsSingleton ) { if (AllowReplace(XmlILOptimization.EliminateSort, local0)) { return Replace(XmlILOptimization.EliminateSort, local0, VisitNop(f.Nop(local3))); } } } } return NoReplace(local0); }
private static void SetLastParent(QilNode node, QilLoop parent) { Debug.Assert(parent.NodeType == QilNodeType.Filter); Annotation ann = (Annotation)node.Annotation ?? new Annotation(); ann.Parent = parent; node.Annotation = ann; }
protected override QilNode VisitFilter(QilLoop local0) { QilNode local1 = local0[0]; QilNode local2 = local0[1]; if (this[XmlILOptimization.FoldNone]) { if ((object)((local1).XmlType) == (object)XmlQueryTypeFactory.None) { // PATTERN: [FoldNone] (Filter $i:* ^ (None? (TypeOf $i)) *) => (Nop (First $i)) if (AllowReplace(XmlILOptimization.FoldNone, local0)) { return Replace(XmlILOptimization.FoldNone, local0, VisitNop(f.Nop((QilNode)(local1)[0]))); } } } if (this[XmlILOptimization.FoldNone]) { if ((object)((local2).XmlType) == (object)XmlQueryTypeFactory.None) { // PATTERN: [FoldNone] (Filter $i:* $w:* ^ (None? (TypeOf $w))) => (Loop $i $w) if (AllowReplace(XmlILOptimization.FoldNone, local0)) { return Replace(XmlILOptimization.FoldNone, local0, VisitLoop(f.Loop(local1, local2))); } } } if (this[XmlILOptimization.EliminateFilter]) { if (!OptimizerPatterns.Read(local1).MatchesPattern(OptimizerPatternName.MaybeSideEffects)) { if (local2.NodeType == QilNodeType.False) { // PATTERN: [EliminateFilter] (Filter $i:* ^ (NoSideEffects? $i) (False)) => (Sequence) if (AllowReplace(XmlILOptimization.EliminateFilter, local0)) { return Replace(XmlILOptimization.EliminateFilter, local0, VisitSequence(f.Sequence())); } } } } if (this[XmlILOptimization.EliminateFilter]) { if (local2.NodeType == QilNodeType.True) { // PATTERN: [EliminateFilter] (Filter $i:* (True)) => (First $i) if (AllowReplace(XmlILOptimization.EliminateFilter, local0)) { return Replace(XmlILOptimization.EliminateFilter, local0, (QilNode)(local1)[0]); } } } if (this[XmlILOptimization.NormalizeAttribute]) { if (local1.NodeType == QilNodeType.For) { QilNode local3 = local1[0]; if (local3.NodeType == QilNodeType.Content) { QilNode local4 = local3[0]; if (local2.NodeType == QilNodeType.And) { QilNode local5 = local2[0]; QilNode local9 = local2[1]; if (local5.NodeType == QilNodeType.IsType) { QilNode local6 = local5[0]; QilNode local7 = local5[1]; if (local6 == local1) { if (local7.NodeType == QilNodeType.LiteralType) { XmlQueryType local8 = (XmlQueryType)((QilLiteral)local7).Value; if ((local8) == (XmlQueryTypeFactory.Attribute)) { if (local9.NodeType == QilNodeType.Eq) { QilNode local10 = local9[0]; QilNode local12 = local9[1]; if (local10.NodeType == QilNodeType.NameOf) { QilNode local11 = local10[0]; if (local11 == local1) { if (local12.NodeType == QilNodeType.LiteralQName) { // PATTERN: [NormalizeAttribute] (Filter $iter:(For (Content $input:*)) (And (IsType $iter (LiteralType $typ:* ^ (Equal? $typ (ConstructType {Attribute})))) (Eq (NameOf $iter) $qname:(LiteralQName * * *)))) => (Attribute $input $qname) if (AllowReplace(XmlILOptimization.NormalizeAttribute, local0)) { return Replace(XmlILOptimization.NormalizeAttribute, local0, VisitAttribute(f.Attribute(local4, local12))); } } } } } } } } } } } } } if (this[XmlILOptimization.CommuteFilterLoop]) { if (local1.NodeType == QilNodeType.For) { QilNode local3 = local1[0]; if (local3.NodeType == QilNodeType.Loop) { QilNode local4 = local3[0]; QilNode local5 = local3[1]; if ((NonPositional(local2, local1)) && (!(IsDocOrderDistinct(local3)))) { // PATTERN: [CommuteFilterLoop] (Filter $iter:(For $loop:(Loop $iter2:* $ret2:*)) $cond:* ^ (NonPositional? $cond $iter) ^ ~((DocOrderDistinct? $loop))) => (Loop $iter2 (Filter $iter3:(For $ret2) (Subs $cond $iter $iter3))) if (AllowReplace(XmlILOptimization.CommuteFilterLoop, local0)) { QilNode local6 = VisitFor(f.For(local5)); return Replace(XmlILOptimization.CommuteFilterLoop, local0, VisitLoop(f.Loop(local4, VisitFilter(f.Filter(local6, Subs(local2, local1, local6)))))); } } } } } if (this[XmlILOptimization.NormalizeLoopInvariant]) { if ((!OptimizerPatterns.Read(local1).MatchesPattern(OptimizerPatternName.MaybeSideEffects)) && (!(((QilNode)(local1)[0]).NodeType == QilNodeType.OptimizeBarrier))) { if ((!(DependsOn(local2, local1))) && (!OptimizerPatterns.Read(local2).MatchesPattern(OptimizerPatternName.MaybeSideEffects))) { // PATTERN: [NormalizeLoopInvariant] (Filter $iter:* ^ (NoSideEffects? $iter) ^ ~((NodeType? (First $iter) {OptimizeBarrier})) $cond:* ^ ~($cond >> $iter) ^ (NoSideEffects? $cond)) => (Conditional $cond (First $iter) (Sequence)) if (AllowReplace(XmlILOptimization.NormalizeLoopInvariant, local0)) { return Replace(XmlILOptimization.NormalizeLoopInvariant, local0, VisitConditional(f.Conditional(local2, (QilNode)(local1)[0], VisitSequence(f.Sequence())))); } } } } if (this[XmlILOptimization.AnnotateMaxPositionEq]) { if (local2.NodeType == QilNodeType.Eq) { QilNode local3 = local2[0]; QilNode local5 = local2[1]; if (local3.NodeType == QilNodeType.PositionOf) { QilNode local4 = local3[0]; if (local4 == local1) { if (local5.NodeType == QilNodeType.LiteralInt32) { int local6 = (int)((QilLiteral)local5).Value; // PATTERN: [AnnotateMaxPositionEq] $outer:(Filter $iter:* (Eq (PositionOf $iter) (LiteralInt32 $num:*))) => (AddPattern $iter {MaxPosition}) ^ (AddArgument $iter {MaxPosition} $num) ^ { } if (AllowReplace(XmlILOptimization.AnnotateMaxPositionEq, local0)) { OptimizerPatterns.Write((QilNode)(local1)).AddPattern(OptimizerPatternName.MaxPosition); OptimizerPatterns.Write((QilNode)(local1)).AddArgument(OptimizerPatternArgument.MaxPosition, local6); } } } } } } if (this[XmlILOptimization.AnnotateMaxPositionLe]) { if (local2.NodeType == QilNodeType.Le) { QilNode local3 = local2[0]; QilNode local5 = local2[1]; if (local3.NodeType == QilNodeType.PositionOf) { QilNode local4 = local3[0]; if (local4 == local1) { if (local5.NodeType == QilNodeType.LiteralInt32) { int local6 = (int)((QilLiteral)local5).Value; // PATTERN: [AnnotateMaxPositionLe] $outer:(Filter $iter:* (Le (PositionOf $iter) (LiteralInt32 $num:*))) => (AddPattern $iter {MaxPosition}) ^ (AddArgument $iter {MaxPosition} $num) ^ { } if (AllowReplace(XmlILOptimization.AnnotateMaxPositionLe, local0)) { OptimizerPatterns.Write((QilNode)(local1)).AddPattern(OptimizerPatternName.MaxPosition); OptimizerPatterns.Write((QilNode)(local1)).AddArgument(OptimizerPatternArgument.MaxPosition, local6); } } } } } } if (this[XmlILOptimization.AnnotateMaxPositionLt]) { if (local2.NodeType == QilNodeType.Lt) { QilNode local3 = local2[0]; QilNode local5 = local2[1]; if (local3.NodeType == QilNodeType.PositionOf) { QilNode local4 = local3[0]; if (local4 == local1) { if (local5.NodeType == QilNodeType.LiteralInt32) { int local6 = (int)((QilLiteral)local5).Value; // PATTERN: [AnnotateMaxPositionLt] $outer:(Filter $iter:* (Lt (PositionOf $iter) (LiteralInt32 $num:*))) => (AddPattern $iter {MaxPosition}) ^ (AddArgument $iter {MaxPosition} { {$num} - 1 }) ^ { } if (AllowReplace(XmlILOptimization.AnnotateMaxPositionLt, local0)) { OptimizerPatterns.Write((QilNode)(local1)).AddPattern(OptimizerPatternName.MaxPosition); OptimizerPatterns.Write((QilNode)(local1)).AddArgument(OptimizerPatternArgument.MaxPosition, local6 - 1); } } } } } } if (this[XmlILOptimization.AnnotateFilter]) { if (local1.NodeType == QilNodeType.For) { QilNode local3 = local1[0]; // PATTERN: [AnnotateFilter] $outer:(Filter $iter:(For $bind:*) *) => (InheritPattern $outer $bind {Step}) ^ (InheritPattern $outer $bind {IsDocOrderDistinct}) ^ (InheritPattern $outer $bind {SameDepth}) ^ { } if (AllowReplace(XmlILOptimization.AnnotateFilter, local0)) { OptimizerPatterns.Inherit((QilNode)(local3), (QilNode)(local0), OptimizerPatternName.Step); OptimizerPatterns.Inherit((QilNode)(local3), (QilNode)(local0), OptimizerPatternName.IsDocOrderDistinct); OptimizerPatterns.Inherit((QilNode)(local3), (QilNode)(local0), OptimizerPatternName.SameDepth); } } } if (this[XmlILOptimization.AnnotateFilterElements]) { if (local1.NodeType == QilNodeType.For) { QilNode local3 = local1[0]; if (OptimizerPatterns.Read((QilNode)(local3)).MatchesPattern(OptimizerPatternName.Axis)) { if (local2.NodeType == QilNodeType.And) { QilNode local4 = local2[0]; QilNode local8 = local2[1]; if (local4.NodeType == QilNodeType.IsType) { QilNode local5 = local4[0]; QilNode local6 = local4[1]; if (local5 == local1) { if (local6.NodeType == QilNodeType.LiteralType) { XmlQueryType local7 = (XmlQueryType)((QilLiteral)local6).Value; if ((local7) == (XmlQueryTypeFactory.Element)) { if (local8.NodeType == QilNodeType.Eq) { QilNode local9 = local8[0]; QilNode local11 = local8[1]; if (local9.NodeType == QilNodeType.NameOf) { QilNode local10 = local9[0]; if (local10 == local1) { if (local11.NodeType == QilNodeType.LiteralQName) { // PATTERN: [AnnotateFilterElements] $outer:(Filter $iter:(For $bind:* ^ (Pattern? $bind {Axis})) (And (IsType $iter (LiteralType $typ:* ^ (Equal? $typ (ConstructType {Element})))) (Eq (NameOf $iter) $qname:(LiteralQName * * *)))) => (AddPattern $outer {FilterElements}) ^ (AddArgument $outer {ElementQName} $qname) ^ { } if (AllowReplace(XmlILOptimization.AnnotateFilterElements, local0)) { OptimizerPatterns.Write((QilNode)(local0)).AddPattern(OptimizerPatternName.FilterElements); OptimizerPatterns.Write((QilNode)(local0)).AddArgument(OptimizerPatternArgument.ElementQName, local11); } } } } } } } } } } } } } if (this[XmlILOptimization.AnnotateFilterContentKind]) { if (local1.NodeType == QilNodeType.For) { QilNode local3 = local1[0]; if (OptimizerPatterns.Read((QilNode)(local3)).MatchesPattern(OptimizerPatternName.Axis)) { if (local2.NodeType == QilNodeType.IsType) { QilNode local4 = local2[0]; QilNode local5 = local2[1]; if (local4 == local1) { if (local5.NodeType == QilNodeType.LiteralType) { XmlQueryType local6 = (XmlQueryType)((QilLiteral)local5).Value; if (MatchesContentTest(local6)) { // PATTERN: [AnnotateFilterContentKind] $outer:(Filter $iter:(For $bind:* ^ (Pattern? $bind {Axis})) (IsType $iter (LiteralType $kind:* ^ (ContentTest? $kind)))) => (AddPattern $outer {FilterContentKind}) ^ (AddArgument $outer {KindTestType} $kind) ^ { } if (AllowReplace(XmlILOptimization.AnnotateFilterContentKind, local0)) { OptimizerPatterns.Write((QilNode)(local0)).AddPattern(OptimizerPatternName.FilterContentKind); OptimizerPatterns.Write((QilNode)(local0)).AddArgument(OptimizerPatternArgument.KindTestType, local6); } } } } } } } } if (this[XmlILOptimization.AnnotateFilterAttributeKind]) { if (local1.NodeType == QilNodeType.For) { QilNode local3 = local1[0]; if (local3.NodeType == QilNodeType.Content) { if (local2.NodeType == QilNodeType.IsType) { QilNode local5 = local2[0]; QilNode local6 = local2[1]; if (local5 == local1) { if (local6.NodeType == QilNodeType.LiteralType) { XmlQueryType local7 = (XmlQueryType)((QilLiteral)local6).Value; if ((local7) == (XmlQueryTypeFactory.Attribute)) { // PATTERN: [AnnotateFilterAttributeKind] $outer:(Filter $iter:(For (Content *)) (IsType $iter (LiteralType $kind:*) ^ (Equal? $kind (ConstructType {Attribute})))) => (AddPattern $outer {FilterAttributeKind}) ^ { } if (AllowReplace(XmlILOptimization.AnnotateFilterAttributeKind, local0)) { OptimizerPatterns.Write((QilNode)(local0)).AddPattern(OptimizerPatternName.FilterAttributeKind); } } } } } } } } return NoReplace(local0); }
protected override QilNode VisitSort(QilLoop n) { return NoReplace(n); }
// Filers that travers Content being converted to global travers: // Filter($j= ... Filter($i = Content(fixup), ...)) -> Filter($j= ... Filter($i = Loop($j = DesendentOrSelf(Root(fixup)), Content($j), ...))) protected override QilNode VisitLoop(QilLoop n) { if (n.Variable.Binding.NodeType == QilNodeType.Root || n.Variable.Binding.NodeType == QilNodeType.Deref) { // This is absolute path already. We shouldn't touch it return n; } if (n.Variable.Binding.NodeType == QilNodeType.Content) { // This is "begin" of reletive path. Let's rewrite it as absolute: QilUnary content = (QilUnary)n.Variable.Binding; Debug.Assert(content.Child == this.fixup, "Unexpected content node"); QilIterator it = f.For(f.DescendantOrSelf(f.Root(this.fixup))); content.Child = it; n.Variable.Binding = f.Loop(it, content); return n; } n.Variable.Binding = Visit(n.Variable.Binding); return n; }
/// <summary> /// Generate code for QilNodeType.Sort. /// </summary> protected override QilNode VisitSort(QilLoop ndSort) { Type itemStorageType = GetItemStorageType(ndSort); LocalBuilder locCache, locKeys; Label lblOnEndSort = _helper.DefineLabel(); Debug.Assert(ndSort.Variable.NodeType == QilNodeType.For); // XmlQuerySequence<T> cache; // cache = XmlQuerySequence.CreateOrReuse(cache); XmlILStorageMethods methods = XmlILMethods.StorageMethods[itemStorageType]; locCache = _helper.DeclareLocal("$$$cache", methods.SeqType); _helper.Emit(OpCodes.Ldloc, locCache); _helper.CallToken(methods.SeqReuse); _helper.Emit(OpCodes.Stloc, locCache); _helper.Emit(OpCodes.Ldloc, locCache); // XmlSortKeyAccumulator keys; // keys.Create(runtime); locKeys = _helper.DeclareLocal("$$$keys", typeof(XmlSortKeyAccumulator)); _helper.Emit(OpCodes.Ldloca, locKeys); _helper.Call(XmlILMethods.SortKeyCreate); // Construct nested iterator // foreach (item in sort-expr) { StartNestedIterator(ndSort.Variable, lblOnEndSort); StartBinding(ndSort.Variable); Debug.Assert(!_iterNested.Storage.IsCached); // cache.Add(item); _iterCurr.EnsureStackNoCache(); _iterCurr.EnsureItemStorageType(ndSort.Variable.XmlType, GetItemStorageType(ndSort.Variable)); _helper.Call(methods.SeqAdd); _helper.Emit(OpCodes.Ldloca, locKeys); // Add keys to accumulator (there may be several keys) foreach (QilSortKey ndKey in ndSort.Body) VisitSortKey(ndKey, locKeys); // keys.FinishSortKeys(); _helper.Call(XmlILMethods.SortKeyFinish); // } _helper.Emit(OpCodes.Ldloc, locCache); _iterCurr.LoopToEnd(lblOnEndSort); // Remove cache reference from stack _helper.Emit(OpCodes.Pop); // cache.SortByKeys(keys.Keys); _helper.Emit(OpCodes.Ldloc, locCache); _helper.Emit(OpCodes.Ldloca, locKeys); _helper.Call(XmlILMethods.SortKeyKeys); _helper.Call(methods.SeqSortByKeys); // End nested iterator _iterCurr.Storage = StorageDescriptor.Local(locCache, itemStorageType, true); EndBinding(ndSort.Variable); EndNestedIterator(ndSort.Variable); _iterCurr.SetIterator(_iterNested); return ndSort; }
private void FixupFilterBinding(QilLoop filter, QilNode newBinding) { AssertFilter(filter); filter.Variable.Binding = newBinding; }
/// <summary> /// Generate code for a QilNodeType.Filter. /// </summary> protected override QilNode VisitFilter(QilLoop ndFilter) { // Handle any special-case patterns that are rooted at Filter if (HandleFilterPatterns(ndFilter)) return ndFilter; StartBinding(ndFilter.Variable); // Result of filter is the sequence bound to the iterator _iterCurr.SetIterator(_iterNested); // If filter is false, skip the current item StartNestedIterator(ndFilter.Body); _iterCurr.SetBranching(BranchingContext.OnFalse, _iterCurr.ParentIterator.GetLabelNext()); Visit(ndFilter.Body); EndNestedIterator(ndFilter.Body); EndBinding(ndFilter.Variable); return ndFilter; }
/// <summary> /// There are a number of path patterns that can be rooted at Filter nodes. Determine whether one of these patterns /// has been previously matched on "ndFilter". If so, generate code for the pattern and return true. Otherwise, just /// return false. /// </summary> private bool HandleFilterPatterns(QilLoop ndFilter) { OptimizerPatterns patt = OptimizerPatterns.Read(ndFilter); LocalBuilder locIter; XmlNodeKindFlags kinds; QilName name; QilNode input, step; bool isFilterElements; // Handle FilterElements and FilterContentKind patterns isFilterElements = patt.MatchesPattern(OptimizerPatternName.FilterElements); if (isFilterElements || patt.MatchesPattern(OptimizerPatternName.FilterContentKind)) { if (isFilterElements) { // FilterElements pattern, so Kind = Element and Name = Argument kinds = XmlNodeKindFlags.Element; name = (QilName)patt.GetArgument(OptimizerPatternArgument.ElementQName); } else { // FilterKindTest pattern, so Kind = Argument and Name = null kinds = ((XmlQueryType)patt.GetArgument(OptimizerPatternArgument.KindTestType)).NodeKinds; name = null; } step = (QilNode)patt.GetArgument(OptimizerPatternArgument.StepNode); input = (QilNode)patt.GetArgument(OptimizerPatternArgument.StepInput); switch (step.NodeType) { case QilNodeType.Content: if (isFilterElements) { // Iterator iter; locIter = _helper.DeclareLocal("$$$iterElemContent", typeof(ElementContentIterator)); // iter.Create(navCtxt, locName, ns); _helper.Emit(OpCodes.Ldloca, locIter); NestedVisitEnsureStack(input); _helper.CallGetAtomizedName(_helper.StaticData.DeclareName(name.LocalName)); _helper.CallGetAtomizedName(_helper.StaticData.DeclareName(name.NamespaceUri)); _helper.Call(XmlILMethods.ElemContentCreate); GenerateSimpleIterator(typeof(XPathNavigator), locIter, XmlILMethods.ElemContentNext); } else { if (kinds == XmlNodeKindFlags.Content) { CreateSimpleIterator(input, "$$$iterContent", typeof(ContentIterator), XmlILMethods.ContentCreate, XmlILMethods.ContentNext); } else { // Iterator iter; locIter = _helper.DeclareLocal("$$$iterContent", typeof(NodeKindContentIterator)); // iter.Create(navCtxt, nodeType); _helper.Emit(OpCodes.Ldloca, locIter); NestedVisitEnsureStack(input); _helper.LoadInteger((int)QilXmlToXPathNodeType(kinds)); _helper.Call(XmlILMethods.KindContentCreate); GenerateSimpleIterator(typeof(XPathNavigator), locIter, XmlILMethods.KindContentNext); } } return true; case QilNodeType.Parent: CreateFilteredIterator(input, "$$$iterPar", typeof(ParentIterator), XmlILMethods.ParentCreate, XmlILMethods.ParentNext, kinds, name, TriState.Unknown, null); return true; case QilNodeType.Ancestor: case QilNodeType.AncestorOrSelf: CreateFilteredIterator(input, "$$$iterAnc", typeof(AncestorIterator), XmlILMethods.AncCreate, XmlILMethods.AncNext, kinds, name, (step.NodeType == QilNodeType.Ancestor) ? TriState.False : TriState.True, null); return true; case QilNodeType.Descendant: case QilNodeType.DescendantOrSelf: CreateFilteredIterator(input, "$$$iterDesc", typeof(DescendantIterator), XmlILMethods.DescCreate, XmlILMethods.DescNext, kinds, name, (step.NodeType == QilNodeType.Descendant) ? TriState.False : TriState.True, null); return true; case QilNodeType.Preceding: CreateFilteredIterator(input, "$$$iterPrec", typeof(PrecedingIterator), XmlILMethods.PrecCreate, XmlILMethods.PrecNext, kinds, name, TriState.Unknown, null); return true; case QilNodeType.FollowingSibling: CreateFilteredIterator(input, "$$$iterFollSib", typeof(FollowingSiblingIterator), XmlILMethods.FollSibCreate, XmlILMethods.FollSibNext, kinds, name, TriState.Unknown, null); return true; case QilNodeType.PrecedingSibling: CreateFilteredIterator(input, "$$$iterPreSib", typeof(PrecedingSiblingIterator), XmlILMethods.PreSibCreate, XmlILMethods.PreSibNext, kinds, name, TriState.Unknown, null); return true; case QilNodeType.NodeRange: CreateFilteredIterator(input, "$$$iterRange", typeof(NodeRangeIterator), XmlILMethods.NodeRangeCreate, XmlILMethods.NodeRangeNext, kinds, name, TriState.Unknown, ((QilBinary)step).Right); return true; case QilNodeType.XPathFollowing: CreateFilteredIterator(input, "$$$iterFoll", typeof(XPathFollowingIterator), XmlILMethods.XPFollCreate, XmlILMethods.XPFollNext, kinds, name, TriState.Unknown, null); return true; case QilNodeType.XPathPreceding: CreateFilteredIterator(input, "$$$iterPrec", typeof(XPathPrecedingIterator), XmlILMethods.XPPrecCreate, XmlILMethods.XPPrecNext, kinds, name, TriState.Unknown, null); return true; default: Debug.Assert(false, "Pattern " + step.NodeType + " should have been handled."); break; } } else if (patt.MatchesPattern(OptimizerPatternName.FilterAttributeKind)) { // Handle FilterAttributeKind pattern input = (QilNode)patt.GetArgument(OptimizerPatternArgument.StepInput); CreateSimpleIterator(input, "$$$iterAttr", typeof(AttributeIterator), XmlILMethods.AttrCreate, XmlILMethods.AttrNext); return true; } else if (patt.MatchesPattern(OptimizerPatternName.EqualityIndex)) { // Handle EqualityIndex pattern Label lblOnEnd = _helper.DefineLabel(); Label lblLookup = _helper.DefineLabel(); QilIterator nodes = (QilIterator)patt.GetArgument(OptimizerPatternArgument.IndexedNodes); QilNode keys = (QilNode)patt.GetArgument(OptimizerPatternArgument.KeyExpression); // XmlILIndex index; // if (runtime.FindIndex(navCtxt, indexId, out index)) goto LabelLookup; LocalBuilder locIndex = _helper.DeclareLocal("$$$index", typeof(XmlILIndex)); _helper.LoadQueryRuntime(); _helper.Emit(OpCodes.Ldarg_1); _helper.LoadInteger(_indexId); _helper.Emit(OpCodes.Ldloca, locIndex); _helper.Call(XmlILMethods.FindIndex); _helper.Emit(OpCodes.Brtrue, lblLookup); // runtime.AddNewIndex(navCtxt, indexId, [build index]); _helper.LoadQueryRuntime(); _helper.Emit(OpCodes.Ldarg_1); _helper.LoadInteger(_indexId); _helper.Emit(OpCodes.Ldloc, locIndex); // Generate code to iterate over the the nodes which are being indexed ($iterNodes in the pattern) StartNestedIterator(nodes, lblOnEnd); StartBinding(nodes); // Generate code to iterate over the keys for each node ($bindingKeys in the pattern) Visit(keys); // index.Add(key, value); _iterCurr.EnsureStackNoCache(); VisitFor(nodes); _iterCurr.EnsureStackNoCache(); _iterCurr.EnsureItemStorageType(nodes.XmlType, typeof(XPathNavigator)); _helper.Call(XmlILMethods.IndexAdd); _helper.Emit(OpCodes.Ldloc, locIndex); // LabelOnEnd: _iterCurr.LoopToEnd(lblOnEnd); EndBinding(nodes); EndNestedIterator(nodes); // runtime.AddNewIndex(navCtxt, indexId, [build index]); _helper.Call(XmlILMethods.AddNewIndex); // LabelLookup: // results = index.Lookup(keyValue); _helper.MarkLabel(lblLookup); _helper.Emit(OpCodes.Ldloc, locIndex); _helper.Emit(OpCodes.Ldarg_2); _helper.Call(XmlILMethods.IndexLookup); _iterCurr.Storage = StorageDescriptor.Stack(typeof(XPathNavigator), true); _indexId++; return true; } return false; }
/// <summary> /// Generate code for a QilNodeType.Loop. /// </summary> protected override QilNode VisitLoop(QilLoop ndLoop) { bool hasOnEnd; Label lblOnEnd; StartWriterLoop(ndLoop, out hasOnEnd, out lblOnEnd); StartBinding(ndLoop.Variable); // Unnest loop body as part of the current iterator Visit(ndLoop.Body); EndBinding(ndLoop.Variable); EndWriterLoop(ndLoop, hasOnEnd, lblOnEnd); return ndLoop; }
//----------------------------------------------- // loops //----------------------------------------------- public QilLoop Loop(QilNode variable, QilNode body) { QilLoop n = new QilLoop(QilNodeType.Loop, variable, body); n.XmlType = _typeCheck.CheckLoop(n); TraceNode(n); return n; }
protected override QilNode VisitSort(QilLoop local0) { QilNode local1 = local0[0]; QilNode local2 = local0[1]; if (this[XmlILOptimization.FoldNone]) { if ((object)((local1).XmlType) == (object)XmlQueryTypeFactory.None) { // PATTERN: [FoldNone] (Sort $i:* ^ (None? (TypeOf $i)) *) => (Nop (First $i)) if (AllowReplace(XmlILOptimization.FoldNone, local0)) { return Replace(XmlILOptimization.FoldNone, local0, VisitNop(f.Nop((QilNode)(local1)[0]))); } } } if (this[XmlILOptimization.EliminateSort]) { if (local1.NodeType == QilNodeType.For) { QilNode local3 = local1[0]; if (((local3).XmlType).IsSingleton) { // PATTERN: [EliminateSort] (Sort (For $bind:* ^ (Single? (TypeOf $bind))) *) => (Nop $bind) if (AllowReplace(XmlILOptimization.EliminateSort, local0)) { return Replace(XmlILOptimization.EliminateSort, local0, VisitNop(f.Nop(local3))); } } } } return NoReplace(local0); }
public void SetContext(QilLoop filter) { this.baseContext = filter; }
protected virtual QilNode VisitSort(QilLoop n) { return VisitChildren(n); }
protected override QilNode VisitFilter(QilLoop n) { return NoReplace(n); }
public void AssertFilter(QilLoop filter) { Debug.Assert(filter.NodeType == QilNodeType.Filter, "XPathPatternBuilder expected to generate list of Filters on top level"); Debug.Assert(filter.Variable.XmlType.IsSubtypeOf(T.NodeNotRtf)); Debug.Assert(filter.Variable.Binding.NodeType == QilNodeType.Unknown); // fixupNode Debug.Assert(filter.Body.XmlType.IsSubtypeOf(T.Boolean)); }
protected override QilNode VisitFilter(QilLoop n) { return VisitLoop(n); }
public XmlQueryType CheckFilter(QilLoop node) { CheckClass(node[0], typeof(QilIterator)); Check(node.Variable.NodeType == QilNodeType.For || node.Variable.NodeType == QilNodeType.Let, node, "Filter variable must be a For or Let iterator"); CheckXmlType(node.Body, XmlQueryTypeFactory.BooleanX); // Attempt to restrict filter's type by checking condition XmlQueryType filterType = FindFilterType(node.Variable, node.Body); if (filterType != null) return filterType; return XmlQueryTypeFactory.AtMost(node.Variable.Binding.XmlType, node.Variable.Binding.XmlType.Cardinality); }
/// <summary> /// Analyze loop. /// </summary> protected virtual void AnalyzeLoop(QilLoop ndLoop, XmlILConstructInfo info) { XmlQueryType typ = ndLoop.XmlType; // Ensure that construct method is Writer info.ConstructMethod = XmlILConstructMethod.Writer; if (!typ.IsSingleton) StartLoop(typ, info); // Body constructs content ndLoop.Body = AnalyzeContent(ndLoop.Body); if (!typ.IsSingleton) EndLoop(typ, info); }
protected override QilNode VisitLoop(QilLoop local0) { QilNode local1 = local0[0]; QilNode local2 = local0[1]; if (this[XmlILOptimization.FoldNone]) { if ((object)((local1).XmlType) == (object)XmlQueryTypeFactory.None) { // PATTERN: [FoldNone] (Loop $i:* ^ (None? (TypeOf $i)) *) => (Nop (First $i)) if (AllowReplace(XmlILOptimization.FoldNone, local0)) { return Replace(XmlILOptimization.FoldNone, local0, VisitNop(f.Nop((QilNode)(local1)[0]))); } } } if (this[XmlILOptimization.EliminateIterator]) { if (local1.NodeType == QilNodeType.For) { QilNode local3 = local1[0]; if (local3.NodeType == QilNodeType.For) { if (!OptimizerPatterns.Read(local1).MatchesPattern(OptimizerPatternName.IsPositional)) { // PATTERN: [EliminateIterator] $outer:(Loop $iter:(For $iterRef:(For *)) ^ (NonPositionalIterator? $iter) $ret:*) => (Subs $ret $iter $iterRef) if (AllowReplace(XmlILOptimization.EliminateIterator, local0)) { return Replace(XmlILOptimization.EliminateIterator, local0, Subs(local2, local1, local3)); } } } } } if (this[XmlILOptimization.EliminateLoop]) { if (local1.NodeType == QilNodeType.For) { QilNode local3 = local1[0]; if (local3.NodeType == QilNodeType.Sequence) { if ((local3).Count == (0)) { // PATTERN: [EliminateLoop] (Loop (For $x:(Sequence) ^ (Count? $x 0)) *) => (Sequence) if (AllowReplace(XmlILOptimization.EliminateLoop, local0)) { return Replace(XmlILOptimization.EliminateLoop, local0, VisitSequence(f.Sequence())); } } } } } if (this[XmlILOptimization.EliminateLoop]) { if (!OptimizerPatterns.Read(local1).MatchesPattern(OptimizerPatternName.MaybeSideEffects)) { if (local2.NodeType == QilNodeType.Sequence) { if ((local2).Count == (0)) { // PATTERN: [EliminateLoop] (Loop $i:* ^ (NoSideEffects? $i) $x:(Sequence) ^ (Count? $x 0)) => (Sequence) if (AllowReplace(XmlILOptimization.EliminateLoop, local0)) { return Replace(XmlILOptimization.EliminateLoop, local0, VisitSequence(f.Sequence())); } } } } } if (this[XmlILOptimization.EliminateLoop]) { if (local2 == local1) { // PATTERN: [EliminateLoop] (Loop $iter:* $iter) => (First $iter) if (AllowReplace(XmlILOptimization.EliminateLoop, local0)) { return Replace(XmlILOptimization.EliminateLoop, local0, (QilNode)(local1)[0]); } } } if (this[XmlILOptimization.NormalizeLoopText]) { if (local1.NodeType == QilNodeType.For) { QilNode local3 = local1[0]; if (((local3).XmlType).IsSingleton) { if (local2.NodeType == QilNodeType.TextCtor) { QilNode local4 = local2[0]; // PATTERN: [NormalizeLoopText] (Loop $iter:(For $bind:* ^ (Single? (TypeOf $bind))) $ctor:(TextCtor $text:*)) => (TextCtor (Loop $iter $text)) if (AllowReplace(XmlILOptimization.NormalizeLoopText, local0)) { return Replace(XmlILOptimization.NormalizeLoopText, local0, VisitTextCtor(f.TextCtor(VisitLoop(f.Loop(local1, local4))))); } } } } } if (this[XmlILOptimization.EliminateIteratorUsedAtMostOnce]) { if ((((local1).NodeType == QilNodeType.Let) || ((((QilNode)(local1)[0]).XmlType).IsSingleton)) && (!OptimizerPatterns.Read(local1).MatchesPattern(OptimizerPatternName.MaybeSideEffects))) { if (_nodeCounter.Count(local2, local1) <= 1) { // PATTERN: [EliminateIteratorUsedAtMostOnce] (Loop $iter:* ^ (NodeType? $iter {Let}) | (Single? (TypeOf (First $iter))) ^ (NoSideEffects? $iter) $ret:* ^ (RefCountZeroOrOne? $ret $iter)) => (Subs $ret $iter (First $iter)) if (AllowReplace(XmlILOptimization.EliminateIteratorUsedAtMostOnce, local0)) { return Replace(XmlILOptimization.EliminateIteratorUsedAtMostOnce, local0, Subs(local2, local1, (QilNode)(local1)[0])); } } } } if (this[XmlILOptimization.NormalizeLoopConditional]) { if (local2.NodeType == QilNodeType.Conditional) { QilNode local3 = local2[0]; QilNode local4 = local2[1]; QilNode local5 = local2[2]; if (local4.NodeType == QilNodeType.Sequence) { if ((local4).Count == (0)) { if (local5 == local1) { // PATTERN: [NormalizeLoopConditional] (Loop $iter:* (Conditional $cond:* $left:(Sequence) ^ (Count? $left 0) $iter)) => (Filter $iter (Not $cond)) if (AllowReplace(XmlILOptimization.NormalizeLoopConditional, local0)) { return Replace(XmlILOptimization.NormalizeLoopConditional, local0, VisitFilter(f.Filter(local1, VisitNot(f.Not(local3))))); } } } } } } if (this[XmlILOptimization.NormalizeLoopConditional]) { if (local2.NodeType == QilNodeType.Conditional) { QilNode local3 = local2[0]; QilNode local4 = local2[1]; QilNode local5 = local2[2]; if (local4 == local1) { if (local5.NodeType == QilNodeType.Sequence) { if ((local5).Count == (0)) { // PATTERN: [NormalizeLoopConditional] (Loop $iter:* (Conditional $cond:* $iter $right:(Sequence) ^ (Count? $right 0))) => (Filter $iter $cond) if (AllowReplace(XmlILOptimization.NormalizeLoopConditional, local0)) { return Replace(XmlILOptimization.NormalizeLoopConditional, local0, VisitFilter(f.Filter(local1, local3))); } } } } } } if (this[XmlILOptimization.NormalizeLoopConditional]) { if (local1.NodeType == QilNodeType.For) { if (local2.NodeType == QilNodeType.Conditional) { QilNode local4 = local2[0]; QilNode local5 = local2[1]; QilNode local6 = local2[2]; if (local5.NodeType == QilNodeType.Sequence) { if ((local5).Count == (0)) { if (NonPositional(local6, local1)) { // PATTERN: [NormalizeLoopConditional] (Loop $iter:(For *) (Conditional $cond:* $left:(Sequence) ^ (Count? $left 0) $right:* ^ (NonPositional? $right $iter))) => (Loop $iter2:(For (Filter $iter (Not $cond))) (Subs $right $iter $iter2)) if (AllowReplace(XmlILOptimization.NormalizeLoopConditional, local0)) { QilNode local7 = VisitFor(f.For(VisitFilter(f.Filter(local1, VisitNot(f.Not(local4)))))); return Replace(XmlILOptimization.NormalizeLoopConditional, local0, VisitLoop(f.Loop(local7, Subs(local6, local1, local7)))); } } } } } } } if (this[XmlILOptimization.NormalizeLoopConditional]) { if (local1.NodeType == QilNodeType.For) { if (local2.NodeType == QilNodeType.Conditional) { QilNode local4 = local2[0]; QilNode local5 = local2[1]; QilNode local6 = local2[2]; if (NonPositional(local5, local1)) { if (local6.NodeType == QilNodeType.Sequence) { if ((local6).Count == (0)) { // PATTERN: [NormalizeLoopConditional] (Loop $iter:(For *) (Conditional $cond:* $left:* ^ (NonPositional? $left $iter) $right:(Sequence) ^ (Count? $right 0))) => (Loop $iter2:(For (Filter $iter $cond)) (Subs $left $iter $iter2)) if (AllowReplace(XmlILOptimization.NormalizeLoopConditional, local0)) { QilNode local7 = VisitFor(f.For(VisitFilter(f.Filter(local1, local4)))); return Replace(XmlILOptimization.NormalizeLoopConditional, local0, VisitLoop(f.Loop(local7, Subs(local5, local1, local7)))); } } } } } } } if (this[XmlILOptimization.NormalizeLoopLoop]) { if (local2.NodeType == QilNodeType.Loop) { QilNode local3 = local2[0]; QilNode local5 = local2[1]; if (local3.NodeType == QilNodeType.For) { QilNode local4 = local3[0]; if ((!(DependsOn(local5, local1))) && (NonPositional(local5, local3))) { // PATTERN: [NormalizeLoopLoop] (Loop $iter:* $ret:(Loop $iter2:(For $bind2:*) $ret2:* ^ ~($ret2 >> $iter) ^ (NonPositional? $ret2 $iter2))) => (Loop $iter3:(For (Loop $iter $bind2)) (Subs $ret2 $iter2 $iter3)) if (AllowReplace(XmlILOptimization.NormalizeLoopLoop, local0)) { QilNode local6 = VisitFor(f.For(VisitLoop(f.Loop(local1, local4)))); return Replace(XmlILOptimization.NormalizeLoopLoop, local0, VisitLoop(f.Loop(local6, Subs(local5, local3, local6)))); } } } } } if (this[XmlILOptimization.AnnotateSingletonLoop]) { if (local1.NodeType == QilNodeType.For) { QilNode local3 = local1[0]; if (!((local3).XmlType).MaybeMany) { // PATTERN: [AnnotateSingletonLoop] $outer:(Loop (For $bind:* ^ (AtMostOne? (TypeOf $bind))) $ret:*) => (InheritPattern $outer $ret {IsDocOrderDistinct}) ^ (InheritPattern $outer $ret {SameDepth}) ^ { } if (AllowReplace(XmlILOptimization.AnnotateSingletonLoop, local0)) { OptimizerPatterns.Inherit((QilNode)(local2), (QilNode)(local0), OptimizerPatternName.IsDocOrderDistinct); OptimizerPatterns.Inherit((QilNode)(local2), (QilNode)(local0), OptimizerPatternName.SameDepth); } } } } if (this[XmlILOptimization.AnnotateRootLoop]) { if (IsStepPattern(local2, QilNodeType.Root)) { // PATTERN: [AnnotateRootLoop] $outer:(Loop * $ret:* ^ (StepPattern? $ret {Root})) => (AddPattern $outer {SameDepth}) ^ { } if (AllowReplace(XmlILOptimization.AnnotateRootLoop, local0)) { OptimizerPatterns.Write((QilNode)(local0)).AddPattern(OptimizerPatternName.SameDepth); } } } if (this[XmlILOptimization.AnnotateContentLoop]) { if (local1.NodeType == QilNodeType.For) { QilNode local3 = local1[0]; if (OptimizerPatterns.Read((QilNode)(local3)).MatchesPattern(OptimizerPatternName.SameDepth)) { if (((IsStepPattern(local2, QilNodeType.Content)) || (IsStepPattern(local2, QilNodeType.Union))) && ((local1) == (OptimizerPatterns.Read((QilNode)(local2)).GetArgument(OptimizerPatternArgument.StepInput)))) { // PATTERN: [AnnotateContentLoop] $outer:(Loop $iter:(For $bind:* ^ (Pattern? $bind {SameDepth})) $ret:* ^ (StepPattern? $ret {Content}) | (StepPattern? $ret {Union}) ^ (Equal? $iter (Argument $ret {StepInput}))) => (AddPattern $outer {SameDepth}) ^ (InheritPattern $outer $bind {IsDocOrderDistinct}) ^ { } if (AllowReplace(XmlILOptimization.AnnotateContentLoop, local0)) { OptimizerPatterns.Write((QilNode)(local0)).AddPattern(OptimizerPatternName.SameDepth); OptimizerPatterns.Inherit((QilNode)(local3), (QilNode)(local0), OptimizerPatternName.IsDocOrderDistinct); } } } } } if (this[XmlILOptimization.AnnotateAttrNmspLoop]) { if (local1.NodeType == QilNodeType.For) { QilNode local3 = local1[0]; if ((((IsStepPattern(local2, QilNodeType.Attribute)) || (IsStepPattern(local2, QilNodeType.XPathNamespace))) || (OptimizerPatterns.Read((QilNode)(local2)).MatchesPattern(OptimizerPatternName.FilterAttributeKind))) && ((local1) == (OptimizerPatterns.Read((QilNode)(local2)).GetArgument(OptimizerPatternArgument.StepInput)))) { // PATTERN: [AnnotateAttrNmspLoop] $outer:(Loop $iter:(For $bind:*) $ret:* ^ (StepPattern? $ret {Attribute}) | (StepPattern? $ret {XPathNamespace}) | (Pattern? $ret {FilterAttributeKind}) ^ (Equal? $iter (Argument $ret {StepInput}))) => (InheritPattern $outer $bind {SameDepth}) ^ (InheritPattern $outer $bind {IsDocOrderDistinct}) ^ { } if (AllowReplace(XmlILOptimization.AnnotateAttrNmspLoop, local0)) { OptimizerPatterns.Inherit((QilNode)(local3), (QilNode)(local0), OptimizerPatternName.SameDepth); OptimizerPatterns.Inherit((QilNode)(local3), (QilNode)(local0), OptimizerPatternName.IsDocOrderDistinct); } } } } if (this[XmlILOptimization.AnnotateDescendantLoop]) { if (local1.NodeType == QilNodeType.For) { QilNode local3 = local1[0]; if (OptimizerPatterns.Read((QilNode)(local3)).MatchesPattern(OptimizerPatternName.SameDepth)) { if (((IsStepPattern(local2, QilNodeType.Descendant)) || (IsStepPattern(local2, QilNodeType.DescendantOrSelf))) && ((local1) == (OptimizerPatterns.Read((QilNode)(local2)).GetArgument(OptimizerPatternArgument.StepInput)))) { // PATTERN: [AnnotateDescendantLoop] $outer:(Loop $iter:(For $bind:* ^ (Pattern? $bind {SameDepth})) $ret:* ^ (StepPattern? $ret {Descendant}) | (StepPattern? $ret {DescendantOrSelf}) ^ (Equal? $iter (Argument $ret {StepInput}))) => (InheritPattern $outer $bind {IsDocOrderDistinct}) ^ { } if (AllowReplace(XmlILOptimization.AnnotateDescendantLoop, local0)) { OptimizerPatterns.Inherit((QilNode)(local3), (QilNode)(local0), OptimizerPatternName.IsDocOrderDistinct); } } } } } return NoReplace(local0); }
protected virtual QilNode VisitFilter(QilLoop n) { return VisitChildren(n); }
/// <summary> /// Analyze loop. /// </summary> protected override void AnalyzeLoop(QilLoop ndLoop, XmlILConstructInfo info) { // Constructing attributes/namespaces in a loop can cause duplicates, namespaces after attributes, etc. if (ndLoop.XmlType.MaybeMany) CheckAttributeNamespaceConstruct(ndLoop.XmlType); base.AnalyzeLoop(ndLoop, info); }
public QilLoop Filter(QilNode variable, QilNode body) { QilLoop n = new QilLoop(QilNodeType.Filter, variable, body); n.XmlType = this.typeCheck.CheckFilter(n); TraceNode(n); return n; }
//----------------------------------------------- // sorting //----------------------------------------------- public QilLoop Sort(QilNode variable, QilNode body) { QilLoop n = new QilLoop(QilNodeType.Sort, variable, body); n.XmlType = this.typeCheck.CheckSort(n); TraceNode(n); return n; }
//----------------------------------------------- // loops //----------------------------------------------- public XmlQueryType CheckLoop(QilLoop node) { CheckClass(node[0], typeof(QilIterator)); Check(node.Variable.NodeType == QilNodeType.For || node.Variable.NodeType == QilNodeType.Let, node, "Loop variable must be a For or Let iterator"); XmlQueryType bodyType = node.Body.XmlType; XmlQueryCardinality variableCard = node.Variable.NodeType == QilNodeType.Let ? XmlQueryCardinality.One : node.Variable.Binding.XmlType.Cardinality; // Loops do not preserve DocOrderDistinct return XmlQueryTypeFactory.PrimeProduct(bodyType, variableCard * bodyType.Cardinality); }
protected override QilNode VisitLoop(QilLoop local0) { QilNode local1 = local0[0]; QilNode local2 = local0[1]; if (this[XmlILOptimization.FoldNone]) { if ( (object) ( (local1).XmlType ) == (object) XmlQueryTypeFactory.None ) { if (AllowReplace(XmlILOptimization.FoldNone, local0)) { return Replace(XmlILOptimization.FoldNone, local0, VisitNop(f.Nop( (QilNode) (local1)[0] ))); } } } if (this[XmlILOptimization.EliminateIterator]) { if (local1.NodeType == QilNodeType.For) { QilNode local3 = local1[0]; if (local3.NodeType == QilNodeType.For) { if ( !OptimizerPatterns.Read(local1).MatchesPattern(OptimizerPatternName.IsPositional) ) { if (AllowReplace(XmlILOptimization.EliminateIterator, local0)) { return Replace(XmlILOptimization.EliminateIterator, local0, Subs(local2, local1, local3) ); } } } } } if (this[XmlILOptimization.EliminateLoop]) { if (local1.NodeType == QilNodeType.For) { QilNode local3 = local1[0]; if (local3.NodeType == QilNodeType.Sequence) { if ( (local3).Count == (0) ) { if (AllowReplace(XmlILOptimization.EliminateLoop, local0)) { return Replace(XmlILOptimization.EliminateLoop, local0, VisitSequence(f.Sequence())); } } } } } if (this[XmlILOptimization.EliminateLoop]) { if ( !OptimizerPatterns.Read(local1).MatchesPattern(OptimizerPatternName.MaybeSideEffects) ) { if (local2.NodeType == QilNodeType.Sequence) { if ( (local2).Count == (0) ) { if (AllowReplace(XmlILOptimization.EliminateLoop, local0)) { return Replace(XmlILOptimization.EliminateLoop, local0, VisitSequence(f.Sequence())); } } } } } if (this[XmlILOptimization.EliminateLoop]) { if (local2 == local1) { if (AllowReplace(XmlILOptimization.EliminateLoop, local0)) { return Replace(XmlILOptimization.EliminateLoop, local0, (QilNode) (local1)[0] ); } } } if (this[XmlILOptimization.NormalizeLoopText]) { if (local1.NodeType == QilNodeType.For) { QilNode local3 = local1[0]; if ( ( (local3).XmlType ).IsSingleton ) { if (local2.NodeType == QilNodeType.TextCtor) { QilNode local4 = local2[0]; if (AllowReplace(XmlILOptimization.NormalizeLoopText, local0)) { return Replace(XmlILOptimization.NormalizeLoopText, local0, VisitTextCtor(f.TextCtor(VisitLoop(f.Loop(local1, local4))))); } } } } } if (this[XmlILOptimization.EliminateIteratorUsedAtMostOnce]) { if ((( (local1).NodeType == QilNodeType.Let ) || ( ( ( (QilNode) (local1)[0] ).XmlType ).IsSingleton )) && ( !OptimizerPatterns.Read(local1).MatchesPattern(OptimizerPatternName.MaybeSideEffects) )) { if (( nodeCounter.Count(local2, local1) <= 1 ) && ( !OptimizerPatterns.Read(local2).MatchesPattern(OptimizerPatternName.MaybeSideEffects) )) { if (AllowReplace(XmlILOptimization.EliminateIteratorUsedAtMostOnce, local0)) { return Replace(XmlILOptimization.EliminateIteratorUsedAtMostOnce, local0, Subs(local2, local1, (QilNode) (local1)[0] ) ); } } } } if (this[XmlILOptimization.NormalizeLoopConditional]) { if (local2.NodeType == QilNodeType.Conditional) { QilNode local3 = local2[0]; QilNode local4 = local2[1]; QilNode local5 = local2[2]; if (local4.NodeType == QilNodeType.Sequence) { if ( (local4).Count == (0) ) { if (local5 == local1) { if (AllowReplace(XmlILOptimization.NormalizeLoopConditional, local0)) { return Replace(XmlILOptimization.NormalizeLoopConditional, local0, VisitFilter(f.Filter(local1, VisitNot(f.Not(local3))))); } } } } } } if (this[XmlILOptimization.NormalizeLoopConditional]) { if (local2.NodeType == QilNodeType.Conditional) { QilNode local3 = local2[0]; QilNode local4 = local2[1]; QilNode local5 = local2[2]; if (local4 == local1) { if (local5.NodeType == QilNodeType.Sequence) { if ( (local5).Count == (0) ) { if (AllowReplace(XmlILOptimization.NormalizeLoopConditional, local0)) { return Replace(XmlILOptimization.NormalizeLoopConditional, local0, VisitFilter(f.Filter(local1, local3))); } } } } } } if (this[XmlILOptimization.NormalizeLoopConditional]) { if (local1.NodeType == QilNodeType.For) { if (local2.NodeType == QilNodeType.Conditional) { QilNode local4 = local2[0]; QilNode local5 = local2[1]; QilNode local6 = local2[2]; if (local5.NodeType == QilNodeType.Sequence) { if ( (local5).Count == (0) ) { if ( NonPositional(local6, local1) ) { if (AllowReplace(XmlILOptimization.NormalizeLoopConditional, local0)) { QilNode local7 = VisitFor(f.For(VisitFilter(f.Filter(local1, VisitNot(f.Not(local4)))))); return Replace(XmlILOptimization.NormalizeLoopConditional, local0, VisitLoop(f.Loop(local7, Subs(local6, local1, local7) ))); } } } } } } } if (this[XmlILOptimization.NormalizeLoopConditional]) { if (local1.NodeType == QilNodeType.For) { if (local2.NodeType == QilNodeType.Conditional) { QilNode local4 = local2[0]; QilNode local5 = local2[1]; QilNode local6 = local2[2]; if ( NonPositional(local5, local1) ) { if (local6.NodeType == QilNodeType.Sequence) { if ( (local6).Count == (0) ) { if (AllowReplace(XmlILOptimization.NormalizeLoopConditional, local0)) { QilNode local7 = VisitFor(f.For(VisitFilter(f.Filter(local1, local4)))); return Replace(XmlILOptimization.NormalizeLoopConditional, local0, VisitLoop(f.Loop(local7, Subs(local5, local1, local7) ))); } } } } } } } if (this[XmlILOptimization.NormalizeLoopLoop]) { if (local2.NodeType == QilNodeType.Loop) { QilNode local3 = local2[0]; QilNode local5 = local2[1]; if (local3.NodeType == QilNodeType.For) { QilNode local4 = local3[0]; if ((!(DependsOn(local5,local1))) && ( NonPositional(local5, local3) )) { if (AllowReplace(XmlILOptimization.NormalizeLoopLoop, local0)) { QilNode local6 = VisitFor(f.For(VisitLoop(f.Loop(local1, local4)))); return Replace(XmlILOptimization.NormalizeLoopLoop, local0, VisitLoop(f.Loop(local6, Subs(local5, local3, local6) ))); } } } } } if (this[XmlILOptimization.AnnotateSingletonLoop]) { if (local1.NodeType == QilNodeType.For) { QilNode local3 = local1[0]; if ( !( (local3).XmlType ).MaybeMany ) { if (AllowReplace(XmlILOptimization.AnnotateSingletonLoop, local0)) { OptimizerPatterns.Inherit((QilNode) (local2), (QilNode) (local0), OptimizerPatternName.IsDocOrderDistinct); OptimizerPatterns.Inherit((QilNode) (local2), (QilNode) (local0), OptimizerPatternName.SameDepth); } } } } if (this[XmlILOptimization.AnnotateRootLoop]) { if ( IsStepPattern(local2, QilNodeType.Root) ) { if (AllowReplace(XmlILOptimization.AnnotateRootLoop, local0)) { OptimizerPatterns.Write((QilNode) (local0)).AddPattern(OptimizerPatternName.SameDepth); } } } if (this[XmlILOptimization.AnnotateContentLoop]) { if (local1.NodeType == QilNodeType.For) { QilNode local3 = local1[0]; if ( OptimizerPatterns.Read((QilNode) (local3)).MatchesPattern(OptimizerPatternName.SameDepth) ) { if ((( IsStepPattern(local2, QilNodeType.Content) ) || ( IsStepPattern(local2, QilNodeType.Union) )) && ( (local1) == ( OptimizerPatterns.Read((QilNode) (local2)).GetArgument(OptimizerPatternArgument.StepInput) ) )) { if (AllowReplace(XmlILOptimization.AnnotateContentLoop, local0)) { OptimizerPatterns.Write((QilNode) (local0)).AddPattern(OptimizerPatternName.SameDepth); OptimizerPatterns.Inherit((QilNode) (local3), (QilNode) (local0), OptimizerPatternName.IsDocOrderDistinct); } } } } } if (this[XmlILOptimization.AnnotateAttrNmspLoop]) { if (local1.NodeType == QilNodeType.For) { QilNode local3 = local1[0]; if (((( IsStepPattern(local2, QilNodeType.Attribute) ) || ( IsStepPattern(local2, QilNodeType.XPathNamespace) )) || ( OptimizerPatterns.Read((QilNode) (local2)).MatchesPattern(OptimizerPatternName.FilterAttributeKind) )) && ( (local1) == ( OptimizerPatterns.Read((QilNode) (local2)).GetArgument(OptimizerPatternArgument.StepInput) ) )) { if (AllowReplace(XmlILOptimization.AnnotateAttrNmspLoop, local0)) { OptimizerPatterns.Inherit((QilNode) (local3), (QilNode) (local0), OptimizerPatternName.SameDepth); OptimizerPatterns.Inherit((QilNode) (local3), (QilNode) (local0), OptimizerPatternName.IsDocOrderDistinct); } } } } if (this[XmlILOptimization.AnnotateDescendantLoop]) { if (local1.NodeType == QilNodeType.For) { QilNode local3 = local1[0]; if ( OptimizerPatterns.Read((QilNode) (local3)).MatchesPattern(OptimizerPatternName.SameDepth) ) { if ((( IsStepPattern(local2, QilNodeType.Descendant) ) || ( IsStepPattern(local2, QilNodeType.DescendantOrSelf) )) && ( (local1) == ( OptimizerPatterns.Read((QilNode) (local2)).GetArgument(OptimizerPatternArgument.StepInput) ) )) { if (AllowReplace(XmlILOptimization.AnnotateDescendantLoop, local0)) { OptimizerPatterns.Inherit((QilNode) (local3), (QilNode) (local0), OptimizerPatternName.IsDocOrderDistinct); } } } } } return NoReplace(local0); }
//----------------------------------------------- // sorting //----------------------------------------------- public XmlQueryType CheckSort(QilLoop node) { XmlQueryType varType = node.Variable.Binding.XmlType; CheckClassAndNodeType(node[0], typeof(QilIterator), QilNodeType.For); CheckClassAndNodeType(node[1], typeof(QilList), QilNodeType.SortKeyList); // Sort does not preserve DocOrderDistinct return XmlQueryTypeFactory.PrimeProduct(varType, varType.Cardinality); }
protected override QilNode VisitFilter(QilLoop local0) { QilNode local1 = local0[0]; QilNode local2 = local0[1]; if (this[XmlILOptimization.FoldNone]) { if ( (object) ( (local2).XmlType ) == (object) XmlQueryTypeFactory.None ) { if (AllowReplace(XmlILOptimization.FoldNone, local0)) { return Replace(XmlILOptimization.FoldNone, local0, VisitLoop(f.Loop(local1, local2))); } } } if (this[XmlILOptimization.EliminateFilter]) { if ( !OptimizerPatterns.Read(local1).MatchesPattern(OptimizerPatternName.MaybeSideEffects) ) { if (local2.NodeType == QilNodeType.False) { if (AllowReplace(XmlILOptimization.EliminateFilter, local0)) { return Replace(XmlILOptimization.EliminateFilter, local0, VisitSequence(f.Sequence())); } } } } if (this[XmlILOptimization.EliminateFilter]) { if (local2.NodeType == QilNodeType.True) { if (AllowReplace(XmlILOptimization.EliminateFilter, local0)) { return Replace(XmlILOptimization.EliminateFilter, local0, (QilNode) (local1)[0] ); } } } if (this[XmlILOptimization.NormalizeAttribute]) { if (local1.NodeType == QilNodeType.For) { QilNode local3 = local1[0]; if (local3.NodeType == QilNodeType.Content) { QilNode local4 = local3[0]; if (local2.NodeType == QilNodeType.And) { QilNode local5 = local2[0]; QilNode local9 = local2[1]; if (local5.NodeType == QilNodeType.IsType) { QilNode local6 = local5[0]; QilNode local7 = local5[1]; if (local6 == local1) { if (local7.NodeType == QilNodeType.LiteralType) { XmlQueryType local8 = (XmlQueryType)((QilLiteral)local7).Value; if ( (local8) == ( XmlQueryTypeFactory.Attribute ) ) { if (local9.NodeType == QilNodeType.Eq) { QilNode local10 = local9[0]; QilNode local12 = local9[1]; if (local10.NodeType == QilNodeType.NameOf) { QilNode local11 = local10[0]; if (local11 == local1) { if (local12.NodeType == QilNodeType.LiteralQName) { if (AllowReplace(XmlILOptimization.NormalizeAttribute, local0)) { return Replace(XmlILOptimization.NormalizeAttribute, local0, VisitAttribute(f.Attribute(local4, local12))); } } } } } } } } } } } } } if (this[XmlILOptimization.CommuteFilterLoop]) { if (local1.NodeType == QilNodeType.For) { QilNode local3 = local1[0]; if (local3.NodeType == QilNodeType.Loop) { QilNode local4 = local3[0]; QilNode local5 = local3[1]; if ( NonPositional(local2, local1) ) { if (AllowReplace(XmlILOptimization.CommuteFilterLoop, local0)) { QilNode local6 = VisitFor(f.For(local5)); return Replace(XmlILOptimization.CommuteFilterLoop, local0, VisitLoop(f.Loop(local4, VisitFilter(f.Filter(local6, Subs(local2, local1, local6) ))))); } } } } } if (this[XmlILOptimization.NormalizeLoopInvariant]) { if ( !OptimizerPatterns.Read(local1).MatchesPattern(OptimizerPatternName.MaybeSideEffects) ) { if ((!(DependsOn(local2,local1))) && ( !OptimizerPatterns.Read(local2).MatchesPattern(OptimizerPatternName.MaybeSideEffects) )) { if (AllowReplace(XmlILOptimization.NormalizeLoopInvariant, local0)) { return Replace(XmlILOptimization.NormalizeLoopInvariant, local0, VisitConditional(f.Conditional(local2, (QilNode) (local1)[0] , VisitSequence(f.Sequence())))); } } } } if (this[XmlILOptimization.AnnotateMaxPositionEq]) { if (local2.NodeType == QilNodeType.Eq) { QilNode local3 = local2[0]; QilNode local5 = local2[1]; if (local3.NodeType == QilNodeType.PositionOf) { QilNode local4 = local3[0]; if (local4 == local1) { if (local5.NodeType == QilNodeType.LiteralInt32) { int local6 = (int)((QilLiteral)local5).Value; if (AllowReplace(XmlILOptimization.AnnotateMaxPositionEq, local0)) { OptimizerPatterns.Write((QilNode) (local1)).AddPattern(OptimizerPatternName.MaxPosition); OptimizerPatterns.Write((QilNode) (local1)).AddArgument(OptimizerPatternArgument.MaxPosition, local6); } } } } } } if (this[XmlILOptimization.AnnotateMaxPositionLe]) { if (local2.NodeType == QilNodeType.Le) { QilNode local3 = local2[0]; QilNode local5 = local2[1]; if (local3.NodeType == QilNodeType.PositionOf) { QilNode local4 = local3[0]; if (local4 == local1) { if (local5.NodeType == QilNodeType.LiteralInt32) { int local6 = (int)((QilLiteral)local5).Value; if (AllowReplace(XmlILOptimization.AnnotateMaxPositionLe, local0)) { OptimizerPatterns.Write((QilNode) (local1)).AddPattern(OptimizerPatternName.MaxPosition); OptimizerPatterns.Write((QilNode) (local1)).AddArgument(OptimizerPatternArgument.MaxPosition, local6); } } } } } } if (this[XmlILOptimization.AnnotateMaxPositionLt]) { if (local2.NodeType == QilNodeType.Lt) { QilNode local3 = local2[0]; QilNode local5 = local2[1]; if (local3.NodeType == QilNodeType.PositionOf) { QilNode local4 = local3[0]; if (local4 == local1) { if (local5.NodeType == QilNodeType.LiteralInt32) { int local6 = (int)((QilLiteral)local5).Value; if (AllowReplace(XmlILOptimization.AnnotateMaxPositionLt, local0)) { OptimizerPatterns.Write((QilNode) (local1)).AddPattern(OptimizerPatternName.MaxPosition); OptimizerPatterns.Write((QilNode) (local1)).AddArgument(OptimizerPatternArgument.MaxPosition, local6 - 1 ); } } } } } } if (this[XmlILOptimization.AnnotateFilter]) { if (local1.NodeType == QilNodeType.For) { QilNode local3 = local1[0]; if (AllowReplace(XmlILOptimization.AnnotateFilter, local0)) { OptimizerPatterns.Inherit((QilNode) (local3), (QilNode) (local0), OptimizerPatternName.Step); OptimizerPatterns.Inherit((QilNode) (local3), (QilNode) (local0), OptimizerPatternName.IsDocOrderDistinct); OptimizerPatterns.Inherit((QilNode) (local3), (QilNode) (local0), OptimizerPatternName.SameDepth); } } } if (this[XmlILOptimization.AnnotateFilterElements]) { if (local1.NodeType == QilNodeType.For) { QilNode local3 = local1[0]; if ( OptimizerPatterns.Read((QilNode) (local3)).MatchesPattern(OptimizerPatternName.Axis) ) { if (local2.NodeType == QilNodeType.And) { QilNode local4 = local2[0]; QilNode local8 = local2[1]; if (local4.NodeType == QilNodeType.IsType) { QilNode local5 = local4[0]; QilNode local6 = local4[1]; if (local5 == local1) { if (local6.NodeType == QilNodeType.LiteralType) { XmlQueryType local7 = (XmlQueryType)((QilLiteral)local6).Value; if ( (local7) == ( XmlQueryTypeFactory.Element ) ) { if (local8.NodeType == QilNodeType.Eq) { QilNode local9 = local8[0]; QilNode local11 = local8[1]; if (local9.NodeType == QilNodeType.NameOf) { QilNode local10 = local9[0]; if (local10 == local1) { if (local11.NodeType == QilNodeType.LiteralQName) { if (AllowReplace(XmlILOptimization.AnnotateFilterElements, local0)) { OptimizerPatterns.Write((QilNode) (local0)).AddPattern(OptimizerPatternName.FilterElements); OptimizerPatterns.Write((QilNode) (local0)).AddArgument(OptimizerPatternArgument.ElementQName, local11); } } } } } } } } } } } } } if (this[XmlILOptimization.AnnotateFilterContentKind]) { if (local1.NodeType == QilNodeType.For) { QilNode local3 = local1[0]; if ( OptimizerPatterns.Read((QilNode) (local3)).MatchesPattern(OptimizerPatternName.Axis) ) { if (local2.NodeType == QilNodeType.IsType) { QilNode local4 = local2[0]; QilNode local5 = local2[1]; if (local4 == local1) { if (local5.NodeType == QilNodeType.LiteralType) { XmlQueryType local6 = (XmlQueryType)((QilLiteral)local5).Value; if ( MatchesContentTest(local6) ) { if (AllowReplace(XmlILOptimization.AnnotateFilterContentKind, local0)) { OptimizerPatterns.Write((QilNode) (local0)).AddPattern(OptimizerPatternName.FilterContentKind); OptimizerPatterns.Write((QilNode) (local0)).AddArgument(OptimizerPatternArgument.KindTestType, local6); } } } } } } } } if (this[XmlILOptimization.AnnotateFilterAttributeKind]) { if (local1.NodeType == QilNodeType.For) { QilNode local3 = local1[0]; if (local3.NodeType == QilNodeType.Content) { if (local2.NodeType == QilNodeType.IsType) { QilNode local5 = local2[0]; QilNode local6 = local2[1]; if (local5 == local1) { if (local6.NodeType == QilNodeType.LiteralType) { XmlQueryType local7 = (XmlQueryType)((QilLiteral)local6).Value; if ( (local7) == ( XmlQueryTypeFactory.Attribute ) ) { if (AllowReplace(XmlILOptimization.AnnotateFilterAttributeKind, local0)) { OptimizerPatterns.Write((QilNode) (local0)).AddPattern(OptimizerPatternName.FilterAttributeKind); } } } } } } } } return NoReplace(local0); }
protected virtual QilNode VisitSort(QilLoop n) { return(VisitChildren(n)); }
protected override QilNode VisitFilter(QilLoop n) { return NoReplace(n); }