Implemented equality comparison for primitive types
This commit is contained in:
committed by
Anton Bannykh
parent
7cde03938a
commit
3a7518cad2
+7
-4
@@ -78,6 +78,9 @@ fun box(): String {
|
||||
val dnq: Double? = dn
|
||||
val adnq: Any? = dn
|
||||
|
||||
// see https://bugs.openjdk.java.net/browse/JDK-8141407
|
||||
val nanBug = js("dn == dn")
|
||||
|
||||
assertFalse(dn == dn, "Double: NaN == NaN")
|
||||
assertTrue(dn == adn, "Double: NaN != (Any)NaN")
|
||||
assertTrue(adn == dn, "Double: (Any)NaN != NaN")
|
||||
@@ -93,7 +96,7 @@ fun box(): String {
|
||||
assertTrue(adnq == dn, "Double: (Any?)NaN != NaN")
|
||||
assertTrue(adnq == adn, "Double: (Any?)NaN != (Any)NaN")
|
||||
|
||||
assertFalse(dnq == dnq, "Double: NaN? == NaN?")
|
||||
if (!nanBug) assertFalse(dnq == dnq, "Double: NaN? == NaN?")
|
||||
assertTrue(dnq == adnq, "Double: NaN? != (Any?)NaN")
|
||||
assertTrue(adnq == dnq, "Double: (Any?)NaN != NaN?")
|
||||
assertTrue(adnq == adnq, "Double: (Any?)NaN != (Any?)NaN")
|
||||
@@ -113,7 +116,7 @@ fun box(): String {
|
||||
assertFalse(adnq != dn, "Double: (Any?)NaN != NaN")
|
||||
assertFalse(adnq != adn, "Double: (Any?)NaN != (Any)NaN")
|
||||
|
||||
assertTrue(dnq != dnq, "Double: NaN? == NaN?")
|
||||
if (!nanBug) assertTrue(dnq != dnq, "Double: NaN? == NaN?")
|
||||
assertFalse(dnq != adnq, "Double: NaN? != (Any?)NaN")
|
||||
assertFalse(adnq != dnq, "Double: (Any?)NaN != NaN?")
|
||||
assertFalse(adnq != adnq, "Double: (Any?)NaN != (Any?)NaN")
|
||||
@@ -168,7 +171,7 @@ fun box(): String {
|
||||
assertTrue(afnq == fn, "Float: (Any?)NaN != NaN")
|
||||
assertTrue(afnq == afn, "Float: (Any?)NaN != (Any)NaN")
|
||||
|
||||
assertFalse(fnq == fnq, "Float: NaN? == NaN?")
|
||||
if (!nanBug) assertFalse(fnq == fnq, "Float: NaN? == NaN?")
|
||||
assertTrue(fnq == afnq, "Float: NaN? != (Any?)NaN")
|
||||
assertTrue(afnq == fnq, "Float: (Any?)NaN != NaN?")
|
||||
assertTrue(afnq == afnq, "Float: (Any?)NaN != (Any?)NaN")
|
||||
@@ -188,7 +191,7 @@ fun box(): String {
|
||||
assertFalse(afnq != fn, "Float: (Any?)NaN != NaN")
|
||||
assertFalse(afnq != afn, "Float: (Any?)NaN != (Any)NaN")
|
||||
|
||||
assertTrue(fnq != fnq, "Float: NaN? == NaN?")
|
||||
if (!nanBug) assertTrue(fnq != fnq, "Float: NaN? == NaN?")
|
||||
assertFalse(fnq != afnq, "Float: NaN? != (Any?)NaN")
|
||||
assertFalse(afnq != fnq, "Float: (Any?)NaN != NaN?")
|
||||
assertFalse(afnq != afnq, "Float: (Any?)NaN != (Any?)NaN")
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+6
@@ -16780,6 +16780,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("crossTypeEquals.kt")
|
||||
public void testCrossTypeEquals() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/primitiveTypes/crossTypeEquals.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ea35963.kt")
|
||||
public void testEa35963() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/primitiveTypes/ea35963.kt");
|
||||
|
||||
+7
-32
@@ -19,14 +19,9 @@ package org.jetbrains.kotlin.js.translate.intrinsic.operation
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.isPrimitiveTypeOrNullablePrimitiveType
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsBinaryOperation
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsExpression
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsIntLiteral
|
||||
import org.jetbrains.kotlin.js.patterns.PatternBuilder.pattern
|
||||
import org.jetbrains.kotlin.js.translate.operation.OperatorTable
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.*
|
||||
import org.jetbrains.kotlin.js.translate.utils.PsiUtils.getOperationToken
|
||||
import org.jetbrains.kotlin.lexer.KtSingleValueToken
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
@@ -36,36 +31,15 @@ import org.jetbrains.kotlin.utils.identity
|
||||
object CompareToBOIF : BinaryOperationIntrinsicFactory {
|
||||
override fun getSupportTokens(): Set<KtSingleValueToken> = OperatorConventions.COMPARISON_OPERATIONS
|
||||
|
||||
// toLeft(L, R) OP toRight(L, R)
|
||||
private fun intrinsic(
|
||||
toLeft: (JsExpression, JsExpression) -> JsExpression,
|
||||
toRight: (JsExpression, JsExpression) -> JsExpression
|
||||
): BinaryOperationIntrinsic = { expression, left, right, _ ->
|
||||
val operator = OperatorTable.getBinaryOperator(getOperationToken(expression))
|
||||
JsBinaryOperation(operator, toLeft(left, right), toRight(left, right))
|
||||
}
|
||||
|
||||
// toLeft(L) OP toRight(R)
|
||||
private fun primitiveIntrinsic(
|
||||
toLeft: (JsExpression) -> JsExpression,
|
||||
toRight: (JsExpression) -> JsExpression
|
||||
): BinaryOperationIntrinsic = intrinsic({ l, _ -> toLeft(l) }, { _, r -> toRight(r) })
|
||||
|
||||
private fun unboxCharIfNeeded(type: KotlinType): (JsExpression) -> JsExpression = { e ->
|
||||
if (KotlinBuiltIns.isCharOrNullableChar(type)) {
|
||||
charToInt(e)
|
||||
} else e
|
||||
}
|
||||
|
||||
private val patterns = listOf(
|
||||
pattern("Int|Short|Byte|Float|Double.compareTo(Long)") to primitiveIntrinsic(identity(), ::longToNumber),
|
||||
pattern("Long.compareTo(Int|Short|Byte|Float|Double)") to primitiveIntrinsic(::longToNumber, identity()),
|
||||
pattern("Int|Short|Byte|Float|Double.compareTo(Long)") to binaryIntrinsic(toRight = { r, _ -> longToNumber(r) }),
|
||||
pattern("Long.compareTo(Int|Short|Byte|Float|Double)") to binaryIntrinsic(toLeft = { l, _ -> longToNumber(l) }),
|
||||
// L.compareTo(R) OP 0
|
||||
pattern("Long.compareTo(Long)") to intrinsic({ l, r -> compareForObject(l, r) }, { _, _ -> JsIntLiteral(0) })
|
||||
pattern("Long.compareTo(Long)") to intrinsic({ l, r, _ -> compareForObject(l, r) }, { _, _, _-> JsIntLiteral(0) })
|
||||
)
|
||||
|
||||
override fun getIntrinsic(descriptor: FunctionDescriptor, leftType: KotlinType?, rightType: KotlinType?): BinaryOperationIntrinsic? {
|
||||
if (descriptor.isDynamic()) return primitiveIntrinsic(identity(), identity())
|
||||
if (descriptor.isDynamic()) return binaryIntrinsic()
|
||||
|
||||
if (leftType == null || rightType == null || !KotlinBuiltIns.isBuiltIn(descriptor)) return null
|
||||
|
||||
@@ -73,9 +47,10 @@ object CompareToBOIF : BinaryOperationIntrinsicFactory {
|
||||
|
||||
// Types may be nullable if properIeeeComparisons are switched off, e.g. fun foo(a: Double?) = a != null && a < 0.0
|
||||
return if (isPrimitiveTypeOrNullablePrimitiveType(leftType) && isPrimitiveTypeOrNullablePrimitiveType(rightType)) {
|
||||
primitiveIntrinsic(unboxCharIfNeeded(leftType), unboxCharIfNeeded(rightType))
|
||||
binaryIntrinsic(coerceTo(leftType), coerceTo(rightType))
|
||||
} else {
|
||||
intrinsic({ l, r -> compareTo(l, r) }, { _, _ -> JsIntLiteral(0) })
|
||||
// Kotlin.compareTo(L, R) OP 0
|
||||
intrinsic({ l, r, _ -> compareTo(l, r) }, { _, _, _ -> JsIntLiteral(0) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+78
-75
@@ -17,19 +17,14 @@
|
||||
package org.jetbrains.kotlin.js.translate.intrinsic.operation
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsBinaryOperation
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsBinaryOperator
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsExpression
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsNullLiteral
|
||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||
import org.jetbrains.kotlin.js.translate.intrinsic.functions.factories.TopLevelFIF
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||
import org.jetbrains.kotlin.js.translate.utils.PsiUtils.getOperationToken
|
||||
import org.jetbrains.kotlin.js.translate.utils.PsiUtils.isNegatedOperation
|
||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
@@ -37,89 +32,97 @@ import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||
import org.jetbrains.kotlin.types.isDynamic
|
||||
import java.util.*
|
||||
|
||||
object EqualsBOIF : BinaryOperationIntrinsicFactory {
|
||||
override fun getSupportTokens() = OperatorConventions.EQUALS_OPERATIONS!!
|
||||
|
||||
private val JS_NUMBER_PRIMITIVES =
|
||||
EnumSet.of(PrimitiveType.BYTE, PrimitiveType.SHORT, PrimitiveType.INT, PrimitiveType.DOUBLE, PrimitiveType.FLOAT)
|
||||
|
||||
private fun equalsIntrinsic(expression: KtBinaryExpression, left: JsExpression, right: JsExpression, context: TranslationContext): JsExpression {
|
||||
val isNegated = expression.isNegated()
|
||||
val anyType = context.currentModule.builtIns.anyType
|
||||
if (right is JsNullLiteral || left is JsNullLiteral) {
|
||||
val (subject, ktSubject) = if (right is JsNullLiteral) Pair(left, expression.left!!) else Pair(right, expression.right!!)
|
||||
return TranslationUtils.nullCheck(ktSubject, subject, context, isNegatedOperation(expression))
|
||||
}
|
||||
|
||||
val (leftKotlinType, rightKotlinType) = binaryOperationTypes(expression, context)
|
||||
|
||||
val leftType = leftKotlinType?.let { KotlinBuiltIns.getPrimitiveType(it) }
|
||||
val rightType = rightKotlinType?.let { KotlinBuiltIns.getPrimitiveType(it) }
|
||||
|
||||
if (leftType != null && rightType != null) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (leftType != null && rightType != null && (
|
||||
leftType in JS_NUMBER_PRIMITIVES && rightType in JS_NUMBER_PRIMITIVES ||
|
||||
leftType in JS_NUMBER_PRIMITIVES && rightType == PrimitiveType.LONG ||
|
||||
leftType == PrimitiveType.LONG && rightType in JS_NUMBER_PRIMITIVES ||
|
||||
leftType == PrimitiveType.BOOLEAN && rightType == PrimitiveType.BOOLEAN ||
|
||||
leftType == PrimitiveType.CHAR && rightType == PrimitiveType.CHAR
|
||||
)) {
|
||||
val useEq = leftType == PrimitiveType.LONG || rightType == PrimitiveType.LONG
|
||||
|
||||
val operator = when {
|
||||
useEq && isNegated -> JsBinaryOperator.NEQ
|
||||
useEq && !isNegated -> JsBinaryOperator.EQ
|
||||
!useEq && isNegated -> JsBinaryOperator.REF_NEQ
|
||||
else /* !useEq && !isNegated */ -> JsBinaryOperator.REF_EQ
|
||||
}
|
||||
|
||||
val coercedLeft = TranslationUtils.coerce(context, left, leftKotlinType)
|
||||
val coercedRight = TranslationUtils.coerce(context, right, rightKotlinType)
|
||||
return JsBinaryOperation(operator, coercedLeft, coercedRight)
|
||||
}
|
||||
|
||||
val resolvedCall = expression.getResolvedCall(context.bindingContext())
|
||||
val appliedToDynamic =
|
||||
resolvedCall != null &&
|
||||
with(resolvedCall.dispatchReceiver) {
|
||||
if (this != null) type.isDynamic() else false
|
||||
}
|
||||
|
||||
if (appliedToDynamic) {
|
||||
return JsBinaryOperation(if (isNegated) JsBinaryOperator.NEQ else JsBinaryOperator.EQ, left, right)
|
||||
}
|
||||
|
||||
val coercedLeft = TranslationUtils.coerce(context, left, anyType)
|
||||
val coercedRight = TranslationUtils.coerce(context, right, anyType)
|
||||
val result = TopLevelFIF.KOTLIN_EQUALS.apply(coercedLeft, listOf(coercedRight), context)
|
||||
return if (isNegated) JsAstUtils.not(result) else result
|
||||
private val equalsNullIntrinsic: BinaryOperationIntrinsic = { expression, left, right, context ->
|
||||
val (subject, ktSubject) = if (right is JsNullLiteral) Pair(left, expression.left!!) else Pair(right, expression.right!!)
|
||||
TranslationUtils.nullCheck(ktSubject, subject, context, isNegatedOperation(expression))
|
||||
}
|
||||
|
||||
override fun getSupportTokens() = OperatorConventions.EQUALS_OPERATIONS!!
|
||||
private val kotlinEqualsIntrinsic: BinaryOperationIntrinsic = { expression, left, right, context ->
|
||||
val coercedLeft = TranslationUtils.coerce(context, left, context.currentModule.builtIns.anyType)
|
||||
val coercedRight = TranslationUtils.coerce(context, right, context.currentModule.builtIns.anyType)
|
||||
val result = TopLevelFIF.KOTLIN_EQUALS.apply(coercedLeft, listOf(coercedRight), context)
|
||||
if (isNegatedOperation(expression)) JsAstUtils.not(result) else result
|
||||
}
|
||||
|
||||
private val refEqSelector: OperatorSelector = { if (isNegatedOperation(it)) JsBinaryOperator.REF_NEQ else JsBinaryOperator.REF_EQ }
|
||||
|
||||
private val eqSelector: OperatorSelector = { if (isNegatedOperation(it)) JsBinaryOperator.NEQ else JsBinaryOperator.EQ }
|
||||
|
||||
private val refEqIntrinsic = binaryIntrinsic(operator = refEqSelector)
|
||||
|
||||
private val eqIntrinsic = binaryIntrinsic(operator = eqSelector)
|
||||
|
||||
private fun primitiveTypes(
|
||||
leftKotlinType: KotlinType, rightKotlinType: KotlinType
|
||||
): BinaryOperationIntrinsic {
|
||||
|
||||
fun <T> select(number: T, long: T, bool: T, char: T): (KotlinType) -> T = {
|
||||
when {
|
||||
KotlinBuiltIns.isLongOrNullableLong(it) -> long
|
||||
KotlinBuiltIns.isBooleanOrNullableBoolean(it) -> bool
|
||||
KotlinBuiltIns.isCharOrNullableChar(it) -> char
|
||||
else -> number
|
||||
}
|
||||
}
|
||||
|
||||
val eq = binaryIntrinsic(coerceTo(leftKotlinType), coerceTo(rightKotlinType), eqSelector)
|
||||
|
||||
val refEq = binaryIntrinsic(coerceTo(leftKotlinType), coerceTo(rightKotlinType), refEqSelector)
|
||||
|
||||
// Used for number to number comparison
|
||||
val default = { leftNullable: Boolean, rightNullable: Boolean ->
|
||||
if (leftNullable && rightNullable) eq else refEq
|
||||
}
|
||||
|
||||
// Used to compare Boolean with number types and Long. Kotlin.equals handles cases like 0: Int? == false: Boolean?
|
||||
val bool = { leftNullable: Boolean, rightNullable: Boolean ->
|
||||
if (leftNullable && rightNullable) kotlinEqualsIntrinsic else refEq
|
||||
}
|
||||
|
||||
// Used to compare Long with number types.
|
||||
val allEq = { _: Boolean, _: Boolean -> eq }
|
||||
|
||||
// Used to compare Char with other primitive types and Long with Long
|
||||
val allKEq = { _: Boolean, _: Boolean -> kotlinEqualsIntrinsic }
|
||||
|
||||
return select(
|
||||
select(default, allEq, bool, allKEq),
|
||||
select(allEq, allKEq, bool, allKEq),
|
||||
select(bool, bool, default, allKEq),
|
||||
select(allKEq, allKEq, allKEq, default)
|
||||
)(leftKotlinType)(rightKotlinType)(TypeUtils.isNullableType(leftKotlinType), TypeUtils.isNullableType(rightKotlinType))
|
||||
}
|
||||
|
||||
override fun getIntrinsic(descriptor: FunctionDescriptor, leftType: KotlinType?, rightType: KotlinType?): BinaryOperationIntrinsic? =
|
||||
when {
|
||||
isEnumEqualsIntrinsicApplicable(descriptor, leftType, rightType) -> { expression, left, right, _ ->
|
||||
val operator = if (expression.isNegated()) JsBinaryOperator.REF_NEQ else JsBinaryOperator.REF_EQ
|
||||
JsBinaryOperation(operator, left, right)
|
||||
}
|
||||
leftType == null || rightType == null -> null
|
||||
|
||||
KotlinBuiltIns.isBuiltIn(descriptor) ||
|
||||
TopLevelFIF.EQUALS_IN_ANY.test(descriptor) -> ::equalsIntrinsic
|
||||
isEnumEqualsIntrinsicApplicable(descriptor, leftType, rightType) -> refEqIntrinsic
|
||||
|
||||
KotlinBuiltIns.isBuiltIn(descriptor) || TopLevelFIF.EQUALS_IN_ANY.test(descriptor) -> { expression, left, right, context ->
|
||||
when {
|
||||
left is JsNullLiteral || right is JsNullLiteral -> equalsNullIntrinsic
|
||||
leftType.primitive && rightType.primitive -> primitiveTypes(leftType, rightType)
|
||||
expression.appliedToDynamic(context) -> eqIntrinsic
|
||||
else -> kotlinEqualsIntrinsic
|
||||
}(expression, left, right, context)
|
||||
}
|
||||
|
||||
else -> null
|
||||
}
|
||||
|
||||
private fun isEnumEqualsIntrinsicApplicable(descriptor: FunctionDescriptor, leftType: KotlinType?, rightType: KotlinType?): Boolean {
|
||||
return DescriptorUtils.isEnumClass(descriptor.containingDeclaration) && leftType != null && rightType != null &&
|
||||
private fun KtBinaryExpression.appliedToDynamic(context: TranslationContext) =
|
||||
getResolvedCall(context.bindingContext())?.dispatchReceiver?.type?.isDynamic() ?: false
|
||||
|
||||
private val KotlinType.primitive
|
||||
get() = KotlinBuiltIns.isPrimitiveTypeOrNullablePrimitiveType(this)
|
||||
|
||||
private fun isEnumEqualsIntrinsicApplicable(descriptor: FunctionDescriptor, leftType: KotlinType, rightType: KotlinType): Boolean {
|
||||
return DescriptorUtils.isEnumClass(descriptor.containingDeclaration) &&
|
||||
!TypeUtils.isNullableType(leftType) && !TypeUtils.isNullableType(rightType)
|
||||
}
|
||||
|
||||
|
||||
private fun KtBinaryExpression.isNegated() = getOperationToken(this) == KtTokens.EXCLEQ
|
||||
}
|
||||
|
||||
+33
-2
@@ -18,9 +18,13 @@ package org.jetbrains.kotlin.js.translate.intrinsic.operation
|
||||
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsExpression
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsBinaryOperation
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsBinaryOperator
|
||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||
import org.jetbrains.kotlin.js.translate.operation.OperatorTable
|
||||
import org.jetbrains.kotlin.js.translate.utils.BindingUtils.getCallableDescriptorForOperationExpression
|
||||
import org.jetbrains.kotlin.js.translate.utils.PsiUtils.getOperationToken
|
||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
|
||||
import org.jetbrains.kotlin.js.translate.utils.getPrecisePrimitiveType
|
||||
import org.jetbrains.kotlin.js.translate.utils.getPrimitiveNumericComparisonInfo
|
||||
import org.jetbrains.kotlin.lexer.KtToken
|
||||
@@ -43,7 +47,8 @@ class BinaryOperationIntrinsics {
|
||||
private val intrinsicCache = mutableMapOf<IntrinsicKey, BinaryOperationIntrinsic?>()
|
||||
|
||||
fun getIntrinsic(expression: KtBinaryExpression, context: TranslationContext): BinaryOperationIntrinsic? {
|
||||
val descriptor = getCallableDescriptorForOperationExpression(context.bindingContext(), expression) as? FunctionDescriptor ?: return null
|
||||
val descriptor =
|
||||
getCallableDescriptorForOperationExpression(context.bindingContext(), expression) as? FunctionDescriptor ?: return null
|
||||
|
||||
val (leftType, rightType) = binaryOperationTypes(expression, context)
|
||||
|
||||
@@ -83,4 +88,30 @@ interface BinaryOperationIntrinsicFactory {
|
||||
fun getSupportTokens(): Set<KtToken>
|
||||
|
||||
fun getIntrinsic(descriptor: FunctionDescriptor, leftType: KotlinType?, rightType: KotlinType?): BinaryOperationIntrinsic?
|
||||
}
|
||||
}
|
||||
|
||||
typealias OperatorSelector = (KtBinaryExpression) -> JsBinaryOperator
|
||||
|
||||
val defaultOperatorSelector: OperatorSelector = { OperatorTable.getBinaryOperator(getOperationToken(it)) }
|
||||
|
||||
// toLeft(L, R) OP toRight(L, R)
|
||||
fun intrinsic(
|
||||
toLeft: (JsExpression, JsExpression, TranslationContext) -> JsExpression,
|
||||
toRight: (JsExpression, JsExpression, TranslationContext) -> JsExpression,
|
||||
operator: (KtBinaryExpression) -> JsBinaryOperator = defaultOperatorSelector
|
||||
): BinaryOperationIntrinsic = { expression, left, right, context ->
|
||||
JsBinaryOperation(operator(expression), toLeft(left, right, context), toRight(left, right, context))
|
||||
}
|
||||
|
||||
// toLeft(L, C) OP toRight(R, C)
|
||||
fun binaryIntrinsic(
|
||||
toLeft: (JsExpression, TranslationContext) -> JsExpression = { l, _ -> l },
|
||||
toRight: (JsExpression, TranslationContext) -> JsExpression = { r, _ -> r },
|
||||
operator: OperatorSelector = defaultOperatorSelector
|
||||
): BinaryOperationIntrinsic = intrinsic({ l, _, c -> toLeft(l, c) }, { _, r, c -> toRight(r, c) }, operator)
|
||||
|
||||
|
||||
fun coerceTo(type: KotlinType): (JsExpression, TranslationContext) -> JsExpression =
|
||||
{ e, c ->
|
||||
TranslationUtils.coerce(c, e, type)
|
||||
}
|
||||
Reference in New Issue
Block a user