System.Xml.Xsl.IlGen.XmlILVisitor.CreateSetIterator C# (CSharp) Method

CreateSetIterator() private method

Generate code to combine nodes from two nested iterators using Union, Intersection, or Difference semantics.
private CreateSetIterator ( QilBinary ndSet, string iterName, Type iterType, MethodInfo methCreate, MethodInfo methNext ) : QilNode
ndSet System.Xml.Xsl.Qil.QilBinary
iterName string
iterType System.Type
methCreate System.Reflection.MethodInfo
methNext System.Reflection.MethodInfo
return QilNode
        private QilNode CreateSetIterator(QilBinary ndSet, string iterName, Type iterType, MethodInfo methCreate, MethodInfo methNext) {
            LocalBuilder locIter, locNav;
            Label lblNext, lblCall, lblNextLeft, lblNextRight, lblInitRight;

            // SetIterator iterSet;
            // XPathNavigator navSet;
            locIter = this.helper.DeclareLocal(iterName, iterType);
            locNav = this.helper.DeclareLocal("$$$navSet", typeof(XPathNavigator));

            // iterSet.Create(runtime);
            this.helper.Emit(OpCodes.Ldloca, locIter);
            this.helper.LoadQueryRuntime();
            this.helper.Call(methCreate);

            // Define labels that will be used
            lblNext = this.helper.DefineLabel();
            lblCall = this.helper.DefineLabel();
            lblInitRight = this.helper.DefineLabel();

            // Generate left nested iterator.  When it is empty, it will branch to lblNext.
            // goto LabelCall;
            NestedVisit(ndSet.Left, lblNext);
            lblNextLeft = this.iterNested.GetLabelNext();
            this.iterCurr.EnsureLocal(locNav);
            this.helper.EmitUnconditionalBranch(OpCodes.Brtrue, lblCall);

            // Generate right nested iterator.  When it is empty, it will branch to lblNext.
            // LabelInitRight:
            // goto LabelCall;
            this.helper.MarkLabel(lblInitRight);
            NestedVisit(ndSet.Right, lblNext);
            lblNextRight = this.iterNested.GetLabelNext();
            this.iterCurr.EnsureLocal(locNav);
            this.helper.EmitUnconditionalBranch(OpCodes.Brtrue, lblCall);

            // LabelNext:
            this.helper.MarkLabel(lblNext);
            this.helper.Emit(OpCodes.Ldnull);
            this.helper.Emit(OpCodes.Stloc, locNav);

            // LabelCall:
            // switch (iterSet.MoveNext(nestedNested)) {
            //      case SetIteratorResult.NoMoreNodes: goto LabelNextCtxt;
            //      case SetIteratorResult.InitRightIterator: goto LabelInitRight;
            //      case SetIteratorResult.NeedLeftNode: goto LabelNextLeft;
            //      case SetIteratorResult.NeedRightNode: goto LabelNextRight;
            // }
            this.helper.MarkLabel(lblCall);
            this.helper.Emit(OpCodes.Ldloca, locIter);
            this.helper.Emit(OpCodes.Ldloc, locNav);
            this.helper.Call(methNext);

            // If this iterator always returns a single node, then NoMoreNodes will never be returned
            // Don't expose Next label if this iterator always returns a single node
            if (ndSet.XmlType.IsSingleton) {
                this.helper.Emit(OpCodes.Switch, new Label[] {lblInitRight, lblNextLeft, lblNextRight});
                this.iterCurr.Storage = StorageDescriptor.Current(locIter, typeof(XPathNavigator));
            }
            else {
                this.helper.Emit(OpCodes.Switch, new Label[] {this.iterCurr.GetLabelNext(), lblInitRight, lblNextLeft, lblNextRight});
                this.iterCurr.SetIterator(lblNext, StorageDescriptor.Current(locIter, typeof(XPathNavigator)));
            }

            return ndSet;
        }
XmlILVisitor