private RegionAnalysisContext RegionAnalysisContext(
            StatementSyntax firstStatement,
            StatementSyntax lastStatement
            )
        {
            var memberModel = GetMemberModel(firstStatement);

            if (memberModel == null)
            {
                // Recover from error cases
                var node = new BoundBadStatement(
                    firstStatement,
                    ImmutableArray <BoundNode> .Empty,
                    hasErrors: true
                    );
                return(new RegionAnalysisContext(Compilation, null, node, node, node));
            }

            Symbol    member;
            BoundNode boundNode = GetBoundRoot(memberModel, out member);
            var       first     = memberModel.GetUpperBoundNode(firstStatement, promoteToBindable: true);
            var       last      = memberModel.GetUpperBoundNode(lastStatement, promoteToBindable: true);

            return(new RegionAnalysisContext(Compilation, member, boundNode, first, last));
        }
        private RegionAnalysisContext RegionAnalysisContext(ExpressionSyntax expression)
        {
            while (expression.Kind() == SyntaxKind.ParenthesizedExpression)
            {
                expression = ((ParenthesizedExpressionSyntax)expression).Expression;
            }

            var memberModel = GetMemberModel(expression);

            if (memberModel == null)
            {
                // Recover from error cases
                var node = new BoundBadStatement(
                    expression,
                    ImmutableArray <BoundNode> .Empty,
                    hasErrors: true
                    );
                return(new RegionAnalysisContext(Compilation, null, node, node, node));
            }

            Symbol    member;
            BoundNode boundNode = GetBoundRoot(memberModel, out member);
            var       first     = memberModel.GetUpperBoundNode(expression, promoteToBindable: true);
            var       last      = first;

            return(new RegionAnalysisContext(this.Compilation, member, boundNode, first, last));
        }
        private RegionAnalysisContext RegionAnalysisContext(StatementSyntax firstStatement, StatementSyntax lastStatement)
        {
            var memberModel = GetMemberModel(firstStatement);
            if (memberModel == null)
            {
                // Recover from error cases
                var node = new BoundBadStatement(firstStatement, ImmutableArray<BoundNode>.Empty, hasErrors: true);
                return new RegionAnalysisContext(Compilation, null, node, node, node);
            }

            Symbol member;
            BoundNode boundNode = GetBoundRoot(memberModel, out member);
            var first = memberModel.GetUpperBoundNode(firstStatement, promoteToBindable: true);
            var last = memberModel.GetUpperBoundNode(lastStatement, promoteToBindable: true);
            return new RegionAnalysisContext(Compilation, member, boundNode, first, last);
        }
        private RegionAnalysisContext RegionAnalysisContext(ExpressionSyntax expression)
        {
            while (expression.Kind() == SyntaxKind.ParenthesizedExpression)
                expression = ((ParenthesizedExpressionSyntax)expression).Expression;

            var memberModel = GetMemberModel(expression);
            if (memberModel == null)
            {
                // Recover from error cases
                var node = new BoundBadStatement(expression, ImmutableArray<BoundNode>.Empty, hasErrors: true);
                return new RegionAnalysisContext(Compilation, null, node, node, node);
            }

            Symbol member;
            BoundNode boundNode = GetBoundRoot(memberModel, out member);
            var first = memberModel.GetUpperBoundNode(expression, promoteToBindable: true);
            var last = first;
            return new RegionAnalysisContext(this.Compilation, member, boundNode, first, last);
        }
        /// <summary>
        /// In script C#, some field initializers are assignments to fields and others are global
        /// statements.  There are no restrictions on accessing instance members.
        /// </summary>
        private static void BindScriptFieldInitializers(CSharpCompilation compilation, MethodSymbol scriptCtor,
                                                        ImmutableArray <ImmutableArray <FieldOrPropertyInitializer> > initializers, ArrayBuilder <BoundInitializer> boundInitializers, DiagnosticBag diagnostics,
                                                        out ImportChain firstDebugImports)
        {
            Debug.Assert((object)scriptCtor != null);

            firstDebugImports = null;

            for (int i = 0; i < initializers.Length; i++)
            {
                ImmutableArray <FieldOrPropertyInitializer> siblingInitializers = initializers[i];

                // All sibling initializers share the same parent node and tree so we can reuse the binder
                // factory across siblings.  Unfortunately, we cannot reuse the binder itself, because
                // individual fields might have their own binders (e.g. because of being declared unsafe).
                BinderFactory binderFactory = null;

                for (int j = 0; j < siblingInitializers.Length; j++)
                {
                    var initializer = siblingInitializers[j];
                    var fieldSymbol = initializer.FieldOpt;

                    if ((object)fieldSymbol != null && fieldSymbol.IsConst)
                    {
                        // Constants do not need field initializers.
                        continue;
                    }

                    var syntaxRef = initializer.Syntax;
                    Debug.Assert(syntaxRef.SyntaxTree.Options.Kind != SourceCodeKind.Regular);

                    var initializerNode = (CSharpSyntaxNode)syntaxRef.GetSyntax();

                    if (binderFactory == null)
                    {
                        binderFactory = compilation.GetBinderFactory(syntaxRef.SyntaxTree);
                    }

                    Binder scriptClassBinder = binderFactory.GetBinder(initializerNode);
                    Debug.Assert(((ImplicitNamedTypeSymbol)scriptClassBinder.ContainingMemberOrLambda).IsScriptClass);

                    if (firstDebugImports == null)
                    {
                        firstDebugImports = scriptClassBinder.ImportChain;
                    }

                    Binder parentBinder = new ExecutableCodeBinder((CSharpSyntaxNode)syntaxRef.SyntaxTree.GetRoot(), scriptCtor, scriptClassBinder);

                    BoundInitializer boundInitializer;
                    if ((object)fieldSymbol != null)
                    {
                        boundInitializer = BindFieldInitializer(
                            new LocalScopeBinder(parentBinder).WithAdditionalFlagsAndContainingMemberOrLambda(parentBinder.Flags | BinderFlags.FieldInitializer, fieldSymbol),
                            fieldSymbol,
                            (EqualsValueClauseSyntax)initializerNode,
                            diagnostics);
                    }
                    else if (initializerNode.Kind() == SyntaxKind.LabeledStatement)
                    {
                        // TODO: labels in interactive
                        var boundStatement = new BoundBadStatement(initializerNode, ImmutableArray <BoundNode> .Empty, true);
                        boundInitializer = new BoundGlobalStatementInitializer(initializerNode, boundStatement);
                    }
                    else
                    {
                        var collisionDetector = new LocalScopeBinder(parentBinder);
                        boundInitializer = BindGlobalStatement(collisionDetector, (StatementSyntax)initializerNode, diagnostics,
                                                               isLast: i == initializers.Length - 1 && j == siblingInitializers.Length - 1);
                    }

                    boundInitializers.Add(boundInitializer);
                }
            }
        }
        /// <summary>
        /// In script C#, some field initializers are assignments to fields and others are global
        /// statements.  There are no restrictions on accessing instance members.
        /// </summary>
        private static void BindScriptFieldInitializers(CSharpCompilation compilation, MethodSymbol scriptCtor,
            ImmutableArray<ImmutableArray<FieldInitializer>> initializers, ArrayBuilder<BoundInitializer> boundInitializers, DiagnosticBag diagnostics,
            bool generateDebugInfo, out ConsList<Imports> firstDebugImports)
        {
            Debug.Assert((object)scriptCtor != null);

            firstDebugImports = null;

            for (int i = 0; i < initializers.Length; i++)
            {
                ImmutableArray<FieldInitializer> siblingInitializers = initializers[i];

                // All sibling initializers share the same parent node and tree so we can reuse the binder 
                // factory across siblings.  Unfortunately, we cannot reuse the binder itself, because
                // individual fields might have their own binders (e.g. because of being declared unsafe).
                BinderFactory binderFactory = null;

                for (int j = 0; j < siblingInitializers.Length; j++)
                {
                    var initializer = siblingInitializers[j];
                    var fieldSymbol = initializer.Field;

                    if ((object)fieldSymbol != null && fieldSymbol.IsConst)
                    {
                        // Constants do not need field initializers.
                        continue;
                    }

                    var syntaxRef = initializer.Syntax;
                    Debug.Assert(syntaxRef.SyntaxTree.Options.Kind != SourceCodeKind.Regular);

                    var initializerNode = (CSharpSyntaxNode)syntaxRef.GetSyntax();

                    if (binderFactory == null)
                    {
                        binderFactory = compilation.GetBinderFactory(syntaxRef.SyntaxTree);
                    }

                    Binder scriptClassBinder = binderFactory.GetBinder(initializerNode);
                    Debug.Assert(((ImplicitNamedTypeSymbol)scriptClassBinder.ContainingMemberOrLambda).IsScriptClass);

                    if (generateDebugInfo && firstDebugImports == null)
                    {
                        firstDebugImports = scriptClassBinder.ImportsList;
                    }

                    Binder parentBinder = new ExecutableCodeBinder((CSharpSyntaxNode)syntaxRef.SyntaxTree.GetRoot(), scriptCtor, scriptClassBinder);

                    BoundInitializer boundInitializer;
                    if ((object)fieldSymbol != null)
                    {
                        boundInitializer = BindFieldInitializer(
                            new LocalScopeBinder(parentBinder).WithAdditionalFlagsAndContainingMemberOrLambda(parentBinder.Flags | BinderFlags.FieldInitializer, fieldSymbol),
                            fieldSymbol,
                            (EqualsValueClauseSyntax)initializerNode,
                            diagnostics);
                    }
                    else if (initializerNode.Kind == SyntaxKind.LabeledStatement)
                    {
                        // TODO: labels in interactive
                        var boundStatement = new BoundBadStatement(initializerNode, ImmutableArray<BoundNode>.Empty, true);
                        boundInitializer = new BoundGlobalStatementInitializer(initializerNode, boundStatement);
                    }
                    else
                    {
                        var collisionDetector = new LocalScopeBinder(parentBinder);
                        boundInitializer = BindGlobalStatement(collisionDetector, (StatementSyntax)initializerNode, diagnostics,
                            isLast: i == initializers.Length - 1 && j == siblingInitializers.Length - 1);
                    }

                    boundInitializers.Add(boundInitializer);
                }
            }
        }
        /// <remarks>
        /// Noteworthy override is in MemberSemanticModel.IncrementalBinder (used for caching).
        /// </remarks>
        public virtual BoundStatement BindStatement(StatementSyntax node, DiagnosticBag diagnostics)
        {
            Debug.Assert(node != null);

            BoundStatement result;

            switch (node.Kind())
            {
                case SyntaxKind.Block:
                    result = BindBlock((BlockSyntax)node, diagnostics);
                    break;
                case SyntaxKind.LocalDeclarationStatement:
                    result = BindDeclarationStatement((LocalDeclarationStatementSyntax)node, diagnostics);
                    break;
                case SyntaxKind.ExpressionStatement:
                    result = BindExpressionStatement((ExpressionStatementSyntax)node, diagnostics);
                    break;
                case SyntaxKind.IfStatement:
                    result = BindIfStatement((IfStatementSyntax)node, diagnostics);
                    break;
                case SyntaxKind.SwitchStatement:
                    result = BindSwitchStatement((SwitchStatementSyntax)node, diagnostics);
                    break;
                case SyntaxKind.DoStatement:
                    result = BindDo((DoStatementSyntax)node, diagnostics);
                    break;
                case SyntaxKind.WhileStatement:
                    result = BindWhile((WhileStatementSyntax)node, diagnostics);
                    break;
                case SyntaxKind.ForStatement:
                    result = BindFor((ForStatementSyntax)node, diagnostics);
                    break;
                case SyntaxKind.ForEachStatement:
                    result = BindForEach((ForEachStatementSyntax)node, diagnostics);
                    break;
                case SyntaxKind.BreakStatement:
                    result = BindBreak((BreakStatementSyntax)node, diagnostics);
                    break;
                case SyntaxKind.ContinueStatement:
                    result = BindContinue((ContinueStatementSyntax)node, diagnostics);
                    break;
                case SyntaxKind.ReturnStatement:
                    result = BindReturn((ReturnStatementSyntax)node, diagnostics);
                    break;
                case SyntaxKind.FixedStatement:
                    result = BindFixedStatement((FixedStatementSyntax)node, diagnostics);
                    break;
                case SyntaxKind.LabeledStatement:
                    result = BindLabeled((LabeledStatementSyntax)node, diagnostics);
                    break;
                case SyntaxKind.GotoStatement:
                case SyntaxKind.GotoCaseStatement:
                case SyntaxKind.GotoDefaultStatement:
                    result = BindGoto((GotoStatementSyntax)node, diagnostics);
                    break;
                case SyntaxKind.TryStatement:
                    result = BindTryStatement((TryStatementSyntax)node, diagnostics);
                    break;
                case SyntaxKind.EmptyStatement:
                    result = BindEmpty((EmptyStatementSyntax)node);
                    break;
                case SyntaxKind.ThrowStatement:
                    result = BindThrow((ThrowStatementSyntax)node, diagnostics);
                    break;
                case SyntaxKind.UnsafeStatement:
                    result = BindUnsafeStatement((UnsafeStatementSyntax)node, diagnostics);
                    break;
                case SyntaxKind.UncheckedStatement:
                case SyntaxKind.CheckedStatement:
                    result = BindCheckedStatement((CheckedStatementSyntax)node, diagnostics);
                    break;
                case SyntaxKind.UsingStatement:
                    result = BindUsingStatement((UsingStatementSyntax)node, diagnostics);
                    break;
                case SyntaxKind.YieldBreakStatement:
                    result = BindYieldBreakStatement((YieldStatementSyntax)node, diagnostics);
                    break;
                case SyntaxKind.YieldReturnStatement:
                    result = BindYieldReturnStatement((YieldStatementSyntax)node, diagnostics);
                    break;
                case SyntaxKind.LockStatement:
                    result = BindLockStatement((LockStatementSyntax)node, diagnostics);
                    break;
                default:
                    // NOTE: We could probably throw an exception here, but it's conceivable
                    // that a non-parser syntax tree could reach this point with an unexpected
                    // SyntaxKind and we don't want to throw if that occurs.
                    Debug.Assert(false, "Unexpected SyntaxKind " + node.Kind());
                    result = new BoundBadStatement(node, ImmutableArray<BoundNode>.Empty, hasErrors: true);
                    break;
            }

            Debug.Assert(result.WasCompilerGenerated == false, "Synthetic node would not get cached");

            Debug.Assert(result.Syntax is StatementSyntax, "BoundStatement should be associated with a statement syntax.");

            Debug.Assert(System.Linq.Enumerable.Contains(result.Syntax.AncestorsAndSelf(), node), @"Bound statement (or one of its parents) 
                                                                            should have same syntax as the given syntax node. 
                                                                            Otherwise it may be confusung to the binder cache that uses syntax node as keys.");

            return result;
        }