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 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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -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")
|
||||||
}
|
}
|
||||||
|
|||||||
+5
@@ -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")
|
||||||
|
|||||||
Reference in New Issue
Block a user