public bool MoveNext() { if (_first) { _first = false; return(true); } if (_stack.Count == 0) { return(false); } var curr = _stack.Pop(); if (curr.HasElementType) { _stack.Push(curr.GetElementType()); return(true); } // Push children in reverse order so they get popped in forward order. var children = curr.GetGenericArguments(); var numChildren = children.Length; for (int i = numChildren - 1; i >= 0; i--) { _stack.Push(children[i]); } return(_stack.Count > 0); }
/// <summary> /// An async-iterator state machine has a flag indicating "dispose mode". /// We enter dispose mode by calling DisposeAsync() when the state machine is paused on a `yield return`. /// DisposeAsync() will resume execution of the state machine from that state (using existing dispatch mechanism /// to restore execution from a given state, without executing other code to get there). /// /// From there, we don't want normal code flow: /// - from `yield return`, we'll jump to the enclosing `finally` (or method exit) /// - after finishing a `finally`, we'll jump to the next enclosing `finally` (or method exit) /// /// Some `finally` clauses may have already been rewritten and extracted to a plain block (<see cref="AsyncExceptionHandlerRewriter"/>). /// In those cases, we saved the finally-entry label in <see cref="BoundTryStatement.FinallyLabelOpt"/>. /// </summary> public override BoundNode VisitTryStatement(BoundTryStatement node) { _previousDisposalLabels ??= new ArrayBuilder <LabelSymbol>(); _previousDisposalLabels.Push(_enclosingFinallyEntryOrFinallyExitOrExitLabel); var finallyExit = F.GenerateLabel("finallyExit"); _previousDisposalLabels.Push(finallyExit); if (node.FinallyBlockOpt != null) { var finallyEntry = F.GenerateLabel("finallyEntry"); _enclosingFinallyEntryOrFinallyExitOrExitLabel = finallyEntry; // Add finallyEntry label: // try // { // ... // finallyEntry: // Add finallyExit label: // finally // { // ... // finallyExit: // } node = node.Update( tryBlock: F.Block(node.TryBlock, F.Label(finallyEntry)), node.CatchBlocks, F.Block(node.FinallyBlockOpt, F.Label(finallyExit)), node.FinallyLabelOpt, node.PreferFaultHandler); } else if ((object)node.FinallyLabelOpt != null) { _enclosingFinallyEntryOrFinallyExitOrExitLabel = node.FinallyLabelOpt; } var result = (BoundStatement)base.VisitTryStatement(node); // While inside the try and catch blocks, we'll use the current finallyEntry label for disposal // As soon as we close the try and catch blocks (ie. possibly enter the finally block), we'll use the finallyExit label for disposal (restored/popped from the stack by CloseTryCatchBlocks) Debug.Assert(_enclosingFinallyEntryOrFinallyExitOrExitLabel == finallyExit); // When exiting the try statement, we restore the previous disposal label. _enclosingFinallyEntryOrFinallyExitOrExitLabel = _previousDisposalLabels.Pop(); if (node.FinallyBlockOpt != null) { // Append: // if (disposeMode) /* jump to parent's finally or exit */ result = AppendJumpToCurrentFinallyOrExit(result); } // Note: we add this jump to extracted `finally` blocks as well, using `VisitExtractedFinallyBlock` below return(result); }
internal TResult Invoke <TResult>(object instance, MethodId method, Func <TInterface, TResult> f) { // If the last n - 1 calls are to the same method, // call the n-th implementation. var instanceAndMethod = new InstanceAndMethod(instance, method); int n = _calls.Count; int index = 0; while ((n - index > 0) && _calls[n - index - 1].Equals(instanceAndMethod)) { index++; } if (index == _implementations.Length) { throw new InvalidOperationException(); } var item = _implementations[index]; _calls.Push(instanceAndMethod); try { return(f(item)); } finally { _calls.Pop(); } }
public TypeEnumerator(Type type) { _first = true; _stack = ArrayBuilder <Type> .GetInstance(); _stack.Push(type); }
private static void PushReachableBlockToProcess(ArrayBuilder <BasicBlock> reachableBlocks, BasicBlock block) { if (block.Reachability == Reachability.NotReachable) { reachableBlocks.Push(block); } }
private ScopeTreeBuilder( Scope rootScope, MethodSymbol topLevelMethod, HashSet <MethodSymbol> methodsConvertedToDelegates, DiagnosticBag diagnostics) { Debug.Assert(rootScope != null); Debug.Assert(topLevelMethod != null); Debug.Assert(methodsConvertedToDelegates != null); Debug.Assert(diagnostics != null); _currentScope = rootScope; _labelsInScope.Push(ArrayBuilder <LabelSymbol> .GetInstance()); _topLevelMethod = topLevelMethod; _methodsConvertedToDelegates = methodsConvertedToDelegates; _diagnostics = diagnostics; }
static void pushLeftNodes(BoundBinaryOperator binary, ArrayBuilder <BoundBinaryOperator> stack, TArg arg, Action <BoundBinaryOperator, TArg>?binaryOperatorCallback) { Debug.Assert(typeof(TInterpolatedStringType) == typeof(BoundInterpolatedString) || binary.IsUnconvertedInterpolatedStringAddition); BoundBinaryOperator?current = binary; while (current != null) { binaryOperatorCallback?.Invoke(current, arg); stack.Push(current); current = current.Left as BoundBinaryOperator; } }
private void EmitAllElementInitializersRecursive( ArrayTypeSymbol arrayType, ArrayBuilder <IndexDesc> indices, bool includeConstants ) { var top = indices.Peek(); var inits = top.Initializers; if (IsMultidimensionalInitializer(inits)) { // emit initializers for the less significant indices recursively for (int i = 0; i < inits.Length; i++) { indices.Push( new IndexDesc(i, ((BoundArrayInitialization)inits[i]).Initializers) ); EmitAllElementInitializersRecursive(arrayType, indices, includeConstants); } } else { // leaf case for (int i = 0; i < inits.Length; i++) { var init = inits[i]; if (ShouldEmitInitExpression(includeConstants, init)) { // emit array ref _builder.EmitOpCode(ILOpCode.Dup); Debug.Assert(indices.Count == arrayType.Rank - 1); // emit values of all indices that are in progress foreach (var row in indices) { _builder.EmitIntConstant(row.Index); } // emit the leaf index _builder.EmitIntConstant(i); var initExpr = inits[i]; EmitExpression(initExpr, true); EmitArrayElementStore(arrayType, init.Syntax); } } } indices.Pop(); }
public TwoEnumeratorListStack(SyntaxNode startingNode, Func <SyntaxNode, bool>?descendIntoChildren) { _nodeStack = new ChildSyntaxListEnumeratorStack(startingNode, descendIntoChildren); _triviaStack = new TriviaListEnumeratorStack(); if (_nodeStack.IsNotEmpty) { _discriminatorStack = ArrayBuilder <Which> .GetInstance(); _discriminatorStack.Push(Which.Node); } else { _discriminatorStack = null; } }
private void EmitMultidimensionalElementInitializers(ArrayTypeSymbol arrayType, ImmutableArray<BoundExpression> inits, bool includeConstants) { // Using a List for the stack instead of the framework Stack because IEnumerable from Stack is top to bottom. // This algorithm requires the IEnumerable to be from bottom to top. See extensions for List in CollectionExtensions.vb. var indices = new ArrayBuilder<IndexDesc>(); // emit initializers for all values of the leftmost index. for (int i = 0; i < inits.Length; i++) { indices.Push(new IndexDesc(i, ((BoundArrayInitialization)inits[i]).Initializers)); EmitAllElementInitializersRecursive(arrayType, indices, includeConstants); } Debug.Assert(!indices.Any()); }
// Bucketing algorithm: // Start with empty stack of buckets. // While there are still labels // If bucket from remaining labels is dense // Create a newBucket from remaining labels // Else // Create a singleton newBucket from the next label // While the top bucket on stack can be merged with newBucket into a dense bucket // merge top bucket on stack into newBucket, and pop bucket from stack // End While // Push newBucket on stack // End While private ImmutableArray <SwitchBucket> GenerateSwitchBuckets(int startLabelIndex, int endLabelIndex) { Debug.Assert(startLabelIndex >= 0 && startLabelIndex <= endLabelIndex); Debug.Assert(_sortedCaseLabels.Length > endLabelIndex); // Start with empty stack of buckets. ArrayBuilder <SwitchBucket> switchBucketsStack = ArrayBuilder <SwitchBucket> .GetInstance(); int curStartLabelIndex = startLabelIndex; // While there are still labels while (curStartLabelIndex <= endLabelIndex) { SwitchBucket newBucket = CreateNextBucket(curStartLabelIndex, endLabelIndex); // While the top bucket on stack can be merged with newBucket into a dense bucket // merge top bucket on stack into newBucket, and pop bucket from stack // End While while (!switchBucketsStack.IsEmpty()) { // get the bucket at top of the stack SwitchBucket prevBucket = switchBucketsStack.Peek(); if (newBucket.TryMergeWith(prevBucket)) { // pop the previous bucket from the stack switchBucketsStack.Pop(); } else { // merge failed break; } } // Push newBucket on stack switchBucketsStack.Push(newBucket); // update curStartLabelIndex curStartLabelIndex++; } Debug.Assert(!switchBucketsStack.IsEmpty()); // crumble leaf buckets into degenerate buckets where possible ArrayBuilder <SwitchBucket> crumbled = ArrayBuilder <SwitchBucket> .GetInstance(); foreach (SwitchBucket uncrumbled in switchBucketsStack) { int degenerateSplit = uncrumbled.DegenerateBucketSplit; switch (degenerateSplit) { case -1: // cannot be split crumbled.Add(uncrumbled); break; case 0: // already degenerate crumbled.Add(new SwitchBucket(_sortedCaseLabels, uncrumbled.StartLabelIndex, uncrumbled.EndLabelIndex, isDegenerate: true)); break; default: // can split crumbled.Add(new SwitchBucket(_sortedCaseLabels, uncrumbled.StartLabelIndex, degenerateSplit - 1, isDegenerate: true)); crumbled.Add(new SwitchBucket(_sortedCaseLabels, degenerateSplit, uncrumbled.EndLabelIndex, isDegenerate: true)); break; } } switchBucketsStack.Free(); return(crumbled.ToImmutableAndFree()); }
/// <summary> /// Emits all initializers that match indices on the stack recursively. /// /// Example: /// if array has [0..2, 0..3, 0..2] shape /// and we have {1, 2} indices on the stack /// initializers for /// [1, 2, 0] /// [1, 2, 1] /// [1, 2, 2] /// /// will be emitted and the top index will be pushed off the stack /// as at that point we would be completely done with emitting initializers /// corresponding to that index. /// </summary> private void EmitAllElementInitializersRecursive(ArrayTypeSymbol arrayType, ArrayBuilder<IndexDesc> indices, bool includeConstants) { var top = indices.Peek(); var inits = top.Initializers; if (IsMultidimensionalInitializer(inits)) { // emit initializers for the less significant indices recursively for (int i = 0; i < inits.Length; i++) { indices.Push(new IndexDesc(i, ((BoundArrayInitialization)inits[i]).Initializers)); EmitAllElementInitializersRecursive(arrayType, indices, includeConstants); } } else { // leaf case for (int i = 0; i < inits.Length; i++) { var init = inits[i]; if (ShouldEmitInitExpression(includeConstants, init)) { // emit array ref _builder.EmitOpCode(ILOpCode.Dup); Debug.Assert(indices.Count == arrayType.Rank - 1); // emit values of all indices that are in progress foreach (var row in indices) { _builder.EmitIntConstant(row.Index); } // emit the leaf index _builder.EmitIntConstant(i); var initExpr = inits[i]; EmitExpression(initExpr, true); EmitArrayElementStore(arrayType, init.Syntax); } } } indices.Pop(); }
private void EmitMultidimensionalElementInitializers(ArrayTypeSymbol arrayType, ImmutableArray<BoundExpression> inits, bool includeConstants) { // Using a List for the stack instead of the framework Stack because IEnumerable from Stack is top to bottom. // This algorithm requires the IEnumerable to be from bottom to top. See extensions for List in CollectionExtensions.vb. var indices = new ArrayBuilder<IndexDesc>(); // emit initializers for all values of the leftmost index. for (int i = 0; i < inits.Length; i++) { indices.Push(new IndexDesc(i, ((BoundArrayInitialization)inits[i]).Initializers)); EmitAllElementInitializersRecursive(arrayType, indices, includeConstants); } Debug.Assert(!indices.Any()); }
private static void PushReachableBlockToProcess(ArrayBuilder<BasicBlock> reachableBlocks, BasicBlock block) { if (block.Reachability == Reachability.NotReachable) { reachableBlocks.Push(block); } }
public TypeEnumerator(Type type) { _first = true; _stack = ArrayBuilder<Type>.GetInstance(); _stack.Push(type); }
public ThreeEnumeratorListStack(SyntaxNode startingNode, Func<SyntaxNode, bool> descendIntoChildren) { _nodeStack = new ChildSyntaxListEnumeratorStack(startingNode, descendIntoChildren); _triviaStack = new TriviaListEnumeratorStack(); if (_nodeStack.IsNotEmpty) { _tokenStack = ArrayBuilder<SyntaxNodeOrToken>.GetInstance(); _discriminatorStack = ArrayBuilder<Which>.GetInstance(); _discriminatorStack.Push(Which.Node); } else { _tokenStack = null; _discriminatorStack = null; } }
public void Push(T0 value) { stack0.Push(value); discriminatorStack.Push(Discriminator.Value0); }
public void Push(ref T2 value) { stack2.Push(value); discriminatorStack.Push(Discriminator.Value2); }
public void Push(T1 value) { stack1.Push(value); discriminatorStack.Push(Discriminator.Value1); }