newProgram creates a program instance with an environment, an ast, and an optional list of ProgramOption values. If the program cannot be configured the prog will be nil, with a non-nil error response.
(e *Env, a *ast.AST, opts []ProgramOption)
| 171 | // |
| 172 | // If the program cannot be configured the prog will be nil, with a non-nil error response. |
| 173 | func newProgram(e *Env, a *ast.AST, opts []ProgramOption) (Program, error) { |
| 174 | // Build the dispatcher, interpreter, and default program value. |
| 175 | disp := interpreter.NewDispatcher() |
| 176 | |
| 177 | // Ensure the default attribute factory is set after the adapter and provider are |
| 178 | // configured. |
| 179 | p := &prog{ |
| 180 | Env: e, |
| 181 | plannerOptions: []interpreter.PlannerOption{}, |
| 182 | dispatcher: disp, |
| 183 | costOptions: []interpreter.CostTrackerOption{}, |
| 184 | } |
| 185 | |
| 186 | // Configure the program via the ProgramOption values. |
| 187 | var err error |
| 188 | for _, opt := range opts { |
| 189 | p, err = opt(p) |
| 190 | if err != nil { |
| 191 | return nil, err |
| 192 | } |
| 193 | } |
| 194 | |
| 195 | e.funcBindOnce.Do(func() { |
| 196 | var bindings []*functions.Overload |
| 197 | e.functionBindings = []*functions.Overload{} |
| 198 | for _, fn := range e.functions { |
| 199 | bindings, err = fn.Bindings() |
| 200 | if err != nil { |
| 201 | return |
| 202 | } |
| 203 | e.functionBindings = append(e.functionBindings, bindings...) |
| 204 | } |
| 205 | }) |
| 206 | if err != nil { |
| 207 | return nil, err |
| 208 | } |
| 209 | |
| 210 | // Add the function bindings created via Function() options. |
| 211 | err = disp.Add(e.functionBindings...) |
| 212 | if err != nil { |
| 213 | return nil, err |
| 214 | } |
| 215 | |
| 216 | // Set the attribute factory after the options have been set. |
| 217 | var attrFactory interpreter.AttributeFactory |
| 218 | attrFactorOpts := []interpreter.AttrFactoryOption{ |
| 219 | interpreter.EnableErrorOnBadPresenceTest(p.HasFeature(featureEnableErrorOnBadPresenceTest)), |
| 220 | } |
| 221 | if a.SourceInfo().HasExtension("json_name", ast.NewExtensionVersion(1, 1)) { |
| 222 | if !e.HasFeature(featureJSONFieldNames) { |
| 223 | return nil, errors.New("the AST extension 'json_name' requires the option cel.JSONFieldNames(true)") |
| 224 | } |
| 225 | } |
| 226 | // Configure the type provider, considering whether the AST indicates whether it supports JSON field names |
| 227 | if p.evalOpts&OptPartialEval == OptPartialEval { |
| 228 | attrFactory = interpreter.NewPartialAttributeFactory(e.Container, e.adapter, e.provider, attrFactorOpts...) |
| 229 | } else { |
| 230 | attrFactory = interpreter.NewAttributeFactory(e.Container, e.adapter, e.provider, attrFactorOpts...) |
no test coverage detected