Skip to content

Commit cea20a2

Browse files
authored
Distinguish Definitions from Usages in Variable Resolver (#219)
1 parent 647f13c commit cea20a2

3 files changed

Lines changed: 27 additions & 7 deletions

File tree

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

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public static Map<String, Expression> resolve(Expression exp) {
2626
resolveRecursive(exp, map);
2727

2828
// remove variables that were not used in the expression
29-
map.entrySet().removeIf(entry -> !hasUsage(exp, entry.getKey()));
29+
map.entrySet().removeIf(entry -> !hasUsage(exp, entry.getKey(), entry.getValue()));
3030

3131
// transitively resolve variables
3232
return resolveTransitive(map);
@@ -138,20 +138,21 @@ private static Expression lookup(Expression exp, Map<String, Expression> map, Se
138138
*
139139
* @return true if used, false otherwise
140140
*/
141-
private static boolean hasUsage(Expression exp, String name) {
141+
private static boolean hasUsage(Expression exp, String name, Expression value) {
142142
// exclude own definitions
143143
if (exp instanceof BinaryExpression binary && "==".equals(binary.getOperator())) {
144144
Expression left = binary.getFirstOperand();
145145
Expression right = binary.getSecondOperand();
146-
if (left instanceof Var v && v.getName().equals(name)
146+
if (left instanceof Var v && v.getName().equals(name) && right.equals(value)
147147
&& (right.isLiteral() || (!(right instanceof Var) && canSubstitute(v, right))))
148148
return false;
149-
if (left instanceof FunctionInvocation && left.toString().equals(name)
149+
if (left instanceof FunctionInvocation && left.toString().equals(name) && right.equals(value)
150150
&& (right.isLiteral() || (!(right instanceof Var) && !containsExpression(right, left))))
151151
return false;
152-
if (right instanceof Var v && v.getName().equals(name) && left.isLiteral())
152+
if (right instanceof Var v && v.getName().equals(name) && left.equals(value) && left.isLiteral())
153153
return false;
154-
if (right instanceof FunctionInvocation && right.toString().equals(name) && left.isLiteral())
154+
if (right instanceof FunctionInvocation && right.toString().equals(name) && left.equals(value)
155+
&& left.isLiteral())
155156
return false;
156157
}
157158

@@ -166,7 +167,7 @@ private static boolean hasUsage(Expression exp, String name) {
166167
// recurse children
167168
if (exp.hasChildren()) {
168169
for (Expression child : exp.getChildren())
169-
if (hasUsage(child, name))
170+
if (hasUsage(child, name, value))
170171
return true;
171172
}
172173

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,16 @@ void testIteEqualBranchesSimplifiesToBranch() {
457457
assertDerivationEquals(expected, result, "");
458458
}
459459

460+
@Test
461+
void testIteConditionUsesEqualityFromConjunction() {
462+
Expression expr = parse("mode == 1 && (mode == 2 ? explicit(param) : start(param))");
463+
ValDerivationNode result = ExpressionSimplifier.simplify(expr);
464+
465+
assertNotNull(result, "Result should not be null");
466+
assertEquals("start(param)", result.getValue().toString(),
467+
"mode == 1 should make the mode == 2 ternary condition false");
468+
}
469+
460470
@Test
461471
void testByteAliasExpansion() {
462472
String sut = "Byte(b)";

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,15 @@ void testUnusedEqualitiesShouldBeIgnored() {
9090
assertEquals("3", result.get("z").toString());
9191
}
9292

93+
@Test
94+
void testDifferentEqualityInIteConditionCountsAsUsage() {
95+
Expression expression = parse("mode == 1 && (mode == 2 ? explicit(param) : start(param))");
96+
Map<String, Expression> result = VariableResolver.resolve(expression);
97+
98+
assertEquals(1, result.size(), "Ternary condition should count as a use of mode");
99+
assertEquals("1", result.get("mode").toString());
100+
}
101+
93102
@Test
94103
void testReturnVariableIsNotSubstituted() {
95104
Expression expression = parse("x > 0 && #ret_1 == x");

0 commit comments

Comments
 (0)