/// <summary> /// Creates a SemanticModel for an ArrowExpressionClause, which includes /// an ExecutableCodeBinder and a ScopedExpressionBinder. /// </summary> internal static MethodBodySemanticModel Create(CSharpCompilation compilation, MethodSymbol owner, Binder rootBinder, ArrowExpressionClauseSyntax syntax) { Binder binder = new ExecutableCodeBinder(syntax, owner, rootBinder); binder = new ScopedExpressionBinder(binder, syntax.Expression); return(new MethodBodySemanticModel(compilation, owner, binder, syntax)); }
public QueryUnboundLambdaState(UnboundLambda unbound, Binder binder, RangeVariableMap rangeVariableMap, ImmutableArray <RangeVariableSymbol> parameters, ExpressionSyntax body) : this(unbound, binder, rangeVariableMap, parameters, (LambdaSymbol lambdaSymbol, ref Binder lambdaBodyBinder, DiagnosticBag diagnostics) => { lambdaBodyBinder = new ScopedExpressionBinder(lambdaBodyBinder, body); return(lambdaBodyBinder.BindLambdaExpressionAsBlock(body, diagnostics)); }) { }
public QueryUnboundLambdaState(UnboundLambda unbound, Binder binder, RangeVariableMap rangeVariableMap, ImmutableArray<RangeVariableSymbol> parameters, ExpressionSyntax body) : this(unbound, binder, rangeVariableMap, parameters, (LambdaSymbol lambdaSymbol, ref Binder lambdaBodyBinder, DiagnosticBag diagnostics) => { lambdaBodyBinder = new ScopedExpressionBinder(lambdaBodyBinder, body); return lambdaBodyBinder.BindLambdaExpressionAsBlock(body, diagnostics); }) { }
public QueryUnboundLambdaState(UnboundLambda unbound, Binder binder, RangeVariableMap rangeVariableMap, ImmutableArray <RangeVariableSymbol> parameters, ExpressionSyntax body, TypeSyntax castTypeSyntax, TypeSymbol castType) : this(unbound, binder, rangeVariableMap, parameters, (LambdaSymbol lambdaSymbol, ref Binder lambdaBodyBinder, DiagnosticBag diagnostics) => { lambdaBodyBinder = new ScopedExpressionBinder(lambdaBodyBinder, body); BoundExpression expression = lambdaBodyBinder.BindValue(body, diagnostics, BindValueKind.RValue); Debug.Assert((object)castType != null); Debug.Assert(castTypeSyntax != null); // We transform the expression from "expr" to "expr.Cast<castTypeOpt>()". expression = lambdaBodyBinder.MakeQueryInvocation(body, expression, "Cast", castTypeSyntax, castType, diagnostics); return(lambdaBodyBinder.CreateBlockFromExpression(lambdaBodyBinder.Locals, expression, body, diagnostics)); }) { }
public QueryUnboundLambdaState(UnboundLambda unbound, Binder binder, RangeVariableMap rangeVariableMap, ImmutableArray<RangeVariableSymbol> parameters, ExpressionSyntax body, TypeSyntax castTypeSyntax, TypeSymbol castType) : this(unbound, binder, rangeVariableMap, parameters, (LambdaSymbol lambdaSymbol, ref Binder lambdaBodyBinder, DiagnosticBag diagnostics) => { lambdaBodyBinder = new ScopedExpressionBinder(lambdaBodyBinder, body); BoundExpression expression = lambdaBodyBinder.BindValue(body, diagnostics, BindValueKind.RValue); Debug.Assert((object)castType != null); Debug.Assert(castTypeSyntax != null); // We transform the expression from "expr" to "expr.Cast<castTypeOpt>()". expression = lambdaBodyBinder.MakeQueryInvocation(body, expression, "Cast", castTypeSyntax, castType, diagnostics); return lambdaBodyBinder.CreateBlockFromExpression(lambdaBodyBinder.Locals, expression, body, diagnostics); }) { }
protected override BoundBlock BindLambdaBody(LambdaSymbol lambdaSymbol, ref Binder lambdaBodyBinder, DiagnosticBag diagnostics) { if (this.IsExpressionLambda) { var body = (ExpressionSyntax)this.Body; lambdaBodyBinder = new ScopedExpressionBinder(lambdaBodyBinder, body); return(lambdaBodyBinder.BindLambdaExpressionAsBlock(body, diagnostics)); } else { return(lambdaBodyBinder.BindBlock((BlockSyntax)this.Body, diagnostics)); } }
void ReduceLet(LetClauseSyntax let, QueryTranslationState state, DiagnosticBag diagnostics) { // A query expression with a let clause // from x in e // let y = f // ... // is translated into // from * in ( e ) . Select ( x => new { x , y = f } ) // ... var x = state.rangeVariable; // We use a slightly different translation strategy. We produce // from * in ( e ) . Select ( x => new Pair<X,Y>(x, f) ) // Where X is the type of x, and Y is the type of the expression f. // Subsequently, x (or members of x, if it is a transparent identifier) // are accessed as TRID.Item1 (or members of that), and y is accessed // as TRID.Item2, where TRID is the compiler-generated identifier used // to represent the transparent identifier in the result. LambdaBodyResolver resolver = (LambdaSymbol lambdaSymbol, ref Binder lambdaBodyBinder, DiagnosticBag d) => { var xExpression = new BoundParameter(let, lambdaSymbol.Parameters[0]) { WasCompilerGenerated = true }; lambdaBodyBinder = new ScopedExpressionBinder(lambdaBodyBinder, let.Expression); var yExpression = lambdaBodyBinder.BindValue(let.Expression, d, BindValueKind.RValue); SourceLocation errorLocation = new SourceLocation(let.SyntaxTree, new TextSpan(let.Identifier.SpanStart, let.Expression.Span.End - let.Identifier.SpanStart)); if (!yExpression.HasAnyErrors && !yExpression.HasExpressionType()) { MessageID id = MessageID.IDS_NULL; if (yExpression.Kind == BoundKind.UnboundLambda) { id = ((UnboundLambda)yExpression).MessageID; } else if (yExpression.Kind == BoundKind.MethodGroup) { id = MessageID.IDS_MethodGroup; } else { Debug.Assert(yExpression.IsLiteralNull(), "How did we successfully bind an expression without a type?"); } Error(d, ErrorCode.ERR_QueryRangeVariableAssignedBadValue, errorLocation, id.Localize()); yExpression = new BoundBadExpression(yExpression.Syntax, LookupResultKind.Empty, ImmutableArray <Symbol> .Empty, ImmutableArray.Create <BoundNode>(yExpression), CreateErrorType()); } else if (!yExpression.HasAnyErrors && yExpression.Type.SpecialType == SpecialType.System_Void) { Error(d, ErrorCode.ERR_QueryRangeVariableAssignedBadValue, errorLocation, yExpression.Type); yExpression = new BoundBadExpression(yExpression.Syntax, LookupResultKind.Empty, ImmutableArray <Symbol> .Empty, ImmutableArray.Create <BoundNode>(yExpression), yExpression.Type); } var construction = MakePair(let, x.Name, xExpression, let.Identifier.ValueText, yExpression, state, d); return(lambdaBodyBinder.CreateBlockFromExpression(lambdaBodyBinder.Locals, construction, let, d)); }; var lambda = MakeQueryUnboundLambda(state.RangeVariableMap(), x, let.Expression, resolver); state.rangeVariable = state.TransparentRangeVariable(this); state.AddTransparentIdentifier(x.Name); var y = state.AddRangeVariable(this, let.Identifier, diagnostics); state.allRangeVariables[y].Add(let.Identifier.ValueText); var invocation = MakeQueryInvocation(let, state.fromExpression, "Select", lambda, diagnostics); state.fromExpression = MakeQueryClause(let, invocation, y, invocation); }
protected override BoundBlock BindLambdaBody(LambdaSymbol lambdaSymbol, ref Binder lambdaBodyBinder, DiagnosticBag diagnostics) { if (this.IsExpressionLambda) { var body = (ExpressionSyntax)this.Body; lambdaBodyBinder = new ScopedExpressionBinder(lambdaBodyBinder, body); return lambdaBodyBinder.BindLambdaExpressionAsBlock(body, diagnostics); } else { return lambdaBodyBinder.BindBlock((BlockSyntax)this.Body, diagnostics); } }
/// <summary> /// Creates a SemanticModel for an ArrowExpressionClause, which includes /// an ExecutableCodeBinder and a ScopedExpressionBinder. /// </summary> internal static MethodBodySemanticModel Create(CSharpCompilation compilation, MethodSymbol owner, Binder rootBinder, ArrowExpressionClauseSyntax syntax) { Binder binder = new ExecutableCodeBinder(syntax, owner, rootBinder); binder = new ScopedExpressionBinder(binder, syntax.Expression); return new MethodBodySemanticModel(compilation, owner, binder, syntax); }
/// <summary> /// In regular C#, all field initializers are assignments to fields and the assigned expressions /// may not reference instance members. /// </summary> private static void BindRegularCSharpFieldInitializers( CSharpCompilation compilation, ImmutableArray <FieldInitializers> initializers, ArrayBuilder <BoundInitializer> boundInitializers, DiagnosticBag diagnostics, bool generateDebugInfo, out ConsList <Imports> firstDebugImports) { firstDebugImports = null; foreach (FieldInitializers siblingInitializers in initializers) { // 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; var infos = ArrayBuilder <FieldInitializerInfo> .GetInstance(); // Exact size is not known up front. foreach (FieldInitializer initializer in siblingInitializers.Initializers) { FieldSymbol fieldSymbol = initializer.Field; Debug.Assert((object)fieldSymbol != null); // A constant field of type decimal needs a field initializer, so // check if it is a metadata constant, not just a constant to exclude // decimals. Other constants do not need field initializers. if (!fieldSymbol.IsMetadataConstant) { //Can't assert that this is a regular C# compilation, because we could be in a nested type of a script class. SyntaxReference syntaxRef = initializer.Syntax; var initializerNode = (EqualsValueClauseSyntax)syntaxRef.GetSyntax(); if (binderFactory == null) { binderFactory = compilation.GetBinderFactory(syntaxRef.SyntaxTree); } Binder parentBinder = binderFactory.GetBinder(initializerNode); Debug.Assert(parentBinder.ContainingMemberOrLambda == fieldSymbol.ContainingType || //should be the binder for the type fieldSymbol.ContainingType.IsImplicitClass); //however, we also allow fields in namespaces to help support script scenarios if (generateDebugInfo && firstDebugImports == null) { firstDebugImports = parentBinder.ImportsList; } parentBinder = new LocalScopeBinder(parentBinder).WithAdditionalFlagsAndContainingMemberOrLambda(parentBinder.Flags | BinderFlags.FieldInitializer, fieldSymbol); if (!fieldSymbol.IsConst && !fieldSymbol.IsStatic) { parentBinder = parentBinder.WithPrimaryConstructorParametersIfNecessary(fieldSymbol.ContainingType); } infos.Add(new FieldInitializerInfo(initializer, parentBinder, initializerNode)); } } // See if there are locals that we need to bring into the scope. var locals = default(ImmutableArray <LocalSymbol>); if (siblingInitializers.TypeDeclarationSyntax != null) { locals = GetInitializationScopeLocals(infos); } ArrayBuilder <BoundInitializer> initializersBuilder = locals.IsDefaultOrEmpty ? boundInitializers : ArrayBuilder <BoundInitializer> .GetInstance(infos.Count); foreach (var info in infos) { Binder binder = info.Binder; ScopedExpressionBinder scopedExpressionBinder = null; // Constant initializers is not part of the initialization scope. if (info.Initializer.Field.IsConst || locals.IsDefault) { binder = scopedExpressionBinder = new ScopedExpressionBinder(binder, info.EqualsValue.Value); } else if (!locals.IsEmpty) { binder = new SimpleLocalScopeBinder(locals, binder); } BoundFieldInitializer boundInitializer = BindFieldInitializer(binder, info.Initializer.Field, info.EqualsValue, diagnostics); if (scopedExpressionBinder != null && !scopedExpressionBinder.Locals.IsDefaultOrEmpty) { boundInitializer = boundInitializer.Update(boundInitializer.Field, scopedExpressionBinder.AddLocalScopeToExpression(boundInitializer.InitialValue)); } initializersBuilder.Add(boundInitializer); } Debug.Assert(locals.IsDefaultOrEmpty == (initializersBuilder == boundInitializers)); if (!locals.IsDefaultOrEmpty) { boundInitializers.Add(new BoundInitializationScope((CSharpSyntaxNode)siblingInitializers.TypeDeclarationSyntax.GetSyntax(), locals, initializersBuilder.ToImmutableAndFree())); } } }