Private Shared Function PerformCompileTimeBinaryOperation()

in src/Compilers/VisualBasic/Portable/Preprocessor/ExpressionEvaluator.vb [1099:1581]


        Private Shared Function PerformCompileTimeBinaryOperation(opcode As SyntaxKind,
                                                                  resultType As SpecialType,
                                                                  left As CConst,
                                                                  right As CConst,
                                                                  expr As ExpressionSyntax) As CConst

            Debug.Assert(opcode = SyntaxKind.LeftShiftExpression OrElse
                     opcode = SyntaxKind.RightShiftExpression OrElse
                     left.SpecialType = right.SpecialType, "Binary operation on mismatched types.")

            If left.SpecialType.IsIntegralType() OrElse left.SpecialType = SpecialType.System_Char OrElse left.SpecialType = SpecialType.System_DateTime Then
                Dim LeftValue As Int64 = TypeHelpers.UncheckedCLng(left)
                Dim RightValue As Int64 = TypeHelpers.UncheckedCLng(right)

                If resultType = SpecialType.System_Boolean Then
                    Dim ComparisonSucceeds As Boolean = False

                    Select Case (opcode)
                        Case SyntaxKind.EqualsExpression
                            ComparisonSucceeds =
                                If(left.SpecialType.IsUnsignedIntegralType(),
                                    UncheckedCULng(LeftValue) = UncheckedCULng(RightValue),
                                    LeftValue = RightValue)

                        Case SyntaxKind.NotEqualsExpression
                            ComparisonSucceeds =
                                If(left.SpecialType.IsUnsignedIntegralType(),
                                    UncheckedCULng(LeftValue) <> UncheckedCULng(RightValue),
                                    LeftValue <> RightValue)

                        Case SyntaxKind.LessThanOrEqualExpression
                            ComparisonSucceeds =
                                If(left.SpecialType.IsUnsignedIntegralType(),
                                    UncheckedCULng(LeftValue) <= UncheckedCULng(RightValue),
                                    LeftValue <= RightValue)

                        Case SyntaxKind.GreaterThanOrEqualExpression
                            ComparisonSucceeds =
                                If(left.SpecialType.IsUnsignedIntegralType(),
                                    UncheckedCULng(LeftValue) >= UncheckedCULng(RightValue),
                                    LeftValue >= RightValue)

                        Case SyntaxKind.LessThanExpression
                            ComparisonSucceeds = If(left.SpecialType.IsUnsignedIntegralType(),
                                UncheckedCULng(LeftValue) < UncheckedCULng(RightValue),
                                LeftValue < RightValue)

                        Case SyntaxKind.GreaterThanExpression
                            ComparisonSucceeds =
                                If(left.SpecialType.IsUnsignedIntegralType(),
                                    UncheckedCULng(LeftValue) > UncheckedCULng(RightValue),
                                    LeftValue > RightValue)

                        Case Else
                            Throw ExceptionUtilities.UnexpectedValue(opcode)
                    End Select
                    Return CConst.Create(ComparisonSucceeds)
                Else
                    
                    

                    Dim ResultValue As Int64 = 0
                    Dim Overflow As Boolean = False

                    Select Case (opcode)
                        Case SyntaxKind.AddExpression
                            ResultValue = NarrowIntegralResult(
                                LeftValue + RightValue,
                                left.SpecialType,
                                resultType,
                                Overflow)

                            If Not resultType.IsUnsignedIntegralType() Then
                                If (RightValue > 0 AndAlso ResultValue < LeftValue) OrElse
                                    (RightValue < 0 AndAlso ResultValue > LeftValue) Then

                                    Overflow = True
                                End If

                            ElseIf (
                                UncheckedCULng(ResultValue) < UncheckedCULng(LeftValue)
                            ) Then
                                Overflow = True
                            End If

                        Case SyntaxKind.SubtractExpression
                            ResultValue = NarrowIntegralResult(
                                LeftValue - RightValue,
                                left.SpecialType,
                                resultType,
                                Overflow)

                            If Not resultType.IsUnsignedIntegralType() Then
                                If (RightValue > 0 AndAlso ResultValue > LeftValue) OrElse
                                   (RightValue < 0 AndAlso ResultValue < LeftValue) Then

                                    Overflow = True
                                End If

                            ElseIf UncheckedCULng(ResultValue) > UncheckedCULng(LeftValue) Then
                                Overflow = True
                            End If

                        Case SyntaxKind.MultiplyExpression
                            ResultValue = Multiply(LeftValue, RightValue, left.SpecialType, resultType, Overflow)

                        Case SyntaxKind.IntegerDivideExpression
                            If RightValue = 0 Then
                                Return ReportSemanticError(ERRID.ERR_ZeroDivide, expr)
                            End If

                            ResultValue = NarrowIntegralResult(
                                If(resultType.IsUnsignedIntegralType(),
                                    CompileTimeCalculations.UncheckedCLng(UncheckedCULng(LeftValue) \ UncheckedCULng(RightValue)),
                                    UncheckedIntegralDiv(LeftValue, RightValue)),
                                left.SpecialType,
                                resultType,
                                Overflow)

                            If Not resultType.IsUnsignedIntegralType() AndAlso LeftValue = Int64.MinValue AndAlso RightValue = -1 Then
                                Overflow = True
                            End If

                        Case SyntaxKind.ModuloExpression
                            If RightValue = 0 Then
                                Return ReportSemanticError(ERRID.ERR_ZeroDivide, expr)
                            End If

                            If resultType.IsUnsignedIntegralType() Then
                                ResultValue = CompileTimeCalculations.UncheckedCLng(UncheckedCULng(LeftValue) Mod UncheckedCULng(RightValue))

                                
                            ElseIf RightValue <> Not CType(0, Int64) Then
                                ResultValue = LeftValue Mod RightValue
                            Else
                                ResultValue = 0
                            End If

                        Case SyntaxKind.ExclusiveOrExpression
                            ResultValue = LeftValue Xor RightValue

                        Case SyntaxKind.OrExpression
                            ResultValue = LeftValue Or RightValue

                        Case SyntaxKind.AndExpression
                            ResultValue = LeftValue And RightValue

                        Case SyntaxKind.LeftShiftExpression
                            RightValue = RightValue And left.SpecialType.GetShiftSizeMask()
                            ResultValue = LeftValue << CType(RightValue, Integer)

                            
                            
                            

                            Dim overflowTemp As Boolean = False
                            ResultValue = NarrowIntegralResult(ResultValue, left.SpecialType, resultType, overflowTemp)

                        Case SyntaxKind.RightShiftExpression
                            RightValue = RightValue And left.SpecialType.GetShiftSizeMask()
                            If resultType.IsUnsignedIntegralType() Then
                                ResultValue = CompileTimeCalculations.UncheckedCLng((UncheckedCULng(LeftValue) >> CType(RightValue, Integer)))
                            Else
                                ResultValue = LeftValue >> CType(RightValue, Integer)
                            End If

                        Case Else
                            Throw ExceptionUtilities.UnexpectedValue(opcode)
                    End Select

                    If Overflow Then
                        Return ReportSemanticError(ERRID.ERR_ExpressionOverflow1, expr, resultType.GetDisplayName())
                    End If

                    Return Convert(CConst.Create(ResultValue), resultType, expr)
                End If
            ElseIf left.SpecialType.IsFloatingType() Then
                Dim LeftValue As Double = CDbl(left.ValueAsObject)
                Dim RightValue As Double = CDbl(right.ValueAsObject)

                If resultType = SpecialType.System_Boolean Then
                    Dim ComparisonSucceeds As Boolean = False
                    Select Case (opcode)
                        Case SyntaxKind.EqualsExpression
                            ComparisonSucceeds = LeftValue = RightValue

                        Case SyntaxKind.NotEqualsExpression
                            ComparisonSucceeds = LeftValue <> RightValue

                        Case SyntaxKind.LessThanOrEqualExpression
                            ComparisonSucceeds = LeftValue <= RightValue

                        Case SyntaxKind.GreaterThanOrEqualExpression
                            ComparisonSucceeds = LeftValue >= RightValue

                        Case SyntaxKind.LessThanExpression
                            ComparisonSucceeds = LeftValue < RightValue

                        Case SyntaxKind.GreaterThanExpression
                            ComparisonSucceeds = LeftValue > RightValue

                        Case Else
                            Throw ExceptionUtilities.UnexpectedValue(opcode)
                    End Select

                    Return CConst.Create(If(ComparisonSucceeds, True, False))
                Else
                    Dim resultValue As Double = 0
                    Dim overflow As Boolean = False

                    Select Case (opcode)
                        Case SyntaxKind.AddExpression
                            resultValue = LeftValue + RightValue

                        Case SyntaxKind.SubtractExpression
                            resultValue = LeftValue - RightValue

                        Case SyntaxKind.MultiplyExpression
                            resultValue = LeftValue * RightValue

                        Case SyntaxKind.ExponentiateExpression
                            
                            If (
                                Double.IsInfinity(RightValue)
                            ) Then
                                
                                If LeftValue = 1.0 Then
                                    resultValue = LeftValue
                                    Exit Select
                                End If

                                
                                If LeftValue = -1.0 Then
                                    resultValue = Double.NaN
                                    Exit Select
                                End If

                            ElseIf (
                                Double.IsNaN(RightValue)
                            ) Then
                                resultValue = Double.NaN
                                Exit Select
                            End If
                            resultValue = Math.Pow(LeftValue, RightValue)

                        Case SyntaxKind.DivideExpression

                            

                            
                            
