Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / whidbey / netfxsp / ndp / fx / src / XmlUtils / System / Xml / Xsl / QIL / QilTypeChecker.cs / 5 / 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
- SystemException.cs
- ApplicationTrust.cs
- WebPartConnectionsCloseVerb.cs
- Rfc2898DeriveBytes.cs
- RemoteWebConfigurationHostStream.cs
- HasCopySemanticsAttribute.cs
- ProviderConnectionPointCollection.cs
- FieldToken.cs
- InstanceHandle.cs
- HashCodeCombiner.cs
- InfoCardKeyedHashAlgorithm.cs
- WebConfigurationHostFileChange.cs
- WsdlBuildProvider.cs
- BlurEffect.cs
- CounterSample.cs
- ParameterElementCollection.cs
- LicenseException.cs
- ScriptManager.cs
- WorkflowInstanceContextProvider.cs
- SystemFonts.cs
- TableLayoutCellPaintEventArgs.cs
- ThrowOnMultipleAssignment.cs
- HttpCachePolicyBase.cs
- ColorMap.cs
- PasswordTextNavigator.cs
- SafeLibraryHandle.cs
- HttpModule.cs
- MetadataSource.cs
- XmlIlGenerator.cs
- DataGridViewTextBoxEditingControl.cs
- RepeaterItem.cs
- DeviceSpecificChoiceCollection.cs
- ContainerControlDesigner.cs
- DiagnosticEventProvider.cs
- SimpleWorkerRequest.cs
- DataListItem.cs
- TextBox.cs
- BuildResult.cs
- ImageMetadata.cs
- Compensation.cs
- DesignerAutoFormat.cs
- SecurityHelper.cs
- ProviderCommandInfoUtils.cs
- CompositionAdorner.cs
- SimplePropertyEntry.cs
- RandomDelaySendsAsyncResult.cs
- MdImport.cs
- NavigationFailedEventArgs.cs
- ContainerParaClient.cs
- ParagraphResult.cs
- TextCharacters.cs
- PathStreamGeometryContext.cs
- PersianCalendar.cs
- Expression.cs
- DBCommandBuilder.cs
- ErrorWrapper.cs
- ControlPropertyNameConverter.cs
- ToolStripComboBox.cs
- DrawingContextDrawingContextWalker.cs
- PolicyLevel.cs
- SqlDependency.cs
- RunClient.cs
- odbcmetadatacolumnnames.cs
- TreeView.cs
- ProcessModule.cs
- ReflectionHelper.cs
- PenCursorManager.cs
- CompileLiteralTextParser.cs
- HttpClientCertificate.cs
- ServicePointManagerElement.cs
- UIElementHelper.cs
- AutomationPatternInfo.cs
- FixedPageProcessor.cs
- TableLayoutColumnStyleCollection.cs
- AuthorizationRule.cs
- BehaviorService.cs
- OSFeature.cs
- SiteOfOriginPart.cs
- LinearKeyFrames.cs
- StreamInfo.cs
- WebMessageEncodingBindingElement.cs
- DockPanel.cs
- WebPartTracker.cs
- SoapAttributes.cs
- DragAssistanceManager.cs
- SimpleType.cs
- TypeUtil.cs
- Thread.cs
- OutputCacheModule.cs
- NodeFunctions.cs
- VisualProxy.cs
- CompiledQuery.cs
- PtsPage.cs
- PropagatorResult.cs
- RegisteredHiddenField.cs
- HyperLinkDesigner.cs
- RootCodeDomSerializer.cs
- Int16AnimationBase.cs
- FrameworkElementFactoryMarkupObject.cs
- HScrollBar.cs