diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/IrInterpreter.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/IrInterpreter.kt index 6503ccf120d..074bc51fcb3 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/IrInterpreter.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/IrInterpreter.kt @@ -5,26 +5,16 @@ package org.jetbrains.kotlin.backend.common.interpreter -import org.jetbrains.kotlin.backend.common.interpreter.builtins.CompileTimeFunction -import org.jetbrains.kotlin.backend.common.interpreter.builtins.binaryFunctions -import org.jetbrains.kotlin.backend.common.interpreter.builtins.unaryFunctions import org.jetbrains.kotlin.backend.common.interpreter.stack.* import org.jetbrains.kotlin.builtins.DefaultBuiltIns import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.declarations.IrConstructor -import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl -import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.util.isFakeOverride import org.jetbrains.kotlin.ir.util.statements import org.jetbrains.kotlin.ir.visitors.IrElementVisitor -import org.jetbrains.kotlin.resolve.descriptorUtil.classId -import org.jetbrains.kotlin.types.TypeUtils class IrInterpreter : IrElementVisitor { private val builtIns = DefaultBuiltIns.Instance @@ -41,57 +31,6 @@ class IrInterpreter : IrElementVisitor { else -> TODO("not supported") } } - //todo move out util methods - private fun IrElement?.getState(descriptor: DeclarationDescriptor, data: Frame): State? { - val arg = this?.accept(this@IrInterpreter, data) ?: return null - return arg.setDescriptor(descriptor) - } - - private fun IrMemberAccessExpression.convertValueParameters(data: Frame): MutableList { - val state = mutableListOf() - for (i in 0 until this.valueArgumentsCount) { - this.getValueArgument(i).getState((this.symbol.descriptor as FunctionDescriptor).valueParameters[i], data)?.let { state += it } - } - return state - } - - private fun calculateOverridden(symbol: IrFunctionSymbol, data: Frame): State { - val owner = symbol.owner as IrFunctionImpl - val overridden = owner.overriddenSymbols.first() - val overriddenReceiver = data.getVar(symbol.getThisAsReceiver()).getState(overridden.getThisAsReceiver()) - val valueParameters = symbol.owner.valueParameters.zip(overridden.owner.valueParameters) - .map { data.getVar(it.first.descriptor).setDescriptor(it.second.descriptor) } - val newStates = InterpreterFrame((valueParameters + overriddenReceiver).toMutableList()) - - return if (overridden.owner.body != null) { - overridden.owner.body!!.accept(this@IrInterpreter, newStates) - } else { - calculateOverridden(overridden.owner.symbol, newStates) - } - } - - private fun calculateBuiltIns(descriptor: FunctionDescriptor, frame: Frame): Any { - val methodName = descriptor.name.asString() - val receiverType = descriptor.dispatchReceiverParameter?.type ?: descriptor.extensionReceiverParameter?.type - val argsType = listOfNotNull(receiverType) + descriptor.valueParameters.map { TypeUtils.makeNotNullable(it.original.type) } - val argsValues = frame.getAll() - .map { it as? Primitive<*> ?: throw IllegalArgumentException("Builtin functions accept only const args") } - .map { it.getIrConst().value } - val signature = CompileTimeFunction(methodName, argsType.map { it.toString() }) - return when (argsType.size) { - 1 -> { - val function = unaryFunctions[signature] - ?: throw NoSuchMethodException("For given function $signature there is no entry in unary map") - function.invoke(argsValues.first()) - } - 2 -> { - val function = binaryFunctions[signature] - ?: throw NoSuchMethodException("For given function $signature there is no entry in binary map") - function.invoke(argsValues[1], argsValues[0]) - } - else -> throw UnsupportedOperationException("Unsupported number of arguments") - } - } override fun visitElement(element: IrElement, data: Frame): State { return when (element) { @@ -108,7 +47,7 @@ class IrInterpreter : IrElementVisitor { } override fun visitCall(expression: IrCall, data: Frame): State { - val newFrame = InterpreterFrame(expression.convertValueParameters(data)) + val newFrame = InterpreterFrame(convertValueParameters(expression, data)) if (expression.symbol.owner.isFakeOverride) { expression.dispatchReceiver?.accept(this, data)?.let { newFrame.addVar(it) } return calculateOverridden(expression.symbol, newFrame) @@ -132,7 +71,7 @@ class IrInterpreter : IrElementVisitor { } private fun visitConstructor(constructor: IrFunctionAccessExpression, data: Frame): State { - val newFrame = InterpreterFrame(constructor.convertValueParameters(data)) + val newFrame = InterpreterFrame(convertValueParameters(constructor, data)) val obj = Complex((constructor.symbol.descriptor.containingDeclaration as ClassDescriptor).thisAsReceiverParameter, mutableListOf()) constructor.getBody()?.statements?.forEach { when (it) { diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/Utils.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/Utils.kt index 709ab08b206..63ccf86b97e 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/Utils.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/Utils.kt @@ -5,12 +5,68 @@ package org.jetbrains.kotlin.backend.common.interpreter +import org.jetbrains.kotlin.backend.common.interpreter.builtins.CompileTimeFunction +import org.jetbrains.kotlin.backend.common.interpreter.builtins.binaryFunctions +import org.jetbrains.kotlin.backend.common.interpreter.builtins.unaryFunctions +import org.jetbrains.kotlin.backend.common.interpreter.stack.Frame +import org.jetbrains.kotlin.backend.common.interpreter.stack.InterpreterFrame import org.jetbrains.kotlin.backend.common.interpreter.stack.Primitive +import org.jetbrains.kotlin.backend.common.interpreter.stack.State import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor +import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.types.TypeUtils + +fun IrInterpreter.calculateOverridden(symbol: IrFunctionSymbol, data: Frame): State { + val owner = symbol.owner as IrFunctionImpl + val overridden = owner.overriddenSymbols.first() + val overriddenReceiver = data.getVar(symbol.getThisAsReceiver()).getState(overridden.getThisAsReceiver()) + val valueParameters = symbol.owner.valueParameters.zip(overridden.owner.valueParameters) + .map { data.getVar(it.first.descriptor).setDescriptor(it.second.descriptor) } + val newStates = InterpreterFrame((valueParameters + overriddenReceiver).toMutableList()) + + return if (overridden.owner.body != null) { + overridden.owner.body!!.accept(this, newStates) + } else { + calculateOverridden(overridden.owner.symbol, newStates) + } +} + +fun calculateBuiltIns(descriptor: FunctionDescriptor, frame: Frame): Any { + val methodName = descriptor.name.asString() + val receiverType = descriptor.dispatchReceiverParameter?.type ?: descriptor.extensionReceiverParameter?.type + val argsType = listOfNotNull(receiverType) + descriptor.valueParameters.map { TypeUtils.makeNotNullable(it.original.type) } + val argsValues = frame.getAll() + .map { it as? Primitive<*> ?: throw IllegalArgumentException("Builtin functions accept only const args") } + .map { it.getIrConst().value } + val signature = CompileTimeFunction(methodName, argsType.map { it.toString() }) + return when (argsType.size) { + 1 -> { + val function = unaryFunctions[signature] + ?: throw NoSuchMethodException("For given function $signature there is no entry in unary map") + function.invoke(argsValues.first()) + } + 2 -> { + val function = binaryFunctions[signature] + ?: throw NoSuchMethodException("For given function $signature there is no entry in binary map") + function.invoke(argsValues[1], argsValues[0]) + } + else -> throw UnsupportedOperationException("Unsupported number of arguments") + } +} + +fun IrInterpreter.convertValueParameters(memberAccess: IrMemberAccessExpression, data: Frame): MutableList { + return mutableListOf().apply { + for (i in 0 until memberAccess.valueArgumentsCount) { + val arg = memberAccess.getValueArgument(i)?.accept(this@convertValueParameters, data) + arg?.setDescriptor((memberAccess.symbol.descriptor as FunctionDescriptor).valueParameters[i])?.let { this += it } + } + } +} fun IrFunctionSymbol.getThisAsReceiver(): ReceiverParameterDescriptor { return (this.descriptor.containingDeclaration as ClassDescriptor).thisAsReceiverParameter