Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / whidbey / NetFxQFE / ndp / fx / src / XmlUtils / System / Xml / Xsl / QIL / QilTypeChecker.cs / 1 / QilTypeChecker.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //----------------------------------------------------------------------------- using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Xml.Schema; using System.Xml.XPath; using System.Xml.Xsl; using System.Xml.Xsl.Runtime; namespace System.Xml.Xsl.Qil { ////// This class performs two functions: /// 1. Infer XmlQueryType of Qil nodes (constant, from arguments, etc) /// 2. Validate the arguments of Qil nodes if DEBUG is defined /// internal class QilTypeChecker { public QilTypeChecker() { } public XmlQueryType Check(QilNode n) { #region AUTOGENERATED switch (n.NodeType) { case QilNodeType.QilExpression: return CheckQilExpression((QilExpression)n); case QilNodeType.FunctionList: return CheckFunctionList((QilList)n); case QilNodeType.GlobalVariableList: return CheckGlobalVariableList((QilList)n); case QilNodeType.GlobalParameterList: return CheckGlobalParameterList((QilList)n); case QilNodeType.ActualParameterList: return CheckActualParameterList((QilList)n); case QilNodeType.FormalParameterList: return CheckFormalParameterList((QilList)n); case QilNodeType.SortKeyList: return CheckSortKeyList((QilList)n); case QilNodeType.BranchList: return CheckBranchList((QilList)n); case QilNodeType.OptimizeBarrier: return CheckOptimizeBarrier((QilUnary)n); case QilNodeType.Unknown: return CheckUnknown(n); case QilNodeType.DataSource: return CheckDataSource((QilDataSource)n); case QilNodeType.Nop: return CheckNop((QilUnary)n); case QilNodeType.Error: return CheckError((QilUnary)n); case QilNodeType.Warning: return CheckWarning((QilUnary)n); case QilNodeType.For: return CheckFor((QilIterator)n); case QilNodeType.Let: return CheckLet((QilIterator)n); case QilNodeType.Parameter: return CheckParameter((QilParameter)n); case QilNodeType.PositionOf: return CheckPositionOf((QilUnary)n); case QilNodeType.True: return CheckTrue(n); case QilNodeType.False: return CheckFalse(n); case QilNodeType.LiteralString: return CheckLiteralString((QilLiteral)n); case QilNodeType.LiteralInt32: return CheckLiteralInt32((QilLiteral)n); case QilNodeType.LiteralInt64: return CheckLiteralInt64((QilLiteral)n); case QilNodeType.LiteralDouble: return CheckLiteralDouble((QilLiteral)n); case QilNodeType.LiteralDecimal: return CheckLiteralDecimal((QilLiteral)n); case QilNodeType.LiteralQName: return CheckLiteralQName((QilName)n); case QilNodeType.LiteralType: return CheckLiteralType((QilLiteral)n); case QilNodeType.LiteralObject: return CheckLiteralObject((QilLiteral)n); case QilNodeType.And: return CheckAnd((QilBinary)n); case QilNodeType.Or: return CheckOr((QilBinary)n); case QilNodeType.Not: return CheckNot((QilUnary)n); case QilNodeType.Conditional: return CheckConditional((QilTernary)n); case QilNodeType.Choice: return CheckChoice((QilChoice)n); case QilNodeType.Length: return CheckLength((QilUnary)n); case QilNodeType.Sequence: return CheckSequence((QilList)n); case QilNodeType.Union: return CheckUnion((QilBinary)n); case QilNodeType.Intersection: return CheckIntersection((QilBinary)n); case QilNodeType.Difference: return CheckDifference((QilBinary)n); case QilNodeType.Average: return CheckAverage((QilUnary)n); case QilNodeType.Sum: return CheckSum((QilUnary)n); case QilNodeType.Minimum: return CheckMinimum((QilUnary)n); case QilNodeType.Maximum: return CheckMaximum((QilUnary)n); case QilNodeType.Negate: return CheckNegate((QilUnary)n); case QilNodeType.Add: return CheckAdd((QilBinary)n); case QilNodeType.Subtract: return CheckSubtract((QilBinary)n); case QilNodeType.Multiply: return CheckMultiply((QilBinary)n); case QilNodeType.Divide: return CheckDivide((QilBinary)n); case QilNodeType.Modulo: return CheckModulo((QilBinary)n); case QilNodeType.StrLength: return CheckStrLength((QilUnary)n); case QilNodeType.StrConcat: return CheckStrConcat((QilStrConcat)n); case QilNodeType.StrParseQName: return CheckStrParseQName((QilBinary)n); case QilNodeType.Ne: return CheckNe((QilBinary)n); case QilNodeType.Eq: return CheckEq((QilBinary)n); case QilNodeType.Gt: return CheckGt((QilBinary)n); case QilNodeType.Ge: return CheckGe((QilBinary)n); case QilNodeType.Lt: return CheckLt((QilBinary)n); case QilNodeType.Le: return CheckLe((QilBinary)n); case QilNodeType.Is: return CheckIs((QilBinary)n); case QilNodeType.After: return CheckAfter((QilBinary)n); case QilNodeType.Before: return CheckBefore((QilBinary)n); case QilNodeType.Loop: return CheckLoop((QilLoop)n); case QilNodeType.Filter: return CheckFilter((QilLoop)n); case QilNodeType.Sort: return CheckSort((QilLoop)n); case QilNodeType.SortKey: return CheckSortKey((QilSortKey)n); case QilNodeType.DocOrderDistinct: return CheckDocOrderDistinct((QilUnary)n); case QilNodeType.Function: return CheckFunction((QilFunction)n); case QilNodeType.Invoke: return CheckInvoke((QilInvoke)n); case QilNodeType.Content: return CheckContent((QilUnary)n); case QilNodeType.Attribute: return CheckAttribute((QilBinary)n); case QilNodeType.Parent: return CheckParent((QilUnary)n); case QilNodeType.Root: return CheckRoot((QilUnary)n); case QilNodeType.XmlContext: return CheckXmlContext(n); case QilNodeType.Descendant: return CheckDescendant((QilUnary)n); case QilNodeType.DescendantOrSelf: return CheckDescendantOrSelf((QilUnary)n); case QilNodeType.Ancestor: return CheckAncestor((QilUnary)n); case QilNodeType.AncestorOrSelf: return CheckAncestorOrSelf((QilUnary)n); case QilNodeType.Preceding: return CheckPreceding((QilUnary)n); case QilNodeType.FollowingSibling: return CheckFollowingSibling((QilUnary)n); case QilNodeType.PrecedingSibling: return CheckPrecedingSibling((QilUnary)n); case QilNodeType.NodeRange: return CheckNodeRange((QilBinary)n); case QilNodeType.Deref: return CheckDeref((QilBinary)n); case QilNodeType.ElementCtor: return CheckElementCtor((QilBinary)n); case QilNodeType.AttributeCtor: return CheckAttributeCtor((QilBinary)n); case QilNodeType.CommentCtor: return CheckCommentCtor((QilUnary)n); case QilNodeType.PICtor: return CheckPICtor((QilBinary)n); case QilNodeType.TextCtor: return CheckTextCtor((QilUnary)n); case QilNodeType.RawTextCtor: return CheckRawTextCtor((QilUnary)n); case QilNodeType.DocumentCtor: return CheckDocumentCtor((QilUnary)n); case QilNodeType.NamespaceDecl: return CheckNamespaceDecl((QilBinary)n); case QilNodeType.RtfCtor: return CheckRtfCtor((QilBinary)n); case QilNodeType.NameOf: return CheckNameOf((QilUnary)n); case QilNodeType.LocalNameOf: return CheckLocalNameOf((QilUnary)n); case QilNodeType.NamespaceUriOf: return CheckNamespaceUriOf((QilUnary)n); case QilNodeType.PrefixOf: return CheckPrefixOf((QilUnary)n); case QilNodeType.TypeAssert: return CheckTypeAssert((QilTargetType)n); case QilNodeType.IsType: return CheckIsType((QilTargetType)n); case QilNodeType.IsEmpty: return CheckIsEmpty((QilUnary)n); case QilNodeType.XPathNodeValue: return CheckXPathNodeValue((QilUnary)n); case QilNodeType.XPathFollowing: return CheckXPathFollowing((QilUnary)n); case QilNodeType.XPathPreceding: return CheckXPathPreceding((QilUnary)n); case QilNodeType.XPathNamespace: return CheckXPathNamespace((QilUnary)n); case QilNodeType.XsltGenerateId: return CheckXsltGenerateId((QilUnary)n); case QilNodeType.XsltInvokeLateBound: return CheckXsltInvokeLateBound((QilInvokeLateBound)n); case QilNodeType.XsltInvokeEarlyBound: return CheckXsltInvokeEarlyBound((QilInvokeEarlyBound)n); case QilNodeType.XsltCopy: return CheckXsltCopy((QilBinary)n); case QilNodeType.XsltCopyOf: return CheckXsltCopyOf((QilUnary)n); case QilNodeType.XsltConvert: return CheckXsltConvert((QilTargetType)n); default: return CheckUnknown(n); } #endregion } #region meta //----------------------------------------------- // meta //----------------------------------------------- public XmlQueryType CheckQilExpression(QilExpression node) { Check(node[0].NodeType == QilNodeType.False || node[0].NodeType == QilNodeType.True, node, "IsDebug must either be True or False"); CheckLiteralValue(node[1], typeof(XmlWriterSettings)); CheckLiteralValue(node[2], typeof(IList)); CheckClassAndNodeType(node[3], typeof(QilList), QilNodeType.GlobalParameterList); CheckClassAndNodeType(node[4], typeof(QilList), QilNodeType.GlobalVariableList); CheckLiteralValue(node[5], typeof(IList )); CheckClassAndNodeType(node[6], typeof(QilList), QilNodeType.FunctionList); return XmlQueryTypeFactory.ItemS; } public XmlQueryType CheckFunctionList(QilList node) { foreach (QilNode child in node) CheckClassAndNodeType(child, typeof(QilFunction), QilNodeType.Function); return node.XmlType; } public XmlQueryType CheckGlobalVariableList(QilList node) { foreach (QilNode child in node) CheckClassAndNodeType(child, typeof(QilIterator), QilNodeType.Let); return node.XmlType; } public XmlQueryType CheckGlobalParameterList(QilList node) { foreach (QilNode child in node) CheckClassAndNodeType(child, typeof(QilParameter), QilNodeType.Parameter); return node.XmlType; } public XmlQueryType CheckActualParameterList(QilList node) { return node.XmlType; } public XmlQueryType CheckFormalParameterList(QilList node) { foreach (QilNode child in node) CheckClassAndNodeType(child, typeof(QilParameter), QilNodeType.Parameter); return node.XmlType; } public XmlQueryType CheckSortKeyList(QilList node) { foreach (QilNode child in node) CheckClassAndNodeType(child, typeof(QilSortKey), QilNodeType.SortKey); return node.XmlType; } public XmlQueryType CheckBranchList(QilList node) { return node.XmlType; } public XmlQueryType CheckOptimizeBarrier(QilUnary node) { return node.Child.XmlType; } public XmlQueryType CheckNoDefaultValue(QilNode node) { return XmlQueryTypeFactory.None; } public XmlQueryType CheckUnknown(QilNode node) { return node.XmlType; } #endregion // meta #region specials //----------------------------------------------- // specials //----------------------------------------------- public XmlQueryType CheckDataSource(QilDataSource node) { CheckXmlType(node.Name, XmlQueryTypeFactory.StringX); CheckXmlType(node.BaseUri, XmlQueryTypeFactory.StringX); return XmlQueryTypeFactory.NodeNotRtfQ; } public XmlQueryType CheckNop(QilUnary node) { return node.Child.XmlType; } public XmlQueryType CheckError(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.StringX); return XmlQueryTypeFactory.None; } public XmlQueryType CheckWarning(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.StringX); return XmlQueryTypeFactory.Empty; } #endregion // specials #region variables //----------------------------------------------- // variables //----------------------------------------------- public XmlQueryType CheckFor(QilIterator node) { return node.Binding.XmlType.Prime; } public XmlQueryType CheckLet(QilIterator node) { return node.Binding.XmlType; } public XmlQueryType CheckParameter(QilParameter node) { Check(node.Binding == null || node.Binding.XmlType.IsSubtypeOf(node.XmlType), node, "Parameter binding's xml type must be a subtype of the parameter's type"); return node.XmlType; } public XmlQueryType CheckPositionOf(QilUnary node) { return XmlQueryTypeFactory.IntX; } #endregion // variables #region literals //----------------------------------------------- // literals //----------------------------------------------- public XmlQueryType CheckTrue(QilNode node) { return XmlQueryTypeFactory.BooleanX; } public XmlQueryType CheckFalse(QilNode node) { return XmlQueryTypeFactory.BooleanX; } public XmlQueryType CheckLiteralString(QilLiteral node) { CheckLiteralValue(node, typeof(string)); return XmlQueryTypeFactory.StringX; } public XmlQueryType CheckLiteralInt32(QilLiteral node) { CheckLiteralValue(node, typeof(int)); return XmlQueryTypeFactory.IntX; } public XmlQueryType CheckLiteralInt64(QilLiteral node) { CheckLiteralValue(node, typeof(long)); return XmlQueryTypeFactory.IntegerX; } public XmlQueryType CheckLiteralDouble(QilLiteral node) { CheckLiteralValue(node, typeof(double)); return XmlQueryTypeFactory.DoubleX; } public XmlQueryType CheckLiteralDecimal(QilLiteral node) { CheckLiteralValue(node, typeof(decimal)); return XmlQueryTypeFactory.DecimalX; } public XmlQueryType CheckLiteralQName(QilName node) { CheckLiteralValue(node, typeof(QilName)); // return XmlQueryTypeFactory.QNameX; } public XmlQueryType CheckLiteralType(QilLiteral node) { CheckLiteralValue(node, typeof(XmlQueryType)); return (XmlQueryType) node; } public XmlQueryType CheckLiteralObject(QilLiteral node) { Check(node.Value != null, node, "Literal value is null"); return XmlQueryTypeFactory.ItemS; } #endregion // literals #region boolean operators //----------------------------------------------- // boolean operators //----------------------------------------------- public XmlQueryType CheckAnd(QilBinary node) { CheckXmlType(node.Left, XmlQueryTypeFactory.BooleanX); CheckXmlType(node.Right, XmlQueryTypeFactory.BooleanX); return XmlQueryTypeFactory.BooleanX; } public XmlQueryType CheckOr(QilBinary node) { return CheckAnd(node); } public XmlQueryType CheckNot(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.BooleanX); return XmlQueryTypeFactory.BooleanX; } #endregion // boolean operators #region choice //----------------------------------------------- // choice //----------------------------------------------- public XmlQueryType CheckConditional(QilTernary node) { CheckXmlType(node.Left, XmlQueryTypeFactory.BooleanX); return XmlQueryTypeFactory.Choice(node.Center.XmlType, node.Right.XmlType); } public XmlQueryType CheckChoice(QilChoice node) { CheckXmlType(node.Expression, XmlQueryTypeFactory.IntX); CheckClassAndNodeType(node.Branches, typeof(QilList), QilNodeType.BranchList); Check(node.Branches.Count > 0, node, "Choice must have at least one branch"); return node.Branches.XmlType; } #endregion // choice #region collection operators //----------------------------------------------- // collection operators //----------------------------------------------- public XmlQueryType CheckLength(QilUnary node) { return XmlQueryTypeFactory.IntX; } public XmlQueryType CheckSequence(QilList node) { return node.XmlType; } public XmlQueryType CheckUnion(QilBinary node) { CheckXmlType(node.Left, XmlQueryTypeFactory.NodeNotRtfS); CheckXmlType(node.Right, XmlQueryTypeFactory.NodeNotRtfS); return DistinctType(XmlQueryTypeFactory.Sequence(node.Left.XmlType, node.Right.XmlType)); } public XmlQueryType CheckIntersection(QilBinary node) { return CheckUnion(node); } public XmlQueryType CheckDifference(QilBinary node) { CheckXmlType(node.Left, XmlQueryTypeFactory.NodeNotRtfS); CheckXmlType(node.Right, XmlQueryTypeFactory.NodeNotRtfS); return XmlQueryTypeFactory.AtMost(node.Left.XmlType, node.Left.XmlType.Cardinality); } public XmlQueryType CheckAverage(QilUnary node) { XmlQueryType xmlType = node.Child.XmlType; CheckNumericXS(node.Child); return XmlQueryTypeFactory.PrimeProduct(xmlType, xmlType.MaybeEmpty ? XmlQueryCardinality.ZeroOrOne : XmlQueryCardinality.One); } public XmlQueryType CheckSum(QilUnary node) { return CheckAverage(node); } public XmlQueryType CheckMinimum(QilUnary node) { return CheckAverage(node); } public XmlQueryType CheckMaximum(QilUnary node) { return CheckAverage(node); } #endregion // collection operators #region arithmetic operators //----------------------------------------------- // arithmetic operators //----------------------------------------------- public XmlQueryType CheckNegate(QilUnary node) { CheckNumericX(node.Child); return node.Child.XmlType; } public XmlQueryType CheckAdd(QilBinary node) { CheckNumericX(node.Left); CheckNumericX(node.Right); CheckNotDisjoint(node); return node.Left.XmlType.TypeCode == XmlTypeCode.None ? node.Right.XmlType : node.Left.XmlType; } public XmlQueryType CheckSubtract(QilBinary node) { return CheckAdd(node); } public XmlQueryType CheckMultiply(QilBinary node) { return CheckAdd(node); } public XmlQueryType CheckDivide(QilBinary node) { return CheckAdd(node); } public XmlQueryType CheckModulo(QilBinary node) { return CheckAdd(node); } #endregion // arithmetic operators #region string operators //----------------------------------------------- // string operators //----------------------------------------------- public XmlQueryType CheckStrLength(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.StringX); return XmlQueryTypeFactory.IntX; } public XmlQueryType CheckStrConcat(QilStrConcat node) { CheckXmlType(node.Delimiter, XmlQueryTypeFactory.StringX); CheckXmlType(node.Values, XmlQueryTypeFactory.StringXS); return XmlQueryTypeFactory.StringX; } public XmlQueryType CheckStrParseQName(QilBinary node) { CheckXmlType(node.Left, XmlQueryTypeFactory.StringX); Check(node.Right.XmlType.IsSubtypeOf(XmlQueryTypeFactory.StringX) || node.Right.XmlType.IsSubtypeOf(XmlQueryTypeFactory.NamespaceS), node, "StrParseQName must take either a string or a list of namespace as its second argument"); return XmlQueryTypeFactory.QNameX; } #endregion // string operators #region value comparison operators //----------------------------------------------- // value comparison operators //----------------------------------------------- public XmlQueryType CheckNe(QilBinary node) { CheckAtomicX(node.Left); CheckAtomicX(node.Right); CheckNotDisjoint(node); return XmlQueryTypeFactory.BooleanX; } public XmlQueryType CheckEq(QilBinary node) { return CheckNe(node); } public XmlQueryType CheckGt(QilBinary node) { return CheckNe(node); } public XmlQueryType CheckGe(QilBinary node) { return CheckNe(node); } public XmlQueryType CheckLt(QilBinary node) { return CheckNe(node); } public XmlQueryType CheckLe(QilBinary node) { return CheckNe(node); } #endregion // value comparison operators #region node comparison operators //----------------------------------------------- // node comparison operators //----------------------------------------------- public XmlQueryType CheckIs(QilBinary node) { CheckXmlType(node.Left, XmlQueryTypeFactory.NodeNotRtf); CheckXmlType(node.Right, XmlQueryTypeFactory.NodeNotRtf); return XmlQueryTypeFactory.BooleanX; } public XmlQueryType CheckAfter(QilBinary node) { return CheckIs(node); } public XmlQueryType CheckBefore(QilBinary node) { return CheckIs(node); } #endregion // node comparison operators #region loops //----------------------------------------------- // 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 if (bodyType.IsDod) return XmlQueryTypeFactory.PrimeProduct(XmlQueryTypeFactory.NodeNotRtfS, variableCard * bodyType.Cardinality); return XmlQueryTypeFactory.PrimeProduct(bodyType, variableCard * bodyType.Cardinality); } 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); } #endregion // loops #region sorting //----------------------------------------------- // 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 if (varType.IsDod) return XmlQueryTypeFactory.PrimeProduct(XmlQueryTypeFactory.NodeNotRtfS, varType.Cardinality); return node.Variable.Binding.XmlType; } public XmlQueryType CheckSortKey(QilSortKey node) { CheckAtomicX(node.Key); CheckXmlType(node.Collation, XmlQueryTypeFactory.StringX); return node.Key.XmlType; } public XmlQueryType CheckDocOrderDistinct(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeNotRtfS); return DistinctType(node.Child.XmlType); } #endregion // sorting #region function definition and invocation //----------------------------------------------- // function definition and invocation //----------------------------------------------- public XmlQueryType CheckFunction(QilFunction node) { CheckClassAndNodeType(node[0], typeof(QilList), QilNodeType.FormalParameterList); Check(node[2].NodeType == QilNodeType.False || node[2].NodeType == QilNodeType.True, node, "SideEffects must either be True or False"); Check(node.Definition.XmlType.IsSubtypeOf(node.XmlType), node, "Function definition's xml type must be a subtype of the function's return type"); return node.XmlType; } public XmlQueryType CheckInvoke(QilInvoke node) { #if DEBUG CheckClassAndNodeType(node[1], typeof(QilList), QilNodeType.ActualParameterList); QilList actualArgs = node.Arguments; QilList formalArgs = node.Function.Arguments; Check(actualArgs.Count == formalArgs.Count, actualArgs, "Invoke argument count must match function's argument count"); for (int i = 0; i < actualArgs.Count; i++) Check(actualArgs[i].XmlType.IsSubtypeOf(formalArgs[i].XmlType), actualArgs[i], "Invoke argument must be a subtype of the invoked function's argument"); #endif return node.Function.XmlType; } #endregion // function definition and invocation #region XML navigation //----------------------------------------------- // XML navigation //----------------------------------------------- public XmlQueryType CheckContent(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeNotRtf); return XmlQueryTypeFactory.AttributeOrContentS; } public XmlQueryType CheckAttribute(QilBinary node) { CheckXmlType(node.Left, XmlQueryTypeFactory.NodeNotRtf); CheckXmlType(node.Right, XmlQueryTypeFactory.QNameX); return XmlQueryTypeFactory.AttributeQ; } public XmlQueryType CheckParent(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeNotRtf); return XmlQueryTypeFactory.DocumentOrElementQ; } public XmlQueryType CheckRoot(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeNotRtf); return XmlQueryTypeFactory.NodeNotRtf; } public XmlQueryType CheckXmlContext(QilNode node) { return XmlQueryTypeFactory.NodeNotRtf; } public XmlQueryType CheckDescendant(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeNotRtf); return XmlQueryTypeFactory.ContentS; } public XmlQueryType CheckDescendantOrSelf(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeNotRtf); return XmlQueryTypeFactory.Choice(node.Child.XmlType, XmlQueryTypeFactory.ContentS); } public XmlQueryType CheckAncestor(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeNotRtf); return XmlQueryTypeFactory.DocumentOrElementS; } public XmlQueryType CheckAncestorOrSelf(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeNotRtf); return XmlQueryTypeFactory.Choice(node.Child.XmlType, XmlQueryTypeFactory.DocumentOrElementS); } public XmlQueryType CheckPreceding(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeNotRtf); return XmlQueryTypeFactory.DocumentOrContentS; } public XmlQueryType CheckFollowingSibling(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeNotRtf); return XmlQueryTypeFactory.ContentS; } public XmlQueryType CheckPrecedingSibling(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeNotRtf); return XmlQueryTypeFactory.ContentS; } public XmlQueryType CheckNodeRange(QilBinary node) { CheckXmlType(node.Left, XmlQueryTypeFactory.NodeNotRtf); CheckXmlType(node.Right, XmlQueryTypeFactory.NodeNotRtf); return XmlQueryTypeFactory.Choice(node.Left.XmlType, XmlQueryTypeFactory.ContentS, node.Right.XmlType); } public XmlQueryType CheckDeref(QilBinary node) { CheckXmlType(node.Left, XmlQueryTypeFactory.NodeNotRtf); CheckXmlType(node.Right, XmlQueryTypeFactory.StringX); return XmlQueryTypeFactory.ElementS; } #endregion // XML navigation #region XML construction //----------------------------------------------- // XML construction //----------------------------------------------- public XmlQueryType CheckElementCtor(QilBinary node) { CheckXmlType(node.Left, XmlQueryTypeFactory.QNameX); CheckXmlType(node.Right, XmlQueryTypeFactory.NodeNotRtfS); return XmlQueryTypeFactory.UntypedElement; } public XmlQueryType CheckAttributeCtor(QilBinary node) { CheckXmlType(node.Left, XmlQueryTypeFactory.QNameX); CheckXmlType(node.Right, XmlQueryTypeFactory.NodeNotRtfS); return XmlQueryTypeFactory.UntypedAttribute; } public XmlQueryType CheckCommentCtor(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeNotRtfS); return XmlQueryTypeFactory.Comment; } public XmlQueryType CheckPICtor(QilBinary node) { CheckXmlType(node.Left, XmlQueryTypeFactory.StringX); CheckXmlType(node.Right, XmlQueryTypeFactory.NodeNotRtfS); return XmlQueryTypeFactory.PI; } public XmlQueryType CheckTextCtor(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.StringX); return XmlQueryTypeFactory.Text; } public XmlQueryType CheckRawTextCtor(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.StringX); return XmlQueryTypeFactory.Text; } public XmlQueryType CheckDocumentCtor(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeNotRtfS); return XmlQueryTypeFactory.UntypedDocument; } public XmlQueryType CheckNamespaceDecl(QilBinary node) { CheckXmlType(node.Left, XmlQueryTypeFactory.StringX); CheckXmlType(node.Right, XmlQueryTypeFactory.StringX); return XmlQueryTypeFactory.Namespace; } public XmlQueryType CheckRtfCtor(QilBinary node) { CheckXmlType(node.Left, XmlQueryTypeFactory.NodeNotRtfS); CheckClassAndNodeType(node.Right, typeof(QilLiteral), QilNodeType.LiteralString); return XmlQueryTypeFactory.Node; } #endregion // XML construction #region Node properties //----------------------------------------------- // Node properties //----------------------------------------------- public XmlQueryType CheckNameOf(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.Node); return XmlQueryTypeFactory.QNameX; } public XmlQueryType CheckLocalNameOf(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.Node); return XmlQueryTypeFactory.StringX; } public XmlQueryType CheckNamespaceUriOf(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.Node); return XmlQueryTypeFactory.StringX; } public XmlQueryType CheckPrefixOf(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.Node); return XmlQueryTypeFactory.StringX; } #endregion // Node properties #region Copy operators //----------------------------------------------- // Copy operators //----------------------------------------------- public XmlQueryType CheckDeepCopy(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeNotRtf); return node.XmlType; } #endregion // Copy operators #region Type operators //----------------------------------------------- // Type operators //----------------------------------------------- public XmlQueryType CheckTypeAssert(QilTargetType node) { CheckClassAndNodeType(node[1], typeof(QilLiteral), QilNodeType.LiteralType); return node.TargetType; } public XmlQueryType CheckIsType(QilTargetType node) { CheckClassAndNodeType(node[1], typeof(QilLiteral), QilNodeType.LiteralType); return XmlQueryTypeFactory.BooleanX; } public XmlQueryType CheckIsEmpty(QilUnary node) { return XmlQueryTypeFactory.BooleanX; } #endregion // Type operators #region XPath operators //----------------------------------------------- // XPath operators //----------------------------------------------- public XmlQueryType CheckXPathNodeValue(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeS); return XmlQueryTypeFactory.StringX; } public XmlQueryType CheckXPathFollowing(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeNotRtf); return XmlQueryTypeFactory.ContentS; } public XmlQueryType CheckXPathPreceding(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeNotRtf); return XmlQueryTypeFactory.ContentS; } public XmlQueryType CheckXPathNamespace(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeNotRtf); return XmlQueryTypeFactory.NamespaceS; } #endregion // XPath operators #region XSLT //----------------------------------------------- // XSLT //----------------------------------------------- public XmlQueryType CheckXsltGenerateId(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeNotRtfS); return XmlQueryTypeFactory.StringX; } public XmlQueryType CheckXsltInvokeLateBound(QilInvokeLateBound node) { CheckLiteralValue(node[0], typeof(QilName)); CheckClassAndNodeType(node[1], typeof(QilList), QilNodeType.ActualParameterList); return XmlQueryTypeFactory.ItemS; } 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; } public XmlQueryType CheckXsltCopy(QilBinary node) { CheckXmlType(node.Left, XmlQueryTypeFactory.NodeNotRtf); CheckXmlType(node.Right, XmlQueryTypeFactory.NodeS); return XmlQueryTypeFactory.Choice(node.Left.XmlType, node.Right.XmlType); } public XmlQueryType CheckXsltCopyOf(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.Node); if ((node.Child.XmlType.NodeKinds & XmlNodeKindFlags.Document) != 0) return XmlQueryTypeFactory.NodeNotRtfS; return node.Child.XmlType; } public XmlQueryType CheckXsltConvert(QilTargetType node) { CheckClassAndNodeType(node[1], typeof(QilLiteral), QilNodeType.LiteralType); return node.TargetType; } #endregion // Xslt operators //----------------------------------------------- // Helper functions //----------------------------------------------- [Conditional("DEBUG")] private void Check(bool value, QilNode node, string message) { if (!value) QilValidationVisitor.SetError(node, message); } [Conditional("DEBUG")] private void CheckLiteralValue(QilNode node, Type clrTypeValue) { Check(node is QilLiteral, node, "Node must be instance of QilLiteral"); Type clrType = ((QilLiteral) node).Value.GetType(); Check(clrTypeValue.IsAssignableFrom(clrType), node, "Literal value must be of type " + clrTypeValue.Name); } [Conditional("DEBUG")] private void CheckClass(QilNode node, Type clrTypeClass) { Check(clrTypeClass.IsAssignableFrom(node.GetType()), node, "Node must be instance of " + clrTypeClass.Name); } [Conditional("DEBUG")] private void CheckClassAndNodeType(QilNode node, Type clrTypeClass, QilNodeType nodeType) { CheckClass(node, clrTypeClass); Check(node.NodeType == nodeType, node, "Node must have QilNodeType." + nodeType); } [Conditional("DEBUG")] private void CheckXmlType(QilNode node, XmlQueryType xmlType) { Check(node.XmlType.IsSubtypeOf(xmlType), node, "Node's type " + node.XmlType + " is not a subtype of " + xmlType); } [Conditional("DEBUG")] private void CheckNumericX(QilNode node) { Check(node.XmlType.IsNumeric && node.XmlType.IsSingleton && node.XmlType.IsStrict, node, "Node's type " + node.XmlType + " must be a strict singleton numeric type"); } [Conditional("DEBUG")] private void CheckNumericXS(QilNode node) { Check(node.XmlType.IsNumeric && node.XmlType.IsStrict, node, "Node's type " + node.XmlType + " must be a strict numeric type"); } [Conditional("DEBUG")] private void CheckAtomicX(QilNode node) { Check(node.XmlType.IsAtomicValue && node.XmlType.IsStrict, node, "Node's type " + node.XmlType + " must be a strict atomic value type"); } [Conditional("DEBUG")] private void CheckNotDisjoint(QilBinary node) { Check(node.Left.XmlType.IsSubtypeOf(node.Right.XmlType) || node.Right.XmlType.IsSubtypeOf(node.Left.XmlType), node, "Node must not have arguments with disjoint types " + node.Left.XmlType + " and " + node.Right.XmlType); } 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 XmlQueryType FindFilterType(QilIterator variable, QilNode body) { XmlQueryType leftType; QilBinary binary; if (body.XmlType.TypeCode == XmlTypeCode.None) return XmlQueryTypeFactory.None; switch (body.NodeType) { case QilNodeType.False: return XmlQueryTypeFactory.Empty; case QilNodeType.IsType: // If testing the type of "variable", then filter type can be restricted if (Ref.Equals(((QilTargetType) body).Source, variable)) return XmlQueryTypeFactory.AtMost(((QilTargetType)body).TargetType, variable.Binding.XmlType.Cardinality); break; case QilNodeType.And: // Both And conditions can be used to restrict filter's type leftType = FindFilterType(variable, ((QilBinary) body).Left); if (leftType != null) return leftType; return FindFilterType(variable, ((QilBinary) body).Right); case QilNodeType.Eq: // Restrict cardinality if position($iterator) = $pos is found binary = (QilBinary) body; if (binary.Left.NodeType == QilNodeType.PositionOf) { if (Ref.Equals(((QilUnary) binary.Left).Child, variable)) return XmlQueryTypeFactory.AtMost(variable.Binding.XmlType, XmlQueryCardinality.ZeroOrOne); } break; } return null; } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //----------------------------------------------------------------------------- using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Xml.Schema; using System.Xml.XPath; using System.Xml.Xsl; using System.Xml.Xsl.Runtime; namespace System.Xml.Xsl.Qil { ////// This class performs two functions: /// 1. Infer XmlQueryType of Qil nodes (constant, from arguments, etc) /// 2. Validate the arguments of Qil nodes if DEBUG is defined /// internal class QilTypeChecker { public QilTypeChecker() { } public XmlQueryType Check(QilNode n) { #region AUTOGENERATED switch (n.NodeType) { case QilNodeType.QilExpression: return CheckQilExpression((QilExpression)n); case QilNodeType.FunctionList: return CheckFunctionList((QilList)n); case QilNodeType.GlobalVariableList: return CheckGlobalVariableList((QilList)n); case QilNodeType.GlobalParameterList: return CheckGlobalParameterList((QilList)n); case QilNodeType.ActualParameterList: return CheckActualParameterList((QilList)n); case QilNodeType.FormalParameterList: return CheckFormalParameterList((QilList)n); case QilNodeType.SortKeyList: return CheckSortKeyList((QilList)n); case QilNodeType.BranchList: return CheckBranchList((QilList)n); case QilNodeType.OptimizeBarrier: return CheckOptimizeBarrier((QilUnary)n); case QilNodeType.Unknown: return CheckUnknown(n); case QilNodeType.DataSource: return CheckDataSource((QilDataSource)n); case QilNodeType.Nop: return CheckNop((QilUnary)n); case QilNodeType.Error: return CheckError((QilUnary)n); case QilNodeType.Warning: return CheckWarning((QilUnary)n); case QilNodeType.For: return CheckFor((QilIterator)n); case QilNodeType.Let: return CheckLet((QilIterator)n); case QilNodeType.Parameter: return CheckParameter((QilParameter)n); case QilNodeType.PositionOf: return CheckPositionOf((QilUnary)n); case QilNodeType.True: return CheckTrue(n); case QilNodeType.False: return CheckFalse(n); case QilNodeType.LiteralString: return CheckLiteralString((QilLiteral)n); case QilNodeType.LiteralInt32: return CheckLiteralInt32((QilLiteral)n); case QilNodeType.LiteralInt64: return CheckLiteralInt64((QilLiteral)n); case QilNodeType.LiteralDouble: return CheckLiteralDouble((QilLiteral)n); case QilNodeType.LiteralDecimal: return CheckLiteralDecimal((QilLiteral)n); case QilNodeType.LiteralQName: return CheckLiteralQName((QilName)n); case QilNodeType.LiteralType: return CheckLiteralType((QilLiteral)n); case QilNodeType.LiteralObject: return CheckLiteralObject((QilLiteral)n); case QilNodeType.And: return CheckAnd((QilBinary)n); case QilNodeType.Or: return CheckOr((QilBinary)n); case QilNodeType.Not: return CheckNot((QilUnary)n); case QilNodeType.Conditional: return CheckConditional((QilTernary)n); case QilNodeType.Choice: return CheckChoice((QilChoice)n); case QilNodeType.Length: return CheckLength((QilUnary)n); case QilNodeType.Sequence: return CheckSequence((QilList)n); case QilNodeType.Union: return CheckUnion((QilBinary)n); case QilNodeType.Intersection: return CheckIntersection((QilBinary)n); case QilNodeType.Difference: return CheckDifference((QilBinary)n); case QilNodeType.Average: return CheckAverage((QilUnary)n); case QilNodeType.Sum: return CheckSum((QilUnary)n); case QilNodeType.Minimum: return CheckMinimum((QilUnary)n); case QilNodeType.Maximum: return CheckMaximum((QilUnary)n); case QilNodeType.Negate: return CheckNegate((QilUnary)n); case QilNodeType.Add: return CheckAdd((QilBinary)n); case QilNodeType.Subtract: return CheckSubtract((QilBinary)n); case QilNodeType.Multiply: return CheckMultiply((QilBinary)n); case QilNodeType.Divide: return CheckDivide((QilBinary)n); case QilNodeType.Modulo: return CheckModulo((QilBinary)n); case QilNodeType.StrLength: return CheckStrLength((QilUnary)n); case QilNodeType.StrConcat: return CheckStrConcat((QilStrConcat)n); case QilNodeType.StrParseQName: return CheckStrParseQName((QilBinary)n); case QilNodeType.Ne: return CheckNe((QilBinary)n); case QilNodeType.Eq: return CheckEq((QilBinary)n); case QilNodeType.Gt: return CheckGt((QilBinary)n); case QilNodeType.Ge: return CheckGe((QilBinary)n); case QilNodeType.Lt: return CheckLt((QilBinary)n); case QilNodeType.Le: return CheckLe((QilBinary)n); case QilNodeType.Is: return CheckIs((QilBinary)n); case QilNodeType.After: return CheckAfter((QilBinary)n); case QilNodeType.Before: return CheckBefore((QilBinary)n); case QilNodeType.Loop: return CheckLoop((QilLoop)n); case QilNodeType.Filter: return CheckFilter((QilLoop)n); case QilNodeType.Sort: return CheckSort((QilLoop)n); case QilNodeType.SortKey: return CheckSortKey((QilSortKey)n); case QilNodeType.DocOrderDistinct: return CheckDocOrderDistinct((QilUnary)n); case QilNodeType.Function: return CheckFunction((QilFunction)n); case QilNodeType.Invoke: return CheckInvoke((QilInvoke)n); case QilNodeType.Content: return CheckContent((QilUnary)n); case QilNodeType.Attribute: return CheckAttribute((QilBinary)n); case QilNodeType.Parent: return CheckParent((QilUnary)n); case QilNodeType.Root: return CheckRoot((QilUnary)n); case QilNodeType.XmlContext: return CheckXmlContext(n); case QilNodeType.Descendant: return CheckDescendant((QilUnary)n); case QilNodeType.DescendantOrSelf: return CheckDescendantOrSelf((QilUnary)n); case QilNodeType.Ancestor: return CheckAncestor((QilUnary)n); case QilNodeType.AncestorOrSelf: return CheckAncestorOrSelf((QilUnary)n); case QilNodeType.Preceding: return CheckPreceding((QilUnary)n); case QilNodeType.FollowingSibling: return CheckFollowingSibling((QilUnary)n); case QilNodeType.PrecedingSibling: return CheckPrecedingSibling((QilUnary)n); case QilNodeType.NodeRange: return CheckNodeRange((QilBinary)n); case QilNodeType.Deref: return CheckDeref((QilBinary)n); case QilNodeType.ElementCtor: return CheckElementCtor((QilBinary)n); case QilNodeType.AttributeCtor: return CheckAttributeCtor((QilBinary)n); case QilNodeType.CommentCtor: return CheckCommentCtor((QilUnary)n); case QilNodeType.PICtor: return CheckPICtor((QilBinary)n); case QilNodeType.TextCtor: return CheckTextCtor((QilUnary)n); case QilNodeType.RawTextCtor: return CheckRawTextCtor((QilUnary)n); case QilNodeType.DocumentCtor: return CheckDocumentCtor((QilUnary)n); case QilNodeType.NamespaceDecl: return CheckNamespaceDecl((QilBinary)n); case QilNodeType.RtfCtor: return CheckRtfCtor((QilBinary)n); case QilNodeType.NameOf: return CheckNameOf((QilUnary)n); case QilNodeType.LocalNameOf: return CheckLocalNameOf((QilUnary)n); case QilNodeType.NamespaceUriOf: return CheckNamespaceUriOf((QilUnary)n); case QilNodeType.PrefixOf: return CheckPrefixOf((QilUnary)n); case QilNodeType.TypeAssert: return CheckTypeAssert((QilTargetType)n); case QilNodeType.IsType: return CheckIsType((QilTargetType)n); case QilNodeType.IsEmpty: return CheckIsEmpty((QilUnary)n); case QilNodeType.XPathNodeValue: return CheckXPathNodeValue((QilUnary)n); case QilNodeType.XPathFollowing: return CheckXPathFollowing((QilUnary)n); case QilNodeType.XPathPreceding: return CheckXPathPreceding((QilUnary)n); case QilNodeType.XPathNamespace: return CheckXPathNamespace((QilUnary)n); case QilNodeType.XsltGenerateId: return CheckXsltGenerateId((QilUnary)n); case QilNodeType.XsltInvokeLateBound: return CheckXsltInvokeLateBound((QilInvokeLateBound)n); case QilNodeType.XsltInvokeEarlyBound: return CheckXsltInvokeEarlyBound((QilInvokeEarlyBound)n); case QilNodeType.XsltCopy: return CheckXsltCopy((QilBinary)n); case QilNodeType.XsltCopyOf: return CheckXsltCopyOf((QilUnary)n); case QilNodeType.XsltConvert: return CheckXsltConvert((QilTargetType)n); default: return CheckUnknown(n); } #endregion } #region meta //----------------------------------------------- // meta //----------------------------------------------- public XmlQueryType CheckQilExpression(QilExpression node) { Check(node[0].NodeType == QilNodeType.False || node[0].NodeType == QilNodeType.True, node, "IsDebug must either be True or False"); CheckLiteralValue(node[1], typeof(XmlWriterSettings)); CheckLiteralValue(node[2], typeof(IList)); CheckClassAndNodeType(node[3], typeof(QilList), QilNodeType.GlobalParameterList); CheckClassAndNodeType(node[4], typeof(QilList), QilNodeType.GlobalVariableList); CheckLiteralValue(node[5], typeof(IList )); CheckClassAndNodeType(node[6], typeof(QilList), QilNodeType.FunctionList); return XmlQueryTypeFactory.ItemS; } public XmlQueryType CheckFunctionList(QilList node) { foreach (QilNode child in node) CheckClassAndNodeType(child, typeof(QilFunction), QilNodeType.Function); return node.XmlType; } public XmlQueryType CheckGlobalVariableList(QilList node) { foreach (QilNode child in node) CheckClassAndNodeType(child, typeof(QilIterator), QilNodeType.Let); return node.XmlType; } public XmlQueryType CheckGlobalParameterList(QilList node) { foreach (QilNode child in node) CheckClassAndNodeType(child, typeof(QilParameter), QilNodeType.Parameter); return node.XmlType; } public XmlQueryType CheckActualParameterList(QilList node) { return node.XmlType; } public XmlQueryType CheckFormalParameterList(QilList node) { foreach (QilNode child in node) CheckClassAndNodeType(child, typeof(QilParameter), QilNodeType.Parameter); return node.XmlType; } public XmlQueryType CheckSortKeyList(QilList node) { foreach (QilNode child in node) CheckClassAndNodeType(child, typeof(QilSortKey), QilNodeType.SortKey); return node.XmlType; } public XmlQueryType CheckBranchList(QilList node) { return node.XmlType; } public XmlQueryType CheckOptimizeBarrier(QilUnary node) { return node.Child.XmlType; } public XmlQueryType CheckNoDefaultValue(QilNode node) { return XmlQueryTypeFactory.None; } public XmlQueryType CheckUnknown(QilNode node) { return node.XmlType; } #endregion // meta #region specials //----------------------------------------------- // specials //----------------------------------------------- public XmlQueryType CheckDataSource(QilDataSource node) { CheckXmlType(node.Name, XmlQueryTypeFactory.StringX); CheckXmlType(node.BaseUri, XmlQueryTypeFactory.StringX); return XmlQueryTypeFactory.NodeNotRtfQ; } public XmlQueryType CheckNop(QilUnary node) { return node.Child.XmlType; } public XmlQueryType CheckError(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.StringX); return XmlQueryTypeFactory.None; } public XmlQueryType CheckWarning(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.StringX); return XmlQueryTypeFactory.Empty; } #endregion // specials #region variables //----------------------------------------------- // variables //----------------------------------------------- public XmlQueryType CheckFor(QilIterator node) { return node.Binding.XmlType.Prime; } public XmlQueryType CheckLet(QilIterator node) { return node.Binding.XmlType; } public XmlQueryType CheckParameter(QilParameter node) { Check(node.Binding == null || node.Binding.XmlType.IsSubtypeOf(node.XmlType), node, "Parameter binding's xml type must be a subtype of the parameter's type"); return node.XmlType; } public XmlQueryType CheckPositionOf(QilUnary node) { return XmlQueryTypeFactory.IntX; } #endregion // variables #region literals //----------------------------------------------- // literals //----------------------------------------------- public XmlQueryType CheckTrue(QilNode node) { return XmlQueryTypeFactory.BooleanX; } public XmlQueryType CheckFalse(QilNode node) { return XmlQueryTypeFactory.BooleanX; } public XmlQueryType CheckLiteralString(QilLiteral node) { CheckLiteralValue(node, typeof(string)); return XmlQueryTypeFactory.StringX; } public XmlQueryType CheckLiteralInt32(QilLiteral node) { CheckLiteralValue(node, typeof(int)); return XmlQueryTypeFactory.IntX; } public XmlQueryType CheckLiteralInt64(QilLiteral node) { CheckLiteralValue(node, typeof(long)); return XmlQueryTypeFactory.IntegerX; } public XmlQueryType CheckLiteralDouble(QilLiteral node) { CheckLiteralValue(node, typeof(double)); return XmlQueryTypeFactory.DoubleX; } public XmlQueryType CheckLiteralDecimal(QilLiteral node) { CheckLiteralValue(node, typeof(decimal)); return XmlQueryTypeFactory.DecimalX; } public XmlQueryType CheckLiteralQName(QilName node) { CheckLiteralValue(node, typeof(QilName)); // return XmlQueryTypeFactory.QNameX; } public XmlQueryType CheckLiteralType(QilLiteral node) { CheckLiteralValue(node, typeof(XmlQueryType)); return (XmlQueryType) node; } public XmlQueryType CheckLiteralObject(QilLiteral node) { Check(node.Value != null, node, "Literal value is null"); return XmlQueryTypeFactory.ItemS; } #endregion // literals #region boolean operators //----------------------------------------------- // boolean operators //----------------------------------------------- public XmlQueryType CheckAnd(QilBinary node) { CheckXmlType(node.Left, XmlQueryTypeFactory.BooleanX); CheckXmlType(node.Right, XmlQueryTypeFactory.BooleanX); return XmlQueryTypeFactory.BooleanX; } public XmlQueryType CheckOr(QilBinary node) { return CheckAnd(node); } public XmlQueryType CheckNot(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.BooleanX); return XmlQueryTypeFactory.BooleanX; } #endregion // boolean operators #region choice //----------------------------------------------- // choice //----------------------------------------------- public XmlQueryType CheckConditional(QilTernary node) { CheckXmlType(node.Left, XmlQueryTypeFactory.BooleanX); return XmlQueryTypeFactory.Choice(node.Center.XmlType, node.Right.XmlType); } public XmlQueryType CheckChoice(QilChoice node) { CheckXmlType(node.Expression, XmlQueryTypeFactory.IntX); CheckClassAndNodeType(node.Branches, typeof(QilList), QilNodeType.BranchList); Check(node.Branches.Count > 0, node, "Choice must have at least one branch"); return node.Branches.XmlType; } #endregion // choice #region collection operators //----------------------------------------------- // collection operators //----------------------------------------------- public XmlQueryType CheckLength(QilUnary node) { return XmlQueryTypeFactory.IntX; } public XmlQueryType CheckSequence(QilList node) { return node.XmlType; } public XmlQueryType CheckUnion(QilBinary node) { CheckXmlType(node.Left, XmlQueryTypeFactory.NodeNotRtfS); CheckXmlType(node.Right, XmlQueryTypeFactory.NodeNotRtfS); return DistinctType(XmlQueryTypeFactory.Sequence(node.Left.XmlType, node.Right.XmlType)); } public XmlQueryType CheckIntersection(QilBinary node) { return CheckUnion(node); } public XmlQueryType CheckDifference(QilBinary node) { CheckXmlType(node.Left, XmlQueryTypeFactory.NodeNotRtfS); CheckXmlType(node.Right, XmlQueryTypeFactory.NodeNotRtfS); return XmlQueryTypeFactory.AtMost(node.Left.XmlType, node.Left.XmlType.Cardinality); } public XmlQueryType CheckAverage(QilUnary node) { XmlQueryType xmlType = node.Child.XmlType; CheckNumericXS(node.Child); return XmlQueryTypeFactory.PrimeProduct(xmlType, xmlType.MaybeEmpty ? XmlQueryCardinality.ZeroOrOne : XmlQueryCardinality.One); } public XmlQueryType CheckSum(QilUnary node) { return CheckAverage(node); } public XmlQueryType CheckMinimum(QilUnary node) { return CheckAverage(node); } public XmlQueryType CheckMaximum(QilUnary node) { return CheckAverage(node); } #endregion // collection operators #region arithmetic operators //----------------------------------------------- // arithmetic operators //----------------------------------------------- public XmlQueryType CheckNegate(QilUnary node) { CheckNumericX(node.Child); return node.Child.XmlType; } public XmlQueryType CheckAdd(QilBinary node) { CheckNumericX(node.Left); CheckNumericX(node.Right); CheckNotDisjoint(node); return node.Left.XmlType.TypeCode == XmlTypeCode.None ? node.Right.XmlType : node.Left.XmlType; } public XmlQueryType CheckSubtract(QilBinary node) { return CheckAdd(node); } public XmlQueryType CheckMultiply(QilBinary node) { return CheckAdd(node); } public XmlQueryType CheckDivide(QilBinary node) { return CheckAdd(node); } public XmlQueryType CheckModulo(QilBinary node) { return CheckAdd(node); } #endregion // arithmetic operators #region string operators //----------------------------------------------- // string operators //----------------------------------------------- public XmlQueryType CheckStrLength(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.StringX); return XmlQueryTypeFactory.IntX; } public XmlQueryType CheckStrConcat(QilStrConcat node) { CheckXmlType(node.Delimiter, XmlQueryTypeFactory.StringX); CheckXmlType(node.Values, XmlQueryTypeFactory.StringXS); return XmlQueryTypeFactory.StringX; } public XmlQueryType CheckStrParseQName(QilBinary node) { CheckXmlType(node.Left, XmlQueryTypeFactory.StringX); Check(node.Right.XmlType.IsSubtypeOf(XmlQueryTypeFactory.StringX) || node.Right.XmlType.IsSubtypeOf(XmlQueryTypeFactory.NamespaceS), node, "StrParseQName must take either a string or a list of namespace as its second argument"); return XmlQueryTypeFactory.QNameX; } #endregion // string operators #region value comparison operators //----------------------------------------------- // value comparison operators //----------------------------------------------- public XmlQueryType CheckNe(QilBinary node) { CheckAtomicX(node.Left); CheckAtomicX(node.Right); CheckNotDisjoint(node); return XmlQueryTypeFactory.BooleanX; } public XmlQueryType CheckEq(QilBinary node) { return CheckNe(node); } public XmlQueryType CheckGt(QilBinary node) { return CheckNe(node); } public XmlQueryType CheckGe(QilBinary node) { return CheckNe(node); } public XmlQueryType CheckLt(QilBinary node) { return CheckNe(node); } public XmlQueryType CheckLe(QilBinary node) { return CheckNe(node); } #endregion // value comparison operators #region node comparison operators //----------------------------------------------- // node comparison operators //----------------------------------------------- public XmlQueryType CheckIs(QilBinary node) { CheckXmlType(node.Left, XmlQueryTypeFactory.NodeNotRtf); CheckXmlType(node.Right, XmlQueryTypeFactory.NodeNotRtf); return XmlQueryTypeFactory.BooleanX; } public XmlQueryType CheckAfter(QilBinary node) { return CheckIs(node); } public XmlQueryType CheckBefore(QilBinary node) { return CheckIs(node); } #endregion // node comparison operators #region loops //----------------------------------------------- // 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 if (bodyType.IsDod) return XmlQueryTypeFactory.PrimeProduct(XmlQueryTypeFactory.NodeNotRtfS, variableCard * bodyType.Cardinality); return XmlQueryTypeFactory.PrimeProduct(bodyType, variableCard * bodyType.Cardinality); } 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); } #endregion // loops #region sorting //----------------------------------------------- // 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 if (varType.IsDod) return XmlQueryTypeFactory.PrimeProduct(XmlQueryTypeFactory.NodeNotRtfS, varType.Cardinality); return node.Variable.Binding.XmlType; } public XmlQueryType CheckSortKey(QilSortKey node) { CheckAtomicX(node.Key); CheckXmlType(node.Collation, XmlQueryTypeFactory.StringX); return node.Key.XmlType; } public XmlQueryType CheckDocOrderDistinct(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeNotRtfS); return DistinctType(node.Child.XmlType); } #endregion // sorting #region function definition and invocation //----------------------------------------------- // function definition and invocation //----------------------------------------------- public XmlQueryType CheckFunction(QilFunction node) { CheckClassAndNodeType(node[0], typeof(QilList), QilNodeType.FormalParameterList); Check(node[2].NodeType == QilNodeType.False || node[2].NodeType == QilNodeType.True, node, "SideEffects must either be True or False"); Check(node.Definition.XmlType.IsSubtypeOf(node.XmlType), node, "Function definition's xml type must be a subtype of the function's return type"); return node.XmlType; } public XmlQueryType CheckInvoke(QilInvoke node) { #if DEBUG CheckClassAndNodeType(node[1], typeof(QilList), QilNodeType.ActualParameterList); QilList actualArgs = node.Arguments; QilList formalArgs = node.Function.Arguments; Check(actualArgs.Count == formalArgs.Count, actualArgs, "Invoke argument count must match function's argument count"); for (int i = 0; i < actualArgs.Count; i++) Check(actualArgs[i].XmlType.IsSubtypeOf(formalArgs[i].XmlType), actualArgs[i], "Invoke argument must be a subtype of the invoked function's argument"); #endif return node.Function.XmlType; } #endregion // function definition and invocation #region XML navigation //----------------------------------------------- // XML navigation //----------------------------------------------- public XmlQueryType CheckContent(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeNotRtf); return XmlQueryTypeFactory.AttributeOrContentS; } public XmlQueryType CheckAttribute(QilBinary node) { CheckXmlType(node.Left, XmlQueryTypeFactory.NodeNotRtf); CheckXmlType(node.Right, XmlQueryTypeFactory.QNameX); return XmlQueryTypeFactory.AttributeQ; } public XmlQueryType CheckParent(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeNotRtf); return XmlQueryTypeFactory.DocumentOrElementQ; } public XmlQueryType CheckRoot(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeNotRtf); return XmlQueryTypeFactory.NodeNotRtf; } public XmlQueryType CheckXmlContext(QilNode node) { return XmlQueryTypeFactory.NodeNotRtf; } public XmlQueryType CheckDescendant(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeNotRtf); return XmlQueryTypeFactory.ContentS; } public XmlQueryType CheckDescendantOrSelf(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeNotRtf); return XmlQueryTypeFactory.Choice(node.Child.XmlType, XmlQueryTypeFactory.ContentS); } public XmlQueryType CheckAncestor(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeNotRtf); return XmlQueryTypeFactory.DocumentOrElementS; } public XmlQueryType CheckAncestorOrSelf(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeNotRtf); return XmlQueryTypeFactory.Choice(node.Child.XmlType, XmlQueryTypeFactory.DocumentOrElementS); } public XmlQueryType CheckPreceding(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeNotRtf); return XmlQueryTypeFactory.DocumentOrContentS; } public XmlQueryType CheckFollowingSibling(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeNotRtf); return XmlQueryTypeFactory.ContentS; } public XmlQueryType CheckPrecedingSibling(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeNotRtf); return XmlQueryTypeFactory.ContentS; } public XmlQueryType CheckNodeRange(QilBinary node) { CheckXmlType(node.Left, XmlQueryTypeFactory.NodeNotRtf); CheckXmlType(node.Right, XmlQueryTypeFactory.NodeNotRtf); return XmlQueryTypeFactory.Choice(node.Left.XmlType, XmlQueryTypeFactory.ContentS, node.Right.XmlType); } public XmlQueryType CheckDeref(QilBinary node) { CheckXmlType(node.Left, XmlQueryTypeFactory.NodeNotRtf); CheckXmlType(node.Right, XmlQueryTypeFactory.StringX); return XmlQueryTypeFactory.ElementS; } #endregion // XML navigation #region XML construction //----------------------------------------------- // XML construction //----------------------------------------------- public XmlQueryType CheckElementCtor(QilBinary node) { CheckXmlType(node.Left, XmlQueryTypeFactory.QNameX); CheckXmlType(node.Right, XmlQueryTypeFactory.NodeNotRtfS); return XmlQueryTypeFactory.UntypedElement; } public XmlQueryType CheckAttributeCtor(QilBinary node) { CheckXmlType(node.Left, XmlQueryTypeFactory.QNameX); CheckXmlType(node.Right, XmlQueryTypeFactory.NodeNotRtfS); return XmlQueryTypeFactory.UntypedAttribute; } public XmlQueryType CheckCommentCtor(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeNotRtfS); return XmlQueryTypeFactory.Comment; } public XmlQueryType CheckPICtor(QilBinary node) { CheckXmlType(node.Left, XmlQueryTypeFactory.StringX); CheckXmlType(node.Right, XmlQueryTypeFactory.NodeNotRtfS); return XmlQueryTypeFactory.PI; } public XmlQueryType CheckTextCtor(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.StringX); return XmlQueryTypeFactory.Text; } public XmlQueryType CheckRawTextCtor(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.StringX); return XmlQueryTypeFactory.Text; } public XmlQueryType CheckDocumentCtor(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeNotRtfS); return XmlQueryTypeFactory.UntypedDocument; } public XmlQueryType CheckNamespaceDecl(QilBinary node) { CheckXmlType(node.Left, XmlQueryTypeFactory.StringX); CheckXmlType(node.Right, XmlQueryTypeFactory.StringX); return XmlQueryTypeFactory.Namespace; } public XmlQueryType CheckRtfCtor(QilBinary node) { CheckXmlType(node.Left, XmlQueryTypeFactory.NodeNotRtfS); CheckClassAndNodeType(node.Right, typeof(QilLiteral), QilNodeType.LiteralString); return XmlQueryTypeFactory.Node; } #endregion // XML construction #region Node properties //----------------------------------------------- // Node properties //----------------------------------------------- public XmlQueryType CheckNameOf(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.Node); return XmlQueryTypeFactory.QNameX; } public XmlQueryType CheckLocalNameOf(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.Node); return XmlQueryTypeFactory.StringX; } public XmlQueryType CheckNamespaceUriOf(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.Node); return XmlQueryTypeFactory.StringX; } public XmlQueryType CheckPrefixOf(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.Node); return XmlQueryTypeFactory.StringX; } #endregion // Node properties #region Copy operators //----------------------------------------------- // Copy operators //----------------------------------------------- public XmlQueryType CheckDeepCopy(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeNotRtf); return node.XmlType; } #endregion // Copy operators #region Type operators //----------------------------------------------- // Type operators //----------------------------------------------- public XmlQueryType CheckTypeAssert(QilTargetType node) { CheckClassAndNodeType(node[1], typeof(QilLiteral), QilNodeType.LiteralType); return node.TargetType; } public XmlQueryType CheckIsType(QilTargetType node) { CheckClassAndNodeType(node[1], typeof(QilLiteral), QilNodeType.LiteralType); return XmlQueryTypeFactory.BooleanX; } public XmlQueryType CheckIsEmpty(QilUnary node) { return XmlQueryTypeFactory.BooleanX; } #endregion // Type operators #region XPath operators //----------------------------------------------- // XPath operators //----------------------------------------------- public XmlQueryType CheckXPathNodeValue(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeS); return XmlQueryTypeFactory.StringX; } public XmlQueryType CheckXPathFollowing(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeNotRtf); return XmlQueryTypeFactory.ContentS; } public XmlQueryType CheckXPathPreceding(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeNotRtf); return XmlQueryTypeFactory.ContentS; } public XmlQueryType CheckXPathNamespace(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeNotRtf); return XmlQueryTypeFactory.NamespaceS; } #endregion // XPath operators #region XSLT //----------------------------------------------- // XSLT //----------------------------------------------- public XmlQueryType CheckXsltGenerateId(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.NodeNotRtfS); return XmlQueryTypeFactory.StringX; } public XmlQueryType CheckXsltInvokeLateBound(QilInvokeLateBound node) { CheckLiteralValue(node[0], typeof(QilName)); CheckClassAndNodeType(node[1], typeof(QilList), QilNodeType.ActualParameterList); return XmlQueryTypeFactory.ItemS; } 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; } public XmlQueryType CheckXsltCopy(QilBinary node) { CheckXmlType(node.Left, XmlQueryTypeFactory.NodeNotRtf); CheckXmlType(node.Right, XmlQueryTypeFactory.NodeS); return XmlQueryTypeFactory.Choice(node.Left.XmlType, node.Right.XmlType); } public XmlQueryType CheckXsltCopyOf(QilUnary node) { CheckXmlType(node.Child, XmlQueryTypeFactory.Node); if ((node.Child.XmlType.NodeKinds & XmlNodeKindFlags.Document) != 0) return XmlQueryTypeFactory.NodeNotRtfS; return node.Child.XmlType; } public XmlQueryType CheckXsltConvert(QilTargetType node) { CheckClassAndNodeType(node[1], typeof(QilLiteral), QilNodeType.LiteralType); return node.TargetType; } #endregion // Xslt operators //----------------------------------------------- // Helper functions //----------------------------------------------- [Conditional("DEBUG")] private void Check(bool value, QilNode node, string message) { if (!value) QilValidationVisitor.SetError(node, message); } [Conditional("DEBUG")] private void CheckLiteralValue(QilNode node, Type clrTypeValue) { Check(node is QilLiteral, node, "Node must be instance of QilLiteral"); Type clrType = ((QilLiteral) node).Value.GetType(); Check(clrTypeValue.IsAssignableFrom(clrType), node, "Literal value must be of type " + clrTypeValue.Name); } [Conditional("DEBUG")] private void CheckClass(QilNode node, Type clrTypeClass) { Check(clrTypeClass.IsAssignableFrom(node.GetType()), node, "Node must be instance of " + clrTypeClass.Name); } [Conditional("DEBUG")] private void CheckClassAndNodeType(QilNode node, Type clrTypeClass, QilNodeType nodeType) { CheckClass(node, clrTypeClass); Check(node.NodeType == nodeType, node, "Node must have QilNodeType." + nodeType); } [Conditional("DEBUG")] private void CheckXmlType(QilNode node, XmlQueryType xmlType) { Check(node.XmlType.IsSubtypeOf(xmlType), node, "Node's type " + node.XmlType + " is not a subtype of " + xmlType); } [Conditional("DEBUG")] private void CheckNumericX(QilNode node) { Check(node.XmlType.IsNumeric && node.XmlType.IsSingleton && node.XmlType.IsStrict, node, "Node's type " + node.XmlType + " must be a strict singleton numeric type"); } [Conditional("DEBUG")] private void CheckNumericXS(QilNode node) { Check(node.XmlType.IsNumeric && node.XmlType.IsStrict, node, "Node's type " + node.XmlType + " must be a strict numeric type"); } [Conditional("DEBUG")] private void CheckAtomicX(QilNode node) { Check(node.XmlType.IsAtomicValue && node.XmlType.IsStrict, node, "Node's type " + node.XmlType + " must be a strict atomic value type"); } [Conditional("DEBUG")] private void CheckNotDisjoint(QilBinary node) { Check(node.Left.XmlType.IsSubtypeOf(node.Right.XmlType) || node.Right.XmlType.IsSubtypeOf(node.Left.XmlType), node, "Node must not have arguments with disjoint types " + node.Left.XmlType + " and " + node.Right.XmlType); } 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 XmlQueryType FindFilterType(QilIterator variable, QilNode body) { XmlQueryType leftType; QilBinary binary; if (body.XmlType.TypeCode == XmlTypeCode.None) return XmlQueryTypeFactory.None; switch (body.NodeType) { case QilNodeType.False: return XmlQueryTypeFactory.Empty; case QilNodeType.IsType: // If testing the type of "variable", then filter type can be restricted if (Ref.Equals(((QilTargetType) body).Source, variable)) return XmlQueryTypeFactory.AtMost(((QilTargetType)body).TargetType, variable.Binding.XmlType.Cardinality); break; case QilNodeType.And: // Both And conditions can be used to restrict filter's type leftType = FindFilterType(variable, ((QilBinary) body).Left); if (leftType != null) return leftType; return FindFilterType(variable, ((QilBinary) body).Right); case QilNodeType.Eq: // Restrict cardinality if position($iterator) = $pos is found binary = (QilBinary) body; if (binary.Left.NodeType == QilNodeType.PositionOf) { if (Ref.Equals(((QilUnary) binary.Left).Child, variable)) return XmlQueryTypeFactory.AtMost(variable.Binding.XmlType, XmlQueryCardinality.ZeroOrOne); } break; } return null; } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- EventLogTraceListener.cs
- CodeArrayCreateExpression.cs
- CacheModeValueSerializer.cs
- InfiniteTimeSpanConverter.cs
- BuildManager.cs
- WindowPatternIdentifiers.cs
- InfocardInteractiveChannelInitializer.cs
- BuildTopDownAttribute.cs
- Attributes.cs
- CachedBitmap.cs
- BinarySecretSecurityToken.cs
- SettingsContext.cs
- Stroke2.cs
- FunctionQuery.cs
- DuplicateWaitObjectException.cs
- EventProvider.cs
- _FtpDataStream.cs
- StreamWriter.cs
- ExpressionBuilderContext.cs
- Control.cs
- TableSectionStyle.cs
- DataGridViewSelectedRowCollection.cs
- XpsFont.cs
- WindowsSpinner.cs
- TogglePattern.cs
- Pen.cs
- ToolStripDropDownClosedEventArgs.cs
- SemanticResultValue.cs
- ObjectListCommandEventArgs.cs
- SessionStateModule.cs
- EventWaitHandleSecurity.cs
- OleDbReferenceCollection.cs
- Debugger.cs
- UriWriter.cs
- DockAndAnchorLayout.cs
- NetPeerTcpBindingElement.cs
- SqlDataRecord.cs
- BindingMemberInfo.cs
- ECDiffieHellmanPublicKey.cs
- CounterCreationData.cs
- OpenTypeLayout.cs
- DataServiceQueryOfT.cs
- SamlDelegatingWriter.cs
- PropertyTabAttribute.cs
- NamespaceCollection.cs
- CodeDefaultValueExpression.cs
- OleDbRowUpdatedEvent.cs
- VirtualDirectoryMapping.cs
- ConsoleKeyInfo.cs
- ReadOnlyTernaryTree.cs
- XmlQualifiedName.cs
- KnownTypeDataContractResolver.cs
- SafePEFileHandle.cs
- FactoryId.cs
- TransformProviderWrapper.cs
- ReadOnlyHierarchicalDataSource.cs
- IdentifierService.cs
- ConnectionManagementElement.cs
- ScriptManagerProxy.cs
- TextRunCache.cs
- ControlBindingsCollection.cs
- IntegerFacetDescriptionElement.cs
- ClientScriptItemCollection.cs
- ScrollBarRenderer.cs
- EventMappingSettingsCollection.cs
- WindowsPrincipal.cs
- EntityStoreSchemaFilterEntry.cs
- ThreadNeutralSemaphore.cs
- NameTable.cs
- InheritedPropertyChangedEventArgs.cs
- SeekStoryboard.cs
- LinqDataSourceHelper.cs
- HMACRIPEMD160.cs
- MexTcpBindingCollectionElement.cs
- ToolBar.cs
- UpdatePanelControlTrigger.cs
- FilePresentation.cs
- RepeatButton.cs
- XMLSyntaxException.cs
- CopyCodeAction.cs
- WebConvert.cs
- InvokeHandlers.cs
- Matrix3D.cs
- XmlSchemaSet.cs
- UnderstoodHeaders.cs
- XmlWellformedWriter.cs
- Evidence.cs
- COM2ColorConverter.cs
- HttpCookieCollection.cs
- Base64Decoder.cs
- FormViewInsertedEventArgs.cs
- ParagraphVisual.cs
- ConfigurationValues.cs
- DataSourceListEditor.cs
- DeviceFilterEditorDialog.cs
- TextTreeTextBlock.cs
- FunctionDetailsReader.cs
- RotateTransform3D.cs
- URLMembershipCondition.cs
- HttpHostedTransportConfiguration.cs