Support interpretation of dataClassArrayMemberToString method

This commit is contained in:
Ivan Kylchik
2021-06-08 17:25:55 +03:00
committed by TeamCityServer
parent 15808cb376
commit 42ea17b151
5 changed files with 43 additions and 1 deletions
@@ -61,7 +61,7 @@ internal class DefaultCallInterceptor(override val interpreter: IrInterpreter) :
return interpreter.withNewCallStack(irCall) {
this@withNewCallStack.environment.callStack.addInstruction(SimpleInstruction(irCall))
valueArguments.forEach { this@withNewCallStack.environment.callStack.addVariable(it) }
}.wrap(this@DefaultCallInterceptor, remainArraysAsIs = true, extendFrom = expectedResultClass)
}.wrap(this@DefaultCallInterceptor, remainArraysAsIs = false, extendFrom = expectedResultClass)
}
override fun interceptCall(call: IrCall, irFunction: IrFunction, args: List<State>, defaultAction: () -> Unit) {
@@ -8,6 +8,10 @@ package org.jetbrains.kotlin.ir.interpreter.exceptions
import org.jetbrains.kotlin.ir.interpreter.IrInterpreterEnvironment
import org.jetbrains.kotlin.ir.interpreter.state.ExceptionState
internal fun stop(lazyMessage: () -> Any): Nothing {
throw InterpreterAssertionError(lazyMessage().toString())
}
internal fun verify(value: Boolean) {
verify(value) { "Assertion failed" }
}
@@ -24,6 +24,7 @@ internal object IntrinsicEvaluator {
ArrayConstructor.canHandleFunctionWithName(fqName, irFunction.origin) -> ArrayConstructor.unwind(irFunction, environment)
SourceLocation.canHandleFunctionWithName(fqName, irFunction.origin) -> SourceLocation.unwind(irFunction, environment)
AssertIntrinsic.canHandleFunctionWithName(fqName, irFunction.origin) -> AssertIntrinsic.unwind(irFunction, environment)
DataClassArrayToString.canHandleFunctionWithName(fqName, irFunction.origin) -> DataClassArrayToString.unwind(irFunction, environment)
else -> null
}
}
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
import org.jetbrains.kotlin.ir.interpreter.*
import org.jetbrains.kotlin.ir.interpreter.exceptions.handleUserException
import org.jetbrains.kotlin.ir.interpreter.exceptions.stop
import org.jetbrains.kotlin.ir.interpreter.state.*
import org.jetbrains.kotlin.ir.interpreter.state.reflection.KFunctionState
import org.jetbrains.kotlin.ir.interpreter.state.reflection.KPropertyState
@@ -21,6 +22,7 @@ import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.ir.util.resolveFakeOverride
import org.jetbrains.kotlin.types.Variance
import java.util.*
internal sealed class IntrinsicBase {
abstract fun canHandleFunctionWithName(fqName: String, origin: IrDeclarationOrigin): Boolean
@@ -304,4 +306,31 @@ internal object AssertIntrinsic : IntrinsicBase() {
2 -> AssertionError(environment.callStack.popState().asString()).handleUserException(environment)
}
}
}
internal object DataClassArrayToString : IntrinsicBase() {
override fun canHandleFunctionWithName(fqName: String, origin: IrDeclarationOrigin): Boolean {
return fqName == "kotlin.internal.ir.dataClassArrayMemberToString"
}
private fun arrayToString(array: Any?): String {
return when (array) {
null -> "null"
is Array<*> -> Arrays.toString(array)
is ByteArray -> Arrays.toString(array)
is ShortArray -> Arrays.toString(array)
is IntArray -> Arrays.toString(array)
is LongArray -> Arrays.toString(array)
is CharArray -> Arrays.toString(array)
is BooleanArray -> Arrays.toString(array)
is FloatArray -> Arrays.toString(array)
is DoubleArray -> Arrays.toString(array)
else -> stop { "Only arrays are supported in `dataClassArrayMemberToString` call" }
}
}
override fun evaluate(irFunction: IrFunction, environment: IrInterpreterEnvironment) {
val array = environment.callStack.getState(irFunction.valueParameters.single().symbol) as Primitive<*>
environment.callStack.pushState(arrayToString(array.value).toState(irFunction.returnType))
}
}
+8
View File
@@ -17,3 +17,11 @@ const val b2 = Person("John", 789).copy("Adam", 123).<!EVALUATED: `Person(name=A
const val c = Person("John", 123456).<!EVALUATED: `true`!>equals(Person("John", 123456))<!>
const val d = Person("John", 123456).<!EVALUATED: `Person name is John and his phone is 123456`!>getAsString()<!>
@CompileTimeCalculation
data class WithArray(val array: Array<*>?, val intArray: IntArray?)
const val e1 = WithArray(arrayOf(1, 2.0), intArrayOf(1, 2, 3)).<!EVALUATED: `WithArray(array=[1, 2.0], intArray=[1, 2, 3])`!>toString()<!>
const val e2 = WithArray(null, intArrayOf(1, 2, 3)).<!EVALUATED: `WithArray(array=null, intArray=[1, 2, 3])`!>toString()<!>
const val e3 = WithArray(arrayOf("1", false), null).<!EVALUATED: `WithArray(array=[1, false], intArray=null)`!>toString()<!>
const val e4 = WithArray(null, null).<!EVALUATED: `WithArray(array=null, intArray=null)`!>toString()<!>