Describe default behaviour for Any class methods
We are talking about such methods as equals, hashCode and toString.
This commit is contained in:
+46
-36
@@ -18,10 +18,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl
|
|||||||
import org.jetbrains.kotlin.ir.types.IrType
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
import org.jetbrains.kotlin.ir.types.classOrNull
|
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||||
import org.jetbrains.kotlin.ir.types.isSubtypeOf
|
import org.jetbrains.kotlin.ir.types.isSubtypeOf
|
||||||
import org.jetbrains.kotlin.ir.util.constructors
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.util.defaultType
|
|
||||||
import org.jetbrains.kotlin.ir.util.isSubclassOf
|
|
||||||
import org.jetbrains.kotlin.ir.util.statements
|
|
||||||
import java.lang.invoke.MethodHandle
|
import java.lang.invoke.MethodHandle
|
||||||
|
|
||||||
enum class Code(var info: String = "") {
|
enum class Code(var info: String = "") {
|
||||||
@@ -167,14 +164,15 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
val superQualifier = (data.getVariableState(variableDescriptor) as Complex).superType!!
|
val superQualifier = (data.getVariableState(variableDescriptor) as Complex).superType!!
|
||||||
val overridden = owner.overriddenSymbols.first { it.getReceiver()?.equalTo(superQualifier.getReceiver()) == true }
|
val overridden = owner.overriddenSymbols.first { it.getReceiver()?.equalTo(superQualifier.getReceiver()) == true }
|
||||||
|
|
||||||
val valueParameters = owner.valueParameters.zip(overridden.owner.valueParameters)
|
val newStates = InterpreterFrame(mutableListOf(Variable(overridden.getReceiver()!!, superQualifier)))
|
||||||
|
owner.valueParameters.zip(overridden.owner.valueParameters)
|
||||||
.map { Variable(it.second.descriptor, data.getVariableState(it.first.descriptor)) }
|
.map { Variable(it.second.descriptor, data.getVariableState(it.first.descriptor)) }
|
||||||
val newStates = InterpreterFrame(valueParameters.toMutableList())
|
.forEach { newStates.addVar(it) }
|
||||||
newStates.addVar(Variable(overridden.getReceiver()!!, superQualifier))
|
|
||||||
|
|
||||||
val overriddenOwner = overridden.owner as IrFunctionImpl
|
val overriddenOwner = overridden.owner as IrFunctionImpl
|
||||||
return when {
|
return when {
|
||||||
overriddenOwner.body != null -> overriddenOwner.interpret(newStates)
|
overriddenOwner.body != null -> overriddenOwner.interpret(newStates)
|
||||||
|
superQualifier.superType == null -> calculateBuiltIns(overriddenOwner, newStates)
|
||||||
else -> calculateOverridden(overriddenOwner, newStates)
|
else -> calculateOverridden(overriddenOwner, newStates)
|
||||||
}.apply { data.pushReturnValue(newStates) }
|
}.apply { data.pushReturnValue(newStates) }
|
||||||
}
|
}
|
||||||
@@ -182,34 +180,47 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
private fun calculateBuiltIns(irFunction: IrFunction, data: Frame): Code {
|
private fun calculateBuiltIns(irFunction: IrFunction, data: Frame): Code {
|
||||||
val descriptor = irFunction.descriptor
|
val descriptor = irFunction.descriptor
|
||||||
val methodName = descriptor.name.asString()
|
val methodName = descriptor.name.asString()
|
||||||
val receiverType = descriptor.dispatchReceiverParameter?.type ?: descriptor.extensionReceiverParameter?.type
|
val args = data.getAll().map { it.state }
|
||||||
val argsType = listOfNotNull(receiverType) + descriptor.valueParameters.map { it.original.type }
|
|
||||||
val argsValues = data.getAll()
|
val result: Any?
|
||||||
.map { it.state }
|
if (irFunction.parent.fqNameForIrSerialization.toString() == "kotlin.Any" || args.any { it !is Primitive<*> }) {
|
||||||
.map { it as? Primitive<*> ?: throw IllegalArgumentException("Builtin functions accept only const args") }
|
// if ir function is declaration in Any class OR it is ir builtin operator for non primitive types
|
||||||
.map { it.value }
|
val receiver = (args[0] as Complex).instance
|
||||||
val signature = CompileTimeFunction(methodName, argsType.map { it.toString() })
|
result = when (methodName) {
|
||||||
//todo try catch
|
"equals", "EQEQ", "EQEQEQ" -> (args[1] as Complex).instance === receiver
|
||||||
val result = when (argsType.size) {
|
"hashCode" -> System.identityHashCode(receiver)
|
||||||
1 -> {
|
"toString" -> receiver?.irClass?.name?.asString() + "@" + System.identityHashCode(receiver).toString(16).padStart(8)
|
||||||
val function = unaryFunctions[signature]
|
else -> throw IllegalStateException("Method $methodName can not be interpreted")
|
||||||
?: throw NoSuchMethodException("For given function $signature there is no entry in unary map")
|
|
||||||
function.invoke(argsValues.first())
|
|
||||||
}
|
}
|
||||||
2 -> {
|
} else {
|
||||||
val function = binaryFunctions[signature]
|
val receiverType = descriptor.dispatchReceiverParameter?.type ?: descriptor.extensionReceiverParameter?.type
|
||||||
?: throw NoSuchMethodException("For given function $signature there is no entry in binary map")
|
val argsType = listOfNotNull(receiverType) + descriptor.valueParameters.map { it.original.type }
|
||||||
when (methodName) {
|
val argsValues = args
|
||||||
"rangeTo" -> return calculateRangeTo(irFunction.returnType, data)
|
.map { it as? Primitive<*> ?: throw IllegalArgumentException("Builtin functions accept only const args") }
|
||||||
else -> function.invoke(argsValues[0], argsValues[1])
|
.map { it.value }
|
||||||
|
val signature = CompileTimeFunction(methodName, argsType.map { it.toString() })
|
||||||
|
|
||||||
|
result = when (argsType.size) {
|
||||||
|
1 -> {
|
||||||
|
val function = unaryFunctions[signature]
|
||||||
|
?: throw NoSuchMethodException("For given function $signature there is no entry in unary map")
|
||||||
|
function.invoke(argsValues.first())
|
||||||
}
|
}
|
||||||
|
2 -> {
|
||||||
|
val function = binaryFunctions[signature]
|
||||||
|
?: throw NoSuchMethodException("For given function $signature there is no entry in binary map")
|
||||||
|
when (methodName) {
|
||||||
|
"rangeTo" -> return calculateRangeTo(irFunction.returnType, data)
|
||||||
|
else -> function.invoke(argsValues[0], argsValues[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
3 -> {
|
||||||
|
val function = ternaryFunctions[signature]
|
||||||
|
?: throw NoSuchMethodException("For given function $signature there is no entry in ternary map")
|
||||||
|
function.invoke(argsValues[0], argsValues[1], argsValues[2])
|
||||||
|
}
|
||||||
|
else -> throw UnsupportedOperationException("Unsupported number of arguments")
|
||||||
}
|
}
|
||||||
3 -> {
|
|
||||||
val function = ternaryFunctions[signature]
|
|
||||||
?: throw NoSuchMethodException("For given function $signature there is no entry in ternary map")
|
|
||||||
function.invoke(argsValues[0], argsValues[1], argsValues[2])
|
|
||||||
}
|
|
||||||
else -> throw UnsupportedOperationException("Unsupported number of arguments")
|
|
||||||
}
|
}
|
||||||
data.pushReturnValue(result.toState(result.getType(irFunction.returnType)))
|
data.pushReturnValue(result.toState(result.getType(irFunction.returnType)))
|
||||||
return Code.NEXT
|
return Code.NEXT
|
||||||
@@ -295,9 +306,7 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
val state = Complex(parent, mutableListOf())
|
val state = Complex(parent, mutableListOf())
|
||||||
newFrame.addVar(Variable(constructorCall.getThisAsReceiver(), state)) //used to set up fields in body
|
newFrame.addVar(Variable(constructorCall.getThisAsReceiver(), state)) //used to set up fields in body
|
||||||
val code = constructorCall.getBody()?.interpret(newFrame) ?: Code.NEXT
|
val code = constructorCall.getBody()?.interpret(newFrame) ?: Code.NEXT
|
||||||
if (newFrame.hasReturnValue()) {
|
state.superType = newFrame.popReturnValue() as Complex
|
||||||
state.superType = newFrame.popReturnValue() as Complex
|
|
||||||
}
|
|
||||||
data.pushReturnValue(state)
|
data.pushReturnValue(state)
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
@@ -311,6 +320,8 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
|
|
||||||
private fun interpretDelegatedConstructorCall(delegatingConstructorCall: IrDelegatingConstructorCall, data: Frame): Code {
|
private fun interpretDelegatedConstructorCall(delegatingConstructorCall: IrDelegatingConstructorCall, data: Frame): Code {
|
||||||
if (delegatingConstructorCall.symbol.descriptor.containingDeclaration.defaultType == DefaultBuiltIns.Instance.anyType) {
|
if (delegatingConstructorCall.symbol.descriptor.containingDeclaration.defaultType == DefaultBuiltIns.Instance.anyType) {
|
||||||
|
val anyComplex = Complex(irBuiltIns.anyClass.owner, mutableListOf())
|
||||||
|
data.pushReturnValue(anyComplex)
|
||||||
return Code.NEXT
|
return Code.NEXT
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -323,7 +334,6 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun interpretStatements(statements: List<IrStatement>, data: Frame): Code {
|
private fun interpretStatements(statements: List<IrStatement>, data: Frame): Code {
|
||||||
//create newFrame
|
|
||||||
val newFrame = data.copy()
|
val newFrame = data.copy()
|
||||||
|
|
||||||
var code = Code.NEXT
|
var code = Code.NEXT
|
||||||
|
|||||||
Reference in New Issue
Block a user