Compose stitches together a set of expressions within a CompiledRule into a single CEL ast.
(r *CompiledRule)
| 72 | |
| 73 | // Compose stitches together a set of expressions within a CompiledRule into a single CEL ast. |
| 74 | func (c *RuleComposer) Compose(r *CompiledRule) (*cel.Ast, *cel.Issues) { |
| 75 | ruleRoot, _ := c.env.Compile("true") |
| 76 | composer := &ruleComposerImpl{ |
| 77 | rule: r, |
| 78 | varIndices: []varIndex{}, |
| 79 | } |
| 80 | // ruleRoot is a placeholder expression used as the root of the AST before optimization. Because |
| 81 | // StaticOptimizer would normally copy the source info from it, we must use OptimizeWithSource |
| 82 | // to override the correct source. |
| 83 | source := recoverOriginalSource(r) |
| 84 | opt, err := cel.NewStaticOptimizer(composer, cel.OptimizeWithSource(source)) |
| 85 | if err != nil { |
| 86 | errs := common.NewErrors(source) |
| 87 | errs.ReportErrorString(common.NoLocation, err.Error()) |
| 88 | return nil, cel.NewIssues(errs) |
| 89 | } |
| 90 | ast, iss := opt.Optimize(c.env, ruleRoot) |
| 91 | if iss.Err() != nil { |
| 92 | return nil, iss |
| 93 | } |
| 94 | unnester := &ruleUnnesterImpl{ |
| 95 | nextVarIndex: len(composer.varIndices), |
| 96 | varIndices: composer.varIndices, |
| 97 | exprUnnestHeight: c.exprUnnestHeight, |
| 98 | } |
| 99 | opt, err = cel.NewStaticOptimizer(unnester) |
| 100 | if err != nil { |
| 101 | errs := common.NewErrors(source) |
| 102 | errs.ReportErrorString(common.NoLocation, err.Error()) |
| 103 | return nil, cel.NewIssues(errs) |
| 104 | } |
| 105 | return opt.Optimize(c.env, ast) |
| 106 | } |
| 107 | |
| 108 | func recoverOriginalSource(r *CompiledRule) cel.Source { |
| 109 | match := r.Matches()[0] |