/// <summary> /// Create and initialize OptimizerPatterns annotation for the specified node. /// </summary> public static void Inherit(QilNode ndSrc, QilNode ndDst, OptimizerPatternName pattern) { OptimizerPatterns annSrc = OptimizerPatterns.Read(ndSrc); if (annSrc.MatchesPattern(pattern)) { OptimizerPatterns annDst = OptimizerPatterns.Write(ndDst); annDst.AddPattern(pattern); // Inherit pattern arguments switch (pattern) { case OptimizerPatternName.Step: annDst.AddArgument(OptimizerPatternArgument.StepNode, annSrc.GetArgument(OptimizerPatternArgument.StepNode)); annDst.AddArgument(OptimizerPatternArgument.StepInput, annSrc.GetArgument(OptimizerPatternArgument.StepInput)); break; case OptimizerPatternName.FilterElements: annDst.AddArgument(OptimizerPatternArgument.ElementQName, annSrc.GetArgument(OptimizerPatternArgument.ElementQName)); break; case OptimizerPatternName.FilterContentKind: annDst.AddArgument(OptimizerPatternArgument.KindTestType, annSrc.GetArgument(OptimizerPatternArgument.KindTestType)); break; case OptimizerPatternName.EqualityIndex: annDst.AddArgument(OptimizerPatternArgument.IndexedNodes, annSrc.GetArgument(OptimizerPatternArgument.IndexedNodes)); annDst.AddArgument(OptimizerPatternArgument.KeyExpression, annSrc.GetArgument(OptimizerPatternArgument.KeyExpression)); break; case OptimizerPatternName.DodReverse: case OptimizerPatternName.JoinAndDod: annDst.AddArgument(OptimizerPatternArgument.DodStep, annSrc.GetArgument(OptimizerPatternArgument.DodStep)); break; case OptimizerPatternName.MaxPosition: annDst.AddArgument(OptimizerPatternArgument.MaxPosition, annSrc.GetArgument(OptimizerPatternArgument.MaxPosition)); break; case OptimizerPatternName.SingleTextRtf: annDst.AddArgument(OptimizerPatternArgument.RtfText, annSrc.GetArgument(OptimizerPatternArgument.RtfText)); break; } } }
/// <summary> /// Return true if "patt" matches the Step pattern and the StepType argument is equal to "stepType". /// </summary> private bool IsStepPattern(OptimizerPatterns patt, QilNodeType stepType) { return patt.MatchesPattern(OptimizerPatternName.Step) && ((QilNode) patt.GetArgument(OptimizerPatternArgument.StepNode)).NodeType == stepType; }
/// <summary> /// Bind values produced by the "ndFor" expression to a non-stack location that can later /// be referenced. /// </summary> private void StartForBinding(QilIterator ndFor, OptimizerPatterns patt) { LocalBuilder locPos = null; Debug.Assert(ndFor.XmlType.IsSingleton); // For expression iterator will be unnested as part of parent iterator if (_iterCurr.HasLabelNext) StartNestedIterator(ndFor.Binding, _iterCurr.GetLabelNext()); else StartNestedIterator(ndFor.Binding); if (patt.MatchesPattern(OptimizerPatternName.IsPositional)) { // Need to track loop index so initialize it to 0 before starting loop locPos = _helper.DeclareLocal("$$$pos", typeof(int)); _helper.Emit(OpCodes.Ldc_I4_0); _helper.Emit(OpCodes.Stloc, locPos); } // Allow base internal class to dispatch based on QilExpression node type Visit(ndFor.Binding); // DebugInfo: Open variable scope // DebugInfo: Ensure that for variable is stored in a local and tag it with the user-defined name if (_qil.IsDebug && ndFor.DebugName != null) { _helper.DebugStartScope(); // Ensure that values are stored in a local variable with a user-defined name _iterCurr.EnsureLocalNoCache("$$$for"); } else { // Ensure that values are not stored on the stack _iterCurr.EnsureNoStackNoCache("$$$for"); } if (patt.MatchesPattern(OptimizerPatternName.IsPositional)) { // Increment position _helper.Emit(OpCodes.Ldloc, locPos); _helper.Emit(OpCodes.Ldc_I4_1); _helper.Emit(OpCodes.Add); _helper.Emit(OpCodes.Stloc, locPos); if (patt.MatchesPattern(OptimizerPatternName.MaxPosition)) { // Short-circuit rest of loop if max position has already been reached _helper.Emit(OpCodes.Ldloc, locPos); _helper.LoadInteger((int)patt.GetArgument(OptimizerPatternArgument.MaxPosition)); _helper.Emit(OpCodes.Bgt, _iterCurr.ParentIterator.GetLabelNext()); } _iterCurr.LocalPosition = locPos; } EndNestedIterator(ndFor.Binding); _iterCurr.SetIterator(_iterNested); }