Support interpretation for floorDiv and mod functions

This commit is contained in:
Ivan Kylchik
2021-08-04 16:59:02 +03:00
committed by TeamCityServer
parent f9607292b5
commit b85a796492
6 changed files with 103 additions and 10 deletions
@@ -643,6 +643,66 @@ internal fun interpretBinaryFunction(name: String, typeA: String, typeB: String,
"OROR" -> when (typeA) {
"Boolean" -> if (typeB == "Boolean") return (a as Boolean) || (b as Boolean)
}
"mod" -> when (typeA) {
"Byte" -> when (typeB) {
"Byte" -> return (a as Byte).mod(b as Byte)
"Short" -> return (a as Byte).mod(b as Short)
"Int" -> return (a as Byte).mod(b as Int)
"Long" -> return (a as Byte).mod(b as Long)
}
"Short" -> when (typeB) {
"Byte" -> return (a as Short).mod(b as Byte)
"Short" -> return (a as Short).mod(b as Short)
"Int" -> return (a as Short).mod(b as Int)
"Long" -> return (a as Short).mod(b as Long)
}
"Int" -> when (typeB) {
"Byte" -> return (a as Int).mod(b as Byte)
"Short" -> return (a as Int).mod(b as Short)
"Int" -> return (a as Int).mod(b as Int)
"Long" -> return (a as Int).mod(b as Long)
}
"Long" -> when (typeB) {
"Byte" -> return (a as Long).mod(b as Byte)
"Short" -> return (a as Long).mod(b as Short)
"Int" -> return (a as Long).mod(b as Int)
"Long" -> return (a as Long).mod(b as Long)
}
"Float" -> when (typeB) {
"Float" -> return (a as Float).mod(b as Float)
"Double" -> return (a as Float).mod(b as Double)
}
"Double" -> when (typeB) {
"Float" -> return (a as Double).mod(b as Float)
"Double" -> return (a as Double).mod(b as Double)
}
}
"floorDiv" -> when (typeA) {
"Byte" -> when (typeB) {
"Byte" -> return (a as Byte).floorDiv(b as Byte)
"Short" -> return (a as Byte).floorDiv(b as Short)
"Int" -> return (a as Byte).floorDiv(b as Int)
"Long" -> return (a as Byte).floorDiv(b as Long)
}
"Short" -> when (typeB) {
"Byte" -> return (a as Short).floorDiv(b as Byte)
"Short" -> return (a as Short).floorDiv(b as Short)
"Int" -> return (a as Short).floorDiv(b as Int)
"Long" -> return (a as Short).floorDiv(b as Long)
}
"Int" -> when (typeB) {
"Byte" -> return (a as Int).floorDiv(b as Byte)
"Short" -> return (a as Int).floorDiv(b as Short)
"Int" -> return (a as Int).floorDiv(b as Int)
"Long" -> return (a as Int).floorDiv(b as Long)
}
"Long" -> when (typeB) {
"Byte" -> return (a as Long).floorDiv(b as Byte)
"Short" -> return (a as Long).floorDiv(b as Short)
"Int" -> return (a as Long).floorDiv(b as Int)
"Long" -> return (a as Long).floorDiv(b as Long)
}
}
}
throw InterpreterMethodNotFoundError("Unknown function: $name($typeA, $typeB)")
}
@@ -51,19 +51,22 @@ enum class EvaluationMode(protected val mustCheckBody: Boolean) {
ONLY_BUILTINS(mustCheckBody = false) {
private val forbiddenMethodsOnPrimitives = setOf("inc", "dec", "rangeTo", "hashCode")
private val forbiddenMethodsOnStrings = setOf("subSequence", "hashCode", "<init>")
private val allowedExtensionFunctions = setOf("kotlin.floorDiv", "kotlin.mod", "kotlin.NumbersKt.floorDiv", "kotlin.NumbersKt.mod")
override fun canEvaluateFunction(function: IrFunction, expression: IrCall?): Boolean {
if ((function as? IrSimpleFunction)?.correspondingPropertySymbol?.owner?.isConst == true) return true
val parent = function.parentClassOrNull ?: return false
val parentType = parent.defaultType
val fqName = function.fqNameWhenAvailable?.asString()
val parent = function.parentClassOrNull
val parentType = parent?.defaultType
return when {
parentType == null -> fqName in allowedExtensionFunctions
parentType.isPrimitiveType() -> function.name.asString() !in forbiddenMethodsOnPrimitives
parentType.isString() -> function.name.asString() !in forbiddenMethodsOnStrings
parentType.isAny() -> function.name.asString() == "toString" && expression?.dispatchReceiver !is IrGetObjectValue
parent.isObject -> parent.parentClassOrNull?.defaultType?.let { it.isPrimitiveType() || it.isUnsigned() } == true
parentType.isUnsignedType() && function is IrConstructor -> true
else -> false
else -> fqName in allowedExtensionFunctions
}
}
};