Exemple #1
0
        private QilNode RelationalOperator(XPathOperator op, QilNode left, QilNode right)
        {
            Debug.Assert(op == XPathOperator.Lt || op == XPathOperator.Le || op == XPathOperator.Gt || op == XPathOperator.Ge);
            XmlQueryType leftType  = left.XmlType;
            XmlQueryType rightType = right.XmlType;

            if (_f.IsAnyType(left) || _f.IsAnyType(right))
            {
                return(_f.InvokeRelationalOperator(s_qilOperator[(int)op], left, right));
            }
            else if (leftType.IsNode && rightType.IsNode)
            {
                return(CompareNodeSetAndNodeSet(op, left, right, XmlTypeCode.Double));
            }
            else if (leftType.IsNode)
            {
                XmlTypeCode compType = rightType.TypeCode == XmlTypeCode.Boolean ? XmlTypeCode.Boolean : XmlTypeCode.Double;
                return(CompareNodeSetAndValue(op, /*nodeset:*/ left, /*val:*/ right, compType));
            }
            else if (rightType.IsNode)
            {
                XmlTypeCode compType = leftType.TypeCode == XmlTypeCode.Boolean ? XmlTypeCode.Boolean : XmlTypeCode.Double;
                op = InvertOp(op);
                return(CompareNodeSetAndValue(op, /*nodeset:*/ right, /*val:*/ left, compType));
            }
            else
            {
                return(CompareValues(op, left, right, XmlTypeCode.Double));
            }
        }
        //-----------------------------------------------
        // Constructor
        //-----------------------------------------------

        /// <summary>
        /// Construct a node
        /// </summary>
        public QilFunction(QilNodeType nodeType, QilNode arguments, QilNode definition, QilNode sideEffects, XmlQueryType resultType)
            : base(nodeType) {
            this.arguments = arguments;
            this.definition = definition;
            this.sideEffects = sideEffects;
            this.xmlType = resultType;
        }
        /// <summary>
        /// Calculate starting xml states that will result when iterating over and constructing an expression of the specified type.
        /// </summary>
        private void StartLoop(XmlQueryType typ, XmlILConstructInfo info)
        {
            Debug.Assert(!typ.IsSingleton);

            // This is tricky, because the looping introduces a feedback loop:
            //   1. Because loops may be executed many times, the beginning set of states must include the ending set of states.
            //   2. Because loops may be executed 0 times, the final set of states after all looping is complete must include
            //      the initial set of states.
            //
            // +-- states-initial
            // |         |
            // | states-begin-loop <--+
            // |         |            |
            // |  +--------------+    |
            // |  | Construction |    |
            // |  +--------------+    |
            // |         |            |
            // |  states-end-loop ----+
            // |         |
            // +--> states-final

            // Save starting loop states
            info.BeginLoopStates = this.xstates;

            if (typ.MaybeMany)
            {
                // If transition might occur from EnumAttrs to WithinContent, then states-end might be WithinContent, which
                // means states-begin needs to also include WithinContent.
                if (this.xstates == PossibleXmlStates.EnumAttrs && MaybeContent(typ))
                {
                    info.BeginLoopStates = this.xstates = PossibleXmlStates.Any;
                }
            }
        }
Exemple #4
0
        /// <summary>
        /// Add "type" to the list of unique types that are used by this query.  Return the index of
        /// the unique type in the list.
        /// </summary>
        public int DeclareXmlType(XmlQueryType type)
        {
            _uniqueXmlTypes ??= new UniqueList <XmlQueryType>();

            XmlQueryTypeFactory.CheckSerializability(type);
            return(_uniqueXmlTypes.Add(type));
        }
        /// <summary>
        /// Create an XmlQueryType from an Xsd simple type (where variety can be Atomic, List, or Union).
        /// </summary>
        /// <param name="schemaType">the simple Xsd schema type of the atomic value</param>
        /// <param name="isStrict">true if the dynamic type is guaranteed to match the static type exactly</param>
        /// <returns>the atomic value type</returns>
        public static XmlQueryType Type(XmlSchemaSimpleType schemaType, bool isStrict) {
            if (schemaType.Datatype.Variety == XmlSchemaDatatypeVariety.Atomic) {
                // We must special-case xs:anySimpleType because it is broken in Xsd and is sometimes treated as
                // an atomic value and sometimes as a list value.  In XQuery, it always maps to xdt:anyAtomicType*.
                if (schemaType == DatatypeImplementation.AnySimpleType)
                    return AnyAtomicTypeS;

                return ItemType.Create(schemaType, isStrict);
            }

            // Skip restrictions. It is safe to do that because this is a list or union, so it's not a build in type
            while (schemaType.DerivedBy == XmlSchemaDerivationMethod.Restriction)
                schemaType = (XmlSchemaSimpleType) schemaType.BaseXmlSchemaType;

            // Convert Xsd list
            if (schemaType.DerivedBy == XmlSchemaDerivationMethod.List)
                return PrimeProduct(Type(((XmlSchemaSimpleTypeList) schemaType.Content).BaseItemType, isStrict), XmlQueryCardinality.ZeroOrMore);

            // Convert Xsd union
            Debug.Assert(schemaType.DerivedBy == XmlSchemaDerivationMethod.Union);
            XmlSchemaSimpleType[] baseMemberTypes = ((XmlSchemaSimpleTypeUnion) schemaType.Content).BaseMemberTypes;
            XmlQueryType[] queryMemberTypes = new XmlQueryType[baseMemberTypes.Length];

            for (int i = 0; i < baseMemberTypes.Length; i++)
                queryMemberTypes[i] = Type(baseMemberTypes[i], isStrict);

            return Choice(queryMemberTypes);
        }
Exemple #6
0
        public QilNode SafeDocOrderDistinct(QilNode n)
        {
            XmlQueryType xt = n.XmlType !;

            if (xt.MaybeMany)
            {
                if (xt.IsNode && xt.IsNotRtf)
                {
                    // node-set
                    return(DocOrderDistinct(n));
                }
                else if (!xt.IsAtomicValue)
                {
                    QilIterator i;
                    return(Loop(i = Let(n),
                                Conditional(Gt(Length(i), Int32(1)),
                                            DocOrderDistinct(TypeAssert(i, T.NodeNotRtfS)),
                                            i
                                            )
                                ));
                }
            }

            return(n);
        }
