//----------------------------------------------- // QilReplaceVisitor methods //----------------------------------------------- /// <summary> /// Once children have been replaced, the Xml type is recalculated. /// </summary> protected virtual void RecalculateType(QilNode node, XmlQueryType oldType) { XmlQueryType newType; newType = QilTypeChecker.Check(node); // Note the use of AtMost to account for cases when folding of Error nodes in the graph cause // cardinality to be recalculated. // For example, (Sequence (TextCtor (Error "error")) (Int32 1)) => (Sequence (Error "error") (Int32 1)) // In this case, cardinality has gone from More to One Debug.Assert(newType.IsSubtypeOf(XmlQueryTypeFactory.AtMost(oldType, oldType.Cardinality)), "Replace shouldn't relax original type"); node.XmlType = newType; }
//----------------------------------------------- // QilVisitor overrides //----------------------------------------------- protected override QilNode VisitChildren(QilNode parent) { if (this.parents.Contains(parent)) { // We have already visited the node that starts the infinite loop, but don't visit its children SetError(parent, "Infinite loop"); } else if (AddNode(parent)) { if (parent.XmlType == null) { SetError(parent, "Type information missing"); } else { XmlQueryType type = _typeCheck.Check(parent); // BUGBUG: Hack to account for Xslt compiler type fixups if (!type.IsSubtypeOf(parent.XmlType)) { SetError(parent, "Type information was not correctly inferred"); } } this.parents.Add(parent, parent); for (int i = 0; i < parent.Count; i++) { if (parent[i] == null) { // Allow parameter name and default value to be null if (parent.NodeType == QilNodeType.Parameter) { continue; } // Do not allow null anywhere else in the graph else { SetError(parent, "Child " + i + " must not be null"); } } if (parent.NodeType == QilNodeType.GlobalVariableList || parent.NodeType == QilNodeType.GlobalParameterList || parent.NodeType == QilNodeType.FunctionList) { if (((QilReference)parent[i]).DebugName == null) { SetError(parent[i], "DebugName must not be null"); } } // If child is a reference, then call VisitReference instead of Visit in order to avoid circular visits. if (IsReference(parent, i)) { VisitReference(parent[i]); } else { Visit(parent[i]); } } this.parents.Remove(parent); } return(parent); }