Skip to content

Commit c7afdde

Browse files
committed
Fold Adjacent Constants
1 parent b3c83ce commit c7afdde

2 files changed

Lines changed: 58 additions & 3 deletions

File tree

liquidjava-verifier/src/main/java/liquidjava/rj_language/opt/ExpressionFolding.java

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,10 @@ else if (left instanceof LiteralBoolean && right instanceof LiteralBoolean) {
146146
return new ValDerivationNode(res, new BinaryDerivationNode(leftNode, rightNode, op));
147147
}
148148

149+
ValDerivationNode adjacentConstants = foldAdjacentIntegerConstants(leftNode, rightNode, op);
150+
if (adjacentConstants != null)
151+
return adjacentConstants;
152+
149153
// no folding
150154
DerivationNode origin = (leftNode.getOrigin() != null || rightNode.getOrigin() != null)
151155
? new BinaryDerivationNode(leftNode, rightNode, op) : null;
@@ -243,4 +247,32 @@ private static ValDerivationNode foldIte(ValDerivationNode node) {
243247
private static boolean hasIteChildOrigin(ValDerivationNode cond, ValDerivationNode then, ValDerivationNode els) {
244248
return cond.getOrigin() != null || then.getOrigin() != null || els.getOrigin() != null;
245249
}
246-
}
250+
251+
private static ValDerivationNode foldAdjacentIntegerConstants(ValDerivationNode leftNode,
252+
ValDerivationNode rightNode, String op) {
253+
if (!"+".equals(op) && !"-".equals(op))
254+
return null;
255+
if (!(rightNode.getValue()instanceof LiteralInt rightLiteral))
256+
return null;
257+
if (!(leftNode.getValue()instanceof BinaryExpression leftBinary))
258+
return null;
259+
if (!"+".equals(leftBinary.getOperator()) && !"-".equals(leftBinary.getOperator()))
260+
return null;
261+
if (!(leftBinary.getSecondOperand()instanceof LiteralInt leftLiteral))
262+
return null;
263+
264+
int signedLeft = "+".equals(leftBinary.getOperator()) ? leftLiteral.getValue() : -leftLiteral.getValue();
265+
int signedRight = "+".equals(op) ? rightLiteral.getValue() : -rightLiteral.getValue();
266+
Expression folded = expressionWithConstant(leftBinary.getFirstOperand(), signedLeft + signedRight);
267+
268+
return new ValDerivationNode(folded, new BinaryDerivationNode(leftNode, rightNode, op));
269+
}
270+
271+
private static Expression expressionWithConstant(Expression base, int constant) {
272+
if (constant == 0)
273+
return base.clone();
274+
if (constant > 0)
275+
return new BinaryExpression(base.clone(), "+", new LiteralInt(constant));
276+
return new BinaryExpression(base.clone(), "-", new LiteralInt(-constant));
277+
}
278+
}

liquidjava-verifier/src/test/java/liquidjava/rj_language/opt/ExpressionSimplifierTest.java

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,7 +1093,7 @@ void testEquivalentBoundsKeepOneSide() {
10931093
@Test
10941094
void testSubstitutesVariableDefinedByArithmeticExpression() {
10951095
// Given: z == y - 2 && y == x + 1
1096-
// Expected: z == x + 1 - 2
1096+
// Expected: z == x - 1
10971097

10981098
Expression z = new Var("z");
10991099
Expression y = new Var("y");
@@ -1108,6 +1108,29 @@ void testSubstitutesVariableDefinedByArithmeticExpression() {
11081108

11091109
// Then
11101110
assertNotNull(result, "Result should not be null");
1111-
assertEquals("z == x + 1 - 2", result.getValue().toString(), "Expected variable definition to be substituted");
1111+
assertEquals("z == x - 1", result.getValue().toString(), "Expected variable definition to be substituted");
1112+
}
1113+
1114+
@Test
1115+
void testFoldsAdjacentIntegerConstantsInLeftAssociatedArithmetic() {
1116+
// Given: x + 1 - 2, x - 1 + 2, x + 1 + 2, and x + 1 - 1
1117+
// Expected: x - 1, x + 1, x + 3, and x
1118+
1119+
Expression x = new Var("x");
1120+
1121+
Expression xPlus1Minus2 = new BinaryExpression(new BinaryExpression(x, "+", new LiteralInt(1)), "-",
1122+
new LiteralInt(2));
1123+
Expression xMinus1Plus2 = new BinaryExpression(new BinaryExpression(x, "-", new LiteralInt(1)), "+",
1124+
new LiteralInt(2));
1125+
Expression xPlus1Plus2 = new BinaryExpression(new BinaryExpression(x, "+", new LiteralInt(1)), "+",
1126+
new LiteralInt(2));
1127+
Expression xPlus1Minus1 = new BinaryExpression(new BinaryExpression(x, "+", new LiteralInt(1)), "-",
1128+
new LiteralInt(1));
1129+
1130+
// When / Then
1131+
assertEquals("x - 1", ExpressionSimplifier.simplify(xPlus1Minus2).getValue().toString());
1132+
assertEquals("x + 1", ExpressionSimplifier.simplify(xMinus1Plus2).getValue().toString());
1133+
assertEquals("x + 3", ExpressionSimplifier.simplify(xPlus1Plus2).getValue().toString());
1134+
assertEquals("x", ExpressionSimplifier.simplify(xPlus1Minus1).getValue().toString());
11121135
}
11131136
}

0 commit comments

Comments
 (0)