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 IrGetField -> visitGetField(element, data)
is IrGetValue -> visitGetValue(element, data) is IrGetValue -> visitGetValue(element, data)
is IrConst<*> -> visitConst(element, data) is IrConst<*> -> visitConst(element, data)
is IrWhen -> visitWhen(element, data)
else -> TODO("${element.javaClass} not supported") else -> TODO("${element.javaClass} not supported")
} }
} }
override fun visitCall(expression: IrCall, data: Frame): State { 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) { if (expression.symbol.owner.isFakeOverride) {
expression.dispatchReceiver?.accept(this, data)?.let { newFrame.addVar(it) } expression.dispatchReceiver?.accept(this, data)?.let { newFrame.addVar(it) }
newFrame.addAll(valueParameters)
return calculateOverridden(expression.symbol, newFrame) return calculateOverridden(expression.symbol, newFrame)
} }
@@ -60,6 +64,7 @@ class IrInterpreter : IrElementVisitor<State, Frame> {
val extensionReceiver = expression.extensionReceiver?.accept(this, data) val extensionReceiver = expression.extensionReceiver?.accept(this, data)
?.setDescriptor(expression.symbol.descriptor.extensionReceiverParameter!!) ?.setDescriptor(expression.symbol.descriptor.extensionReceiverParameter!!)
(dispatchReceiver ?: extensionReceiver)?.also { newFrame.addVar(it) } (dispatchReceiver ?: extensionReceiver)?.also { newFrame.addVar(it) }
newFrame.addAll(valueParameters)
return if (expression.getBody() == null) { return if (expression.getBody() == null) {
calculateBuiltIns(expression.symbol.descriptor, newFrame).toIrConst(expression).toPrimitive() 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 { private fun visitStatements(statements: List<IrStatement>, data: Frame): State {
statements.forEach { statements.forEachIndexed { index, statement ->
when (it) { when {
is IrReturn -> return it.accept(this, data) statement is IrReturn || index == statements.lastIndex -> return statement.accept(this, data)
else -> it.accept(this, data) else -> statement.accept(this, data)
} }
} }
// unreachable state; method must return inside forEach
return unit return unit
} }
@@ -147,4 +153,13 @@ class IrInterpreter : IrElementVisitor<State, Frame> {
} }
return unit 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 -> { 2 -> {
val function = binaryFunctions[signature] val function = binaryFunctions[signature]
?: throw NoSuchMethodException("For given function $signature there is no entry in binary map") ?: 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") else -> throw UnsupportedOperationException("Unsupported number of arguments")
} }
@@ -10,6 +10,7 @@ import java.util.NoSuchElementException
interface Frame { interface Frame {
fun addVar(state: State) fun addVar(state: State)
fun addAll(states: List<State>)
fun getVar(descriptor: DeclarationDescriptor): State fun getVar(descriptor: DeclarationDescriptor): State
fun getAll(): List<State> fun getAll(): List<State>
fun contains(descriptor: DeclarationDescriptor): Boolean fun contains(descriptor: DeclarationDescriptor): Boolean
@@ -20,6 +21,10 @@ class InterpreterFrame(val pool: MutableList<State> = mutableListOf()) : Frame {
pool.add(state) pool.add(state)
} }
override fun addAll(states: List<State>) {
pool.addAll(states)
}
override fun getVar(descriptor: DeclarationDescriptor): State { override fun getVar(descriptor: DeclarationDescriptor): State {
return pool.firstOrNull { it.isTypeOf(descriptor) } return pool.firstOrNull { it.isTypeOf(descriptor) }
?: throw NoSuchElementException("Frame pool doesn't contains variable with descriptor $descriptor") ?: throw NoSuchElementException("Frame pool doesn't contains variable with descriptor $descriptor")