From d931e2eeadb2cc07dbd345d5aa18b8f0c01eac63 Mon Sep 17 00:00:00 2001 From: Ivan Kylchik Date: Sun, 30 Aug 2020 21:36:37 +0300 Subject: [PATCH] Implement simple proxy for non interface structures like kotlin.Pair --- .../kotlin/ir/interpreter/IrInterpreter.kt | 5 ++-- .../ir/interpreter/proxy/CommonProxy.kt | 26 +++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt index c4860d3f02b..8fbab5fa0e9 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt @@ -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))) } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/CommonProxy.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/CommonProxy.kt index ae4aeca929f..8352d47d26d 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/CommonProxy.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/proxy/CommonProxy.kt @@ -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)