Exemple #7
0
        /// <summary>
        /// Return the default Clr data type that will be used to store instances of the QilNode's type.
        /// </summary>
        public static Type GetStorageType(XmlQueryType qyTyp)
        {
            Type storageType;

            if (qyTyp.IsSingleton)
            {
                storageType = TypeCodeToStorage[(int)qyTyp.TypeCode];

                // Non-strict items must store the type along with the value, so use XPathItem
                if (!qyTyp.IsStrict && storageType != typeof(XPathNavigator))
                {
                    return(typeof(XPathItem));
                }
            }
            else
            {
                storageType = TypeCodeToCachedStorage[(int)qyTyp.TypeCode];

                // Non-strict items must store the type along with the value, so use XPathItem
                if (!qyTyp.IsStrict && storageType != typeof(IList <XPathNavigator>))
                {
                    return(typeof(IList <XPathItem>));
                }
            }

            return(storageType);
        }
        public QilNode XsltInvokeEarlyBound(QilNode name, MethodInfo d, XmlQueryType t, IList <QilNode> args)
        {
            QilList list = _f.ActualParameterList();

            list.Add(args);
            return(_f.XsltInvokeEarlyBound(name, _f.LiteralObject(d), list, t));
        }
Exemple #9
0
        QilNode IXPathEnvironment.ResolveVariable(string prefix, string name)
        {
            if (!_allowVariables)
            {
                throw new XslLoadException(SR.Xslt_VariablesNotAllowed);
            }
            string ns = ResolvePrefixThrow(/*ignoreDefaultNs:*/ true, prefix);

            Debug.Assert(ns != null);

            // Look up in params and variables of the current scope and all outer ones
            QilNode?var = _scope.LookupVariable(name, ns);

            if (var == null)
            {
                throw new XslLoadException(SR.Xslt_InvalidVariable, Compiler.ConstructQName(prefix, name));
            }

            // All Node* parameters are guaranteed to be in document order with no duplicates, so TypeAssert
            // this so that optimizer can use this information to avoid redundant sorts and duplicate removal.
            XmlQueryType varType = var.XmlType !;

            if (var.NodeType == QilNodeType.Parameter && varType.IsNode && varType.IsNotRtf && varType.MaybeMany && !varType.IsDod)
            {
                var = _f.TypeAssert(var, XmlQueryTypeFactory.NodeSDod);
            }

            return(var);
        }
Exemple #10
0
        public XmlQueryType CheckAverage(QilUnary node)
        {
            XmlQueryType xmlType = node.Child.XmlType;

            CheckNumericXS(node.Child);
            return(XmlQueryTypeFactory.PrimeProduct(xmlType, xmlType.MaybeEmpty ? XmlQueryCardinality.ZeroOrOne : XmlQueryCardinality.One));
        }
Exemple #11
0
        public void CheckXsltType(QilNode n)
        {
            // Five possible types are: anyType, node-set, string, boolean, and number
            XmlQueryType xt = n.XmlType !;

            switch (xt.TypeCode)
            {
            case XmlTypeCode.String:
            case XmlTypeCode.Boolean:
            case XmlTypeCode.Double:
                Debug.Assert(xt.IsSingleton && xt.IsStrict, "Xslt assumes that these types will always be singleton and strict");
                break;

            case XmlTypeCode.Item:
            case XmlTypeCode.None:
                break;

            case XmlTypeCode.QName:
                Debug.Assert(IsDebug, "QName is reserved as the marker for missing values");
                break;

            default:
                Debug.Assert(xt.IsNode, $"Unexpected expression type: {xt}");
                break;
            }
        }
        /// <summary>
        /// Return true if the type of every item in "seq" matches the xml type identified by "idxType".
        /// </summary>
        public bool MatchesXmlType(IList <XPathItem> seq, int indexType)
        {
            XmlQueryType typBase = GetXmlType(indexType);

            XmlQueryCardinality card = seq.Count switch
            {
                0 => XmlQueryCardinality.Zero,
                1 => XmlQueryCardinality.One,
                _ => XmlQueryCardinality.More,
            };

            if (!(card <= typBase.Cardinality))
            {
                return(false);
            }

            typBase = typBase.Prime;
            for (int i = 0; i < seq.Count; i++)
            {
                if (!CreateXmlType(seq[0]).IsSubtypeOf(typBase))
                {
                    return(false);
                }
            }

            return(true);
        }
Exemple #13
0
        private QilNode EqualityOperator(XPathOperator op, QilNode left, QilNode right)
        {
            Debug.Assert(op == XPathOperator.Eq || op == XPathOperator.Ne);
            XmlQueryType leftType  = left.XmlType;
            XmlQueryType rightType = right.XmlType;

            if (_f.IsAnyType(left) || _f.IsAnyType(right))
            {
                return(_f.InvokeEqualityOperator(s_qilOperator[(int)op], left, right));
            }
            else if (leftType.IsNode && rightType.IsNode)
            {
                return(CompareNodeSetAndNodeSet(op, left, right, XmlTypeCode.String));
            }
            else if (leftType.IsNode)
            {
                return(CompareNodeSetAndValue(op, /*nodeset:*/ left, /*val:*/ right, rightType.TypeCode));
            }
            else if (rightType.IsNode)
            {
                return(CompareNodeSetAndValue(op, /*nodeset:*/ right, /*val:*/ left, leftType.TypeCode));
            }
            else
            {
                XmlTypeCode compType = (
                    leftType.TypeCode == XmlTypeCode.Boolean || rightType.TypeCode == XmlTypeCode.Boolean ? XmlTypeCode.Boolean :
                    leftType.TypeCode == XmlTypeCode.Double || rightType.TypeCode == XmlTypeCode.Double ? XmlTypeCode.Double :
                    /*default:*/ XmlTypeCode.String
                    );
                return(CompareValues(op, left, right, compType));
            }
        }
Exemple #14
0
        // Return true if inferred type of the given expression is never a subtype of T.NodeS
        public bool CannotBeNodeSet(QilNode n)
        {
            XmlQueryType xt = n.XmlType !;

            // Do not report compile error if n is a VarPar, whose inferred type forbids nodes (SQLBUDT 339398)
            return(xt.IsAtomicValue && !xt.IsEmpty && !(n is QilIterator));
        }
Exemple #15
0
        /// <summary>
        /// Return true if the type of every item in "seq" matches the xml type identified by "idxType".
        /// </summary>
        public bool MatchesXmlType(IList <XPathItem> seq, int indexType)
        {
            XmlQueryType        typBase = GetXmlType(indexType);
            XmlQueryCardinality card;

            switch (seq.Count)
            {
            case 0: card = XmlQueryCardinality.Zero; break;

            case 1: card = XmlQueryCardinality.One; break;

            default: card = XmlQueryCardinality.More; break;
            }

            if (!(card <= typBase.Cardinality))
            {
                return(false);
            }

            typBase = typBase.Prime;
            for (int i = 0; i < seq.Count; i++)
            {
                if (!CreateXmlType(seq[0]).IsSubtypeOf(typBase))
                {
                    return(false);
                }
            }

            return(true);
        }
