/// <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; } }
/// <summary> /// Analyze conditional. /// </summary> protected virtual void AnalyzeConditional(QilTernary ndCond, XmlILConstructInfo info) { PossibleXmlStates xstatesTrue; // Ensure that construct method is Writer info.ConstructMethod = XmlILConstructMethod.Writer; // Visit true branch; save resulting states ndCond.Center = AnalyzeContent(ndCond.Center); xstatesTrue = this.xstates; // Restore starting states and visit false branch this.xstates = info.InitialStates; ndCond.Right = AnalyzeContent(ndCond.Right); // Conditional ending states consist of combination of true and false branch states if (xstatesTrue != this.xstates) { this.xstates = PossibleXmlStates.Any; } }