Пример #1
0
 // also called by XPathPatternBuilder
 public static XmlNodeKindFlags AxisTypeMask(XmlNodeKindFlags inputTypeMask, XPathNodeType nodeType, XPathAxis xpathAxis)
 {
     return((XmlNodeKindFlags)(
                (int)inputTypeMask &
                (int)s_XPathNodeType2QilXmlNodeKind[(int)nodeType] & (int)s_XPathAxisMask[(int)xpathAxis]
                ));
 }
Пример #2
0
        public QilNode BuildMatcher(QilIterator it, IList <XslNode> actualArgs, QilNode otherwise)
        {
            QilNode result = otherwise;

            foreach (List <TemplateMatch> list in allMatches)
            {
                foreach (TemplateMatch match in list)
                {
                    XmlNodeKindFlags nodeKind = match.NodeKind;
                    QilName          qname    = match.QName;
                    QilNode          cond     = match.Condition;

                    if (cond != null)
                    {
                        // We have to clone, because the same pattern may be used
                        // in many different xsl:apply-templates/imports functions
                        cond = cond.DeepClone(f.BaseFactory);
                        cond = refReplacer.Replace(cond, match.Iterator, it);
                    }

                    if (nodeKind != 0)
                    {
                        XmlQueryType nodeType;
                        switch (nodeKind)
                        {
                        case XmlNodeKindFlags.Element: nodeType = T.Element;  break;

                        case XmlNodeKindFlags.Attribute: nodeType = T.Attribute;  break;

                        case XmlNodeKindFlags.Text: nodeType = T.Text;  break;

                        case XmlNodeKindFlags.Document: nodeType = T.Document;  break;

                        case XmlNodeKindFlags.Comment: nodeType = T.Comment;  break;

                        case XmlNodeKindFlags.PI: nodeType = T.PI;  break;

                        default: nodeType = null;  break;
                        }

                        Debug.Assert(nodeType != null, "Unexpected nodeKind: " + nodeKind);
                        QilNode typeNameCheck = f.IsType(it, nodeType);

                        if (qname != null)
                        {
                            typeNameCheck = f.And(typeNameCheck, f.Eq(f.NameOf(it), qname.ShallowClone(f.BaseFactory)));
                        }

                        cond = (cond == null) ? typeNameCheck : f.And(typeNameCheck, cond);
                    }

                    result = f.Conditional(cond,
                                           invkGen.GenerateInvoke(match.TemplateFunction, actualArgs),
                                           result
                                           );
                }
            }
            return(result);
        }
