コード例 #1
0
        private static ImmutableArray <BoundInitializer> BindFieldInitializers(
            CSharpCompilation compilation,
            SynthesizedInteractiveInitializerMethod scriptInitializerOpt,
            ImmutableArray <ImmutableArray <FieldOrPropertyInitializer> > initializers,
            DiagnosticBag diagnostics,
            out ImportChain firstImportChain)
        {
            if (initializers.IsEmpty)
            {
                firstImportChain = null;
                return(ImmutableArray <BoundInitializer> .Empty);
            }

            var boundInitializers = ArrayBuilder <BoundInitializer> .GetInstance();

            if ((object)scriptInitializerOpt == null)
            {
                BindRegularCSharpFieldInitializers(compilation, initializers, boundInitializers, diagnostics, out firstImportChain);
            }
            else
            {
                BindScriptFieldInitializers(compilation, scriptInitializerOpt, initializers, boundInitializers, diagnostics, out firstImportChain);
            }
            return(boundInitializers.ToImmutableAndFree());
        }
コード例 #2
0
        private static void SetScriptInitializerReturnType(
            CSharpCompilation compilation,
            SynthesizedInteractiveInitializerMethod scriptInitializer,
            ImmutableArray <ImmutableArray <FieldOrPropertyInitializer> > fieldInitializers,
            DiagnosticBag diagnostics)
        {
            bool       isAsync    = scriptInitializer.IsSubmissionInitializer && fieldInitializers.Any(i => i.Any(ContainsAwaitsVisitor.ContainsAwait));
            var        resultType = scriptInitializer.ResultType;
            TypeSymbol returnType;

            if ((object)resultType == null)
            {
                Debug.Assert(!isAsync);
                returnType = compilation.GetSpecialType(SpecialType.System_Void);
            }
            else if (!isAsync)
            {
                returnType = resultType;
            }
            else
            {
                var taskT             = compilation.GetWellKnownType(WellKnownType.System_Threading_Tasks_Task_T);
                var useSiteDiagnostic = taskT.GetUseSiteDiagnostic();
                if (useSiteDiagnostic != null)
                {
                    diagnostics.Add(useSiteDiagnostic, NoLocation.Singleton);
                }
                returnType = taskT.Construct(resultType);
            }

            scriptInitializer.SetReturnType(isAsync, returnType);
        }
コード例 #3
0
        private static BoundInitializer BindGlobalStatement(
            Binder binder,
            SynthesizedInteractiveInitializerMethod scriptInitializer,
            StatementSyntax statementNode,
            DiagnosticBag diagnostics,
            bool isLast)
        {
            BoundStatement boundStatement = binder.BindStatement(statementNode, diagnostics);

            // the result of the last global expression is assigned to the result storage for submission result:
            if (binder.Compilation.IsSubmission && isLast && !boundStatement.HasAnyErrors)
            {
                // insert an implicit conversion for the submission return type (if needed):
                var expression = InitializerRewriter.GetTrailingScriptExpression(boundStatement);
                if (expression != null &&
                    ((object)expression.Type == null || expression.Type.SpecialType != SpecialType.System_Void))
                {
                    var submissionResultType = scriptInitializer.ResultType;
                    expression     = binder.GenerateConversionForAssignment(submissionResultType, expression, diagnostics);
                    boundStatement = new BoundExpressionStatement(boundStatement.Syntax, expression, expression.HasErrors);
                }
            }

            return(new BoundGlobalStatementInitializer(statementNode, boundStatement));
        }
コード例 #4
0
 internal Labels(
     SynthesizedInteractiveInitializerMethod scriptInitializer,
     CompilationUnitSyntax syntax
     )
 {
     _scriptInitializer = scriptInitializer;
     _syntax            = syntax;
 }
