arraycreationexpression.vb
来自「大名鼎鼎的mono是.NET平台的跨平台(支持linux」· VB 代码 · 共 274 行
VB
274 行
' ' Visual Basic.Net Compiler' Copyright (C) 2004 - 2007 Rolf Bjarne Kvinge, RKvinge@novell.com' ' This library is free software; you can redistribute it and/or' modify it under the terms of the GNU Lesser General Public' License as published by the Free Software Foundation; either' version 2.1 of the License, or (at your option) any later version.' ' This library is distributed in the hope that it will be useful,' but WITHOUT ANY WARRANTY; without even the implied warranty of' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU' Lesser General Public License for more details.' ' You should have received a copy of the GNU Lesser General Public' License along with this library; if not, write to the Free Software' Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA' ''' <summary>''' ArrayCreationExpression ::= "New" NonArrayTypeName ArraySizeInitializationModifier ArrayElementInitializer''' ''' LAMESPEC? I think the following should be used:''' ArrayCreationExpression ::= "New" NonArrayTypeName ArrayNameModifier ArrayElementInitializer''' ''' A New expression is classified as a value and the result is the new instance of the type.''' </summary>''' <remarks></remarks>Public Class ArrayCreationExpression Inherits Expression Private m_NonArrayTypeName As NonArrayTypeName Private m_ArrayNameModifier As ArrayNameModifier Private m_ArrayElementInitializer As ArrayElementInitializer Private m_ExpressionType As Type ReadOnly Property ArrayElementInitalizer() As ArrayElementInitializer Get Return m_ArrayElementInitializer End Get End Property Public Overrides ReadOnly Property IsConstant() As Boolean Get Return False End Get End Property Public Overrides Function ResolveTypeReferences() As Boolean Dim result As Boolean = True If m_NonArrayTypeName IsNot Nothing Then result = m_NonArrayTypeName.ResolveTypeReferences AndAlso result If m_ArrayNameModifier IsNot Nothing Then result = m_ArrayNameModifier.ResolveTypeReferences AndAlso result If m_ArrayElementInitializer IsNot Nothing Then result = m_ArrayElementInitializer.ResolveTypeReferences AndAlso result Return result End Function Sub New(ByVal Parent As ParsedObject) MyBase.New(Parent) End Sub Sub Init(ByVal NonArrayTypeName As NonArrayTypeName, ByVal ArrayNameModifier As ArrayNameModifier, ByVal ArrayElementInitializer As ArrayElementInitializer) m_NonArrayTypeName = NonArrayTypeName m_ArrayNameModifier = ArrayNameModifier m_ArrayElementInitializer = ArrayElementInitializer End Sub Sub Init(ByVal ArrayType As Type, ByVal InitializerElements As Expression()) m_ExpressionType = ArrayType m_ArrayElementInitializer = New ArrayElementInitializer(Me) m_ArrayElementInitializer.Init(InitializerElements) End Sub Sub Init(ByVal ArrayType As Type, ByVal ArrayBounds() As Expression, ByVal InitializerElements As Expression()) m_ExpressionType = ArrayType If ArrayBounds IsNot Nothing Then m_ArrayNameModifier = New ArrayNameModifier(Me) Dim newSizes As New ArraySizeInitializationModifier(Me) Dim bounds As New BoundList(newSizes) bounds.Init(ArrayBounds) newSizes.Init(bounds, Nothing) m_ArrayNameModifier.Init(newSizes) End If If InitializerElements IsNot Nothing Then m_ArrayElementInitializer = New ArrayElementInitializer(Me) m_ArrayElementInitializer.Init(InitializerElements) End If End Sub Public Shared Sub EmitArrayCreation(ByVal Parent As ParsedObject, ByVal Info As EmitInfo, ByVal ArrayType As Type, ByVal asim As ArraySizeInitializationModifier) If asim.ArrayTypeModifiers Is Nothing OrElse True Then Dim Ranks As Integer = asim.BoundList.Expressions.Length For i As Integer = 0 To Ranks - 1 Dim litexp As New ConstantExpression(Parent, 1, Parent.Compiler.TypeCache.System_Int32) Dim exp As BinaryAddExpression exp = New BinaryAddExpression(Parent, asim.BoundList.Expressions(i), litexp) If exp.ResolveExpression(ResolveInfo.Default(Info.Compiler)) = False Then Throw New InternalException(Parent) If exp.GenerateCode(Info.Clone(True)) = False Then Throw New InternalException(parent) Emitter.EmitConversion(exp.ExpressionType, Parent.Compiler.TypeCache.System_Int32, Info) Next EmitArrayConstructor(Info, ArrayType, Ranks) Else Helper.NotImplemented() End If End Sub ''' <summary> ''' Creates an array of the specified type and number of elements (and ranks) ''' </summary> ''' <param name="Info"></param> ''' <param name="arraytype"></param> ''' <param name="Elements"></param> ''' <remarks></remarks> Public Shared Sub EmitArrayCreation(ByVal Info As EmitInfo, ByVal ArrayType As Type, ByVal Elements As Generic.List(Of Integer)) If Elements.Count = 0 Then Emitter.EmitLoadI4Value(Info, 0) Else For i As Integer = 0 To Elements.Count - 1 Emitter.EmitLoadI4Value(Info, Elements(i)) Next End If EmitArrayConstructor(Info, ArrayType, Elements.Count) End Sub ''' <summary> ''' Emits the array constructor. ''' The number of elements for each rank must be emitted already. ''' </summary> ''' <param name="Info"></param> ''' <param name="ArrayType"></param> ''' <param name="Ranks"></param> ''' <remarks></remarks> Public Shared Sub EmitArrayConstructor(ByVal Info As EmitInfo, ByVal ArrayType As Type, ByVal Ranks As Integer) If Ranks <= 1 Then Emitter.EmitNewArr(Info, ArrayType.GetElementType) Else Dim ctor As ConstructorInfo Dim types() As Type = Helper.CreateArray(Of Type)(Info.Compiler.TypeCache.System_Int32, Ranks) ctor = Info.Compiler.TypeManager.GetRegisteredType(ArrayType).GetConstructor(BindingFlags.ExactBinding Or BindingFlags.Instance Or BindingFlags.Public Or BindingFlags.DeclaredOnly, Nothing, Nothing, types, Nothing) If ctor IsNot Nothing Then Emitter.EmitNew(Info, ctor) Else Dim minfo As MethodInfo minfo = Info.Compiler.ModuleBuilder.GetArrayMethod(ArrayType, ".ctor", CallingConventions.HasThis Or CallingConventions.Standard, Nothing, types) Emitter.EmitNew(Info, minfo, types) End If End If End Sub Protected Overrides Function GenerateCodeInternal(ByVal Info As EmitInfo) As Boolean Dim result As Boolean = True Dim ArrayType As Type = Helper.GetTypeOrTypeBuilder(ExpressionType()) Dim tmpVar As LocalBuilder = Info.ILGen.DeclareLocal(ArrayType) If m_ArrayNameModifier Is Nothing OrElse m_ArrayNameModifier.IsArrayTypeModifiers Then EmitArrayCreation(Info, ArrayType, m_ArrayElementInitializer.Elements) ElseIf m_ArrayNameModifier.IsArraySizeInitializationModifier Then EmitArrayCreation(Me, Info, ArrayType, m_ArrayNameModifier.AsArraySizeInitializationModifier) Else Throw New InternalException(Me) End If Emitter.EmitStoreVariable(Info, tmpVar) If m_ArrayElementInitializer IsNot Nothing AndAlso m_ArrayElementInitializer.Initializers IsNot Nothing Then With m_ArrayElementInitializer.Initializers Dim indices As New Generic.List(Of Integer) For i As Integer = 0 To .List.ToArray.GetUpperBound(0) indices.Add(i) result = EmitElementInitializer(Info, .List.ToArray(i), 1, i, tmpVar, ArrayType, indices) AndAlso result indices.RemoveAt(indices.Count - 1) Next End With End If Emitter.EmitLoadVariable(Info, tmpVar) Return result End Function Private Function EmitElementInitializer(ByVal Info As EmitInfo, ByVal Initializer As VariableInitializer, ByVal CurrentDepth As Integer, ByVal ElementIndex As Integer, ByVal ArrayVariable As LocalBuilder, ByVal ArrayType As Type, ByVal Indices As Generic.List(Of Integer)) As Boolean Dim result As Boolean = True Dim vi As VariableInitializer = Initializer Dim elementType As Type = ArrayType.GetElementType If vi.IsRegularInitializer Then Emitter.EmitLoadVariable(Info, ArrayVariable) For i As Integer = 0 To Indices.Count - 1 Emitter.EmitLoadValue(Info.Clone(True, False, Compiler.TypeCache.System_Int32), Indices(i)) Next If elementType.IsValueType AndAlso elementType.IsPrimitive = False AndAlso elementType.IsEnum = False Then Emitter.EmitLoadElementAddress(Info, elementType, ArrayType) End If result = vi.AsRegularInitializer.GenerateCode(Info.Clone(True, False, elementType)) AndAlso result If CurrentDepth = 1 Then Emitter.EmitStoreElement(Info, elementType, ArrayType) Else Dim setmethod As MethodInfo Dim settypes(CurrentDepth) As Type For i As Integer = 0 To CurrentDepth - 1 settypes(i) = Compiler.TypeCache.System_Int32 Next settypes(CurrentDepth) = ArrayType.GetElementType setmethod = ArrayType.GetMethod("Set", settypes) Emitter.EmitCallOrCallVirt(Info, setmethod) End If ElseIf vi.IsArrayElementInitializer Then For i As Integer = 0 To vi.AsArrayElementInitializer.Initializers.List.ToArray.GetUpperBound(0) Indices.Add(i) result = EmitElementInitializer(Info, vi.AsArrayElementInitializer.Initializers.List.ToArray(i), CurrentDepth + 1, i, ArrayVariable, ArrayType, Indices) AndAlso result Indices.RemoveAt(Indices.Count - 1) Next Else Throw New InternalException(Me) End If Return result End Function Protected Overrides Function ResolveExpressionInternal(ByVal Info As ResolveInfo) As Boolean Dim result As Boolean = True If m_ExpressionType Is Nothing Then result = m_NonArrayTypeName.ResolveTypeReferences AndAlso result If m_ArrayNameModifier IsNot Nothing Then result = m_ArrayNameModifier.ResolveCode(Info) AndAlso result Dim tmptp As Type = m_NonArrayTypeName.ResolvedType If m_ArrayNameModifier.IsArraySizeInitializationModifier Then tmptp = m_ArrayNameModifier.AsArraySizeInitializationModifier.CreateArrayType(tmptp) ElseIf m_ArrayNameModifier.IsArrayTypeModifiers Then tmptp = m_ArrayNameModifier.AsArrayTypeModifiers.CreateArrayType(tmptp) Else Throw New InternalException(Me) End If m_ExpressionType = tmptp End If If m_ArrayElementInitializer IsNot Nothing Then Dim elementInfo As New ExpressionResolveInfo(Compiler, m_ExpressionType) result = m_ArrayElementInitializer.ResolveCode(elementInfo) AndAlso result End If Classification = New ValueClassification(Me, m_ExpressionType) Return result End Function Overrides ReadOnly Property ExpressionType() As Type Get If Me.IsResolved Then Return m_ExpressionType ElseIf m_ExpressionType IsNot Nothing Then Return m_ExpressionType Else Throw New InternalException(Me) End If End Get End PropertyEnd Class
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?