/// <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; } }
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; }
/// <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]); } }
private void FlushBuilder() { if (_concat == null) { _concat = _f.BaseFactory.Sequence(); } if (_builder.Length != 0) { _concat.Add(_f.String(_builder.ToString())); _builder.Length = 0; } }
private void FlushBuilder() { if (concat == null) { concat = f.BaseFactory.Sequence(); } if (builder.Length != 0) { concat.Add(f.String(builder.ToString())); builder.Length = 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); }
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); }
/// <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; } }