An anonymous QilExpression function node.

Function is a block, so it may introduce assignments (scoped to the function body). Additionally, it has an argument list, which will be assigned values when the function is invoked.

The XmlType property defines the expected return type of this function. Normally, this should be the same as its definition's types, so setting the function definition changes the function's types. In some rare cases, a compiler may wish to override the types after setting the function's definition (for example, an XQuery might define a function's return type to be wider than its definition would imply.)

Inheritance: QilReference
示例#1
0
 //-----------------------------------------------
 // function definition and invocation
 //-----------------------------------------------
 public XmlQueryType CheckFunction(QilFunction node)
 {
     CheckClassAndNodeType(node[0], typeof(QilList), QilNodeType.FormalParameterList);
     Check(node[2].NodeType == QilNodeType.False || node[2].NodeType == QilNodeType.True, node, "SideEffects must either be True or False");
     Check(node.Definition.XmlType.IsSubtypeOf(node.XmlType), node, "Function definition's xml type must be a subtype of the function's return type");
     return(node.XmlType);
 }
示例#2
0
        public QilNode GenerateInvoke(QilFunction func, IList<XslNode> actualArgs)
        {
            _iterStack.Clear();
            _formalArgs = func.Arguments;
            _invokeArgs = _fac.ActualParameterList();

            // curArg is an instance variable used in Clone() method
            for (_curArg = 0; _curArg < _formalArgs.Count; _curArg++)
            {
                // Find actual value for a given formal arg
                QilParameter formalArg = (QilParameter)_formalArgs[_curArg];
                QilNode invokeArg = FindActualArg(formalArg, actualArgs);

                // If actual value was not specified, use the default value and copy its debug comment
                if (invokeArg == null)
                {
                    if (_debug)
                    {
                        if (formalArg.Name.NamespaceUri == XmlReservedNs.NsXslDebug)
                        {
                            Debug.Assert(formalArg.Name.LocalName == "namespaces", "Cur,Pos,Last don't have default values and should be always added to by caller in AddImplicitArgs()");
                            Debug.Assert(formalArg.DefaultValue != null, "PrecompileProtoTemplatesHeaders() set it");
                            invokeArg = Clone(formalArg.DefaultValue);
                        }
                        else
                        {
                            invokeArg = _fac.DefaultValueMarker();
                        }
                    }
                    else
                    {
                        Debug.Assert(formalArg.Name.NamespaceUri != XmlReservedNs.NsXslDebug, "Cur,Pos,Last don't have default values and should be always added to by caller in AddImplicitArgs(). We don't have $namespaces in !debug.");
                        invokeArg = Clone(formalArg.DefaultValue);
                    }
                }

                XmlQueryType formalType = formalArg.XmlType;
                XmlQueryType invokeType = invokeArg.XmlType;

                // Possible arg types: anyType, node-set, string, boolean, and number
                _fac.CheckXsltType(formalArg);
                _fac.CheckXsltType(invokeArg);

                if (!invokeType.IsSubtypeOf(formalType))
                {
                    // This may occur only if inferred type of invokeArg is XslFlags.None
                    Debug.Assert(invokeType == T.ItemS, "Actual argument type is not a subtype of formal argument type");
                    invokeArg = _fac.TypeAssert(invokeArg, formalType);
                }

                _invokeArgs.Add(invokeArg);
            }

            // Create Invoke node and wrap it with previous parameter declarations
            QilNode invoke = _fac.Invoke(func, _invokeArgs);
            while (_iterStack.Count != 0)
                invoke = _fac.Loop(_iterStack.Pop(), invoke);

            return invoke;
        }
示例#3
0
        //-----------------------------------------------
        // function definition and invocation
        //-----------------------------------------------
        public QilFunction Function(QilNode arguments, QilNode definition, QilNode sideEffects, XmlQueryType xmlType)
        {
            QilFunction n = new QilFunction(QilNodeType.Function, arguments, definition, sideEffects, xmlType);

            n.XmlType = this.typeCheck.CheckFunction(n);
            TraceNode(n);
            return(n);
        }
 public QilNode Invoke(QilFunction func, QilList args) {
     Debug.Assert(args.NodeType == QilNodeType.ActualParameterList);
     Debug.Assert(func.Arguments.Count == args.Count);
     return f.Invoke(func, args);
 }
 public QilNode Invoke(QilFunction func, QilList args)
 {
     Debug.Assert(args.NodeType == QilNodeType.ActualParameterList);
     Debug.Assert(func.Arguments.Count == args.Count);
     return(_f.Invoke(func, args));
 }
 //-----------------------------------------------
 // function definition and invocation
 //-----------------------------------------------
 public XmlQueryType CheckFunction(QilFunction node) {
     CheckClassAndNodeType(node[0], typeof(QilList), QilNodeType.FormalParameterList);
     Check(node[2].NodeType == QilNodeType.False || node[2].NodeType == QilNodeType.True, node, "SideEffects must either be True or False");
     Check(node.Definition.XmlType.IsSubtypeOf(node.XmlType), node, "Function definition's xml type must be a subtype of the function's return type");
     return node.XmlType;
 }
