class_docstr: This class is a singleton builder to construct a MIL program. For more
  information, see `Create a MIL program <https://coremltools.readme.io/docs/model-intermediate-language#create-a-mil-program>`_.
  
  Importing ``.ops`` triggers the installation of all MIL ops into the Builder.
  For details on each op, see `MIL ops <https://apple.github.io/coremltools/source/coremltools.converters.mil.mil.ops.defs.html>`_.
  
  Examples
  --------
  
  >>> from coremltools.converters.mil.mil import Builder as mb
  >>> from coremltools.converters.mil.mil import Program, Function
  
  >>> prog = Program()
  >>> func_inputs = {"x": mb.placeholder(shape=[2,3]),
  >>>                "y": mb.placeholder(shape=[2,3])}
  >>> with Function(func_inputs) as ssa_fun:
  >>>   x, y = ssa_fun.inputs['x'], ssa_fun.inputs['y']
  >>>   res_var = mb.add(x=x, y=y) # created within ssa_fun block
  >>>   ssa_fun.set_outputs([res_var])
  >>> prog.add_function("main", ssa_fun)
  
  >>> # Importing ops triggers installation of all ops into Builder.
  >>> from .ops import defs as _ops
docstr: Add an op of type `op_cls` (e.g., convolution) to current block.
docstr_tok: ["Add","an","op","of","type","`","op_cls","`","(","e.g.",",","convolution",")","to","current","block","."]
code: def _add_op(cls, op_cls, **kwargs):
      """
      Add an op of type `op_cls` (e.g., convolution) to current block.
      """
      kwargs = cls._maybe_set_name(kwargs, op_cls.__name__)
      logger.debug(
          "Adding op '{}' of type {}".format(
              kwargs["name"], op_cls.__name__
          )
      )
      before_op = kwargs.get("before_op", None)
      # Shallow copy list inputs to ensure op inputs are immutable
      kwargs = {
          k: v if not isinstance(v, (list, tuple)) else v[:]
          for k, v in kwargs.items()
          if v is not None
      }
      kwargs.update(
          cls._create_vars(
              input_spec=op_cls.input_spec,
              op_name=kwargs["name"],
              before_op=before_op,
              candidate_kv=kwargs,
          )
      )
      kwargs["enclosing_block"] = curr_block()
      new_op = op_cls(**kwargs)
  
      # Initialize optional input Vars if it wasn't in kwargs
      default_inputs = new_op.default_inputs()
      # Shallow copy list inputs to ensure op inputs are immutable
      missing_optional_vals = {
          k: v if not isinstance(v, (list, tuple)) else v[:]
          for k, v in default_inputs.items()
          if k not in kwargs and v is not None
      }
      missing_optional_vars = cls._create_vars(
          input_spec=op_cls.input_spec,
          op_name=kwargs["name"],
          before_op=before_op,
          candidate_kv=missing_optional_vals,
      )
      new_op.set_inputs(type_inference=False, **missing_optional_vars)
  
      curr_block()._insert_op_before(new_op, before_op=before_op)
      new_op.build_nested_blocks()
      new_op.type_value_inference()
      if len(new_op.outputs) == 1:
          return new_op.outputs[0]
      return new_op.outputs
  
imports: import numbers
  from collections import defaultdict
  from typing import Callable, List, Optional
  import numpy
  from coremltools import _logger
  from coremltools.converters.mil._deployment_compatibility import AvailableTarget
  from coremltools.converters.mil.mil.types.symbolic import any_symbolic
  from .block import Function, curr_block
  from .input_type import InternalInputType, ListOrTensorInputType, TensorInputType, TupleInputType
  from .program import Placeholder, Program
  from .var import InternalVar, Var
label_desc: Use image node_id 5 for calling the Builder obj's underlying member method code with example usage: obj._add_op(cls, op_cls) and returns: new_op, new_op