As the Qil graph is traversed, patterns are identified. Subtrees that match these patterns are annotated with this class, which identifies the matching patterns and their arguments.
상속: IQilAnnotation
예제 #1
0
        /// <summary>
        /// Recursively analyze the definition of a function.
        /// </summary>
        private static void AnalyzeDefinition(QilNode nd)
        {
            Debug.Assert(XmlILConstructInfo.Read(nd).PushToWriterLast,
                         "Only need to analyze expressions which will be compiled in push mode.");

            switch (nd.NodeType)
            {
            case QilNodeType.Invoke:
                // Invoke node can either be compiled as IteratorThenWriter, or Writer.
                // Since IteratorThenWriter involves caching the results of the function call
                // and iterating over them, .tailcall cannot be used
                if (XmlILConstructInfo.Read(nd).ConstructMethod == XmlILConstructMethod.Writer)
                {
                    OptimizerPatterns.Write(nd).AddPattern(OptimizerPatternName.TailCall);
                }
                break;

            case QilNodeType.Loop: {
                // Recursively analyze Loop return value
                QilLoop ndLoop = (QilLoop)nd;
                if (ndLoop.Variable.NodeType == QilNodeType.Let || !ndLoop.Variable.Binding.XmlType.MaybeMany)
                {
                    AnalyzeDefinition(ndLoop.Body);
                }
                break;
            }

            case QilNodeType.Sequence: {
                // Recursively analyze last expression in Sequence
                QilList ndSeq = (QilList)nd;
                if (ndSeq.Count > 0)
                {
                    AnalyzeDefinition(ndSeq[ndSeq.Count - 1]);
                }
                break;
            }

            case QilNodeType.Choice: {
                // Recursively analyze Choice branches
                QilChoice ndChoice = (QilChoice)nd;
                for (int i = 0; i < ndChoice.Branches.Count; i++)
                {
                    AnalyzeDefinition(ndChoice.Branches[i]);
                }
                break;
            }

            case QilNodeType.Conditional: {
                // Recursively analyze Conditional branches
                QilTernary ndCond = (QilTernary)nd;
                AnalyzeDefinition(ndCond.Center);
                AnalyzeDefinition(ndCond.Right);
                break;
            }

            case QilNodeType.Nop:
                AnalyzeDefinition(((QilUnary)nd).Child);
                break;
            }
        }
예제 #2
0
        /// <summary>
        /// Get OptimizerPatterns annotation for the specified node.  Lazily create if necessary.
        /// </summary>
        public static OptimizerPatterns Read(QilNode nd)
        {
            XmlILAnnotation   ann     = nd.Annotation as XmlILAnnotation;
            OptimizerPatterns optPatt = (ann != null) ? ann.Patterns : null;

            if (optPatt == null)
            {
                if (!nd.XmlType.MaybeMany)
                {
                    // Expressions with ZeroOrOne cardinality should always report IsDocOrderDistinct and NoContainedNodes
                    if (s_zeroOrOneDefault == null)
                    {
                        optPatt = new OptimizerPatterns();
                        optPatt.AddPattern(OptimizerPatternName.IsDocOrderDistinct);
                        optPatt.AddPattern(OptimizerPatternName.SameDepth);
                        optPatt._isReadOnly = true;

                        s_zeroOrOneDefault = optPatt;
                    }
                    else
                    {
                        optPatt = s_zeroOrOneDefault;
                    }
                }
                else if (nd.XmlType.IsDod)
                {
                    if (s_dodDefault == null)
                    {
                        optPatt = new OptimizerPatterns();
                        optPatt.AddPattern(OptimizerPatternName.IsDocOrderDistinct);
                        optPatt._isReadOnly = true;

                        s_dodDefault = optPatt;
                    }
                    else
                    {
                        optPatt = s_dodDefault;
                    }
                }
                else
                {
                    if (s_maybeManyDefault == null)
                    {
                        optPatt             = new OptimizerPatterns();
                        optPatt._isReadOnly = true;

                        s_maybeManyDefault = optPatt;
                    }
                    else
                    {
                        optPatt = s_maybeManyDefault;
                    }
                }
            }

            return(optPatt);
        }
