File: Lowering\AsyncRewriter\AsyncRewriter.SpillBuilder.vb
Web Access
Project: src\src\roslyn\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 System.Runtime.InteropServices
Imports Microsoft.CodeAnalysis.PooledObjects
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols

Namespace Microsoft.CodeAnalysis.VisualBasic

    Partial Friend NotInheritable Class AsyncRewriter
        Inherits StateMachineRewriter(Of CapturedSymbolOrExpression)

        Private Structure SpillBuilder
            Private _locals As ArrayBuilder(Of LocalSymbol)
            Private _fields As ArrayBuilder(Of FieldSymbol)
            Private _statements As ArrayBuilder(Of BoundStatement)

            Friend Sub Free()
                If Me._locals IsNot Nothing Then
                    Me._locals.Free()
                    Me._locals = Nothing
                End If

                If Me._statements IsNot Nothing Then
                    Me._statements.Free()
                    Me._statements = Nothing
                End If

                If Me._fields IsNot Nothing Then
                    Me._fields.Free()
                    Me._fields = Nothing
                End If
            End Sub

            Friend Function BuildSequenceAndFree(F As SyntheticBoundNodeFactory, expression As BoundExpression) As BoundExpression
                If Not Me.IsEmpty Then
                    expression =
                        F.SpillSequence(If(Me._locals Is Nothing, ImmutableArray(Of LocalSymbol).Empty, Me._locals.ToImmutableAndFree()),
                                        If(Me._fields Is Nothing, ImmutableArray(Of FieldSymbol).Empty, Me._fields.ToImmutableAndFree()),
                                        If(Me._statements Is Nothing, ImmutableArray(Of BoundStatement).Empty, Me._statements.ToImmutableAndFree()),
                                        expression)
                    Me._locals = Nothing
                    Me._statements = Nothing
                    Me._fields = Nothing
                End If
                Return expression
            End Function

            Public ReadOnly Property IsEmpty As Boolean
                Get
                    Return Me._locals Is Nothing AndAlso Me._statements Is Nothing AndAlso Me._fields Is Nothing
                End Get
            End Property

            Friend Sub AddSpill(<[In]> ByRef spill As SpillBuilder)
                If Not spill.IsEmpty Then
                    AddRange(Me._locals, spill._locals)
                    AddRange(Me._fields, spill._fields)
                    AddRange(Me._statements, spill._statements)
                End If
            End Sub

            Friend Sub AddSpill(spill As BoundSpillSequence)
                AddRange(Me._locals, spill.Locals)
                AddRange(Me._fields, spill.SpillFields)
                AddRange(Me._statements, spill.Statements)
            End Sub

            Friend Sub AddFieldWithInitialization(field As FieldSymbol, init As BoundStatement)
                Debug.Assert(field IsNot Nothing)
                Debug.Assert(init IsNot Nothing)

                Add(Me._fields, field)
                Add(Me._statements, init)
            End Sub

            Friend Sub AddLocal(local As LocalSymbol)
                Add(Me._locals, local)
            End Sub

            Friend Sub AddLocals(locals As ImmutableArray(Of LocalSymbol))
                AddRange(Me._locals, locals)
            End Sub

            Friend Sub AddStatement(statement As BoundStatement)
                Add(Me._statements, statement)
            End Sub

            Friend Sub AssumeFieldsIfNeeded(<[In], Out> ByRef expression As BoundSpillSequence)
                Debug.Assert(expression IsNot Nothing)
                If Not expression.SpillFields.IsEmpty Then
                    AddRange(Me._fields, expression.SpillFields)
                    expression = expression.Update(expression.Locals,
                                                   ImmutableArray(Of FieldSymbol).Empty,
                                                   expression.Statements,
                                                   expression.ValueOpt,
                                                   expression.Type)
                End If
            End Sub

            Private Shared Sub EnsureArrayBuilder(Of T)(<[In], Out> ByRef array As ArrayBuilder(Of T))
                If array Is Nothing Then
                    array = ArrayBuilder(Of T).GetInstance()
                End If
            End Sub

            Private Shared Sub Add(Of T)(<[In], Out> ByRef array As ArrayBuilder(Of T), element As T)
                EnsureArrayBuilder(array)
                array.Add(element)
            End Sub

            Private Shared Sub AddRange(Of T)(<[In], Out> ByRef array As ArrayBuilder(Of T), other As ArrayBuilder(Of T))
                If other Is Nothing OrElse other.Count = 0 Then
                    Return
                End If

                EnsureArrayBuilder(array)
                array.AddRange(other)
            End Sub

            Private Shared Sub AddRange(Of T)(<[In], Out> ByRef array As ArrayBuilder(Of T), other As ImmutableArray(Of T))
                If other.IsEmpty Then
                    Return
                End If

                EnsureArrayBuilder(array)
                array.AddRange(other)
            End Sub

        End Structure

    End Class

End Namespace