Add reference to sub class in Complex class
This is replacement for instance field
This commit is contained in:
+12
-17
@@ -268,7 +268,7 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
||||
private suspend fun calculateAbstract(irFunction: IrFunction, data: Frame): Code {
|
||||
if (irFunction.body == null) {
|
||||
val receiver = data.getVariableState(irFunction.symbol.getReceiver()!!) as Complex
|
||||
val instance = receiver.instance!!
|
||||
val instance = receiver.getOriginal()
|
||||
|
||||
val functionImplementation = instance.getIrFunction(irFunction.descriptor)
|
||||
if (functionImplementation?.body == null) throw NoSuchMethodException("Method \"${irFunction.name}\" wasn't implemented")
|
||||
@@ -283,7 +283,7 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
||||
|
||||
private suspend fun calculateOverridden(owner: IrSimpleFunction, data: Frame): Code {
|
||||
val variableDescriptor = owner.symbol.getReceiver()!!
|
||||
val superQualifier = (data.getVariableState(variableDescriptor) as? Complex)?.superType
|
||||
val superQualifier = (data.getVariableState(variableDescriptor) as? Complex)?.superClass
|
||||
if (superQualifier == null) {
|
||||
// superQualifier is null for exception state => find method in builtins
|
||||
return calculateBuiltIns(owner.getLastOverridden() as IrSimpleFunction, data)
|
||||
@@ -298,7 +298,7 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
||||
val overriddenOwner = overridden.owner
|
||||
return when {
|
||||
overriddenOwner.body != null -> overriddenOwner.interpret(newStates)
|
||||
superQualifier.superType == null -> calculateBuiltIns(overriddenOwner, newStates)
|
||||
superQualifier.superClass == null -> calculateBuiltIns(overriddenOwner, newStates)
|
||||
else -> calculateOverridden(overriddenOwner, newStates)
|
||||
}.apply { data.pushReturnValue(newStates) }
|
||||
}
|
||||
@@ -313,7 +313,7 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
||||
|
||||
val receiverType = descriptor.dispatchReceiverParameter?.type ?: descriptor.extensionReceiverParameter?.type
|
||||
val argsType = listOfNotNull(receiverType) + descriptor.valueParameters.map { it.original.type }
|
||||
val argsValues = args.map { (it as? Complex)?.instance ?: (it as Primitive<*>).value }
|
||||
val argsValues = args.map { (it as? Complex)?.getOriginal() ?: (it as Primitive<*>).value }
|
||||
val signature = CompileTimeFunction(methodName, argsType.map { it.toString() })
|
||||
|
||||
val result = when (argsType.size) {
|
||||
@@ -376,7 +376,7 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
||||
val dispatchReceiver = rawDispatchReceiver?.let { data.popReturnValue() }
|
||||
val irFunctionReceiver = when (expression.superQualifierSymbol) {
|
||||
null -> dispatchReceiver
|
||||
else -> (dispatchReceiver as Complex).superType?.takeIf { it.irClass.isSubclassOf(expression.superQualifierSymbol!!.owner) }
|
||||
else -> (dispatchReceiver as Complex).superClass?.takeIf { it.irClass.isSubclassOf(expression.superQualifierSymbol!!.owner) }
|
||||
}
|
||||
// it is important firstly to add receiver, then arguments; this order is used in builtin method call
|
||||
val irFunction = irFunctionReceiver?.getIrFunction(expression.symbol.descriptor) ?: expression.symbol.owner
|
||||
@@ -400,7 +400,7 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
||||
|
||||
irFunction.takeIf { it.isInline }?.typeParameters?.forEachIndexed { index, typeParameter ->
|
||||
if (typeParameter.isReified) {
|
||||
val typeArgumentState = Common(expression.getTypeArgument(index)?.classOrNull!!.owner, mutableListOf())
|
||||
val typeArgumentState = Common(expression.getTypeArgument(index)?.classOrNull!!.owner)
|
||||
newFrame.addVar(Variable(typeParameter.descriptor, typeArgumentState))
|
||||
}
|
||||
}
|
||||
@@ -497,30 +497,25 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
||||
return Code.NEXT
|
||||
}
|
||||
|
||||
val state = Common(parent, mutableListOf())
|
||||
val state = Common(parent)
|
||||
newFrame.addVar(Variable(constructorCall.getThisAsReceiver(), state)) //used to set up fields in body
|
||||
constructorCall.getBody()?.interpret(newFrame)?.checkForReturn(newFrame, data) { return it }
|
||||
val returnedState = newFrame.popReturnValue() as Complex
|
||||
data.pushReturnValue(if (isPrimary) state.apply { superType = returnedState } else returnedState.apply { setStatesFrom(state) })
|
||||
data.pushReturnValue(if (isPrimary) state.apply { this.setSuperClassInstance(returnedState) } else returnedState.apply { setStatesFrom(state) })
|
||||
return Code.NEXT
|
||||
}
|
||||
|
||||
private suspend fun interpretConstructorCall(constructorCall: IrConstructorCall, data: Frame): Code {
|
||||
return interpretConstructor(constructorCall, data).apply {
|
||||
// constructor can return primitive object; fot example, when create array by constructor
|
||||
(data.peekReturnValue() as? Complex)?.let { it.setInstanceRecursive(it) }
|
||||
}
|
||||
return interpretConstructor(constructorCall, data)
|
||||
}
|
||||
|
||||
private suspend fun interpretEnumConstructorCall(enumConstructorCall: IrEnumConstructorCall, data: Frame): Code {
|
||||
return interpretConstructor(enumConstructorCall, data).apply {
|
||||
(data.peekReturnValue() as Complex).let { it.setInstanceRecursive(it) }
|
||||
}
|
||||
return interpretConstructor(enumConstructorCall, data)
|
||||
}
|
||||
|
||||
private suspend fun interpretDelegatedConstructorCall(delegatingConstructorCall: IrDelegatingConstructorCall, data: Frame): Code {
|
||||
if (delegatingConstructorCall.symbol.descriptor.containingDeclaration.defaultType == DefaultBuiltIns.Instance.anyType) {
|
||||
val anyAsStateObject = Common(irBuiltIns.anyClass.owner, mutableListOf())
|
||||
val anyAsStateObject = Common(irBuiltIns.anyClass.owner)
|
||||
data.pushReturnValue(anyAsStateObject)
|
||||
return Code.NEXT
|
||||
}
|
||||
@@ -665,7 +660,7 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
||||
data.pushReturnValue(Wrapper.getCompanionObject(owner))
|
||||
return Code.NEXT
|
||||
}
|
||||
val objectState = Common(owner, mutableListOf()).apply { this.instance = this }
|
||||
val objectState = Common(owner)
|
||||
data.pushReturnValue(objectState)
|
||||
return Code.NEXT
|
||||
}
|
||||
|
||||
+40
-39
@@ -96,17 +96,16 @@ class Primitive<T>(var value: T, val type: IrType) : State {
|
||||
}
|
||||
}
|
||||
|
||||
abstract class Complex(override val irClass: IrClass, override val fields: MutableList<Variable>) : State {
|
||||
var superType: Complex? = null
|
||||
var instance: Complex? = null
|
||||
|
||||
fun setInstanceRecursive(instance: Complex) {
|
||||
this.instance = instance
|
||||
superType?.setInstanceRecursive(instance)
|
||||
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
|
||||
}
|
||||
|
||||
fun getReceiver(): DeclarationDescriptor {
|
||||
return irClass.thisReceiver!!.descriptor
|
||||
fun getOriginal(): Complex {
|
||||
return subClass?.getOriginal() ?: this
|
||||
}
|
||||
|
||||
fun irClassFqName(): String {
|
||||
@@ -130,7 +129,12 @@ abstract class Complex(override val irClass: IrClass, override val fields: Mutab
|
||||
}
|
||||
}
|
||||
|
||||
class Common(override val irClass: IrClass, override val fields: MutableList<Variable>) : Complex(irClass, fields) {
|
||||
class Common private constructor(
|
||||
override val irClass: IrClass, override val fields: MutableList<Variable>, superClass: Complex?, subClass: Complex?
|
||||
) : Complex(irClass, fields, superClass, subClass) {
|
||||
|
||||
constructor(irClass: IrClass) : this(irClass, mutableListOf(), null, null)
|
||||
|
||||
fun getToStringFunction(): IrFunctionImpl {
|
||||
return irClass.declarations.filterIsInstance<IrFunction>()
|
||||
.filter { it.descriptor.name.asString() == "toString" }
|
||||
@@ -138,24 +142,22 @@ class Common(override val irClass: IrClass, override val fields: MutableList<Var
|
||||
}
|
||||
|
||||
override fun copy(): State {
|
||||
return Common(irClass, fields).apply {
|
||||
this@apply.superType = this@Common.superType
|
||||
this@apply.instance = this@Common.instance
|
||||
}
|
||||
return Common(irClass, fields, superClass, subClass ?: this)
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "Common(obj='${irClass.fqNameForIrSerialization}', super=$superType, values=$fields)"
|
||||
return "Common(obj='${irClass.fqNameForIrSerialization}', super=$superClass, values=$fields)"
|
||||
}
|
||||
}
|
||||
|
||||
class Wrapper(val value: Any, override val irClass: IrClass) : Complex(irClass, mutableListOf()) {
|
||||
class Wrapper private constructor(
|
||||
val value: Any, override val irClass: IrClass, subClass: Complex?
|
||||
) : Complex(irClass, mutableListOf(), null, subClass) {
|
||||
|
||||
private val typeFqName = irClass.fqNameForIrSerialization.toUnsafe()
|
||||
private val receiverClass = irClass.defaultType.getClass(true)
|
||||
|
||||
init {
|
||||
instance = this
|
||||
}
|
||||
constructor(value: Any, irClass: IrClass) : this(value, irClass, null)
|
||||
|
||||
fun getMethod(irFunction: IrFunction): MethodHandle? {
|
||||
// if function is actually a getter, then use "get${property.name.capitalize()}" as method name
|
||||
@@ -280,7 +282,7 @@ class Wrapper(val value: Any, override val irClass: IrClass) : Complex(irClass,
|
||||
}
|
||||
|
||||
override fun copy(): State {
|
||||
return Wrapper(value, irClass).apply { this@apply.instance = this@Wrapper.instance }
|
||||
return Wrapper(value, irClass, subClass ?: this)
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
@@ -288,7 +290,9 @@ class Wrapper(val value: Any, override val irClass: IrClass) : Complex(irClass,
|
||||
}
|
||||
}
|
||||
|
||||
class Lambda(val irFunction: IrFunction, override val irClass: IrClass) : Complex(irClass, mutableListOf()) {
|
||||
class Lambda(val irFunction: IrFunction, override val irClass: IrClass) : State {
|
||||
override val fields: MutableList<Variable> = mutableListOf()
|
||||
|
||||
// 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
|
||||
|
||||
@@ -301,7 +305,7 @@ class Lambda(val irFunction: IrFunction, override val irClass: IrClass) : Comple
|
||||
}
|
||||
|
||||
override fun copy(): State {
|
||||
return Lambda(irFunction, irClass).apply { this@apply.instance = this@Lambda.instance }
|
||||
return Lambda(irFunction, irClass)
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
@@ -310,18 +314,17 @@ class Lambda(val irFunction: IrFunction, override val irClass: IrClass) : Comple
|
||||
}
|
||||
|
||||
class ExceptionState private constructor(
|
||||
override val irClass: IrClass, override val fields: MutableList<Variable>, stackTrace: List<String>
|
||||
) : Complex(irClass, fields) {
|
||||
override val irClass: IrClass, override val fields: MutableList<Variable>, stackTrace: List<String>, subClass: Complex? = null
|
||||
) : Complex(irClass, fields, null, subClass) {
|
||||
|
||||
private lateinit var exceptionFqName: String
|
||||
private val exceptionHierarchy = mutableListOf<String>()
|
||||
private val messageProperty = irClass.getPropertyByName("message")
|
||||
private val causeProperty = irClass.getPropertyByName("cause")
|
||||
|
||||
private val stackTrace: List<String>
|
||||
private val stackTrace: List<String> = stackTrace.reversed()
|
||||
|
||||
init {
|
||||
instance = this
|
||||
this.stackTrace = stackTrace.reversed()
|
||||
if (!this::exceptionFqName.isInitialized) this.exceptionFqName = irClassFqName()
|
||||
|
||||
if (fields.none { it.descriptor.equalTo(messageProperty.descriptor) }) {
|
||||
@@ -331,7 +334,7 @@ class ExceptionState private constructor(
|
||||
|
||||
constructor(common: Common, stackTrace: List<String>) : this(common.irClass, common.fields, stackTrace) {
|
||||
var wrapperSuperType: Complex? = common
|
||||
while (wrapperSuperType != null && wrapperSuperType !is Wrapper) wrapperSuperType = (wrapperSuperType as Common).superType
|
||||
while (wrapperSuperType != null && wrapperSuperType !is Wrapper) wrapperSuperType = (wrapperSuperType as Common).superClass
|
||||
setUpCauseIfNeeded(wrapperSuperType as? Wrapper)
|
||||
}
|
||||
|
||||
@@ -351,6 +354,13 @@ class ExceptionState private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
data class ExceptionData(val state: ExceptionState) : Throwable() {
|
||||
override val message: String? = state.getMessage().value
|
||||
override fun fillInStackTrace() = this
|
||||
|
||||
override fun toString(): String = state.getMessageWithName()
|
||||
}
|
||||
|
||||
private fun setUpCauseIfNeeded(wrapper: Wrapper?) {
|
||||
val cause = (wrapper?.value as? Throwable)?.cause as? ExceptionData
|
||||
setCause(cause?.state)
|
||||
@@ -376,7 +386,7 @@ class ExceptionState private constructor(
|
||||
}
|
||||
|
||||
fun getMessage(): Primitive<String?> = getState(messageProperty.descriptor) as Primitive<String?>
|
||||
fun getMessageWithName(): String = getMessage().value?.let { "$exceptionFqName: $it" } ?: exceptionFqName
|
||||
private fun getMessageWithName(): String = getMessage().value?.let { "$exceptionFqName: $it" } ?: exceptionFqName
|
||||
|
||||
fun getCause(): ExceptionState? = getState(causeProperty.descriptor)?.let { if (it is ExceptionState) it else null }
|
||||
|
||||
@@ -394,7 +404,7 @@ class ExceptionState private constructor(
|
||||
fun getThisAsCauseForException() = ExceptionData(this)
|
||||
|
||||
override fun copy(): State {
|
||||
return ExceptionState(irClass, fields, stackTrace).apply { this@apply.instance = this@ExceptionState.instance }
|
||||
return ExceptionState(irClass, fields, stackTrace, subClass ?: this)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@@ -443,12 +453,3 @@ class ExceptionState private constructor(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO remove this data class and make ExceptionState a child of Throwable
|
||||
// this is possible by converting Complex to an interface
|
||||
data class ExceptionData(val state: ExceptionState) : Throwable() {
|
||||
override val message: String? = state.getMessage().value
|
||||
override fun fillInStackTrace() = this
|
||||
|
||||
override fun toString(): String = state.getMessageWithName()
|
||||
}
|
||||
Reference in New Issue
Block a user