Skip to content

Commit

Permalink
Remove Declaration Expressions feature for now. (changeset 1345194)
Browse files Browse the repository at this point in the history
  • Loading branch information
AlekseyTs committed Oct 2, 2014
1 parent 9e69820 commit 9d36a64
Show file tree
Hide file tree
Showing 96 changed files with 312 additions and 13,229 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ public QueryUnboundLambdaState(UnboundLambda unbound, Binder binder, RangeVariab
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);
Expand All @@ -42,7 +41,6 @@ public QueryUnboundLambdaState(UnboundLambda unbound, Binder binder, RangeVariab
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);
})
{ }
Expand Down
230 changes: 1 addition & 229 deletions Src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs

Large diffs are not rendered by default.

158 changes: 35 additions & 123 deletions Src/Compilers/CSharp/Portable/Binder/Binder_Initializers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ internal struct ProcessedFieldInitializers
internal static void BindFieldInitializers(
SourceMemberContainerTypeSymbol typeSymbol,
MethodSymbol scriptCtor,
ImmutableArray<FieldInitializers> fieldInitializers,
ImmutableArray<ImmutableArray<FieldInitializer>> fieldInitializers,
bool generateDebugInfo,
DiagnosticBag diagnostics,
ref ProcessedFieldInitializers processedInitializers) //by ref so that we can store the results of lowering
Expand All @@ -48,7 +48,7 @@ internal static void BindFieldInitializers(
internal static ImmutableArray<BoundInitializer> BindFieldInitializers(
SourceMemberContainerTypeSymbol containingType,
MethodSymbol scriptCtor,
ImmutableArray<FieldInitializers> initializers,
ImmutableArray<ImmutableArray<FieldInitializer>> initializers,
DiagnosticBag diagnostics,
bool generateDebugInfo,
out ConsList<Imports> firstDebugImports)
Expand Down Expand Up @@ -80,151 +80,64 @@ internal static ImmutableArray<BoundInitializer> BindFieldInitializers(
/// </summary>
private static void BindRegularCSharpFieldInitializers(
CSharpCompilation compilation,
ImmutableArray<FieldInitializers> initializers,
ImmutableArray<ImmutableArray<FieldInitializer>> initializers,
ArrayBuilder<BoundInitializer> boundInitializers,
DiagnosticBag diagnostics,
bool generateDebugInfo,
out ConsList<Imports> firstDebugImports)
{
firstDebugImports = null;

foreach (FieldInitializers siblingInitializers in initializers)
foreach (ImmutableArray<FieldInitializer> siblingInitializers in initializers)
{
var infos = ArrayBuilder<FieldInitializerInfo>.GetInstance(); // Exact size is not known up front.
var locals = GetFieldInitializerInfos(compilation, siblingInitializers, infos, generateDebugInfo, ref firstDebugImports);

ArrayBuilder<BoundInitializer> initializersBuilder = locals.IsDefaultOrEmpty ? boundInitializers : ArrayBuilder<BoundInitializer>.GetInstance(infos.Count);

foreach (var info in infos)
{
BoundFieldInitializer boundInitializer = BindFieldInitializer(info.Binder, info.Initializer.Field, info.EqualsValue, diagnostics);
initializersBuilder.Add(boundInitializer);
}

Debug.Assert(locals.IsDefaultOrEmpty == (initializersBuilder == boundInitializers));
if (!locals.IsDefaultOrEmpty)
{
boundInitializers.Add(new BoundInitializationScope((CSharpSyntaxNode)siblingInitializers.TypeDeclarationSyntax.GetSyntax(),
locals, initializersBuilder.ToImmutableAndFree()));
}

infos.Free();
}
}

internal static ImmutableArray<LocalSymbol> GetFieldInitializerInfos(
CSharpCompilation compilation,
FieldInitializers siblingInitializers,
ArrayBuilder<FieldInitializerInfo> infos,
bool generateDebugInfo,
ref ConsList<Imports> firstDebugImports)
{
// 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;

foreach (FieldInitializer initializer in siblingInitializers.Initializers)
{
FieldSymbol fieldSymbol = initializer.Field;
Debug.Assert((object)fieldSymbol != null);
// 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;

// 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)
foreach (FieldInitializer initializer in siblingInitializers)
{
//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);
}
FieldSymbol fieldSymbol = initializer.Field;
Debug.Assert((object)fieldSymbol != null);

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)
// 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)
{
firstDebugImports = parentBinder.ImportsList;
}
//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();

parentBinder = new LocalScopeBinder(parentBinder).WithAdditionalFlagsAndContainingMemberOrLambda(parentBinder.Flags | BinderFlags.FieldInitializer, fieldSymbol);

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);

if (!locals.IsDefaultOrEmpty)
{
for (int i = 0; i < infos.Count; i++)
{
FieldInitializerInfo info = infos[i];

// Constant initializers is not part of the initialization scope.
if (!info.Initializer.Field.IsConst)
if (binderFactory == null)
{
infos[i] = new FieldInitializerInfo(info.Initializer,
new SimpleLocalScopeBinder(locals, info.Binder),
info.EqualsValue);
binderFactory = compilation.GetBinderFactory(syntaxRef.SyntaxTree);
}
}
}
}

return locals;
}
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

