/// <summary>
        /// Recursively analyze the definition of a function.
        /// </summary>
        private static void AnalyzeDefinition(QilNode nd)
        {
            Debug.Assert(XmlILConstructInfo.Read(nd).PushToWriterLast,
                         "Only need to analyze expressions which will be compiled in push mode.");

            switch (nd.NodeType)
            {
            case QilNodeType.Invoke:
                // Invoke node can either be compiled as IteratorThenWriter, or Writer.
                // Since IteratorThenWriter involves caching the results of the function call
                // and iterating over them, .tailcall cannot be used
                if (XmlILConstructInfo.Read(nd).ConstructMethod == XmlILConstructMethod.Writer)
                {
                    OptimizerPatterns.Write(nd).AddPattern(OptimizerPatternName.TailCall);
                }
                break;

            case QilNodeType.Loop: {
                // Recursively analyze Loop return value
                QilLoop ndLoop = (QilLoop)nd;
                if (ndLoop.Variable.NodeType == QilNodeType.Let || !ndLoop.Variable.Binding.XmlType.MaybeMany)
                {
                    AnalyzeDefinition(ndLoop.Body);
                }
                break;
            }

            case QilNodeType.Sequence: {
                // Recursively analyze last expression in Sequence
                QilList ndSeq = (QilList)nd;
                if (ndSeq.Count > 0)
                {
                    AnalyzeDefinition(ndSeq[ndSeq.Count - 1]);
                }
                break;
            }

            case QilNodeType.Choice: {
                // Recursively analyze Choice branches
                QilChoice ndChoice = (QilChoice)nd;
                for (int i = 0; i < ndChoice.Branches.Count; i++)
                {
                    AnalyzeDefinition(ndChoice.Branches[i]);
                }
                break;
            }

            case QilNodeType.Conditional: {
                // Recursively analyze Conditional branches
                QilTernary ndCond = (QilTernary)nd;
                AnalyzeDefinition(ndCond.Center);
                AnalyzeDefinition(ndCond.Right);
                break;
            }

            case QilNodeType.Nop:
                AnalyzeDefinition(((QilUnary)nd).Child);
                break;
            }
        }
Example #2
0
 public void Reset()
 {
     Debug.Assert(!_inUse);
     _inUse          = true;
     _builder.Length = 0;
     _concat         = null;
 }
 public void Reset()
 {
     Debug.Assert(!inUse);
     inUse          = true;
     builder.Length = 0;
     concat         = null;
 }
Example #4
0
        /// <summary>
        /// Analyze list.
        /// </summary>
        protected virtual void AnalyzeSequence(QilList ndSeq, XmlILConstructInfo info)
        {
            // Ensure that construct method is Writer
            info.ConstructMethod = XmlILConstructMethod.Writer;

            // Analyze each item in the list
            for (int idx = 0; idx < ndSeq.Count; idx++)
            {
                ndSeq[idx] = AnalyzeContent(ndSeq[idx]);
            }
        }
Example #5
0
 private void FlushBuilder()
 {
     if (_concat == null)
     {
         _concat = _f.BaseFactory.Sequence();
     }
     if (_builder.Length != 0)
     {
         _concat.Add(_f.String(_builder.ToString()));
         _builder.Length = 0;
     }
 }
Example #6
0
 private void FlushBuilder()
 {
     if (concat == null)
     {
         concat = f.BaseFactory.Sequence();
     }
     if (builder.Length != 0)
     {
         concat.Add(f.String(builder.ToString()));
         builder.Length = 0;
     }
 }
Example #7
0
        private QilNode CompileSingleKey(List <Key> defList, QilIterator key, QilIterator context)
        {
            Debug.Assert(defList != null && defList.Count > 0);
            QilList result = _f.BaseFactory.Sequence();
            QilNode keyRef = null;

            foreach (Key keyDef in defList)
            {
                keyRef = _f.Invoke(keyDef.Function, _f.ActualParameterList(context, key));
                result.Add(keyRef);
            }
            return(defList.Count == 1 ? keyRef : result);
        }
Example #8
0
        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);
        }
Example #9
0
        /// <summary>
        /// Recursively analyze content.  Return "nd" or a replacement for it.
        /// </summary>
        private void AnalyzeContent(QilNode nd)
        {
            int cntNmspSave;

            switch (nd.NodeType)
            {
            case QilNodeType.Loop:
                _addInScopeNmsp = false;
                AnalyzeContent((nd as QilLoop).Body);
                break;

            case QilNodeType.Sequence:
                foreach (QilNode ndContent in nd)
                {
                    AnalyzeContent(ndContent);
                }
                break;

            case QilNodeType.Conditional:
                _addInScopeNmsp = false;
                AnalyzeContent((nd as QilTernary).Center);
                AnalyzeContent((nd as QilTernary).Right);
                break;

            case QilNodeType.Choice:
                _addInScopeNmsp = false;
                QilList ndBranches = (nd as QilChoice).Branches;
                for (int idx = 0; idx < ndBranches.Count; idx++)
                {
                    AnalyzeContent(ndBranches[idx]);
                }

                break;

            case QilNodeType.ElementCtor:
                // Start a new namespace scope
                _addInScopeNmsp = true;
                _nsmgr.PushScope();
                cntNmspSave = _cntNmsp;

                if (CheckNamespaceInScope(nd as QilBinary))
                {
                    AnalyzeContent((nd as QilBinary).Right);
                }

                _nsmgr.PopScope();
                _addInScopeNmsp = false;
                _cntNmsp        = cntNmspSave;
                break;

            case QilNodeType.AttributeCtor:
                _addInScopeNmsp = false;
                CheckNamespaceInScope(nd as QilBinary);
                break;

            case QilNodeType.NamespaceDecl:
                CheckNamespaceInScope(nd as QilBinary);
                break;

            case QilNodeType.Nop:
                AnalyzeContent((nd as QilUnary).Child);
                break;

            default:
                _addInScopeNmsp = false;
                break;
            }
        }