Skip to content

Commit 5905379

Browse files
committed
Allow constant folding to fold equals operator
1 parent f174988 commit 5905379

2 files changed

Lines changed: 37 additions & 0 deletions

File tree

optimizer/src/main/java/dev/cel/optimizer/optimizers/ConstantFoldingOptimizer.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,10 @@ private boolean canFold(CelNavigableMutableExpr navigableExpr) {
167167
&& cond.constant().getKind().equals(CelConstant.Kind.BOOLEAN_VALUE);
168168
}
169169

170+
if (functionName.equals(Operator.EQUALS.getFunction())) {
171+
return mutableCall.args().stream().anyMatch(x -> isExprConstantOfKind(x, CelConstant.Kind.BOOLEAN_VALUE));
172+
}
173+
170174
if (functionName.equals(Operator.IN.getFunction())) {
171175
return canFoldInOperator(navigableExpr);
172176
}
@@ -393,6 +397,27 @@ private Optional<CelMutableAst> maybePruneBranches(
393397
}
394398
}
395399
}
400+
} else if (function.equals(Operator.EQUALS.getFunction())) {
401+
CelMutableExpr lhs = call.args().get(0);
402+
CelMutableExpr rhs = call.args().get(1);
403+
boolean lhsIsBoolean = isExprConstantOfKind(lhs, CelConstant.Kind.BOOLEAN_VALUE);
404+
boolean rhsIsBoolean = isExprConstantOfKind(rhs, CelConstant.Kind.BOOLEAN_VALUE);
405+
Optional<CelMutableExpr> branchToRetain = Optional.empty();
406+
407+
if (lhsIsBoolean && rhsIsBoolean) {
408+
boolean result = lhs.constant().booleanValue() == rhs.constant().booleanValue();
409+
branchToRetain = Optional.of(CelMutableExpr.ofConstant(CelConstant.ofValue(result)));
410+
} else if (lhsIsBoolean) {
411+
branchToRetain = Optional.of(lhs.constant().booleanValue() ? rhs : lhs);
412+
} else if (rhsIsBoolean) {
413+
branchToRetain = Optional.of(rhs.constant().booleanValue() ? lhs : rhs);
414+
}
415+
416+
return branchToRetain.map(node ->
417+
astMutator.replaceSubtree(
418+
mutableAst,
419+
node,
420+
expr.id()));
396421
}
397422

398423
return Optional.empty();
@@ -663,6 +688,10 @@ public static Builder newBuilder() {
663688
ConstantFoldingOptions() {}
664689
}
665690

691+
private static boolean isExprConstantOfKind(CelMutableExpr expr, CelConstant.Kind constantKind) {
692+
return expr.getKind().equals(Kind.CONSTANT) && expr.constant().getKind().equals(constantKind);
693+
}
694+
666695
private ConstantFoldingOptimizer(ConstantFoldingOptions constantFoldingOptions) {
667696
this.constantFoldingOptions = constantFoldingOptions;
668697
this.astMutator = AstMutator.newInstance(constantFoldingOptions.maxIterationLimit());

optimizer/src/test/java/dev/cel/optimizer/optimizers/ConstantFoldingOptimizerTest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,14 @@ public class ConstantFoldingOptimizerTest {
189189
@TestParameters("{source: 'sets.contains([1], [1])', expected: 'true'}")
190190
@TestParameters(
191191
"{source: 'cel.bind(r0, [1, 2, 3], cel.bind(r1, 1 in r0, r1))', expected: 'true'}")
192+
@TestParameters("{source: 'x == true', expected: 'x'}")
193+
@TestParameters("{source: 'true == x', expected: 'x'}")
194+
@TestParameters("{source: 'x == false', expected: 'false'}")
195+
@TestParameters("{source: 'false == x', expected: 'false'}")
196+
@TestParameters("{source: 'true == false', expected: 'false'}")
197+
@TestParameters("{source: 'true == true', expected: 'true'}")
198+
@TestParameters("{source: 'false == true', expected: 'false'}")
199+
@TestParameters("{source: 'false == false', expected: 'true'}")
192200
// TODO: Support folding lists with mixed types. This requires mutable lists.
193201
// @TestParameters("{source: 'dyn([1]) + [1.0]'}")
194202
public void constantFold_success(String source, String expected) throws Exception {

0 commit comments

Comments
 (0)