Exemple #16
0
        /// <summary>
        /// If type might contain attributes or namespaces, set appropriate parent element flags.
        /// </summary>
        private void CheckAttributeNamespaceConstruct(XmlQueryType typ)
        {
            // If content might contain attributes,
            if ((typ.NodeKinds & XmlNodeKindFlags.Attribute) != XmlNodeKindFlags.None)
            {
                // Mark element as possibly having attributes and duplicate attributes (since we don't know the names)
                this.parentInfo.MightHaveAttributes          = true;
                this.parentInfo.MightHaveDuplicateAttributes = true;

                // Attribute namespaces might be declared
                this.parentInfo.MightHaveNamespaces = true;
            }

            // If content might contain namespaces,
            if ((typ.NodeKinds & XmlNodeKindFlags.Namespace) != XmlNodeKindFlags.None)
            {
                // Then element might have namespaces,
                this.parentInfo.MightHaveNamespaces = true;

                // If attributes might already have been constructed,
                if (this.parentInfo.MightHaveAttributes)
                {
                    // Then attributes might precede namespace declarations
                    this.parentInfo.MightHaveNamespacesAfterAttributes = true;
                }
            }
        }
Exemple #17
0
 private QilNode MatchPatterns(QilIterator it, XmlQueryType xt, List <Pattern> patternList, QilNode otherwise)
 {
     if (patternList.Count == 0)
     {
         return(otherwise);
     }
     return(_f.Conditional(_f.IsType(it, xt), MatchPatterns(it, patternList), otherwise));
 }
Exemple #18
0
        public QilLiteral LiteralType(XmlQueryType value)
        {
            QilLiteral n = new QilLiteral(QilNodeType.LiteralType, value);

            n.XmlType = this.typeCheck.CheckLiteralType(n);
            TraceNode(n);
            return(n);
        }
Exemple #19
0
        public QilParameter Parameter(QilNode defaultValue, QilNode name, XmlQueryType xmlType)
        {
            QilParameter n = new QilParameter(QilNodeType.Parameter, defaultValue, name, xmlType);

            n.XmlType = this.typeCheck.CheckParameter(n);
            TraceNode(n);
            return(n);
        }
Exemple #20
0
        public QilNode Unknown(XmlQueryType xmlType)
        {
            QilNode n = new QilNode(QilNodeType.Unknown, xmlType);

            n.XmlType = this.typeCheck.CheckUnknown(n);
            TraceNode(n);
            return(n);
        }
Exemple #21
0
        public bool IsAnyType(QilNode n)
        {
            XmlQueryType xt     = n.XmlType;
            bool         result = !(xt.IsStrict || xt.IsNode);

            Debug.Assert(result == (xt.TypeCode == XmlTypeCode.Item || xt.TypeCode == XmlTypeCode.AnyAtomicType), "What else can it be?");
            return(result);
        }
Exemple #22
0
        /// <summary>
        /// Add "type" to the list of unique types that are used by this query.  Return the index of
        /// the unique type in the list.
        /// </summary>
        public int DeclareXmlType(XmlQueryType type)
        {
            if (this.uniqueXmlTypes == null)
            {
                this.uniqueXmlTypes = new UniqueList <XmlQueryType>();
            }

            return(this.uniqueXmlTypes.Add(type));
        }
        //-----------------------------------------------
        // 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));
        }
        /// <summary>
        /// Add "type" to the list of unique types that are used by this query.  Return the index of
        /// the unique type in the list.
        /// </summary>
        public int DeclareXmlType(XmlQueryType type)
        {
            if (this.uniqueXmlTypes == null)
            {
                this.uniqueXmlTypes = new UniqueList <XmlQueryType>();
            }

            XmlQueryTypeFactory.CheckSerializability(type);
            return(this.uniqueXmlTypes.Add(type));
        }
        //-----------------------------------------------
        // 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));
        }
Exemple #26
0
        /// <summary>
        /// Bind to the specified MethodInfo.
        /// </summary>
        private void Bind(MethodInfo meth)
        {
            ParameterInfo[] paramInfo = meth.GetParameters();
            int             i;

            // Save the MethodInfo
            _meth = meth;

            // Get the Clr type of each parameter
            _argClrTypes = new Type[paramInfo.Length];
            for (i = 0; i < paramInfo.Length; i++)
            {
                _argClrTypes[i] = GetClrType(paramInfo[i].ParameterType);
            }

            // Get the Clr type of the return value
            _retClrType = GetClrType(_meth.ReturnType);

            // Infer an Xml type for each Clr type
            _argXmlTypes = new XmlQueryType[paramInfo.Length];
            for (i = 0; i < paramInfo.Length; i++)
            {
                _argXmlTypes[i] = InferXmlType(_argClrTypes[i]);

                // BUGBUG:
                // 1. A couple built-in Xslt functions  allow Rtf as argument, which is
                //    different from what InferXmlType returns.  Until XsltEarlyBound references
                //    a Qil function, we'll work around this case by assuming that all built-in
                //    Xslt functions allow Rtf.
                // 2. Script arguments should allow node-sets which are not statically known
                //    to be Dod to be passed, so relax static typing in this case.
                if (_namespaceUri.Length == 0)
                {
                    if ((object)_argXmlTypes[i] == (object)XmlQueryTypeFactory.NodeNotRtf)
                    {
                        _argXmlTypes[i] = XmlQueryTypeFactory.Node;
                    }
                    else if ((object)_argXmlTypes[i] == (object)XmlQueryTypeFactory.NodeSDod)
                    {
                        _argXmlTypes[i] = XmlQueryTypeFactory.NodeS;
                    }
                }
                else
                {
                    if ((object)_argXmlTypes[i] == (object)XmlQueryTypeFactory.NodeSDod)
                    {
                        _argXmlTypes[i] = XmlQueryTypeFactory.NodeNotRtfS;
                    }
                }
            }

            // Infer an Xml type for the return Clr type
            _retXmlType = InferXmlType(_retClrType);
        }
Exemple #27
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);
            }