Пример #3
0
        QilNode BuildAxisFilter(QilNode qilAxis, XPathAxis xpathAxis, XPathNodeType nodeType, string name, string nsUri)
        {
            XmlNodeKindFlags original = qilAxis.XmlType.NodeKinds;
            XmlNodeKindFlags required = AxisTypeMask(original, nodeType, xpathAxis);

            QilIterator itr;

            if (required == 0)
            {
                return(f.Sequence());
            }
            else if (required == original)
            {
            }
            else
            {
                qilAxis         = f.Filter(itr = f.For(qilAxis), f.IsType(itr, T.NodeChoice(required)));
                qilAxis.XmlType = T.PrimeProduct(T.NodeChoice(required), qilAxis.XmlType.Cardinality);


                // Without code bellow IlGeneragion gives stack overflow exception for the following passage.
                //<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
                //    <xsl:template match="/">
                //        <xsl:value-of select="descendant::author/@id | comment()" />
                //    </xsl:template>
                //</xsl:stylesheet>

                // ToDo: remove this code when IlGen bug will be fixed.
                if (qilAxis.NodeType == QilNodeType.Filter)
                {
                    QilLoop filter = (QilLoop)qilAxis;
                    filter.Body = f.And(filter.Body,
                                        name != null && nsUri != null ? f.Eq(f.NameOf(itr), f.QName(name, nsUri))    :  // ns:bar || bar
                                        nsUri != null                  ? f.Eq(f.NamespaceUriOf(itr), f.String(nsUri)) : // ns:*
                                        name != null                  ? f.Eq(f.LocalNameOf(itr), f.String(name))     :  // *:foo
                                        /*name  == nsUri == null*/ f.True()                                             // *
                                        );
                    return(filter);
                }
            }

            return(f.Filter(itr = f.For(qilAxis),
                            name != null && nsUri != null ? f.Eq(f.NameOf(itr), f.QName(name, nsUri))    :  // ns:bar || bar
                            nsUri != null                  ? f.Eq(f.NamespaceUriOf(itr), f.String(nsUri)) : // ns:*
                            name != null                  ? f.Eq(f.LocalNameOf(itr), f.String(name))     :  // *:foo
                            /*name  == nsUri == null*/ f.True()                                             // *
                            ));
        }
            public QilNode GetPosition()
            {
                QilLoop          clone     = (QilLoop)cloner.Clone(baseContext);
                XmlNodeKindFlags nodeKinds = baseContext.XmlType.NodeKinds;

                // baseContext either always returns attributes (attribute::), or never returns attributes or namespaces (child::)
                if (nodeKinds == XmlNodeKindFlags.Attribute)
                {
                    QilIterator i = f.For(f.Parent(GetCurrent()));
                    clone.Variable.Binding = f.Content(i);
                    clone.Body             = f.And(clone.Body, f.Before(clone.Variable, GetCurrent()));
                    clone = f.BaseFactory.Loop(i, clone);
                }
                else
                {
                    Debug.Assert((nodeKinds & (XmlNodeKindFlags.Attribute | XmlNodeKindFlags.Namespace)) == XmlNodeKindFlags.None);
                    clone.Variable.Binding = f.PrecedingSibling(GetCurrent());
                }
                return(f.Add(f.Double(1), f.XsltConvert(f.Length(clone), T.DoubleX)));
            }
        QilNode BuildAxisFilter(QilNode qilAxis, XPathAxis xpathAxis, XPathNodeType nodeType, string name, string nsUri)
        {
            XmlNodeKindFlags original = qilAxis.XmlType.NodeKinds;
            XmlNodeKindFlags required = AxisTypeMask(original, nodeType, xpathAxis);

            QilIterator itr;

            if (required == 0)
            {
                return(f.Sequence());
            }
            else if (required == original)
            {
            }
            else
            {
                qilAxis         = f.Filter(itr = f.For(qilAxis), f.IsType(itr, T.NodeChoice(required)));
                qilAxis.XmlType = T.PrimeProduct(T.NodeChoice(required), qilAxis.XmlType.Cardinality);



                if (qilAxis.NodeType == QilNodeType.Filter)
                {
                    QilLoop filter = (QilLoop)qilAxis;
                    filter.Body = f.And(filter.Body,
                                        name != null && nsUri != null ? f.Eq(f.NameOf(itr), f.QName(name, nsUri))    :  // ns:bar || bar
                                        nsUri != null                  ? f.Eq(f.NamespaceUriOf(itr), f.String(nsUri)) : // ns:*
                                        name != null                  ? f.Eq(f.LocalNameOf(itr), f.String(name))     :  // *:foo
                                        /*name  == nsUri == null*/ f.True()                                             // *
                                        );
                    return(filter);
                }
            }

            return(f.Filter(itr = f.For(qilAxis),
                            name != null && nsUri != null ? f.Eq(f.NameOf(itr), f.QName(name, nsUri))    :  // ns:bar || bar
                            nsUri != null                  ? f.Eq(f.NamespaceUriOf(itr), f.String(nsUri)) : // ns:*
                            name != null                  ? f.Eq(f.LocalNameOf(itr), f.String(name))     :  // *:foo
                            /*name  == nsUri == null*/ f.True()                                             // *
                            ));
        }
Пример #6
0
        private static QilLoop BuildAxisFilter(QilPatternFactory f, QilIterator itr, XPathAxis xpathAxis, XPathNodeType nodeType, string name, string nsUri)
        {
            QilNode nameTest = (
                name != null && nsUri != null ? f.Eq(f.NameOf(itr), f.QName(name, nsUri)) :                   // ns:bar || bar
                nsUri != null ? f.Eq(f.NamespaceUriOf(itr), f.String(nsUri)) :                                // ns:*
                name != null ? f.Eq(f.LocalNameOf(itr), f.String(name)) :                                     // *:foo
                                                                          /*name  == nsUri == null*/ f.True() // *
                );

            XmlNodeKindFlags intersection = XPathBuilder.AxisTypeMask(itr.XmlType.NodeKinds, nodeType, xpathAxis);

            QilNode typeTest = (
                intersection == 0 ? f.False() :                    // input & required doesn't intersect
                intersection == itr.XmlType.NodeKinds ? f.True() : // input is subset of required
                                                                    /*else*/ f.IsType(itr, T.NodeChoice(intersection))
                );

            QilLoop filter = f.BaseFactory.Filter(itr, f.And(typeTest, nameTest));

            filter.XmlType = T.PrimeProduct(T.NodeChoice(intersection), filter.XmlType.Cardinality);

            return(filter);
        }
