Add abstract classes and interfaces support in interpreter
This commit is contained in:
+42
-38
@@ -7,20 +7,18 @@ package org.jetbrains.kotlin.backend.common.interpreter
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.interpreter.stack.*
|
import org.jetbrains.kotlin.backend.common.interpreter.stack.*
|
||||||
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.util.isFakeOverride
|
|
||||||
import org.jetbrains.kotlin.ir.util.statements
|
import org.jetbrains.kotlin.ir.util.statements
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||||
|
|
||||||
class IrInterpreter : IrElementVisitor<State, Frame> {
|
class IrInterpreter : IrElementVisitor<State, Frame> {
|
||||||
private val builtIns = DefaultBuiltIns.Instance
|
private val builtIns = DefaultBuiltIns.Instance
|
||||||
private val unit = Complex(builtIns.unit, mutableListOf())
|
private val empty = EmptyState()
|
||||||
private val any = Complex(builtIns.any, mutableListOf())
|
|
||||||
|
|
||||||
fun interpret(expression: IrExpression): IrExpression {
|
fun interpret(expression: IrExpression): IrExpression {
|
||||||
return visitExpression(expression, InterpreterFrame()).convertToIrExpression(expression)
|
return visitExpression(expression, InterpreterFrame()).convertToIrExpression(expression)
|
||||||
@@ -50,26 +48,28 @@ class IrInterpreter : IrElementVisitor<State, Frame> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitCall(expression: IrCall, data: Frame): State {
|
override fun visitCall(expression: IrCall, data: Frame): State {
|
||||||
val newFrame = InterpreterFrame() // it is important firstly to add receiver, then arguments
|
val newFrame = InterpreterFrame()
|
||||||
val valueParameters = convertValueParameters(expression, data)
|
val valueParameters = convertValueParameters(expression, data)
|
||||||
|
|
||||||
if (expression.symbol.owner.isFakeOverride) {
|
val dispatchReceiver = expression.dispatchReceiver?.accept(this, data) // can be either Primitive or Complex
|
||||||
expression.dispatchReceiver?.accept(this, data)?.let { newFrame.addVar(it) }
|
val extensionReceiver = expression.extensionReceiver?.accept(this, data) // similarly
|
||||||
newFrame.addAll(valueParameters)
|
|
||||||
return calculateOverridden(expression.symbol, newFrame)
|
|
||||||
}
|
|
||||||
|
|
||||||
val dispatchReceiver = expression.dispatchReceiver?.accept(this, data)
|
// it is important firstly to add receiver, then arguments
|
||||||
?.setDescriptor(expression.symbol.descriptor.dispatchReceiverParameter!!)
|
val receiverParameter = (expression.symbol.descriptor.dispatchReceiverParameter ?: expression.symbol.descriptor.extensionReceiverParameter)
|
||||||
val extensionReceiver = expression.extensionReceiver?.accept(this, data)
|
when (val receiver = (dispatchReceiver ?: extensionReceiver)) {
|
||||||
?.setDescriptor(expression.symbol.descriptor.extensionReceiverParameter!!)
|
// if receiver is complex then frame will contain receiver and its supers as raw list (not tree)
|
||||||
(dispatchReceiver ?: extensionReceiver)?.also { newFrame.addVar(it) }
|
// this is necessary because it is hard to instantly say that receiver will be used; for example, in abstract methods
|
||||||
|
is Complex -> newFrame.addAll(receiver.getAllStates())
|
||||||
|
else -> receiver?.let { newFrame.addVar(Variable(receiverParameter!!, it)) }
|
||||||
|
}
|
||||||
newFrame.addAll(valueParameters)
|
newFrame.addAll(valueParameters)
|
||||||
|
|
||||||
return if (expression.getBody() == null) {
|
val irFunction = (dispatchReceiver as? Complex)?.getIrFunctionByName(expression.symbol.descriptor.name)
|
||||||
calculateBuiltIns(expression.symbol.descriptor, newFrame).toIrConst(expression).toPrimitive()
|
return when {
|
||||||
} else {
|
expression.isAbstract() -> calculateAbstract(irFunction, newFrame) //abstract check must be first
|
||||||
expression.getBody()!!.accept(this, newFrame)
|
expression.isFakeOverridden() -> calculateOverridden(irFunction!!.symbol, newFrame)
|
||||||
|
expression.getBody() == null -> calculateBuiltIns(expression.symbol.descriptor, newFrame).toIrConst(expression).toPrimitive()
|
||||||
|
else -> expression.getBody()!!.accept(this, newFrame)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,12 +79,16 @@ class IrInterpreter : IrElementVisitor<State, Frame> {
|
|||||||
|
|
||||||
private fun visitConstructor(constructor: IrFunctionAccessExpression, data: Frame): State {
|
private fun visitConstructor(constructor: IrFunctionAccessExpression, data: Frame): State {
|
||||||
val newFrame = InterpreterFrame(convertValueParameters(constructor, data))
|
val newFrame = InterpreterFrame(convertValueParameters(constructor, data))
|
||||||
val obj = Complex((constructor.symbol.descriptor.containingDeclaration as ClassDescriptor).thisAsReceiverParameter, mutableListOf())
|
val obj = Complex(constructor.symbol.owner.parent as IrClass, mutableListOf())
|
||||||
constructor.getBody()?.statements?.forEach {
|
constructor.getBody()?.statements?.forEach {
|
||||||
when (it) {
|
when (it) {
|
||||||
is IrDelegatingConstructorCall -> {
|
is IrDelegatingConstructorCall -> {
|
||||||
obj.addSuperQualifier(visitDelegatingConstructorCall(it, newFrame) as Complex)
|
val delegatingConstructorCall = visitDelegatingConstructorCall(it, newFrame)
|
||||||
newFrame.addVar(obj)
|
if (delegatingConstructorCall != empty) {
|
||||||
|
val superObj = Variable(it.symbol.descriptor.containingDeclaration.thisAsReceiverParameter, delegatingConstructorCall)
|
||||||
|
obj.addSuperQualifier(superObj)
|
||||||
|
}
|
||||||
|
newFrame.addVar(Variable(constructor.getThisAsReceiver(), obj))
|
||||||
}
|
}
|
||||||
else -> it.accept(this, newFrame)
|
else -> it.accept(this, newFrame)
|
||||||
}
|
}
|
||||||
@@ -98,7 +102,7 @@ class IrInterpreter : IrElementVisitor<State, Frame> {
|
|||||||
|
|
||||||
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall, data: Frame): State {
|
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall, data: Frame): State {
|
||||||
if (expression.symbol.descriptor.containingDeclaration.defaultType == builtIns.anyType) {
|
if (expression.symbol.descriptor.containingDeclaration.defaultType == builtIns.anyType) {
|
||||||
return any
|
return empty
|
||||||
}
|
}
|
||||||
|
|
||||||
return visitConstructor(expression, data)
|
return visitConstructor(expression, data)
|
||||||
@@ -113,7 +117,7 @@ class IrInterpreter : IrElementVisitor<State, Frame> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// unreachable state; method must return inside forEach
|
// unreachable state; method must return inside forEach
|
||||||
return unit
|
return empty
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitReturn(expression: IrReturn, data: Frame): State {
|
override fun visitReturn(expression: IrReturn, data: Frame): State {
|
||||||
@@ -121,37 +125,37 @@ class IrInterpreter : IrElementVisitor<State, Frame> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitSetField(expression: IrSetField, data: Frame): State {
|
override fun visitSetField(expression: IrSetField, data: Frame): State {
|
||||||
val value = expression.value.accept(this, data).setDescriptor(expression.symbol.owner.descriptor)
|
val value = expression.value.accept(this, data)
|
||||||
val receiver = (expression.receiver as IrDeclarationReference).symbol.descriptor
|
val receiver = (expression.receiver as IrDeclarationReference).symbol.descriptor
|
||||||
data.getVar(receiver).setState(value)
|
data.getVariableState(receiver).setState(Variable(expression.symbol.owner.descriptor, value))
|
||||||
return unit
|
return empty
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitGetField(expression: IrGetField, data: Frame): State {
|
override fun visitGetField(expression: IrGetField, data: Frame): State {
|
||||||
val receiver = (expression.receiver as? IrDeclarationReference)?.symbol?.descriptor // receiver is null, for example, for top level fields
|
val receiver = (expression.receiver as? IrDeclarationReference)?.symbol?.descriptor // receiver is null, for example, for top level fields
|
||||||
?: return expression.symbol.owner.initializer!!.expression.accept(this, data)
|
?: return expression.symbol.owner.initializer!!.expression.accept(this, data)
|
||||||
return data.getVar(receiver).getState(expression.symbol.descriptor).copy()
|
return data.getVariableState(receiver).getState(expression.symbol.descriptor).copy()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitGetValue(expression: IrGetValue, data: Frame): State {
|
override fun visitGetValue(expression: IrGetValue, data: Frame): State {
|
||||||
return data.getVar(expression.symbol.descriptor).copy()
|
return data.getVariableState(expression.symbol.descriptor).copy()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitVariable(declaration: IrVariable, data: Frame): State {
|
override fun visitVariable(declaration: IrVariable, data: Frame): State {
|
||||||
val variable = declaration.initializer?.accept(this, data)?.setDescriptor(declaration.descriptor)
|
val variable = declaration.initializer?.accept(this, data)
|
||||||
variable?.let { data.addVar(it) }
|
variable?.let { data.addVar(Variable(declaration.descriptor, it)) }
|
||||||
return unit
|
return empty
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitSetVariable(expression: IrSetVariable, data: Frame): State {
|
override fun visitSetVariable(expression: IrSetVariable, data: Frame): State {
|
||||||
if (data.contains(expression.symbol.descriptor)) {
|
if (data.contains(expression.symbol.descriptor)) {
|
||||||
val variable = data.getVar(expression.symbol.descriptor)
|
val variable = data.getVariableState(expression.symbol.descriptor)
|
||||||
variable.setState(expression.value.accept(this, data))
|
variable.setState(Variable(expression.symbol.descriptor, expression.value.accept(this, data)))
|
||||||
} else {
|
} else {
|
||||||
val variable = expression.value.accept(this, data).setDescriptor(expression.symbol.descriptor)
|
val variable = expression.value.accept(this, data)
|
||||||
data.addVar(variable)
|
data.addVar(Variable(expression.symbol.descriptor, variable))
|
||||||
}
|
}
|
||||||
return unit
|
return empty
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitWhen(expression: IrWhen, data: Frame): State {
|
override fun visitWhen(expression: IrWhen, data: Frame): State {
|
||||||
@@ -160,6 +164,6 @@ class IrInterpreter : IrElementVisitor<State, Frame> {
|
|||||||
return it.result.accept(this, data)
|
return it.result.accept(this, data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return unit
|
return empty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+28
-10
@@ -8,26 +8,27 @@ package org.jetbrains.kotlin.backend.common.interpreter
|
|||||||
import org.jetbrains.kotlin.backend.common.interpreter.builtins.CompileTimeFunction
|
import org.jetbrains.kotlin.backend.common.interpreter.builtins.CompileTimeFunction
|
||||||
import org.jetbrains.kotlin.backend.common.interpreter.builtins.binaryFunctions
|
import org.jetbrains.kotlin.backend.common.interpreter.builtins.binaryFunctions
|
||||||
import org.jetbrains.kotlin.backend.common.interpreter.builtins.unaryFunctions
|
import org.jetbrains.kotlin.backend.common.interpreter.builtins.unaryFunctions
|
||||||
import org.jetbrains.kotlin.backend.common.interpreter.stack.Frame
|
import org.jetbrains.kotlin.backend.common.interpreter.stack.*
|
||||||
import org.jetbrains.kotlin.backend.common.interpreter.stack.InterpreterFrame
|
|
||||||
import org.jetbrains.kotlin.backend.common.interpreter.stack.Primitive
|
|
||||||
import org.jetbrains.kotlin.backend.common.interpreter.stack.State
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.util.isFakeOverride
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
|
|
||||||
fun IrInterpreter.calculateOverridden(symbol: IrFunctionSymbol, data: Frame): State {
|
fun IrInterpreter.calculateOverridden(symbol: IrFunctionSymbol, data: Frame): State {
|
||||||
val owner = symbol.owner as IrFunctionImpl
|
val owner = symbol.owner as IrFunctionImpl
|
||||||
val overridden = owner.overriddenSymbols.first()
|
val overridden = owner.overriddenSymbols.first()
|
||||||
val overriddenReceiver = data.getVar(symbol.getThisAsReceiver()).getState(overridden.getThisAsReceiver())
|
val overriddenReceiver = data.getVariableState(symbol.getThisAsReceiver()).getState(overridden.getThisAsReceiver())
|
||||||
val valueParameters = symbol.owner.valueParameters.zip(overridden.owner.valueParameters)
|
val valueParameters = symbol.owner.valueParameters.zip(overridden.owner.valueParameters)
|
||||||
.map { data.getVar(it.first.descriptor).setDescriptor(it.second.descriptor) }
|
.map { Variable(it.second.descriptor, data.getVariableState(it.first.descriptor)) }
|
||||||
val newStates = InterpreterFrame((valueParameters + overriddenReceiver).toMutableList())
|
val newStates = InterpreterFrame((valueParameters + Variable(overridden.getThisAsReceiver(), overriddenReceiver)).toMutableList())
|
||||||
|
|
||||||
return if (overridden.owner.body != null) {
|
return if (overridden.owner.body != null) {
|
||||||
overridden.owner.body!!.accept(this, newStates)
|
overridden.owner.body!!.accept(this, newStates)
|
||||||
@@ -41,6 +42,7 @@ fun calculateBuiltIns(descriptor: FunctionDescriptor, frame: Frame): Any {
|
|||||||
val receiverType = descriptor.dispatchReceiverParameter?.type ?: descriptor.extensionReceiverParameter?.type
|
val receiverType = descriptor.dispatchReceiverParameter?.type ?: descriptor.extensionReceiverParameter?.type
|
||||||
val argsType = listOfNotNull(receiverType) + descriptor.valueParameters.map { TypeUtils.makeNotNullable(it.original.type) }
|
val argsType = listOfNotNull(receiverType) + descriptor.valueParameters.map { TypeUtils.makeNotNullable(it.original.type) }
|
||||||
val argsValues = frame.getAll()
|
val argsValues = frame.getAll()
|
||||||
|
.map { it.state }
|
||||||
.map { it as? Primitive<*> ?: throw IllegalArgumentException("Builtin functions accept only const args") }
|
.map { it as? Primitive<*> ?: throw IllegalArgumentException("Builtin functions accept only const args") }
|
||||||
.map { it.getIrConst().value }
|
.map { it.getIrConst().value }
|
||||||
val signature = CompileTimeFunction(methodName, argsType.map { it.toString() })
|
val signature = CompileTimeFunction(methodName, argsType.map { it.toString() })
|
||||||
@@ -59,11 +61,15 @@ fun calculateBuiltIns(descriptor: FunctionDescriptor, frame: Frame): Any {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun IrInterpreter.convertValueParameters(memberAccess: IrMemberAccessExpression, data: Frame): MutableList<State> {
|
fun IrInterpreter.calculateAbstract(irFunction: IrFunction?, data: Frame): State {
|
||||||
return mutableListOf<State>().apply {
|
return irFunction?.body?.accept(this, data)!!
|
||||||
|
}
|
||||||
|
|
||||||
|
fun IrInterpreter.convertValueParameters(memberAccess: IrMemberAccessExpression, data: Frame): MutableList<Variable> {
|
||||||
|
return mutableListOf<Variable>().apply {
|
||||||
for (i in 0 until memberAccess.valueArgumentsCount) {
|
for (i in 0 until memberAccess.valueArgumentsCount) {
|
||||||
val arg = memberAccess.getValueArgument(i)?.accept(this@convertValueParameters, data)
|
val arg = memberAccess.getValueArgument(i)?.accept(this@convertValueParameters, data)
|
||||||
arg?.setDescriptor((memberAccess.symbol.descriptor as FunctionDescriptor).valueParameters[i])?.let { this += it }
|
arg?.let { add(Variable((memberAccess.symbol.descriptor as FunctionDescriptor).valueParameters[i], it)) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -72,10 +78,22 @@ fun IrFunctionSymbol.getThisAsReceiver(): ReceiverParameterDescriptor {
|
|||||||
return (this.descriptor.containingDeclaration as ClassDescriptor).thisAsReceiverParameter
|
return (this.descriptor.containingDeclaration as ClassDescriptor).thisAsReceiverParameter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun IrFunctionAccessExpression.getThisAsReceiver(): ReceiverParameterDescriptor {
|
||||||
|
return (this.symbol.descriptor.containingDeclaration as ClassDescriptor).thisAsReceiverParameter
|
||||||
|
}
|
||||||
|
|
||||||
fun IrFunctionAccessExpression.getBody(): IrBody? {
|
fun IrFunctionAccessExpression.getBody(): IrBody? {
|
||||||
return this.symbol.owner.body
|
return this.symbol.owner.body
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun IrCall.isAbstract(): Boolean {
|
||||||
|
return (this.symbol.owner as? IrSimpleFunction)?.modality == Modality.ABSTRACT
|
||||||
|
}
|
||||||
|
|
||||||
|
fun IrCall.isFakeOverridden(): Boolean {
|
||||||
|
return this.symbol.owner.isFakeOverride
|
||||||
|
}
|
||||||
|
|
||||||
fun Any?.toIrConst(expression: IrExpression): IrConst<*> {
|
fun Any?.toIrConst(expression: IrExpression): IrConst<*> {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
is Boolean -> expression.copyParametersTo(IrConstKind.Boolean, this)
|
is Boolean -> expression.copyParametersTo(IrConstKind.Boolean, this)
|
||||||
|
|||||||
+26
-15
@@ -6,35 +6,46 @@
|
|||||||
package org.jetbrains.kotlin.backend.common.interpreter.stack
|
package org.jetbrains.kotlin.backend.common.interpreter.stack
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import java.util.NoSuchElementException
|
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
data class Variable(val descriptor: DeclarationDescriptor, val state: State) {
|
||||||
|
override fun toString(): String {
|
||||||
|
val descriptorName = when (descriptor) {
|
||||||
|
is ReceiverParameterDescriptor -> descriptor.containingDeclaration.name.toString() + "::this"
|
||||||
|
else -> descriptor.name
|
||||||
|
}
|
||||||
|
return "Variable(descriptor=$descriptorName, state=$state)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
interface Frame {
|
interface Frame {
|
||||||
fun addVar(state: State)
|
fun addVar(variable: Variable)
|
||||||
fun addAll(states: List<State>)
|
fun addAll(variables: List<Variable>)
|
||||||
fun getVar(descriptor: DeclarationDescriptor): State
|
fun getVariableState(variableDescriptor: DeclarationDescriptor): State
|
||||||
fun getAll(): List<State>
|
fun getAll(): List<Variable>
|
||||||
fun contains(descriptor: DeclarationDescriptor): Boolean
|
fun contains(descriptor: DeclarationDescriptor): Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
class InterpreterFrame(val pool: MutableList<State> = mutableListOf()) : Frame {
|
class InterpreterFrame(val pool: MutableList<Variable> = mutableListOf()) : Frame {
|
||||||
override fun addVar(state: State) {
|
override fun addVar(variable: Variable) {
|
||||||
pool.add(state)
|
pool.add(variable)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addAll(states: List<State>) {
|
override fun addAll(variables: List<Variable>) {
|
||||||
pool.addAll(states)
|
pool.addAll(variables)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getVar(descriptor: DeclarationDescriptor): State {
|
override fun getVariableState(variableDescriptor: DeclarationDescriptor): State {
|
||||||
return pool.firstOrNull { it.isTypeOf(descriptor) }
|
return pool.firstOrNull { it.descriptor == variableDescriptor }?.state
|
||||||
?: throw NoSuchElementException("Frame pool doesn't contains variable with descriptor $descriptor")
|
?: throw NoSuchElementException("Frame pool doesn't contains variable with descriptor $variableDescriptor")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getAll(): List<State> {
|
override fun getAll(): List<Variable> {
|
||||||
return pool
|
return pool
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun contains(descriptor: DeclarationDescriptor): Boolean {
|
override fun contains(descriptor: DeclarationDescriptor): Boolean {
|
||||||
return pool.any { it.isTypeOf(descriptor) }
|
return pool.any { it.descriptor == descriptor }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+59
-59
@@ -6,100 +6,100 @@
|
|||||||
package org.jetbrains.kotlin.backend.common.interpreter.stack
|
package org.jetbrains.kotlin.backend.common.interpreter.stack
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrConst
|
import org.jetbrains.kotlin.ir.expressions.IrConst
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||||
|
import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
fun getState(descriptor: DeclarationDescriptor): State
|
fun getState(descriptor: DeclarationDescriptor): State
|
||||||
fun setState(newState: State)
|
fun setState(newVar: Variable)
|
||||||
fun getDescriptor(): DeclarationDescriptor
|
|
||||||
fun setDescriptor(descriptor: DeclarationDescriptor): State
|
|
||||||
fun isTypeOf(descriptor: DeclarationDescriptor): Boolean
|
|
||||||
fun copy(): State
|
fun copy(): State
|
||||||
}
|
}
|
||||||
|
|
||||||
class Primitive<T>(private var value: IrConst<T>) : State {
|
class Primitive<T>(private var value: IrConst<T>) : State {
|
||||||
private lateinit var declarationDescriptor: DeclarationDescriptor
|
|
||||||
|
|
||||||
constructor(descriptor: DeclarationDescriptor, value: IrConst<T>) : this(value) {
|
|
||||||
declarationDescriptor = descriptor
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getIrConst(): IrConst<T> {
|
fun getIrConst(): IrConst<T> {
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getState(descriptor: DeclarationDescriptor): State {
|
override fun getState(descriptor: DeclarationDescriptor): State {
|
||||||
return when (descriptor) {
|
throw UnsupportedOperationException("Only complex are allowed")
|
||||||
this.declarationDescriptor -> this
|
|
||||||
else -> throw IllegalAccessException("Can't get descriptor $descriptor from $this")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setState(newState: State) {
|
override fun setState(newVar: Variable) {
|
||||||
newState as? Primitive<T> ?: throw IllegalArgumentException("Cannot set $newState in current $this")
|
newVar.state as? Primitive<T> ?: throw IllegalArgumentException("Cannot set $newVar in current $this")
|
||||||
value = newState.value
|
value = newVar.state.value
|
||||||
}
|
|
||||||
|
|
||||||
override fun getDescriptor(): DeclarationDescriptor {
|
|
||||||
return declarationDescriptor
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setDescriptor(descriptor: DeclarationDescriptor): State {
|
|
||||||
declarationDescriptor = descriptor
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun isTypeOf(descriptor: DeclarationDescriptor): Boolean {
|
|
||||||
return declarationDescriptor == descriptor
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun copy(): State {
|
override fun copy(): State {
|
||||||
return Primitive(declarationDescriptor, value)
|
return Primitive(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "Primitive(varName='${declarationDescriptor.name}', value=${value.value})"
|
return "Primitive(value=${value.value})"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class Complex(private var declarationDescriptor: DeclarationDescriptor, private val values: MutableList<State>) : State {
|
class Complex(private var classOfObject: IrClass, private val values: MutableList<Variable>) : State {
|
||||||
private val superQualifiers = mutableListOf<Complex>()
|
fun addSuperQualifier(superObj: Variable) {
|
||||||
|
val superTypesList = getSuperTypes(classOfObject).map { it.descriptor.thisAsReceiverParameter }
|
||||||
|
(superObj.state as? Complex)?.values?.filter { superTypesList.contains(it.descriptor) }?.let { values += it }
|
||||||
|
values += superObj
|
||||||
|
}
|
||||||
|
|
||||||
public fun addSuperQualifier(superObj: Complex) {
|
private fun getSuperTypes(descriptor: IrClass): List<IrClassSymbol> {
|
||||||
superQualifiers += superObj.superQualifiers
|
val superTypesList = descriptor.superTypes.mapNotNull { it.classOrNull }.toMutableList()
|
||||||
superQualifiers += superObj
|
return superTypesList + superTypesList.flatMap { getSuperTypes(it.owner) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getIrFunctionByName(name: Name): IrFunction {
|
||||||
|
return classOfObject.declarations.firstOrNull { it.descriptor.name == name } as? IrFunction
|
||||||
|
?: throw NoSuchMethodException("Abstract method $name has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAllStates(): List<Variable> {
|
||||||
|
val superTypesList = getSuperTypes(classOfObject).map { it.descriptor.thisAsReceiverParameter }
|
||||||
|
return values.filter { superTypesList.contains(it.descriptor) } + Variable(classOfObject.descriptor.thisAsReceiverParameter, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getState(descriptor: DeclarationDescriptor): State {
|
override fun getState(descriptor: DeclarationDescriptor): State {
|
||||||
return (values + superQualifiers).first { it.getDescriptor() == descriptor }
|
return values.firstOrNull { it.descriptor == descriptor }?.state
|
||||||
|
?: throw NoSuchElementException("Complex object doesn't contains state with descriptor $descriptor")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setState(newState: State) {
|
override fun setState(newVar: Variable) {
|
||||||
val oldState = values.firstOrNull { it.getDescriptor() == newState.getDescriptor() }
|
when (val oldState = values.firstOrNull { it.descriptor == newVar.descriptor }) {
|
||||||
if (oldState == null) {
|
null -> values.add(newVar) // newVar isn't present in value list
|
||||||
values.add(newState)
|
else -> values[values.indexOf(oldState)] = newVar // newVar already present
|
||||||
} else {
|
|
||||||
values[values.indexOf(oldState)] = newState
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getDescriptor(): DeclarationDescriptor {
|
|
||||||
return declarationDescriptor
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setDescriptor(descriptor: DeclarationDescriptor): State {
|
|
||||||
declarationDescriptor = descriptor
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun isTypeOf(descriptor: DeclarationDescriptor): Boolean {
|
|
||||||
return (superQualifiers + this).any { it.declarationDescriptor == descriptor }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun copy(): State {
|
override fun copy(): State {
|
||||||
return Complex(declarationDescriptor, values).apply { this.superQualifiers += this@Complex.superQualifiers }
|
return Complex(classOfObject, values)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "Complex(obj='$declarationDescriptor', super=$superQualifiers, values=$values)"
|
return "Complex(obj='${classOfObject.fqNameForIrSerialization}', values=$values)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class EmptyState : State {
|
||||||
|
override fun getState(descriptor: DeclarationDescriptor): State {
|
||||||
|
throw UnsupportedOperationException("Get state is not supported in empty state object")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setState(newVar: Variable) {
|
||||||
|
throw UnsupportedOperationException("Set state is not supported in empty state object")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun copy(): State {
|
||||||
|
throw UnsupportedOperationException("Copy method is not supported in empty state object")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return "EmptyState"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user