(ctx *cel.OptimizerContext, a *ast.AST)
| 277 | } |
| 278 | |
| 279 | func (opt *ruleUnnesterImpl) Optimize(ctx *cel.OptimizerContext, a *ast.AST) *ast.AST { |
| 280 | // Since the optimizer is based on the original environment provided to the composer, |
| 281 | // a second pass on the `cel.@block` will require a rebuilding of the cel environment |
| 282 | ruleExpr := ast.NavigateAST(a) |
| 283 | var varExprs []ast.Expr |
| 284 | var varDecls []cel.EnvOption |
| 285 | unnestOffset := opt.nextVarIndex |
| 286 | if ruleExpr.Kind() == ast.CallKind && ruleExpr.AsCall().FunctionName() == "cel.@block" { |
| 287 | // Check that the result of the compose pass is consistent with the intial set of variable |
| 288 | // definitions in the optimizer. Extract the value expressions and types to set up the |
| 289 | // checker environment. |
| 290 | block := ruleExpr.AsCall() |
| 291 | ruleExpr = block.Args()[1].(ast.NavigableExpr) |
| 292 | |
| 293 | // Collect the list of variables associated with the block |
| 294 | blockList := block.Args()[0].(ast.NavigableExpr) |
| 295 | vars := blockList.AsList() |
| 296 | if vars.Size() != len(opt.varIndices) { |
| 297 | ctx.ReportErrorAtID(ruleExpr.ID(), "ast block list and computed one have different sizes") |
| 298 | return a |
| 299 | } |
| 300 | varExprs = make([]ast.Expr, vars.Size()) |
| 301 | varDecls = make([]cel.EnvOption, vars.Size()) |
| 302 | for i, v := range opt.varIndices { |
| 303 | if i >= len(varExprs) { |
| 304 | break |
| 305 | } |
| 306 | varDecls[i] = cel.Variable(v.indexVar, v.celType) |
| 307 | varExprs[i] = v.expr |
| 308 | } |
| 309 | } |
| 310 | if len(varDecls) != 0 { |
| 311 | err := ctx.ExtendEnv(varDecls...) |
| 312 | if err != nil { |
| 313 | ctx.ReportErrorAtID(ruleExpr.ID(), "%s", err.Error()) |
| 314 | } |
| 315 | } |
| 316 | |
| 317 | // Attempt to unnest the rule. |
| 318 | ruleExpr = opt.maybeUnnestRule(ctx, ruleExpr) |
| 319 | // If there were no variables, return the expression. |
| 320 | if len(opt.varIndices) == 0 { |
| 321 | return a |
| 322 | } |
| 323 | |
| 324 | // Otherwise populate the cel.@block with the variable declarations and wrap the expression |
| 325 | // in the block. |
| 326 | for i := unnestOffset; i < len(opt.varIndices); i++ { |
| 327 | vi := opt.varIndices[i] |
| 328 | varExprs = append(varExprs, vi.expr) |
| 329 | err := ctx.ExtendEnv(cel.Variable(vi.indexVar, vi.celType)) |
| 330 | if err != nil { |
| 331 | ctx.ReportErrorAtID(ruleExpr.ID(), "%s", err.Error()) |
| 332 | } |
| 333 | } |
| 334 | blockExpr := ctx.NewCall("cel.@block", ctx.NewList(varExprs, []int32{}), ruleExpr) |
| 335 | return ctx.NewAST(blockExpr) |
| 336 | } |
nothing calls this directly
no test coverage detected