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