#If 0 Then

                        If ( 
                            RightValue = 0 
                        )
                            ReportSemanticError( 
                                ERRID.ERR_ZeroDivide,
                                ExpressionLocation) : 

                            return AllocateBadExpression(ExpressionLocation) : 
                        End If
#End If
                            resultValue = LeftValue / RightValue

                        Case SyntaxKind.ModuloExpression
                            
                            
#If 0 Then

                        If ( 
                            RightValue = 0 
                        )
                            ReportSemanticError( 
                            ERRID.ERR_ZeroDivide,
                            ExpressionLocation) : 

                            return AllocateBadExpression(ExpressionLocation) : 
                        End If
#End If
                            resultValue = Math.IEEERemainder(LeftValue, RightValue)
                        Case Else
                            Throw ExceptionUtilities.UnexpectedValue(opcode)
                    End Select

                    resultValue = NarrowFloatingResult(resultValue, resultType, overflow)

                    
                    
#If 0 Then

                If ( 
                    Overflow 
                )
                    ReportSemanticError( 
                    ERRID.ERR_ExpressionOverflow1,
                    ExpressionLocation,
                    ResultType) : 

                    return AllocateBadExpression(ExpressionLocation) : 
                End If
#End If

                    Return Convert(CConst.Create(resultValue), resultType, expr)
                End If
            ElseIf left.SpecialType = SpecialType.System_Decimal Then
                Dim LeftValue As Decimal = CDec(left.ValueAsObject)
                Dim RightValue As Decimal = CDec(right.ValueAsObject)

                If resultType = SpecialType.System_Boolean Then
                    Dim ComparisonSucceeds As Boolean = False
                    Dim ComparisonResult As Integer = LeftValue.CompareTo(RightValue)

                    Select Case (opcode)
                        Case SyntaxKind.EqualsExpression
                            ComparisonSucceeds = (ComparisonResult = 0)

                        Case SyntaxKind.NotEqualsExpression
                            ComparisonSucceeds = Not (ComparisonResult = 0)

                        Case SyntaxKind.LessThanOrEqualExpression
                            ComparisonSucceeds = (ComparisonResult <= 0)

                        Case SyntaxKind.GreaterThanOrEqualExpression
                            ComparisonSucceeds = (ComparisonResult >= 0)

                        Case SyntaxKind.LessThanExpression
                            ComparisonSucceeds = (ComparisonResult < 0)

                        Case SyntaxKind.GreaterThanExpression
                            ComparisonSucceeds = (ComparisonResult > 0)

                        Case Else
                            Throw ExceptionUtilities.UnexpectedValue(opcode)
                    End Select

                    Return CConst.Create(ComparisonSucceeds)
                Else
                    Dim ResultValue As Decimal
                    Dim Overflow As Boolean = False

                    Select Case (opcode)
                        Case SyntaxKind.AddExpression
                            Overflow = VarDecAdd(LeftValue, RightValue, ResultValue)

                        Case SyntaxKind.SubtractExpression
                            Overflow = VarDecSub(LeftValue, RightValue, ResultValue)

                        Case SyntaxKind.MultiplyExpression
                            Overflow = VarDecMul(LeftValue, RightValue, ResultValue)

                        Case SyntaxKind.DivideExpression
                            If RightValue = Decimal.Zero Then
                                Return ReportSemanticError(ERRID.ERR_ZeroDivide, expr)
                            End If
                            Overflow = VarDecDiv(LeftValue, RightValue, ResultValue)

                        Case SyntaxKind.ModuloExpression
                            If RightValue = Decimal.Zero Then
                                Return ReportSemanticError(ERRID.ERR_ZeroDivide, expr)
                            End If

                            
                            

                            
                            
                            

                            Overflow = VarDecDiv(LeftValue, RightValue, ResultValue)

                            If Not Overflow Then
                                ResultValue = Decimal.Truncate(ResultValue)
                                Overflow = VarDecMul(ResultValue, RightValue, ResultValue)
                                If Not Overflow Then
                                    Overflow = VarDecSub(LeftValue, ResultValue, ResultValue)
                                End If
                            End If

                        Case Else
                            Throw ExceptionUtilities.UnexpectedValue(opcode)
                    End Select

                    If Overflow Then
                        Return ReportSemanticError(ERRID.ERR_ExpressionOverflow1, expr, resultType.GetDisplayName())
                    End If

                    Return CConst.Create(ResultValue)
                End If
            ElseIf left.SpecialType = SpecialType.System_String Then

                
                Dim LeftSpelling = If(CStr(left.ValueAsObject), "")
                Dim RightSpelling = If(CStr(right.ValueAsObject), "")

                Select Case (opcode)
                    Case SyntaxKind.ConcatenateExpression
                        Dim ResultString As String = String.Concat(LeftSpelling, RightSpelling)
                        Return CConst.Create(ResultString)

                    Case SyntaxKind.GreaterThanExpression,
                        SyntaxKind.LessThanExpression,
                        SyntaxKind.GreaterThanOrEqualExpression,
                        SyntaxKind.LessThanOrEqualExpression,
                        SyntaxKind.EqualsExpression,
                        SyntaxKind.NotEqualsExpression

                        Dim StringComparisonSucceeds As Boolean = False

                        
                        Dim ComparisonResult = StringComparer.Ordinal.Compare(LeftSpelling, RightSpelling)

                        Select Case (opcode)
                            Case SyntaxKind.EqualsExpression
                                StringComparisonSucceeds = ComparisonResult = 0

                            Case SyntaxKind.NotEqualsExpression
                                StringComparisonSucceeds = ComparisonResult <> 0

                            Case SyntaxKind.GreaterThanExpression
                                StringComparisonSucceeds = ComparisonResult > 0

                            Case SyntaxKind.GreaterThanOrEqualExpression
                                StringComparisonSucceeds = ComparisonResult >= 0

                            Case SyntaxKind.LessThanExpression
                                StringComparisonSucceeds = ComparisonResult < 0

                            Case SyntaxKind.LessThanOrEqualExpression
                                StringComparisonSucceeds = ComparisonResult <= 0

                        End Select
                        Return CConst.Create(StringComparisonSucceeds)

                    Case Else
                        Throw ExceptionUtilities.UnexpectedValue(opcode)
                End Select

            ElseIf left.SpecialType = SpecialType.System_Boolean Then
                Dim LeftValue As Boolean = CBool(left.ValueAsObject)
                Dim RightValue As Boolean = CBool(right.ValueAsObject)

                Dim OperationSucceeds As Boolean = False

                Select Case (opcode)
                    Case SyntaxKind.EqualsExpression
                        OperationSucceeds = LeftValue = RightValue

                    Case SyntaxKind.NotEqualsExpression
                        OperationSucceeds = LeftValue <> RightValue

                    

                    Case SyntaxKind.GreaterThanExpression
                        OperationSucceeds = LeftValue = False AndAlso RightValue <> False

                    Case SyntaxKind.GreaterThanOrEqualExpression
                        OperationSucceeds = LeftValue = False OrElse RightValue <> False

                    Case SyntaxKind.LessThanExpression
                        OperationSucceeds = LeftValue <> False AndAlso RightValue = False

                    Case SyntaxKind.LessThanOrEqualExpression
                        OperationSucceeds = LeftValue <> False OrElse RightValue = False

                    Case SyntaxKind.ExclusiveOrExpression
                        OperationSucceeds = LeftValue Xor RightValue

                    Case SyntaxKind.OrElseExpression, SyntaxKind.OrExpression
                        OperationSucceeds = LeftValue Or RightValue

                    Case SyntaxKind.AndAlsoExpression, SyntaxKind.AndExpression
                        OperationSucceeds = LeftValue And RightValue

                    Case Else
                        Throw ExceptionUtilities.UnexpectedValue(opcode)
                End Select

                Return CConst.Create(OperationSucceeds)
            End If

            Throw ExceptionUtilities.Unreachable
        End Function