diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt index 7ec2595116c..b113512816f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/ConstantExpressionEvaluator.kt @@ -35,6 +35,7 @@ import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.resolve.checkers.ExperimentalUsageChecker import org.jetbrains.kotlin.resolve.constants.* +import org.jetbrains.kotlin.resolve.constants.evaluate.CompileTimeType.* import org.jetbrains.kotlin.resolve.descriptorUtil.classId import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeUtils @@ -903,7 +904,7 @@ private class ConstantExpressionEvaluatorVisitor( return null } - private class OperationArgument(val value: Any, val ctcType: CompileTimeType<*>, val expression: KtExpression) + private class OperationArgument(val value: Any, val ctcType: CompileTimeType, val expression: KtExpression) private fun createOperationArgumentForReceiver(resolvedCall: ResolvedCall<*>, expression: KtExpression): OperationArgument? { val receiverExpressionType = getReceiverExpressionType(resolvedCall) ?: return null @@ -927,7 +928,7 @@ private class ConstantExpressionEvaluatorVisitor( return createOperationArgument(argumentExpression, parameter.type, argumentCompileTimeType) } - private fun getCompileTimeType(c: KotlinType): CompileTimeType? = + private fun getCompileTimeType(c: KotlinType): CompileTimeType? = when (TypeUtils.makeNotNullable(c)) { builtIns.intType -> INT builtIns.byteType -> BYTE @@ -945,7 +946,7 @@ private class ConstantExpressionEvaluatorVisitor( private fun createOperationArgument( expression: KtExpression, parameterType: KotlinType, - compileTimeType: CompileTimeType<*> + compileTimeType: CompileTimeType, ): OperationArgument? { val compileTimeConstant = constantExpressionEvaluator.evaluateExpression(expression, trace, parameterType) ?: return null if (compileTimeConstant is TypedCompileTimeConstant && !compileTimeConstant.type.isSubtypeOf(parameterType)) return null @@ -1098,44 +1099,11 @@ private fun getReceiverExpressionType(resolvedCall: ResolvedCall<*>): KotlinType } } -internal class CompileTimeType(val name: String) { - override fun toString() = name +internal enum class CompileTimeType { + BYTE, SHORT, INT, LONG, DOUBLE, FLOAT, CHAR, BOOLEAN, + STRING, ANY } -internal val BYTE = CompileTimeType("Byte") -internal val SHORT = CompileTimeType("Short") -internal val INT = CompileTimeType("Int") -internal val LONG = CompileTimeType("Long") -internal val DOUBLE = CompileTimeType("Double") -internal val FLOAT = CompileTimeType("Float") -internal val CHAR = CompileTimeType("Char") -internal val BOOLEAN = CompileTimeType("Boolean") -internal val STRING = CompileTimeType("String") -internal val ANY = CompileTimeType("Any") - -@Suppress("UNCHECKED_CAST") -internal fun binaryOperation( - a: CompileTimeType, - b: CompileTimeType, - functionName: String, - operation: Function2, - checker: Function2 -) = BinaryOperationKey(a, b, functionName) to Pair( - operation, - checker -) as Pair, Function2> - -@Suppress("UNCHECKED_CAST") -internal fun unaryOperation( - a: CompileTimeType, - functionName: String, - operation: Function1, - checker: Function1 -) = UnaryOperationKey(a, functionName) to Pair(operation, checker) as Pair, Function1> - -internal data class BinaryOperationKey(val f: CompileTimeType, val s: CompileTimeType, val functionName: String) -internal data class UnaryOperationKey(val f: CompileTimeType, val functionName: String) - fun ConstantValue<*>.isStandaloneOnlyConstant(): Boolean { return this is KClassValue || this is EnumValue || this is AnnotationValue || this is ArrayValue } @@ -1156,39 +1124,28 @@ private fun isZero(value: Any?): Boolean { } private fun typeStrToCompileTimeType(str: String) = when (str) { - BYTE.name -> BYTE - SHORT.name -> SHORT - INT.name -> INT - LONG.name -> LONG - DOUBLE.name -> DOUBLE - FLOAT.name -> FLOAT - CHAR.name -> CHAR - BOOLEAN.name -> BOOLEAN - STRING.name -> STRING - ANY.name -> ANY + "Byte" -> BYTE + "Short" -> SHORT + "Int" -> INT + "Long" -> LONG + "Double" -> DOUBLE + "Float" -> FLOAT + "Char" -> CHAR + "Boolean" -> BOOLEAN + "String" -> STRING + "Any" -> ANY else -> throw IllegalArgumentException("Unsupported type: $str") } -fun evaluateUnary(name: String, typeStr: String, value: Any): Any? { - return evaluateUnaryAndCheck(name, typeStrToCompileTimeType(typeStr), value) -} +fun evaluateUnary(name: String, typeStr: String, value: Any): Any? = + evalUnaryOp(name, typeStrToCompileTimeType(typeStr), value) -private fun evaluateUnaryAndCheck(name: String, type: CompileTimeType<*>, value: Any, tracer: () -> Unit = {}): Any? { - val functions = unaryOperations[UnaryOperationKey(type, name)] ?: return null - - val (function, check) = functions - val result = function(value) - if (check == emptyUnaryFun) { - return result +private fun evaluateUnaryAndCheck(name: String, type: CompileTimeType, value: Any, reportIntegerOverflow: () -> Unit): Any? = + evalUnaryOp(name, type, value).also { result -> + if (isIntegerType(value) && (name == "minus" || name == "unaryMinus") && value == result && !isZero(value)) { + reportIntegerOverflow() + } } - assert(isIntegerType(value)) { "Only integer constants should be checked for overflow" } - assert(name == "minus" || name == "unaryMinus") { "Only negation should be checked for overflow" } - - if (value == result && !isZero(value)) { - tracer() - } - return result -} fun evaluateBinary( name: String, @@ -1200,42 +1157,35 @@ fun evaluateBinary( val receiverType = typeStrToCompileTimeType(receiverTypeStr) val parameterType = typeStrToCompileTimeType(parameterTypeStr) - return evaluateBinaryAndCheck(name, receiverType, receiverValue, parameterType, parameterValue) + return try { + evalBinaryOp(name, receiverType, receiverValue, parameterType, parameterValue) + } catch (e: Exception) { + null + } } private fun evaluateBinaryAndCheck( name: String, - receiverType: CompileTimeType<*>, + receiverType: CompileTimeType, receiverValue: Any, - parameterType: CompileTimeType<*>, + parameterType: CompileTimeType, parameterValue: Any, - tracer: () -> Unit = {} + reportIntegerOverflow: () -> Unit, ): Any? { - val functions = binaryOperations[BinaryOperationKey(receiverType, parameterType, name)] ?: return null - - val (function, checker) = functions val actualResult = try { - function(receiverValue, parameterValue) + evalBinaryOp(name, receiverType, receiverValue, parameterType, parameterValue) } catch (e: Exception) { null } - if (checker == emptyBinaryFun) { - return actualResult - } - assert(isIntegerType(receiverValue) && isIntegerType(parameterValue)) { "Only integer constants should be checked for overflow" } fun toBigInteger(value: Any?) = BigInteger.valueOf((value as Number).toLong()) - val refinedChecker = if (name == OperatorNameConventions.MOD.asString()) { - binaryOperations[BinaryOperationKey(receiverType, parameterType, OperatorNameConventions.REM.asString())]?.second ?: return null - } else { - checker + if (actualResult != null && isIntegerType(receiverValue) && isIntegerType(parameterValue)) { + val checkedResult = checkBinaryOp(name, receiverType, toBigInteger(receiverValue), parameterType, toBigInteger(parameterValue)) + if (checkedResult != null && toBigInteger(actualResult) != checkedResult) { + reportIntegerOverflow() + } } - val resultInBigIntegers = refinedChecker(toBigInteger(receiverValue), toBigInteger(parameterValue)) - - if (toBigInteger(actualResult) != resultInBigIntegers) { - tracer() - } return actualResult } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/OperationsMapGenerated.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/OperationsMapGenerated.kt index 4e60845f696..a05c37eb6b1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/OperationsMapGenerated.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/constants/evaluate/OperationsMapGenerated.kt @@ -14,344 +14,616 @@ * limitations under the License. */ -@file:Suppress("DEPRECATION", "DEPRECATION_ERROR") +@file:Suppress("DEPRECATION", "DEPRECATION_ERROR", "NON_EXHAUSTIVE_WHEN") package org.jetbrains.kotlin.resolve.constants.evaluate +import org.jetbrains.kotlin.resolve.constants.evaluate.CompileTimeType.* import java.math.BigInteger -import java.util.HashMap -/** This file is generated by org.jetbrains.kotlin.generators.evaluate:generate(). DO NOT MODIFY MANUALLY */ +/** This file is generated by `./gradlew generateOperationsMap`. DO NOT MODIFY MANUALLY */ -internal val emptyBinaryFun: Function2 = { _, _ -> BigInteger("0") } -internal val emptyUnaryFun: Function1 = { _ -> 1.toLong() } +internal fun evalUnaryOp(name: String, type: CompileTimeType, value: Any): Any? { + when (type) { + BOOLEAN -> when (name) { + "not" -> return (value as Boolean).not() + "toString" -> return (value as Boolean).toString() + } + BYTE -> when (name) { + "toByte" -> return (value as Byte).toByte() + "toChar" -> return (value as Byte).toChar() + "toDouble" -> return (value as Byte).toDouble() + "toFloat" -> return (value as Byte).toFloat() + "toInt" -> return (value as Byte).toInt() + "toLong" -> return (value as Byte).toLong() + "toShort" -> return (value as Byte).toShort() + "toString" -> return (value as Byte).toString() + "unaryMinus" -> return (value as Byte).unaryMinus() + "unaryPlus" -> return (value as Byte).unaryPlus() + } + CHAR -> when (name) { + "toByte" -> return (value as Char).toByte() + "toChar" -> return (value as Char).toChar() + "toDouble" -> return (value as Char).toDouble() + "toFloat" -> return (value as Char).toFloat() + "toInt" -> return (value as Char).toInt() + "toLong" -> return (value as Char).toLong() + "toShort" -> return (value as Char).toShort() + "toString" -> return (value as Char).toString() + } + DOUBLE -> when (name) { + "toByte" -> return (value as Double).toByte() + "toChar" -> return (value as Double).toChar() + "toDouble" -> return (value as Double).toDouble() + "toFloat" -> return (value as Double).toFloat() + "toInt" -> return (value as Double).toInt() + "toLong" -> return (value as Double).toLong() + "toShort" -> return (value as Double).toShort() + "toString" -> return (value as Double).toString() + "unaryMinus" -> return (value as Double).unaryMinus() + "unaryPlus" -> return (value as Double).unaryPlus() + } + FLOAT -> when (name) { + "toByte" -> return (value as Float).toByte() + "toChar" -> return (value as Float).toChar() + "toDouble" -> return (value as Float).toDouble() + "toFloat" -> return (value as Float).toFloat() + "toInt" -> return (value as Float).toInt() + "toLong" -> return (value as Float).toLong() + "toShort" -> return (value as Float).toShort() + "toString" -> return (value as Float).toString() + "unaryMinus" -> return (value as Float).unaryMinus() + "unaryPlus" -> return (value as Float).unaryPlus() + } + INT -> when (name) { + "inv" -> return (value as Int).inv() + "toByte" -> return (value as Int).toByte() + "toChar" -> return (value as Int).toChar() + "toDouble" -> return (value as Int).toDouble() + "toFloat" -> return (value as Int).toFloat() + "toInt" -> return (value as Int).toInt() + "toLong" -> return (value as Int).toLong() + "toShort" -> return (value as Int).toShort() + "toString" -> return (value as Int).toString() + "unaryMinus" -> return (value as Int).unaryMinus() + "unaryPlus" -> return (value as Int).unaryPlus() + } + LONG -> when (name) { + "inv" -> return (value as Long).inv() + "toByte" -> return (value as Long).toByte() + "toChar" -> return (value as Long).toChar() + "toDouble" -> return (value as Long).toDouble() + "toFloat" -> return (value as Long).toFloat() + "toInt" -> return (value as Long).toInt() + "toLong" -> return (value as Long).toLong() + "toShort" -> return (value as Long).toShort() + "toString" -> return (value as Long).toString() + "unaryMinus" -> return (value as Long).unaryMinus() + "unaryPlus" -> return (value as Long).unaryPlus() + } + SHORT -> when (name) { + "toByte" -> return (value as Short).toByte() + "toChar" -> return (value as Short).toChar() + "toDouble" -> return (value as Short).toDouble() + "toFloat" -> return (value as Short).toFloat() + "toInt" -> return (value as Short).toInt() + "toLong" -> return (value as Short).toLong() + "toShort" -> return (value as Short).toShort() + "toString" -> return (value as Short).toString() + "unaryMinus" -> return (value as Short).unaryMinus() + "unaryPlus" -> return (value as Short).unaryPlus() + } + STRING -> when (name) { + "length" -> return (value as String).length + "toString" -> return (value as String).toString() + } + } + return null +} -internal val unaryOperations: HashMap, Pair, Function1>> - = hashMapOf, Pair, Function1>>( - unaryOperation(BOOLEAN, "not", { a -> a.not() }, emptyUnaryFun), - unaryOperation(BOOLEAN, "toString", { a -> a.toString() }, emptyUnaryFun), - unaryOperation(BYTE, "toByte", { a -> a.toByte() }, emptyUnaryFun), - unaryOperation(BYTE, "toChar", { a -> a.toChar() }, emptyUnaryFun), - unaryOperation(BYTE, "toDouble", { a -> a.toDouble() }, emptyUnaryFun), - unaryOperation(BYTE, "toFloat", { a -> a.toFloat() }, emptyUnaryFun), - unaryOperation(BYTE, "toInt", { a -> a.toInt() }, emptyUnaryFun), - unaryOperation(BYTE, "toLong", { a -> a.toLong() }, emptyUnaryFun), - unaryOperation(BYTE, "toShort", { a -> a.toShort() }, emptyUnaryFun), - unaryOperation(BYTE, "toString", { a -> a.toString() }, emptyUnaryFun), - unaryOperation(BYTE, "unaryMinus", { a -> a.unaryMinus() }, { a -> a.unaryMinus() }), - unaryOperation(BYTE, "unaryPlus", { a -> a.unaryPlus() }, emptyUnaryFun), - unaryOperation(CHAR, "toByte", { a -> a.toByte() }, emptyUnaryFun), - unaryOperation(CHAR, "toChar", { a -> a.toChar() }, emptyUnaryFun), - unaryOperation(CHAR, "toDouble", { a -> a.toDouble() }, emptyUnaryFun), - unaryOperation(CHAR, "toFloat", { a -> a.toFloat() }, emptyUnaryFun), - unaryOperation(CHAR, "toInt", { a -> a.toInt() }, emptyUnaryFun), - unaryOperation(CHAR, "toLong", { a -> a.toLong() }, emptyUnaryFun), - unaryOperation(CHAR, "toShort", { a -> a.toShort() }, emptyUnaryFun), - unaryOperation(CHAR, "toString", { a -> a.toString() }, emptyUnaryFun), - unaryOperation(DOUBLE, "toByte", { a -> a.toByte() }, emptyUnaryFun), - unaryOperation(DOUBLE, "toChar", { a -> a.toChar() }, emptyUnaryFun), - unaryOperation(DOUBLE, "toDouble", { a -> a.toDouble() }, emptyUnaryFun), - unaryOperation(DOUBLE, "toFloat", { a -> a.toFloat() }, emptyUnaryFun), - unaryOperation(DOUBLE, "toInt", { a -> a.toInt() }, emptyUnaryFun), - unaryOperation(DOUBLE, "toLong", { a -> a.toLong() }, emptyUnaryFun), - unaryOperation(DOUBLE, "toShort", { a -> a.toShort() }, emptyUnaryFun), - unaryOperation(DOUBLE, "toString", { a -> a.toString() }, emptyUnaryFun), - unaryOperation(DOUBLE, "unaryMinus", { a -> a.unaryMinus() }, emptyUnaryFun), - unaryOperation(DOUBLE, "unaryPlus", { a -> a.unaryPlus() }, emptyUnaryFun), - unaryOperation(FLOAT, "toByte", { a -> a.toByte() }, emptyUnaryFun), - unaryOperation(FLOAT, "toChar", { a -> a.toChar() }, emptyUnaryFun), - unaryOperation(FLOAT, "toDouble", { a -> a.toDouble() }, emptyUnaryFun), - unaryOperation(FLOAT, "toFloat", { a -> a.toFloat() }, emptyUnaryFun), - unaryOperation(FLOAT, "toInt", { a -> a.toInt() }, emptyUnaryFun), - unaryOperation(FLOAT, "toLong", { a -> a.toLong() }, emptyUnaryFun), - unaryOperation(FLOAT, "toShort", { a -> a.toShort() }, emptyUnaryFun), - unaryOperation(FLOAT, "toString", { a -> a.toString() }, emptyUnaryFun), - unaryOperation(FLOAT, "unaryMinus", { a -> a.unaryMinus() }, emptyUnaryFun), - unaryOperation(FLOAT, "unaryPlus", { a -> a.unaryPlus() }, emptyUnaryFun), - unaryOperation(INT, "inv", { a -> a.inv() }, emptyUnaryFun), - unaryOperation(INT, "toByte", { a -> a.toByte() }, emptyUnaryFun), - unaryOperation(INT, "toChar", { a -> a.toChar() }, emptyUnaryFun), - unaryOperation(INT, "toDouble", { a -> a.toDouble() }, emptyUnaryFun), - unaryOperation(INT, "toFloat", { a -> a.toFloat() }, emptyUnaryFun), - unaryOperation(INT, "toInt", { a -> a.toInt() }, emptyUnaryFun), - unaryOperation(INT, "toLong", { a -> a.toLong() }, emptyUnaryFun), - unaryOperation(INT, "toShort", { a -> a.toShort() }, emptyUnaryFun), - unaryOperation(INT, "toString", { a -> a.toString() }, emptyUnaryFun), - unaryOperation(INT, "unaryMinus", { a -> a.unaryMinus() }, { a -> a.unaryMinus() }), - unaryOperation(INT, "unaryPlus", { a -> a.unaryPlus() }, emptyUnaryFun), - unaryOperation(LONG, "inv", { a -> a.inv() }, emptyUnaryFun), - unaryOperation(LONG, "toByte", { a -> a.toByte() }, emptyUnaryFun), - unaryOperation(LONG, "toChar", { a -> a.toChar() }, emptyUnaryFun), - unaryOperation(LONG, "toDouble", { a -> a.toDouble() }, emptyUnaryFun), - unaryOperation(LONG, "toFloat", { a -> a.toFloat() }, emptyUnaryFun), - unaryOperation(LONG, "toInt", { a -> a.toInt() }, emptyUnaryFun), - unaryOperation(LONG, "toLong", { a -> a.toLong() }, emptyUnaryFun), - unaryOperation(LONG, "toShort", { a -> a.toShort() }, emptyUnaryFun), - unaryOperation(LONG, "toString", { a -> a.toString() }, emptyUnaryFun), - unaryOperation(LONG, "unaryMinus", { a -> a.unaryMinus() }, { a -> a.unaryMinus() }), - unaryOperation(LONG, "unaryPlus", { a -> a.unaryPlus() }, emptyUnaryFun), - unaryOperation(SHORT, "toByte", { a -> a.toByte() }, emptyUnaryFun), - unaryOperation(SHORT, "toChar", { a -> a.toChar() }, emptyUnaryFun), - unaryOperation(SHORT, "toDouble", { a -> a.toDouble() }, emptyUnaryFun), - unaryOperation(SHORT, "toFloat", { a -> a.toFloat() }, emptyUnaryFun), - unaryOperation(SHORT, "toInt", { a -> a.toInt() }, emptyUnaryFun), - unaryOperation(SHORT, "toLong", { a -> a.toLong() }, emptyUnaryFun), - unaryOperation(SHORT, "toShort", { a -> a.toShort() }, emptyUnaryFun), - unaryOperation(SHORT, "toString", { a -> a.toString() }, emptyUnaryFun), - unaryOperation(SHORT, "unaryMinus", { a -> a.unaryMinus() }, { a -> a.unaryMinus() }), - unaryOperation(SHORT, "unaryPlus", { a -> a.unaryPlus() }, emptyUnaryFun), - unaryOperation(STRING, "length", { a -> a.length }, emptyUnaryFun), - unaryOperation(STRING, "toString", { a -> a.toString() }, emptyUnaryFun) -) -internal val binaryOperations: HashMap, Pair, Function2>> - = hashMapOf, Pair, Function2>>( - binaryOperation(BOOLEAN, BOOLEAN, "and", { a, b -> a.and(b) }, emptyBinaryFun), - binaryOperation(BOOLEAN, BOOLEAN, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(BOOLEAN, ANY, "equals", { a, b -> a.equals(b) }, emptyBinaryFun), - binaryOperation(BOOLEAN, BOOLEAN, "or", { a, b -> a.or(b) }, emptyBinaryFun), - binaryOperation(BOOLEAN, BOOLEAN, "xor", { a, b -> a.xor(b) }, emptyBinaryFun), - binaryOperation(BYTE, BYTE, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(BYTE, DOUBLE, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(BYTE, FLOAT, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(BYTE, INT, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(BYTE, LONG, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(BYTE, SHORT, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(BYTE, BYTE, "div", { a, b -> a.div(b) }, { a, b -> a.divide(b) }), - binaryOperation(BYTE, DOUBLE, "div", { a, b -> a.div(b) }, emptyBinaryFun), - binaryOperation(BYTE, FLOAT, "div", { a, b -> a.div(b) }, emptyBinaryFun), - binaryOperation(BYTE, INT, "div", { a, b -> a.div(b) }, { a, b -> a.divide(b) }), - binaryOperation(BYTE, LONG, "div", { a, b -> a.div(b) }, { a, b -> a.divide(b) }), - binaryOperation(BYTE, SHORT, "div", { a, b -> a.div(b) }, { a, b -> a.divide(b) }), - binaryOperation(BYTE, ANY, "equals", { a, b -> a.equals(b) }, emptyBinaryFun), - binaryOperation(BYTE, BYTE, "minus", { a, b -> a.minus(b) }, { a, b -> a.subtract(b) }), - binaryOperation(BYTE, DOUBLE, "minus", { a, b -> a.minus(b) }, emptyBinaryFun), - binaryOperation(BYTE, FLOAT, "minus", { a, b -> a.minus(b) }, emptyBinaryFun), - binaryOperation(BYTE, INT, "minus", { a, b -> a.minus(b) }, { a, b -> a.subtract(b) }), - binaryOperation(BYTE, LONG, "minus", { a, b -> a.minus(b) }, { a, b -> a.subtract(b) }), - binaryOperation(BYTE, SHORT, "minus", { a, b -> a.minus(b) }, { a, b -> a.subtract(b) }), - binaryOperation(BYTE, BYTE, "plus", { a, b -> a.plus(b) }, { a, b -> a.add(b) }), - binaryOperation(BYTE, DOUBLE, "plus", { a, b -> a.plus(b) }, emptyBinaryFun), - binaryOperation(BYTE, FLOAT, "plus", { a, b -> a.plus(b) }, emptyBinaryFun), - binaryOperation(BYTE, INT, "plus", { a, b -> a.plus(b) }, { a, b -> a.add(b) }), - binaryOperation(BYTE, LONG, "plus", { a, b -> a.plus(b) }, { a, b -> a.add(b) }), - binaryOperation(BYTE, SHORT, "plus", { a, b -> a.plus(b) }, { a, b -> a.add(b) }), - binaryOperation(BYTE, BYTE, "rem", { a, b -> a.rem(b) }, { a, b -> a.rem(b) }), - binaryOperation(BYTE, DOUBLE, "rem", { a, b -> a.rem(b) }, emptyBinaryFun), - binaryOperation(BYTE, FLOAT, "rem", { a, b -> a.rem(b) }, emptyBinaryFun), - binaryOperation(BYTE, INT, "rem", { a, b -> a.rem(b) }, { a, b -> a.rem(b) }), - binaryOperation(BYTE, LONG, "rem", { a, b -> a.rem(b) }, { a, b -> a.rem(b) }), - binaryOperation(BYTE, SHORT, "rem", { a, b -> a.rem(b) }, { a, b -> a.rem(b) }), - binaryOperation(BYTE, BYTE, "times", { a, b -> a.times(b) }, { a, b -> a.multiply(b) }), - binaryOperation(BYTE, DOUBLE, "times", { a, b -> a.times(b) }, emptyBinaryFun), - binaryOperation(BYTE, FLOAT, "times", { a, b -> a.times(b) }, emptyBinaryFun), - binaryOperation(BYTE, INT, "times", { a, b -> a.times(b) }, { a, b -> a.multiply(b) }), - binaryOperation(BYTE, LONG, "times", { a, b -> a.times(b) }, { a, b -> a.multiply(b) }), - binaryOperation(BYTE, SHORT, "times", { a, b -> a.times(b) }, { a, b -> a.multiply(b) }), - binaryOperation(CHAR, CHAR, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(CHAR, ANY, "equals", { a, b -> a.equals(b) }, emptyBinaryFun), - binaryOperation(CHAR, CHAR, "minus", { a, b -> a.minus(b) }, emptyBinaryFun), - binaryOperation(CHAR, INT, "minus", { a, b -> a.minus(b) }, emptyBinaryFun), - binaryOperation(CHAR, INT, "plus", { a, b -> a.plus(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, BYTE, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, DOUBLE, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, FLOAT, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, INT, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, LONG, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, SHORT, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, BYTE, "div", { a, b -> a.div(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, DOUBLE, "div", { a, b -> a.div(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, FLOAT, "div", { a, b -> a.div(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, INT, "div", { a, b -> a.div(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, LONG, "div", { a, b -> a.div(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, SHORT, "div", { a, b -> a.div(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, ANY, "equals", { a, b -> a.equals(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, BYTE, "minus", { a, b -> a.minus(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, DOUBLE, "minus", { a, b -> a.minus(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, FLOAT, "minus", { a, b -> a.minus(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, INT, "minus", { a, b -> a.minus(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, LONG, "minus", { a, b -> a.minus(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, SHORT, "minus", { a, b -> a.minus(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, BYTE, "plus", { a, b -> a.plus(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, DOUBLE, "plus", { a, b -> a.plus(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, FLOAT, "plus", { a, b -> a.plus(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, INT, "plus", { a, b -> a.plus(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, LONG, "plus", { a, b -> a.plus(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, SHORT, "plus", { a, b -> a.plus(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, BYTE, "rem", { a, b -> a.rem(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, DOUBLE, "rem", { a, b -> a.rem(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, FLOAT, "rem", { a, b -> a.rem(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, INT, "rem", { a, b -> a.rem(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, LONG, "rem", { a, b -> a.rem(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, SHORT, "rem", { a, b -> a.rem(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, BYTE, "times", { a, b -> a.times(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, DOUBLE, "times", { a, b -> a.times(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, FLOAT, "times", { a, b -> a.times(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, INT, "times", { a, b -> a.times(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, LONG, "times", { a, b -> a.times(b) }, emptyBinaryFun), - binaryOperation(DOUBLE, SHORT, "times", { a, b -> a.times(b) }, emptyBinaryFun), - binaryOperation(FLOAT, BYTE, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(FLOAT, DOUBLE, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(FLOAT, FLOAT, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(FLOAT, INT, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(FLOAT, LONG, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(FLOAT, SHORT, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(FLOAT, BYTE, "div", { a, b -> a.div(b) }, emptyBinaryFun), - binaryOperation(FLOAT, DOUBLE, "div", { a, b -> a.div(b) }, emptyBinaryFun), - binaryOperation(FLOAT, FLOAT, "div", { a, b -> a.div(b) }, emptyBinaryFun), - binaryOperation(FLOAT, INT, "div", { a, b -> a.div(b) }, emptyBinaryFun), - binaryOperation(FLOAT, LONG, "div", { a, b -> a.div(b) }, emptyBinaryFun), - binaryOperation(FLOAT, SHORT, "div", { a, b -> a.div(b) }, emptyBinaryFun), - binaryOperation(FLOAT, ANY, "equals", { a, b -> a.equals(b) }, emptyBinaryFun), - binaryOperation(FLOAT, BYTE, "minus", { a, b -> a.minus(b) }, emptyBinaryFun), - binaryOperation(FLOAT, DOUBLE, "minus", { a, b -> a.minus(b) }, emptyBinaryFun), - binaryOperation(FLOAT, FLOAT, "minus", { a, b -> a.minus(b) }, emptyBinaryFun), - binaryOperation(FLOAT, INT, "minus", { a, b -> a.minus(b) }, emptyBinaryFun), - binaryOperation(FLOAT, LONG, "minus", { a, b -> a.minus(b) }, emptyBinaryFun), - binaryOperation(FLOAT, SHORT, "minus", { a, b -> a.minus(b) }, emptyBinaryFun), - binaryOperation(FLOAT, BYTE, "plus", { a, b -> a.plus(b) }, emptyBinaryFun), - binaryOperation(FLOAT, DOUBLE, "plus", { a, b -> a.plus(b) }, emptyBinaryFun), - binaryOperation(FLOAT, FLOAT, "plus", { a, b -> a.plus(b) }, emptyBinaryFun), - binaryOperation(FLOAT, INT, "plus", { a, b -> a.plus(b) }, emptyBinaryFun), - binaryOperation(FLOAT, LONG, "plus", { a, b -> a.plus(b) }, emptyBinaryFun), - binaryOperation(FLOAT, SHORT, "plus", { a, b -> a.plus(b) }, emptyBinaryFun), - binaryOperation(FLOAT, BYTE, "rem", { a, b -> a.rem(b) }, emptyBinaryFun), - binaryOperation(FLOAT, DOUBLE, "rem", { a, b -> a.rem(b) }, emptyBinaryFun), - binaryOperation(FLOAT, FLOAT, "rem", { a, b -> a.rem(b) }, emptyBinaryFun), - binaryOperation(FLOAT, INT, "rem", { a, b -> a.rem(b) }, emptyBinaryFun), - binaryOperation(FLOAT, LONG, "rem", { a, b -> a.rem(b) }, emptyBinaryFun), - binaryOperation(FLOAT, SHORT, "rem", { a, b -> a.rem(b) }, emptyBinaryFun), - binaryOperation(FLOAT, BYTE, "times", { a, b -> a.times(b) }, emptyBinaryFun), - binaryOperation(FLOAT, DOUBLE, "times", { a, b -> a.times(b) }, emptyBinaryFun), - binaryOperation(FLOAT, FLOAT, "times", { a, b -> a.times(b) }, emptyBinaryFun), - binaryOperation(FLOAT, INT, "times", { a, b -> a.times(b) }, emptyBinaryFun), - binaryOperation(FLOAT, LONG, "times", { a, b -> a.times(b) }, emptyBinaryFun), - binaryOperation(FLOAT, SHORT, "times", { a, b -> a.times(b) }, emptyBinaryFun), - binaryOperation(INT, INT, "and", { a, b -> a.and(b) }, { a, b -> a.and(b) }), - binaryOperation(INT, BYTE, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(INT, DOUBLE, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(INT, FLOAT, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(INT, INT, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(INT, LONG, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(INT, SHORT, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(INT, BYTE, "div", { a, b -> a.div(b) }, { a, b -> a.divide(b) }), - binaryOperation(INT, DOUBLE, "div", { a, b -> a.div(b) }, emptyBinaryFun), - binaryOperation(INT, FLOAT, "div", { a, b -> a.div(b) }, emptyBinaryFun), - binaryOperation(INT, INT, "div", { a, b -> a.div(b) }, { a, b -> a.divide(b) }), - binaryOperation(INT, LONG, "div", { a, b -> a.div(b) }, { a, b -> a.divide(b) }), - binaryOperation(INT, SHORT, "div", { a, b -> a.div(b) }, { a, b -> a.divide(b) }), - binaryOperation(INT, ANY, "equals", { a, b -> a.equals(b) }, emptyBinaryFun), - binaryOperation(INT, BYTE, "minus", { a, b -> a.minus(b) }, { a, b -> a.subtract(b) }), - binaryOperation(INT, DOUBLE, "minus", { a, b -> a.minus(b) }, emptyBinaryFun), - binaryOperation(INT, FLOAT, "minus", { a, b -> a.minus(b) }, emptyBinaryFun), - binaryOperation(INT, INT, "minus", { a, b -> a.minus(b) }, { a, b -> a.subtract(b) }), - binaryOperation(INT, LONG, "minus", { a, b -> a.minus(b) }, { a, b -> a.subtract(b) }), - binaryOperation(INT, SHORT, "minus", { a, b -> a.minus(b) }, { a, b -> a.subtract(b) }), - binaryOperation(INT, INT, "or", { a, b -> a.or(b) }, { a, b -> a.or(b) }), - binaryOperation(INT, BYTE, "plus", { a, b -> a.plus(b) }, { a, b -> a.add(b) }), - binaryOperation(INT, DOUBLE, "plus", { a, b -> a.plus(b) }, emptyBinaryFun), - binaryOperation(INT, FLOAT, "plus", { a, b -> a.plus(b) }, emptyBinaryFun), - binaryOperation(INT, INT, "plus", { a, b -> a.plus(b) }, { a, b -> a.add(b) }), - binaryOperation(INT, LONG, "plus", { a, b -> a.plus(b) }, { a, b -> a.add(b) }), - binaryOperation(INT, SHORT, "plus", { a, b -> a.plus(b) }, { a, b -> a.add(b) }), - binaryOperation(INT, BYTE, "rem", { a, b -> a.rem(b) }, { a, b -> a.rem(b) }), - binaryOperation(INT, DOUBLE, "rem", { a, b -> a.rem(b) }, emptyBinaryFun), - binaryOperation(INT, FLOAT, "rem", { a, b -> a.rem(b) }, emptyBinaryFun), - binaryOperation(INT, INT, "rem", { a, b -> a.rem(b) }, { a, b -> a.rem(b) }), - binaryOperation(INT, LONG, "rem", { a, b -> a.rem(b) }, { a, b -> a.rem(b) }), - binaryOperation(INT, SHORT, "rem", { a, b -> a.rem(b) }, { a, b -> a.rem(b) }), - binaryOperation(INT, INT, "shl", { a, b -> a.shl(b) }, emptyBinaryFun), - binaryOperation(INT, INT, "shr", { a, b -> a.shr(b) }, emptyBinaryFun), - binaryOperation(INT, BYTE, "times", { a, b -> a.times(b) }, { a, b -> a.multiply(b) }), - binaryOperation(INT, DOUBLE, "times", { a, b -> a.times(b) }, emptyBinaryFun), - binaryOperation(INT, FLOAT, "times", { a, b -> a.times(b) }, emptyBinaryFun), - binaryOperation(INT, INT, "times", { a, b -> a.times(b) }, { a, b -> a.multiply(b) }), - binaryOperation(INT, LONG, "times", { a, b -> a.times(b) }, { a, b -> a.multiply(b) }), - binaryOperation(INT, SHORT, "times", { a, b -> a.times(b) }, { a, b -> a.multiply(b) }), - binaryOperation(INT, INT, "ushr", { a, b -> a.ushr(b) }, emptyBinaryFun), - binaryOperation(INT, INT, "xor", { a, b -> a.xor(b) }, { a, b -> a.xor(b) }), - binaryOperation(LONG, LONG, "and", { a, b -> a.and(b) }, { a, b -> a.and(b) }), - binaryOperation(LONG, BYTE, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(LONG, DOUBLE, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(LONG, FLOAT, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(LONG, INT, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(LONG, LONG, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(LONG, SHORT, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(LONG, BYTE, "div", { a, b -> a.div(b) }, { a, b -> a.divide(b) }), - binaryOperation(LONG, DOUBLE, "div", { a, b -> a.div(b) }, emptyBinaryFun), - binaryOperation(LONG, FLOAT, "div", { a, b -> a.div(b) }, emptyBinaryFun), - binaryOperation(LONG, INT, "div", { a, b -> a.div(b) }, { a, b -> a.divide(b) }), - binaryOperation(LONG, LONG, "div", { a, b -> a.div(b) }, { a, b -> a.divide(b) }), - binaryOperation(LONG, SHORT, "div", { a, b -> a.div(b) }, { a, b -> a.divide(b) }), - binaryOperation(LONG, ANY, "equals", { a, b -> a.equals(b) }, emptyBinaryFun), - binaryOperation(LONG, BYTE, "minus", { a, b -> a.minus(b) }, { a, b -> a.subtract(b) }), - binaryOperation(LONG, DOUBLE, "minus", { a, b -> a.minus(b) }, emptyBinaryFun), - binaryOperation(LONG, FLOAT, "minus", { a, b -> a.minus(b) }, emptyBinaryFun), - binaryOperation(LONG, INT, "minus", { a, b -> a.minus(b) }, { a, b -> a.subtract(b) }), - binaryOperation(LONG, LONG, "minus", { a, b -> a.minus(b) }, { a, b -> a.subtract(b) }), - binaryOperation(LONG, SHORT, "minus", { a, b -> a.minus(b) }, { a, b -> a.subtract(b) }), - binaryOperation(LONG, LONG, "or", { a, b -> a.or(b) }, { a, b -> a.or(b) }), - binaryOperation(LONG, BYTE, "plus", { a, b -> a.plus(b) }, { a, b -> a.add(b) }), - binaryOperation(LONG, DOUBLE, "plus", { a, b -> a.plus(b) }, emptyBinaryFun), - binaryOperation(LONG, FLOAT, "plus", { a, b -> a.plus(b) }, emptyBinaryFun), - binaryOperation(LONG, INT, "plus", { a, b -> a.plus(b) }, { a, b -> a.add(b) }), - binaryOperation(LONG, LONG, "plus", { a, b -> a.plus(b) }, { a, b -> a.add(b) }), - binaryOperation(LONG, SHORT, "plus", { a, b -> a.plus(b) }, { a, b -> a.add(b) }), - binaryOperation(LONG, BYTE, "rem", { a, b -> a.rem(b) }, { a, b -> a.rem(b) }), - binaryOperation(LONG, DOUBLE, "rem", { a, b -> a.rem(b) }, emptyBinaryFun), - binaryOperation(LONG, FLOAT, "rem", { a, b -> a.rem(b) }, emptyBinaryFun), - binaryOperation(LONG, INT, "rem", { a, b -> a.rem(b) }, { a, b -> a.rem(b) }), - binaryOperation(LONG, LONG, "rem", { a, b -> a.rem(b) }, { a, b -> a.rem(b) }), - binaryOperation(LONG, SHORT, "rem", { a, b -> a.rem(b) }, { a, b -> a.rem(b) }), - binaryOperation(LONG, INT, "shl", { a, b -> a.shl(b) }, emptyBinaryFun), - binaryOperation(LONG, INT, "shr", { a, b -> a.shr(b) }, emptyBinaryFun), - binaryOperation(LONG, BYTE, "times", { a, b -> a.times(b) }, { a, b -> a.multiply(b) }), - binaryOperation(LONG, DOUBLE, "times", { a, b -> a.times(b) }, emptyBinaryFun), - binaryOperation(LONG, FLOAT, "times", { a, b -> a.times(b) }, emptyBinaryFun), - binaryOperation(LONG, INT, "times", { a, b -> a.times(b) }, { a, b -> a.multiply(b) }), - binaryOperation(LONG, LONG, "times", { a, b -> a.times(b) }, { a, b -> a.multiply(b) }), - binaryOperation(LONG, SHORT, "times", { a, b -> a.times(b) }, { a, b -> a.multiply(b) }), - binaryOperation(LONG, INT, "ushr", { a, b -> a.ushr(b) }, emptyBinaryFun), - binaryOperation(LONG, LONG, "xor", { a, b -> a.xor(b) }, { a, b -> a.xor(b) }), - binaryOperation(SHORT, BYTE, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(SHORT, DOUBLE, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(SHORT, FLOAT, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(SHORT, INT, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(SHORT, LONG, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(SHORT, SHORT, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(SHORT, BYTE, "div", { a, b -> a.div(b) }, { a, b -> a.divide(b) }), - binaryOperation(SHORT, DOUBLE, "div", { a, b -> a.div(b) }, emptyBinaryFun), - binaryOperation(SHORT, FLOAT, "div", { a, b -> a.div(b) }, emptyBinaryFun), - binaryOperation(SHORT, INT, "div", { a, b -> a.div(b) }, { a, b -> a.divide(b) }), - binaryOperation(SHORT, LONG, "div", { a, b -> a.div(b) }, { a, b -> a.divide(b) }), - binaryOperation(SHORT, SHORT, "div", { a, b -> a.div(b) }, { a, b -> a.divide(b) }), - binaryOperation(SHORT, ANY, "equals", { a, b -> a.equals(b) }, emptyBinaryFun), - binaryOperation(SHORT, BYTE, "minus", { a, b -> a.minus(b) }, { a, b -> a.subtract(b) }), - binaryOperation(SHORT, DOUBLE, "minus", { a, b -> a.minus(b) }, emptyBinaryFun), - binaryOperation(SHORT, FLOAT, "minus", { a, b -> a.minus(b) }, emptyBinaryFun), - binaryOperation(SHORT, INT, "minus", { a, b -> a.minus(b) }, { a, b -> a.subtract(b) }), - binaryOperation(SHORT, LONG, "minus", { a, b -> a.minus(b) }, { a, b -> a.subtract(b) }), - binaryOperation(SHORT, SHORT, "minus", { a, b -> a.minus(b) }, { a, b -> a.subtract(b) }), - binaryOperation(SHORT, BYTE, "plus", { a, b -> a.plus(b) }, { a, b -> a.add(b) }), - binaryOperation(SHORT, DOUBLE, "plus", { a, b -> a.plus(b) }, emptyBinaryFun), - binaryOperation(SHORT, FLOAT, "plus", { a, b -> a.plus(b) }, emptyBinaryFun), - binaryOperation(SHORT, INT, "plus", { a, b -> a.plus(b) }, { a, b -> a.add(b) }), - binaryOperation(SHORT, LONG, "plus", { a, b -> a.plus(b) }, { a, b -> a.add(b) }), - binaryOperation(SHORT, SHORT, "plus", { a, b -> a.plus(b) }, { a, b -> a.add(b) }), - binaryOperation(SHORT, BYTE, "rem", { a, b -> a.rem(b) }, { a, b -> a.rem(b) }), - binaryOperation(SHORT, DOUBLE, "rem", { a, b -> a.rem(b) }, emptyBinaryFun), - binaryOperation(SHORT, FLOAT, "rem", { a, b -> a.rem(b) }, emptyBinaryFun), - binaryOperation(SHORT, INT, "rem", { a, b -> a.rem(b) }, { a, b -> a.rem(b) }), - binaryOperation(SHORT, LONG, "rem", { a, b -> a.rem(b) }, { a, b -> a.rem(b) }), - binaryOperation(SHORT, SHORT, "rem", { a, b -> a.rem(b) }, { a, b -> a.rem(b) }), - binaryOperation(SHORT, BYTE, "times", { a, b -> a.times(b) }, { a, b -> a.multiply(b) }), - binaryOperation(SHORT, DOUBLE, "times", { a, b -> a.times(b) }, emptyBinaryFun), - binaryOperation(SHORT, FLOAT, "times", { a, b -> a.times(b) }, emptyBinaryFun), - binaryOperation(SHORT, INT, "times", { a, b -> a.times(b) }, { a, b -> a.multiply(b) }), - binaryOperation(SHORT, LONG, "times", { a, b -> a.times(b) }, { a, b -> a.multiply(b) }), - binaryOperation(SHORT, SHORT, "times", { a, b -> a.times(b) }, { a, b -> a.multiply(b) }), - binaryOperation(STRING, STRING, "compareTo", { a, b -> a.compareTo(b) }, emptyBinaryFun), - binaryOperation(STRING, ANY, "equals", { a, b -> a.equals(b) }, emptyBinaryFun), - binaryOperation(STRING, INT, "get", { a, b -> a.get(b) }, emptyBinaryFun), - binaryOperation(STRING, ANY, "plus", { a, b -> a.plus(b) }, emptyBinaryFun) -) +internal fun evalBinaryOp(name: String, leftType: CompileTimeType, left: Any, rightType: CompileTimeType, right: Any): Any? { + when (leftType) { + BOOLEAN -> when (rightType) { + BOOLEAN -> when (name) { + "and" -> return (left as Boolean).and(right as Boolean) + "compareTo" -> return (left as Boolean).compareTo(right as Boolean) + "or" -> return (left as Boolean).or(right as Boolean) + "xor" -> return (left as Boolean).xor(right as Boolean) + } + ANY -> when (name) { + "equals" -> return (left as Boolean).equals(right) + } + } + BYTE -> when (rightType) { + BYTE -> when (name) { + "compareTo" -> return (left as Byte).compareTo(right as Byte) + "div" -> return (left as Byte).div(right as Byte) + "minus" -> return (left as Byte).minus(right as Byte) + "plus" -> return (left as Byte).plus(right as Byte) + "rem" -> return (left as Byte).rem(right as Byte) + "times" -> return (left as Byte).times(right as Byte) + } + DOUBLE -> when (name) { + "compareTo" -> return (left as Byte).compareTo(right as Double) + "div" -> return (left as Byte).div(right as Double) + "minus" -> return (left as Byte).minus(right as Double) + "plus" -> return (left as Byte).plus(right as Double) + "rem" -> return (left as Byte).rem(right as Double) + "times" -> return (left as Byte).times(right as Double) + } + FLOAT -> when (name) { + "compareTo" -> return (left as Byte).compareTo(right as Float) + "div" -> return (left as Byte).div(right as Float) + "minus" -> return (left as Byte).minus(right as Float) + "plus" -> return (left as Byte).plus(right as Float) + "rem" -> return (left as Byte).rem(right as Float) + "times" -> return (left as Byte).times(right as Float) + } + INT -> when (name) { + "compareTo" -> return (left as Byte).compareTo(right as Int) + "div" -> return (left as Byte).div(right as Int) + "minus" -> return (left as Byte).minus(right as Int) + "plus" -> return (left as Byte).plus(right as Int) + "rem" -> return (left as Byte).rem(right as Int) + "times" -> return (left as Byte).times(right as Int) + } + LONG -> when (name) { + "compareTo" -> return (left as Byte).compareTo(right as Long) + "div" -> return (left as Byte).div(right as Long) + "minus" -> return (left as Byte).minus(right as Long) + "plus" -> return (left as Byte).plus(right as Long) + "rem" -> return (left as Byte).rem(right as Long) + "times" -> return (left as Byte).times(right as Long) + } + SHORT -> when (name) { + "compareTo" -> return (left as Byte).compareTo(right as Short) + "div" -> return (left as Byte).div(right as Short) + "minus" -> return (left as Byte).minus(right as Short) + "plus" -> return (left as Byte).plus(right as Short) + "rem" -> return (left as Byte).rem(right as Short) + "times" -> return (left as Byte).times(right as Short) + } + ANY -> when (name) { + "equals" -> return (left as Byte).equals(right) + } + } + CHAR -> when (rightType) { + CHAR -> when (name) { + "compareTo" -> return (left as Char).compareTo(right as Char) + "minus" -> return (left as Char).minus(right as Char) + } + ANY -> when (name) { + "equals" -> return (left as Char).equals(right) + } + INT -> when (name) { + "minus" -> return (left as Char).minus(right as Int) + "plus" -> return (left as Char).plus(right as Int) + } + } + DOUBLE -> when (rightType) { + BYTE -> when (name) { + "compareTo" -> return (left as Double).compareTo(right as Byte) + "div" -> return (left as Double).div(right as Byte) + "minus" -> return (left as Double).minus(right as Byte) + "plus" -> return (left as Double).plus(right as Byte) + "rem" -> return (left as Double).rem(right as Byte) + "times" -> return (left as Double).times(right as Byte) + } + DOUBLE -> when (name) { + "compareTo" -> return (left as Double).compareTo(right as Double) + "div" -> return (left as Double).div(right as Double) + "minus" -> return (left as Double).minus(right as Double) + "plus" -> return (left as Double).plus(right as Double) + "rem" -> return (left as Double).rem(right as Double) + "times" -> return (left as Double).times(right as Double) + } + FLOAT -> when (name) { + "compareTo" -> return (left as Double).compareTo(right as Float) + "div" -> return (left as Double).div(right as Float) + "minus" -> return (left as Double).minus(right as Float) + "plus" -> return (left as Double).plus(right as Float) + "rem" -> return (left as Double).rem(right as Float) + "times" -> return (left as Double).times(right as Float) + } + INT -> when (name) { + "compareTo" -> return (left as Double).compareTo(right as Int) + "div" -> return (left as Double).div(right as Int) + "minus" -> return (left as Double).minus(right as Int) + "plus" -> return (left as Double).plus(right as Int) + "rem" -> return (left as Double).rem(right as Int) + "times" -> return (left as Double).times(right as Int) + } + LONG -> when (name) { + "compareTo" -> return (left as Double).compareTo(right as Long) + "div" -> return (left as Double).div(right as Long) + "minus" -> return (left as Double).minus(right as Long) + "plus" -> return (left as Double).plus(right as Long) + "rem" -> return (left as Double).rem(right as Long) + "times" -> return (left as Double).times(right as Long) + } + SHORT -> when (name) { + "compareTo" -> return (left as Double).compareTo(right as Short) + "div" -> return (left as Double).div(right as Short) + "minus" -> return (left as Double).minus(right as Short) + "plus" -> return (left as Double).plus(right as Short) + "rem" -> return (left as Double).rem(right as Short) + "times" -> return (left as Double).times(right as Short) + } + ANY -> when (name) { + "equals" -> return (left as Double).equals(right) + } + } + FLOAT -> when (rightType) { + BYTE -> when (name) { + "compareTo" -> return (left as Float).compareTo(right as Byte) + "div" -> return (left as Float).div(right as Byte) + "minus" -> return (left as Float).minus(right as Byte) + "plus" -> return (left as Float).plus(right as Byte) + "rem" -> return (left as Float).rem(right as Byte) + "times" -> return (left as Float).times(right as Byte) + } + DOUBLE -> when (name) { + "compareTo" -> return (left as Float).compareTo(right as Double) + "div" -> return (left as Float).div(right as Double) + "minus" -> return (left as Float).minus(right as Double) + "plus" -> return (left as Float).plus(right as Double) + "rem" -> return (left as Float).rem(right as Double) + "times" -> return (left as Float).times(right as Double) + } + FLOAT -> when (name) { + "compareTo" -> return (left as Float).compareTo(right as Float) + "div" -> return (left as Float).div(right as Float) + "minus" -> return (left as Float).minus(right as Float) + "plus" -> return (left as Float).plus(right as Float) + "rem" -> return (left as Float).rem(right as Float) + "times" -> return (left as Float).times(right as Float) + } + INT -> when (name) { + "compareTo" -> return (left as Float).compareTo(right as Int) + "div" -> return (left as Float).div(right as Int) + "minus" -> return (left as Float).minus(right as Int) + "plus" -> return (left as Float).plus(right as Int) + "rem" -> return (left as Float).rem(right as Int) + "times" -> return (left as Float).times(right as Int) + } + LONG -> when (name) { + "compareTo" -> return (left as Float).compareTo(right as Long) + "div" -> return (left as Float).div(right as Long) + "minus" -> return (left as Float).minus(right as Long) + "plus" -> return (left as Float).plus(right as Long) + "rem" -> return (left as Float).rem(right as Long) + "times" -> return (left as Float).times(right as Long) + } + SHORT -> when (name) { + "compareTo" -> return (left as Float).compareTo(right as Short) + "div" -> return (left as Float).div(right as Short) + "minus" -> return (left as Float).minus(right as Short) + "plus" -> return (left as Float).plus(right as Short) + "rem" -> return (left as Float).rem(right as Short) + "times" -> return (left as Float).times(right as Short) + } + ANY -> when (name) { + "equals" -> return (left as Float).equals(right) + } + } + INT -> when (rightType) { + INT -> when (name) { + "and" -> return (left as Int).and(right as Int) + "compareTo" -> return (left as Int).compareTo(right as Int) + "div" -> return (left as Int).div(right as Int) + "minus" -> return (left as Int).minus(right as Int) + "or" -> return (left as Int).or(right as Int) + "plus" -> return (left as Int).plus(right as Int) + "rem" -> return (left as Int).rem(right as Int) + "shl" -> return (left as Int).shl(right as Int) + "shr" -> return (left as Int).shr(right as Int) + "times" -> return (left as Int).times(right as Int) + "ushr" -> return (left as Int).ushr(right as Int) + "xor" -> return (left as Int).xor(right as Int) + } + BYTE -> when (name) { + "compareTo" -> return (left as Int).compareTo(right as Byte) + "div" -> return (left as Int).div(right as Byte) + "minus" -> return (left as Int).minus(right as Byte) + "plus" -> return (left as Int).plus(right as Byte) + "rem" -> return (left as Int).rem(right as Byte) + "times" -> return (left as Int).times(right as Byte) + } + DOUBLE -> when (name) { + "compareTo" -> return (left as Int).compareTo(right as Double) + "div" -> return (left as Int).div(right as Double) + "minus" -> return (left as Int).minus(right as Double) + "plus" -> return (left as Int).plus(right as Double) + "rem" -> return (left as Int).rem(right as Double) + "times" -> return (left as Int).times(right as Double) + } + FLOAT -> when (name) { + "compareTo" -> return (left as Int).compareTo(right as Float) + "div" -> return (left as Int).div(right as Float) + "minus" -> return (left as Int).minus(right as Float) + "plus" -> return (left as Int).plus(right as Float) + "rem" -> return (left as Int).rem(right as Float) + "times" -> return (left as Int).times(right as Float) + } + LONG -> when (name) { + "compareTo" -> return (left as Int).compareTo(right as Long) + "div" -> return (left as Int).div(right as Long) + "minus" -> return (left as Int).minus(right as Long) + "plus" -> return (left as Int).plus(right as Long) + "rem" -> return (left as Int).rem(right as Long) + "times" -> return (left as Int).times(right as Long) + } + SHORT -> when (name) { + "compareTo" -> return (left as Int).compareTo(right as Short) + "div" -> return (left as Int).div(right as Short) + "minus" -> return (left as Int).minus(right as Short) + "plus" -> return (left as Int).plus(right as Short) + "rem" -> return (left as Int).rem(right as Short) + "times" -> return (left as Int).times(right as Short) + } + ANY -> when (name) { + "equals" -> return (left as Int).equals(right) + } + } + LONG -> when (rightType) { + LONG -> when (name) { + "and" -> return (left as Long).and(right as Long) + "compareTo" -> return (left as Long).compareTo(right as Long) + "div" -> return (left as Long).div(right as Long) + "minus" -> return (left as Long).minus(right as Long) + "or" -> return (left as Long).or(right as Long) + "plus" -> return (left as Long).plus(right as Long) + "rem" -> return (left as Long).rem(right as Long) + "times" -> return (left as Long).times(right as Long) + "xor" -> return (left as Long).xor(right as Long) + } + BYTE -> when (name) { + "compareTo" -> return (left as Long).compareTo(right as Byte) + "div" -> return (left as Long).div(right as Byte) + "minus" -> return (left as Long).minus(right as Byte) + "plus" -> return (left as Long).plus(right as Byte) + "rem" -> return (left as Long).rem(right as Byte) + "times" -> return (left as Long).times(right as Byte) + } + DOUBLE -> when (name) { + "compareTo" -> return (left as Long).compareTo(right as Double) + "div" -> return (left as Long).div(right as Double) + "minus" -> return (left as Long).minus(right as Double) + "plus" -> return (left as Long).plus(right as Double) + "rem" -> return (left as Long).rem(right as Double) + "times" -> return (left as Long).times(right as Double) + } + FLOAT -> when (name) { + "compareTo" -> return (left as Long).compareTo(right as Float) + "div" -> return (left as Long).div(right as Float) + "minus" -> return (left as Long).minus(right as Float) + "plus" -> return (left as Long).plus(right as Float) + "rem" -> return (left as Long).rem(right as Float) + "times" -> return (left as Long).times(right as Float) + } + INT -> when (name) { + "compareTo" -> return (left as Long).compareTo(right as Int) + "div" -> return (left as Long).div(right as Int) + "minus" -> return (left as Long).minus(right as Int) + "plus" -> return (left as Long).plus(right as Int) + "rem" -> return (left as Long).rem(right as Int) + "shl" -> return (left as Long).shl(right as Int) + "shr" -> return (left as Long).shr(right as Int) + "times" -> return (left as Long).times(right as Int) + "ushr" -> return (left as Long).ushr(right as Int) + } + SHORT -> when (name) { + "compareTo" -> return (left as Long).compareTo(right as Short) + "div" -> return (left as Long).div(right as Short) + "minus" -> return (left as Long).minus(right as Short) + "plus" -> return (left as Long).plus(right as Short) + "rem" -> return (left as Long).rem(right as Short) + "times" -> return (left as Long).times(right as Short) + } + ANY -> when (name) { + "equals" -> return (left as Long).equals(right) + } + } + SHORT -> when (rightType) { + BYTE -> when (name) { + "compareTo" -> return (left as Short).compareTo(right as Byte) + "div" -> return (left as Short).div(right as Byte) + "minus" -> return (left as Short).minus(right as Byte) + "plus" -> return (left as Short).plus(right as Byte) + "rem" -> return (left as Short).rem(right as Byte) + "times" -> return (left as Short).times(right as Byte) + } + DOUBLE -> when (name) { + "compareTo" -> return (left as Short).compareTo(right as Double) + "div" -> return (left as Short).div(right as Double) + "minus" -> return (left as Short).minus(right as Double) + "plus" -> return (left as Short).plus(right as Double) + "rem" -> return (left as Short).rem(right as Double) + "times" -> return (left as Short).times(right as Double) + } + FLOAT -> when (name) { + "compareTo" -> return (left as Short).compareTo(right as Float) + "div" -> return (left as Short).div(right as Float) + "minus" -> return (left as Short).minus(right as Float) + "plus" -> return (left as Short).plus(right as Float) + "rem" -> return (left as Short).rem(right as Float) + "times" -> return (left as Short).times(right as Float) + } + INT -> when (name) { + "compareTo" -> return (left as Short).compareTo(right as Int) + "div" -> return (left as Short).div(right as Int) + "minus" -> return (left as Short).minus(right as Int) + "plus" -> return (left as Short).plus(right as Int) + "rem" -> return (left as Short).rem(right as Int) + "times" -> return (left as Short).times(right as Int) + } + LONG -> when (name) { + "compareTo" -> return (left as Short).compareTo(right as Long) + "div" -> return (left as Short).div(right as Long) + "minus" -> return (left as Short).minus(right as Long) + "plus" -> return (left as Short).plus(right as Long) + "rem" -> return (left as Short).rem(right as Long) + "times" -> return (left as Short).times(right as Long) + } + SHORT -> when (name) { + "compareTo" -> return (left as Short).compareTo(right as Short) + "div" -> return (left as Short).div(right as Short) + "minus" -> return (left as Short).minus(right as Short) + "plus" -> return (left as Short).plus(right as Short) + "rem" -> return (left as Short).rem(right as Short) + "times" -> return (left as Short).times(right as Short) + } + ANY -> when (name) { + "equals" -> return (left as Short).equals(right) + } + } + STRING -> when (rightType) { + STRING -> when (name) { + "compareTo" -> return (left as String).compareTo(right as String) + } + ANY -> when (name) { + "equals" -> return (left as String).equals(right) + "plus" -> return (left as String).plus(right) + } + INT -> when (name) { + "get" -> return (left as String).get(right as Int) + } + } + } + return null +} + +internal fun checkBinaryOp( + name: String, leftType: CompileTimeType, left: BigInteger, rightType: CompileTimeType, right: BigInteger +): BigInteger? { + when (leftType) { + BYTE -> when (rightType) { + BYTE -> when (name) { + "div" -> return left.divide(right) + "minus" -> return left.subtract(right) + "plus" -> return left.add(right) + "rem" -> return left.rem(right) + "times" -> return left.multiply(right) + } + INT -> when (name) { + "div" -> return left.divide(right) + "minus" -> return left.subtract(right) + "plus" -> return left.add(right) + "rem" -> return left.rem(right) + "times" -> return left.multiply(right) + } + LONG -> when (name) { + "div" -> return left.divide(right) + "minus" -> return left.subtract(right) + "plus" -> return left.add(right) + "rem" -> return left.rem(right) + "times" -> return left.multiply(right) + } + SHORT -> when (name) { + "div" -> return left.divide(right) + "minus" -> return left.subtract(right) + "plus" -> return left.add(right) + "rem" -> return left.rem(right) + "times" -> return left.multiply(right) + } + } + INT -> when (rightType) { + INT -> when (name) { + "and" -> return left.and(right) + "div" -> return left.divide(right) + "minus" -> return left.subtract(right) + "or" -> return left.or(right) + "plus" -> return left.add(right) + "rem" -> return left.rem(right) + "times" -> return left.multiply(right) + "xor" -> return left.xor(right) + } + BYTE -> when (name) { + "div" -> return left.divide(right) + "minus" -> return left.subtract(right) + "plus" -> return left.add(right) + "rem" -> return left.rem(right) + "times" -> return left.multiply(right) + } + LONG -> when (name) { + "div" -> return left.divide(right) + "minus" -> return left.subtract(right) + "plus" -> return left.add(right) + "rem" -> return left.rem(right) + "times" -> return left.multiply(right) + } + SHORT -> when (name) { + "div" -> return left.divide(right) + "minus" -> return left.subtract(right) + "plus" -> return left.add(right) + "rem" -> return left.rem(right) + "times" -> return left.multiply(right) + } + } + LONG -> when (rightType) { + LONG -> when (name) { + "and" -> return left.and(right) + "div" -> return left.divide(right) + "minus" -> return left.subtract(right) + "or" -> return left.or(right) + "plus" -> return left.add(right) + "rem" -> return left.rem(right) + "times" -> return left.multiply(right) + "xor" -> return left.xor(right) + } + BYTE -> when (name) { + "div" -> return left.divide(right) + "minus" -> return left.subtract(right) + "plus" -> return left.add(right) + "rem" -> return left.rem(right) + "times" -> return left.multiply(right) + } + INT -> when (name) { + "div" -> return left.divide(right) + "minus" -> return left.subtract(right) + "plus" -> return left.add(right) + "rem" -> return left.rem(right) + "times" -> return left.multiply(right) + } + SHORT -> when (name) { + "div" -> return left.divide(right) + "minus" -> return left.subtract(right) + "plus" -> return left.add(right) + "rem" -> return left.rem(right) + "times" -> return left.multiply(right) + } + } + SHORT -> when (rightType) { + BYTE -> when (name) { + "div" -> return left.divide(right) + "minus" -> return left.subtract(right) + "plus" -> return left.add(right) + "rem" -> return left.rem(right) + "times" -> return left.multiply(right) + } + INT -> when (name) { + "div" -> return left.divide(right) + "minus" -> return left.subtract(right) + "plus" -> return left.add(right) + "rem" -> return left.rem(right) + "times" -> return left.multiply(right) + } + LONG -> when (name) { + "div" -> return left.divide(right) + "minus" -> return left.subtract(right) + "plus" -> return left.add(right) + "rem" -> return left.rem(right) + "times" -> return left.multiply(right) + } + SHORT -> when (name) { + "div" -> return left.divide(right) + "minus" -> return left.subtract(right) + "plus" -> return left.add(right) + "rem" -> return left.rem(right) + "times" -> return left.multiply(right) + } + } + } + return null +} diff --git a/generators/evaluate/GenerateOperationsMap.kt b/generators/evaluate/GenerateOperationsMap.kt index e2a7646c391..acf4d3931fa 100644 --- a/generators/evaluate/GenerateOperationsMap.kt +++ b/generators/evaluate/GenerateOperationsMap.kt @@ -12,7 +12,7 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.generators.util.GeneratorsFileUtil import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.TypeUtils +import org.jetbrains.kotlin.types.typeUtil.makeNotNullable import org.jetbrains.kotlin.utils.Printer import java.io.File @@ -27,29 +27,30 @@ fun generate(): String { val sb = StringBuilder() val p = Printer(sb) p.println(File("license/COPYRIGHT.txt").readText()) - p.println("@file:Suppress(\"DEPRECATION\", \"DEPRECATION_ERROR\")") + p.println("@file:Suppress(\"DEPRECATION\", \"DEPRECATION_ERROR\", \"NON_EXHAUSTIVE_WHEN\")") p.println() p.println("package org.jetbrains.kotlin.resolve.constants.evaluate") p.println() + p.println("import org.jetbrains.kotlin.resolve.constants.evaluate.CompileTimeType.*") p.println("import java.math.BigInteger") - p.println("import java.util.HashMap") p.println() - p.println("/** This file is generated by org.jetbrains.kotlin.generators.evaluate:generate(). DO NOT MODIFY MANUALLY */") + p.println("/** This file is generated by `./gradlew generateOperationsMap`. DO NOT MODIFY MANUALLY */") p.println() val unaryOperationsMap = arrayListOf, Boolean>>() val binaryOperationsMap = arrayListOf>>() val builtIns = DefaultBuiltIns.Instance + @Suppress("UNCHECKED_CAST") val allPrimitiveTypes = builtIns.builtInsPackageScope.getContributedDescriptors() - .filter { it is ClassDescriptor && KotlinBuiltIns.isPrimitiveType(it.defaultType) } as List + .filter { it is ClassDescriptor && KotlinBuiltIns.isPrimitiveType(it.defaultType) } as List for (descriptor in allPrimitiveTypes + builtIns.string) { @Suppress("UNCHECKED_CAST") val functions = descriptor.getMemberScope(listOf()).getContributedDescriptors() - .filter { it is CallableDescriptor && !EXCLUDED_FUNCTIONS.contains(it.getName().asString()) } as List + .filter { it is CallableDescriptor && !EXCLUDED_FUNCTIONS.contains(it.getName().asString()) } as List for (function in functions) { val parametersTypes = function.getParametersTypes() @@ -57,108 +58,116 @@ fun generate(): String { when (parametersTypes.size) { 1 -> unaryOperationsMap.add(Triple(function.name.asString(), parametersTypes, function is FunctionDescriptor)) 2 -> binaryOperationsMap.add(function.name.asString() to parametersTypes) - else -> throw IllegalStateException("Couldn't add following method from builtins to operations map: ${function.name} in class ${descriptor.name}") + else -> throw IllegalStateException( + "Couldn't add following method from builtins to operations map: ${function.name} in class ${descriptor.name}" + ) } } } - p.println("internal val emptyBinaryFun: Function2 = { _, _ -> BigInteger(\"0\") }") - p.println("internal val emptyUnaryFun: Function1 = { _ -> 1.toLong() }") - p.println() - p.println("internal val unaryOperations: HashMap, Pair, Function1>>") - p.println(" = hashMapOf, Pair, Function1>>(") + p.println("internal fun evalUnaryOp(name: String, type: CompileTimeType, value: Any): Any? {") p.pushIndent() - - val unaryOperationsMapIterator = unaryOperationsMap.iterator() - while (unaryOperationsMapIterator.hasNext()) { - val (funcName, parameters, isFunction) = unaryOperationsMapIterator.next() - val parenthesesOrBlank = if (isFunction) "()" else "" - p.println( - "unaryOperation(", - parameters.map { it.asString() }.joinToString(", "), - ", ", - "\"$funcName\"", - ", { a -> a.$funcName$parenthesesOrBlank }, ", - renderCheckUnaryOperation(funcName, parameters), - ")", - if (unaryOperationsMapIterator.hasNext()) "," else "" - ) + p.println("when (type) {") + p.pushIndent() + for ((type, operations) in unaryOperationsMap.groupBy { (_, parameters, _) -> parameters.single() }) { + p.println("${type.asString()} -> when (name) {") + p.pushIndent() + for ((name, _, isFunction) in operations) { + val parenthesesOrBlank = if (isFunction) "()" else "" + p.println("\"$name\" -> return (value as ${type.typeName}).$name$parenthesesOrBlank") + } + p.popIndent() + p.println("}") } p.popIndent() - p.println(")") - + p.println("}") + p.println("return null") + p.popIndent() + p.println("}") + p.println() p.println() - p.println("internal val binaryOperations: HashMap, Pair, Function2>>") - p.println(" = hashMapOf, Pair, Function2>>(") + p.println("internal fun evalBinaryOp(name: String, leftType: CompileTimeType, left: Any, rightType: CompileTimeType, right: Any): Any? {") p.pushIndent() - - val binaryOperationsMapIterator = binaryOperationsMap.iterator() - while (binaryOperationsMapIterator.hasNext()) { - val (funcName, parameters) = binaryOperationsMapIterator.next() - p.println( - "binaryOperation(", - parameters.map { it.asString() }.joinToString(", "), - ", ", - "\"$funcName\"", - ", { a, b -> a.$funcName(b) }, ", - renderCheckBinaryOperation(funcName, parameters), - ")", - if (binaryOperationsMapIterator.hasNext()) "," else "" - ) + p.println("when (leftType) {") + p.pushIndent() + for ((leftType, operationsOnThisLeftType) in binaryOperationsMap.groupBy { (_, parameters) -> parameters.first() }) { + p.println("${leftType.asString()} -> when (rightType) {") + p.pushIndent() + for ((rightType, operations) in operationsOnThisLeftType.groupBy { (_, parameters) -> parameters[1] }) { + p.println("${rightType.asString()} -> when (name) {") + p.pushIndent() + for ((name, _) in operations) { + val castToRightType = if (rightType.typeName == "Any") "" else " as ${rightType.typeName}" + p.println("\"$name\" -> return (left as ${leftType.typeName}).$name(right$castToRightType)") + } + p.popIndent() + p.println("}") + } + p.popIndent() + p.println("}") } p.popIndent() - p.println(")") + p.println("}") + p.println("return null") + p.popIndent() + p.println("}") + p.println() + + p.println("internal fun checkBinaryOp(") + p.println(" name: String, leftType: CompileTimeType, left: BigInteger, rightType: CompileTimeType, right: BigInteger") + p.println("): BigInteger? {") + p.pushIndent() + p.println("when (leftType) {") + p.pushIndent() + val checkedBinaryOperations = + binaryOperationsMap.filter { (name, parameters) -> getBinaryCheckerName(name, parameters[0], parameters[1]) != null } + for ((leftType, operationsOnThisLeftType) in checkedBinaryOperations.groupBy { (_, parameters) -> parameters.first() }) { + p.println("${leftType.asString()} -> when (rightType) {") + p.pushIndent() + for ((rightType, operations) in operationsOnThisLeftType.groupBy { (_, parameters) -> parameters[1] }) { + p.println("${rightType.asString()} -> when (name) {") + p.pushIndent() + for ((name, _) in operations) { + val checkerName = getBinaryCheckerName(name, leftType, rightType)!! + p.println("\"$name\" -> return left.$checkerName(right)") + } + p.popIndent() + p.println("}") + } + p.popIndent() + p.println("}") + } + p.popIndent() + p.println("}") + p.println("return null") + p.popIndent() + p.println("}") return sb.toString() } -fun renderCheckUnaryOperation(name: String, params: List): String { - val isAllParamsIntegers = params.fold(true) { a, b -> a && b.isIntegerType() } - if (!isAllParamsIntegers) { - return "emptyUnaryFun" - } +private fun getBinaryCheckerName(name: String, leftType: KotlinType, rightType: KotlinType): String? { + if (!leftType.isIntegerType() || !rightType.isIntegerType()) return null - return when(name) { - "unaryMinus", "minus" -> "{ a -> a.$name() }" - else -> "emptyUnaryFun" + return when (name) { + "plus" -> "add" + "minus" -> "subtract" + "div" -> "divide" + "times" -> "multiply" + "mod", "rem", "xor", "or", "and" -> name + else -> null } } -fun renderCheckBinaryOperation(name: String, params: List): String { - val isAllParamsIntegers = params.fold(true) { a, b -> a && b.isIntegerType() } - if (!isAllParamsIntegers) { - return "emptyBinaryFun" - } +private fun KotlinType.isIntegerType(): Boolean = + KotlinBuiltIns.isInt(this) || KotlinBuiltIns.isShort(this) || KotlinBuiltIns.isByte(this) || KotlinBuiltIns.isLong(this) - return when(name) { - "plus" -> "{ a, b -> a.add(b) }" - "minus" -> "{ a, b -> a.subtract(b) }" - "div" -> "{ a, b -> a.divide(b) }" - "times" -> "{ a, b -> a.multiply(b) }" - "mod", - "rem", - "xor", - "or", - "and" -> "{ a, b -> a.$name(b) }" - else -> "emptyBinaryFun" - } -} +private fun CallableDescriptor.getParametersTypes(): List = + listOf((containingDeclaration as ClassDescriptor).defaultType) + + valueParameters.map { it.type.makeNotNullable() } -private fun KotlinType.isIntegerType(): Boolean { - return KotlinBuiltIns.isInt(this) || - KotlinBuiltIns.isShort(this) || - KotlinBuiltIns.isByte(this) || - KotlinBuiltIns.isLong(this) -} +private fun KotlinType.asString(): String = typeName.toUpperCase() - -private fun CallableDescriptor.getParametersTypes(): List { - val list = arrayListOf((containingDeclaration as ClassDescriptor).defaultType) - valueParameters.map { it.type }.forEach { - list.add(TypeUtils.makeNotNullable(it)) - } - return list -} - -private fun KotlinType.asString(): String = constructor.declarationDescriptor!!.name.asString().toUpperCase() +private val KotlinType.typeName: String + get(): String = constructor.declarationDescriptor!!.name.asString()