1' 2' Visual Basic.Net Compiler 3' Copyright (C) 2004 - 2010 Rolf Bjarne Kvinge, RKvinge@novell.com 4' 5' This library is free software; you can redistribute it and/or 6' modify it under the terms of the GNU Lesser General Public 7' License as published by the Free Software Foundation; either 8' version 2.1 of the License, or (at your option) any later version. 9' 10' This library is distributed in the hope that it will be useful, 11' but WITHOUT ANY WARRANTY; without even the implied warranty of 12' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13' Lesser General Public License for more details. 14' 15' You should have received a copy of the GNU Lesser General Public 16' License along with this library; if not, write to the Free Software 17' Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18' 19 20''' <summary> 21''' Every variable has an associated type, namely the declared type of the variable. 22''' </summary> 23''' <remarks></remarks> 24Public Class VariableClassification 25 Inherits ExpressionClassification 26 27 Private m_ParameterInfo As Mono.Cecil.ParameterDefinition 28 Private m_FieldInfo As Mono.Cecil.FieldReference 29 Private m_LocalBuilder As Mono.Cecil.Cil.VariableDefinition 30 31 Private m_InstanceExpression As Expression 32 Private m_Parameter As Parameter 33 Private m_Variable As VariableDeclaration 34 Private m_LocalVariable As LocalVariableDeclaration 35 Private m_TypeVariable As TypeVariableDeclaration 36 Private m_Method As IMethod 37 Private m_Expression As Expression 38 39 Private m_ExpressionType As Mono.Cecil.TypeReference 40 41 Private m_ArrayVariable As Expression 42 Private m_Arguments As ArgumentList 43 44 ReadOnly Property LocalVariable As LocalVariableDeclaration 45 Get 46 Return m_LocalVariable 47 End Get 48 End Property 49 50 ReadOnly Property Method() As IMethod 51 Get 52 Return m_Method 53 End Get 54 End Property 55 56 ReadOnly Property Expression() As Expression 57 Get 58 Return m_Expression 59 End Get 60 End Property 61 62 ReadOnly Property ArrayVariable() As Expression 63 Get 64 Return m_ArrayVariable 65 End Get 66 End Property 67 68 ReadOnly Property Arguments() As ArgumentList 69 Get 70 Return m_Arguments 71 End Get 72 End Property 73 74 Public Overrides Function GetConstant(ByRef value As Object, ByVal ShowError As Boolean) As Boolean 75 If Me.FieldInfo IsNot Nothing Then 76 Dim attrib As Object 77 Dim dec As Decimal, dt As Date 78 Dim constant As ConstantDeclaration 79 Dim enumc As EnumMemberDeclaration 80 81 attrib = FieldDefinition.Annotations(Compiler) 82 83 If attrib IsNot Nothing Then 84 enumc = TryCast(attrib, EnumMemberDeclaration) 85 If enumc IsNot Nothing Then Return enumc.GetConstantValue(value) 86 87 constant = TryCast(attrib, ConstantDeclaration) 88 If constant IsNot Nothing Then Return constant.GetConstant(value, ShowError) 89 End If 90 91 If Me.FieldDefinition.IsLiteral Then 92 value = Me.FieldDefinition.Constant 93 Return True 94 ElseIf Me.FieldDefinition.IsInitOnly Then 95 If ConstantDeclaration.GetDecimalConstant(Compiler, FieldDefinition, dec) Then 96 value = dec 97 Return True 98 ElseIf ConstantDeclaration.GetDateConstant(Compiler, FieldDefinition, dt) Then 99 value = dt 100 Return True 101 Else 102 If ShowError Then Parent.Show30059() 103 Return False 104 End If 105 Else 106 If ShowError Then Parent.Show30059() 107 Return False 108 End If 109 ElseIf m_LocalVariable IsNot Nothing Then 110 If m_LocalVariable.IsConst Then 111 If m_LocalVariable.VariableInitializer.IsRegularInitializer Then 112 Return m_LocalVariable.VariableInitializer.AsRegularInitializer.GetConstant(value, ShowError) 113 End If 114 If ShowError Then Parent.Show30059() 115 Return False 116 End If 117 Else 118 If ShowError Then Parent.Show30059() 119 Return False 120 End If 121 End Function 122 123 ReadOnly Property ParameterInfo() As Mono.Cecil.ParameterDefinition 124 Get 125 Return m_ParameterInfo 126 End Get 127 End Property 128 129 ReadOnly Property LocalBuilder() As Mono.Cecil.Cil.VariableDefinition 130 Get 131 If m_LocalVariable IsNot Nothing Then 132 Return m_LocalVariable.LocalBuilder 133 Else 134 Return Nothing 135 End If 136 End Get 137 End Property 138 139 ReadOnly Property FieldDefinition() As Mono.Cecil.FieldDefinition 140 Get 141 If m_TypeVariable IsNot Nothing AndAlso m_TypeVariable.FieldBuilder IsNot Nothing Then 142 Return m_TypeVariable.FieldBuilder 143 ElseIf m_LocalVariable IsNot Nothing AndAlso m_LocalVariable.FieldBuilder IsNot Nothing Then 144 Return m_LocalVariable.FieldBuilder 145 Else 146 Return CecilHelper.FindDefinition(m_FieldInfo) 147 End If 148 End Get 149 End Property 150 151 ReadOnly Property FieldInfo() As Mono.Cecil.FieldReference 152 Get 153 If m_TypeVariable IsNot Nothing AndAlso m_TypeVariable.FieldBuilder IsNot Nothing Then 154 Return m_TypeVariable.FieldBuilder 155 ElseIf m_LocalVariable IsNot Nothing AndAlso m_LocalVariable.FieldBuilder IsNot Nothing Then 156 Return m_LocalVariable.FieldBuilder 157 Else 158 Return m_FieldInfo 159 End If 160 End Get 161 End Property 162 163 164 ''' <summary> 165 ''' Loads the value of the variable. 166 ''' </summary> 167 ''' <param name="Info"></param> 168 ''' <returns></returns> 169 ''' <remarks></remarks> 170 Friend Function GenerateCodeAsValue(ByVal Info As EmitInfo) As Boolean 171 Dim result As Boolean = True 172 173 Helper.Assert(Info.DesiredType IsNot Nothing) 174 175 If m_InstanceExpression IsNot Nothing Then 176 result = m_InstanceExpression.GenerateCode(Info) AndAlso result 177 End If 178 179 If FieldInfo IsNot Nothing Then 180 If Info.IsRHS Then 181 Emitter.EmitLoadVariable(Info, FieldInfo) 182 Else 183 Return Compiler.Report.ShowMessage(Messages.VBNC99997, Parent.Location) 184 End If 185 ElseIf LocalBuilder IsNot Nothing Then 186 If Info.IsRHS Then 187 Emitter.EmitLoadVariable(Info, LocalBuilder) 188 Else 189 Return Compiler.Report.ShowMessage(Messages.VBNC99997, Parent.Location) 190 End If 191 ElseIf ParameterInfo IsNot Nothing Then 192 Helper.Assert(m_InstanceExpression Is Nothing) 193 If Info.IsRHS Then 194 Emitter.EmitLoadVariable(Info, ParameterInfo) 195 Else 196 Return Compiler.Report.ShowMessage(Messages.VBNC99997, Parent.Location) 197 End If 198 ElseIf m_ArrayVariable IsNot Nothing Then 199 result = Helper.EmitLoadArrayElement(Info, m_ArrayVariable, m_Arguments) AndAlso result 200 ElseIf m_Expression IsNot Nothing Then 201 result = m_Expression.GenerateCode(Info) AndAlso result 202 Else 203 Throw New InternalException(Me) 204 End If 205 206 If CecilHelper.IsByRef(Info.DesiredType) Then 207 Dim elementType As Mono.Cecil.TypeReference = CecilHelper.GetElementType(Info.DesiredType) 208 Dim local As Mono.Cecil.Cil.VariableDefinition 209 local = Emitter.DeclareLocal(Info, elementType) 210 211 Emitter.EmitStoreVariable(Info, local) 212 Emitter.EmitLoadVariableLocation(Info, local) 213 End If 214 215 Return result 216 End Function 217 218 ''' <summary> 219 ''' Stores at the address of the variable. 220 ''' </summary> 221 ''' <param name="Info"></param> 222 ''' <returns></returns> 223 ''' <remarks></remarks> 224 Friend Overrides Function GenerateCode(ByVal Info As EmitInfo) As Boolean 225 Dim result As Boolean = True 226 227 If m_Expression IsNot Nothing Then 228 Return m_Expression.GenerateCode(Info) 229 End If 230 231 Helper.Assert(Info.IsRHS AndAlso Info.RHSExpression Is Nothing OrElse Info.IsLHS AndAlso Info.RHSExpression IsNot Nothing) 232 233 If m_InstanceExpression IsNot Nothing Then 234 Dim exp As Mono.Cecil.TypeReference = m_InstanceExpression.ExpressionType 235 If CecilHelper.IsValueType(exp) AndAlso CecilHelper.IsByRef(exp) = False Then 236 exp = Compiler.TypeManager.MakeByRefType(Me.Parent, exp) 237 End If 238 result = m_InstanceExpression.GenerateCode(Info.Clone(Parent, True, False, exp)) AndAlso result 239 End If 240 241 If FieldInfo IsNot Nothing Then 242 If Info.IsRHS Then 243 If CecilHelper.IsByRef(Info.DesiredType) Then 244 Emitter.EmitLoadVariableLocation(Info, FieldInfo) 245 Else 246 Emitter.EmitLoadVariable(Info, FieldInfo) 247 End If 248 Else 249 Dim rInfo As EmitInfo = Info.Clone(Parent, True, False, FieldInfo.FieldType) 250 251 Helper.Assert(Info.RHSExpression IsNot Nothing) 252 Helper.Assert(Info.RHSExpression.Classification.IsValueClassification) 253 result = Info.RHSExpression.Classification.GenerateCode(rInfo) AndAlso result 254 255 Emitter.EmitConversion(Info.RHSExpression.ExpressionType, FieldInfo.FieldType, Info.Clone(Parent, Info.RHSExpression.ExpressionType)) 256 Emitter.EmitStoreField(Info, FieldInfo) 257 End If 258 ElseIf LocalBuilder IsNot Nothing Then 259 result = VariableExpression.Emit(Info, LocalBuilder) AndAlso result 260 ElseIf ParameterInfo IsNot Nothing Then 261 Dim isByRef As Boolean 262 Dim isByRefStructure As Boolean 263 Dim paramType As Mono.Cecil.TypeReference 264 Dim paramElementType As Mono.Cecil.TypeReference = Nothing 265 266 paramType = ParameterInfo.ParameterType 267 isByRef = CecilHelper.IsByRef(paramType) 268 If isByRef Then 269 paramElementType = CecilHelper.GetElementType(paramType) 270 isByRefStructure = CecilHelper.IsValueType(paramElementType) 271 End If 272 273 Helper.Assert(m_InstanceExpression Is Nothing) 274 275 If Info.IsRHS Then 276 If isByRef Then 277 Return Compiler.Report.ShowMessage(Messages.VBNC99997, Parent.Location) 278 Else 279 Emitter.EmitLoadVariable(Info, ParameterInfo) 280 End If 281 Else 282 Dim rInfo As EmitInfo 283 Dim rhs As Expression = Info.RHSExpression 284 Dim paramConsumed As Boolean 285 286 If isByRefStructure Then 287 Emitter.EmitLoadVariable(Info.Clone(Parent, paramType), ParameterInfo) 288 If TypeOf rhs Is GetRefExpression Then rhs = DirectCast(rhs, GetRefExpression).Expression 289 'paramConsumed = TypeOf rhs Is NewExpression 290 If paramConsumed Then 291 rInfo = Info.Clone(Parent, True, False, paramType) 292 Else 293 rInfo = Info.Clone(Parent, True, False, paramElementType) 294 End If 295 ElseIf isByRef Then 296 Emitter.EmitLoadVariableLocation(Info, ParameterInfo) 297 rInfo = Info.Clone(Parent, True, False, paramElementType) 298 Else 299 rInfo = Info.Clone(Parent, True, False, paramType) 300 End If 301 302 Helper.Assert(rhs IsNot Nothing, "RHSExpression Is Nothing!") 303 Helper.Assert(rhs.Classification.IsValueClassification) 304 result = rhs.Classification.GenerateCode(rInfo) AndAlso result 305 306 If Not paramConsumed Then 307 If isByRef = False Then 308 Emitter.EmitConversion(rhs.ExpressionType, paramType, Info) 309 End If 310 If isByRefStructure Then 311 Emitter.EmitStoreIndirect(Info, paramType) 312 Else 313 Emitter.EmitStoreVariable(Info, ParameterInfo) 314 End If 315 End If 316 End If 317 ElseIf Me.m_Variable IsNot Nothing Then 318 If Info.IsRHS Then 319 Return Compiler.Report.ShowMessage(Messages.VBNC99997, Parent.Location) 320 Else 321 Dim rInfo As EmitInfo = Info.Clone(Parent, True, False, m_Variable.VariableType) 322 323 Helper.Assert(Info.RHSExpression IsNot Nothing) 324 Helper.Assert(Info.RHSExpression.Classification.IsValueClassification) 325 result = Info.RHSExpression.Classification.GenerateCode(rInfo) AndAlso result 326 327 Emitter.EmitConversion(Info.RHSExpression.ExpressionType, m_Variable.VariableType, Info) 328 329 If Helper.CompareType(m_Variable.VariableType, Compiler.TypeCache.System_Object) AndAlso Helper.CompareType(Info.RHSExpression.ExpressionType, Compiler.TypeCache.System_Object) Then 330 Emitter.EmitCall(Info, Compiler.TypeCache.System_Runtime_CompilerServices_RuntimeHelpers__GetObjectValue_Object) 331 End If 332 333 Emitter.EmitStoreVariable(Info, LocalBuilder) 334 Return Compiler.Report.ShowMessage(Messages.VBNC99997, Parent.Location) 335 End If 336 ElseIf m_ArrayVariable IsNot Nothing Then 337 If Info.IsRHS Then 338 result = Me.GenerateCodeAsValue(Info) AndAlso result 339 Else 340 result = Helper.EmitStoreArrayElement(Info, m_ArrayVariable, m_Arguments) AndAlso result 341 342 End If 343 ElseIf m_Method IsNot Nothing Then 344 If Info.IsRHS Then 345 Emitter.EmitLoadVariable(Info, m_Method.DefaultReturnVariable) 346 Else 347 Helper.Assert(Info.RHSExpression IsNot Nothing, "RHSExpression Is Nothing!") 348 Helper.Assert(Info.RHSExpression.Classification.IsValueClassification) 349 result = Info.RHSExpression.Classification.GenerateCode(Info.Clone(Parent, True, False, m_Method.DefaultReturnVariable.VariableType)) AndAlso result 350 Emitter.EmitStoreVariable(Info, m_Method.DefaultReturnVariable) 351 End If 352 Else 353 Throw New InternalException(Me) 354 End If 355 356 Return result 357 End Function 358 359 ReadOnly Property InstanceExpression() As Expression 360 Get 361 Return m_InstanceExpression 362 End Get 363 End Property 364 365 <Obsolete()> Overloads Function ReclassifyToValue() As ValueClassification 366 Return New ValueClassification(Me) 367 End Function 368 369 ''' <summary> 370 ''' A variable declaration which refers to the implicitly declared local variable 371 ''' for methods with return values (functions and get properties) 372 ''' </summary> 373 ''' <param name="Parent"></param> 374 ''' <param name="method"></param> 375 ''' <remarks></remarks> 376 Sub New(ByVal Parent As ParsedObject, ByVal method As IMethod) 377 MyBase.New(Classifications.Variable, Parent) 378 Helper.Assert(TypeOf method Is FunctionDeclaration OrElse TypeOf method Is PropertyGetDeclaration) 379 m_Method = method 380 End Sub 381 382 Sub New(ByVal Parent As ParsedObject, ByVal parameter As Parameter) 383 MyBase.New(Classifications.Variable, Parent) 384 m_Parameter = parameter 385 m_ParameterInfo = parameter.CecilBuilder 386 End Sub 387 388 Sub New(ByVal Parent As ParsedObject, ByVal variable As VariableDeclaration, Optional ByVal InstanceExpression As Expression = Nothing) 389 MyBase.New(Classifications.Variable, Parent) 390 m_Variable = variable 391 m_LocalVariable = TryCast(m_Variable, LocalVariableDeclaration) 392 m_TypeVariable = TryCast(m_Variable, TypeVariableDeclaration) 393 m_InstanceExpression = InstanceExpression 394 End Sub 395 396 Sub New(ByVal Parent As ParsedObject, ByVal Expression As Expression, ByVal ExpressionType As Mono.Cecil.TypeReference) 397 MyBase.new(Classifications.Variable, Parent) 398 m_Expression = Expression 399 m_ExpressionType = ExpressionType 400 End Sub 401 402 Sub New(ByVal Parent As ParsedObject, ByVal variable As Mono.Cecil.FieldReference, ByVal InstanceExpression As Expression) 403 MyBase.New(Classifications.Variable, Parent) 404 m_FieldInfo = variable 405 m_InstanceExpression = InstanceExpression 406 Helper.Assert(m_InstanceExpression Is Nothing OrElse m_InstanceExpression.IsResolved) 407 Helper.Assert((Helper.IsShared(variable) AndAlso m_InstanceExpression Is Nothing) OrElse (Helper.IsShared(variable) = False AndAlso m_InstanceExpression IsNot Nothing)) 408 End Sub 409 410 ''' <summary> 411 ''' Creates a variable classification for an array access. 412 ''' </summary> 413 ''' <param name="Parent"></param> 414 ''' <param name="Arguments"></param> 415 ''' <remarks></remarks> 416 Sub New(ByVal Parent As ParsedObject, ByVal ArrayVariableExpression As Expression, ByVal Arguments As ArgumentList) 417 MyBase.New(Classifications.Variable, Parent) 418 m_ArrayVariable = ArrayVariableExpression 419 m_Arguments = Arguments 420 Helper.Assert(ArrayVariable IsNot Nothing) 421 Helper.Assert(Arguments IsNot Nothing) 422 End Sub 423 424 ReadOnly Property Type() As Mono.Cecil.TypeReference 425 Get 426 Dim result As Mono.Cecil.TypeReference 427 If m_ExpressionType IsNot Nothing Then 428 result = m_ExpressionType 429 ElseIf m_Method IsNot Nothing Then 430 result = m_Method.Signature.ReturnType 431 ElseIf m_Variable IsNot Nothing Then 432 result = m_Variable.VariableType 433 ElseIf m_FieldInfo IsNot Nothing Then 434 If Helper.IsEnum(Compiler, m_FieldInfo.DeclaringType) Then 435 result = m_FieldInfo.DeclaringType 436 Else 437 result = m_FieldInfo.FieldType 438 End If 439 ElseIf m_Parameter IsNot Nothing Then 440 result = m_Parameter.ParameterType 441 ElseIf m_ArrayVariable IsNot Nothing Then 442 result = CecilHelper.GetElementType(m_ArrayVariable.ExpressionType) 443 Else 444 Throw New InternalException(Me) 445 End If 446 Helper.Assert(result IsNot Nothing) 447 Return result 448 End Get 449 End Property 450End Class 451 452