|
2 | 2 |
|
3 | 3 | import static org.junit.jupiter.api.Assertions.*; |
4 | 4 |
|
| 5 | +import java.util.List; |
5 | 6 | import java.util.Map; |
6 | 7 |
|
7 | 8 | import org.junit.jupiter.api.Test; |
8 | 9 |
|
9 | 10 | import liquidjava.rj_language.ast.BinaryExpression; |
10 | 11 | import liquidjava.rj_language.ast.Expression; |
| 12 | +import liquidjava.rj_language.ast.FunctionInvocation; |
11 | 13 | import liquidjava.rj_language.ast.GroupExpression; |
12 | 14 | import liquidjava.rj_language.ast.LiteralInt; |
13 | 15 | import liquidjava.rj_language.ast.UnaryExpression; |
@@ -168,4 +170,67 @@ void testFreshVariableIsNotUsedAsSubstitutionTarget() { |
168 | 170 | Map<String, Expression> result = VariableResolver.resolve(fullExpr); |
169 | 171 | assertTrue(result.isEmpty(), "Fresh variables should not replace another variable"); |
170 | 172 | } |
| 173 | + |
| 174 | + @Test |
| 175 | + void testFunctionInvocationEqualityExtractsFunctionKey() { |
| 176 | + // size(stack) > 0 && size(stack) == 1 should extract size(stack) -> 1 |
| 177 | + Expression stack = new Var("stack"); |
| 178 | + Expression sizeStack = new FunctionInvocation("size", List.of(stack)); |
| 179 | + Expression sizeStackGreaterZero = new BinaryExpression(sizeStack, ">", new LiteralInt(0)); |
| 180 | + Expression sizeStackEqualsOne = new BinaryExpression(sizeStack, "==", new LiteralInt(1)); |
| 181 | + Expression fullExpr = new BinaryExpression(sizeStackGreaterZero, "&&", sizeStackEqualsOne); |
| 182 | + |
| 183 | + Map<String, Expression> result = VariableResolver.resolve(fullExpr); |
| 184 | + |
| 185 | + assertEquals(1, result.size(), "Should extract the function invocation as a substitution key"); |
| 186 | + assertEquals("1", result.get("size(stack)").toString()); |
| 187 | + } |
| 188 | + |
| 189 | + @Test |
| 190 | + void testLiteralOnLeftExtractsFunctionInvocationKey() { |
| 191 | + // size(stack) > 0 && 1 == size(stack) should extract size(stack) -> 1 |
| 192 | + Expression stack = new Var("stack"); |
| 193 | + Expression sizeStack = new FunctionInvocation("size", List.of(stack)); |
| 194 | + Expression sizeStackGreaterZero = new BinaryExpression(sizeStack, ">", new LiteralInt(0)); |
| 195 | + Expression oneEqualsSizeStack = new BinaryExpression(new LiteralInt(1), "==", sizeStack); |
| 196 | + Expression fullExpr = new BinaryExpression(sizeStackGreaterZero, "&&", oneEqualsSizeStack); |
| 197 | + |
| 198 | + Map<String, Expression> result = VariableResolver.resolve(fullExpr); |
| 199 | + |
| 200 | + assertEquals(1, result.size(), "Should extract function invocation equalities from either side"); |
| 201 | + assertEquals("1", result.get("size(stack)").toString()); |
| 202 | + } |
| 203 | + |
| 204 | + @Test |
| 205 | + void testFunctionInvocationEqualitiesResolveTransitively() { |
| 206 | + // func(a) > 0 && func(a) == func(b) && func(b) == 1 should extract func(a) -> 1 |
| 207 | + Expression funcA = new FunctionInvocation("func", List.of(new Var("a"))); |
| 208 | + Expression funcB = new FunctionInvocation("func", List.of(new Var("b"))); |
| 209 | + Expression funcAGreaterZero = new BinaryExpression(funcA, ">", new LiteralInt(0)); |
| 210 | + Expression funcAEqualsFuncB = new BinaryExpression(funcA, "==", funcB); |
| 211 | + Expression funcBEqualsOne = new BinaryExpression(funcB, "==", new LiteralInt(1)); |
| 212 | + Expression fullExpr = new BinaryExpression(funcAGreaterZero, "&&", |
| 213 | + new BinaryExpression(funcAEqualsFuncB, "&&", funcBEqualsOne)); |
| 214 | + |
| 215 | + Map<String, Expression> result = VariableResolver.resolve(fullExpr); |
| 216 | + |
| 217 | + assertEquals(2, result.size(), "Should keep the function invocation chain that was used"); |
| 218 | + assertEquals("1", result.get("func(a)").toString()); |
| 219 | + assertEquals("1", result.get("func(b)").toString()); |
| 220 | + } |
| 221 | + |
| 222 | + @Test |
| 223 | + void testUnusedFunctionInvocationEqualityIsIgnored() { |
| 224 | + // x > 0 && size(stack) == 1 should not extract size(stack), because it is only defined |
| 225 | + Expression x = new Var("x"); |
| 226 | + Expression stack = new Var("stack"); |
| 227 | + Expression sizeStack = new FunctionInvocation("size", List.of(stack)); |
| 228 | + Expression xGreaterZero = new BinaryExpression(x, ">", new LiteralInt(0)); |
| 229 | + Expression sizeStackEqualsOne = new BinaryExpression(sizeStack, "==", new LiteralInt(1)); |
| 230 | + Expression fullExpr = new BinaryExpression(xGreaterZero, "&&", sizeStackEqualsOne); |
| 231 | + |
| 232 | + Map<String, Expression> result = VariableResolver.resolve(fullExpr); |
| 233 | + |
| 234 | + assertTrue(result.isEmpty(), "Function invocation definitions with no usage should be ignored"); |
| 235 | + } |
171 | 236 | } |
0 commit comments