diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/CallInterceptor.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/CallInterceptor.kt index 2ee556577d0..2d75e0fb32b 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/CallInterceptor.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/CallInterceptor.kt @@ -144,6 +144,9 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) : return true } + private data class Signature(var name: String, var args: List) + private data class Arg(var type: String, var value: Any?) + private fun calculateBuiltIns(irFunction: IrFunction, args: List) { val methodName = when (val property = irFunction.property?.symbol) { null -> irFunction.name.asString() @@ -151,42 +154,37 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) : } val receiverType = irFunction.dispatchReceiverParameter?.type ?: irFunction.extensionReceiverParameter?.type - val argsType = (listOfNotNull(receiverType) + irFunction.valueParameters.map { it.type }).map { - // TODO: for consistency with current K/JS implementation Float constant should be treated as a Double (KT-35422) - if (environment.configuration.treatFloatInSpecialWay && it.makeNotNull().isFloat()) { - if (it.isNullable()) irBuiltIns.doubleType.makeNullable() else irBuiltIns.doubleType - } else { - it - } - } + val argsType = (listOfNotNull(receiverType) + irFunction.valueParameters.map { it.type }).map { it.getOnlyName() } val argsValues = args.wrap(this, irFunction) - // TODO replace unary, binary, ternary functions with vararg withExceptionHandler(environment) { - val result = when (argsType.size) { - 1 -> when { - methodName == "toString" && environment.configuration.treatFloatInSpecialWay && (argsValues[0] is Double || argsValues[0] is Float) -> { - argsValues[0].specialToStringForJs() - } - else -> interpretUnaryFunction(methodName, argsType[0].getOnlyName(), argsValues[0]) - } - 2 -> when (methodName) { - "rangeTo" -> return calculateRangeTo(irFunction.returnType, args) - else -> interpretBinaryFunction( - methodName, argsType[0].getOnlyName(), argsType[1].getOnlyName(), argsValues[0], argsValues[1] - ) - } - 3 -> interpretTernaryFunction( - methodName, argsType[0].getOnlyName(), argsType[1].getOnlyName(), argsType[2].getOnlyName(), - argsValues[0], argsValues[1], argsValues[2] - ) - else -> throw InterpreterError("Unsupported number of arguments for invocation as builtin function: $methodName") - } + if (methodName == "rangeTo") return calculateRangeTo(irFunction.returnType, args) + val result = interpretBuiltinFunction(Signature(methodName, argsType.zip(argsValues).map { Arg(it.first, it.second) })) // TODO check "result is Unit" callStack.pushState(environment.convertToState(result, result.getType(irFunction.returnType))) } } + private fun interpretBuiltinFunction(signature: Signature): Any? { + if (environment.configuration.treatFloatInSpecialWay) { + if (signature.name == "toString") return signature.args[0].value.specialToStringForJs() + if (signature.name == "toFloat") signature.name = "toDouble" + signature.args.filter { it.type == "Float" }.forEach { + it.type = "Double" + it.value = it.value.toString().toDouble() + } + } + + val name = signature.name + val args = signature.args + return when (args.size) { + 1 -> interpretUnaryFunction(name, args[0].type, args[0].value) + 2 -> interpretBinaryFunction(name, args[0].type, args[1].type, args[0].value, args[1].value) + 3 -> interpretTernaryFunction(name, args[0].type, args[1].type, args[2].type, args[0].value, args[1].value, args[2].value) + else -> throw InterpreterError("Unsupported number of arguments for invocation as builtin function: $name") + } + } + private fun calculateRangeTo(type: IrType, args: List) { val constructor = type.classOrNull!!.owner.constructors.first() val constructorCall = constructor.createConstructorCall() diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/InstructionsUnfolder.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/InstructionsUnfolder.kt index 881069190cc..9e5938d1e7b 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/InstructionsUnfolder.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/InstructionsUnfolder.kt @@ -395,7 +395,7 @@ private fun unfoldStringConcatenation(expression: IrStringConcatenation, environ val explicitToStringCheck = fun() { when (val state = callStack.peekState()) { is Primitive<*> -> { - // This block is not really needed, but this way it is easier to handle `toString` with `treatFloatInSpecialWay` enabled. + // This block is not really needed, but this way it is easier to handle `toString` for JS. callStack.popState() val toStringCall = IrCallImpl.fromSymbolOwner( UNDEFINED_OFFSET, UNDEFINED_OFFSET, diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrTreeBuildUtils.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrTreeBuildUtils.kt index 5634e5ebd8a..af3f1c34323 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrTreeBuildUtils.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrTreeBuildUtils.kt @@ -36,7 +36,7 @@ import org.jetbrains.kotlin.name.Name internal val TEMP_CLASS_FOR_INTERPRETER = object : IrDeclarationOriginImpl("TEMP_CLASS_FOR_INTERPRETER") {} internal val TEMP_FUNCTION_FOR_INTERPRETER = object : IrDeclarationOriginImpl("TEMP_FUNCTION_FOR_INTERPRETER") {} -fun Any?.toIrConstOrNull(irType: IrType, startOffset: Int = SYNTHETIC_OFFSET, endOffset: Int = SYNTHETIC_OFFSET): IrConst<*>? { +private fun Any?.toIrConstOrNull(irType: IrType, startOffset: Int = SYNTHETIC_OFFSET, endOffset: Int = SYNTHETIC_OFFSET): IrConst<*>? { if (this == null) return IrConstImpl.constNull(startOffset, endOffset, irType) val constType = irType.makeNotNull().removeAnnotations() diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/checker/IrInterpreterCommonChecker.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/checker/IrInterpreterCommonChecker.kt index ffe6c9df9a7..8b5d6aab212 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/checker/IrInterpreterCommonChecker.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/checker/IrInterpreterCommonChecker.kt @@ -61,13 +61,6 @@ class IrInterpreterCommonChecker : IrInterpreterChecker { val owner = expression.symbol.owner if (!data.mode.canEvaluateFunction(owner)) return false - // We disable `toFloat` folding on K/JS till `toFloat` is fixed (KT-35422) - // This check must be placed here instead of CallInterceptor because we still - // want to evaluate (1) `const val` expressions and (2) values in annotations. - if (owner.name.asString() == "toFloat" && data.interpreterConfiguration.treatFloatInSpecialWay) { - return super.visitCall(expression, data) - } - if (expression.dispatchReceiver.isAccessToNotNullableObject()) { return expression.isGetterToConstVal() } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/Proxy.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/Proxy.kt index 9d9fee04cc3..5cfd3795c33 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/Proxy.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/Proxy.kt @@ -35,8 +35,6 @@ internal fun State.wrap(callInterceptor: CallInterceptor, remainArraysAsIs: Bool is Primitive<*> -> when { this.isNull() -> null this.type.isArray() || this.type.isPrimitiveArray() -> if (remainArraysAsIs) this else this.value - // TODO: for consistency with current K/JS implementation Float constant should be treated as a Double (KT-35422) - this.type.isFloat() && callInterceptor.environment.configuration.treatFloatInSpecialWay -> this.value.toString().toDouble() else -> this.value } is Common -> this.asProxy(callInterceptor, extendFrom) diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/transformer/IrConstAnnotationTransformer.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/transformer/IrConstAnnotationTransformer.kt index c49e24f908f..b57d8880d00 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/transformer/IrConstAnnotationTransformer.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/transformer/IrConstAnnotationTransformer.kt @@ -63,7 +63,7 @@ internal abstract class IrConstAnnotationTransformer( } private fun IrExpression.transformSingleArg(expectedType: IrType): IrExpression { - if (this.canBeInterpreted(configuration = interpreter.environment.configuration.copy(treatFloatInSpecialWay = false))) { + if (this.canBeInterpreted()) { return this.interpret(failAsError = true).convertToConstIfPossible(expectedType) } else if (this is IrConstructorCall) { transformAnnotation(this) diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/transformer/IrConstExpressionTransformer.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/transformer/IrConstExpressionTransformer.kt index 156eb41c027..b106f6b6df1 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/transformer/IrConstExpressionTransformer.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/transformer/IrConstExpressionTransformer.kt @@ -44,7 +44,7 @@ internal class IrConstExpressionTransformer( if (!isConst) return super.visitField(declaration, data) val getField = declaration.createGetField() - if (getField.canBeInterpreted(interpreter.environment.configuration.copy(treatFloatInSpecialWay = false))) { + if (getField.canBeInterpreted()) { initializer.expression = expression.interpret(failAsError = true) }