Add variables support in interpreter

This commit is contained in:
Ivan Kylchik
2019-11-13 17:58:14 +03:00
parent aca7a49214
commit dcd8a4a4c7
3 changed files with 42 additions and 13 deletions
@@ -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
}
}
@@ -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)
}
@@ -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) }
}
}