From e00dc766456b94ad00a388be7c50349c6e2c04da Mon Sep 17 00:00:00 2001 From: Ivan Kylchik Date: Mon, 13 Apr 2020 21:19:32 +0300 Subject: [PATCH] Simplify constructor interpretation Unified case with secondary and primary constructors --- .../common/interpreter/IrInterpreter.kt | 19 ++++++------------- .../common/interpreter/state/Complex.kt | 15 +++++++++++---- 2 files changed, 17 insertions(+), 17 deletions(-) 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 76370b51306..c86461e2e6b 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 @@ -427,7 +427,6 @@ class IrInterpreter(irModule: IrModuleFragment) { private suspend fun interpretConstructor(constructorCall: IrFunctionAccessExpression): ExecutionResult { val owner = constructorCall.symbol.owner - val isPrimary = (owner as IrConstructor).isPrimary val valueArguments = mutableListOf() interpretValueParameters(constructorCall, owner, valueArguments).check { return it } @@ -472,23 +471,17 @@ class IrInterpreter(irModule: IrModuleFragment) { return Next } - val receiverState = Common(parent) - valueArguments.add(Variable(constructorCall.getThisAsReceiver(), receiverState)) //used to set up fields in body + val state = Common(parent) + valueArguments.add(Variable(constructorCall.getThisAsReceiver(), state)) //used to set up fields in body return stack.newFrame(initPool = valueArguments) { val statements = constructorCall.getBody()!!.statements - when (val first = statements[0]) { - // enum entry use IrTypeOperatorCall with IMPLICIT_COERCION_TO_UNIT as delegation call, but we need the value - is IrTypeOperatorCall -> first.argument.interpret().check { return@newFrame it } - else -> first.interpret().check { return@newFrame it } - } + // enum entry use IrTypeOperatorCall with IMPLICIT_COERCION_TO_UNIT as delegation call, but we need the value + ((statements[0] as? IrTypeOperatorCall)?.argument ?: statements[0]).interpret().check { return@newFrame it } val returnedState = stack.popReturnValue() as Complex + for (i in 1 until statements.size) statements[i].interpret().check { return@newFrame it } - val state = - if (isPrimary) receiverState.apply { this.setSuperClassInstance(returnedState) } - else returnedState.apply { setStatesFrom(receiverState) } // if is secondary then only copy all properties from receiver - - stack.pushReturnValue(state) + stack.pushReturnValue(state.apply { this.setSuperClassInstance(returnedState) }) Next } } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/state/Complex.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/state/Complex.kt index b93f69d125f..c7c30699da1 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/state/Complex.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/state/Complex.kt @@ -17,8 +17,15 @@ abstract class Complex( override val irClass: IrClass, override val fields: MutableList, var superClass: Complex?, var subClass: Complex? ) : State { fun setSuperClassInstance(superClass: Complex) { - this.superClass = superClass - superClass.subClass = this + if (this.irClass == superClass.irClass) { + // if superClass is just secondary constructor instance, then copy properties that isn't already present in instance + superClass.fields.forEach { if (!this.contains(it)) fields.add(it) } + this.superClass = superClass.superClass + superClass.superClass?.subClass = this + } else { + this.superClass = superClass + superClass.subClass = this + } } fun getOriginal(): Complex { @@ -29,6 +36,8 @@ abstract class Complex( return irClass.fqNameForIrSerialization.toString() } + private fun contains(variable: Variable) = fields.any { it.descriptor == variable.descriptor } + override fun setState(newVar: Variable) { when (val oldState = fields.firstOrNull { it.descriptor == newVar.descriptor }) { null -> fields.add(newVar) // newVar isn't present in value list @@ -36,8 +45,6 @@ abstract class Complex( } } - fun setStatesFrom(state: Complex) = state.fields.forEach { setState(it) } - override fun getIrFunction(descriptor: FunctionDescriptor): IrFunction? { val propertyGetters = irClass.declarations.filterIsInstance().mapNotNull { it.getter } val functions = irClass.declarations.filterIsInstance()