Add branches support in interpreter
This commit is contained in:
+20
-5
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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")
|
||||
}
|
||||
|
||||
+5
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user