Skip to content

Commit 0d5b026

Browse files
committed
Fix Misleading Expansions
1 parent e9efbc4 commit 0d5b026

File tree

4 files changed

+45
-12
lines changed

4 files changed

+45
-12
lines changed

liquidjava-verifier/src/main/java/liquidjava/rj_language/ast/Var.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,4 +70,8 @@ public boolean equals(Object obj) {
7070
return name.equals(other.name);
7171
}
7272
}
73+
74+
public boolean isInternal() {
75+
return name.startsWith("#");
76+
}
7377
}

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,18 +172,24 @@ private static ValDerivationNode foldUnary(ValDerivationNode node) {
172172
// !true => false, !false => true
173173
boolean value = operand.isBooleanTrue();
174174
Expression res = new LiteralBoolean(!value);
175-
return new ValDerivationNode(res, new UnaryDerivationNode(operandNode, operator));
175+
DerivationNode origin = operandNode.getOrigin() != null ? new UnaryDerivationNode(operandNode, operator)
176+
: null;
177+
return new ValDerivationNode(res, origin);
176178
}
177179
// unary minus
178180
if ("-".equals(operator)) {
179181
// -(x) => -x
180182
if (operand instanceof LiteralInt) {
181183
Expression res = new LiteralInt(-((LiteralInt) operand).getValue());
182-
return new ValDerivationNode(res, new UnaryDerivationNode(operandNode, operator));
184+
DerivationNode origin = operandNode.getOrigin() != null ? new UnaryDerivationNode(operandNode, operator)
185+
: null;
186+
return new ValDerivationNode(res, origin);
183187
}
184188
if (operand instanceof LiteralReal) {
185189
Expression res = new LiteralReal(-((LiteralReal) operand).getValue());
186-
return new ValDerivationNode(res, new UnaryDerivationNode(operandNode, operator));
190+
DerivationNode origin = operandNode.getOrigin() != null ? new UnaryDerivationNode(operandNode, operator)
191+
: null;
192+
return new ValDerivationNode(res, origin);
187193
}
188194
}
189195

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,12 @@ private static ValDerivationNode simplifyValDerivationNode(ValDerivationNode nod
8181

8282
// return the conjunction with simplified children
8383
Expression newValue = new BinaryExpression(leftSimplified.getValue(), "&&", rightSimplified.getValue());
84-
DerivationNode newOrigin = new BinaryDerivationNode(leftSimplified, rightSimplified, "&&");
85-
return new ValDerivationNode(newValue, newOrigin);
84+
// only create origin if at least one child has a meaningful origin
85+
if (leftSimplified.getOrigin() != null || rightSimplified.getOrigin() != null) {
86+
DerivationNode newOrigin = new BinaryDerivationNode(leftSimplified, rightSimplified, "&&");
87+
return new ValDerivationNode(newValue, newOrigin);
88+
}
89+
return new ValDerivationNode(newValue, null);
8690
}
8791
// no simplification
8892
return node;

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

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,7 @@ void testSimpleComparison() {
120120
ValDerivationNode trueFromOr = new ValDerivationNode(new LiteralBoolean(true), orFalseTrue);
121121

122122
// !true = false
123-
ValDerivationNode valTrue2 = new ValDerivationNode(new LiteralBoolean(true), null);
124-
UnaryDerivationNode notOp = new UnaryDerivationNode(valTrue2, "!");
125-
ValDerivationNode falseFromNot = new ValDerivationNode(new LiteralBoolean(false), notOp);
123+
ValDerivationNode falseFromNot = new ValDerivationNode(new LiteralBoolean(false), null);
126124

127125
// true && false = false
128126
BinaryDerivationNode andTrueFalse = new BinaryDerivationNode(trueFromOr, falseFromNot, "&&");
@@ -187,10 +185,8 @@ void testArithmeticWithConstants() {
187185
BinaryDerivationNode div6By2 = new BinaryDerivationNode(val6, val2, "/");
188186
ValDerivationNode val3 = new ValDerivationNode(new LiteralInt(3), div6By2);
189187

190-
// -5 from unary negation of 5
191-
ValDerivationNode val5 = new ValDerivationNode(new LiteralInt(5), null);
192-
UnaryDerivationNode unaryNeg5 = new UnaryDerivationNode(val5, "-");
193-
ValDerivationNode valNeg5 = new ValDerivationNode(new LiteralInt(-5), unaryNeg5);
188+
// -5 is a literal with no origin
189+
ValDerivationNode valNeg5 = new ValDerivationNode(new LiteralInt(-5), null);
194190

195191
// 3 + (-5) = -2
196192
BinaryDerivationNode add3AndNeg5 = new BinaryDerivationNode(val3, valNeg5, "+");
@@ -580,6 +576,29 @@ void testShouldNotOversimplifyToTrue() {
580576
"Should stop simplification before collapsing to true");
581577
}
582578

579+
@Test
580+
void testNoSimplificationHasNoOrigin() {
581+
// Given: x > 0 && y >= -128 && y <= 127
582+
// Expected: same expression with no origin (nothing to simplify)
583+
584+
Expression varX = new Var("x");
585+
Expression varY = new Var("y");
586+
Expression xGreater0 = new BinaryExpression(varX, ">", new LiteralInt(0));
587+
Expression yGeMinus128 = new BinaryExpression(varY, ">=", new UnaryExpression("-", new LiteralInt(128)));
588+
Expression yLe127 = new BinaryExpression(varY, "<=", new LiteralInt(127));
589+
Expression firstAnd = new BinaryExpression(xGreater0, "&&", yGeMinus128);
590+
Expression fullExpression = new BinaryExpression(firstAnd, "&&", yLe127);
591+
592+
// When
593+
ValDerivationNode result = ExpressionSimplifier.simplify(fullExpression);
594+
595+
// Then
596+
assertNotNull(result, "Result should not be null");
597+
assertEquals("x > 0 && y >= -128 && y <= 127", result.getValue().toString(),
598+
"Expression should remain unchanged");
599+
assertNull(result.getOrigin(), "No origin should be present when nothing was simplified");
600+
}
601+
583602
/**
584603
* Helper method to compare two derivation nodes recursively
585604
*/

0 commit comments

Comments
 (0)