Exemple #28
0
        /// <summary>
        /// Calculate ending xml states that will result when iterating over and constructing an expression of the specified type.
        /// </summary>
        private void EndLoop(XmlQueryType typ, XmlILConstructInfo info)
        {
            Debug.Assert(!typ.IsSingleton);

            // Save ending loop states
            info.EndLoopStates = this.xstates;

            // If it's possible to loop zero times, then states-final needs to include states-initial
            if (typ.MaybeEmpty && info.InitialStates != this.xstates)
            {
                this.xstates = PossibleXmlStates.Any;
            }
        }
        //-----------------------------------------------
        // QilReplaceVisitor methods
        //-----------------------------------------------

        /// <summary>
        /// Once children have been replaced, the Xml type is recalculated.
        /// </summary>
        protected virtual void RecalculateType(QilNode node, XmlQueryType oldType) {
            XmlQueryType newType;

            newType = f.TypeChecker.Check(node);

            // Note the use of AtMost to account for cases when folding of Error nodes in the graph cause
            // cardinality to be recalculated.
            // For example, (Sequence (TextCtor (Error "error")) (Int32 1)) => (Sequence (Error "error") (Int32 1))
            // In this case, cardinality has gone from More to One
            Debug.Assert(newType.IsSubtypeOf(XmlQueryTypeFactory.AtMost(oldType, oldType.Cardinality)), "Replace shouldn't relax original type");

            node.XmlType = newType;
        }
        /// <summary>
        /// Bind to the specified MethodInfo.
        /// </summary>
        private void Bind(MethodInfo meth)
        {
            ParameterInfo[] paramInfo = meth.GetParameters();
            int             i;

            // Save the MethodInfo
            this.meth = meth;

            // Get the Clr type of each parameter
            this.argClrTypes = new Type[paramInfo.Length];
            for (i = 0; i < paramInfo.Length; i++)
            {
                this.argClrTypes[i] = GetClrType(paramInfo[i].ParameterType);
            }

            // Get the Clr type of the return value
            this.retClrType = GetClrType(this.meth.ReturnType);

            // Infer an Xml type for each Clr type
            this.argXmlTypes = new XmlQueryType[paramInfo.Length];
            for (i = 0; i < paramInfo.Length; i++)
            {
                this.argXmlTypes[i] = InferXmlType(this.argClrTypes[i]);

                //



                if (this.namespaceUri.Length == 0)
                {
                    if ((object)this.argXmlTypes[i] == (object)XmlQueryTypeFactory.NodeNotRtf)
                    {
                        this.argXmlTypes[i] = XmlQueryTypeFactory.Node;
                    }
                    else if ((object)this.argXmlTypes[i] == (object)XmlQueryTypeFactory.NodeSDod)
                    {
                        this.argXmlTypes[i] = XmlQueryTypeFactory.NodeS;
                    }
                }
                else
                {
                    if ((object)this.argXmlTypes[i] == (object)XmlQueryTypeFactory.NodeSDod)
                    {
                        this.argXmlTypes[i] = XmlQueryTypeFactory.NodeNotRtfS;
                    }
                }
            }

            // Infer an Xml type for the return Clr type
            this.retXmlType = InferXmlType(this.retClrType);
        }
Exemple #31
0
        private XmlQueryType DistinctType(XmlQueryType type)
        {
            if (type.Cardinality == XmlQueryCardinality.More)
            {
                return(XmlQueryTypeFactory.PrimeProduct(type, XmlQueryCardinality.OneOrMore));
            }

            if (type.Cardinality == XmlQueryCardinality.NotOne)
            {
                return(XmlQueryTypeFactory.PrimeProduct(type, XmlQueryCardinality.ZeroOrMore));
            }

            return(type);
        }
        //-----------------------------------------------
        // QilReplaceVisitor methods
        //-----------------------------------------------

        /// <summary>
        /// Once children have been replaced, the Xml type is recalculated.
        /// </summary>
        protected virtual void RecalculateType(QilNode node, XmlQueryType oldType)
        {
            XmlQueryType newType;

            newType = f.TypeChecker.Check(node);

            // Note the use of AtMost to account for cases when folding of Error nodes in the graph cause
            // cardinality to be recalculated.
            // For example, (Sequence (TextCtor (Error "error")) (Int32 1)) => (Sequence (Error "error") (Int32 1))
            // In this case, cardinality has gone from More to One
            Debug.Assert(newType.IsSubtypeOf(XmlQueryTypeFactory.AtMost(oldType, oldType.Cardinality)), "Replace shouldn't relax original type");

            node.XmlType = newType;
        }