コード例 #5
0
        /// <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,
            SynthesizedInteractiveInitializerMethod scriptInitializer,
            ImmutableArray <ImmutableArray <FieldOrPropertyInitializer> > initializers,
            ArrayBuilder <BoundInitializer> boundInitializers,
            BindingDiagnosticBag diagnostics,
            out ImportChain?firstDebugImports
            )
        {
            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;
                // Label instances must be shared across all global statements.
                ScriptLocalScopeBinder.Labels?labels = 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;
                    var syntaxTree = syntaxRef.SyntaxTree;
                    Debug.Assert(syntaxTree.Options.Kind != SourceCodeKind.Regular);

                    var syntax     = (CSharpSyntaxNode)syntaxRef.GetSyntax();
                    var syntaxRoot = syntaxTree.GetCompilationUnitRoot();

                    if (binderFactory == null)
                    {
                        binderFactory = compilation.GetBinderFactory(syntaxTree);
                        labels        = new ScriptLocalScopeBinder.Labels(scriptInitializer, syntaxRoot);
                    }

                    Binder scriptClassBinder = binderFactory.GetBinder(syntax);
                    Debug.Assert(
                        scriptClassBinder.ContainingMemberOrLambda
                        is NamedTypeSymbol {
                        IsScriptClass: true
                    }
コード例 #6
0
            private static ImmutableArray <LabelSymbol> GetLabels(SynthesizedInteractiveInitializerMethod scriptInitializer, CompilationUnitSyntax syntax)
            {
                var builder = ArrayBuilder <LabelSymbol> .GetInstance();

                foreach (var member in syntax.Members)
                {
                    if (member.Kind() != SyntaxKind.GlobalStatement)
                    {
                        continue;
                    }
                    LocalScopeBinder.BuildLabels(scriptInitializer, ((GlobalStatementSyntax)member).Statement, ref builder);
                }
                return(builder.ToImmutableAndFree());
            }
コード例 #7
0
        internal static void BindFieldInitializers(
            CSharpCompilation compilation,
            SynthesizedInteractiveInitializerMethod scriptInitializerOpt,
            ImmutableArray <ImmutableArray <FieldOrPropertyInitializer> > fieldInitializers,
            DiagnosticBag diagnostics,
            ref ProcessedFieldInitializers processedInitializers)
        {
            var         diagsForInstanceInitializers = DiagnosticBag.GetInstance();
            ImportChain firstImportChain;

            processedInitializers.BoundInitializers = BindFieldInitializers(compilation, scriptInitializerOpt, fieldInitializers, diagsForInstanceInitializers, out firstImportChain);
            processedInitializers.HasErrors         = diagsForInstanceInitializers.HasAnyErrors();
            processedInitializers.FirstImportChain  = firstImportChain;
            diagnostics.AddRange(diagsForInstanceInitializers);
            diagsForInstanceInitializers.Free();
        }
コード例 #8
0
        private static BoundInitializer BindGlobalStatement(
            Binder binder,
            SynthesizedInteractiveInitializerMethod scriptInitializer,
            StatementSyntax statementNode,
            DiagnosticBag diagnostics,
            bool isLast)
        {
            var statement = binder.BindStatement(statementNode, diagnostics);

            if (isLast && !statement.HasAnyErrors)
            {
                // the result of the last global expression is assigned to the result storage for submission result:
                if (binder.Compilation.IsSubmission)
                {
                    // insert an implicit conversion for the submission return type (if needed):
                    var expression = InitializerRewriter.GetTrailingScriptExpression(statement);
                    if (expression != null &&
                        ((object)expression.Type == null || expression.Type.SpecialType != SpecialType.System_Void))
                    {
                        var submissionResultType = scriptInitializer.ResultType;
                        expression = binder.GenerateConversionForAssignment(submissionResultType, expression, diagnostics);
                        statement  = new BoundExpressionStatement(statement.Syntax, expression, expression.HasErrors);
                    }
                }

                // don't allow trailing expressions after labels (as in regular C#, labels must be followed by a statement):
                if (statement.Kind == BoundKind.LabeledStatement)
                {
                    var labeledStatementBody = ((BoundLabeledStatement)statement).Body;
                    while (labeledStatementBody.Kind == BoundKind.LabeledStatement)
                    {
                        labeledStatementBody = ((BoundLabeledStatement)labeledStatementBody).Body;
                    }

                    if (InitializerRewriter.GetTrailingScriptExpression(labeledStatementBody) != null)
                    {
                        Error(diagnostics, ErrorCode.ERR_SemicolonExpected, ((ExpressionStatementSyntax)labeledStatementBody.Syntax).SemicolonToken);
                    }
                }
            }

            return(new BoundGlobalStatementInitializer(statementNode, statement));
        }
コード例 #9
0
        internal static void BindFieldInitializers(
            CSharpCompilation compilation,
            SynthesizedInteractiveInitializerMethod scriptInitializerOpt,
            ImmutableArray <ImmutableArray <FieldOrPropertyInitializer> > fieldInitializers,
            DiagnosticBag diagnostics,
            bool setReturnType, // Remove once static fields are errors in submissions.
            ref ProcessedFieldInitializers processedInitializers)
        {
            if (setReturnType && ((object)scriptInitializerOpt != null))
            {
                SetScriptInitializerReturnType(compilation, scriptInitializerOpt, fieldInitializers, diagnostics);
            }

            var         diagsForInstanceInitializers = DiagnosticBag.GetInstance();
            ImportChain firstImportChain;

            processedInitializers.BoundInitializers = BindFieldInitializers(compilation, scriptInitializerOpt, fieldInitializers, diagsForInstanceInitializers, out firstImportChain);
            processedInitializers.HasErrors         = diagsForInstanceInitializers.HasAnyErrors();
            processedInitializers.FirstImportChain  = firstImportChain;
            diagnostics.AddRange(diagsForInstanceInitializers);
            diagsForInstanceInitializers.Free();
        }
コード例 #10
0
        /// <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,
            SynthesizedInteractiveInitializerMethod scriptInitializer,
            ImmutableArray <ImmutableArray <FieldOrPropertyInitializer> > initializers,
            ArrayBuilder <BoundInitializer> boundInitializers,
            DiagnosticBag diagnostics,
            out ImportChain firstDebugImports)
        {
            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(), scriptInitializer, 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, scriptInitializer, (StatementSyntax)initializerNode, diagnostics,
                                                               isLast: i == initializers.Length - 1 && j == siblingInitializers.Length - 1);
                    }

                    boundInitializers.Add(boundInitializer);
                }
            }
        }