示例#7
0
 protected virtual QilNode VisitFunctionReference(QilFunction n) { return n; }
示例#8
0
 protected virtual QilNode VisitFunction(QilFunction n) { return VisitChildren(n); }
示例#9
0
        /// <summary>
        /// Generate code for the specified function.
        /// </summary>
        private void Function(QilFunction ndFunc)
        {
            MethodInfo methFunc;
            int paramId;
            IteratorDescriptor iterInfo;
            bool useWriter;

            // Annotate each function parameter with a IteratorDescriptor
            foreach (QilIterator iter in ndFunc.Arguments)
            {
                Debug.Assert(iter.NodeType == QilNodeType.Parameter);

                // Create an IteratorDescriptor for this parameter
                iterInfo = new IteratorDescriptor(_helper);

                // Add one to parameter index, as 0th parameter is always "this"
                paramId = XmlILAnnotation.Write(iter).ArgumentPosition + 1;

                // The ParameterInfo for each argument should be set as its location
                iterInfo.Storage = StorageDescriptor.Parameter(paramId, GetItemStorageType(iter), !iter.XmlType.IsSingleton);

                // Associate IteratorDescriptor with Let iterator
                XmlILAnnotation.Write(iter).CachedIteratorDescriptor = iterInfo;
            }

            methFunc = XmlILAnnotation.Write(ndFunc).FunctionBinding;
            useWriter = (XmlILConstructInfo.Read(ndFunc).ConstructMethod == XmlILConstructMethod.Writer);

            // Generate query code from QilExpression tree
            _helper.MethodBegin(methFunc, ndFunc.SourceLine, useWriter);

            foreach (QilIterator iter in ndFunc.Arguments)
            {
                // DebugInfo: Sequence point just before generating code for the bound expression
                if (_qil.IsDebug && iter.SourceLine != null)
                    _helper.DebugSequencePoint(iter.SourceLine);

                // Calculate default value of this parameter
                if (iter.Binding != null)
                {
                    Debug.Assert(iter.XmlType == TypeFactory.ItemS, "IlGen currently only supports default values in parameters of type item*.");
                    paramId = (iter.Annotation as XmlILAnnotation).ArgumentPosition + 1;

                    // runtime.MatchesXmlType(param, XmlTypeCode.QName);
                    Label lblLocalComputed = _helper.DefineLabel();
                    _helper.LoadQueryRuntime();
                    _helper.LoadParameter(paramId);
                    _helper.LoadInteger((int)XmlTypeCode.QName);
                    _helper.Call(XmlILMethods.SeqMatchesCode);

                    _helper.Emit(OpCodes.Brfalse, lblLocalComputed);

                    // Compute default value of this parameter
                    StartNestedIterator(iter);
                    NestedVisitEnsureStack(iter.Binding, GetItemStorageType(iter), /*isCached:*/!iter.XmlType.IsSingleton);
                    EndNestedIterator(iter);

                    _helper.SetParameter(paramId);
                    _helper.MarkLabel(lblLocalComputed);
                }
            }

            StartNestedIterator(ndFunc);

            // If function did not push results to writer, then function will return value(s) (rather than void)
            if (useWriter)
                NestedVisit(ndFunc.Definition);
            else
                NestedVisitEnsureStack(ndFunc.Definition, GetItemStorageType(ndFunc), !ndFunc.XmlType.IsSingleton);

            EndNestedIterator(ndFunc);

            _helper.MethodEnd();
        }
示例#10
0
 protected override QilNode VisitFunctionReference(QilFunction n) { return NoReplace(n); }
示例#11
0
 protected override QilNode VisitFunction(QilFunction n)
 {
     // No need to change function references
     return n;
 }
