Make state property mutable in Variable class
This change allow to remove copy method from State interface
This commit is contained in:
+11
-12
@@ -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
|
||||||
|
|||||||
+9
-9
@@ -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)))
|
||||||
|
|||||||
+3
-9
@@ -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> {
|
||||||
|
|||||||
+5
-5
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -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"
|
||||||
|
|||||||
-2
@@ -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)"
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-19
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-4
@@ -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") }
|
||||||
|
|||||||
-8
@@ -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 = ")")
|
||||||
|
|||||||
-9
@@ -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
|
||||||
|
|||||||
+6
-10
@@ -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?
|
||||||
}
|
}
|
||||||
|
|||||||
-6
@@ -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)"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user