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)
| 205 | // |
| 206 | // If the program cannot be configured the prog will be nil, with a non-nil error response. |
| 207 | func newProgram(e *Env, a *ast.AST, opts []ProgramOption) (Program, error) { |
| 208 | // Build the dispatcher, interpreter, and default program value. |
| 209 | disp := interpreter.NewDispatcher() |
| 210 | |
| 211 | // Ensure the default attribute factory is set after the adapter and provider are |
| 212 | // configured. |
| 213 | p := &prog{ |
| 214 | Env: e, |
| 215 | plannerOptions: []interpreter.PlannerOption{}, |
| 216 | dispatcher: disp, |
| 217 | costOptions: []interpreter.CostTrackerOption{}, |
| 218 | drainStrategy: async.DrainReady(100 * time.Microsecond), |
| 219 | } |
| 220 | |
| 221 | // Configure the program via the ProgramOption values. |
| 222 | var err error |
| 223 | for _, opt := range opts { |
| 224 | p, err = opt(p) |
| 225 | if err != nil { |
| 226 | return nil, err |
| 227 | } |
| 228 | } |
| 229 | |
| 230 | e.funcBindOnce.Do(func() { |
| 231 | var bindings []*functions.Overload |
| 232 | e.functionBindings = []*functions.Overload{} |
| 233 | for _, fn := range e.functions { |
| 234 | bindings, err = fn.Bindings() |
| 235 | if err != nil { |
| 236 | return |
| 237 | } |
| 238 | e.functionBindings = append(e.functionBindings, bindings...) |
| 239 | } |
| 240 | }) |
| 241 | if err != nil { |
| 242 | return nil, err |
| 243 | } |
| 244 | |
| 245 | // Add the function bindings created via Function() options. |
| 246 | err = disp.Add(e.functionBindings...) |
| 247 | if err != nil { |
| 248 | return nil, err |
| 249 | } |
| 250 | |
| 251 | // Determine whether the environment declares any asynchronous function. Async is a property of |
| 252 | // the binding, so its presence is known from the environment alone, without inspecting the |
| 253 | // program plan. The synchronous entry points (Eval, ContextEval) reject programs from an env |
| 254 | // with async functions; callers needing synchronous evaluation should use a non-async env. |
| 255 | for _, b := range e.functionBindings { |
| 256 | if b.Async != nil { |
| 257 | p.hasAsync = true |
| 258 | break |
| 259 | } |
| 260 | } |
| 261 | |
| 262 | // Set the attribute factory after the options have been set. |
| 263 | var attrFactory interpreter.AttributeFactory |
| 264 | attrFactorOpts := []interpreter.AttrFactoryOption{ |
no test coverage detected