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 6bd19f74e2d..b4af541ccd9 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 @@ -44,14 +44,18 @@ class IrInterpreter : IrElementVisitor { is IrGetField -> visitGetField(element, data) is IrGetValue -> visitGetValue(element, data) is IrConst<*> -> visitConst(element, data) + is IrWhen -> visitWhen(element, data) else -> TODO("${element.javaClass} not supported") } } override fun visitCall(expression: IrCall, data: Frame): State { - val newFrame = InterpreterFrame(convertValueParameters(expression, data)) + val newFrame = InterpreterFrame() // it is important firstly to add receiver, then arguments + val valueParameters = convertValueParameters(expression, data) + if (expression.symbol.owner.isFakeOverride) { expression.dispatchReceiver?.accept(this, data)?.let { newFrame.addVar(it) } + newFrame.addAll(valueParameters) return calculateOverridden(expression.symbol, newFrame) } @@ -60,6 +64,7 @@ class IrInterpreter : IrElementVisitor { val extensionReceiver = expression.extensionReceiver?.accept(this, data) ?.setDescriptor(expression.symbol.descriptor.extensionReceiverParameter!!) (dispatchReceiver ?: extensionReceiver)?.also { newFrame.addVar(it) } + newFrame.addAll(valueParameters) return if (expression.getBody() == null) { calculateBuiltIns(expression.symbol.descriptor, newFrame).toIrConst(expression).toPrimitive() @@ -100,13 +105,14 @@ class IrInterpreter : IrElementVisitor { } private fun visitStatements(statements: List, data: Frame): State { - statements.forEach { - when (it) { - is IrReturn -> return it.accept(this, data) - else -> it.accept(this, data) + statements.forEachIndexed { index, statement -> + when { + statement is IrReturn || index == statements.lastIndex -> return statement.accept(this, data) + else -> statement.accept(this, data) } } + // unreachable state; method must return inside forEach return unit } @@ -147,4 +153,13 @@ class IrInterpreter : IrElementVisitor { } return unit } + + override fun visitWhen(expression: IrWhen, data: Frame): State { + expression.branches.forEach { + if ((it.condition.accept(this, data) as? Primitive<*>)?.getIrConst()?.value == true) { + return it.result.accept(this, data) + } + } + return unit + } } 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 a0c840fd39b..13f2bedaee2 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 @@ -53,7 +53,7 @@ fun calculateBuiltIns(descriptor: FunctionDescriptor, frame: Frame): Any { 2 -> { val function = binaryFunctions[signature] ?: throw NoSuchMethodException("For given function $signature there is no entry in binary map") - function.invoke(argsValues[1], argsValues[0]) + function.invoke(argsValues[0], argsValues[1]) } else -> throw UnsupportedOperationException("Unsupported number of arguments") } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/stack/Frame.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/stack/Frame.kt index b57d3f2a733..ec1b3966c4a 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/stack/Frame.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/stack/Frame.kt @@ -10,6 +10,7 @@ import java.util.NoSuchElementException interface Frame { fun addVar(state: State) + fun addAll(states: List) fun getVar(descriptor: DeclarationDescriptor): State fun getAll(): List fun contains(descriptor: DeclarationDescriptor): Boolean @@ -20,6 +21,10 @@ class InterpreterFrame(val pool: MutableList = mutableListOf()) : Frame { pool.add(state) } + override fun addAll(states: List) { + pool.addAll(states) + } + override fun getVar(descriptor: DeclarationDescriptor): State { return pool.firstOrNull { it.isTypeOf(descriptor) } ?: throw NoSuchElementException("Frame pool doesn't contains variable with descriptor $descriptor")