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 IrComposite -> interpretComposite(this)
is IrClass -> if (this.isLocal) Next else TODO("Only local classes are supported")
else -> TODO("${this.javaClass} not supported")
}
@@ -274,9 +275,11 @@ class IrInterpreter(irModule: IrModuleFragment) {
return stack.newFrame(asSubFrame = true, initPool = pool) {
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())) {
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)
}
}
@@ -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) {
val isWrapper = dispatchReceiver is Wrapper && rawExtensionReceiver == null
val isInterfaceDefaultMethod = irFunction.body != null && (irFunction.parent as? IrClass)?.isInterface == true
@@ -367,6 +376,7 @@ class IrInterpreter(irModule: IrModuleFragment) {
}
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
return stack.newFrame(initPool = valueArguments) {
val statements = constructorCall.getBody()!!.statements
@@ -709,7 +719,9 @@ class IrInterpreter(irModule: IrModuleFragment) {
}
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
}
@@ -233,4 +233,10 @@ fun State?.getFunctionReceiver(superIrClass: IrClass?): State? {
}
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 {
return Lambda(irFunction, irClass)
return Lambda(irFunction, irClass).apply { this.fields.addAll(this@Lambda.fields) }
}
override fun toString(): String {