Skip to content

Commit e9efbc4

Browse files
committed
Prevent Oversimplification
1 parent f8d3f3e commit e9efbc4

File tree

2 files changed

+36
-1
lines changed

2 files changed

+36
-1
lines changed

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public static ValDerivationNode simplify(Expression exp) {
2020

2121
/**
2222
* Recursively applies propagation and folding until the expression stops changing (fixed point) Stops early if the
23-
* expression simplifies to 'true', which means we've simplified too much
23+
* expression simplifies to a boolean literal, which means we've simplified too much
2424
*/
2525
private static ValDerivationNode simplifyToFixedPoint(ValDerivationNode current, Expression prevExp) {
2626
// apply propagation and folding
@@ -34,6 +34,11 @@ private static ValDerivationNode simplifyToFixedPoint(ValDerivationNode current,
3434
return current;
3535
}
3636

37+
// prevent oversimplification
38+
if (current != null && currExp instanceof LiteralBoolean && !(current.getValue() instanceof LiteralBoolean)) {
39+
return current;
40+
}
41+
3742
// continue simplifying
3843
return simplifyToFixedPoint(simplified, simplified.getValue());
3944
}

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

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,36 @@ void testTransitive() {
550550
assertEquals("a == 1", result.getValue().toString(), "Expected result to be a == 1");
551551
}
552552

553+
@Test
554+
void testShouldNotOversimplifyToTrue() {
555+
// Given: x > 5 && x == y && y == 10
556+
// Iteration 1: resolves y == 10, substitutes y -> 10: x > 5 && x == 10
557+
// Iteration 2: resolves x == 10, substitutes x -> 10: 10 > 5 && 10 == 10 -> true
558+
// Expected: x > 5 && x == 10 (should NOT simplify to true)
559+
560+
Expression varX = new Var("x");
561+
Expression varY = new Var("y");
562+
Expression five = new LiteralInt(5);
563+
Expression ten = new LiteralInt(10);
564+
565+
Expression xGreater5 = new BinaryExpression(varX, ">", five);
566+
Expression xEqualsY = new BinaryExpression(varX, "==", varY);
567+
Expression yEquals10 = new BinaryExpression(varY, "==", ten);
568+
569+
Expression firstAnd = new BinaryExpression(xGreater5, "&&", xEqualsY);
570+
Expression fullExpression = new BinaryExpression(firstAnd, "&&", yEquals10);
571+
572+
// When
573+
ValDerivationNode result = ExpressionSimplifier.simplify(fullExpression);
574+
575+
// Then
576+
assertNotNull(result, "Result should not be null");
577+
assertFalse(result.getValue() instanceof LiteralBoolean,
578+
"Should not oversimplify to a boolean literal, but got: " + result.getValue());
579+
assertEquals("x > 5 && x == 10", result.getValue().toString(),
580+
"Should stop simplification before collapsing to true");
581+
}
582+
553583
/**
554584
* Helper method to compare two derivation nodes recursively
555585
*/

0 commit comments

Comments
 (0)