Пример #7
0
        private void NipOffTypeNameCheck()
        {
            QilBinary[] leftPath = new QilBinary[4]; // Circular buffer for last 4 And nodes
            int         idx      = -1;               // Index of last element in leftPath
            QilNode     node     = _condition !;     // Walker through left path of the tree

            _nodeKind = XmlNodeKindFlags.None;
            _qname    = null;

            while (node.NodeType == QilNodeType.And)
            {
                node = (leftPath[++idx & 3] = (QilBinary)node).Left;
            }

            // Recognizing (IsType RefTo LiteralType)
            if (!(node.NodeType == QilNodeType.IsType))
            {
                return;
            }

            QilBinary isType = (QilBinary)node;

            if (!(isType.Left == _iterator && isType.Right.NodeType == QilNodeType.LiteralType))
            {
                return;
            }

            XmlNodeKindFlags nodeKinds = isType.Right.XmlType !.NodeKinds;

            if (!Bits.ExactlyOne((uint)nodeKinds))
            {
                return;
            }

            // Recognized pattern A, check for B
            QilNode x = isType;

            _nodeKind = nodeKinds;
            QilBinary lastAnd = leftPath[idx & 3];

            if (lastAnd != null && lastAnd.Right.NodeType == QilNodeType.Eq)
            {
                QilBinary eq = (QilBinary)lastAnd.Right;

                // Recognizing (Eq (NameOf RefTo) LiteralQName)
                if (eq.Left.NodeType == QilNodeType.NameOf &&
                    ((QilUnary)eq.Left).Child == _iterator && eq.Right.NodeType == QilNodeType.LiteralQName
                    )
                {
                    // Recognized pattern B
                    x      = lastAnd;
                    _qname = (QilName?)((QilLiteral)eq.Right).Value;
                    idx--;
                }
            }

            // Nip $x off the condition
            QilBinary and1 = leftPath[idx & 3];
            QilBinary and2 = leftPath[--idx & 3];

            if (and2 != null)
            {
                and2.Left = and1.Right;
            }
            else if (and1 != null)
            {
                _condition = and1.Right;
            }
            else
            {
                _condition = null;
            }
        }
            /// <summary>
            /// Private constructor.  Create methods should be used to create instances.
            /// </summary>
            private ChoiceType(List<XmlQueryType> members) {
                Debug.Assert(members != null && members.Count != 1, "ChoiceType must contain a list with 0 or >1 types.");

                this.members = members;

                // Compute supertype of all member types
                for (int i = 0; i < members.Count; i++) {
                    XmlQueryType t = members[i];
                    Debug.Assert(t.Cardinality == XmlQueryCardinality.One, "ChoiceType member types must be prime types.");

                    // Summarize the union of member types as a single type
                    if (this.code == XmlTypeCode.None) {
                        // None combined with member type is the member type
                        this.code = t.TypeCode;
                        this.schemaType = t.SchemaType;
                    }
                    else if (IsNode && t.IsNode) {
                        // Node combined with node is node
                        if (this.code == t.TypeCode) {
                            // Element or attribute combined with element or attribute can be summarized as element(*, XmlSchemaComplexType.AnyType) or attribute(*, DatatypeImplementation.AnySimpleType)
                            if (this.code == XmlTypeCode.Element)
                                this.schemaType = XmlSchemaComplexType.AnyType;
                            else if (this.code == XmlTypeCode.Attribute)
                                this.schemaType = DatatypeImplementation.AnySimpleType;
                        }
                        else {
                            this.code = XmlTypeCode.Node;
                            this.schemaType = null;
                        }
                    }
                    else if (IsAtomicValue && t.IsAtomicValue) {
                        // Atomic value combined with atomic value is atomic value
                        this.code = XmlTypeCode.AnyAtomicType;
                        this.schemaType = DatatypeImplementation.AnyAtomicType;
                    }
                    else {
                        // Else we'll summarize types as Item
                        this.code = XmlTypeCode.Item;
                        this.schemaType = null;
                    }

                    // Always track union of node kinds
                    this.nodeKinds |= t.NodeKinds;
                }
            }
            /// <summary>
            /// Create choice between node kinds.
            /// </summary>
            public static XmlQueryType Create(XmlNodeKindFlags nodeKinds) {
                List<XmlQueryType> members;

                // If exactly one kind is set, then create singleton ItemType
                if (Bits.ExactlyOne((uint) nodeKinds))
                    return ItemType.Create(NodeKindToTypeCode[Bits.LeastPosition((uint) nodeKinds)], false);

                members = new List<XmlQueryType>();
                while (nodeKinds != XmlNodeKindFlags.None) {
                    members.Add(ItemType.Create(NodeKindToTypeCode[Bits.LeastPosition((uint) nodeKinds)], false));

                    nodeKinds = (XmlNodeKindFlags) Bits.ClearLeast((uint) nodeKinds);
                }

                return Create(members);
            }
            /// <summary>
            /// Private constructor.  Create methods should be used to create instances.
            /// </summary>
            private ItemType(XmlTypeCode code, XmlQualifiedNameTest nameTest, XmlSchemaType schemaType, bool isNillable, bool isStrict, bool isNotRtf) {
                Debug.Assert(nameTest != null, "nameTest cannot be null");
                Debug.Assert(schemaType != null, "schemaType cannot be null");
                this.code = code;
                this.nameTest = nameTest;
                this.schemaType = schemaType;
                this.isNillable = isNillable;
                this.isStrict = isStrict;
                this.isNotRtf = isNotRtf;

                Debug.Assert(!IsAtomicValue || schemaType.Datatype.Variety == XmlSchemaDatatypeVariety.Atomic);

                switch (code) {
                    case XmlTypeCode.Item: this.nodeKinds = XmlNodeKindFlags.Any; break;
                    case XmlTypeCode.Node: this.nodeKinds = XmlNodeKindFlags.Any; break;
                    case XmlTypeCode.Document: this.nodeKinds = XmlNodeKindFlags.Document; break;
                    case XmlTypeCode.Element: this.nodeKinds = XmlNodeKindFlags.Element; break;
                    case XmlTypeCode.Attribute: this.nodeKinds = XmlNodeKindFlags.Attribute; break;
                    case XmlTypeCode.Namespace: this.nodeKinds = XmlNodeKindFlags.Namespace; break;
                    case XmlTypeCode.ProcessingInstruction: this.nodeKinds = XmlNodeKindFlags.PI; break;
                    case XmlTypeCode.Comment: this.nodeKinds = XmlNodeKindFlags.Comment; break;
                    case XmlTypeCode.Text: this.nodeKinds = XmlNodeKindFlags.Text; break;
                    default: this.nodeKinds = XmlNodeKindFlags.None; break;
                }
            }
 /// <summary>
 /// Create a Node XmlQueryType which is the choice between several different node kinds.
 /// </summary>
 /// <param name="kinds">the node kinds which will make up the choice</param>
 /// <returns>the node type</returns>
 public static XmlQueryType NodeChoice(XmlNodeKindFlags kinds) {
     return ChoiceType.Create(kinds);
 }
