MCPcopy Create free account
hub / github.com/cel-expr/cel-go / resolveFunction

Method resolveFunction

interpreter/planner.go:687–747  ·  view source on GitHub ↗

resolveFunction determines the call target, function name, and overload name from a given Expr value. The resolveFunction resolves ambiguities where a function may either be a receiver-style invocation or a qualified global function name. - The target expression may only consist of ident and select

(expr ast.Expr)

Source from the content-addressed store, hash-verified

685// - The function is declared in the environment using its fully-qualified name.
686// - The fully-qualified function name matches the string serialized target value.
687func (p *planBuilder) resolveFunction(expr ast.Expr) (ast.Expr, string, string) {
688 // Note: similar logic exists within the `checker/checker.go`. If making changes here
689 // please consider the impact on checker.go and consolidate implementations or mirror code
690 // as appropriate.
691 call := expr.AsCall()
692 var target ast.Expr = nil
693 if call.IsMemberFunction() {
694 target = call.Target()
695 }
696 fnName := call.FunctionName()
697
698 // Checked expressions always have a reference map entry, and _should_ have the fully qualified
699 // function name as the fnName value.
700 oRef, hasOverload := p.refMap[expr.ID()]
701 if hasOverload {
702 if len(oRef.OverloadIDs) == 1 {
703 return target, fnName, oRef.OverloadIDs[0]
704 }
705 // Note, this namespaced function name will not appear as a fully qualified name in ASTs
706 // built and stored before cel-go v0.5.0; however, this functionality did not work at all
707 // before the v0.5.0 release.
708 return target, fnName, ""
709 }
710
711 // Parse-only expressions need to handle the same logic as is normally performed at check time,
712 // but with potentially much less information. The only reliable source of information about
713 // which functions are configured is the dispatcher.
714 if target == nil {
715 // If the user has a parse-only expression, then it should have been configured as such in
716 // the interpreter dispatcher as it may have been omitted from the checker environment.
717 for _, qualifiedName := range p.container.ResolveCandidateNames(fnName) {
718 _, found := p.disp.FindOverload(qualifiedName)
719 if found {
720 return nil, qualifiedName, ""
721 }
722 }
723 // It's possible that the overload was not found, but this situation is accounted for in
724 // the planCall phase; however, the leading dot used for denoting fully-qualified
725 // namespaced identifiers must be stripped, as all declarations already use fully-qualified
726 // names. This stripping behavior is handled automatically by the ResolveCandidateNames
727 // call.
728 return target, strings.TrimPrefix(fnName, "."), ""
729 }
730
731 // Handle the situation where the function target actually indicates a qualified function name.
732 qualifiedPrefix, maybeQualified := p.toQualifiedName(target)
733 if maybeQualified {
734 maybeQualifiedName := qualifiedPrefix + "." + fnName
735 for _, qualifiedName := range p.container.ResolveCandidateNames(maybeQualifiedName) {
736 _, found := p.disp.FindOverload(qualifiedName)
737 if found {
738 // Clear the target to ensure the proper arity is used for finding the
739 // implementation.
740 return nil, qualifiedName, ""
741 }
742 }
743 }
744 // In the default case, the function is exactly as it was advertised: a receiver call on with

Callers 1

planCallMethod · 0.95

Calls 8

toQualifiedNameMethod · 0.95
ResolveCandidateNamesMethod · 0.80
AsCallMethod · 0.65
IsMemberFunctionMethod · 0.65
TargetMethod · 0.65
FunctionNameMethod · 0.65
IDMethod · 0.65
FindOverloadMethod · 0.65

Tested by

no test coverage detected