Change interpretConstructor method to be able to init object single time

This commit is contained in:
Ivan Kylchik
2020-09-09 01:07:34 +03:00
committed by TeamCityServer
parent 903e883809
commit 8b2706aaee
3 changed files with 54 additions and 15 deletions
@@ -393,8 +393,14 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
return Next
}
val state = Common(irClass).apply { this.addTypeArguments(typeArguments) }
if (irClass.isLocal) state.fields.addAll(stack.getAll()) // TODO save only necessary declarations
val state = stack.getVariable(constructorCall.getThisReceiver()).state as Common
state.addTypeArguments(typeArguments)
if (irClass.isLocal) {
state.fields.addAll(stack.getAll()) // TODO save only necessary declarations
valueArguments.addAll(stack.getAll())
}
if (irClass.isInner) {
constructorCall.dispatchReceiver!!.interpret().check { return it }
state.outerClass = Variable(irClass.parentAsClass.thisReceiver!!.symbol, stack.popReturnValue())
@@ -403,25 +409,44 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
// used to get information from outer class
valueArguments.add(state.outerClass!!)
}
valueArguments.add(Variable(irClass.thisReceiver!!.symbol, state)) //used to set up fields in body
valueArguments.add(Variable(constructorCall.getThisReceiver(), state)) //used to set up fields in body
return stack.newFrame(initPool = valueArguments + state.typeArguments) {
val statements = constructorCall.getBody()!!.statements
// 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 }
when (val irStatement = statements[0]) {
is IrTypeOperatorCall -> {
// enum entry use IrTypeOperatorCall with IMPLICIT_COERCION_TO_UNIT as delegation call, but we need the value
stack.addVar(Variable((irStatement.argument as IrFunctionAccessExpression).getThisReceiver(), state))
irStatement.argument.interpret().check { return@newFrame it }
}
is IrFunctionAccessExpression -> {
stack.addVar(Variable(irStatement.getThisReceiver(), state))
irStatement.interpret().check { return@newFrame it }
}
is IrBlock -> {
stack.addVar(Variable((irStatement.statements.last() as IrFunctionAccessExpression).getThisReceiver(), state))
irStatement.interpret().check { return@newFrame it }
}
else -> TODO("${irStatement::class.java} is not supported as first statement in constructor call")
}
val returnedState = stack.popReturnValue() as Complex
for (i in 1 until statements.size) statements[i].interpret().check { return@newFrame it }
stack.pushReturnValue(state.apply { this.copyFieldsFrom(returnedState) })
state.superWrapperClass = returnedState.superWrapperClass ?: returnedState as? Wrapper
stack.pushReturnValue(state)
Next
}
}
private fun interpretConstructorCall(constructorCall: IrConstructorCall): ExecutionResult {
return interpretConstructor(constructorCall)
val irClass = constructorCall.symbol.owner.parentAsClass
val classState = Variable(constructorCall.getThisReceiver(), Common(irClass))
return stack.newFrame(asSubFrame = true, initPool = listOf(classState)) { interpretConstructor(constructorCall) }
}
private fun interpretEnumConstructorCall(enumConstructorCall: IrEnumConstructorCall): ExecutionResult {
// interpretConstructorCall logic is implemented in interpretEnumEntry
return interpretConstructor(enumConstructorCall)
}
@@ -605,12 +630,19 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
private fun getOrCreateObjectValue(objectClass: IrClass): ExecutionResult {
mapOfObjects[objectClass.symbol]?.let { return Next.apply { stack.pushReturnValue(it) } }
val objectState = when {
objectClass.hasAnnotation(evaluateIntrinsicAnnotation) -> Wrapper.getCompanionObject(objectClass)
else -> Common(objectClass) // TODO test type arguments
when {
objectClass.hasAnnotation(evaluateIntrinsicAnnotation) -> mapOfObjects[objectClass.symbol] = Wrapper.getCompanionObject(objectClass)
else -> {
val state = Common(objectClass)
mapOfObjects[objectClass.symbol] = state // TODO test type arguments
val variable = Variable(objectClass.thisReceiver!!.symbol, state)
val constructor = objectClass.constructors.first()
val constructorCall = IrConstructorCallImpl.fromSymbolOwner(constructor.returnType, constructor.symbol)
stack.newFrame(asSubFrame = true, initPool = listOf(variable)) { interpretConstructor(constructorCall) }.check { return it }
}
}
mapOfObjects[objectClass.symbol] = objectState
stack.pushReturnValue(objectState)
stack.pushReturnValue(mapOfObjects[objectClass.symbol]!!)
return Next
}
@@ -649,9 +681,14 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
valueArguments.forEachIndexed { index, irConst -> enumSuperCall.putValueArgument(index, irConst) }
}
val executionResult = enumEntry.initializerExpression?.interpret()?.check { return it }
val enumConstructorCall = enumEntry.initializerExpression?.expression as? IrEnumConstructorCall
?: throw InterpreterError("Initializer at enum entry ${enumEntry.fqNameWhenAvailable} is null")
val enumClassState = Variable(enumConstructorCall.getThisReceiver(), Common(enumEntry.correspondingClass ?: enumClass))
val executionResult = stack.newFrame(asSubFrame = true, initPool = listOf(enumClassState)) {
enumConstructorCall.interpret()
}
enumSuperCall?.apply { (0 until this.valueArgumentsCount).forEach { putValueArgument(it, null) } } // restore to null
return executionResult ?: throw InterpreterError("Initializer at enum entry ${enumEntry.fqNameWhenAvailable} is null")
return executionResult
}
private fun interpretTypeOperatorCall(expression: IrTypeOperatorCall): ExecutionResult {
@@ -36,6 +36,8 @@ internal fun IrFunction.getReceiver(): IrSymbol? = this.getDispatchReceiver() ?:
internal fun IrFunctionAccessExpression.getBody(): IrBody? = this.symbol.owner.body
internal fun IrFunctionAccessExpression.getThisReceiver(): IrValueSymbol = this.symbol.owner.parentAsClass.thisReceiver!!.symbol
internal fun State.toIrExpression(expression: IrExpression): IrExpression {
val start = expression.startOffset
val end = expression.endOffset
@@ -53,7 +53,7 @@ internal interface Complex: State {
if (owner.parent == superWrapperClass?.irClass) return owner
if (!owner.isFakeOverride || owner.body != null || owner.parentAsClass.defaultType.isAny()) return owner
val overriddenOwner = owner.overriddenSymbols.singleOrNull { !it.owner.parentAsClass.isInterface }?.owner
val overriddenOwner = owner.overriddenSymbols.let { it.singleOrNull { it.owner.body != null } ?: it.singleOrNull() }?.owner
return overriddenOwner?.let { getOverridden(it) } ?: owner.getLastOverridden() as IrSimpleFunction
}