Simplify constructor interpretation
Unified case with secondary and primary constructors
This commit is contained in:
+6
-13
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
+11
-4
@@ -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>()
|
||||
|
||||
Reference in New Issue
Block a user