Implement correct interpretation of toList function
This commit is contained in:
+13
-8
@@ -54,7 +54,10 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
||||
is Float -> irBuiltIns.floatType
|
||||
is Double -> irBuiltIns.doubleType
|
||||
null -> irBuiltIns.nothingType
|
||||
else -> defaultType
|
||||
else -> when (defaultType.classifierOrNull?.owner) {
|
||||
is IrTypeParameter -> stack.getVariableState(defaultType.classifierOrFail.descriptor).irClass.defaultType
|
||||
else -> defaultType
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,7 +176,7 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
||||
functionImplementation.valueParameters
|
||||
.map { Variable(it.descriptor, stack.getVariableState(it.descriptor)) }
|
||||
.forEach { valueArguments.add(it) }
|
||||
return stack.newFrame(initPool = valueArguments) {
|
||||
return stack.newFrame(asSubFrame = true, initPool = valueArguments) {
|
||||
functionImplementation.interpret()
|
||||
}
|
||||
}
|
||||
@@ -195,7 +198,7 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
||||
.map { Variable(it.second.descriptor, stack.getVariableState(it.first.descriptor)) }
|
||||
.forEach { valueArguments.add(it) }
|
||||
|
||||
return stack.newFrame(initPool = valueArguments) {
|
||||
return stack.newFrame(asSubFrame = true, initPool = valueArguments) {
|
||||
val overriddenOwner = overridden.owner
|
||||
return@newFrame when {
|
||||
overriddenOwner.body != null -> overriddenOwner.interpret()
|
||||
@@ -316,10 +319,11 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
||||
interpretValueParameters(expression, irFunction, valueArguments).check { return it }
|
||||
|
||||
valueArguments.addAll(getTypeArguments(irFunction, expression) { stack.getVariableState(it) })
|
||||
if (dispatchReceiver is Common) valueArguments.addAll(dispatchReceiver.typeArguments)
|
||||
if (extensionReceiver is Common) valueArguments.addAll(extensionReceiver.typeArguments)
|
||||
if (dispatchReceiver is Complex) valueArguments.addAll(dispatchReceiver.typeArguments)
|
||||
if (extensionReceiver is Complex) valueArguments.addAll(extensionReceiver.typeArguments)
|
||||
|
||||
if (irFunction.isLocal) valueArguments.addAll(dispatchReceiver.extractNonLocalDeclarations())
|
||||
val isLocal = (dispatchReceiver as? Complex)?.getOriginal()?.irClass?.isLocal ?: irFunction.isLocal
|
||||
if (isLocal) valueArguments.addAll(dispatchReceiver.extractNonLocalDeclarations())
|
||||
|
||||
return stack.newFrame(asSubFrame = irFunction.isInline || irFunction.isLocal, initPool = valueArguments) {
|
||||
val isWrapper = dispatchReceiver is Wrapper && rawExtensionReceiver == null
|
||||
@@ -364,8 +368,10 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
||||
interpretValueParameters(constructorCall, owner, valueArguments).check { return it }
|
||||
|
||||
val parent = owner.parent as IrClass
|
||||
val typeArguments = getTypeArguments(parent, constructorCall) { stack.getVariableState(it) } + stack.getAllTypeArguments()
|
||||
if (parent.hasAnnotation(evaluateIntrinsicAnnotation)) {
|
||||
return stack.newFrame(initPool = valueArguments) { Wrapper.getConstructorMethod(owner).invokeMethod(owner) }
|
||||
.apply { (stack.peekReturnValue() as? Wrapper)?.typeArguments?.addAll(typeArguments) } // can be exception
|
||||
}
|
||||
|
||||
if (parent.defaultType.isArray() || parent.defaultType.isPrimitiveArray()) {
|
||||
@@ -373,8 +379,7 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
||||
return stack.newFrame(initPool = valueArguments) { handleIntrinsicMethods(owner) }
|
||||
}
|
||||
|
||||
val state = Common(parent)
|
||||
state.typeArguments.addAll(getTypeArguments(parent, constructorCall) { stack.getVariableState(it) } + stack.getAllTypeArguments())
|
||||
val state = Common(parent).apply { this.typeArguments.addAll(typeArguments) }
|
||||
if (parent.isLocal) state.fields.addAll(stack.getAll()) // TODO save only necessary declarations
|
||||
valueArguments.add(Variable(constructorCall.getThisAsReceiver(), state)) //used to set up fields in body
|
||||
return stack.newFrame(initPool = valueArguments + state.typeArguments) {
|
||||
|
||||
+18
-6
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
|
||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
// main purpose is to get receiver from constructor call
|
||||
fun IrMemberAccessExpression.getThisAsReceiver(): DeclarationDescriptor {
|
||||
@@ -238,6 +239,7 @@ fun State?.getFunctionReceiver(superIrClass: IrClass?): State? {
|
||||
|
||||
fun IrFunctionAccessExpression.getVarargType(index: Int): IrType? {
|
||||
val varargType = this.symbol.owner.valueParameters[index].varargElementType ?: return null
|
||||
varargType.classOrNull?.let { return this.symbol.owner.valueParameters[index].type }
|
||||
val typeParameter = varargType.classifierOrFail.owner as IrTypeParameter
|
||||
return this.getTypeArgument(typeParameter.index)
|
||||
}
|
||||
@@ -245,15 +247,25 @@ fun IrFunctionAccessExpression.getVarargType(index: Int): IrType? {
|
||||
fun getTypeArguments(
|
||||
container: IrTypeParametersContainer, expression: IrFunctionAccessExpression, mapper: (TypeParameterDescriptor) -> State
|
||||
): List<Variable> {
|
||||
return container.typeParameters.mapIndexed { index, typeParameter ->
|
||||
val typeArgument = expression.getTypeArgument(index)!!
|
||||
val argumentState = typeArgument.classOrNull?.owner?.let { Common(it) }
|
||||
?: mapper(typeArgument.classifierOrFail.descriptor as TypeParameterDescriptor)
|
||||
Variable(typeParameter.descriptor, argumentState)
|
||||
fun IrType.getState(): State {
|
||||
return this.classOrNull?.owner?.let { Common(it) } ?: mapper(this.classifierOrFail.descriptor as TypeParameterDescriptor)
|
||||
}
|
||||
|
||||
val typeArguments = container.typeParameters.mapIndexed { index, typeParameter ->
|
||||
val typeArgument = expression.getTypeArgument(index)!!
|
||||
Variable(typeParameter.descriptor, typeArgument.getState())
|
||||
}.toMutableList()
|
||||
|
||||
if (container is IrSimpleFunction) {
|
||||
container.returnType.classifierOrFail.owner.safeAs<IrTypeParameter>()
|
||||
?.let { typeArguments.add(Variable(it.descriptor, expression.type.getState())) }
|
||||
}
|
||||
|
||||
return typeArguments
|
||||
}
|
||||
|
||||
fun State?.extractNonLocalDeclarations(): List<Variable> {
|
||||
this ?: return listOf()
|
||||
return this.fields.filterNot { it.descriptor.containingDeclaration == this.irClass.descriptor }
|
||||
val state = this.takeIf { it !is Complex } ?: (this as Complex).getOriginal()
|
||||
return state.fields.filterNot { it.descriptor.containingDeclaration == state.irClass.descriptor }
|
||||
}
|
||||
+2
-1
@@ -65,7 +65,8 @@ class StackImpl : Stack {
|
||||
val fileName = irFunction.file.name
|
||||
val fileNameCapitalized = fileName.replace(".kt", "Kt").capitalize()
|
||||
val lineNum = irFunction.fileEntry.getLineNumber(irFunction.startOffset) + 1
|
||||
getCurrentFrame().frameEntryPoint = "at $fileNameCapitalized.${irFunction.fqNameWhenAvailable}($fileName:$lineNum)"
|
||||
if (getCurrentFrame().frameEntryPoint == null)
|
||||
getCurrentFrame().frameEntryPoint = "at $fileNameCapitalized.${irFunction.fqNameWhenAvailable}($fileName:$lineNum)"
|
||||
}
|
||||
|
||||
override fun getStackTrace(): List<String> {
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization
|
||||
import org.jetbrains.kotlin.ir.util.isInterface
|
||||
|
||||
class Common private constructor(
|
||||
override val irClass: IrClass, override val fields: MutableList<Variable>, val typeArguments: MutableList<Variable>,
|
||||
override val irClass: IrClass, override val fields: MutableList<Variable>, override val typeArguments: MutableList<Variable>,
|
||||
superClass: Complex?, subClass: Complex?
|
||||
) : Complex(irClass, fields, superClass, subClass) {
|
||||
|
||||
|
||||
+2
@@ -16,6 +16,8 @@ import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization
|
||||
abstract class Complex(
|
||||
override val irClass: IrClass, override val fields: MutableList<Variable>, var superClass: Complex?, var subClass: Complex?
|
||||
) : State {
|
||||
abstract val typeArguments: MutableList<Variable>
|
||||
|
||||
fun setSuperClassInstance(superClass: Complex) {
|
||||
if (this.irClass == superClass.irClass) {
|
||||
// if superClass is just secondary constructor instance, then copy properties that isn't already present in instance
|
||||
|
||||
+1
@@ -18,6 +18,7 @@ import kotlin.math.min
|
||||
class ExceptionState private constructor(
|
||||
override val irClass: IrClass, override val fields: MutableList<Variable>, stackTrace: List<String>, subClass: Complex? = null
|
||||
) : Complex(irClass, fields, null, subClass) {
|
||||
override val typeArguments: MutableList<Variable> = mutableListOf()
|
||||
|
||||
private lateinit var exceptionFqName: String
|
||||
private val exceptionHierarchy = mutableListOf<String>()
|
||||
|
||||
+19
-5
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.ir.util.isTypeParameter
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithDifferentJvmName
|
||||
import org.jetbrains.kotlin.load.java.BuiltinSpecialProperties
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.firstOverridden
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
@@ -35,13 +36,13 @@ import java.lang.invoke.MethodHandles
|
||||
import java.lang.invoke.MethodType
|
||||
|
||||
class Wrapper private constructor(
|
||||
val value: Any, override val irClass: IrClass, subClass: Complex?
|
||||
val value: Any, override val irClass: IrClass, subClass: Complex?, override val typeArguments: MutableList<Variable>
|
||||
) : Complex(irClass, mutableListOf(), null, subClass) {
|
||||
|
||||
private val typeFqName = irClass.fqNameForIrSerialization.toUnsafe()
|
||||
private val receiverClass = irClass.defaultType.getClass(true)
|
||||
|
||||
constructor(value: Any, irClass: IrClass) : this(value, irClass, null)
|
||||
constructor(value: Any, irClass: IrClass) : this(value, irClass, null, mutableListOf())
|
||||
|
||||
fun getMethod(irFunction: IrFunction): MethodHandle? {
|
||||
if (irFunction.getEvaluateIntrinsicValue()?.isEmpty() == true) return null // this method will handle IntrinsicEvaluator
|
||||
@@ -136,11 +137,24 @@ class Wrapper private constructor(
|
||||
this.isArray() -> if (asObject) Array<Any?>::class.javaObjectType else Array<Any?>::class.java
|
||||
owner.hasAnnotation(evaluateIntrinsicAnnotation) -> Class.forName(owner!!.getEvaluateIntrinsicValue())
|
||||
//TODO primitive array
|
||||
this.isTypeParameter() -> Any::class.java
|
||||
else -> JavaToKotlinClassMap.mapKotlinToJava(FqNameUnsafe(fqName!!))?.let { Class.forName(it.asSingleFqName().toString()) }
|
||||
this.isTypeParameter() -> Any::class.java // TODO use typeArguments
|
||||
else -> JavaToKotlinClassMap.mapKotlinToJava(FqNameUnsafe(fqName!!))?.let { Class.forName(it.getAsString()) }
|
||||
} ?: Class.forName(fqName)
|
||||
}
|
||||
|
||||
private fun ClassId.getAsString(): String {
|
||||
// TODO come up with something better
|
||||
val fqName = this.asSingleFqName().toString()
|
||||
val names = fqName.split(".")
|
||||
val result = StringBuilder()
|
||||
for (i in 0 until (names.size - 1)) {
|
||||
result.append(names[i])
|
||||
if (names[i][0].isUpperCase() && names[i + 1][0].isUpperCase()) result.append("$") else result.append(".")
|
||||
}
|
||||
result.append(names.last())
|
||||
return result.toString()
|
||||
}
|
||||
|
||||
private fun IrFunction.getOriginalOverriddenSymbols(): MutableList<IrFunctionSymbol> {
|
||||
val overriddenSymbols = mutableListOf<IrFunctionSymbol>()
|
||||
if (this is IrFunctionImpl) {
|
||||
@@ -184,7 +198,7 @@ class Wrapper private constructor(
|
||||
}
|
||||
|
||||
override fun copy(): State {
|
||||
return Wrapper(value, irClass, subClass ?: this)
|
||||
return Wrapper(value, irClass, subClass ?: this, typeArguments)
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
|
||||
Reference in New Issue
Block a user