Implement basic interpretation of IrClassReference
This commit is contained in:
committed by
TeamCityServer
parent
002804941f
commit
40bf4fafc9
@@ -34,7 +34,7 @@ import java.lang.invoke.MethodHandle
|
|||||||
private const val MAX_COMMANDS = 500_000
|
private const val MAX_COMMANDS = 500_000
|
||||||
private const val MAX_STACK = 500
|
private const val MAX_STACK = 500
|
||||||
|
|
||||||
class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map<IdSignature, IrBody> = emptyMap()) {
|
class IrInterpreter(val irBuiltIns: IrBuiltIns, private val bodyMap: Map<IdSignature, IrBody> = emptyMap()) {
|
||||||
private val irExceptions = mutableListOf<IrClass>()
|
private val irExceptions = mutableListOf<IrClass>()
|
||||||
|
|
||||||
private val stack = StackImpl()
|
private val stack = StackImpl()
|
||||||
@@ -142,6 +142,7 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
|
|||||||
is IrFunctionExpression -> interpretFunctionExpression(this)
|
is IrFunctionExpression -> interpretFunctionExpression(this)
|
||||||
is IrFunctionReference -> interpretFunctionReference(this)
|
is IrFunctionReference -> interpretFunctionReference(this)
|
||||||
is IrPropertyReference -> interpretPropertyReference(this)
|
is IrPropertyReference -> interpretPropertyReference(this)
|
||||||
|
is IrClassReference -> interpretClassReference(this)
|
||||||
is IrComposite -> interpretComposite(this)
|
is IrComposite -> interpretComposite(this)
|
||||||
|
|
||||||
else -> TODO("${this.javaClass} not supported")
|
else -> TODO("${this.javaClass} not supported")
|
||||||
@@ -889,4 +890,9 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
|
|||||||
stack.pushReturnValue(propertyState)
|
stack.pushReturnValue(propertyState)
|
||||||
return Next
|
return Next
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun interpretClassReference(classReference: IrClassReference): ExecutionResult {
|
||||||
|
stack.pushReturnValue(KClassState(classReference))
|
||||||
|
return Next
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+3
-2
@@ -29,7 +29,7 @@ enum class EvaluationMode(protected val mustCheckBody: Boolean) {
|
|||||||
WITH_ANNOTATIONS(mustCheckBody = false) {
|
WITH_ANNOTATIONS(mustCheckBody = false) {
|
||||||
override fun canEvaluateFunction(function: IrFunction, expression: IrCall?): Boolean {
|
override fun canEvaluateFunction(function: IrFunction, expression: IrCall?): Boolean {
|
||||||
if (function.isCompileTimeProperty()) return true
|
if (function.isCompileTimeProperty()) return true
|
||||||
return function.isMarkedWith(compileTimeAnnotation) || function.origin == IrBuiltIns.BUILTIN_OPERATOR ||
|
return function.isMarkedAsCompileTime() || function.origin == IrBuiltIns.BUILTIN_OPERATOR ||
|
||||||
(function is IrSimpleFunction && function.isOperator && function.name.asString() == "invoke") ||
|
(function is IrSimpleFunction && function.isOperator && function.name.asString() == "invoke") ||
|
||||||
(function is IrSimpleFunction && function.isFakeOverride && function.overriddenSymbols.any { canEvaluateFunction(it.owner) }) ||
|
(function is IrSimpleFunction && function.isFakeOverride && function.overriddenSymbols.any { canEvaluateFunction(it.owner) }) ||
|
||||||
function.isCompileTimeTypeAlias()
|
function.isCompileTimeTypeAlias()
|
||||||
@@ -38,7 +38,7 @@ enum class EvaluationMode(protected val mustCheckBody: Boolean) {
|
|||||||
private fun IrDeclaration?.isCompileTimeProperty(): Boolean {
|
private fun IrDeclaration?.isCompileTimeProperty(): Boolean {
|
||||||
val property = (this as? IrSimpleFunction)?.correspondingPropertySymbol?.owner ?: return false
|
val property = (this as? IrSimpleFunction)?.correspondingPropertySymbol?.owner ?: return false
|
||||||
if (property.isConst) return true
|
if (property.isConst) return true
|
||||||
if (property.isMarkedWith(compileTimeAnnotation) || property.isCompileTimeTypeAlias()) return true
|
if (property.isMarkedAsCompileTime() || property.isCompileTimeTypeAlias()) return true
|
||||||
|
|
||||||
val backingField = property.backingField
|
val backingField = property.backingField
|
||||||
val backingFieldExpression = backingField?.initializer?.expression as? IrGetValue
|
val backingFieldExpression = backingField?.initializer?.expression as? IrGetValue
|
||||||
@@ -73,6 +73,7 @@ enum class EvaluationMode(protected val mustCheckBody: Boolean) {
|
|||||||
"java.lang.StringBuilder", "java.lang.IllegalArgumentException", "java.util.NoSuchElementException"
|
"java.lang.StringBuilder", "java.lang.IllegalArgumentException", "java.util.NoSuchElementException"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fun IrDeclaration.isMarkedAsCompileTime() = isMarkedWith(compileTimeAnnotation)
|
||||||
private fun IrDeclaration.isContract() = isMarkedWith(contractsDslAnnotation)
|
private fun IrDeclaration.isContract() = isMarkedWith(contractsDslAnnotation)
|
||||||
private fun IrDeclaration.isMarkedAsEvaluateIntrinsic() = isMarkedWith(evaluateIntrinsicAnnotation)
|
private fun IrDeclaration.isMarkedAsEvaluateIntrinsic() = isMarkedWith(evaluateIntrinsicAnnotation)
|
||||||
protected fun IrDeclaration.isCompileTimeTypeAlias() = this.parentClassOrNull?.fqNameWhenAvailable?.asString() in compileTimeTypeAliases
|
protected fun IrDeclaration.isCompileTimeTypeAlias() = this.parentClassOrNull?.fqNameWhenAvailable?.asString() in compileTimeTypeAliases
|
||||||
|
|||||||
+4
@@ -259,4 +259,8 @@ class IrCompileTimeChecker(
|
|||||||
override fun visitPropertyReference(expression: IrPropertyReference, data: Nothing?): Boolean {
|
override fun visitPropertyReference(expression: IrPropertyReference, data: Nothing?): Boolean {
|
||||||
return mode.canEvaluateFunction(expression.getter!!.owner)
|
return mode.canEvaluateFunction(expression.getter!!.owner)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visitClassReference(expression: IrClassReference, data: Nothing?): Boolean {
|
||||||
|
return with(mode) { (expression.symbol.owner as IrClass).isMarkedAsCompileTime() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+12
-15
@@ -6,7 +6,6 @@
|
|||||||
package org.jetbrains.kotlin.ir.interpreter.proxy.reflection
|
package org.jetbrains.kotlin.ir.interpreter.proxy.reflection
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
|
||||||
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
|
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
|
||||||
import org.jetbrains.kotlin.ir.interpreter.state.KPropertyState
|
import org.jetbrains.kotlin.ir.interpreter.state.KPropertyState
|
||||||
import org.jetbrains.kotlin.ir.types.IrType
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
@@ -19,25 +18,22 @@ internal abstract class AbstractKPropertyProxy(
|
|||||||
) : ReflectionProxy, KProperty<Any?> {
|
) : ReflectionProxy, KProperty<Any?> {
|
||||||
|
|
||||||
protected val propertyType: IrType
|
protected val propertyType: IrType
|
||||||
get() = state.propertyReference.getter!!.owner.returnType
|
get() = state.property.getter!!.returnType
|
||||||
|
|
||||||
private val propertyOwner: IrProperty
|
|
||||||
get() = state.propertyReference.symbol.owner
|
|
||||||
|
|
||||||
override val isAbstract: Boolean
|
override val isAbstract: Boolean
|
||||||
get() = propertyOwner.modality == Modality.ABSTRACT
|
get() = state.property.modality == Modality.ABSTRACT
|
||||||
override val isConst: Boolean
|
override val isConst: Boolean
|
||||||
get() = propertyOwner.isConst
|
get() = state.property.isConst
|
||||||
override val isFinal: Boolean
|
override val isFinal: Boolean
|
||||||
get() = propertyOwner.modality == Modality.FINAL
|
get() = state.property.modality == Modality.FINAL
|
||||||
override val isLateinit: Boolean
|
override val isLateinit: Boolean
|
||||||
get() = propertyOwner.isLateinit
|
get() = state.property.isLateinit
|
||||||
override val isOpen: Boolean
|
override val isOpen: Boolean
|
||||||
get() = propertyOwner.modality == Modality.OPEN
|
get() = state.property.modality == Modality.OPEN
|
||||||
override val isSuspend: Boolean
|
override val isSuspend: Boolean
|
||||||
get() = TODO("Not yet implemented")
|
get() = false
|
||||||
override val name: String
|
override val name: String
|
||||||
get() = propertyOwner.name.asString()
|
get() = state.property.name.asString()
|
||||||
|
|
||||||
override val annotations: List<Annotation>
|
override val annotations: List<Annotation>
|
||||||
get() = TODO("Not yet implemented")
|
get() = TODO("Not yet implemented")
|
||||||
@@ -47,14 +43,15 @@ internal abstract class AbstractKPropertyProxy(
|
|||||||
get() = TODO("Not yet implemented")
|
get() = TODO("Not yet implemented")
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
TODO("Not yet implemented")
|
if (other !is AbstractKPropertyProxy) return false
|
||||||
|
return state == other.state
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
override fun hashCode(): Int {
|
||||||
TODO("Not yet implemented")
|
return state.hashCode()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
TODO("Not yet implemented")
|
return state.toString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+77
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.ir.interpreter.proxy.reflection
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
|
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
|
||||||
|
import org.jetbrains.kotlin.ir.interpreter.internalName
|
||||||
|
import org.jetbrains.kotlin.ir.interpreter.proxy.Proxy
|
||||||
|
import org.jetbrains.kotlin.ir.interpreter.state.KClassState
|
||||||
|
import kotlin.reflect.*
|
||||||
|
|
||||||
|
internal class KClassProxy(
|
||||||
|
override val state: KClassState, override val interpreter: IrInterpreter
|
||||||
|
) : ReflectionProxy, KClass<Proxy> {
|
||||||
|
override val simpleName: String?
|
||||||
|
get() = state.irClass.name.asString() // TODO return null if class has no name
|
||||||
|
override val qualifiedName: String?
|
||||||
|
get() = state.irClass.internalName()
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
override val constructors: Collection<KFunction<Proxy>>
|
||||||
|
get() = state.getConstructors(interpreter) as Collection<KFunction<Proxy>>
|
||||||
|
override val members: Collection<KCallable<*>>
|
||||||
|
get() = state.getMembers(interpreter)
|
||||||
|
override val nestedClasses: Collection<KClass<*>>
|
||||||
|
get() = TODO("Not yet implemented")
|
||||||
|
override val objectInstance: Proxy?
|
||||||
|
get() = TODO("Not yet implemented")
|
||||||
|
override val typeParameters: List<KTypeParameter>
|
||||||
|
get() = TODO("Not yet implemented")
|
||||||
|
override val supertypes: List<KType>
|
||||||
|
get() = TODO("Not yet implemented")
|
||||||
|
override val sealedSubclasses: List<KClass<out Proxy>>
|
||||||
|
get() = TODO("Not yet implemented")
|
||||||
|
override val annotations: List<Annotation>
|
||||||
|
get() = TODO("Not yet implemented")
|
||||||
|
|
||||||
|
override val visibility: KVisibility?
|
||||||
|
get() = TODO("Not yet implemented")
|
||||||
|
override val isFinal: Boolean
|
||||||
|
get() = state.irClass.modality == Modality.FINAL
|
||||||
|
override val isOpen: Boolean
|
||||||
|
get() = state.irClass.modality == Modality.OPEN
|
||||||
|
override val isAbstract: Boolean
|
||||||
|
get() = state.irClass.modality == Modality.ABSTRACT
|
||||||
|
override val isSealed: Boolean
|
||||||
|
get() = state.irClass.modality == Modality.SEALED
|
||||||
|
override val isData: Boolean
|
||||||
|
get() = state.irClass.isData
|
||||||
|
override val isInner: Boolean
|
||||||
|
get() = state.irClass.isInner
|
||||||
|
override val isCompanion: Boolean
|
||||||
|
get() = state.irClass.isCompanion
|
||||||
|
override val isFun: Boolean
|
||||||
|
get() = state.irClass.isFun
|
||||||
|
override val isValue: Boolean
|
||||||
|
get() = state.irClass.isInline
|
||||||
|
|
||||||
|
override fun isInstance(value: Any?): Boolean {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
}
|
||||||
+33
-31
@@ -20,50 +20,26 @@ internal class KFunctionProxy(
|
|||||||
) : ReflectionProxy, KFunction<Any?>, FunctionWithAllInvokes {
|
) : ReflectionProxy, KFunction<Any?>, FunctionWithAllInvokes {
|
||||||
override val arity: Int = state.getArity() ?: BuiltInFunctionArity.BIG_ARITY
|
override val arity: Int = state.getArity() ?: BuiltInFunctionArity.BIG_ARITY
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
|
||||||
if (this === other) return true
|
|
||||||
if (other !is ReflectionProxy) return false
|
|
||||||
|
|
||||||
return state == other.state
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
|
||||||
return state.hashCode()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toString(): String {
|
|
||||||
return state.toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
override val annotations: List<Annotation>
|
|
||||||
get() = TODO("Not yet implemented")
|
|
||||||
override val isAbstract: Boolean
|
|
||||||
get() = state.irFunction is IrSimpleFunction && state.irFunction.modality == Modality.ABSTRACT
|
|
||||||
override val isExternal: Boolean
|
|
||||||
get() = state.irFunction.isExternal
|
|
||||||
override val isFinal: Boolean
|
|
||||||
get() = state.irFunction is IrSimpleFunction && state.irFunction.modality == Modality.FINAL
|
|
||||||
override val isInfix: Boolean
|
|
||||||
get() = state.irFunction is IrSimpleFunction && state.irFunction.isInfix
|
|
||||||
override val isInline: Boolean
|
override val isInline: Boolean
|
||||||
get() = state.irFunction.isInline
|
get() = state.irFunction.isInline
|
||||||
override val isOpen: Boolean
|
override val isExternal: Boolean
|
||||||
get() = state.irFunction is IrSimpleFunction && state.irFunction.modality == Modality.OPEN
|
get() = state.irFunction.isExternal
|
||||||
override val isOperator: Boolean
|
override val isOperator: Boolean
|
||||||
get() = state.irFunction is IrSimpleFunction && state.irFunction.isOperator
|
get() = state.irFunction is IrSimpleFunction && state.irFunction.isOperator
|
||||||
override val isSuspend: Boolean
|
override val isInfix: Boolean
|
||||||
get() = state.irFunction.isSuspend
|
get() = state.irFunction is IrSimpleFunction && state.irFunction.isInfix
|
||||||
override val name: String
|
override val name: String
|
||||||
get() = state.irFunction.name.asString()
|
get() = state.irFunction.name.asString()
|
||||||
|
|
||||||
|
|
||||||
|
override val annotations: List<Annotation>
|
||||||
|
get() = TODO("Not yet implemented")
|
||||||
override val parameters: List<KParameter>
|
override val parameters: List<KParameter>
|
||||||
get() = TODO("Not yet implemented")
|
get() = TODO("Not yet implemented")
|
||||||
override val returnType: KType
|
override val returnType: KType
|
||||||
get() = TODO("Not yet implemented")
|
get() = TODO("Not yet implemented")
|
||||||
override val typeParameters: List<KTypeParameter>
|
override val typeParameters: List<KTypeParameter>
|
||||||
get() = TODO("Not yet implemented")
|
get() = TODO("Not yet implemented")
|
||||||
override val visibility: KVisibility?
|
|
||||||
get() = TODO("Not yet implemented")
|
|
||||||
|
|
||||||
override fun call(vararg args: Any?): Any? {
|
override fun call(vararg args: Any?): Any? {
|
||||||
var index = 0
|
var index = 0
|
||||||
@@ -77,5 +53,31 @@ internal class KFunctionProxy(
|
|||||||
override fun callBy(args: Map<KParameter, Any?>): Any? {
|
override fun callBy(args: Map<KParameter, Any?>): Any? {
|
||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val visibility: KVisibility?
|
||||||
|
get() = TODO("Not yet implemented")
|
||||||
|
override val isFinal: Boolean
|
||||||
|
get() = state.irFunction is IrSimpleFunction && state.irFunction.modality == Modality.FINAL
|
||||||
|
override val isOpen: Boolean
|
||||||
|
get() = state.irFunction is IrSimpleFunction && state.irFunction.modality == Modality.OPEN
|
||||||
|
override val isAbstract: Boolean
|
||||||
|
get() = state.irFunction is IrSimpleFunction && state.irFunction.modality == Modality.ABSTRACT
|
||||||
|
override val isSuspend: Boolean
|
||||||
|
get() = state.irFunction.isSuspend
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (other !is ReflectionProxy) return false
|
||||||
|
|
||||||
|
return state == other.state
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return state.hashCode()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return state.toString()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -35,7 +35,7 @@ internal open class KProperty0Proxy(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun get(): Any? {
|
override fun get(): Any? {
|
||||||
return state.dispatchReceiver!!.getState(state.propertyReference.symbol)!!
|
return state.dispatchReceiver!!.getState(state.property.symbol)!!
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getDelegate(): Any? {
|
override fun getDelegate(): Any? {
|
||||||
@@ -53,6 +53,6 @@ internal class KMutableProperty0Proxy(
|
|||||||
get() = TODO("Not yet implemented")
|
get() = TODO("Not yet implemented")
|
||||||
|
|
||||||
override fun set(value: Any?) {
|
override fun set(value: Any?) {
|
||||||
state.dispatchReceiver!!.setField(Variable(state.propertyReference.symbol, value.toState(propertyType)))
|
state.dispatchReceiver!!.setField(Variable(state.property.symbol, value.toState(propertyType)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -36,7 +36,7 @@ internal open class KProperty1Proxy(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun get(receiver: Proxy): Any? {
|
override fun get(receiver: Proxy): Any? {
|
||||||
return receiver.state.getState(state.propertyReference.symbol)!!.wrap(interpreter)
|
return receiver.state.getState(state.property.symbol)!!.wrap(interpreter)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getDelegate(receiver: Proxy): Any? {
|
override fun getDelegate(receiver: Proxy): Any? {
|
||||||
@@ -54,6 +54,6 @@ internal class KMutableProperty1Proxy(
|
|||||||
get() = TODO("Not yet implemented")
|
get() = TODO("Not yet implemented")
|
||||||
|
|
||||||
override fun set(receiver: Proxy, value: Any?) {
|
override fun set(receiver: Proxy, value: Any?) {
|
||||||
receiver.state.setField(Variable(state.propertyReference.symbol, value.toState(propertyType)))
|
receiver.state.setField(Variable(state.property.symbol, value.toState(propertyType)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+5
-3
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.ir.interpreter.proxy.reflection
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
|
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
|
||||||
import org.jetbrains.kotlin.ir.interpreter.proxy.Proxy
|
import org.jetbrains.kotlin.ir.interpreter.proxy.Proxy
|
||||||
|
import org.jetbrains.kotlin.ir.interpreter.state.KClassState
|
||||||
import org.jetbrains.kotlin.ir.interpreter.state.KFunctionState
|
import org.jetbrains.kotlin.ir.interpreter.state.KFunctionState
|
||||||
import org.jetbrains.kotlin.ir.interpreter.state.KPropertyState
|
import org.jetbrains.kotlin.ir.interpreter.state.KPropertyState
|
||||||
import org.jetbrains.kotlin.ir.interpreter.state.ReflectionState
|
import org.jetbrains.kotlin.ir.interpreter.state.ReflectionState
|
||||||
@@ -16,15 +17,16 @@ internal interface ReflectionProxy : Proxy {
|
|||||||
internal fun ReflectionState.asProxy(interpreter: IrInterpreter): ReflectionProxy {
|
internal fun ReflectionState.asProxy(interpreter: IrInterpreter): ReflectionProxy {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
is KPropertyState -> when {
|
is KPropertyState -> when {
|
||||||
this.isKProperty0() -> KProperty0Proxy(this, interpreter)
|
|
||||||
this.isKMutableProperty0() -> KMutableProperty0Proxy(this, interpreter)
|
this.isKMutableProperty0() -> KMutableProperty0Proxy(this, interpreter)
|
||||||
this.isKProperty1() -> KProperty1Proxy(this, interpreter)
|
this.isKProperty0() -> KProperty0Proxy(this, interpreter)
|
||||||
this.isKMutableProperty1() -> KMutableProperty1Proxy(this, interpreter)
|
this.isKMutableProperty1() -> KMutableProperty1Proxy(this, interpreter)
|
||||||
this.isKProperty2() -> KProperty2Proxy(this, interpreter)
|
this.isKProperty1() -> KProperty1Proxy(this, interpreter)
|
||||||
this.isKMutableProperty2() -> KMutableProperty2Proxy(this, interpreter)
|
this.isKMutableProperty2() -> KMutableProperty2Proxy(this, interpreter)
|
||||||
|
this.isKProperty2() -> KProperty2Proxy(this, interpreter)
|
||||||
else -> TODO()
|
else -> TODO()
|
||||||
}
|
}
|
||||||
is KFunctionState -> KFunctionProxy(this, interpreter)
|
is KFunctionState -> KFunctionProxy(this, interpreter)
|
||||||
|
is KClassState -> KClassProxy(this, interpreter)
|
||||||
else -> TODO("not supported reference state")
|
else -> TODO("not supported reference state")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+110
-20
@@ -5,67 +5,146 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.ir.interpreter.state
|
package org.jetbrains.kotlin.ir.interpreter.state
|
||||||
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.descriptors.IrAbstractFunctionFactory
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrClassReference
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
|
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrPropertyReference
|
import org.jetbrains.kotlin.ir.expressions.IrPropertyReference
|
||||||
|
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
|
||||||
import org.jetbrains.kotlin.ir.interpreter.getLastOverridden
|
import org.jetbrains.kotlin.ir.interpreter.getLastOverridden
|
||||||
import org.jetbrains.kotlin.ir.interpreter.isFunction
|
import org.jetbrains.kotlin.ir.interpreter.proxy.Proxy
|
||||||
import org.jetbrains.kotlin.ir.interpreter.isKFunction
|
import org.jetbrains.kotlin.ir.interpreter.proxy.reflection.KFunctionProxy
|
||||||
|
import org.jetbrains.kotlin.ir.interpreter.proxy.reflection.KProperty1Proxy
|
||||||
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
|
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
|
||||||
|
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.util.defaultType
|
import org.jetbrains.kotlin.ir.util.defaultType
|
||||||
import org.jetbrains.kotlin.ir.util.nameForIrSerialization
|
import org.jetbrains.kotlin.ir.util.nameForIrSerialization
|
||||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||||
import org.jetbrains.kotlin.ir.util.render
|
import org.jetbrains.kotlin.ir.util.render
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||||
|
import kotlin.reflect.KCallable
|
||||||
|
import kotlin.reflect.KFunction
|
||||||
|
|
||||||
internal abstract class ReflectionState(override val irClass: IrClass) : State {
|
internal abstract class ReflectionState(override val irClass: IrClass) : State {
|
||||||
override val fields: MutableList<Variable> = mutableListOf()
|
override val fields: MutableList<Variable> = mutableListOf()
|
||||||
override val typeArguments: MutableList<Variable> = mutableListOf()
|
override val typeArguments: MutableList<Variable> = mutableListOf()
|
||||||
|
|
||||||
override fun getIrFunctionByIrCall(expression: IrCall): IrFunction? = null
|
override fun getIrFunctionByIrCall(expression: IrCall): IrFunction? = null
|
||||||
|
|
||||||
|
protected fun renderReceivers(dispatchReceiver: IrType?, extensionReceiver: IrType?): String {
|
||||||
|
return buildString {
|
||||||
|
if (dispatchReceiver != null) {
|
||||||
|
append(dispatchReceiver.render())
|
||||||
|
append(".")
|
||||||
|
}
|
||||||
|
val addParentheses = dispatchReceiver != null && extensionReceiver != null
|
||||||
|
if (addParentheses) append("(")
|
||||||
|
if (extensionReceiver != null) {
|
||||||
|
append(extensionReceiver.render())
|
||||||
|
append(".")
|
||||||
|
}
|
||||||
|
if (addParentheses) append(")")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class KClassState(override val irClass: IrClass) : ReflectionState(irClass) {
|
||||||
|
private var _members: Collection<KCallable<*>>? = null
|
||||||
|
private var _constructors: Collection<KFunction<Proxy>>? = null
|
||||||
|
|
||||||
|
constructor(classReference: IrClassReference) : this(classReference.symbol.owner as IrClass)
|
||||||
|
|
||||||
|
fun getMembers(interpreter: IrInterpreter): Collection<KCallable<*>> {
|
||||||
|
if (_members != null) return _members!!
|
||||||
|
_members = irClass.declarations
|
||||||
|
.filter { it !is IrClass && it !is IrConstructor }
|
||||||
|
.map {
|
||||||
|
when (it) {
|
||||||
|
is IrProperty -> KProperty1Proxy(KPropertyState(it, null, null), interpreter) // TODO KProperty2
|
||||||
|
is IrFunction -> KFunctionProxy(KFunctionState(it, interpreter.irBuiltIns.functionFactory), interpreter)
|
||||||
|
else -> TODO()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _members!!
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getConstructors(interpreter: IrInterpreter): Collection<KFunction<Proxy>> {
|
||||||
|
if (_constructors != null) return _constructors!!
|
||||||
|
_constructors = irClass.declarations
|
||||||
|
.filterIsInstance<IrConstructor>()
|
||||||
|
.map { KFunctionProxy(KFunctionState(it, interpreter.irBuiltIns.functionFactory), interpreter) as KFunction<Proxy> }
|
||||||
|
return _constructors!!
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class KPropertyState(
|
internal class KPropertyState(
|
||||||
val propertyReference: IrPropertyReference, val dispatchReceiver: State?, val extensionReceiver: State?
|
val property: IrProperty, val dispatchReceiver: State?, val extensionReceiver: State?
|
||||||
) : ReflectionState(propertyReference.symbol.owner.parentAsClass) {
|
) : ReflectionState(property.parentAsClass) {
|
||||||
val className = propertyReference.type.classOrNull?.owner?.name?.asString()
|
constructor(propertyReference: IrPropertyReference, dispatchReceiver: State?, extensionReceiver: State?)
|
||||||
|
: this(propertyReference.symbol.owner, dispatchReceiver, extensionReceiver)
|
||||||
|
|
||||||
fun isKProperty0(): Boolean {
|
fun isKProperty0(): Boolean {
|
||||||
return className == "KProperty0"
|
return dispatchReceiver != null && extensionReceiver == null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isKProperty1(): Boolean {
|
fun isKProperty1(): Boolean {
|
||||||
return className == "KProperty1"
|
return dispatchReceiver == null && extensionReceiver == null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isKProperty2(): Boolean {
|
fun isKProperty2(): Boolean {
|
||||||
return className == "KProperty2"
|
return dispatchReceiver != null && extensionReceiver != null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isKMutableProperty0(): Boolean {
|
fun isKMutableProperty0(): Boolean {
|
||||||
return className == "KMutableProperty0"
|
return isKProperty0() && property.isVar
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isKMutableProperty1(): Boolean {
|
fun isKMutableProperty1(): Boolean {
|
||||||
return className == "KMutableProperty1"
|
return isKProperty1() && property.isVar
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isKMutableProperty2(): Boolean {
|
fun isKMutableProperty2(): Boolean {
|
||||||
return className == "KMutableProperty2"
|
return isKProperty1() && property.isVar
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as KPropertyState
|
||||||
|
|
||||||
|
if (property != other.property) return false
|
||||||
|
if (dispatchReceiver != other.dispatchReceiver) return false
|
||||||
|
if (extensionReceiver != other.extensionReceiver) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = property.hashCode()
|
||||||
|
result = 31 * result + (dispatchReceiver?.hashCode() ?: 0)
|
||||||
|
result = 31 * result + (extensionReceiver?.hashCode() ?: 0)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
val prefix = if (property.isVar) "var" else "val"
|
||||||
|
val receivers = renderReceivers(property.getter?.dispatchReceiverParameter?.type, property.getter?.extensionReceiverParameter?.type)
|
||||||
|
val returnType = property.getter!!.returnType.render()
|
||||||
|
return "$prefix $receivers${property.name}: $returnType"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class KFunctionState(val irFunction: IrFunction, override val irClass: IrClass) : ReflectionState(irClass) {
|
internal class KFunctionState(val irFunction: IrFunction, override val irClass: IrClass) : ReflectionState(irClass) {
|
||||||
override val fields: MutableList<Variable> = mutableListOf()
|
override val fields: MutableList<Variable> = mutableListOf()
|
||||||
override val typeArguments: MutableList<Variable> = mutableListOf()
|
override val typeArguments: MutableList<Variable> = mutableListOf()
|
||||||
val isKFunction = irClass.defaultType.isKFunction()
|
|
||||||
val isFunction = irClass.defaultType.isFunction()
|
|
||||||
|
|
||||||
constructor(functionReference: IrFunctionReference) : this(functionReference.symbol.owner, functionReference.type.classOrNull!!.owner)
|
constructor(functionReference: IrFunctionReference) : this(functionReference.symbol.owner, functionReference.type.classOrNull!!.owner)
|
||||||
|
constructor(irFunction: IrFunction, functionFactory: IrAbstractFunctionFactory) :
|
||||||
|
this(irFunction, functionFactory.functionN(irFunction.valueParameters.size))
|
||||||
|
|
||||||
private val invokeSymbol = irClass.declarations
|
private val invokeSymbol = irClass.declarations
|
||||||
.single { it.nameForIrSerialization.asString() == "invoke" }
|
.single { it.nameForIrSerialization.asString() == "invoke" }
|
||||||
@@ -80,10 +159,21 @@ internal class KFunctionState(val irFunction: IrFunction, override val irClass:
|
|||||||
return if (invokeSymbol == expression.symbol) irFunction else null
|
return if (invokeSymbol == expression.symbol) irFunction else null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun isLambda(): Boolean = irFunction.name.let { it == Name.special("<anonymous>") || it == Name.special("<no name provided>") }
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
val receiver = (irFunction.dispatchReceiverParameter?.type ?: irFunction.extensionReceiverParameter?.type)?.render()
|
return if (isLambda()) {
|
||||||
val arguments = irFunction.valueParameters.joinToString(prefix = "(", postfix = ")") { it.type.render() }
|
val receiver = (irFunction.dispatchReceiverParameter?.type ?: irFunction.extensionReceiverParameter?.type)?.render()
|
||||||
val returnType = irFunction.returnType.render()
|
val arguments = irFunction.valueParameters.joinToString(prefix = "(", postfix = ")") { it.type.render() }
|
||||||
return ("$arguments -> $returnType").let { if (receiver != null) "$receiver.$it" else it }
|
val returnType = irFunction.returnType.render()
|
||||||
|
("$arguments -> $returnType").let { if (receiver != null) "$receiver.$it" else it }
|
||||||
|
} else {
|
||||||
|
val dispatchReceiver = irFunction.parentAsClass.defaultType // = instanceReceiverParameter
|
||||||
|
val extensionReceiver = irFunction.extensionReceiverParameter?.type
|
||||||
|
val receivers = if (irFunction is IrConstructor) "" else renderReceivers(dispatchReceiver, extensionReceiver)
|
||||||
|
val arguments = irFunction.valueParameters.joinToString(prefix = "(", postfix = ")") { it.type.render() }
|
||||||
|
val returnType = irFunction.returnType.render()
|
||||||
|
"fun $receivers${irFunction.name}$arguments: $returnType"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user