Make sure expression are only called once when building stack

This commit is contained in:
Brian Norman
2020-02-08 14:12:23 -06:00
parent 9adb5ba4e8
commit 6a5c01bea4
2 changed files with 24 additions and 6 deletions
@@ -16,6 +16,7 @@
package com.bnorm.power
import org.jetbrains.kotlin.backend.common.deepCopyWithVariables
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrConst
@@ -60,9 +61,20 @@ class ExpressionNode(
parent.mutableChildren.add(this)
}
val expressions: MutableList<IrExpression> = mutableListOf()
private val _expressions: MutableList<IrExpression> = mutableListOf()
override fun toString() = "ExpressionNode($expressions)"
fun add(expression: IrExpression) {
_expressions.add(expression)
}
fun getExpressionsCopy(): List<IrExpression> {
// Return a copy of all the expression by creating a deep copy of the head
// expression and running back through the assertion tree builder
val headCopy = _expressions.first().deepCopyWithVariables()
return (buildAssertTree(headCopy).children.single() as ExpressionNode)._expressions
}
override fun toString() = "ExpressionNode($_expressions)"
}
class RootNode : Node() {
@@ -84,7 +96,7 @@ fun buildAssertTree(expression: IrExpression): RootNode {
override fun visitExpression(expression: IrExpression, data: Node) {
val node = data as? ExpressionNode ?: ExpressionNode(data)
node.expressions += expression
node.add(expression)
expression.acceptChildren(this, node)
}
@@ -114,6 +114,7 @@ class PowerAssertCallTransformer(
return irBlock {
buildAssert(this@PowerAssertCallTransformer.context, file, fileSource, callSource, callIndent, title, root)
}
// .also { println(it.dump())}
}
}
}
@@ -161,8 +162,9 @@ private inline fun IrBlockBuilder.irIfNotThan(
node: ExpressionNode,
thenPart: IrBlockBuilder.(subStack: MutableList<IrStackVariable>) -> IrExpression
): IrWhen {
val stackTransformer = StackBuilder(this, stack, file, fileSource, callIndent, node.expressions)
val transformed = node.expressions.first().transform(stackTransformer, null)
val expressions = node.getExpressionsCopy()
val stackTransformer = StackBuilder(this, stack, file, fileSource, callIndent, expressions)
val transformed = expressions.first().transform(stackTransformer, null)
return irIfThen(irNot(transformed), thenPart(stack.toMutableList()))
}
@@ -197,7 +199,11 @@ class StackBuilder(
}
override fun visitExpression(expression: IrExpression): IrExpression {
return super.visitExpression(expression).also { if (expression in transform) push(it) }
return if (expression in transform) {
push(super.visitExpression(expression))
} else {
super.visitExpression(expression)
}
}
}