Exemple #33
0
        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>
        /// Return the default Clr data type that will be used to store instances of the QilNode's type.
        /// </summary>
        public static Type GetStorageType(XmlQueryType qyTyp) {
            Type storageType;

            if (qyTyp.IsSingleton) {
                storageType = TypeCodeToStorage[(int) qyTyp.TypeCode];

                // Non-strict items must store the type along with the value, so use XPathItem
                if (!qyTyp.IsStrict && storageType != typeof(XPathNavigator))
                    return typeof(XPathItem);
            }
            else {
                storageType = TypeCodeToCachedStorage[(int) qyTyp.TypeCode];

                // Non-strict items must store the type along with the value, so use XPathItem
                if (!qyTyp.IsStrict && storageType != typeof(IList<XPathNavigator>))
                    return typeof(IList<XPathItem>);
            }

            return storageType;
        }
        private XmlQueryCardinality AddDescendantParticle(List<XmlQueryType> list, Dictionary<XmlQualifiedName, XmlQueryCardinality> allTypes, XmlSchemaParticle particle, XmlQueryType filter) {
            XmlQueryCardinality card = XmlQueryCardinality.None;
            XmlSchemaElement element = particle as XmlSchemaElement;
            if (element != null) {
                // Single element
                XmlQueryType elementType = CreateElementType(element);

                // Add it
                card = AddFilteredPrime(list, elementType, filter);

                // Descend
                card += AddElementOrTextDescendants(list, allTypes, elementType.SchemaType, filter);
            }
            else {
                XmlSchemaAny any = particle as XmlSchemaAny;
                if (any != null) {
                    // Descendants of any
                    card = AddFilteredPrime(list, Element, filter);
                }
                else {
                    XmlSchemaGroupBase group = particle as XmlSchemaGroupBase;
                    if (group.Items.Count != 0) {
                        if (particle is XmlSchemaChoice) {
                            foreach (XmlSchemaParticle p in group.Items) {
                                card |= AddDescendantParticle(list, allTypes, p, filter);
                            }
                        }
                        else { // Sequence and  All
                            foreach (XmlSchemaParticle p in group.Items) {
                                card += AddDescendantParticle(list, allTypes, p, filter);
                            }
                        }
                    }
                }
            }
            return card * CardinalityOfParticle(particle);
        }
 private XmlQueryCardinality AddElementOrTextDescendants(List<XmlQueryType> list,
     Dictionary<XmlQualifiedName, XmlQueryCardinality> allTypes, XmlSchemaType sourceSchemaType, XmlQueryType filter) {
     XmlQueryCardinality card = XmlQueryCardinality.None;
     if (sourceSchemaType == XmlSchemaComplexType.UntypedAnyType) {
         card = AddFilteredPrime(list, UntypedElement, filter) * XmlQueryCardinality.ZeroOrMore;
         card += AddFilteredPrime(list, Text, filter);
     }
     else if (sourceSchemaType.Datatype != null) {
         // Text is the only child node simple content of complext type
         card = AddFilteredPrime(list, Text, filter, true) * XmlQueryCardinality.ZeroOrOne;
     }
     else {
         // Complex content
         XmlSchemaComplexType complexType = (XmlSchemaComplexType)sourceSchemaType;
         if (complexType.QualifiedName.IsEmpty || !allTypes.TryGetValue(complexType.QualifiedName, out card)) {
             allTypes[complexType.QualifiedName] = XmlQueryCardinality.ZeroOrMore; // take care of left recursion
             card = AddDescendantParticle(list, allTypes, complexType.ContentTypeParticle, filter);
             allTypes[complexType.QualifiedName] = card;  //set correct card
             if (complexType.ContentType == XmlSchemaContentType.Mixed) {
                 card += AddFilteredPrime(list, Text, filter);
             }
         }
     }
     return card;
 }
        /// <summary>
        /// Adds itemType to a union. Returns false if new item is a subtype of one of the types in the list.
        /// </summary>
        private static void AddItemToChoice(List<XmlQueryType> accumulator, XmlQueryType itemType) {
            Debug.Assert(itemType.IsSingleton, "All types should be prime.");

            bool addToList = true;
            for (int i = 0; i < accumulator.Count; i++) {
                // If new prime is a subtype of existing prime, don't add it to the union
                if (itemType.IsSubtypeOf(accumulator[i])) {
                    return;
                }

                // If new prime is a subtype of existing prime, then replace the existing prime with new prime
                if (accumulator[i].IsSubtypeOf(itemType)) {
                    if (addToList) {
                        addToList = false;
                        accumulator[i] = itemType;
                    }
                    else {
                        accumulator.RemoveAt(i);
                        i --;
                    }
                }
            }

            if (addToList) {
                accumulator.Add(itemType);
            }
        }
        /// <summary>
        /// Each XmlQueryType has multiple legal CLR representations.  Ensure that all items returned by this iterator are in
        /// the Clr representation specified by "storageTypeDest".
        /// </summary>
        public void EnsureItemStorageType(XmlQueryType xmlType, Type storageTypeDest) {
            // If source type = destination type, then done
            if (this.storage.ItemStorageType == storageTypeDest)
                goto SetStorageType;

            Debug.Assert(this.storage.ItemStorageType == typeof(XPathItem) || storageTypeDest == typeof(XPathItem),
                         "EnsureItemStorageType must convert to or from Item");

            // If items are cached,
            if (this.storage.IsCached) {
                // Check for special case of IList<XPathNavigator> -> IList<XPathItem>
                if (this.storage.ItemStorageType == typeof(XPathNavigator)) {
                    EnsureStack();
                    this.helper.Call(XmlILMethods.NavsToItems);
                    goto SetStorageType;
                }

                // Check for special case of IList<XPathItem> -> IList<XPathNavigator>
                if (storageTypeDest == typeof(XPathNavigator)) {
                    EnsureStack();
                    this.helper.Call(XmlILMethods.ItemsToNavs);
                    goto SetStorageType;
                }
            }

            // Iterate over each item, and convert each to the destination type
            EnsureStackNoCache();

            // If source type is Item,
            if (this.storage.ItemStorageType == typeof(XPathItem)) {
                // Then downcast to Navigator
                if (storageTypeDest == typeof(XPathNavigator)) {
                    this.helper.Emit(OpCodes.Castclass, typeof(XPathNavigator));
                }
                else {
                    // Call ValueAs methods for atomic types
                    this.helper.CallValueAs(storageTypeDest);
                }
                goto SetStorageType;
            }
            else if (this.storage.ItemStorageType == typeof(XPathNavigator)) {
                // No-op if converting from XPathNavigator to XPathItem
                Debug.Assert(storageTypeDest == typeof(XPathItem), "Must be converting from XPathNavigator to XPathItem");
                goto SetStorageType;
            }

            // Destination type must be item, so generate code to create an XmlAtomicValue
            this.helper.LoadInteger(this.helper.StaticData.DeclareXmlType(xmlType));
            this.helper.LoadQueryRuntime();
            this.helper.Call(XmlILMethods.StorageMethods[this.storage.ItemStorageType].ToAtomicValue);

        SetStorageType:
            this.storage = this.storage.ToStorageType(storageTypeDest);
        }
 public QilNode XsltInvokeEarlyBound(QilNode name, MethodInfo d, XmlQueryType t, IList<QilNode> args) {
     QilList list = f.ActualParameterList();
     list.Add(args);
     return f.XsltInvokeEarlyBound(name, f.LiteralObject(d), list, t);
 }
 //-----------------------------------------------
 // Type operators
 //-----------------------------------------------
 public QilNode TypeAssert(QilNode expr, XmlQueryType t) {
     return f.TypeAssert(expr, t);
 }
 //-----------------------------------------------
 // function definition and invocation
 //-----------------------------------------------
 public QilFunction Function(QilList args, QilNode sideEffects, XmlQueryType resultType) {
     Debug.Assert(args.NodeType == QilNodeType.FormalParameterList);
     return f.Function(args, sideEffects, resultType);
 }
        private XmlQueryCardinality AddFilteredPrime(List<XmlQueryType> list, XmlQueryType source, XmlQueryType filter, bool forseSingle) {
            Debug.Assert(source.IsNode && source.IsSingleton);
            Debug.Assert(filter.IsNode && filter.IsSingleton);

            // Intersect types
            XmlQueryType intersection = IntersectItemTypes(source, filter);
            if ((object)intersection == (object)None) {
                return XmlQueryCardinality.Zero;
            }
            AddItemToChoice(list, intersection);
            // In the case of forseSingle - filtering all nodes behave as singletones
            XmlTypeCode typeCode = (forseSingle ? XmlTypeCode.Node : intersection.TypeCode);
            switch (typeCode) {
            case XmlTypeCode.Node:
            case XmlTypeCode.Document:
            case XmlTypeCode.Element:
                // Filter can result in empty sequence if filter is not wider then source
                if (intersection == source)
                    return XmlQueryCardinality.One;
                else
                    return  XmlQueryCardinality.ZeroOrOne;

            case XmlTypeCode.Attribute:
                    // wildcard attribute matches more then one node
                if (!intersection.NameTest.IsSingleName)
                    return XmlQueryCardinality.ZeroOrMore;
                else if (intersection == source)
                    return XmlQueryCardinality.One;
                else
                    return  XmlQueryCardinality.ZeroOrOne;
            case XmlTypeCode.Comment:
            case XmlTypeCode.Text:
            case XmlTypeCode.ProcessingInstruction:
            case XmlTypeCode.Namespace:
                return XmlQueryCardinality.ZeroOrMore;

            default:
                Debug.Assert(false);
                return XmlQueryCardinality.None;
            }
        }
        /// <summary>
        /// Construct the intersection of two lists of prime XmlQueryTypes.
        /// </summary>
        private XmlQueryType IntersectItemTypes(XmlQueryType left, XmlQueryType right) {
            Debug.Assert(left.Count == 1 && left.IsSingleton, "left should be an item");
            Debug.Assert(right.Count == 1 && right.IsSingleton, "right should be an item");
            if (left.TypeCode == right.TypeCode && (left.NodeKinds & (XmlNodeKindFlags.Document | XmlNodeKindFlags.Element | XmlNodeKindFlags.Attribute)) != 0) {
                if (left.TypeCode == XmlTypeCode.Node) {
                    return left;
                }
                // Intersect name tests
                XmlQualifiedNameTest nameTest = left.NameTest.Intersect(right.NameTest);

                // Intersect types
                XmlSchemaType type = XmlSchemaType.IsDerivedFrom(left.SchemaType, right.SchemaType, /* except:*/XmlSchemaDerivationMethod.Empty) ? left.SchemaType :
                    XmlSchemaType.IsDerivedFrom(right.SchemaType, left.SchemaType, /* except:*/XmlSchemaDerivationMethod.Empty) ? right.SchemaType : null;
                bool isNillable = left.IsNillable && right.IsNillable;

                if ((object)nameTest == (object)left.NameTest && type == left.SchemaType && isNillable == left.IsNillable) {
                    // left is a subtype of right return left
                    return left;
                }
                else if ((object)nameTest == (object)right.NameTest && type == right.SchemaType && isNillable == right.IsNillable) {
                    // right is a subtype of left return right
                    return right;
                }
                else if (nameTest != null && type != null) {
                    // create a new type
                    return ItemType.Create(left.TypeCode, nameTest, type, isNillable);
                }
            }
            else if (left.IsSubtypeOf(right)) {
                // left is a subset of right, so left is in the intersection
                return left;
            }
            else if (right.IsSubtypeOf(left)) {
                // right is a subset of left, so right is in the intersection
                return right;
            }
            return None;
        }
        private XmlQueryType DistinctType(XmlQueryType type) {
            if (type.Cardinality == XmlQueryCardinality.More)
                return XmlQueryTypeFactory.PrimeProduct(type, XmlQueryCardinality.OneOrMore);

            if (type.Cardinality == XmlQueryCardinality.NotOne)
                return XmlQueryTypeFactory.PrimeProduct(type, XmlQueryCardinality.ZeroOrMore);

            return type;
        }
 private void CheckXmlType(QilNode node, XmlQueryType xmlType) {
     Check(node.XmlType.IsSubtypeOf(xmlType), node, "Node's type " + node.XmlType + " is not a subtype of " + xmlType);
 }
        /// <summary>
        /// Convert from the Clr type of "value" to the default Clr type that ILGen uses to represent the xml type, using
        /// the conversion rules of the xml type.
        /// </summary>
        internal object ChangeTypeXsltResult(XmlQueryType xmlType, object value) {
            if (value == null)
                throw new XslTransformException(Res.Xslt_ItemNull, string.Empty);

            switch (xmlType.TypeCode) {
                case XmlTypeCode.String:
                    if (value.GetType() == XsltConvert.DateTimeType)
                        value = XsltConvert.ToString((DateTime) value);
                    break;

                case XmlTypeCode.Double:
                    if (value.GetType() != XsltConvert.DoubleType)
                        value = ((IConvertible) value).ToDouble(null);

                    break;

                case XmlTypeCode.Node:
                    if (!xmlType.IsSingleton) {
                        XPathArrayIterator iter = value as XPathArrayIterator;

                        // Special-case XPathArrayIterator in order to avoid copies
                        if (iter != null && iter.AsList is XmlQueryNodeSequence) {
                            value = iter.AsList as XmlQueryNodeSequence;
                        }
                        else {
                            // Iterate over list and ensure it only contains nodes
                            XmlQueryNodeSequence seq = new XmlQueryNodeSequence();
                            IList list = value as IList;

                            if (list != null) {
                                for (int i = 0; i < list.Count; i++)
                                    seq.Add(EnsureNavigator(list[i]));
                            }
                            else {
                                foreach (object o in (IEnumerable) value)
                                    seq.Add(EnsureNavigator(o));
                            }

                            value = seq;
                        }

                        // Always sort node-set by document order
                        value = ((XmlQueryNodeSequence) value).DocOrderDistinct(this.docOrderCmp);
                    }
                    break;

                case XmlTypeCode.Item: {
                    Type sourceType = value.GetType();
                    IXPathNavigable navigable;

                    // If static type is item, then infer type based on dynamic value
                    switch (XsltConvert.InferXsltType(sourceType).TypeCode) {
                        case XmlTypeCode.Boolean:
                            value = new XmlQueryItemSequence(new XmlAtomicValue(XmlSchemaType.GetBuiltInSimpleType(XmlTypeCode.Boolean), value));
                            break;

                        case XmlTypeCode.Double:
                            value = new XmlQueryItemSequence(new XmlAtomicValue(XmlSchemaType.GetBuiltInSimpleType(XmlTypeCode.Double), ((IConvertible) value).ToDouble(null)));
                            break;

                        case XmlTypeCode.String:
                            if (sourceType == XsltConvert.DateTimeType)
                                value = new XmlQueryItemSequence(new XmlAtomicValue(XmlSchemaType.GetBuiltInSimpleType(XmlTypeCode.String), XsltConvert.ToString((DateTime) value)));
                            else
                                value = new XmlQueryItemSequence(new XmlAtomicValue(XmlSchemaType.GetBuiltInSimpleType(XmlTypeCode.String), value));
                            break;

                        case XmlTypeCode.Node:
                            // Support XPathNavigator[]
                            value = ChangeTypeXsltResult(XmlQueryTypeFactory.NodeS, value);
                            break;

                        case XmlTypeCode.Item:
                            // Support XPathNodeIterator
                            if (value is XPathNodeIterator) {
                                value = ChangeTypeXsltResult(XmlQueryTypeFactory.NodeS, value);
                                break;
                            }

                            // Support IXPathNavigable and XPathNavigator
                            navigable = value as IXPathNavigable;
                            if (navigable != null) {
                                if (value is XPathNavigator)
                                    value = new XmlQueryNodeSequence((XPathNavigator) value);
                                else
                                    value = new XmlQueryNodeSequence(navigable.CreateNavigator());
                                break;
                            }

                            throw new XslTransformException(Res.Xslt_UnsupportedClrType, sourceType.Name);
                    }
                    break;
                }
            }

            Debug.Assert(XmlILTypeHelper.GetStorageType(xmlType).IsAssignableFrom(value.GetType()), "Xml type " + xmlType + " is not represented in ILGen as " + value.GetType().Name);
            return value;
        }
        /// <summary>
        /// Convert from the Clr type of "value" to Clr type "destinationType" using V1 Xslt rules.
        /// These rules include converting any Rtf values to Nodes.
        /// </summary>
        internal object ChangeTypeXsltArgument(XmlQueryType xmlType, object value, Type destinationType) {
            Debug.Assert(XmlILTypeHelper.GetStorageType(xmlType).IsAssignableFrom(value.GetType()),
                         "Values passed to ChangeTypeXsltArgument should be in ILGen's default Clr representation.");
            Debug.Assert(destinationType == XsltConvert.ObjectType || !destinationType.IsAssignableFrom(value.GetType()),
                         "No need to call ChangeTypeXsltArgument since value is already assignable to destinationType " + destinationType);

            switch (xmlType.TypeCode) {
                case XmlTypeCode.String:
                    if (destinationType == XsltConvert.DateTimeType)
                        value = XsltConvert.ToDateTime((string) value);
                    break;

                case XmlTypeCode.Double:
                    if (destinationType != XsltConvert.DoubleType)
                        value = Convert.ChangeType(value, destinationType, CultureInfo.InvariantCulture);
                    break;

                case XmlTypeCode.Node:
                    Debug.Assert(xmlType != XmlQueryTypeFactory.Node && xmlType != XmlQueryTypeFactory.NodeS,
                                 "Rtf values should have been eliminated by caller.");

                    if (destinationType == XsltConvert.XPathNodeIteratorType) {
                        value = new XPathArrayIterator((IList) value);
                    }
                    else if (destinationType == XsltConvert.XPathNavigatorArrayType) {
                        // Copy sequence to XPathNavigator[]
                        IList<XPathNavigator> seq = (IList<XPathNavigator>) value;
                        XPathNavigator[] navArray = new XPathNavigator[seq.Count];

                        for (int i = 0; i < seq.Count; i++)
                            navArray[i] = seq[i];

                        value = navArray;
                    }
                    break;

                case XmlTypeCode.Item: {
                    // Only typeof(object) is supported as a destination type
                    if (destinationType != XsltConvert.ObjectType)
                        throw new XslTransformException(Res.Xslt_UnsupportedClrType, destinationType.Name);

                    // Convert to default, backwards-compatible representation
                    //   1. NodeSet: System.Xml.XPath.XPathNodeIterator
                    //   2. Rtf: System.Xml.XPath.XPathNavigator
                    //   3. Other:   Default V1 representation
                    IList<XPathItem> seq = (IList<XPathItem>) value;
                    if (seq.Count == 1) {
                        XPathItem item = seq[0];

                        if (item.IsNode) {
                            // Node or Rtf
                            RtfNavigator rtf = item as RtfNavigator;
                            if (rtf != null)
                                value = rtf.ToNavigator();
                            else
                                value = new XPathArrayIterator((IList) value);
                        }
                        else {
                            // Atomic value
                            value = item.TypedValue;
                        }
                    }
                    else {
                        // Nodeset
                        value = new XPathArrayIterator((IList) value);
                    }
                    break;
                }
            }

            Debug.Assert(destinationType.IsAssignableFrom(value.GetType()), "ChangeType from type " + value.GetType().Name + " to type " + destinationType.Name + " failed");
            return value;
        }
 public QilParameter Parameter(XmlQueryType t) {
     return f.Parameter(t);
 }
 public QilParameter Parameter(QilNode defaultValue, QilName name, XmlQueryType t) {
     return f.Parameter(defaultValue, name, t);
 }
        /// <summary>
        /// Apply filter an item type, add the result to a list, return cardinality
        /// </summary>
        private XmlQueryCardinality AddFilteredPrime(List<XmlQueryType> list, XmlQueryType source, XmlQueryType filter) {
            return AddFilteredPrime(list, source, filter, false);

        }
 public QilNode Unknown(XmlQueryType t) {
     return f.Unknown(t);
 }
 /// <summary>
 /// Construct the union of two XmlQueryTypes
 /// </summary>
 /// <param name="left">the left type</param>
 /// <param name="right">the right type</param>
 /// <returns>the union type</returns>
 public static XmlQueryType Choice(XmlQueryType left, XmlQueryType right) {
     return SequenceType.Create(ChoiceType.Create(PrimeChoice(new List<XmlQueryType>(left), right)), left.Cardinality | right.Cardinality);
 }
 public QilNode IsType(QilNode expr, XmlQueryType t) {
     Debug.Assert(t != null, "Type can't be null");
     return f.IsType(expr, t);
 }
 /// <summary>
 ///  Descend though the content model
 /// </summary>
 private XmlQueryCardinality AddChildParticle(List<XmlQueryType> list, XmlSchemaParticle particle, XmlQueryType filter) {
     XmlQueryCardinality card = XmlQueryCardinality.None;
     XmlSchemaElement element = particle as XmlSchemaElement;
     if (element != null) {
         // Single element
         card = AddFilteredPrime(list, CreateElementType(element), filter);
     }
     else {
         // XmlSchemaAny matches more then one element
         XmlSchemaAny any = particle as XmlSchemaAny;
         if (any != null) {
             XmlSchemaType elementSchemaType = any.ProcessContentsCorrect == XmlSchemaContentProcessing.Skip ? XmlSchemaComplexType.UntypedAnyType : XmlSchemaComplexType.AnyType;
             switch (any.NamespaceList.Type) {
             case NamespaceList.ListType.Set:
                 // Add a separate type for each namespace in the list
                 foreach (string ns in any.NamespaceList.Enumerate) {
                     card |= AddFilteredPrime(list, CreateElementType(ns, false, elementSchemaType), filter);
                 }
                 break;
             case NamespaceList.ListType.Other:
                 // Add ##other
                 card = AddFilteredPrime(list, CreateElementType(any.NamespaceList.Excluded, true, elementSchemaType), filter);
                 break;
             case NamespaceList.ListType.Any:
             default:
                 // Add ##any
                 card = AddFilteredPrime(list, any.ProcessContentsCorrect == XmlSchemaContentProcessing.Skip ? UntypedElement : Element, filter);
                 break;
             }
         }
         else {
             //  recurse into particle group
             XmlSchemaGroupBase group = particle as XmlSchemaGroupBase;
             if (group.Items.Count != 0) {
                 if (particle is XmlSchemaChoice) {
                     foreach (XmlSchemaParticle p in group.Items) {
                         card |= AddChildParticle(list, p, filter);
                     }
                 }
                 else { // Sequence and  All
                     foreach (XmlSchemaParticle p in group.Items) {
                         card += AddChildParticle(list, p, filter);
                     }
                 }
             }
         }
     }
     return card * CardinalityOfParticle(particle);
 }
 public QilNode XsltConvert(QilNode expr, XmlQueryType t) {
     return f.XsltConvert(expr, t);
 }