Пример #12
0
 /// <summary>
 /// Return true if more than one node type is set.
 /// </summary>
 private static bool IsNodeTypeUnion(XmlNodeKindFlags xmlTypes)
 {
     return ((int)xmlTypes & ((int)xmlTypes - 1)) != 0;
 }
Пример #13
0
        /// <summary>
        /// Load an XmlNavigatorFilter that matches only the specified name and types onto the stack.
        /// </summary>
        private void LoadSelectFilter(XmlNodeKindFlags xmlTypes, QilName ndName)
        {
            if (ndName != null)
            {
                // Push NameFilter
                Debug.Assert(xmlTypes == XmlNodeKindFlags.Element);
                _helper.CallGetNameFilter(_helper.StaticData.DeclareNameFilter(ndName.LocalName, ndName.NamespaceUri));
            }
            else
            {
                // Either type cannot be a union, or else it must be >= union of all Content types
                bool isXmlTypeUnion = IsNodeTypeUnion(xmlTypes);
                Debug.Assert(!isXmlTypeUnion || (xmlTypes & XmlNodeKindFlags.Content) == XmlNodeKindFlags.Content);

                if (isXmlTypeUnion)
                {
                    if ((xmlTypes & XmlNodeKindFlags.Attribute) != 0)
                    {
                        // Union includes attributes, so allow all node kinds
                        _helper.CallGetTypeFilter(XPathNodeType.All);
                    }
                    else
                    {
                        // Filter attributes
                        _helper.CallGetTypeFilter(XPathNodeType.Attribute);
                    }
                }
                else
                {
                    // Filter nodes of all but one type
                    _helper.CallGetTypeFilter(QilXmlToXPathNodeType(xmlTypes));
                }
            }
        }
