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;
}