| File: BoundTree\UnboundLambda.vb | Web Access |
| Project: 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.Concurrent Imports System.Collections.Immutable Imports System.Threading Imports Microsoft.CodeAnalysis Imports Microsoft.CodeAnalysis.Text Imports Microsoft.CodeAnalysis.VisualBasic.Symbols Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Namespace Microsoft.CodeAnalysis.VisualBasic Partial Friend NotInheritable Class UnboundLambda Inherits BoundExpression #If DEBUG Then Private Sub Validate() Debug.Assert((Flags And Not (SourceMemberFlags.Async Or SourceMemberFlags.Iterator)) = 0) End Sub #End If ''' <summary> ''' Should this lambda be treated as a single line lambda? ''' </summary> Public ReadOnly Property IsSingleLine As Boolean Get Debug.Assert(TypeOf Me.Syntax Is LambdaExpressionSyntax) Dim kind As SyntaxKind = Me.Syntax.Kind Return kind = SyntaxKind.SingleLineFunctionLambdaExpression OrElse kind = SyntaxKind.SingleLineSubLambdaExpression End Get End Property ''' <summary> ''' Is this a function lambda ''' </summary> Public ReadOnly Property IsFunctionLambda As Boolean Get Debug.Assert(TypeOf Me.Syntax Is LambdaExpressionSyntax) Dim kind As SyntaxKind = Me.Syntax.Kind Return kind = SyntaxKind.SingleLineFunctionLambdaExpression OrElse kind = SyntaxKind.MultiLineFunctionLambdaExpression End Get End Property Public Function Bind(target As TargetSignature) As BoundLambda Debug.Assert(target IsNot Nothing) Dim result As BoundLambda = _BindingCache.BoundLambdas.GetOrAdd(target, AddressOf DoBind) Debug.Assert(result IsNot Nothing) Return result End Function ''' <summary> ''' target.ReturnType is ignored and must be Void, only parameter types are taken into consideration. ''' </summary> Public Function InferReturnType(target As TargetSignature) As KeyValuePair(Of TypeSymbol, ReadOnlyBindingDiagnostic(Of AssemblySymbol)) Debug.Assert(target IsNot Nothing AndAlso target.ReturnType.IsVoidType()) If Me.ReturnType IsNot Nothing Then Dim result = New KeyValuePair(Of TypeSymbol, ReadOnlyBindingDiagnostic(Of AssemblySymbol))(If(Me.IsFunctionLambda AndAlso Me.ReturnType.IsVoidType(), LambdaSymbol.ReturnTypeVoidReplacement, Me.ReturnType), Nothing) Return _BindingCache.InferredReturnType.GetOrAdd(target, result) End If Debug.Assert(Me.IsFunctionLambda) Return _BindingCache.InferredReturnType.GetOrAdd(target, AddressOf DoInferFunctionLambdaReturnType) End Function Public Function BindForErrorRecovery() As BoundLambda Return _Binder.BindLambdaForErrorRecovery(Me) End Function Public Function GetBoundLambda(target As TargetSignature) As BoundLambda Dim result As BoundLambda = Nothing If _BindingCache.BoundLambdas.TryGetValue(target, result) Then Return result End If Return Nothing End Function Private Function DoBind(target As TargetSignature) As BoundLambda Return _Binder.BindUnboundLambda(Me, target) End Function Private Function DoInferFunctionLambdaReturnType(target As TargetSignature) As KeyValuePair(Of TypeSymbol, ReadOnlyBindingDiagnostic(Of AssemblySymbol)) Return _Binder.InferFunctionLambdaReturnType(Me, target) End Function Public ReadOnly Property InferredAnonymousDelegate As KeyValuePair(Of NamedTypeSymbol, ReadOnlyBindingDiagnostic(Of AssemblySymbol)) Get Dim info As Tuple(Of NamedTypeSymbol, ReadOnlyBindingDiagnostic(Of AssemblySymbol)) = _BindingCache.AnonymousDelegate If info Is Nothing Then Dim delegateInfo As KeyValuePair(Of NamedTypeSymbol, ReadOnlyBindingDiagnostic(Of AssemblySymbol)) = _Binder.InferAnonymousDelegateForLambda(Me) Interlocked.CompareExchange(_BindingCache.AnonymousDelegate, New Tuple(Of NamedTypeSymbol, ReadOnlyBindingDiagnostic(Of AssemblySymbol))(delegateInfo.Key, delegateInfo.Value), Nothing) info = _BindingCache.AnonymousDelegate End If Return New KeyValuePair(Of NamedTypeSymbol, ReadOnlyBindingDiagnostic(Of AssemblySymbol))(info.Item1, info.Item2) End Get End Property Public Function IsInferredDelegateForThisLambda(delegateType As NamedTypeSymbol) As Boolean Dim info As Tuple(Of NamedTypeSymbol, ReadOnlyBindingDiagnostic(Of AssemblySymbol)) = _BindingCache.AnonymousDelegate If info Is Nothing Then Return False End If Return delegateType Is info.Item1 End Function Public ReadOnly Property WithDependencies As Boolean Get Return _BindingCache.WithDependencies End Get End Property Friend Class TargetSignature Public ReadOnly ParameterTypes As ImmutableArray(Of TypeSymbol) Public ReadOnly ReturnType As TypeSymbol Public ReadOnly ReturnsByRef As Boolean Public ReadOnly ParameterIsByRef As BitVector Public Sub New(parameterTypes As ImmutableArray(Of TypeSymbol), parameterIsByRef As BitVector, returnType As TypeSymbol, returnsByRef As Boolean) Debug.Assert(Not parameterTypes.IsDefault) Debug.Assert(Not parameterIsByRef.IsNull) Debug.Assert(returnType IsNot Nothing) Me.ParameterTypes = parameterTypes Me.ParameterIsByRef = parameterIsByRef Me.ReturnType = returnType Me.ReturnsByRef = returnsByRef End Sub Public Sub New(params As ImmutableArray(Of ParameterSymbol), returnType As TypeSymbol, returnsByRef As Boolean) Debug.Assert(Not params.IsDefault) Debug.Assert(returnType IsNot Nothing) Dim isByRef = BitVector.Empty If params.Length = 0 Then Me.ParameterTypes = ImmutableArray(Of TypeSymbol).Empty Else Dim types(params.Length - 1) As TypeSymbol Dim i As Integer For i = 0 To params.Length - 1 types(i) = params(i).Type If params(i).IsByRef Then isByRef(i) = True End If Next Me.ParameterTypes = types.AsImmutableOrNull End If Me.ParameterIsByRef = isByRef Me.ReturnType = returnType Me.ReturnsByRef = returnsByRef End Sub Public Sub New(method As MethodSymbol) Me.New(method.Parameters, method.ReturnType, method.ReturnsByRef) End Sub Public Overrides Function GetHashCode() As Integer Dim hashVal As Integer = 0 For Each item In ParameterTypes hashVal = Hash.Combine(item, hashVal) Next hashVal = Hash.Combine(ReturnType, hashVal) Return hashVal End Function Public Overrides Function Equals(obj As Object) As Boolean If obj Is Me Then Return True End If Dim other = TryCast(obj, TargetSignature) If other Is Nothing OrElse other.ParameterTypes.Length <> Me.ParameterTypes.Length Then Return False End If For i As Integer = 0 To ParameterTypes.Length - 1 If Not TypeSymbol.Equals(Me.ParameterTypes(i), other.ParameterTypes(i), TypeCompareKind.ConsiderEverything) OrElse Me.ParameterIsByRef(i) <> other.ParameterIsByRef(i) Then Return False End If Next Return Me.ReturnsByRef = other.ReturnsByRef AndAlso TypeSymbol.Equals(Me.ReturnType, other.ReturnType, TypeCompareKind.ConsiderEverything) End Function End Class ''' <summary> ''' This class is used to cache various information about a lambda in the course of binding an expression/statement ''' containing the lambda. Even though the members are public, they shouldn't be accessed directly by any code ''' outside of the UnboundLambda class. ''' </summary> Public Class UnboundLambdaBindingCache Public ReadOnly WithDependencies As Boolean Public AnonymousDelegate As Tuple(Of NamedTypeSymbol, ReadOnlyBindingDiagnostic(Of AssemblySymbol)) Public ReadOnly InferredReturnType As New ConcurrentDictionary(Of TargetSignature, KeyValuePair(Of TypeSymbol, ReadOnlyBindingDiagnostic(Of AssemblySymbol)))() Public ReadOnly BoundLambdas As New ConcurrentDictionary(Of TargetSignature, BoundLambda)() Public ErrorRecoverySignature As TargetSignature Public Sub New(withDependencies As Boolean) Me.WithDependencies = withDependencies End Sub End Class End Class End Namespace