Add branches support in interpreter

This commit is contained in:
Ivan Kylchik
2019-11-13 19:45:47 +03:00
parent dcd8a4a4c7
commit b1dc403182
3 changed files with 26 additions and 6 deletions
@@ -44,14 +44,18 @@ class IrInterpreter : IrElementVisitor<State, Frame> {
is IrGetField -> visitGetField(element, data)
is IrGetValue -> visitGetValue(element, data)
is IrConst<*> -> visitConst(element, data)
is IrWhen -> visitWhen(element, data)
else -> TODO("${element.javaClass} not supported")
}
}
override fun visitCall(expression: IrCall, data: Frame): State {
val newFrame = InterpreterFrame(convertValueParameters(expression, data))
val newFrame = InterpreterFrame() // it is important firstly to add receiver, then arguments
val valueParameters = convertValueParameters(expression, data)
if (expression.symbol.owner.isFakeOverride) {
expression.dispatchReceiver?.accept(this, data)?.let { newFrame.addVar(it) }
newFrame.addAll(valueParameters)
return calculateOverridden(expression.symbol, newFrame)
}
@@ -60,6 +64,7 @@ class IrInterpreter : IrElementVisitor<State, Frame> {
val extensionReceiver = expression.extensionReceiver?.accept(this, data)
?.setDescriptor(expression.symbol.descriptor.extensionReceiverParameter!!)
(dispatchReceiver ?: extensionReceiver)?.also { newFrame.addVar(it) }
newFrame.addAll(valueParameters)
return if (expression.getBody() == null) {
calculateBuiltIns(expression.symbol.descriptor, newFrame).toIrConst(expression).toPrimitive()
@@ -100,13 +105,14 @@ class IrInterpreter : IrElementVisitor<State, Frame> {
}
private fun visitStatements(statements: List<IrStatement>, data: Frame): State {
statements.forEach {
when (it) {
is IrReturn -> return it.accept(this, data)
else -> it.accept(this, data)
statements.forEachIndexed { index, statement ->
when {
statement is IrReturn || index == statements.lastIndex -> return statement.accept(this, data)
else -> statement.accept(this, data)
}
}
// unreachable state; method must return inside forEach
return unit
}
@@ -147,4 +153,13 @@ class IrInterpreter : IrElementVisitor<State, Frame> {
}
return unit
}
override fun visitWhen(expression: IrWhen, data: Frame): State {
expression.branches.forEach {
if ((it.condition.accept(this, data) as? Primitive<*>)?.getIrConst()?.value == true) {
return it.result.accept(this, data)
}
}
return unit
}
}
@@ -53,7 +53,7 @@ fun calculateBuiltIns(descriptor: FunctionDescriptor, frame: Frame): Any {
2 -> {
val function = binaryFunctions[signature]
?: throw NoSuchMethodException("For given function $signature there is no entry in binary map")
function.invoke(argsValues[1], argsValues[0])
function.invoke(argsValues[0], argsValues[1])
}
else -> throw UnsupportedOperationException("Unsupported number of arguments")
}
@@ -10,6 +10,7 @@ import java.util.NoSuchElementException
interface Frame {
fun addVar(state: State)
fun addAll(states: List<State>)
fun getVar(descriptor: DeclarationDescriptor): State
fun getAll(): List<State>
fun contains(descriptor: DeclarationDescriptor): Boolean
@@ -20,6 +21,10 @@ class InterpreterFrame(val pool: MutableList<State> = mutableListOf()) : Frame {
pool.add(state)
}
override fun addAll(states: List<State>) {
pool.addAll(states)
}
override fun getVar(descriptor: DeclarationDescriptor): State {
return pool.firstOrNull { it.isTypeOf(descriptor) }
?: throw NoSuchElementException("Frame pool doesn't contains variable with descriptor $descriptor")