Change interpretConstructor method to be able to init object single time
This commit is contained in:
committed by
TeamCityServer
parent
903e883809
commit
8b2706aaee
+51
-14
@@ -393,8 +393,14 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
|
|||||||
return Next
|
return Next
|
||||||
}
|
}
|
||||||
|
|
||||||
val state = Common(irClass).apply { this.addTypeArguments(typeArguments) }
|
val state = stack.getVariable(constructorCall.getThisReceiver()).state as Common
|
||||||
if (irClass.isLocal) state.fields.addAll(stack.getAll()) // TODO save only necessary declarations
|
state.addTypeArguments(typeArguments)
|
||||||
|
|
||||||
|
if (irClass.isLocal) {
|
||||||
|
state.fields.addAll(stack.getAll()) // TODO save only necessary declarations
|
||||||
|
valueArguments.addAll(stack.getAll())
|
||||||
|
}
|
||||||
|
|
||||||
if (irClass.isInner) {
|
if (irClass.isInner) {
|
||||||
constructorCall.dispatchReceiver!!.interpret().check { return it }
|
constructorCall.dispatchReceiver!!.interpret().check { return it }
|
||||||
state.outerClass = Variable(irClass.parentAsClass.thisReceiver!!.symbol, stack.popReturnValue())
|
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
|
// used to get information from outer class
|
||||||
valueArguments.add(state.outerClass!!)
|
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) {
|
return stack.newFrame(initPool = valueArguments + state.typeArguments) {
|
||||||
val statements = constructorCall.getBody()!!.statements
|
val statements = constructorCall.getBody()!!.statements
|
||||||
// enum entry use IrTypeOperatorCall with IMPLICIT_COERCION_TO_UNIT as delegation call, but we need the value
|
when (val irStatement = statements[0]) {
|
||||||
((statements[0] as? IrTypeOperatorCall)?.argument ?: statements[0]).interpret().check { return@newFrame it }
|
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
|
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 }
|
||||||
|
|
||||||
stack.pushReturnValue(state.apply { this.copyFieldsFrom(returnedState) })
|
state.superWrapperClass = returnedState.superWrapperClass ?: returnedState as? Wrapper
|
||||||
|
stack.pushReturnValue(state)
|
||||||
Next
|
Next
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun interpretConstructorCall(constructorCall: IrConstructorCall): ExecutionResult {
|
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 {
|
private fun interpretEnumConstructorCall(enumConstructorCall: IrEnumConstructorCall): ExecutionResult {
|
||||||
|
// interpretConstructorCall logic is implemented in interpretEnumEntry
|
||||||
return interpretConstructor(enumConstructorCall)
|
return interpretConstructor(enumConstructorCall)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -605,12 +630,19 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
|
|||||||
private fun getOrCreateObjectValue(objectClass: IrClass): ExecutionResult {
|
private fun getOrCreateObjectValue(objectClass: IrClass): ExecutionResult {
|
||||||
mapOfObjects[objectClass.symbol]?.let { return Next.apply { stack.pushReturnValue(it) } }
|
mapOfObjects[objectClass.symbol]?.let { return Next.apply { stack.pushReturnValue(it) } }
|
||||||
|
|
||||||
val objectState = when {
|
when {
|
||||||
objectClass.hasAnnotation(evaluateIntrinsicAnnotation) -> Wrapper.getCompanionObject(objectClass)
|
objectClass.hasAnnotation(evaluateIntrinsicAnnotation) -> mapOfObjects[objectClass.symbol] = Wrapper.getCompanionObject(objectClass)
|
||||||
else -> Common(objectClass) // TODO test type arguments
|
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(mapOfObjects[objectClass.symbol]!!)
|
||||||
stack.pushReturnValue(objectState)
|
|
||||||
return Next
|
return Next
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -649,9 +681,14 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
|
|||||||
valueArguments.forEachIndexed { index, irConst -> enumSuperCall.putValueArgument(index, irConst) }
|
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
|
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 {
|
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.getBody(): IrBody? = this.symbol.owner.body
|
||||||
|
|
||||||
|
internal fun IrFunctionAccessExpression.getThisReceiver(): IrValueSymbol = this.symbol.owner.parentAsClass.thisReceiver!!.symbol
|
||||||
|
|
||||||
internal fun State.toIrExpression(expression: IrExpression): IrExpression {
|
internal fun State.toIrExpression(expression: IrExpression): IrExpression {
|
||||||
val start = expression.startOffset
|
val start = expression.startOffset
|
||||||
val end = expression.endOffset
|
val end = expression.endOffset
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ internal interface Complex: State {
|
|||||||
if (owner.parent == superWrapperClass?.irClass) return owner
|
if (owner.parent == superWrapperClass?.irClass) return owner
|
||||||
if (!owner.isFakeOverride || owner.body != null || owner.parentAsClass.defaultType.isAny()) 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
|
return overriddenOwner?.let { getOverridden(it) } ?: owner.getLastOverridden() as IrSimpleFunction
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user