Add variables support in interpreter
This commit is contained in:
+21
-3
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.util.isFakeOverride
|
||||
import org.jetbrains.kotlin.ir.util.statements
|
||||
@@ -22,12 +23,12 @@ class IrInterpreter : IrElementVisitor<State, Frame> {
|
||||
private val any = Complex(builtIns.any, mutableListOf())
|
||||
|
||||
fun interpret(expression: IrExpression): IrExpression {
|
||||
return visitExpression(expression, InterpreterFrame()).toIrExpression()
|
||||
return visitExpression(expression, InterpreterFrame()).convertToIrExpression(expression)
|
||||
}
|
||||
|
||||
private fun State.toIrExpression(): IrExpression {
|
||||
private fun State.convertToIrExpression(expression: IrExpression): IrExpression {
|
||||
return when (this) {
|
||||
is Primitive<*> -> this.getIrConst()
|
||||
is Primitive<*> -> this.getIrConst().value.toIrConst(expression) // it is necessary to replace ir offsets
|
||||
else -> TODO("not supported")
|
||||
}
|
||||
}
|
||||
@@ -129,4 +130,21 @@ class IrInterpreter : IrElementVisitor<State, Frame> {
|
||||
override fun visitGetValue(expression: IrGetValue, data: Frame): State {
|
||||
return data.getVar(expression.symbol.descriptor).copy()
|
||||
}
|
||||
|
||||
override fun visitVariable(declaration: IrVariable, data: Frame): State {
|
||||
val variable = declaration.initializer?.accept(this, data)?.setDescriptor(declaration.descriptor)
|
||||
variable?.let { data.addVar(it) }
|
||||
return unit
|
||||
}
|
||||
|
||||
override fun visitSetVariable(expression: IrSetVariable, data: Frame): State {
|
||||
if (data.contains(expression.symbol.descriptor)) {
|
||||
val variable = data.getVar(expression.symbol.descriptor)
|
||||
variable.setState(expression.value.accept(this, data))
|
||||
} else {
|
||||
val variable = expression.value.accept(this, data).setDescriptor(expression.symbol.descriptor)
|
||||
data.addVar(variable)
|
||||
}
|
||||
return unit
|
||||
}
|
||||
}
|
||||
|
||||
+16
-10
@@ -76,21 +76,27 @@ fun IrFunctionAccessExpression.getBody(): IrBody? {
|
||||
return this.symbol.owner.body
|
||||
}
|
||||
|
||||
fun Any.toIrConst(expression: IrExpression): IrConst<*> {
|
||||
fun Any?.toIrConst(expression: IrExpression): IrConst<*> {
|
||||
return when (this) {
|
||||
is Boolean -> IrConstImpl(expression.startOffset, expression.endOffset, expression.type, IrConstKind.Boolean, this)
|
||||
is Char -> IrConstImpl(expression.startOffset, expression.endOffset, expression.type, IrConstKind.Char, this)
|
||||
is Byte -> IrConstImpl(expression.startOffset, expression.endOffset, expression.type, IrConstKind.Byte, this)
|
||||
is Short -> IrConstImpl(expression.startOffset, expression.endOffset, expression.type, IrConstKind.Short, this)
|
||||
is Int -> IrConstImpl(expression.startOffset, expression.endOffset, expression.type, IrConstKind.Int, this)
|
||||
is Long -> IrConstImpl(expression.startOffset, expression.endOffset, expression.type, IrConstKind.Long, this)
|
||||
is String -> IrConstImpl(expression.startOffset, expression.endOffset, expression.type, IrConstKind.String, this)
|
||||
is Float -> IrConstImpl(expression.startOffset, expression.endOffset, expression.type, IrConstKind.Float, this)
|
||||
is Double -> IrConstImpl(expression.startOffset, expression.endOffset, expression.type, IrConstKind.Double, this)
|
||||
is Boolean -> expression.copyParametersTo(IrConstKind.Boolean, this)
|
||||
is Char -> expression.copyParametersTo(IrConstKind.Char, this)
|
||||
is Byte -> expression.copyParametersTo(IrConstKind.Byte, this)
|
||||
is Short -> expression.copyParametersTo(IrConstKind.Short, this)
|
||||
is Int -> expression.copyParametersTo(IrConstKind.Int, this)
|
||||
is Long -> expression.copyParametersTo(IrConstKind.Long, this)
|
||||
is String -> expression.copyParametersTo(IrConstKind.String, this)
|
||||
is Float -> expression.copyParametersTo(IrConstKind.Float, this)
|
||||
is Double -> expression.copyParametersTo(IrConstKind.Double, this)
|
||||
null -> expression.copyParametersTo(IrConstKind.Null, this)
|
||||
else -> throw UnsupportedOperationException("Unsupported const element type $this")
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun <T> IrExpression.copyParametersTo(kind: IrConstKind<T>, value: Any?): IrConst<T> {
|
||||
return IrConstImpl(startOffset, endOffset, type, kind, value as T)
|
||||
}
|
||||
|
||||
fun <T> IrConst<T>.toPrimitive(): Primitive<T> {
|
||||
return Primitive(this)
|
||||
}
|
||||
+5
@@ -12,6 +12,7 @@ interface Frame {
|
||||
fun addVar(state: State)
|
||||
fun getVar(descriptor: DeclarationDescriptor): State
|
||||
fun getAll(): List<State>
|
||||
fun contains(descriptor: DeclarationDescriptor): Boolean
|
||||
}
|
||||
|
||||
class InterpreterFrame(val pool: MutableList<State> = mutableListOf()) : Frame {
|
||||
@@ -27,4 +28,8 @@ class InterpreterFrame(val pool: MutableList<State> = mutableListOf()) : Frame {
|
||||
override fun getAll(): List<State> {
|
||||
return pool
|
||||
}
|
||||
|
||||
override fun contains(descriptor: DeclarationDescriptor): Boolean {
|
||||
return pool.any { it.isTypeOf(descriptor) }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user