(ctx *cel.OptimizerContext, r *CompiledRule)
| 181 | } |
| 182 | |
| 183 | func (opt *ruleComposerImpl) optimizeRule(ctx *cel.OptimizerContext, r *CompiledRule) ast.Expr { |
| 184 | // Visitor to rewrite variables-prefixed identifiers with index names. |
| 185 | opt.enterScope() |
| 186 | defer opt.exitScope() |
| 187 | vars := r.Variables() |
| 188 | for _, v := range vars { |
| 189 | opt.registerVariable(ctx, v) |
| 190 | } |
| 191 | |
| 192 | matches := r.Matches() |
| 193 | matchCount := len(matches) |
| 194 | var output compositionStep = nil |
| 195 | // If the rule has an optional output, the last result in the ternary should return |
| 196 | // `optional.none`. This output is implicit and created here to reflect the desired |
| 197 | // last possible output of this type of rule. |
| 198 | if r.HasOptionalOutput() { |
| 199 | output = newOptionalCompositionStep(ctx, ctx.NewLiteral(types.True), ctx.NewCall("optional.none")) |
| 200 | } |
| 201 | // Build the rule subgraph. |
| 202 | for i := matchCount - 1; i >= 0; i-- { |
| 203 | m := matches[i] |
| 204 | cond := ctx.CopyASTAndMetadata(m.Condition().NativeRep()) |
| 205 | |
| 206 | // If the output is non-nil, then it is considered a non-optional output since |
| 207 | // it is explictly stated. If the rule itself is optional, then the base case value |
| 208 | // of output being optional.none() will convert the non-optional value to an optional |
| 209 | // one. |
| 210 | if m.Output() != nil { |
| 211 | out := ctx.CopyASTAndMetadata(m.Output().Expr().NativeRep()) |
| 212 | step := newNonOptionalCompositionStep(ctx, cond, out) |
| 213 | output = step.combine(output) |
| 214 | continue |
| 215 | } |
| 216 | |
| 217 | // If the match has a nested rule, then compute the rule and whether it has |
| 218 | // an optional return value. |
| 219 | child := m.NestedRule() |
| 220 | nestedRule := opt.optimizeRule(ctx, child) |
| 221 | nestedHasOptional := child.HasOptionalOutput() |
| 222 | if nestedHasOptional { |
| 223 | step := newOptionalCompositionStep(ctx, cond, nestedRule) |
| 224 | output = step.combine(output) |
| 225 | continue |
| 226 | } |
| 227 | step := newNonOptionalCompositionStep(ctx, cond, nestedRule) |
| 228 | output = step.combine(output) |
| 229 | } |
| 230 | |
| 231 | matchExpr := output.expr() |
| 232 | identVisitor := opt.rewriteVariableName(ctx) |
| 233 | ast.PostOrderVisit(matchExpr, identVisitor) |
| 234 | |
| 235 | return matchExpr |
| 236 | } |
| 237 | |
| 238 | func (opt *ruleComposerImpl) rewriteVariableName(ctx *cel.OptimizerContext) ast.Visitor { |
| 239 | return ast.NewExprVisitor(func(expr ast.Expr) { |
no test coverage detected