InvokeGenerator.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / XmlUtils / System / Xml / Xsl / Xslt / InvokeGenerator.cs / 1305376 / InvokeGenerator.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
//-----------------------------------------------------------------------------
 
using System.Collections.Generic; 
using System.Diagnostics;
using System.Xml.Xsl.Qil; 

namespace System.Xml.Xsl.Xslt {
    using T = XmlQueryTypeFactory;
 
    /**
    InvokeGenerator is one of the trikest peaces here. 
    ARGS: 
         QilFunction func      -- Functions which should be invoked. Arguments of this function (formalArgs) are Let nodes
                                  anotated with names and default valies. 
                                  Problem 1 is that default values can contain references to previouse args of this function.
                                  Problem 2 is that default values shouldn't contain fixup nodes.
         ArrayList actualArgs  -- Array of QilNodes anotated with names. When name of formalArg match name actualArg last one
                                  is used as invokeArg, otherwise formalArg's default value is cloned and used. 
    **/
 
    internal class InvokeGenerator : QilCloneVisitor { 
        private bool                debug;
        private Stack  iterStack; 

        private QilList             formalArgs;
        private QilList             invokeArgs;
        private int                 curArg;     // this.Clone() depends on this value 

        private XsltQilFactory      fac; 
 
        public InvokeGenerator(XsltQilFactory f, bool debug) : base(f.BaseFactory) {
            this.debug  = debug; 
            this.fac    = f;
            this.iterStack = new Stack();
        }
 
        public QilNode GenerateInvoke(QilFunction func, IList 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;
        } 

        private QilNode FindActualArg(QilParameter formalArg, IList actualArgs) {
            QilName argName = formalArg.Name;
            Debug.Assert(argName != null); 
            foreach (XslNode actualArg in actualArgs) {
                if (actualArg.Name.Equals(argName)) { 
                    return ((VarPar)actualArg).Value; 
                }
            } 
            return null;
        }

        // ------------------------------------ QilCloneVisitor ------------------------------------- 

        protected override QilNode VisitReference(QilNode n) { 
            QilNode replacement = FindClonedReference(n); 

            // If the reference is internal for the subtree being cloned, return it as is 
            if (replacement != null) {
                return replacement;
            }
 
            // Replacement was not found, thus the reference is external for the subtree being cloned.
            // The case when it refers to one of previous arguments (xsl:param can refer to previous 
            // xsl:param's) must be taken care of. 
            for (int prevArg = 0; prevArg < curArg; prevArg++) {
                Debug.Assert(formalArgs[prevArg] != null, "formalArg must be in the list"); 
                Debug.Assert(invokeArgs[prevArg] != null, "This arg should be compiled already");

                // Is this a reference to prevArg?
                if (n == formalArgs[prevArg]) { 
                    // If prevArg is a literal, just clone it
                    if (invokeArgs[prevArg] is QilLiteral) { 
                        return invokeArgs[prevArg].ShallowClone(fac.BaseFactory); 
                    }
 
                    // If prevArg is not an iterator, cache it in an iterator, and return it
                    if (!(invokeArgs[prevArg] is QilIterator)) {
                        QilIterator var = fac.BaseFactory.Let(invokeArgs[prevArg]);
                        iterStack.Push(var); 
                        invokeArgs[prevArg] = var;
                    } 
                    Debug.Assert(invokeArgs[prevArg] is QilIterator); 
                    return invokeArgs[prevArg];
                } 
            }

            // This is a truly external reference, return it as is
            return n; 
        }
 
        protected override QilNode VisitFunction(QilFunction n) { 
            // No need to change function references
            return n; 
        }
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK