A function invocation node which reperesents a call to an early bound Clr function.
Inheritance: QilTernary
Example #1
0
        public QilInvokeEarlyBound XsltInvokeEarlyBound(QilNode name, QilNode clrMethod, QilNode arguments, XmlQueryType xmlType)
        {
            QilInvokeEarlyBound n = new QilInvokeEarlyBound(QilNodeType.XsltInvokeEarlyBound, name, clrMethod, arguments, xmlType);

            n.XmlType = this.typeCheck.CheckXsltInvokeEarlyBound(n);
            TraceNode(n);
            return(n);
        }
Example #2
0
        public XmlQueryType CheckXsltInvokeEarlyBound(QilInvokeEarlyBound node)
        {
        #if DEBUG
            CheckLiteralValue(node[0], typeof(QilName));
            CheckLiteralValue(node[1], typeof(MethodInfo));
            CheckClassAndNodeType(node[2], typeof(QilList), QilNodeType.ActualParameterList);

            XmlExtensionFunction extFunc = new XmlExtensionFunction(node.Name.LocalName, node.Name.NamespaceUri, node.ClrMethod);
            QilList actualArgs           = node.Arguments;
            Check(actualArgs.Count == extFunc.Method.GetParameters().Length, actualArgs, "InvokeEarlyBound argument count must match function's argument count");

            for (int i = 0; i < actualArgs.Count; i++)
            {
                Check(actualArgs[i].XmlType.IsSubtypeOf(extFunc.GetXmlArgumentType(i)), actualArgs[i], "InvokeEarlyBound argument must be a subtype of the invoked function's argument type");
            }
        #endif

            return(node.XmlType);
        }
Example #3
0
 protected virtual QilNode VisitXsltInvokeEarlyBound(QilInvokeEarlyBound n)
 {
     return(VisitChildren(n));
 }
        public XmlQueryType CheckXsltInvokeEarlyBound(QilInvokeEarlyBound node) {
        #if DEBUG
            CheckLiteralValue(node[0], typeof(QilName));
            CheckLiteralValue(node[1], typeof(MethodInfo));
            CheckClassAndNodeType(node[2], typeof(QilList), QilNodeType.ActualParameterList);

            XmlExtensionFunction extFunc = new XmlExtensionFunction(node.Name.LocalName, node.Name.NamespaceUri, node.ClrMethod);
            QilList actualArgs = node.Arguments;
            Check(actualArgs.Count == extFunc.Method.GetParameters().Length, actualArgs, "InvokeEarlyBound argument count must match function's argument count");

            for (int i = 0; i < actualArgs.Count; i++) {
                Check(actualArgs[i].XmlType.IsSubtypeOf(extFunc.GetXmlArgumentType(i)), actualArgs[i], "InvokeEarlyBound argument must be a subtype of the invoked function's argument type");
            }
        #endif

            return node.XmlType;
        }
 protected virtual QilNode VisitXsltInvokeEarlyBound(QilInvokeEarlyBound n) { return VisitChildren(n); }
Example #6
0
 protected override QilNode VisitXsltInvokeEarlyBound(QilInvokeEarlyBound n) { return NoReplace(n); }
Example #7
0
 protected override QilNode VisitXsltInvokeEarlyBound(QilInvokeEarlyBound n)
 {
     return(NoReplace(n));
 }
 public QilInvokeEarlyBound XsltInvokeEarlyBound(QilNode name, QilNode clrMethod, QilNode arguments, XmlQueryType xmlType) {
     QilInvokeEarlyBound n = new QilInvokeEarlyBound(QilNodeType.XsltInvokeEarlyBound, name, clrMethod, arguments, xmlType);
     n.XmlType = this.typeCheck.CheckXsltInvokeEarlyBound(n);
     TraceNode(n);
     return n;
 }
