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 package com.bnorm.power
import org.jetbrains.kotlin.backend.common.deepCopyWithVariables
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrConst import org.jetbrains.kotlin.ir.expressions.IrConst
@@ -60,9 +61,20 @@ class ExpressionNode(
parent.mutableChildren.add(this) 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() { class RootNode : Node() {
@@ -84,7 +96,7 @@ fun buildAssertTree(expression: IrExpression): RootNode {
override fun visitExpression(expression: IrExpression, data: Node) { override fun visitExpression(expression: IrExpression, data: Node) {
val node = data as? ExpressionNode ?: ExpressionNode(data) val node = data as? ExpressionNode ?: ExpressionNode(data)
node.expressions += expression node.add(expression)
expression.acceptChildren(this, node) expression.acceptChildren(this, node)
} }
@@ -114,6 +114,7 @@ class PowerAssertCallTransformer(
return irBlock { return irBlock {
buildAssert(this@PowerAssertCallTransformer.context, file, fileSource, callSource, callIndent, title, root) 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, node: ExpressionNode,
thenPart: IrBlockBuilder.(subStack: MutableList<IrStackVariable>) -> IrExpression thenPart: IrBlockBuilder.(subStack: MutableList<IrStackVariable>) -> IrExpression
): IrWhen { ): IrWhen {
val stackTransformer = StackBuilder(this, stack, file, fileSource, callIndent, node.expressions) val expressions = node.getExpressionsCopy()
val transformed = node.expressions.first().transform(stackTransformer, null) val stackTransformer = StackBuilder(this, stack, file, fileSource, callIndent, expressions)
val transformed = expressions.first().transform(stackTransformer, null)
return irIfThen(irNot(transformed), thenPart(stack.toMutableList())) return irIfThen(irNot(transformed), thenPart(stack.toMutableList()))
} }
@@ -197,7 +199,11 @@ class StackBuilder(
} }
override fun visitExpression(expression: IrExpression): IrExpression { 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)
}
} }
} }