| File: Lowering\StateMachineRewriter\CapturedSymbol.cs | Web Access |
| Project: src\roslyn\src\Compilers\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.csproj (Microsoft.CodeAnalysis.CSharp) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #nullable disable using System; using System.Collections.Immutable; using Microsoft.CodeAnalysis.CSharp.Symbols; namespace Microsoft.CodeAnalysis.CSharp { internal abstract class CapturedSymbolReplacement { public readonly bool IsReusable; public CapturedSymbolReplacement(bool isReusable) { this.IsReusable = isReusable; } /// <summary> /// Rewrite the replacement expression for the hoisted local so all synthesized field are accessed as members /// of the appropriate frame. /// </summary> public abstract BoundExpression Replacement<TArg>(SyntaxNode node, Func<NamedTypeSymbol, TArg, BoundExpression> makeFrame, TArg arg); } internal sealed class CapturedToFrameSymbolReplacement : CapturedSymbolReplacement { public readonly LambdaCapturedVariable HoistedField; public CapturedToFrameSymbolReplacement(LambdaCapturedVariable hoistedField, bool isReusable) : base(isReusable) { this.HoistedField = hoistedField; } public override BoundExpression Replacement<TArg>(SyntaxNode node, Func<NamedTypeSymbol, TArg, BoundExpression> makeFrame, TArg arg) { var frame = makeFrame(this.HoistedField.ContainingType, arg); var field = this.HoistedField.AsMember((NamedTypeSymbol)frame.Type); return new BoundFieldAccess(node, frame, field, constantValueOpt: null); } } internal sealed class CapturedToStateMachineFieldReplacement : CapturedSymbolReplacement { public readonly StateMachineFieldSymbol HoistedField; public CapturedToStateMachineFieldReplacement(StateMachineFieldSymbol hoistedField, bool isReusable) : base(isReusable) { this.HoistedField = hoistedField; } public override BoundExpression Replacement<TArg>(SyntaxNode node, Func<NamedTypeSymbol, TArg, BoundExpression> makeFrame, TArg arg) { var frame = makeFrame(this.HoistedField.ContainingType, arg); var field = this.HoistedField.AsMember((NamedTypeSymbol)frame.Type); return new BoundFieldAccess(node, frame, field, constantValueOpt: null); } } internal sealed class CapturedToExpressionSymbolReplacement<THoistedSymbolType> : CapturedSymbolReplacement where THoistedSymbolType : Symbol { private readonly BoundExpression _replacement; public readonly ImmutableArray<THoistedSymbolType> HoistedSymbols; public CapturedToExpressionSymbolReplacement(BoundExpression replacement, ImmutableArray<THoistedSymbolType> hoistedSymbols, bool isReusable) : base(isReusable) { _replacement = replacement; this.HoistedSymbols = hoistedSymbols; } public override BoundExpression Replacement<TArg>(SyntaxNode node, Func<NamedTypeSymbol, TArg, BoundExpression> makeFrame, TArg arg) { // By returning the same replacement each time, it is possible we // are constructing a DAG instead of a tree for the translation. // Because the bound trees are immutable that is usually harmless. return _replacement; } } }