Exemple #56
0
        //-----------------------------------------------
        // XmlSortKeyAccumulator methods
        //-----------------------------------------------

        public void AddSortKey(XmlQueryType keyType)
        {
            MethodInfo meth = null;

            if (keyType == null)
            {
                meth = XmlILMethods.SortKeyEmpty;
            }
            else
            {
                Debug.Assert(keyType.IsAtomicValue, "Sort key must have atomic value type.");

                switch (keyType.TypeCode)
                {
                    case XmlTypeCode.String: meth = XmlILMethods.SortKeyString; break;
                    case XmlTypeCode.Decimal: meth = XmlILMethods.SortKeyDecimal; break;
                    case XmlTypeCode.Integer: meth = XmlILMethods.SortKeyInteger; break;
                    case XmlTypeCode.Int: meth = XmlILMethods.SortKeyInt; break;
                    case XmlTypeCode.Boolean: meth = XmlILMethods.SortKeyInt; break;
                    case XmlTypeCode.Double: meth = XmlILMethods.SortKeyDouble; break;
                    case XmlTypeCode.DateTime: meth = XmlILMethods.SortKeyDateTime; break;

                    case XmlTypeCode.None:
                        // Empty sequence, so this path will never actually be taken
                        Emit(OpCodes.Pop);
                        meth = XmlILMethods.SortKeyEmpty;
                        break;

                    case XmlTypeCode.AnyAtomicType:
                        Debug.Assert(false, "Heterogenous sort key is not allowed.");
                        return;

                    default:
                        Debug.Assert(false, "Sorting over datatype " + keyType.TypeCode + " is not allowed.");
                        break;
                }
            }

            Call(meth);
        }
            /// <summary>
            /// Create sequence type from prime and cardinality.
            /// </summary>
            public static XmlQueryType Create(XmlQueryType prime, XmlQueryCardinality card) {
                Debug.Assert(prime != null, "SequenceType can only modify the cardinality of a non-null XmlQueryType.");
                Debug.Assert(prime.IsSingleton, "Prime type must have cardinality one.");

                if (prime.TypeCode == XmlTypeCode.None) {
                    // If cardinality includes zero, then return (None, Zero), else return (None, None).
                    return XmlQueryCardinality.Zero <= card ? Zero : None;
                }

                // Normalize sequences with these cardinalities: None, Zero, One

                if (card == XmlQueryCardinality.None) {
                    return None;
                }
                else if (card == XmlQueryCardinality.Zero) {
                    return Zero;
                }
                else if (card == XmlQueryCardinality.One) {
                    return prime;
                }

                return new SequenceType(prime, card);
            }
            /// <summary>
            /// Construct arrays of built-in types.
            /// </summary>
            static ItemType() {
            #if DEBUG
                Array arrEnum = Enum.GetValues(typeof(XmlTypeCode));
                Debug.Assert((XmlTypeCode) arrEnum.GetValue(arrEnum.Length - 1) == XmlTypeCode.DayTimeDuration,
                             "DayTimeDuration is no longer the last item in XmlTypeCode.  This code expects it to be.");
            #endif

                int typeCount = (int) XmlTypeCode.DayTimeDuration + 1;

                BuiltInItemTypes = new XmlQueryType[typeCount];
                BuiltInItemTypesStrict = new XmlQueryType[typeCount];

                for (int i = 0; i < typeCount; i++) {
                    XmlTypeCode typeCode = (XmlTypeCode)i;

                    switch ((XmlTypeCode) i) {
                        case XmlTypeCode.None:
                            BuiltInItemTypes[i] = ChoiceType.None;
                            BuiltInItemTypesStrict[i] = ChoiceType.None;
                            continue;

                        case XmlTypeCode.Item:
                        case XmlTypeCode.Node:
                            BuiltInItemTypes[i] = new ItemType(typeCode, XmlQualifiedNameTest.Wildcard, XmlSchemaComplexType.AnyType, false, false, false);
                            BuiltInItemTypesStrict[i] = BuiltInItemTypes[i];
                            break;

                        case XmlTypeCode.Document:
                        case XmlTypeCode.Element:
                        case XmlTypeCode.Namespace:
                        case XmlTypeCode.ProcessingInstruction:
                        case XmlTypeCode.Comment:
                        case XmlTypeCode.Text:
                            BuiltInItemTypes[i] = new ItemType(typeCode, XmlQualifiedNameTest.Wildcard, XmlSchemaComplexType.AnyType, false, false, true);
                            BuiltInItemTypesStrict[i] = BuiltInItemTypes[i];
                            break;

                        case XmlTypeCode.Attribute:
                            BuiltInItemTypes[i] = new ItemType(typeCode, XmlQualifiedNameTest.Wildcard, DatatypeImplementation.AnySimpleType, false, false, true);
                            BuiltInItemTypesStrict[i] = BuiltInItemTypes[i];
                            break;

                        case XmlTypeCode.AnyAtomicType:
                            BuiltInItemTypes[i] = new ItemType(typeCode, XmlQualifiedNameTest.Wildcard, DatatypeImplementation.AnyAtomicType, false, false, true);
                            BuiltInItemTypesStrict[i] = BuiltInItemTypes[i];
                            break;

                        case XmlTypeCode.UntypedAtomic:
                            // xdt:untypedAtomic is sealed, and therefore always strict
                            BuiltInItemTypes[i] = new ItemType(typeCode, XmlQualifiedNameTest.Wildcard, DatatypeImplementation.UntypedAtomicType, false, true, true);
                            BuiltInItemTypesStrict[i] = BuiltInItemTypes[i];
                            break;

                        default:
                            XmlSchemaType builtInType = XmlSchemaType.GetBuiltInSimpleType(typeCode);
                            BuiltInItemTypes[i] = new ItemType(typeCode, XmlQualifiedNameTest.Wildcard, builtInType, false, false, true);
                            BuiltInItemTypesStrict[i] = new ItemType(typeCode, XmlQualifiedNameTest.Wildcard, builtInType, false, true, true);
                            break;
                    }
                }

                UntypedDocument = new ItemType(XmlTypeCode.Document, XmlQualifiedNameTest.Wildcard, XmlSchemaComplexType.UntypedAnyType, false, false, true);
                UntypedElement = new ItemType(XmlTypeCode.Element, XmlQualifiedNameTest.Wildcard, XmlSchemaComplexType.UntypedAnyType, false, false, true);
                UntypedAttribute = new ItemType(XmlTypeCode.Attribute, XmlQualifiedNameTest.Wildcard, DatatypeImplementation.UntypedAtomicType, false, false, true);
                NodeNotRtf = new ItemType(XmlTypeCode.Node, XmlQualifiedNameTest.Wildcard, XmlSchemaComplexType.AnyType, false, false, true);

                SpecialBuiltInItemTypes = new XmlQueryType[4] { UntypedDocument, UntypedElement, UntypedAttribute, NodeNotRtf };
            }
 /// <summary>
 /// Compute a sequence of zero to some max cardinality.
 /// </summary>
 /// <param name="t">the type to sequence</param>
 /// <param name="c">the upper bound</param>
 /// <returns>the sequence of t from 0 to c</returns>
 public static XmlQueryType AtMost(XmlQueryType t, XmlQueryCardinality c) {
     return PrimeProduct(t, c.AtMost());
 }
 /// <summary>
 /// Private constructor.  Create methods should be used to create instances.
 /// </summary>
 private SequenceType(XmlQueryType prime, XmlQueryCardinality card) {
     this.prime = prime;
     this.card = card;
 }