Simplify work with stack by adding additional newFrame method
This commit is contained in:
committed by
TeamCityServer
parent
d578aa0ec5
commit
7fe776fe10
@@ -73,10 +73,9 @@ class IrInterpreter(val irBuiltIns: IrBuiltIns, private val bodyMap: Map<IdSigna
|
||||
if (commandCount >= MAX_COMMANDS) InterpreterTimeOutError().throwAsUserException()
|
||||
}
|
||||
|
||||
fun interpret(expression: IrExpression, parentFile: IrFile? = null): IrExpression {
|
||||
stack.clean()
|
||||
val result = stack.withEntryPoint(irFile = parentFile) { expression.interpret() }
|
||||
return when (val returnLabel = result.returnLabel) {
|
||||
fun interpret(expression: IrExpression, rootFile: IrFile? = null): IrExpression {
|
||||
stack.clean(rootFile)
|
||||
return when (val returnLabel = expression.interpret().returnLabel) {
|
||||
ReturnLabel.REGULAR -> stack.popReturnValue().toIrExpression(expression)
|
||||
ReturnLabel.EXCEPTION -> {
|
||||
val message = (stack.popReturnValue() as ExceptionState).getFullDescription()
|
||||
@@ -377,12 +376,12 @@ class IrInterpreter(val irBuiltIns: IrBuiltIns, private val bodyMap: Map<IdSigna
|
||||
|
||||
val irClass = owner.parent as IrClass
|
||||
if (irClass.hasAnnotation(evaluateIntrinsicAnnotation) || irClass.fqNameWhenAvailable!!.startsWith(Name.identifier("java"))) {
|
||||
return stack.newFrame(initPool = valueArguments) { Wrapper.getConstructorMethod(owner).invokeMethod(owner) }
|
||||
return stack.newFrame(owner, initPool = valueArguments) { Wrapper.getConstructorMethod(owner).invokeMethod(owner) }
|
||||
}
|
||||
|
||||
if (irClass.defaultType.isArray() || irClass.defaultType.isPrimitiveArray()) {
|
||||
// array constructor doesn't have body so must be treated separately
|
||||
return stack.newFrame(initPool = valueArguments) { handleIntrinsicMethods(owner) }
|
||||
return stack.newFrame(owner, initPool = valueArguments) { handleIntrinsicMethods(owner) }
|
||||
.apply {
|
||||
val array = stack.popReturnValue() as Primitive<*>
|
||||
stack.pushReturnValue(Primitive(array.value, constructorCall.type))
|
||||
@@ -413,7 +412,7 @@ class IrInterpreter(val irBuiltIns: IrBuiltIns, private val bodyMap: Map<IdSigna
|
||||
}
|
||||
|
||||
valueArguments.add(Variable(constructorCall.getThisReceiver(), state)) //used to set up fields in body
|
||||
return stack.newFrame(initPool = valueArguments) {
|
||||
return stack.newFrame(owner, initPool = valueArguments) {
|
||||
val statements = constructorCall.getBody()!!.statements
|
||||
when (val irStatement = statements[0]) {
|
||||
is IrTypeOperatorCall -> {
|
||||
|
||||
@@ -21,13 +21,13 @@ import org.jetbrains.kotlin.ir.util.isLocal
|
||||
internal interface Stack {
|
||||
fun newFrame(asSubFrame: Boolean = false, initPool: List<Variable> = listOf(), block: () -> ExecutionResult): ExecutionResult
|
||||
fun newFrame(irFunction: IrFunction, initPool: List<Variable> = listOf(), block: () -> ExecutionResult): ExecutionResult
|
||||
fun newFrame(irFile: IrFile?, initPool: List<Variable> = listOf(), block: () -> ExecutionResult): ExecutionResult
|
||||
|
||||
fun fixCallEntryPoint(irExpression: IrExpression)
|
||||
fun withEntryPoint(irFunction: IrFunction? = null, irFile: IrFile? = null, block: () -> ExecutionResult): ExecutionResult
|
||||
fun getStackTrace(): List<String>
|
||||
fun getStackCount(): Int
|
||||
|
||||
fun clean()
|
||||
fun clean(rootFile: IrFile?)
|
||||
fun addVar(variable: Variable)
|
||||
fun addAll(variables: List<Variable>)
|
||||
fun getVariable(symbol: IrSymbol): Variable
|
||||
@@ -41,16 +41,21 @@ internal interface Stack {
|
||||
}
|
||||
|
||||
internal class StackImpl : Stack {
|
||||
private val frameList = mutableListOf(FrameContainer()) // first frame is default, it is easier to work when last() is not null
|
||||
private val frameList = mutableListOf<FrameContainer>()
|
||||
private fun getCurrentFrame() = frameList.last()
|
||||
private var stackCount = 0
|
||||
|
||||
override fun newFrame(asSubFrame: Boolean, initPool: List<Variable>, block: () -> ExecutionResult): ExecutionResult {
|
||||
private fun addNewFrame(asSubFrame: Boolean, initPool: List<Variable>, irFunction: IrFunction? = null, irFile: IrFile? = null) {
|
||||
val typeArgumentsPool = initPool.filter { it.symbol is IrTypeParameterSymbol }
|
||||
val valueArguments = initPool.filter { it.symbol !is IrTypeParameterSymbol }
|
||||
val newFrame = InterpreterFrame(valueArguments.toMutableList(), typeArgumentsPool)
|
||||
if (asSubFrame) getCurrentFrame().addSubFrame(newFrame) else frameList.add(FrameContainer(newFrame))
|
||||
when {
|
||||
asSubFrame -> getCurrentFrame().addSubFrame(newFrame)
|
||||
else -> frameList.add(FrameContainer(irFile, irFunction, newFrame))
|
||||
}
|
||||
}
|
||||
|
||||
private fun withStackIncrement(asSubFrame: Boolean, block: () -> ExecutionResult): ExecutionResult {
|
||||
return try {
|
||||
stackCount++
|
||||
block()
|
||||
@@ -60,13 +65,20 @@ internal class StackImpl : Stack {
|
||||
}
|
||||
}
|
||||
|
||||
override fun newFrame(asSubFrame: Boolean, initPool: List<Variable>, block: () -> ExecutionResult): ExecutionResult {
|
||||
addNewFrame(asSubFrame, initPool, null, null)
|
||||
return withStackIncrement(asSubFrame, block)
|
||||
}
|
||||
|
||||
override fun newFrame(irFunction: IrFunction, initPool: List<Variable>, block: () -> ExecutionResult): ExecutionResult {
|
||||
val asSubFrame = irFunction.isInline || irFunction.isLocal
|
||||
return newFrame(asSubFrame, initPool) {
|
||||
withEntryPoint(irFunction, irFunction.fileOrNull) {
|
||||
block()
|
||||
}
|
||||
}
|
||||
addNewFrame(asSubFrame, initPool, irFunction, irFunction.fileOrNull)
|
||||
return withStackIncrement(asSubFrame, block)
|
||||
}
|
||||
|
||||
override fun newFrame(irFile: IrFile?, initPool: List<Variable>, block: () -> ExecutionResult): ExecutionResult {
|
||||
addNewFrame(false, initPool, null, irFile)
|
||||
return withStackIncrement(false, block)
|
||||
}
|
||||
|
||||
private fun removeLastFrame() {
|
||||
@@ -75,16 +87,9 @@ internal class StackImpl : Stack {
|
||||
}
|
||||
|
||||
override fun fixCallEntryPoint(irExpression: IrExpression) {
|
||||
val fileEntry = getCurrentFrame().entryPoint?.irFile?.fileEntry ?: return
|
||||
val fileEntry = getCurrentFrame().irFile?.fileEntry ?: return
|
||||
val lineNum = fileEntry.getLineNumber(irExpression.startOffset) + 1
|
||||
getCurrentFrame().entryPoint?.lineNumber = lineNum
|
||||
}
|
||||
|
||||
// TODO remove method and create EntryPoint in frame constructor
|
||||
override fun withEntryPoint(irFunction: IrFunction?, irFile: IrFile?, block: () -> ExecutionResult): ExecutionResult {
|
||||
val frame = getCurrentFrame()
|
||||
if (frame.entryPoint == null && irFile != null) frame.entryPoint = FrameContainer.Companion.EntryPoint(irFunction, irFile)
|
||||
return block()
|
||||
getCurrentFrame().lineNumber = lineNum
|
||||
}
|
||||
|
||||
override fun getStackTrace(): List<String> {
|
||||
@@ -94,10 +99,10 @@ internal class StackImpl : Stack {
|
||||
|
||||
override fun getStackCount(): Int = stackCount
|
||||
|
||||
override fun clean() {
|
||||
override fun clean(rootFile: IrFile?) {
|
||||
stackCount = 0
|
||||
frameList.clear()
|
||||
frameList.add(FrameContainer())
|
||||
rootFile?.let { frameList.add(FrameContainer(rootFile)) }
|
||||
}
|
||||
|
||||
override fun addVar(variable: Variable) {
|
||||
@@ -137,17 +142,11 @@ internal class StackImpl : Stack {
|
||||
}
|
||||
}
|
||||
|
||||
private class FrameContainer(current: Frame = InterpreterFrame()) {
|
||||
var entryPoint: EntryPoint? = null
|
||||
private class FrameContainer(val irFile: IrFile? = null, private val entryPoint: IrFunction? = null, current: Frame = InterpreterFrame()) {
|
||||
var lineNumber: Int = -1
|
||||
private val innerStack = mutableListOf(current)
|
||||
private fun getTopFrame() = innerStack.first()
|
||||
|
||||
companion object {
|
||||
class EntryPoint(val irFunction: IrFunction?, val irFile: IrFile) {
|
||||
var lineNumber: Int = -1
|
||||
}
|
||||
}
|
||||
|
||||
fun addSubFrame(frame: Frame) {
|
||||
innerStack.add(0, frame)
|
||||
}
|
||||
@@ -173,9 +172,9 @@ private class FrameContainer(current: Frame = InterpreterFrame()) {
|
||||
fun peekReturnValue() = getTopFrame().peekReturnValue()
|
||||
|
||||
override fun toString(): String {
|
||||
entryPoint?.irFile ?: return "Not defined"
|
||||
val fileNameCapitalized = entryPoint!!.irFile.name.replace(".kt", "Kt").capitalize()
|
||||
val lineNum = if (entryPoint?.lineNumber != -1) ":${entryPoint?.lineNumber}" else ""
|
||||
return "at $fileNameCapitalized.${entryPoint?.irFunction?.fqNameWhenAvailable ?: "<clinit>"}(${entryPoint!!.irFile.name}$lineNum)"
|
||||
irFile ?: return "Not defined"
|
||||
val fileNameCapitalized = irFile.name.replace(".kt", "Kt").capitalize()
|
||||
val lineNum = if (lineNumber != -1) ":$lineNumber" else ""
|
||||
return "at $fileNameCapitalized.${entryPoint?.fqNameWhenAvailable ?: "<clinit>"}(${irFile.name}$lineNum)"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user