Пример #14
0
 /// <summary>
 /// Map the XmlNodeKindFlags enumeration into the XPathNodeType enumeration.
 /// </summary>
 private XPathNodeType QilXmlToXPathNodeType(XmlNodeKindFlags xmlTypes)
 {
     switch (xmlTypes)
     {
         case XmlNodeKindFlags.Element: return XPathNodeType.Element;
         case XmlNodeKindFlags.Attribute: return XPathNodeType.Attribute;
         case XmlNodeKindFlags.Text: return XPathNodeType.Text;
         case XmlNodeKindFlags.Comment: return XPathNodeType.Comment;
     }
     Debug.Assert(xmlTypes == XmlNodeKindFlags.PI);
     return XPathNodeType.ProcessingInstruction;
 }
Пример #15
0
        /// <summary>
        /// Generate boiler-plate code to create an Xml iterator that controls a nested iterator.
        /// </summary>
        /// <remarks>
        ///     Iterator iter;
        ///     iter.Create(filter [, orSelf]);
        ///         ...nested iterator...
        ///     navInput = nestedNested;
        ///     goto LabelCall;
        /// LabelNext:
        ///     navInput = null;
        /// LabelCall:
        ///     switch (iter.MoveNext(navInput)) {
        ///         case IteratorState.NoMoreNodes: goto LabelNextCtxt;
        ///         case IteratorState.NextInputNode: goto LabelNextNested;
        ///     }
        /// </remarks>
        private void CreateContainerIterator(QilUnary ndDod, string iterName, Type iterType, MethodInfo methCreate, MethodInfo methNext,
                                                   XmlNodeKindFlags kinds, QilName ndName, TriState orSelf)
        {
            // Iterator iter;
            LocalBuilder locIter = _helper.DeclareLocal(iterName, iterType);
            Label lblOnEndNested;
            QilLoop ndLoop = (QilLoop)ndDod.Child;
            Debug.Assert(ndDod.NodeType == QilNodeType.DocOrderDistinct && ndLoop != null);

            // iter.Create(filter [, orSelf]);
            _helper.Emit(OpCodes.Ldloca, locIter);
            LoadSelectFilter(kinds, ndName);
            if (orSelf != TriState.Unknown)
                _helper.LoadBoolean(orSelf == TriState.True);
            _helper.Call(methCreate);

            // Generate nested iterator (branch to lblOnEndNested when iteration is complete)
            lblOnEndNested = _helper.DefineLabel();
            StartNestedIterator(ndLoop, lblOnEndNested);
            StartBinding(ndLoop.Variable);
            EndBinding(ndLoop.Variable);
            EndNestedIterator(ndLoop.Variable);
            _iterCurr.Storage = _iterNested.Storage;

            GenerateContainerIterator(ndDod, locIter, lblOnEndNested, methNext, typeof(XPathNavigator));
        }
Пример #16
0
        /// <summary>
        /// Generate boiler-plate code to create an Xml iterator that uses an XmlNavigatorFilter to filter items.
        /// </summary>
        /// <remarks>
        ///     Iterator iter;
        ///     iter.Create(navCtxt, filter [, orSelf] [, navEnd]);
        /// LabelNext:
        ///     if (!iter.MoveNext())
        ///         goto LabelNextCtxt;
        /// </remarks>
        private void CreateFilteredIterator(QilNode ndCtxt, string iterName, Type iterType, MethodInfo methCreate, MethodInfo methNext,
                                                XmlNodeKindFlags kinds, QilName ndName, TriState orSelf, QilNode ndEnd)
        {
            // Iterator iter;
            LocalBuilder locIter = _helper.DeclareLocal(iterName, iterType);

            // iter.Create(navCtxt, filter [, orSelf], [, navEnd]);
            _helper.Emit(OpCodes.Ldloca, locIter);
            NestedVisitEnsureStack(ndCtxt);
            LoadSelectFilter(kinds, ndName);
            if (orSelf != TriState.Unknown)
                _helper.LoadBoolean(orSelf == TriState.True);
            if (ndEnd != null)
                NestedVisitEnsureStack(ndEnd);
            _helper.Call(methCreate);

            GenerateSimpleIterator(typeof(XPathNavigator), locIter, methNext);
        }