Allow local declaration interpretation

By local declaration is meant local functions and local objects
This commit is contained in:
Ivan Kylchik
2020-04-22 14:34:09 +03:00
parent 2c93c46b84
commit a095309e10
3 changed files with 22 additions and 4 deletions
@@ -121,6 +121,7 @@ class IrInterpreter(irModule: IrModuleFragment) {
is IrFunctionReference -> interpretFunctionReference(this) is IrFunctionReference -> interpretFunctionReference(this)
is IrComposite -> interpretComposite(this) is IrComposite -> interpretComposite(this)
is IrClass -> if (this.isLocal) Next else TODO("Only local classes are supported")
else -> TODO("${this.javaClass} not supported") else -> TODO("${this.javaClass} not supported")
} }
@@ -274,9 +275,11 @@ class IrInterpreter(irModule: IrModuleFragment) {
return stack.newFrame(asSubFrame = true, initPool = pool) { return stack.newFrame(asSubFrame = true, initPool = pool) {
for (i in valueArguments.indices) { for (i in valueArguments.indices) {
(valueArguments[i] ?: defaultValues[i])!!.interpret().check { return@newFrame it } (valueArguments[i] ?: defaultValues[i])?.interpret()?.check { return@newFrame it }
?: stack.pushReturnValue(listOf<Any?>().toPrimitiveStateArray(expression.getVarargType(i)!!))
with(Variable(valueParametersDescriptors[i], stack.popReturnValue())) { with(Variable(valueParametersDescriptors[i], stack.popReturnValue())) {
stack.addVar(this) stack.addVar(this) //must add value argument in current stack because it can be used later as default argument
pool.add(this) pool.add(this)
} }
} }
@@ -314,6 +317,12 @@ class IrInterpreter(irModule: IrModuleFragment) {
} }
} }
// load data from declaration if it is local
if (dispatchReceiver != null && (irFunction.isLocal || dispatchReceiver.irClass.isLocal)) {
with(dispatchReceiver) { this.fields.filterNot { it.descriptor.containingDeclaration == this.irClass.descriptor } }
.apply { valueArguments.addAll(this) }
}
return stack.newFrame(asSubFrame = irFunction.isInline || irFunction.isLocal, initPool = valueArguments) { return stack.newFrame(asSubFrame = irFunction.isInline || irFunction.isLocal, initPool = valueArguments) {
val isWrapper = dispatchReceiver is Wrapper && rawExtensionReceiver == null val isWrapper = dispatchReceiver is Wrapper && rawExtensionReceiver == null
val isInterfaceDefaultMethod = irFunction.body != null && (irFunction.parent as? IrClass)?.isInterface == true val isInterfaceDefaultMethod = irFunction.body != null && (irFunction.parent as? IrClass)?.isInterface == true
@@ -367,6 +376,7 @@ class IrInterpreter(irModule: IrModuleFragment) {
} }
val state = Common(parent) val state = Common(parent)
if (parent.isLocal) state.fields.addAll(stack.getAll()) // TODO save only necessary declarations
valueArguments.add(Variable(constructorCall.getThisAsReceiver(), state)) //used to set up fields in body valueArguments.add(Variable(constructorCall.getThisAsReceiver(), state)) //used to set up fields in body
return stack.newFrame(initPool = valueArguments) { return stack.newFrame(initPool = valueArguments) {
val statements = constructorCall.getBody()!!.statements val statements = constructorCall.getBody()!!.statements
@@ -709,7 +719,9 @@ class IrInterpreter(irModule: IrModuleFragment) {
} }
private fun interpretFunctionExpression(expression: IrFunctionExpression): ExecutionResult { private fun interpretFunctionExpression(expression: IrFunctionExpression): ExecutionResult {
stack.pushReturnValue(Lambda(expression.function, expression.type.classOrNull!!.owner)) val lambda = Lambda(expression.function, expression.type.classOrNull!!.owner)
if (expression.function.isLocal) lambda.fields.addAll(stack.getAll()) // TODO save only necessary declarations
stack.pushReturnValue(lambda)
return Next return Next
} }
@@ -233,4 +233,10 @@ fun State?.getFunctionReceiver(superIrClass: IrClass?): State? {
} }
else -> (this as Complex).superClass else -> (this as Complex).superClass
} }
}
fun IrFunctionAccessExpression.getVarargType(index: Int): IrType? {
val varargType = this.symbol.owner.valueParameters[index].varargElementType ?: return null
val typeParameter = varargType.classifierOrFail.owner as IrTypeParameter
return this.getTypeArgument(typeParameter.index)
} }
@@ -28,7 +28,7 @@ class Lambda(val irFunction: IrFunction, override val irClass: IrClass) : State
} }
override fun copy(): State { override fun copy(): State {
return Lambda(irFunction, irClass) return Lambda(irFunction, irClass).apply { this.fields.addAll(this@Lambda.fields) }
} }
override fun toString(): String { override fun toString(): String {