File: Lowering\AsyncRewriter\AsyncRewriter.CapturedSymbolOrExpression.vb
Web Access
Project: src\src\Compilers\VisualBasic\Portable\Microsoft.CodeAnalysis.VisualBasic.vbproj (Microsoft.CodeAnalysis.VisualBasic)
' 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.
 
Imports System.Collections.Immutable
Imports Microsoft.Cci
Imports Microsoft.CodeAnalysis.PooledObjects
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
 
Namespace Microsoft.CodeAnalysis.VisualBasic
 
    Partial Friend NotInheritable Class AsyncRewriter
        Inherits StateMachineRewriter(Of CapturedSymbolOrExpression)
 
        Friend MustInherit Class CapturedSymbolOrExpression
            ''' <summary>
            ''' Materialize the capture, e.g. return an expression to be used instead of captured symbol
            ''' </summary>
            Friend MustOverride Function Materialize(rewriter As AsyncRewriter.AsyncMethodToClassRewriter, isLValue As Boolean) As BoundExpression
 
            ''' <summary>
            ''' Add proxy field(s) if any to the array builder provided
            ''' 
            ''' Note: is used for binding BoundStateMachineScope with 
            '''       correspondent local/field references
            ''' </summary>
            Friend Overridable Sub AddProxyFieldsForStateMachineScope(proxyFields As ArrayBuilder(Of FieldSymbol))
                Debug.Assert(False, "This method should not be called for " + Me.GetType.Name)
            End Sub
 
            ''' <summary>
            ''' Create assignment expressions initializing for this capture, is only supposed to be
            ''' used for proper handling of reference assignments
            ''' </summary>
            Friend MustOverride Sub CreateCaptureInitializationCode(rewriter As AsyncRewriter.AsyncMethodToClassRewriter, prologue As ArrayBuilder(Of BoundExpression))
        End Class
 
        Private Class CapturedConstantExpression
            Inherits CapturedSymbolOrExpression
 
            Private ReadOnly _constValue As ConstantValue
            Private ReadOnly _type As TypeSymbol
 
            Public Sub New(constValue As ConstantValue, type As TypeSymbol)
                Debug.Assert(constValue IsNot Nothing)
                Debug.Assert(type IsNot Nothing)
                Me._constValue = constValue
                Me._type = type
            End Sub
 
            Friend Overloads Overrides Sub CreateCaptureInitializationCode(rewriter As AsyncRewriter.AsyncMethodToClassRewriter, prologue As ArrayBuilder(Of BoundExpression))
            End Sub
 
            Friend Overloads Overrides Function Materialize(rewriter As AsyncMethodToClassRewriter, isLValue As Boolean) As BoundExpression
                Debug.Assert(Not isLValue)
                Return New BoundLiteral(rewriter.F.Syntax, Me._constValue, Me._type)
            End Function
        End Class
 
        Private MustInherit Class SingleFieldCapture
            Inherits CapturedSymbolOrExpression
 
            Friend ReadOnly Field As FieldSymbol
 
            Public Sub New(field As FieldSymbol)
                Debug.Assert(field IsNot Nothing)
                Me.Field = field
            End Sub
 
            Friend Overloads Overrides Function Materialize(rewriter As AsyncRewriter.AsyncMethodToClassRewriter, isLValue As Boolean) As BoundExpression
                Dim syntax As SyntaxNode = rewriter.F.Syntax
                Dim framePointer As BoundExpression = rewriter.FramePointer(syntax, Me.Field.ContainingType)
                Dim proxyFieldParented = Me.Field.AsMember(DirectCast(framePointer.Type, NamedTypeSymbol))
                Return rewriter.F.Field(framePointer, proxyFieldParented, isLValue)
            End Function
        End Class
 
        Private Class CapturedParameterSymbol
            Inherits SingleFieldCapture
 
            Public Sub New(field As FieldSymbol)
                MyBase.New(field)
            End Sub
 
            Friend Overloads Overrides Sub CreateCaptureInitializationCode(rewriter As AsyncRewriter.AsyncMethodToClassRewriter, prologue As ArrayBuilder(Of BoundExpression))
                ' Don't anything, parameters' proxy fields should only be initialized once
                ' and it is done in AsyncRewriter.InitializeParameterWithProxy
            End Sub
        End Class
 
        Private Class CapturedLocalSymbol
            Inherits SingleFieldCapture
 
            Friend ReadOnly Local As LocalSymbol
 
            Public Sub New(field As FieldSymbol, local As LocalSymbol)
                MyBase.New(field)
                Me.Local = local
            End Sub
 
            Friend Overrides Sub AddProxyFieldsForStateMachineScope(proxyFields As ArrayBuilder(Of FieldSymbol))
                proxyFields.Add(Me.Field)
            End Sub
 
            Friend Overloads Overrides Sub CreateCaptureInitializationCode(rewriter As AsyncRewriter.AsyncMethodToClassRewriter, prologue As ArrayBuilder(Of BoundExpression))
                ' Don't anything, those fields are supposed to replace local in all the method's code
            End Sub
        End Class
 
        Private Class CapturedRValueExpression
            Inherits SingleFieldCapture
 
            Friend ReadOnly Expression As BoundExpression
 
            Public Sub New(field As FieldSymbol, expr As BoundExpression)
                MyBase.New(field)
 
                Debug.Assert(Not expr.IsLValue)
                Me.Expression = expr
            End Sub
 
            Friend Overloads Overrides Sub CreateCaptureInitializationCode(rewriter As AsyncRewriter.AsyncMethodToClassRewriter, prologue As ArrayBuilder(Of BoundExpression))
                ' Initialize with expression
                prologue.Add(
                    rewriter.ProcessRewrittenAssignmentOperator(
                        rewriter.F.AssignmentExpression(
                            Me.Materialize(rewriter, True),
                            rewriter.VisitExpression(Expression))))
            End Sub
        End Class
 
        Private Class CapturedFieldAccessExpression
            Inherits CapturedSymbolOrExpression
 
            Friend ReadOnly ReceiverOpt As CapturedSymbolOrExpression
            Friend ReadOnly Field As FieldSymbol
 
            Public Sub New(receiverOpt As CapturedSymbolOrExpression, field As FieldSymbol)
                Debug.Assert((field.IsShared) = (receiverOpt Is Nothing))
                Me.ReceiverOpt = receiverOpt
                Me.Field = field
            End Sub
 
            Friend Overloads Overrides Sub CreateCaptureInitializationCode(rewriter As AsyncRewriter.AsyncMethodToClassRewriter, prologue As ArrayBuilder(Of BoundExpression))
                If Me.ReceiverOpt IsNot Nothing Then
                    Me.ReceiverOpt.CreateCaptureInitializationCode(rewriter, prologue)
                End If
            End Sub
 
            Friend Overloads Overrides Function Materialize(rewriter As AsyncMethodToClassRewriter, isLValue As Boolean) As BoundExpression
                Dim newReceiverOpt As BoundExpression = Nothing
                If Me.ReceiverOpt IsNot Nothing Then
                    newReceiverOpt = Me.ReceiverOpt.Materialize(rewriter, Me.Field.ContainingType.IsValueType)
                End If
                Return rewriter.F.Field(newReceiverOpt, rewriter.VisitFieldSymbol(Me.Field), isLValue)
            End Function
        End Class
 
        Private Class CapturedArrayAccessExpression
            Inherits CapturedSymbolOrExpression
 
            Friend ReadOnly ArrayPointer As CapturedSymbolOrExpression
            Friend ReadOnly Indices As ImmutableArray(Of CapturedSymbolOrExpression)
 
            Public Sub New(arrayPointer As CapturedSymbolOrExpression, indices As ImmutableArray(Of CapturedSymbolOrExpression))
                Debug.Assert(arrayPointer IsNot Nothing)
                Debug.Assert(Not indices.IsEmpty)
 
                Me.ArrayPointer = arrayPointer
                Me.Indices = indices
            End Sub
 
            Friend Overloads Overrides Sub CreateCaptureInitializationCode(rewriter As AsyncRewriter.AsyncMethodToClassRewriter, prologue As ArrayBuilder(Of BoundExpression))
                Me.ArrayPointer.CreateCaptureInitializationCode(rewriter, prologue)
                For Each index In Me.Indices
                    index.CreateCaptureInitializationCode(rewriter, prologue)
                Next
            End Sub
 
            Friend Overloads Overrides Function Materialize(rewriter As AsyncMethodToClassRewriter, isLValue As Boolean) As BoundExpression
                Dim origIndices As ImmutableArray(Of CapturedSymbolOrExpression) = Me.Indices
                Dim indicesCount As Integer = origIndices.Length
 
                Dim indices(indicesCount - 1) As BoundExpression
                For i = 0 To indicesCount - 1
                    indices(i) = origIndices(i).Materialize(rewriter, False)
                Next
 
                Dim arrayPointer As BoundExpression = Me.ArrayPointer.Materialize(rewriter, False)
                Dim arrayElementType As TypeSymbol = DirectCast(arrayPointer.Type, ArrayTypeSymbol).ElementType
 
                Return rewriter.F.ArrayAccess(arrayPointer, isLValue, indices)
            End Function
        End Class
 
    End Class
 
End Namespace