Example #9
0
        /// <summary>
        /// Generate code for for QilNodeType.XsltInvokeEarlyBound.
        /// </summary>
        protected override QilNode VisitXsltInvokeEarlyBound(QilInvokeEarlyBound ndInvoke)
        {
            QilName ndName = ndInvoke.Name;
            XmlExtensionFunction extFunc;
            Type clrTypeRetSrc, clrTypeRetDst;

            // Retrieve metadata from the extension function
            extFunc = new XmlExtensionFunction(ndName.LocalName, ndName.NamespaceUri, ndInvoke.ClrMethod);
            clrTypeRetSrc = extFunc.ClrReturnType;
            clrTypeRetDst = GetStorageType(ndInvoke);

            // Prepare to call runtime.ChangeTypeXsltResult
            if (clrTypeRetSrc != clrTypeRetDst && !ndInvoke.XmlType.IsEmpty)
            {
                _helper.LoadQueryRuntime();
                _helper.LoadInteger(_helper.StaticData.DeclareXmlType(ndInvoke.XmlType));
            }

            // If this is not a static method, then get the instance object
            if (!extFunc.Method.IsStatic)
            {
                // Special-case the XsltLibrary object
                if (ndName.NamespaceUri.Length == 0)
                    _helper.LoadXsltLibrary();
                else
                    _helper.CallGetEarlyBoundObject(_helper.StaticData.DeclareEarlyBound(ndName.NamespaceUri, extFunc.Method.DeclaringType), extFunc.Method.DeclaringType);
            }

            // Generate code to push each Invoke argument onto the stack
            for (int iArg = 0; iArg < ndInvoke.Arguments.Count; iArg++)
            {
                QilNode ndActualArg;
                XmlQueryType xmlTypeFormalArg;
                Type clrTypeActualArg, clrTypeFormalArg;

                ndActualArg = ndInvoke.Arguments[iArg];

                // Infer Xml type and Clr type of formal argument
                xmlTypeFormalArg = extFunc.GetXmlArgumentType(iArg);
                clrTypeFormalArg = extFunc.GetClrArgumentType(iArg);

                Debug.Assert(ndActualArg.XmlType.IsSubtypeOf(xmlTypeFormalArg), "Xml type of actual arg must be a subtype of the Xml type of the formal arg");

                // Use different conversion rules for internal Xslt libraries.  If the actual argument is
                // stored using Clr type T, then library must use type T, XPathItem, IList<T>, or IList<XPathItem>.
                // If the actual argument is stored using Clr type IList<T>, then library must use type
                // IList<T> or IList<XPathItem>.  This is to ensure that there will not be unnecessary
                // conversions that take place when calling into an internal library.
                if (ndName.NamespaceUri.Length == 0)
                {
                    Type itemType = GetItemStorageType(ndActualArg);

                    if (clrTypeFormalArg == XmlILMethods.StorageMethods[itemType].IListType)
                    {
                        // Formal type is IList<T>
                        NestedVisitEnsureStack(ndActualArg, itemType, true);
                    }
                    else if (clrTypeFormalArg == XmlILMethods.StorageMethods[typeof(XPathItem)].IListType)
                    {
                        // Formal type is IList<XPathItem>
                        NestedVisitEnsureStack(ndActualArg, typeof(XPathItem), true);
                    }
                    else if ((ndActualArg.XmlType.IsSingleton && clrTypeFormalArg == itemType) || ndActualArg.XmlType.TypeCode == XmlTypeCode.None)
                    {
                        // Formal type is T
                        NestedVisitEnsureStack(ndActualArg, clrTypeFormalArg, false);
                    }
                    else if (ndActualArg.XmlType.IsSingleton && clrTypeFormalArg == typeof(XPathItem))
                    {
                        // Formal type is XPathItem
                        NestedVisitEnsureStack(ndActualArg, typeof(XPathItem), false);
                    }
                    else
                        Debug.Fail("Internal Xslt library may not use parameters of type " + clrTypeFormalArg);
                }
                else
                {
                    // There is an implicit upcast to the Xml type of the formal argument.  This can change the Clr storage type.
                    clrTypeActualArg = GetStorageType(xmlTypeFormalArg);

                    // If the formal Clr type is typeof(object) or if it is not a supertype of the actual Clr type, then call ChangeTypeXsltArgument
                    if (xmlTypeFormalArg.TypeCode == XmlTypeCode.Item || !clrTypeFormalArg.IsAssignableFrom(clrTypeActualArg))
                    {
                        // (clrTypeFormalArg) runtime.ChangeTypeXsltArgument(xmlTypeFormalArg, (object) value, clrTypeFormalArg);
                        _helper.LoadQueryRuntime();
                        _helper.LoadInteger(_helper.StaticData.DeclareXmlType(xmlTypeFormalArg));
                        NestedVisitEnsureStack(ndActualArg, GetItemStorageType(xmlTypeFormalArg), !xmlTypeFormalArg.IsSingleton);
                        _helper.TreatAs(clrTypeActualArg, typeof(object));
                        _helper.LoadType(clrTypeFormalArg);
                        _helper.Call(XmlILMethods.ChangeTypeXsltArg);
                        _helper.TreatAs(typeof(object), clrTypeFormalArg);
                    }
                    else
                    {
                        NestedVisitEnsureStack(ndActualArg, GetItemStorageType(xmlTypeFormalArg), !xmlTypeFormalArg.IsSingleton);
                    }
                }
            }

            // Invoke the target method
            _helper.Call(extFunc.Method);

            // Return value is on the stack; convert it to canonical ILGen storage type
            if (ndInvoke.XmlType.IsEmpty)
            {
                _helper.Emit(OpCodes.Ldsfld, XmlILMethods.StorageMethods[typeof(XPathItem)].SeqEmpty);
            }
            else if (clrTypeRetSrc != clrTypeRetDst)
            {
                // (T) runtime.ChangeTypeXsltResult(idxType, (object) value);
                _helper.TreatAs(clrTypeRetSrc, typeof(object));
                _helper.Call(XmlILMethods.ChangeTypeXsltResult);
                _helper.TreatAs(typeof(object), clrTypeRetDst);
            }
            else if (ndName.NamespaceUri.Length != 0 && !clrTypeRetSrc.GetTypeInfo().IsValueType)
            {
                // Check for null if a user-defined extension function returns a reference type
                Label lblSkip = _helper.DefineLabel();
                _helper.Emit(OpCodes.Dup);
                _helper.Emit(OpCodes.Brtrue, lblSkip);
                _helper.LoadQueryRuntime();
                _helper.Emit(OpCodes.Ldstr, SR.Xslt_ItemNull);
                _helper.Call(XmlILMethods.ThrowException);
                _helper.MarkLabel(lblSkip);
            }

            _iterCurr.Storage = StorageDescriptor.Stack(GetItemStorageType(ndInvoke), !ndInvoke.XmlType.IsSingleton);

            return ndInvoke;
        }