File: Lowering\LocalRewriter\LocalRewriter_RedimClause.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 System.Diagnostics
Imports System.Runtime.InteropServices
Imports Microsoft.CodeAnalysis.PooledObjects
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports TypeKind = Microsoft.CodeAnalysis.TypeKind
 
Namespace Microsoft.CodeAnalysis.VisualBasic
    Partial Friend NotInheritable Class LocalRewriter
        Public Overrides Function VisitRedimClause(node As BoundRedimClause) As BoundNode
            '  array type must be known if the node is valid
            Debug.Assert(node.ArrayTypeOpt IsNot Nothing)
 
            '  build expression returning created (and optionally initialized) array
            Dim valueBeingAssigned As BoundExpression = New BoundArrayCreation(node.Syntax,
                                                                               node.Indices, Nothing, node.ArrayTypeOpt)
 
            Dim temporaries As ArrayBuilder(Of SynthesizedLocal) = Nothing
            Dim assignmentTarget = node.Operand
            Dim useSiteInfo = GetNewCompoundUseSiteInfo()
 
            Dim copyArrayUtilityMethod As MethodSymbol = Nothing
            If node.Preserve AndAlso TryGetWellknownMember(copyArrayUtilityMethod, WellKnownMember.Microsoft_VisualBasic_CompilerServices_Utils__CopyArray, node.Syntax) Then
                ' build a call to Microsoft.VisualBasic.CompilerServices.Utils.CopyArray
 
                '  use the operand twice
                temporaries = ArrayBuilder(Of SynthesizedLocal).GetInstance()
                Dim result As UseTwiceRewriter.Result = UseTwiceRewriter.UseTwice(Me._currentMethodOrLambda, assignmentTarget, isForRegularCompoundAssignment:=True, temporaries)
 
                '  the first to be used as an assignment target
                assignmentTarget = result.First
                '  the second will be used for accessing the array's current value
                Dim arrayValueAccess = result.Second
 
                '  make an r-value from array value access
                If arrayValueAccess.Kind = BoundKind.PropertyAccess Then
                    arrayValueAccess = DirectCast(arrayValueAccess, BoundPropertyAccess).SetAccessKind(PropertyAccessKind.Get)
                ElseIf arrayValueAccess.IsLateBound() Then
                    arrayValueAccess = arrayValueAccess.SetLateBoundAccessKind(LateBoundAccessKind.Get)
                Else
                    arrayValueAccess = arrayValueAccess.MakeRValue()
                End If
 
                '  System.Array type
                Dim systemArray = copyArrayUtilityMethod.Parameters(0).Type
 
                '  add conversion
                arrayValueAccess = New BoundDirectCast(node.Syntax, arrayValueAccess,
                                                       Conversions.ClassifyDirectCastConversion(arrayValueAccess.Type, systemArray, useSiteInfo),
                                                       systemArray, Nothing)
 
                valueBeingAssigned = New BoundDirectCast(node.Syntax, valueBeingAssigned,
                                                       Conversions.ClassifyDirectCastConversion(valueBeingAssigned.Type, systemArray, useSiteInfo),
                                                       systemArray, Nothing)
 
                '  bind call to CopyArray
                valueBeingAssigned = New BoundCall(node.Syntax,
                                                   copyArrayUtilityMethod, Nothing, Nothing,
                                                   ImmutableArray.Create(Of BoundExpression)(arrayValueAccess, valueBeingAssigned),
                                                   Nothing, systemArray)
            End If
 
            '  add conversion if needed
            valueBeingAssigned = New BoundDirectCast(node.Syntax, valueBeingAssigned,
                                                     Conversions.ClassifyDirectCastConversion(valueBeingAssigned.Type, assignmentTarget.Type, useSiteInfo),
                                                     assignmentTarget.Type, Nothing)
            _diagnostics.Add(node, useSiteInfo)
 
            '  adjust assignment target
            If assignmentTarget.Kind = BoundKind.PropertyAccess Then
                assignmentTarget = DirectCast(assignmentTarget, BoundPropertyAccess).SetAccessKind(PropertyAccessKind.Set)
            ElseIf assignmentTarget.IsLateBound() Then
                assignmentTarget = assignmentTarget.SetLateBoundAccessKind(LateBoundAccessKind.Set)
            End If
 
            '  create assignment operator
            Dim assignmentOperator As BoundExpression = New BoundAssignmentOperator(node.Syntax, assignmentTarget,
                                                                 valueBeingAssigned, True)
 
            '  if there are any temporaries, wrap it in 
            If temporaries IsNot Nothing Then
                If temporaries.Count > 0 Then
                    assignmentOperator = New BoundSequence(node.Syntax,
                                                           StaticCast(Of LocalSymbol).From(temporaries.ToImmutableAndFree()),
                                                           ImmutableArray.Create(Of BoundExpression)(assignmentOperator),
                                                           Nothing,
                                                           If(assignmentOperator.Type.IsVoidType(),
                                                              assignmentOperator.Type,
                                                              Compilation.GetSpecialType(SpecialType.System_Void)))
                Else
                    temporaries.Free()
                End If
            End If
 
            '  create assignment statement
            Return Visit(New BoundExpressionStatement(node.Syntax, assignmentOperator))
        End Function
    End Class
End Namespace