Add reference to sub class in Complex class

This is replacement for instance field
This commit is contained in:
Ivan Kylchik
2020-03-27 20:41:58 +03:00
parent ad7055b8a0
commit 7e7a5fe736
2 changed files with 52 additions and 56 deletions
@@ -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
}
@@ -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()
}