private static ImmutableArray<LocalSymbol> GetInitializationScopeLocals(ArrayBuilder<FieldInitializerInfo> infos)
{
ArrayBuilder<LocalSymbol> localsBuilder = null;

foreach (var info in infos)
{
// Constant initializers do not contribute to the initialization scope.
if (!info.Initializer.Field.IsConst)
{
var walker = new LocalScopeBinder.BuildLocalsFromDeclarationsWalker(info.Binder, info.EqualsValue.Value);
walker.Visit(info.EqualsValue.Value);

if (walker.Locals != null)
{
if (localsBuilder == null)
{
localsBuilder = walker.Locals;
}
else
if (generateDebugInfo && firstDebugImports == null)
{
localsBuilder.AddRange(walker.Locals);
walker.Locals.Free();
firstDebugImports = parentBinder.ImportsList;
}

parentBinder = new LocalScopeBinder(parentBinder).WithAdditionalFlagsAndContainingMemberOrLambda(parentBinder.Flags | BinderFlags.FieldInitializer, fieldSymbol);

BoundFieldInitializer boundInitializer = BindFieldInitializer(parentBinder, fieldSymbol, initializerNode, diagnostics);
boundInitializers.Add(boundInitializer);
}
}
}

if (localsBuilder != null)
{
return localsBuilder.ToImmutableAndFree();
}

return ImmutableArray<LocalSymbol>.Empty;
}

/// <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<FieldInitializers> initializers, ArrayBuilder<BoundInitializer> boundInitializers, DiagnosticBag diagnostics,
ImmutableArray<ImmutableArray<FieldInitializer>> initializers, ArrayBuilder<BoundInitializer> boundInitializers, DiagnosticBag diagnostics,
bool generateDebugInfo, out ConsList<Imports> firstDebugImports)
{
Debug.Assert((object)scriptCtor != null);
Expand All @@ -233,17 +146,16 @@ private static void BindScriptFieldInitializers(CSharpCompilation compilation, M

for (int i = 0; i < initializers.Length; i++)
{
FieldInitializers siblingInitializers = initializers[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.Initializers.Length; j++)
for (int j = 0; j < siblingInitializers.Length; j++)
{
Debug.Assert(siblingInitializers.TypeDeclarationSyntax == null);
var initializer = siblingInitializers.Initializers[j];
var initializer = siblingInitializers[j];
var fieldSymbol = initializer.Field;

if ((object)fieldSymbol != null && fieldSymbol.IsConst)
Expand Down Expand Up @@ -291,7 +203,7 @@ private static void BindScriptFieldInitializers(CSharpCompilation compilation, M
{
var collisionDetector = new LocalScopeBinder(parentBinder);
boundInitializer = BindGlobalStatement(collisionDetector, (StatementSyntax)initializerNode, diagnostics,
isLast: i == initializers.Length - 1 && j == siblingInitializers.Initializers.Length - 1);
isLast: i == initializers.Length - 1 && j == siblingInitializers.Length - 1);
}

boundInitializers.Add(boundInitializer);
Expand Down
11 changes: 0 additions & 11 deletions Src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1981,17 +1981,6 @@ internal bool IsNonMoveableVariable(BoundExpression expr, out Symbol accessedLoc
// such locals are not moveable.
return true;
}
case BoundKind.DeclarationExpression:
{
var declaration = (BoundDeclarationExpression)expr;
LocalSymbol localSymbol = declaration.LocalSymbol;
Debug.Assert(localSymbol.RefKind == RefKind.None);
accessedLocalOrParameterOpt = localSymbol;
// NOTE: The spec says that this is moveable if it is captured by an anonymous function,
// but that will be reported separately and error-recovery is better if we say that
// such locals are not moveable.
return true;
}
case BoundKind.PointerIndirectionOperator: //Covers ->, since the receiver will be one of these.
case BoundKind.PointerElementAccess:
case BoundKind.StackAllocArrayCreation:
Expand Down
1 change: 0 additions & 1 deletion Src/Compilers/CSharp/Portable/Binder/Binder_Query.cs
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,6 @@ void ReduceLet(LetClauseSyntax let, QueryTranslationState state, 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())
Expand Down
Loading

0 comments on commit 9d36a64

Please sign in to comment.