|
14 | 14 |
|
15 | 15 | package dev.cel.runtime.planner; |
16 | 16 |
|
| 17 | +import static com.google.common.base.Preconditions.checkNotNull; |
| 18 | + |
17 | 19 | import com.google.auto.value.AutoValue; |
18 | 20 | import com.google.common.base.Strings; |
19 | 21 | import com.google.common.collect.ImmutableList; |
@@ -293,17 +295,24 @@ private PlannedInterpretable planCall(CelExpr expr, PlannerContext ctx) { |
293 | 295 | } |
294 | 296 |
|
295 | 297 | if (resolvedOverload == null) { |
296 | | - if (!lateBoundFunctionNames.contains(functionName)) { |
| 298 | + boolean isLateBound = lateBoundFunctionNames.contains(functionName); |
| 299 | + // For type-checked ASTs, functions that are not explicitly registered as late-bound |
| 300 | + // must be resolved at plan time. |
| 301 | + // For parsed-only ASTs or late-bound functions, defer overload resolution to runtime. |
| 302 | + if (ctx.isChecked() && !isLateBound) { |
297 | 303 | CelReference reference = ctx.referenceMap().get(expr.id()); |
298 | | - if (reference != null) { |
| 304 | + if (reference != null && !reference.overloadIds().isEmpty()) { |
299 | 305 | throw new CelOverloadNotFoundException(functionName, reference.overloadIds()); |
300 | 306 | } else { |
301 | 307 | throw new CelOverloadNotFoundException(functionName); |
302 | 308 | } |
303 | 309 | } |
304 | 310 |
|
305 | 311 | ImmutableList<String> overloadIds = ImmutableList.of(); |
306 | | - if (resolvedFunction.overloadId().isPresent()) { |
| 312 | + CelReference reference = ctx.referenceMap().get(expr.id()); |
| 313 | + if (reference != null && !reference.overloadIds().isEmpty()) { |
| 314 | + overloadIds = reference.overloadIds(); |
| 315 | + } else if (resolvedFunction.overloadId().isPresent()) { |
307 | 316 | overloadIds = ImmutableList.of(resolvedFunction.overloadId().get()); |
308 | 317 | } |
309 | 318 |
|
@@ -628,16 +637,23 @@ private static Builder newBuilder() { |
628 | 637 | } |
629 | 638 |
|
630 | 639 | static final class PlannerContext { |
631 | | - private final ImmutableMap<Long, CelReference> referenceMap; |
632 | | - private final ImmutableMap<Long, CelType> typeMap; |
| 640 | + private final CelAbstractSyntaxTree ast; |
633 | 641 | private final HashMap<String, Integer> localVars = new HashMap<>(); |
634 | 642 |
|
| 643 | + CelAbstractSyntaxTree ast() { |
| 644 | + return ast; |
| 645 | + } |
| 646 | + |
635 | 647 | ImmutableMap<Long, CelReference> referenceMap() { |
636 | | - return referenceMap; |
| 648 | + return ast.getReferenceMap(); |
637 | 649 | } |
638 | 650 |
|
639 | 651 | ImmutableMap<Long, CelType> typeMap() { |
640 | | - return typeMap; |
| 652 | + return ast.getTypeMap(); |
| 653 | + } |
| 654 | + |
| 655 | + boolean isChecked() { |
| 656 | + return ast.isChecked(); |
641 | 657 | } |
642 | 658 |
|
643 | 659 | private void pushLocalVars(String... names) { |
@@ -670,14 +686,12 @@ private boolean isLocalVar(String name) { |
670 | 686 | return localVars.containsKey(name); |
671 | 687 | } |
672 | 688 |
|
673 | | - private PlannerContext( |
674 | | - ImmutableMap<Long, CelReference> referenceMap, ImmutableMap<Long, CelType> typeMap) { |
675 | | - this.referenceMap = referenceMap; |
676 | | - this.typeMap = typeMap; |
| 689 | + private PlannerContext(CelAbstractSyntaxTree ast) { |
| 690 | + this.ast = checkNotNull(ast); |
677 | 691 | } |
678 | 692 |
|
679 | 693 | static PlannerContext create(CelAbstractSyntaxTree ast) { |
680 | | - return new PlannerContext(ast.getReferenceMap(), ast.getTypeMap()); |
| 694 | + return new PlannerContext(ast); |
681 | 695 | } |
682 | 696 | } |
683 | 697 |
|
|
0 commit comments