Make state property mutable in Variable class

This change allow to remove copy method from State interface
This commit is contained in:
Ivan Kylchik
2020-06-02 00:09:24 +03:00
parent 848ca70de1
commit ff830cc744
12 changed files with 41 additions and 94 deletions
@@ -59,7 +59,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
is Double -> irBuiltIns.doubleType is Double -> irBuiltIns.doubleType
null -> irBuiltIns.nothingType null -> irBuiltIns.nothingType
else -> when (defaultType.classifierOrNull?.owner) { else -> when (defaultType.classifierOrNull?.owner) {
is IrTypeParameter -> stack.getVariableState(defaultType.classifierOrFail.descriptor).irClass.defaultType is IrTypeParameter -> stack.getVariable(defaultType.classifierOrFail.descriptor).state.irClass.defaultType
else -> defaultType else -> defaultType
} }
} }
@@ -284,7 +284,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
interpretValueParameters(expression, irFunction, valueArguments).check { return it } interpretValueParameters(expression, irFunction, valueArguments).check { return it }
valueArguments.addAll(getTypeArguments(irFunction, expression) { stack.getVariableState(it) }) valueArguments.addAll(getTypeArguments(irFunction, expression) { stack.getVariable(it).state })
if (dispatchReceiver is Complex) valueArguments.addAll(dispatchReceiver.typeArguments) if (dispatchReceiver is Complex) valueArguments.addAll(dispatchReceiver.typeArguments)
if (extensionReceiver is Complex) valueArguments.addAll(extensionReceiver.typeArguments) if (extensionReceiver is Complex) valueArguments.addAll(extensionReceiver.typeArguments)
@@ -331,9 +331,9 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
property.backingField?.initializer?.expression?.interpret()?.check { return it } property.backingField?.initializer?.expression?.interpret()?.check { return it }
val receiver = irClass.descriptor.thisAsReceiverParameter val receiver = irClass.descriptor.thisAsReceiverParameter
if (property.backingField?.initializer != null) { if (property.backingField?.initializer != null) {
val receiverState = stack.getVariableState(receiver) val receiverState = stack.getVariable(receiver).state
val propertyState = Variable(property.backingField!!.descriptor, stack.popReturnValue()) val property = Variable(property.backingField!!.descriptor, stack.popReturnValue())
receiverState.setState(propertyState) receiverState.setField(property)
} }
} }
@@ -351,7 +351,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
interpretValueParameters(constructorCall, owner, valueArguments).check { return it } interpretValueParameters(constructorCall, owner, valueArguments).check { return it }
val irClass = owner.parent as IrClass val irClass = owner.parent as IrClass
val typeArguments = getTypeArguments(irClass, constructorCall) { stack.getVariableState(it) } val typeArguments = getTypeArguments(irClass, constructorCall) { stack.getVariable(it).state }
if (irClass.hasAnnotation(evaluateIntrinsicAnnotation) || irClass.fqNameWhenAvailable!!.startsWith(Name.identifier("java"))) { if (irClass.hasAnnotation(evaluateIntrinsicAnnotation) || irClass.fqNameWhenAvailable!!.startsWith(Name.identifier("java"))) {
return stack.newFrame(initPool = valueArguments) { Wrapper.getConstructorMethod(owner).invokeMethod(owner) } return stack.newFrame(initPool = valueArguments) { Wrapper.getConstructorMethod(owner).invokeMethod(owner) }
.apply { (stack.peekReturnValue() as? Wrapper)?.typeArguments?.addAll(typeArguments) } // 'as?' because can be exception .apply { (stack.peekReturnValue() as? Wrapper)?.typeArguments?.addAll(typeArguments) } // 'as?' because can be exception
@@ -502,14 +502,14 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
// receiver is null only for top level var, but it cannot be used in constexpr; corresponding check is on frontend // receiver is null only for top level var, but it cannot be used in constexpr; corresponding check is on frontend
val receiver = (expression.receiver as IrDeclarationReference).symbol.descriptor val receiver = (expression.receiver as IrDeclarationReference).symbol.descriptor
stack.getVariableState(receiver).setState(Variable(expression.symbol.owner.descriptor, stack.popReturnValue())) stack.getVariable(receiver).apply { this.state.setField(Variable(expression.symbol.owner.descriptor, stack.popReturnValue())) }
return Next return Next
} }
private suspend fun interpretGetField(expression: IrGetField): ExecutionResult { private suspend fun interpretGetField(expression: IrGetField): ExecutionResult {
val receiver = (expression.receiver as? IrDeclarationReference)?.symbol?.descriptor val receiver = (expression.receiver as? IrDeclarationReference)?.symbol?.descriptor
// receiver is null, for example, for top level fields // receiver is null, for example, for top level fields
val result = receiver?.let { stack.getVariableState(receiver).getState(expression.symbol.descriptor)?.copy() } val result = receiver?.let { stack.getVariable(receiver).state.getState(expression.symbol.descriptor) }
?: return (expression.symbol.owner.initializer?.expression?.interpret() ?: Next) ?: return (expression.symbol.owner.initializer?.expression?.interpret() ?: Next)
stack.pushReturnValue(result) stack.pushReturnValue(result)
return Next return Next
@@ -519,7 +519,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
val owner = expression.type.classOrNull?.owner val owner = expression.type.classOrNull?.owner
// used to evaluate constants inside object // used to evaluate constants inside object
if (owner != null && owner.isObject) return getOrCreateObjectValue(owner) // TODO is this correct behaviour? if (owner != null && owner.isObject) return getOrCreateObjectValue(owner) // TODO is this correct behaviour?
stack.pushReturnValue(stack.getVariableState(expression.symbol.descriptor).copy()) stack.pushReturnValue(stack.getVariable(expression.symbol.descriptor).state)
return Next return Next
} }
@@ -533,8 +533,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
expression.value.interpret().check { return it } expression.value.interpret().check { return it }
if (stack.contains(expression.symbol.descriptor)) { if (stack.contains(expression.symbol.descriptor)) {
val variable = stack.getVariableState(expression.symbol.descriptor) stack.getVariable(expression.symbol.descriptor).apply { this.state = stack.popReturnValue() }
variable.setState(Variable(expression.symbol.descriptor, stack.popReturnValue()))
} else { } else {
stack.addVar(Variable(expression.symbol.descriptor, stack.popReturnValue())) stack.addVar(Variable(expression.symbol.descriptor, stack.popReturnValue()))
} }
@@ -600,7 +599,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map<IdSigna
private suspend fun interpretTypeOperatorCall(expression: IrTypeOperatorCall): ExecutionResult { private suspend fun interpretTypeOperatorCall(expression: IrTypeOperatorCall): ExecutionResult {
val executionResult = expression.argument.interpret().check { return it } val executionResult = expression.argument.interpret().check { return it }
val typeOperandDescriptor = expression.typeOperand.classifierOrFail.descriptor val typeOperandDescriptor = expression.typeOperand.classifierOrFail.descriptor
val typeOperandClass = expression.typeOperand.classOrNull?.owner ?: stack.getVariableState(typeOperandDescriptor).irClass val typeOperandClass = expression.typeOperand.classOrNull?.owner ?: stack.getVariable(typeOperandDescriptor).state.irClass
when (expression.operator) { when (expression.operator) {
// coercion to unit means that return value isn't used // coercion to unit means that return value isn't used
@@ -60,7 +60,7 @@ object ArrayOfNulls : IntrinsicBase() {
override suspend fun evaluate( override suspend fun evaluate(
irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult
): ExecutionResult { ): ExecutionResult {
val size = stack.getVariableState(irFunction.valueParameters.first().descriptor).asInt() val size = stack.getVariable(irFunction.valueParameters.first().descriptor).state.asInt()
val array = arrayOfNulls<Any?>(size) val array = arrayOfNulls<Any?>(size)
stack.pushReturnValue(array.toState(irFunction.returnType)) stack.pushReturnValue(array.toState(irFunction.returnType))
return Next return Next
@@ -77,7 +77,7 @@ object EnumValues : IntrinsicBase() {
irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult
): ExecutionResult { ): ExecutionResult {
val enumClass = when (irFunction.fqNameWhenAvailable.toString()) { val enumClass = when (irFunction.fqNameWhenAvailable.toString()) {
"kotlin.enumValues" -> stack.getVariableState(irFunction.typeParameters.first().descriptor).irClass "kotlin.enumValues" -> stack.getVariable(irFunction.typeParameters.first().descriptor).state.irClass
else -> irFunction.parent as IrClass else -> irFunction.parent as IrClass
} }
@@ -98,10 +98,10 @@ object EnumValueOf : IntrinsicBase() {
irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult
): ExecutionResult { ): ExecutionResult {
val enumClass = when (irFunction.fqNameWhenAvailable.toString()) { val enumClass = when (irFunction.fqNameWhenAvailable.toString()) {
"kotlin.enumValueOf" -> stack.getVariableState(irFunction.typeParameters.first().descriptor).irClass "kotlin.enumValueOf" -> stack.getVariable(irFunction.typeParameters.first().descriptor).state.irClass
else -> irFunction.parent as IrClass else -> irFunction.parent as IrClass
} }
val enumEntryName = stack.getVariableState(irFunction.valueParameters.first().descriptor).asString() val enumEntryName = stack.getVariable(irFunction.valueParameters.first().descriptor).state.asString()
val enumEntry = enumClass.declarations.filterIsInstance<IrEnumEntry>().singleOrNull { it.name.asString() == enumEntryName } val enumEntry = enumClass.declarations.filterIsInstance<IrEnumEntry>().singleOrNull { it.name.asString() == enumEntryName }
enumEntry?.interpret()?.check { return it } enumEntry?.interpret()?.check { return it }
?: throw IllegalArgumentException("No enum constant ${enumClass.fqNameWhenAvailable}.$enumEntryName") ?: throw IllegalArgumentException("No enum constant ${enumClass.fqNameWhenAvailable}.$enumEntryName")
@@ -160,12 +160,12 @@ object JsPrimitives : IntrinsicBase() {
): ExecutionResult { ): ExecutionResult {
when (irFunction.fqNameWhenAvailable.toString()) { when (irFunction.fqNameWhenAvailable.toString()) {
"kotlin.Long.<init>" -> { "kotlin.Long.<init>" -> {
val low = stack.getVariableState(irFunction.valueParameters[0].descriptor).asInt() val low = stack.getVariable(irFunction.valueParameters[0].descriptor).state.asInt()
val high = stack.getVariableState(irFunction.valueParameters[1].descriptor).asInt() val high = stack.getVariable(irFunction.valueParameters[1].descriptor).state.asInt()
stack.pushReturnValue((high.toLong().shl(32) + low).toState(irFunction.returnType)) stack.pushReturnValue((high.toLong().shl(32) + low).toState(irFunction.returnType))
} }
"kotlin.Char.<init>" -> { "kotlin.Char.<init>" -> {
val value = stack.getVariableState(irFunction.valueParameters[0].descriptor).asInt() val value = stack.getVariable(irFunction.valueParameters[0].descriptor).state.asInt()
stack.pushReturnValue(value.toChar().toState(irFunction.returnType)) stack.pushReturnValue(value.toChar().toState(irFunction.returnType))
} }
} }
@@ -183,12 +183,12 @@ object ArrayConstructor : IntrinsicBase() {
irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult
): ExecutionResult { ): ExecutionResult {
val sizeDescriptor = irFunction.valueParameters[0].descriptor val sizeDescriptor = irFunction.valueParameters[0].descriptor
val size = stack.getVariableState(sizeDescriptor).asInt() val size = stack.getVariable(sizeDescriptor).state.asInt()
val arrayValue = MutableList<Any>(size) { 0 } val arrayValue = MutableList<Any>(size) { 0 }
if (irFunction.valueParameters.size == 2) { if (irFunction.valueParameters.size == 2) {
val initDescriptor = irFunction.valueParameters[1].descriptor val initDescriptor = irFunction.valueParameters[1].descriptor
val initLambda = stack.getVariableState(initDescriptor) as Lambda val initLambda = stack.getVariable(initDescriptor).state as Lambda
val index = initLambda.irFunction.valueParameters.single() val index = initLambda.irFunction.valueParameters.single()
for (i in 0 until size) { for (i in 0 until size) {
val indexVar = listOf(Variable(index.descriptor, i.toState(index.type))) val indexVar = listOf(Variable(index.descriptor, i.toState(index.type)))
@@ -14,8 +14,7 @@ import kotlin.NoSuchElementException
interface Frame { interface Frame {
fun addVar(variable: Variable) fun addVar(variable: Variable)
fun addAll(variables: List<Variable>) fun addAll(variables: List<Variable>)
fun getVariableState(variableDescriptor: DeclarationDescriptor): State fun getVariable(variableDescriptor: DeclarationDescriptor): Variable?
fun tryGetVariableState(variableDescriptor: DeclarationDescriptor): State?
fun getAll(): List<Variable> fun getAll(): List<Variable>
fun contains(descriptor: DeclarationDescriptor): Boolean fun contains(descriptor: DeclarationDescriptor): Boolean
fun pushReturnValue(state: State) fun pushReturnValue(state: State)
@@ -40,14 +39,9 @@ class InterpreterFrame(
pool.addAll(variables) pool.addAll(variables)
} }
override fun tryGetVariableState(variableDescriptor: DeclarationDescriptor): State? { override fun getVariable(variableDescriptor: DeclarationDescriptor): Variable? {
return (if (variableDescriptor is TypeParameterDescriptor) typeArguments else pool) return (if (variableDescriptor is TypeParameterDescriptor) typeArguments else pool)
.firstOrNull { it.descriptor.equalTo(variableDescriptor) }?.state .firstOrNull { it.descriptor.equalTo(variableDescriptor) }
}
override fun getVariableState(variableDescriptor: DeclarationDescriptor): State {
return tryGetVariableState(variableDescriptor)
?: throw NoSuchElementException("Frame pool doesn't contains variable with descriptor $variableDescriptor")
} }
override fun getAll(): List<Variable> { override fun getAll(): List<Variable> {
@@ -28,7 +28,7 @@ interface Stack {
fun clean() fun clean()
fun addVar(variable: Variable) fun addVar(variable: Variable)
fun addAll(variables: List<Variable>) fun addAll(variables: List<Variable>)
fun getVariableState(variableDescriptor: DeclarationDescriptor): State fun getVariable(variableDescriptor: DeclarationDescriptor): Variable
fun getAll(): List<Variable> fun getAll(): List<Variable>
fun contains(descriptor: DeclarationDescriptor): Boolean fun contains(descriptor: DeclarationDescriptor): Boolean
@@ -86,8 +86,8 @@ class StackImpl : Stack {
getCurrentFrame().addAll(variables) getCurrentFrame().addAll(variables)
} }
override fun getVariableState(variableDescriptor: DeclarationDescriptor): State { override fun getVariable(variableDescriptor: DeclarationDescriptor): Variable {
return getCurrentFrame().getVariableState(variableDescriptor) return getCurrentFrame().getVariable(variableDescriptor)
} }
override fun getAll(): List<Variable> { override fun getAll(): List<Variable> {
@@ -132,8 +132,8 @@ private class FrameContainer(current: Frame = InterpreterFrame()) {
fun addVar(variable: Variable) = getTopFrame().addVar(variable) fun addVar(variable: Variable) = getTopFrame().addVar(variable)
fun addAll(variables: List<Variable>) = getTopFrame().addAll(variables) fun addAll(variables: List<Variable>) = getTopFrame().addAll(variables)
fun getAll() = innerStack.flatMap { it.getAll() } fun getAll() = innerStack.flatMap { it.getAll() }
fun getVariableState(variableDescriptor: DeclarationDescriptor): State { fun getVariable(variableDescriptor: DeclarationDescriptor): Variable {
return innerStack.firstNotNullResult { it.tryGetVariableState(variableDescriptor) } return innerStack.firstNotNullResult { it.getVariable(variableDescriptor) }
?: throw InterpreterException("$variableDescriptor not found") // TODO better message ?: throw InterpreterException("$variableDescriptor not found") // TODO better message
} }
@@ -9,7 +9,7 @@ import org.jetbrains.kotlin.backend.common.interpreter.state.State
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
data class Variable(val descriptor: DeclarationDescriptor, val state: State) { data class Variable(val descriptor: DeclarationDescriptor, var state: State) {
override fun toString(): String { override fun toString(): String {
val descriptorName = when (descriptor) { val descriptorName = when (descriptor) {
is ReceiverParameterDescriptor -> descriptor.containingDeclaration.name.toString() + "::this" is ReceiverParameterDescriptor -> descriptor.containingDeclaration.name.toString() + "::this"
@@ -48,8 +48,6 @@ class Common private constructor(
.let { getOverridden(it as IrSimpleFunction, this) } .let { getOverridden(it as IrSimpleFunction, this) }
} }
override fun copy() = Common(irClass, fields).copyFrom(this)
override fun toString(): String { override fun toString(): String {
return "Common(obj='${irClass.fqNameForIrSerialization}', super=$superClass, values=$fields)" return "Common(obj='${irClass.fqNameForIrSerialization}', super=$superClass, values=$fields)"
} }
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.ir.util.isInterface
abstract class Complex(override val irClass: IrClass, override val fields: MutableList<Variable>) : State { abstract class Complex(override val irClass: IrClass, override val fields: MutableList<Variable>) : State {
var superClass: Complex? = null var superClass: Complex? = null
var subClass: Complex? = null var subClass: Complex? = null
val interfaces: MutableList<Complex> = mutableListOf() // filled lazily, as needed
val typeArguments: MutableList<Variable> = mutableListOf() val typeArguments: MutableList<Variable> = mutableListOf()
var outerClass: Variable? = null var outerClass: Variable? = null
@@ -46,21 +47,6 @@ abstract class Complex(override val irClass: IrClass, override val fields: Mutab
private fun contains(variable: Variable) = fields.any { it.descriptor == variable.descriptor } 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
else -> fields[fields.indexOf(oldState)] = newVar // newVar already present
}
}
protected fun copyFrom(other: Complex): State {
this.superClass = other.superClass
this.subClass = other.subClass ?: other
this.typeArguments.addAll(other.typeArguments)
this.outerClass = other.outerClass
return this
}
private fun getIrFunction(descriptor: FunctionDescriptor): IrFunction? { private 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>()
@@ -70,10 +56,9 @@ abstract class Complex(override val irClass: IrClass, override val fields: Mutab
private fun getThisOrSuperReceiver(superIrClass: IrClass?): Complex? { private fun getThisOrSuperReceiver(superIrClass: IrClass?): Complex? {
return when { return when {
superIrClass == null -> this.getOriginal() superIrClass == null -> this.getOriginal()
superIrClass.isInterface -> { superIrClass.isInterface -> Common(superIrClass).apply {
val interfaceState = Common(superIrClass) interfaces.add(this)
(this.copy() as Complex).setSuperClassInstance(interfaceState) this.subClass = this@Complex
interfaceState
} }
else -> this.superClass else -> this.superClass
} }
@@ -80,11 +80,11 @@ class ExceptionState private constructor(
} }
private fun setMessage(messageValue: String? = null) { private fun setMessage(messageValue: String? = null) {
setState(Variable(messageProperty.descriptor, Primitive(messageValue, messageProperty.getter!!.returnType))) setField(Variable(messageProperty.descriptor, Primitive(messageValue, messageProperty.getter!!.returnType)))
} }
private fun setCause(causeValue: State?) { private fun setCause(causeValue: State?) {
setState(Variable(causeProperty.descriptor, causeValue ?: Primitive<Throwable?>(null, causeProperty.getter!!.returnType))) setField(Variable(causeProperty.descriptor, causeValue ?: Primitive<Throwable?>(null, causeProperty.getter!!.returnType)))
} }
fun getMessage(): Primitive<String?> = getState(messageProperty.descriptor) as Primitive<String?> fun getMessage(): Primitive<String?> = getState(messageProperty.descriptor) as Primitive<String?>
@@ -105,8 +105,6 @@ class ExceptionState private constructor(
fun getThisAsCauseForException() = ExceptionData(this) fun getThisAsCauseForException() = ExceptionData(this)
override fun copy() = ExceptionState(irClass, fields, stackTrace).copyFrom(this)
companion object { companion object {
private fun IrClass.getPropertyByName(name: String): IrProperty { private fun IrClass.getPropertyByName(name: String): IrProperty {
val getPropertyFun = this.declarations.firstOrNull { it.nameForIrSerialization.asString().contains("get-$name") } val getPropertyFun = this.declarations.firstOrNull { it.nameForIrSerialization.asString().contains("get-$name") }
@@ -19,18 +19,10 @@ class Lambda(val irFunction: IrFunction, override val irClass: IrClass) : State
// irFunction is anonymous declaration, but irCall will contain descriptor of invoke method from Function interface // irFunction is anonymous declaration, but irCall will contain descriptor of invoke method from Function interface
private val invokeDescriptor = irClass.declarations.single { it.nameForIrSerialization.asString() == "invoke" }.descriptor private val invokeDescriptor = irClass.declarations.single { it.nameForIrSerialization.asString() == "invoke" }.descriptor
override fun setState(newVar: Variable) {
throw UnsupportedOperationException("Method setState is not supported in Lambda class")
}
override fun getIrFunctionByIrCall(expression: IrCall): IrFunction? { override fun getIrFunctionByIrCall(expression: IrCall): IrFunction? {
return if (invokeDescriptor.equalTo(expression.symbol.descriptor)) irFunction else null return if (invokeDescriptor.equalTo(expression.symbol.descriptor)) irFunction else null
} }
override fun copy(): State {
return Lambda(irFunction, irClass).apply { this.fields.addAll(this@Lambda.fields) }
}
override fun toString(): String { override fun toString(): String {
val receiver = (irFunction.dispatchReceiverParameter?.type ?: irFunction.extensionReceiverParameter?.type)?.getFqName(true) val receiver = (irFunction.dispatchReceiverParameter?.type ?: irFunction.extensionReceiverParameter?.type)?.getFqName(true)
val arguments = irFunction.valueParameters.map { it.type.getFqName(true) }.joinToString(prefix = "(", postfix = ")") val arguments = irFunction.valueParameters.map { it.type.getFqName(true) }.joinToString(prefix = "(", postfix = ")")
@@ -24,15 +24,6 @@ class Primitive<T>(var value: T, val type: IrType) : State {
return super.getState(descriptor) ?: this return super.getState(descriptor) ?: this
} }
override fun setState(newVar: Variable) {
newVar.state as? Primitive<T> ?: throw IllegalArgumentException("Cannot set $newVar in current $this")
value = newVar.state.value
}
override fun copy(): State {
return Primitive(value, type)
}
override fun getIrFunctionByIrCall(expression: IrCall): IrFunction? { override fun getIrFunctionByIrCall(expression: IrCall): IrFunction? {
val descriptor = expression.symbol.descriptor val descriptor = expression.symbol.descriptor
// must add property's getter to declaration's list because they are not present in ir class for primitives // must add property's getter to declaration's list because they are not present in ir class for primitives
@@ -20,16 +20,12 @@ interface State {
return fields.firstOrNull { it.descriptor.equalTo(descriptor) }?.state return fields.firstOrNull { it.descriptor.equalTo(descriptor) }?.state
} }
fun setState(newVar: Variable) fun setField(newVar: Variable) {
when (val oldState = fields.firstOrNull { it.descriptor == newVar.descriptor }) {
/** null -> fields.add(newVar) // newVar isn't present in value list
* This method is used for passing a copy of a state. else -> fields[fields.indexOf(oldState)].state = newVar.state // newVar already present
* It is necessary then copy change its state's value, but the original one must remain the same. }
* }
* @see copyReceivedValue.kt
* @see tryFinally.kt
*/
fun copy(): State
fun getIrFunctionByIrCall(expression: IrCall): IrFunction? fun getIrFunctionByIrCall(expression: IrCall): IrFunction?
} }
@@ -52,10 +52,6 @@ class Wrapper(val value: Any, override val irClass: IrClass) : Complex(irClass,
return MethodHandles.lookup().findVirtual(receiverClass, methodName, methodType) return MethodHandles.lookup().findVirtual(receiverClass, methodName, methodType)
} }
override fun setState(newVar: Variable) {
throw UnsupportedOperationException("Method setState is not supported in Wrapper class")
}
// this method is used to get correct java method name // this method is used to get correct java method name
// for example: - method 'get' in kotlin StringBuilder is actually 'charAt' in java StringBuilder // for example: - method 'get' in kotlin StringBuilder is actually 'charAt' in java StringBuilder
// - method 'keys' in kotlin Map is actually 'keySet' in java // - method 'keys' in kotlin Map is actually 'keySet' in java
@@ -194,8 +190,6 @@ class Wrapper(val value: Any, override val irClass: IrClass) : Complex(irClass,
} }
} }
override fun copy() = Wrapper(value, irClass).copyFrom(this)
override fun toString(): String { override fun toString(): String {
return "Wrapper(obj='$typeFqName', value=$value)" return "Wrapper(obj='$typeFqName', value=$value)"
} }