示例#1
0
            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);
        }
示例#3
0
            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();
                }
            }
示例#4
0
            public TypeEnumerator(Type type)
            {
                _first = true;
                _stack = ArrayBuilder <Type> .GetInstance();

                _stack.Push(type);
            }
示例#5
0
 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;
                }
示例#7
0
            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;
                }
            }
示例#8
0
        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());
        }
示例#12
0
        /// <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();
        }
示例#13
0
        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());
        }
示例#14
0
 private static void PushReachableBlockToProcess(ArrayBuilder<BasicBlock> reachableBlocks, BasicBlock block)
 {
     if (block.Reachability == Reachability.NotReachable)
     {
         reachableBlocks.Push(block);
     }
 }
示例#15
0
 public TypeEnumerator(Type type)
 {
     _first = true;
     _stack = ArrayBuilder<Type>.GetInstance();
     _stack.Push(type);
 }
示例#16
0
 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;
     }
 }
示例#17
0
 public void Push(T0 value)
 {
     stack0.Push(value);
     discriminatorStack.Push(Discriminator.Value0);
 }
示例#18
0
 public void Push(ref T2 value)
 {
     stack2.Push(value);
     discriminatorStack.Push(Discriminator.Value2);
 }
示例#19
0
 public void Push(T1 value)
 {
     stack1.Push(value);
     discriminatorStack.Push(Discriminator.Value1);
 }