Implement basic interpretation for KProperty

This commit is contained in:
Ivan Kylchik
2020-09-13 15:07:38 +03:00
committed by TeamCityServer
parent c3d0438405
commit 41ea1525d1
9 changed files with 382 additions and 1 deletions
+2 -1
View File
@@ -4,7 +4,8 @@ plugins {
}
dependencies {
compile(project(":compiler:ir.tree"))
compileOnly(project(":compiler:ir.tree"))
compileOnly(project(":kotlin-reflect-api"))
}
sourceSets {
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.ir.interpreter.exceptions.*
import org.jetbrains.kotlin.ir.interpreter.intrinsics.IntrinsicEvaluator
import org.jetbrains.kotlin.ir.interpreter.proxy.CommonProxy.Companion.asProxy
import org.jetbrains.kotlin.ir.interpreter.proxy.Proxy
import org.jetbrains.kotlin.ir.interpreter.proxy.reflection.ReflectionProxy
import org.jetbrains.kotlin.ir.interpreter.proxy.wrap
import org.jetbrains.kotlin.ir.interpreter.stack.StackImpl
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
@@ -140,6 +141,7 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
is IrStringConcatenation -> interpretStringConcatenation(this)
is IrFunctionExpression -> interpretFunctionExpression(this)
is IrFunctionReference -> interpretFunctionReference(this)
is IrPropertyReference -> interpretPropertyReference(this)
is IrComposite -> interpretComposite(this)
else -> TODO("${this.javaClass} not supported")
@@ -317,6 +319,10 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
return@newFrame when {
dispatchReceiver is Wrapper && !isInlineOnly -> dispatchReceiver.getMethod(irFunction).invokeMethod(irFunction)
irFunction.hasAnnotation(evaluateIntrinsicAnnotation) -> Wrapper.getStaticMethod(irFunction).invokeMethod(irFunction)
dispatchReceiver is ReflectionState -> {
stack.pushReturnValue((dispatchReceiver.wrap(this) as ReflectionProxy).evaluate(expression, stack.getAll()))
Next
}
dispatchReceiver is Primitive<*> -> calculateBuiltIns(irFunction) // 'is Primitive' check for js char and js long
irFunction.body == null ->
irFunction.trySubstituteFunctionBody() ?: irFunction.tryCalculateLazyConst() ?: calculateBuiltIns(irFunction)
@@ -873,4 +879,12 @@ class IrInterpreter(private val irBuiltIns: IrBuiltIns, private val bodyMap: Map
else -> TODO("${expression.origin} not implemented")
}
}
private fun interpretPropertyReference(propertyReference: IrPropertyReference): ExecutionResult {
val dispatchReceiver = propertyReference.dispatchReceiver?.interpret()?.check { return it }?.let { stack.popReturnValue() }
val extensionReceiver = propertyReference.extensionReceiver?.interpret()?.check { return it }?.let { stack.popReturnValue() }
val propertyState = KPropertyState(propertyReference, dispatchReceiver, extensionReceiver)
stack.pushReturnValue(propertyState)
return Next
}
}
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.ir.interpreter.proxy
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
import org.jetbrains.kotlin.ir.interpreter.proxy.CommonProxy.Companion.asProxy
import org.jetbrains.kotlin.ir.interpreter.proxy.LambdaProxy.Companion.asProxy
import org.jetbrains.kotlin.ir.interpreter.proxy.reflection.ReflectionProxy.Companion.asProxy
import org.jetbrains.kotlin.ir.interpreter.state.*
internal interface Proxy {
@@ -29,6 +30,7 @@ internal fun State.wrap(interpreter: IrInterpreter, extendFrom: Class<*>? = null
is Primitive<*> -> this.value
is Common -> this.asProxy(interpreter, extendFrom, calledFromBuiltIns)
is Lambda -> this.asProxy(interpreter)
is ReflectionState -> this.asProxy(interpreter)
else -> throw AssertionError("${this::class} is unsupported as argument for wrap function")
}
}
@@ -0,0 +1,56 @@
/*
* 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.declarations.IrProperty
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
import org.jetbrains.kotlin.ir.interpreter.state.KPropertyState
import org.jetbrains.kotlin.ir.interpreter.state.State
import kotlin.reflect.KProperty
import kotlin.reflect.KType
import kotlin.reflect.KVisibility
internal abstract class AbstractKPropertyProxy(
override val state: KPropertyState, override val interpreter: IrInterpreter
) : ReflectionProxy, KProperty<State> {
private val propertyOwner: IrProperty
get() = state.propertyReference.symbol.owner
override val isAbstract: Boolean
get() = propertyOwner.modality == Modality.ABSTRACT
override val isConst: Boolean
get() = propertyOwner.isConst
override val isFinal: Boolean
get() = propertyOwner.modality == Modality.FINAL
override val isLateinit: Boolean
get() = propertyOwner.isLateinit
override val isOpen: Boolean
get() = propertyOwner.modality == Modality.OPEN
override val isSuspend: Boolean
get() = TODO("Not yet implemented")
override val name: String
get() = propertyOwner.name.asString()
override val annotations: List<Annotation>
get() = TODO("Not yet implemented")
override val returnType: KType
get() = TODO("Not yet implemented")
override val visibility: KVisibility?
get() = 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")
}
}
@@ -0,0 +1,74 @@
/*
* 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.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
import org.jetbrains.kotlin.ir.interpreter.state.KPropertyState
import org.jetbrains.kotlin.ir.interpreter.state.State
import org.jetbrains.kotlin.ir.interpreter.toState
import kotlin.reflect.*
internal open class KProperty0Proxy(
override val state: KPropertyState, override val interpreter: IrInterpreter
) : AbstractKPropertyProxy(state, interpreter), KProperty0<State> {
override fun evaluate(expression: IrCall, args: List<Variable>): State {
val result: Any = when (expression.symbol.owner.name.asString()) {
"<get-name>" -> name
"get" -> get()
"invoke" -> invoke()
else -> TODO("not supported expression for kProperty0")
}
return result.toState(expression.type)
}
override val getter: KProperty0.Getter<State>
get() = TODO("Not yet implemented")
override val parameters: List<KParameter>
get() = TODO("Not yet implemented")
override val typeParameters: List<KTypeParameter>
get() = TODO("Not yet implemented")
override fun call(vararg args: Any?): State {
TODO("Not yet implemented")
}
override fun callBy(args: Map<KParameter, Any?>): State {
TODO("Not yet implemented")
}
override fun get(): State {
return state.dispatchReceiver!!.getState(state.propertyReference.symbol)!!
}
override fun getDelegate(): Any? {
TODO("Not yet implemented")
}
override fun invoke(): State = get()
}
internal class KMutableProperty0Proxy(
override val state: KPropertyState, override val interpreter: IrInterpreter
) : KProperty0Proxy(state, interpreter), KMutableProperty0<State> {
override fun evaluate(expression: IrCall, args: List<Variable>): State {
val result: Any = when (expression.symbol.owner.name.asString()) {
"set" -> set(args[1].state)
else -> return super.evaluate(expression, args)
}
return result.toState(expression.type)
}
override val setter: KMutableProperty0.Setter<State>
get() = TODO("Not yet implemented")
override fun set(value: State) {
state.dispatchReceiver!!.setField(Variable(state.propertyReference.symbol, value))
}
}
@@ -0,0 +1,74 @@
/*
* 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.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
import org.jetbrains.kotlin.ir.interpreter.state.KPropertyState
import org.jetbrains.kotlin.ir.interpreter.state.State
import org.jetbrains.kotlin.ir.interpreter.toState
import kotlin.reflect.*
internal open class KProperty1Proxy(
override val state: KPropertyState, override val interpreter: IrInterpreter
) : AbstractKPropertyProxy(state, interpreter), KProperty1<State, State> {
override fun evaluate(expression: IrCall, args: List<Variable>): State {
val result: Any = when (expression.symbol.owner.name.asString()) {
"<get-name>" -> name
"get" -> get(args[1].state)
"invoke" -> invoke(args[1].state)
else -> TODO("not supported expression for kProperty0")
}
return result.toState(expression.type)
}
override val getter: KProperty1.Getter<State, State>
get() = TODO("Not yet implemented")
override val parameters: List<KParameter>
get() = TODO("Not yet implemented")
override val typeParameters: List<KTypeParameter>
get() = TODO("Not yet implemented")
override fun call(vararg args: Any?): State {
TODO("Not yet implemented")
}
override fun callBy(args: Map<KParameter, Any?>): State {
TODO("Not yet implemented")
}
override fun get(receiver: State): State {
return receiver.getState(state.propertyReference.symbol)!!
}
override fun getDelegate(receiver: State): Any? {
TODO("Not yet implemented")
}
override fun invoke(p1: State): State = get(p1)
}
internal class KMutableProperty1Proxy(
override val state: KPropertyState, override val interpreter: IrInterpreter
) : KProperty1Proxy(state, interpreter), KMutableProperty1<State, State> {
override fun evaluate(expression: IrCall, args: List<Variable>): State {
val result: Any = when (expression.symbol.owner.name.asString()) {
"set" -> set(args[1].state, args[2].state)
else -> return super.evaluate(expression, args)
}
return result.toState(expression.type)
}
override val setter: KMutableProperty1.Setter<State, State>
get() = TODO("Not yet implemented")
override fun set(receiver: State, value: State) {
receiver.setField(Variable(state.propertyReference.symbol, value))
}
}
@@ -0,0 +1,74 @@
/*
* 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.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
import org.jetbrains.kotlin.ir.interpreter.state.KPropertyState
import org.jetbrains.kotlin.ir.interpreter.state.State
import org.jetbrains.kotlin.ir.interpreter.toState
import kotlin.reflect.*
internal open class KProperty2Proxy(
override val state: KPropertyState, override val interpreter: IrInterpreter
) : AbstractKPropertyProxy(state, interpreter), KProperty2<State, State, State> {
override fun evaluate(expression: IrCall, args: List<Variable>): State {
val result: Any = when (expression.symbol.owner.name.asString()) {
"<get-name>" -> name
//"get" -> get()
//"invoke" -> invoke()
else -> TODO("not supported expression for kProperty0")
}
return result.toState(expression.type)
}
override val getter: KProperty2.Getter<State, State, State>
get() = TODO("Not yet implemented")
override val parameters: List<KParameter>
get() = TODO("Not yet implemented")
override val typeParameters: List<KTypeParameter>
get() = TODO("Not yet implemented")
override fun call(vararg args: Any?): State {
TODO("Not yet implemented")
}
override fun callBy(args: Map<KParameter, Any?>): State {
TODO("Not yet implemented")
}
override fun get(receiver1: State, receiver2: State): State {
TODO("Not yet implemented")
}
override fun getDelegate(receiver1: State, receiver2: State): Any? {
TODO("Not yet implemented")
}
override fun invoke(p1: State, p2: State): State = get(p1, p2)
}
internal class KMutableProperty2Proxy(
override val state: KPropertyState, override val interpreter: IrInterpreter
) : KProperty2Proxy(state, interpreter), KMutableProperty2<State, State, State> {
override fun evaluate(expression: IrCall, args: List<Variable>): State {
val result: Any = when (expression.symbol.owner.name.asString()) {
//"set" -> set()
else -> return super.evaluate(expression, args)
}
return result.toState(expression.type)
}
override val setter: KMutableProperty2.Setter<State, State, State>
get() = TODO("Not yet implemented")
override fun set(receiver1: State, receiver2: State, value: State) {
TODO("Not yet implemented")
}
}
@@ -0,0 +1,35 @@
/*
* 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.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
import org.jetbrains.kotlin.ir.interpreter.proxy.Proxy
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
import org.jetbrains.kotlin.ir.interpreter.state.KPropertyState
import org.jetbrains.kotlin.ir.interpreter.state.ReflectionState
import org.jetbrains.kotlin.ir.interpreter.state.State
internal interface ReflectionProxy : Proxy {
fun evaluate(expression: IrCall, args: List<Variable>): State
companion object {
internal fun ReflectionState.asProxy(interpreter: IrInterpreter): ReflectionProxy {
return when {
this is KPropertyState -> when {
this.isKProperty0() -> KProperty0Proxy(this, interpreter)
this.isKMutableProperty0() -> KMutableProperty0Proxy(this, interpreter)
this.isKProperty1() -> KProperty1Proxy(this, interpreter)
this.isKMutableProperty1() -> KMutableProperty1Proxy(this, interpreter)
this.isKProperty2() -> KProperty2Proxy(this, interpreter)
this.isKMutableProperty2() -> KMutableProperty2Proxy(this, interpreter)
else -> TODO()
}
else -> TODO("not supported reference state")
}
}
}
}
@@ -0,0 +1,51 @@
/*
* 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.state
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrPropertyReference
import org.jetbrains.kotlin.ir.interpreter.stack.Variable
import org.jetbrains.kotlin.ir.types.classOrNull
import org.jetbrains.kotlin.ir.util.parentAsClass
internal abstract class ReflectionState(override val irClass: IrClass) : State {
override val fields: MutableList<Variable> = mutableListOf()
override val typeArguments: MutableList<Variable> = mutableListOf()
override fun getIrFunctionByIrCall(expression: IrCall): IrFunction? = null
}
internal class KPropertyState(
val propertyReference: IrPropertyReference, val dispatchReceiver: State?, val extensionReceiver: State?
) : ReflectionState(propertyReference.symbol.owner.parentAsClass) {
val className = propertyReference.type.classOrNull?.owner?.name?.asString()
fun isKProperty0(): Boolean {
return className == "KProperty0"
}
fun isKProperty1(): Boolean {
return className == "KProperty1"
}
fun isKProperty2(): Boolean {
return className == "KProperty2"
}
fun isKMutableProperty0(): Boolean {
return className == "KMutableProperty0"
}
fun isKMutableProperty1(): Boolean {
return className == "KMutableProperty1"
}
fun isKMutableProperty2(): Boolean {
return className == "KMutableProperty2"
}
}