コード例 #11
0
        internal static BoundTypeOrInstanceInitializers RewriteScriptInitializer(ImmutableArray <BoundInitializer> boundInitializers, SynthesizedInteractiveInitializerMethod method, out bool hasTrailingExpression)
        {
            Debug.Assert(!boundInitializers.IsDefault);

            var boundStatements = ArrayBuilder <BoundStatement> .GetInstance(boundInitializers.Length);

            var             submissionResultType    = method.ResultType;
            var             hasSubmissionResultType = (object)submissionResultType != null;
            BoundStatement  lastStatement           = null;
            BoundExpression trailingExpression      = null;

            foreach (var initializer in boundInitializers)
            {
                // The value of the last expression statement (if any) is returned from the submission initializer,
                // unless this is a #load'ed tree.  I the #load'ed tree case, we'll execute the trailing expression
                // but discard its result.
                if (hasSubmissionResultType &&
                    (initializer == boundInitializers.Last()) &&
                    (initializer.Kind == BoundKind.GlobalStatementInitializer) &&
                    method.DeclaringCompilation.IsSubmissionSyntaxTree(initializer.SyntaxTree))
                {
                    lastStatement = ((BoundGlobalStatementInitializer)initializer).Statement;
                    var expression = GetTrailingScriptExpression(lastStatement);
                    if (expression != null &&
                        (object)expression.Type != null &&
                        expression.Type.SpecialType != SpecialType.System_Void)
                    {
                        trailingExpression = expression;
                        continue;
                    }
                }

                boundStatements.Add(RewriteInitializersAsStatements(initializer));
            }

            if (hasSubmissionResultType && (trailingExpression != null))
            {
                Debug.Assert(submissionResultType.SpecialType != SpecialType.System_Void);

                // Note: The trailing expression was already converted to the submission result type in Binder.BindGlobalStatement.
                boundStatements.Add(new BoundReturnStatement(lastStatement.Syntax, RefKind.None, trailingExpression));
                hasTrailingExpression = true;
            }
            else
            {
                hasTrailingExpression = false;
            }

            return(new BoundTypeOrInstanceInitializers(method.GetNonNullSyntaxNode(), boundStatements.ToImmutableAndFree()));
        }
コード例 #12
0
        internal static BoundTypeOrInstanceInitializers RewriteScriptInitializer(ImmutableArray <BoundInitializer> boundInitializers, SynthesizedInteractiveInitializerMethod method)
        {
            Debug.Assert(!boundInitializers.IsDefault);

            var boundStatements = ArrayBuilder <BoundStatement> .GetInstance(boundInitializers.Length);

            var             submissionResultType = method.ResultType;
            BoundExpression submissionResult     = null;

            foreach (var initializer in boundInitializers)
            {
                // The value of the last expression statement (if any) is returned from the submission initializer.
                if (((object)submissionResultType != null) &&
                    (initializer == boundInitializers.Last()) &&
                    (initializer.Kind == BoundKind.GlobalStatementInitializer))
                {
                    var statement = ((BoundGlobalStatementInitializer)initializer).Statement;
                    if (statement.Kind == BoundKind.ExpressionStatement)
                    {
                        var expr = ((BoundExpressionStatement)statement).Expression;
                        if ((object)expr.Type != null && expr.Type.SpecialType != SpecialType.System_Void)
                        {
                            submissionResult = expr;
                            continue;
                        }
                    }
                }
                boundStatements.Add(RewriteInitializersAsStatements(initializer));
            }

            var syntax = method.GetNonNullSyntaxNode();

            if ((object)submissionResultType != null)
            {
                if (submissionResult == null)
                {
                    // Return default(T) if submission does not have a trailing expression.
                    submissionResult = new BoundDefaultOperator(syntax, submissionResultType);
                }
                Debug.Assert(submissionResult.Type.SpecialType != SpecialType.System_Void);

                // The expression is converted to the submission result type when the initializer is bound.
                boundStatements.Add(new BoundReturnStatement(submissionResult.Syntax, submissionResult));
            }

            return(new BoundTypeOrInstanceInitializers(syntax, boundStatements.ToImmutableAndFree()));
        }