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

Method compileRule

policy/compiler.go:327–432  ·  view source on GitHub ↗
(r *Rule, p *Policy, ruleEnv *cel.Env, iss *cel.Issues, hasAggregateAncestor bool)

Source from the content-addressed store, hash-verified

325}
326
327func (c *compiler) compileRule(r *Rule, p *Policy, ruleEnv *cel.Env, iss *cel.Issues, hasAggregateAncestor bool) (*CompiledRule, *cel.Issues) {
328 if hasAggregateAncestor && r.semantic == aggregate {
329 iss.ReportErrorAtID(r.SourceID(), "nested aggregate rules are not allowed")
330 }
331 compiledVars := make([]*CompiledVariable, len(r.Variables()))
332 for i, v := range r.Variables() {
333 exprSrc := c.relSource(v.Expression())
334 varAST, exprIss := ruleEnv.CompileSource(exprSrc)
335 varName := v.Name().Value
336
337 // Determine the variable type. If the expression is an error then record the error and
338 // mark the variable type as dyn to permit compilation to continue.
339 varType := types.DynType
340 if exprIss.Err() != nil {
341 iss = iss.Append(exprIss)
342 } else {
343 // Otherwise, the expression compiled successfully and we use its output type.
344 varType = varAST.OutputType()
345 }
346
347 // Introduce the variable into the environment. By extending the environment, the variables
348 // are effectively scoped such that they must be declared before use.
349 varDecl := decls.NewVariable(fmt.Sprintf("%s.%s", variablePrefix, varName), varType)
350 varEnv, err := ruleEnv.Extend(cel.Variable(varDecl.Name(), varDecl.Type()))
351 if err != nil {
352 iss.ReportErrorAtID(v.exprID, "invalid variable declaration: %s", err.Error())
353 } else {
354 ruleEnv = varEnv
355 }
356 compiledVar := &CompiledVariable{
357 exprID: v.name.ID,
358 name: v.name.Value,
359 expr: varAST,
360 varDecl: varDecl,
361 }
362 compiledVars[i] = compiledVar
363
364 // Increment the nesting count post-compile.
365 c.nestedCount++
366 if c.nestedCount == c.maxNestedExpressions+1 {
367 iss.ReportErrorAtID(compiledVar.SourceID(), "variable exceeds nested expression limit")
368 }
369 }
370
371 // Compile the set of match conditions under the rule.
372 compiledMatches := []*CompiledMatch{}
373 for _, m := range r.Matches() {
374 condSrc := c.relSource(m.Condition())
375 condAST, condIss := ruleEnv.CompileSource(condSrc)
376 iss = iss.Append(condIss)
377 // This case cannot happen when the Policy object is parsed from yaml, but could happen
378 // with a non-YAML generation of the Policy object.
379 // TODO: Test this case once there's an alternative method of constructing Policy objects
380 if m.HasOutput() && m.HasRule() {
381 iss.ReportErrorAtID(m.Condition().ID, "either output or rule may be set but not both")
382 continue
383 }
384 if m.HasOutput() {

Callers 2

CompileRuleFunction · 0.95
TestRuleComposerUnnestFunction · 0.45

Calls 15

relSourceMethod · 0.95
NameMethod · 0.95
SourceIDMethod · 0.95
checkUnreachableCodeMethod · 0.95
NewVariableFunction · 0.92
VariableFunction · 0.92
ExpressionMethod · 0.80
CompileSourceMethod · 0.80
ErrMethod · 0.80
HasOutputMethod · 0.80
HasRuleMethod · 0.80

Tested by 1

TestRuleComposerUnnestFunction · 0.36