Implement simple proxy for non interface structures like kotlin.Pair

This commit is contained in:
Ivan Kylchik
2020-08-30 21:36:37 +03:00
committed by TeamCityServer
parent 1e5096294e
commit d931e2eead
2 changed files with 29 additions and 2 deletions
@@ -701,6 +701,7 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
}
}
val elementIrClass = expression.varargElementType.classOrNull
val args = expression.elements.flatMap {
it.interpret().check { executionResult -> return executionResult }
return@flatMap when (val result = stack.popReturnValue()) {
@@ -708,7 +709,7 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
is Primitive<*> -> arrayToList(result.value)
is Common -> when {
result.irClass.defaultType.isUnsignedArray() -> arrayToList((result.fields.single().state as Primitive<*>).value)
else -> listOf(result.asProxy(this))
else -> listOf(result.asProxy(this, elementIrClass?.owner))
}
else -> listOf(result)
}
@@ -729,7 +730,7 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
}
else -> args.toPrimitiveStateArray(expression.type).apply {
if (expression.type.isArray()) {
val arrayTypeArgument = expression.varargElementType.classOrNull?.let { Common(it.owner) }
val arrayTypeArgument = elementIrClass?.let { Common(it.owner) }
?: stack.getVariable(expression.varargElementType.classifierOrFail).state
this.addTypeArguments(listOf(Variable(irBuiltIns.arrayClass.owner.typeParameters.single().symbol, arrayTypeArgument)))
}
@@ -5,13 +5,20 @@
package org.jetbrains.kotlin.ir.interpreter.proxy
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
import org.jetbrains.kotlin.ir.interpreter.getDispatchReceiver
import org.jetbrains.kotlin.ir.interpreter.internalName
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
import org.jetbrains.kotlin.ir.interpreter.state.Common
import org.jetbrains.kotlin.ir.interpreter.toState
import org.jetbrains.kotlin.ir.types.defaultType
import org.jetbrains.kotlin.ir.types.isAny
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization
import org.jetbrains.kotlin.ir.util.isFakeOverriddenFromAny
import org.jetbrains.kotlin.ir.util.nameForIrSerialization
/**
* calledFromBuiltIns - used to avoid cyclic calls. For example:
@@ -57,6 +64,25 @@ internal class CommonProxy private constructor(
}
companion object {
internal fun Common.asProxy(interpreter: IrInterpreter, extendFrom: IrClass?): Any {
val elementType = when {
extendFrom?.defaultType?.isAny() == false -> {
val fqName = extendFrom.fqNameForIrSerialization.asString()
if (fqName.startsWith("kotlin")) Class.forName(fqName) else null
}
else -> null
}
return when (elementType) {
Pair::class.java -> {
val first = this.irClass.declarations.single { it.nameForIrSerialization.asString() == "first" } as IrSymbolOwner
val second = this.irClass.declarations.single { it.nameForIrSerialization.asString() == "second" } as IrSymbolOwner
Pair(this.getState(first.symbol), this.getState(second.symbol))
}
else -> this.asProxy(interpreter)
}
}
internal fun Common.asProxy(interpreter: IrInterpreter, extendFrom: Class<*>? = null, calledFromBuiltIns: Boolean = false): Any {
val commonProxy = CommonProxy(this, interpreter, calledFromBuiltIns)