示例#12
0
 protected override QilNode VisitFunctionReference(QilFunction n)
 {
     return(NoReplace(n));
 }
        // ----------------- use-attribute-sets, call-templates, apply-templates, apply-imports ----------------------------- //

        private QilNode GenerateCall(QilFunction func, XslNode node) {
            Debug.Assert(
                node.NodeType == XslNodeType.CallTemplate ||
                node.NodeType == XslNodeType.UseAttributeSet
            );

            AddImplicitArgs(node);
            return invkGen.GenerateInvoke(func, node.Content);
        }
        protected override QilNode VisitFunction(QilFunction local0) {
            QilNode local1 = local0[0];
            QilNode local2 = local0[1];
            QilNode local3 = local0[2];
            XmlQueryType local4 = (XmlQueryType)((QilFunction)local0).XmlType;
            if ((  (local0).XmlType .IsSubtypeOf( XmlQueryTypeFactory.NodeS ) ) && (this[XmlILOptimization.AnnotateIndex1])) {
                if ((( local1.Count == 2 ) && (  ( (QilNode) (local1)[0] ).XmlType .IsSubtypeOf( XmlQueryTypeFactory.Node ) )) && ( ( ( (QilNode) (local1)[1] ).XmlType ) == ( XmlQueryTypeFactory.StringX ) )) {
                    if (local2.NodeType == QilNodeType.Filter) {
                        QilNode local5 = local2[0];
                        QilNode local7 = local2[1];
                        if (local5.NodeType == QilNodeType.For) {
                            QilNode local6 = local5[0];
                            if (local7.NodeType == QilNodeType.Not) {
                                QilNode local8 = local7[0];
                                if (local8.NodeType == QilNodeType.IsEmpty) {
                                    QilNode local9 = local8[0];
                                    if (local9.NodeType == QilNodeType.Filter) {
                                        QilNode local10 = local9[0];
                                        QilNode local12 = local9[1];
                                        if (local10.NodeType == QilNodeType.For) {
                                            QilNode local11 = local10[0];
                                            if (local12.NodeType == QilNodeType.Eq) {
                                                QilNode local13 = local12[0];
                                                QilNode local14 = local12[1];
                                                if (local13 == local10) {
                                                    if (local14.NodeType == QilNodeType.Parameter) {
                                                        if ( (local14) == ( (QilNode) (local1)[1] ) ) {
                                                            if (AllowReplace(XmlILOptimization.AnnotateIndex1, local0)) {
                                                                
    // The following conditions must be true for this pattern to match:
    //   1. The function must have exactly two arguments
    //   2. The type of the first argument must be a subtype of Node
    //   3. The type of the second argument must be String
    //   4. The return type must be a subtype of Node*
    //   5. Every reference to $args[0] (context document) must be wrapped in an (Root *) function
    //   6. $keyParam cannot be used with the $bindingNodes and $bindingKeys expressions

    EqualityIndexVisitor visitor = new EqualityIndexVisitor();
    if (visitor.Scan(local6, local1[0], local14) && visitor.Scan(local11, local1[0], local14)) {
        // All conditions were true, so annotate Filter with the EqualityIndex pattern
        OptimizerPatterns patt = OptimizerPatterns.Write(local2);
        patt.AddPattern(OptimizerPatternName.EqualityIndex);
        patt.AddArgument(OptimizerPatternArgument.IndexedNodes, local5);
        patt.AddArgument(OptimizerPatternArgument.KeyExpression, local11);
    }
}
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            if (this[XmlILOptimization.AnnotateIndex2]) {
                if ((( local1.Count == 2 ) && ( ( ( (QilNode) (local1)[0] ).XmlType ) == ( XmlQueryTypeFactory.Node ) )) && ( ( ( (QilNode) (local1)[1] ).XmlType ) == ( XmlQueryTypeFactory.StringX ) )) {
                    if (local2.NodeType == QilNodeType.Filter) {
                        QilNode local5 = local2[0];
                        QilNode local7 = local2[1];
                        if (local5.NodeType == QilNodeType.For) {
                            QilNode local6 = local5[0];
                            if (local7.NodeType == QilNodeType.Eq) {
                                QilNode local8 = local7[0];
                                QilNode local9 = local7[1];
                                if (local9.NodeType == QilNodeType.Parameter) {
                                    if ( (local9) == ( (QilNode) (local1)[1] ) ) {
                                        if (AllowReplace(XmlILOptimization.AnnotateIndex2, local0)) {
                                            
    // Same as EqualityIndex1, except that each nodes has at most one key value

    EqualityIndexVisitor visitor = new EqualityIndexVisitor();
    if (visitor.Scan(local6, local1[0], local9) && visitor.Scan(local8, local1[0], local9)) {
        // All conditions were true, so annotate Filter with the EqualityIndex pattern
        OptimizerPatterns patt = OptimizerPatterns.Write(local2);
        patt.AddPattern(OptimizerPatternName.EqualityIndex);
        patt.AddArgument(OptimizerPatternArgument.IndexedNodes, local5);
        patt.AddArgument(OptimizerPatternArgument.KeyExpression, local8);
    }
}
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return NoReplace(local0);
        }
示例#15
0
 //-----------------------------------------------
 // function definition and invocation
 //-----------------------------------------------
 public QilFunction Function(QilNode arguments, QilNode definition, QilNode sideEffects, XmlQueryType xmlType) {
     QilFunction n = new QilFunction(QilNodeType.Function, arguments, definition, sideEffects, xmlType);
     n.XmlType = this.typeCheck.CheckFunction(n);
     TraceNode(n);
     return n;
 }
示例#16
0
 protected virtual QilNode VisitFunction(QilFunction n)
 {
     return(VisitChildren(n));
 }
示例#17
0
 protected virtual QilNode VisitFunctionReference(QilFunction n)
 {
     return(n);
 }
示例#18
0
 protected override QilNode VisitFunction(QilFunction n) { return NoReplace(n); }