//----------------------------------------------- // 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 QilNode GenerateInvoke(QilFunction func, IList<XslNode> actualArgs) { _iterStack.Clear(); _formalArgs = func.Arguments; _invokeArgs = _fac.ActualParameterList(); // curArg is an instance variable used in Clone() method for (_curArg = 0; _curArg < _formalArgs.Count; _curArg++) { // Find actual value for a given formal arg QilParameter formalArg = (QilParameter)_formalArgs[_curArg]; QilNode invokeArg = FindActualArg(formalArg, actualArgs); // If actual value was not specified, use the default value and copy its debug comment if (invokeArg == null) { if (_debug) { if (formalArg.Name.NamespaceUri == XmlReservedNs.NsXslDebug) { Debug.Assert(formalArg.Name.LocalName == "namespaces", "Cur,Pos,Last don't have default values and should be always added to by caller in AddImplicitArgs()"); Debug.Assert(formalArg.DefaultValue != null, "PrecompileProtoTemplatesHeaders() set it"); invokeArg = Clone(formalArg.DefaultValue); } else { invokeArg = _fac.DefaultValueMarker(); } } else { Debug.Assert(formalArg.Name.NamespaceUri != XmlReservedNs.NsXslDebug, "Cur,Pos,Last don't have default values and should be always added to by caller in AddImplicitArgs(). We don't have $namespaces in !debug."); invokeArg = Clone(formalArg.DefaultValue); } } XmlQueryType formalType = formalArg.XmlType; XmlQueryType invokeType = invokeArg.XmlType; // Possible arg types: anyType, node-set, string, boolean, and number _fac.CheckXsltType(formalArg); _fac.CheckXsltType(invokeArg); if (!invokeType.IsSubtypeOf(formalType)) { // This may occur only if inferred type of invokeArg is XslFlags.None Debug.Assert(invokeType == T.ItemS, "Actual argument type is not a subtype of formal argument type"); invokeArg = _fac.TypeAssert(invokeArg, formalType); } _invokeArgs.Add(invokeArg); } // Create Invoke node and wrap it with previous parameter declarations QilNode invoke = _fac.Invoke(func, _invokeArgs); while (_iterStack.Count != 0) invoke = _fac.Loop(_iterStack.Pop(), invoke); return invoke; }
//----------------------------------------------- // function definition and invocation //----------------------------------------------- public QilFunction Function(QilNode arguments, QilNode definition, QilNode sideEffects, XmlQueryType xmlType) { QilFunction n = new QilFunction(QilNodeType.Function, arguments, definition, sideEffects, xmlType); n.XmlType = this.typeCheck.CheckFunction(n); TraceNode(n); return(n); }
public QilNode Invoke(QilFunction func, QilList args) { Debug.Assert(args.NodeType == QilNodeType.ActualParameterList); Debug.Assert(func.Arguments.Count == args.Count); return f.Invoke(func, args); }
public QilNode Invoke(QilFunction func, QilList args) { Debug.Assert(args.NodeType == QilNodeType.ActualParameterList); Debug.Assert(func.Arguments.Count == args.Count); return(_f.Invoke(func, args)); }
//----------------------------------------------- // 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; }
protected virtual QilNode VisitFunctionReference(QilFunction n) { return n; }
protected virtual QilNode VisitFunction(QilFunction n) { return VisitChildren(n); }
/// <summary> /// Generate code for the specified function. /// </summary> private void Function(QilFunction ndFunc) { MethodInfo methFunc; int paramId; IteratorDescriptor iterInfo; bool useWriter; // Annotate each function parameter with a IteratorDescriptor foreach (QilIterator iter in ndFunc.Arguments) { Debug.Assert(iter.NodeType == QilNodeType.Parameter); // Create an IteratorDescriptor for this parameter iterInfo = new IteratorDescriptor(_helper); // Add one to parameter index, as 0th parameter is always "this" paramId = XmlILAnnotation.Write(iter).ArgumentPosition + 1; // The ParameterInfo for each argument should be set as its location iterInfo.Storage = StorageDescriptor.Parameter(paramId, GetItemStorageType(iter), !iter.XmlType.IsSingleton); // Associate IteratorDescriptor with Let iterator XmlILAnnotation.Write(iter).CachedIteratorDescriptor = iterInfo; } methFunc = XmlILAnnotation.Write(ndFunc).FunctionBinding; useWriter = (XmlILConstructInfo.Read(ndFunc).ConstructMethod == XmlILConstructMethod.Writer); // Generate query code from QilExpression tree _helper.MethodBegin(methFunc, ndFunc.SourceLine, useWriter); foreach (QilIterator iter in ndFunc.Arguments) { // DebugInfo: Sequence point just before generating code for the bound expression if (_qil.IsDebug && iter.SourceLine != null) _helper.DebugSequencePoint(iter.SourceLine); // Calculate default value of this parameter if (iter.Binding != null) { Debug.Assert(iter.XmlType == TypeFactory.ItemS, "IlGen currently only supports default values in parameters of type item*."); paramId = (iter.Annotation as XmlILAnnotation).ArgumentPosition + 1; // runtime.MatchesXmlType(param, XmlTypeCode.QName); Label lblLocalComputed = _helper.DefineLabel(); _helper.LoadQueryRuntime(); _helper.LoadParameter(paramId); _helper.LoadInteger((int)XmlTypeCode.QName); _helper.Call(XmlILMethods.SeqMatchesCode); _helper.Emit(OpCodes.Brfalse, lblLocalComputed); // Compute default value of this parameter StartNestedIterator(iter); NestedVisitEnsureStack(iter.Binding, GetItemStorageType(iter), /*isCached:*/!iter.XmlType.IsSingleton); EndNestedIterator(iter); _helper.SetParameter(paramId); _helper.MarkLabel(lblLocalComputed); } } StartNestedIterator(ndFunc); // If function did not push results to writer, then function will return value(s) (rather than void) if (useWriter) NestedVisit(ndFunc.Definition); else NestedVisitEnsureStack(ndFunc.Definition, GetItemStorageType(ndFunc), !ndFunc.XmlType.IsSingleton); EndNestedIterator(ndFunc); _helper.MethodEnd(); }
protected override QilNode VisitFunctionReference(QilFunction n) { return NoReplace(n); }
protected override QilNode VisitFunction(QilFunction n) { // No need to change function references return n; }
protected override QilNode VisitFunctionReference(QilFunction n) { return(NoReplace(n)); }
// ----------------- use-attribute-sets, call-templates, apply-templates, apply-imports ----------------------------- // private QilNode GenerateCall(QilFunction func, XslNode node) { Debug.Assert( node.NodeType == XslNodeType.CallTemplate || node.NodeType == XslNodeType.UseAttributeSet ); AddImplicitArgs(node); return invkGen.GenerateInvoke(func, node.Content); }
protected override QilNode VisitFunction(QilFunction local0) { QilNode local1 = local0[0]; QilNode local2 = local0[1]; QilNode local3 = local0[2]; XmlQueryType local4 = (XmlQueryType)((QilFunction)local0).XmlType; if (( (local0).XmlType .IsSubtypeOf( XmlQueryTypeFactory.NodeS ) ) && (this[XmlILOptimization.AnnotateIndex1])) { if ((( local1.Count == 2 ) && ( ( (QilNode) (local1)[0] ).XmlType .IsSubtypeOf( XmlQueryTypeFactory.Node ) )) && ( ( ( (QilNode) (local1)[1] ).XmlType ) == ( XmlQueryTypeFactory.StringX ) )) { if (local2.NodeType == QilNodeType.Filter) { QilNode local5 = local2[0]; QilNode local7 = local2[1]; if (local5.NodeType == QilNodeType.For) { QilNode local6 = local5[0]; if (local7.NodeType == QilNodeType.Not) { QilNode local8 = local7[0]; if (local8.NodeType == QilNodeType.IsEmpty) { QilNode local9 = local8[0]; if (local9.NodeType == QilNodeType.Filter) { QilNode local10 = local9[0]; QilNode local12 = local9[1]; if (local10.NodeType == QilNodeType.For) { QilNode local11 = local10[0]; if (local12.NodeType == QilNodeType.Eq) { QilNode local13 = local12[0]; QilNode local14 = local12[1]; if (local13 == local10) { if (local14.NodeType == QilNodeType.Parameter) { if ( (local14) == ( (QilNode) (local1)[1] ) ) { if (AllowReplace(XmlILOptimization.AnnotateIndex1, local0)) { // The following conditions must be true for this pattern to match: // 1. The function must have exactly two arguments // 2. The type of the first argument must be a subtype of Node // 3. The type of the second argument must be String // 4. The return type must be a subtype of Node* // 5. Every reference to $args[0] (context document) must be wrapped in an (Root *) function // 6. $keyParam cannot be used with the $bindingNodes and $bindingKeys expressions EqualityIndexVisitor visitor = new EqualityIndexVisitor(); if (visitor.Scan(local6, local1[0], local14) && visitor.Scan(local11, local1[0], local14)) { // All conditions were true, so annotate Filter with the EqualityIndex pattern OptimizerPatterns patt = OptimizerPatterns.Write(local2); patt.AddPattern(OptimizerPatternName.EqualityIndex); patt.AddArgument(OptimizerPatternArgument.IndexedNodes, local5); patt.AddArgument(OptimizerPatternArgument.KeyExpression, local11); } } } } } } } } } } } } } } if (this[XmlILOptimization.AnnotateIndex2]) { if ((( local1.Count == 2 ) && ( ( ( (QilNode) (local1)[0] ).XmlType ) == ( XmlQueryTypeFactory.Node ) )) && ( ( ( (QilNode) (local1)[1] ).XmlType ) == ( XmlQueryTypeFactory.StringX ) )) { if (local2.NodeType == QilNodeType.Filter) { QilNode local5 = local2[0]; QilNode local7 = local2[1]; if (local5.NodeType == QilNodeType.For) { QilNode local6 = local5[0]; if (local7.NodeType == QilNodeType.Eq) { QilNode local8 = local7[0]; QilNode local9 = local7[1]; if (local9.NodeType == QilNodeType.Parameter) { if ( (local9) == ( (QilNode) (local1)[1] ) ) { if (AllowReplace(XmlILOptimization.AnnotateIndex2, local0)) { // Same as EqualityIndex1, except that each nodes has at most one key value EqualityIndexVisitor visitor = new EqualityIndexVisitor(); if (visitor.Scan(local6, local1[0], local9) && visitor.Scan(local8, local1[0], local9)) { // All conditions were true, so annotate Filter with the EqualityIndex pattern OptimizerPatterns patt = OptimizerPatterns.Write(local2); patt.AddPattern(OptimizerPatternName.EqualityIndex); patt.AddArgument(OptimizerPatternArgument.IndexedNodes, local5); patt.AddArgument(OptimizerPatternArgument.KeyExpression, local8); } } } } } } } } } return NoReplace(local0); }
//----------------------------------------------- // function definition and invocation //----------------------------------------------- public QilFunction Function(QilNode arguments, QilNode definition, QilNode sideEffects, XmlQueryType xmlType) { QilFunction n = new QilFunction(QilNodeType.Function, arguments, definition, sideEffects, xmlType); n.XmlType = this.typeCheck.CheckFunction(n); TraceNode(n); return n; }
protected virtual QilNode VisitFunction(QilFunction n) { return(VisitChildren(n)); }
protected virtual QilNode VisitFunctionReference(QilFunction n) { return(n); }
protected override QilNode VisitFunction(QilFunction n) { return NoReplace(n); }