internal static SynthesizedEntryPointSymbol Create(SynthesizedInteractiveInitializerMethod initializerMethod, DiagnosticBag diagnostics) { var containingType = initializerMethod.ContainingType; var compilation = containingType.DeclaringCompilation; if (compilation.IsSubmission) { var submissionArrayType = compilation.CreateArrayTypeSymbol(compilation.GetSpecialType(SpecialType.System_Object)); ReportUseSiteDiagnostics(submissionArrayType, diagnostics); return(new SubmissionEntryPoint( containingType, initializerMethod.ReturnType, submissionArrayType)); } else { var taskType = compilation.GetWellKnownType(WellKnownType.System_Threading_Tasks_Task); #if DEBUG HashSet <DiagnosticInfo> useSiteDiagnostics = null; Debug.Assert(taskType.IsErrorType() || initializerMethod.ReturnType.IsDerivedFrom(taskType, TypeCompareKind.IgnoreDynamicAndTupleNames, useSiteDiagnostics: ref useSiteDiagnostics)); #endif ReportUseSiteDiagnostics(taskType, diagnostics); var getAwaiterMethod = taskType.IsErrorType() ? null : GetRequiredMethod(taskType, WellKnownMemberNames.GetAwaiter, diagnostics); var getResultMethod = ((object)getAwaiterMethod == null) ? null : GetRequiredMethod(getAwaiterMethod.ReturnType, WellKnownMemberNames.GetResult, diagnostics); return(new ScriptEntryPoint( containingType, compilation.GetSpecialType(SpecialType.System_Void), getAwaiterMethod, getResultMethod)); } }
internal static SynthesizedEntryPointSymbol Create(SynthesizedInteractiveInitializerMethod initializerMethod, DiagnosticBag diagnostics) { var containingType = initializerMethod.ContainingType; var compilation = containingType.DeclaringCompilation; if (compilation.IsSubmission) { var submissionArrayType = compilation.CreateArrayTypeSymbol(compilation.GetSpecialType(SpecialType.System_Object)); ReportUseSiteDiagnostics(submissionArrayType, diagnostics); return new SubmissionEntryPoint( containingType, initializerMethod.ReturnType, submissionArrayType); } else { var taskType = compilation.GetWellKnownType(WellKnownType.System_Threading_Tasks_Task); #if DEBUG HashSet<DiagnosticInfo> useSiteDiagnostics = null; Debug.Assert(taskType.IsErrorType() || initializerMethod.ReturnType.IsDerivedFrom(taskType, ignoreDynamic: true, useSiteDiagnostics: ref useSiteDiagnostics)); #endif ReportUseSiteDiagnostics(taskType, diagnostics); var getAwaiterMethod = taskType.IsErrorType() ? null : GetRequiredMethod(taskType, WellKnownMemberNames.GetAwaiter, diagnostics); var getResultMethod = ((object)getAwaiterMethod == null) ? null : GetRequiredMethod(getAwaiterMethod.ReturnType, WellKnownMemberNames.GetResult, diagnostics); return new ScriptEntryPoint( containingType, compilation.GetSpecialType(SpecialType.System_Void), getAwaiterMethod, getResultMethod); } }
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); }
internal static SynthesizedEntryPointSymbol Create( SynthesizedInteractiveInitializerMethod initializerMethod, BindingDiagnosticBag diagnostics ) { var containingType = initializerMethod.ContainingType; var compilation = containingType.DeclaringCompilation; if (compilation.IsSubmission) { var systemObject = Binder.GetSpecialType( compilation, SpecialType.System_Object, DummySyntax(), diagnostics ); var submissionArrayType = compilation.CreateArrayTypeSymbol(systemObject); diagnostics.ReportUseSite(submissionArrayType, NoLocation.Singleton); return(new SubmissionEntryPoint( containingType, initializerMethod.ReturnTypeWithAnnotations, submissionArrayType )); } else { var systemVoid = Binder.GetSpecialType( compilation, SpecialType.System_Void, DummySyntax(), diagnostics ); return(new ScriptEntryPoint(containingType, TypeWithAnnotations.Create(systemVoid))); } }
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(); }
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, trailingExpression)); hasTrailingExpression = true; } else { hasTrailingExpression = false; } return new BoundTypeOrInstanceInitializers(method.GetNonNullSyntaxNode(), boundStatements.ToImmutableAndFree()); }
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(); }
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()); }
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(); }
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(); }
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); }
/// <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; // 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(((NamedTypeSymbol)scriptClassBinder.ContainingMemberOrLambda).IsScriptClass); if (firstDebugImports == null) { firstDebugImports = scriptClassBinder.ImportChain; } Binder parentBinder = new ExecutableCodeBinder( syntaxRoot, scriptInitializer, new ScriptLocalScopeBinder(labels, scriptClassBinder)); BoundInitializer boundInitializer; if ((object)fieldSymbol != null) { boundInitializer = BindFieldInitializer( parentBinder.WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.FieldInitializer, fieldSymbol), fieldSymbol, (EqualsValueClauseSyntax)syntax, diagnostics); } else { boundInitializer = BindGlobalStatement( parentBinder, scriptInitializer, (StatementSyntax)syntax, diagnostics, isLast: i == initializers.Length - 1 && j == siblingInitializers.Length - 1); } boundInitializers.Add(boundInitializer); } } }
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); }
internal Labels(SynthesizedInteractiveInitializerMethod scriptInitializer, CompilationUnitSyntax syntax) { _scriptInitializer = scriptInitializer; _syntax = syntax; }