class_docstr: Identify complex data related ops and replace it by using real and imaginary parts separately.
  The goal of this pass it to lower complex dialect ops into core ops.
  
  This pass also checks if the output is complex. As Core ML doesn't support complex data yet,
  it errors out early when detecting complex output.
  
  Input graph (`complex` and `complex_real` are complex dialect ops):
      %complex_data = complex(real_data=%real_data, imag_data=%imag_data)
      %real_data = complex_real(data=%complex_data)
      return %real_data
  
  Output graph (only core ops, no complex dialect ops):
      %complex_data_real = identity(x=%real_data)
      %complex_data_imag = identity(x=%imag_data)
      %real_data = identity(data=%complex_data_real)
      return %real_data
code: def apply(self, prog):
      for block in prog.functions.values():
          # Early error out for complex data output.
          for out_var in block.outputs:
              if types.is_complex(out_var.dtype):
                  raise ValueError(
                      "MIL doesn't support complex data as model's output, please "
                      "extract real and imaginary parts explicitly."
                  )
  
          _lower_complex_dialect_ops_in_block(block)
  
imports: import functools
  from typing import Callable, Dict, Optional, Tuple
  import numpy
  from coremltools.converters.mil.mil import Builder
  from coremltools.converters.mil.mil import types
  from coremltools.converters.mil.mil.operation import Operation
  from coremltools.converters.mil.mil.ops.defs.complex_dialect_ops import fft_canonicalize_length_dim, fft_canonicalize_shapes_dims
  from coremltools.converters.mil.mil.passes.graph_pass import AbstractGraphPass
  from coremltools.converters.mil.mil.passes.helper import block_context_manager
  from coremltools.converters.mil.mil.passes.pass_registry import register_pass
  from coremltools.converters.mil.mil.var import ComplexVar, Var
label_desc: Use image node_id 1 for calling the lower_complex_dialect_ops obj's underlying member method code with example usage: obj.apply(prog) without return types