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 {
val owner = constructorCall.symbol.owner
val isPrimary = (owner as IrConstructor).isPrimary
val valueArguments = mutableListOf<Variable>()
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
}
}
@@ -17,8 +17,15 @@ abstract class Complex(
override val irClass: IrClass, override val fields: MutableList<Variable>, 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<IrProperty>().mapNotNull { it.getter }
val functions = irClass.declarations.filterIsInstance<IrFunction>()