(ctx *OptimizerContext, a *ast.AST)
| 76 | } |
| 77 | |
| 78 | func (opt *inliningOptimizer) Optimize(ctx *OptimizerContext, a *ast.AST) *ast.AST { |
| 79 | root := ast.NavigateAST(a) |
| 80 | for _, inlineVar := range opt.variables { |
| 81 | matches := ast.MatchDescendants(root, opt.matchVariable(inlineVar.Name())) |
| 82 | // Skip cases where the variable isn't in the expression graph |
| 83 | if len(matches) == 0 { |
| 84 | continue |
| 85 | } |
| 86 | |
| 87 | // For a single match, do a direct replacement of the expression sub-graph. |
| 88 | if len(matches) == 1 || !isBindable(matches, inlineVar.Expr(), inlineVar.Type()) { |
| 89 | for _, match := range matches { |
| 90 | // Copy the inlined AST expr and source info. |
| 91 | copyExpr := ctx.CopyASTAndMetadata(inlineVar.def) |
| 92 | opt.inlineExpr(ctx, match, copyExpr, inlineVar.Type()) |
| 93 | } |
| 94 | continue |
| 95 | } |
| 96 | |
| 97 | // For multiple matches, find the least common ancestor (lca) and insert the |
| 98 | // variable as a cel.bind() macro. |
| 99 | var lca ast.NavigableExpr = root |
| 100 | lcaAncestorCount := 0 |
| 101 | ancestors := map[int64]int{} |
| 102 | for _, match := range matches { |
| 103 | // Update the identifier matches with the provided alias. |
| 104 | parent, found := match, true |
| 105 | for found { |
| 106 | ancestorCount, hasAncestor := ancestors[parent.ID()] |
| 107 | if !hasAncestor { |
| 108 | ancestors[parent.ID()] = 1 |
| 109 | parent, found = parent.Parent() |
| 110 | continue |
| 111 | } |
| 112 | if lcaAncestorCount < ancestorCount || (lcaAncestorCount == ancestorCount && lca.Depth() < parent.Depth()) { |
| 113 | lca = parent |
| 114 | lcaAncestorCount = ancestorCount |
| 115 | } |
| 116 | ancestors[parent.ID()] = ancestorCount + 1 |
| 117 | parent, found = parent.Parent() |
| 118 | } |
| 119 | aliasExpr := ctx.NewIdent(inlineVar.Alias()) |
| 120 | opt.inlineExpr(ctx, match, aliasExpr, inlineVar.Type()) |
| 121 | } |
| 122 | |
| 123 | // Copy the inlined AST expr and source info. |
| 124 | copyExpr := ctx.CopyASTAndMetadata(inlineVar.def) |
| 125 | // Update the least common ancestor by inserting a cel.bind() call to the alias. |
| 126 | inlined, bindMacro := ctx.NewBindMacro(lca.ID(), inlineVar.Alias(), copyExpr, lca) |
| 127 | opt.inlineExpr(ctx, lca, inlined, inlineVar.Type()) |
| 128 | ctx.SetMacroCall(lca.ID(), bindMacro) |
| 129 | } |
| 130 | return a |
| 131 | } |
| 132 | |
| 133 | // inlineExpr replaces the current expression with the inlined one, unless the location of the inlining |
| 134 | // happens within a presence test, e.g. has(a.b.c) -> inline alpha for a.b.c in which case an attempt is |
nothing calls this directly
no test coverage detected