Simplify constructor interpretation

Unified case with secondary and primary constructors
This commit is contained in:
Ivan Kylchik
2020-04-13 21:19:32 +03:00
parent cf63a5f52b
commit e00dc76645
2 changed files with 17 additions and 17 deletions
@@ -427,7 +427,6 @@ class IrInterpreter(irModule: IrModuleFragment) {
private suspend fun interpretConstructor(constructorCall: IrFunctionAccessExpression): ExecutionResult { private suspend fun interpretConstructor(constructorCall: IrFunctionAccessExpression): ExecutionResult {
val owner = constructorCall.symbol.owner val owner = constructorCall.symbol.owner
val isPrimary = (owner as IrConstructor).isPrimary
val valueArguments = mutableListOf<Variable>() val valueArguments = mutableListOf<Variable>()
interpretValueParameters(constructorCall, owner, valueArguments).check { return it } interpretValueParameters(constructorCall, owner, valueArguments).check { return it }
@@ -472,23 +471,17 @@ class IrInterpreter(irModule: IrModuleFragment) {
return Next return Next
} }
val receiverState = Common(parent) val state = Common(parent)
valueArguments.add(Variable(constructorCall.getThisAsReceiver(), receiverState)) //used to set up fields in body valueArguments.add(Variable(constructorCall.getThisAsReceiver(), state)) //used to set up fields in body
return stack.newFrame(initPool = valueArguments) { return stack.newFrame(initPool = valueArguments) {
val statements = constructorCall.getBody()!!.statements 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
// 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 }
is IrTypeOperatorCall -> first.argument.interpret().check { return@newFrame it }
else -> first.interpret().check { return@newFrame it }
}
val returnedState = stack.popReturnValue() as Complex val returnedState = stack.popReturnValue() as Complex
for (i in 1 until statements.size) statements[i].interpret().check { return@newFrame it } for (i in 1 until statements.size) statements[i].interpret().check { return@newFrame it }
val state = stack.pushReturnValue(state.apply { this.setSuperClassInstance(returnedState) })
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)
Next Next
} }
} }
@@ -17,8 +17,15 @@ abstract class Complex(
override val irClass: IrClass, override val fields: MutableList<Variable>, var superClass: Complex?, var subClass: Complex? override val irClass: IrClass, override val fields: MutableList<Variable>, var superClass: Complex?, var subClass: Complex?
) : State { ) : State {
fun setSuperClassInstance(superClass: Complex) { fun setSuperClassInstance(superClass: Complex) {
this.superClass = superClass if (this.irClass == superClass.irClass) {
superClass.subClass = this // 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 { fun getOriginal(): Complex {
@@ -29,6 +36,8 @@ abstract class Complex(
return irClass.fqNameForIrSerialization.toString() return irClass.fqNameForIrSerialization.toString()
} }
private fun contains(variable: Variable) = fields.any { it.descriptor == variable.descriptor }
override fun setState(newVar: Variable) { override fun setState(newVar: Variable) {
when (val oldState = fields.firstOrNull { it.descriptor == newVar.descriptor }) { when (val oldState = fields.firstOrNull { it.descriptor == newVar.descriptor }) {
null -> fields.add(newVar) // newVar isn't present in value list 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? { override fun getIrFunction(descriptor: FunctionDescriptor): IrFunction? {
val propertyGetters = irClass.declarations.filterIsInstance<IrProperty>().mapNotNull { it.getter } val propertyGetters = irClass.declarations.filterIsInstance<IrProperty>().mapNotNull { it.getter }
val functions = irClass.declarations.filterIsInstance<IrFunction>() val functions = irClass.declarations.filterIsInstance<IrFunction>()