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

VisitIsEmpty() protected method

Generate code for QilNodeType.IsEmpty.
BranchingContext.OnFalse context: is-empty(expr) ==> foreach (item in expr) goto LabelBranch; BranchingContext.OnTrue context: is-empty(expr) ==> foreach (item in expr) break; ... LabelOnEnd: (called if foreach is empty) goto LabelBranch; BranchingContext.None context: is-empty(expr) ==> foreach (item in expr) break; push true(); ... LabelOnEnd: (called if foreach is empty) push false();
protected VisitIsEmpty ( QilUnary ndIsEmpty ) : QilNode
ndIsEmpty System.Xml.Xsl.Qil.QilUnary
return QilNode
        protected override QilNode VisitIsEmpty(QilUnary ndIsEmpty) {
            Label lblTrue;

            // If the child expression returns a cached result,
            if (CachesResult(ndIsEmpty.Child)) {
                // Then get the count directly from the cache
                NestedVisitEnsureStack(ndIsEmpty.Child);
                this.helper.CallCacheCount(this.iterNested.Storage.ItemStorageType);

                switch (this.iterCurr.CurrentBranchingContext) {
                    case BranchingContext.OnFalse:
                        // Take false path if count != 0
                        this.helper.TestAndBranch(0, this.iterCurr.LabelBranch, OpCodes.Bne_Un);
                        break;

                    case BranchingContext.OnTrue:
                        // Take true path if count == 0
                        this.helper.TestAndBranch(0, this.iterCurr.LabelBranch, OpCodes.Beq);
                        break;

                    default:
                        Debug.Assert(this.iterCurr.CurrentBranchingContext == BranchingContext.None);

                        // if (count == 0) goto LabelTrue;
                        lblTrue = this.helper.DefineLabel();
                        this.helper.Emit(OpCodes.Brfalse_S, lblTrue);

                        // Convert branch targets into push of true/false
                        this.helper.ConvBranchToBool(lblTrue, true);
                        break;
                }
            }
            else {
                Label lblOnEnd = this.helper.DefineLabel();
                IteratorDescriptor iterParent = this.iterCurr;

                // Forward any LabelOnEnd jumps to LabelBranch if BranchingContext.OnTrue
                if (iterParent.CurrentBranchingContext == BranchingContext.OnTrue)
                    StartNestedIterator(ndIsEmpty.Child, this.iterCurr.LabelBranch);
                else
                    StartNestedIterator(ndIsEmpty.Child, lblOnEnd);

                Visit(ndIsEmpty.Child);

                // Pop value of IsEmpty expression from the stack if necessary
                this.iterCurr.EnsureNoCache();
                this.iterCurr.DiscardStack();

                switch (iterParent.CurrentBranchingContext) {
                    case BranchingContext.OnFalse:
                        // Reverse polarity of iterator
                        this.helper.EmitUnconditionalBranch(OpCodes.Br, iterParent.LabelBranch);
                        this.helper.MarkLabel(lblOnEnd);
                        break;

                    case BranchingContext.OnTrue:
                        // Nothing to do
                        break;

                    case BranchingContext.None:
                        // Convert branch targets into push of true/false
                        this.helper.ConvBranchToBool(lblOnEnd, true);
                        break;
                }

                // End nested iterator
                EndNestedIterator(ndIsEmpty.Child);
            }

            if (this.iterCurr.IsBranching)
                this.iterCurr.Storage = StorageDescriptor.None();
            else
                this.iterCurr.Storage = StorageDescriptor.Stack(typeof(bool), false);

            return ndIsEmpty;
        }
XmlILVisitor