예제 #3
0
        /// <summary>
        /// Get OptimizerPatterns annotation for the specified node.  Lazily create if necessary.
        /// </summary>
        public static OptimizerPatterns Read(QilNode nd)
        {
            XmlILAnnotation ann = nd.Annotation as XmlILAnnotation;
            OptimizerPatterns optPatt = (ann != null) ? ann.Patterns : null;

            if (optPatt == null)
            {
                if (!nd.XmlType.MaybeMany)
                {
                    // Expressions with ZeroOrOne cardinality should always report IsDocOrderDistinct and NoContainedNodes
                    if (s_zeroOrOneDefault == null)
                    {
                        optPatt = new OptimizerPatterns();
                        optPatt.AddPattern(OptimizerPatternName.IsDocOrderDistinct);
                        optPatt.AddPattern(OptimizerPatternName.SameDepth);
                        optPatt._isReadOnly = true;

                        s_zeroOrOneDefault = optPatt;
                    }
                    else
                    {
                        optPatt = s_zeroOrOneDefault;
                    }
                }
                else if (nd.XmlType.IsDod)
                {
                    if (s_dodDefault == null)
                    {
                        optPatt = new OptimizerPatterns();
                        optPatt.AddPattern(OptimizerPatternName.IsDocOrderDistinct);
                        optPatt._isReadOnly = true;

                        s_dodDefault = optPatt;
                    }
                    else
                    {
                        optPatt = s_dodDefault;
                    }
                }
                else
                {
                    if (s_maybeManyDefault == null)
                    {
                        optPatt = new OptimizerPatterns();
                        optPatt._isReadOnly = true;

                        s_maybeManyDefault = optPatt;
                    }
                    else
                    {
                        optPatt = s_maybeManyDefault;
                    }
                }
            }

            return optPatt;
        }
예제 #4
0
        /// <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;
                }
            }
        }
예제 #5
0
        /// <summary>
        /// Create and initialize OptimizerPatterns annotation for the specified node.
        /// </summary>
        public static OptimizerPatterns Write(QilNode nd)
        {
            XmlILAnnotation   ann     = XmlILAnnotation.Write(nd);
            OptimizerPatterns optPatt = ann.Patterns;

            if (optPatt == null || optPatt._isReadOnly)
            {
                optPatt      = new OptimizerPatterns();
                ann.Patterns = optPatt;

                if (!nd.XmlType.MaybeMany)
                {
                    optPatt.AddPattern(OptimizerPatternName.IsDocOrderDistinct);
                    optPatt.AddPattern(OptimizerPatternName.SameDepth);
                }
                else if (nd.XmlType.IsDod)
                {
                    optPatt.AddPattern(OptimizerPatternName.IsDocOrderDistinct);
                }
            }

            return(optPatt);
        }
예제 #6
0
        /// <summary>
        /// Create and initialize OptimizerPatterns annotation for the specified node.
        /// </summary>
        public static OptimizerPatterns Write(QilNode nd) {
            XmlILAnnotation ann = XmlILAnnotation.Write(nd);
            OptimizerPatterns optPatt = ann.Patterns;

            if (optPatt == null || optPatt.isReadOnly) {
                optPatt = new OptimizerPatterns();
                ann.Patterns = optPatt;

                if (!nd.XmlType.MaybeMany) {
                    optPatt.AddPattern(OptimizerPatternName.IsDocOrderDistinct);
                    optPatt.AddPattern(OptimizerPatternName.SameDepth);
                }
                else if (nd.XmlType.IsDod) {
                    optPatt.AddPattern(OptimizerPatternName.IsDocOrderDistinct);
                }
            }

            return optPatt;
        }
 /// <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;
 }
예제 #8
0
        /// <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);
        }