def decompose(
    val: Any,
    *,
    intercepting_decomposer: OpDecomposer | None = None,
    fallback_decomposer: OpDecomposer | None = None,
    keep: Callable[[cirq.Operation], bool] | None = None,
    on_stuck_raise: (
        None | Exception | Callable[[cirq.Operation], Exception | None]
    ) = _value_error_describing_bad_operation,
    preserve_structure: bool = False,
    context: DecompositionContext | None = None,
) -> list[cirq.Operation]:
    """Recursively decomposes a value into `cirq.Operation`s meeting a criteria.

    Args:
        val: The value to decompose into operations.
        intercepting_decomposer: An optional method that is called before the
            default decomposer (the value's `_decompose_` method). If
            `intercepting_decomposer` is specified and returns a result that
            isn't `NotImplemented` or `None`, that result is used. Otherwise the
            decomposition falls back to the default decomposer.

            Note that `val` will be passed into `intercepting_decomposer`, even
            if `val` isn't a `cirq.Operation`.
        fallback_decomposer: An optional decomposition that used after the
            `intercepting_decomposer` and the default decomposer (the value's
            `_decompose_` method) both fail.
        keep: A predicate that determines if the initial operation or
            intermediate decomposed operations should be kept or else need to be
            decomposed further. If `keep` isn't specified, it defaults to "value
            can't be decomposed anymore".
        on_stuck_raise: If there is an operation that can't be decomposed and
            also can't be kept, `on_stuck_raise` is used to determine what error
            to raise. `on_stuck_raise` can either directly be an `Exception`, or
            a method that takes the problematic operation and returns an
            `Exception`. If `on_stuck_raise` is set to `None` or a method that
            returns `None`, non-decomposable operations are simply silently
            kept. `on_stuck_raise` defaults to a `ValueError` describing the
            unwanted non-decomposable operation.
        preserve_structure: Prevents subcircuits (i.e. `CircuitOperation`s)
            from being decomposed, but decomposes their contents. If this is
            True, `intercepting_decomposer` cannot be specified.
        context: Decomposition context specifying common configurable options for
            controlling the behavior of decompose.

    Returns:
        A list of operations that the given value was decomposed into. If
        `on_stuck_raise` isn't set to None, all operations in the list will
        satisfy the predicate specified by `keep`.

    Raises:
        TypeError:
            `val` isn't a `cirq.Operation` and can't be decomposed even once.
            (So it's not possible to return a list of operations.)

        ValueError:
            Default type of error raised if there's an non-decomposable
            operation that doesn't satisfy the given `keep` predicate.

        TError:
            Custom type of error raised if there's an non-decomposable operation
            that doesn't satisfy the given `keep` predicate.
    """

    if (
        on_stuck_raise is not _value_error_describing_bad_operation
        and on_stuck_raise is not None
        and keep is None
    ):
        raise ValueError(
            "Must specify 'keep' if specifying 'on_stuck_raise', because it's "
            "not possible to get stuck if you don't have a criteria on what's "
            "acceptable to keep."
        )

    if context is None:
        context = DecompositionContext(ops.SimpleQubitManager(prefix='_decompose_protocol'))
    args = _DecomposeArgs(
        context=context,
        intercepting_decomposer=intercepting_decomposer,
        fallback_decomposer=fallback_decomposer,
        keep=keep,
        on_stuck_raise=on_stuck_raise,
        preserve_structure=preserve_structure,
    )
    return [*_decompose_dfs(val, args)]
Recursively decomposes a value into `cirq.Operation`s meeting a criteria.

    Args:
        val: The value to decompose into operations.
        intercepting_decomposer: An optional method that is called before the
            default decomposer (the value's `_decompose_` method). If
            `intercepting_decomposer` is specified and returns a result that
            isn't `NotImplemented` or `None`, that result is used. Otherwise the
            decomposition falls back to the default decomposer.

            Note that `val` will be passed into `intercepting_decomposer`, even
            if `val` isn't a `cirq.Operation`.
        fallback_decomposer: An optional decomposition that used after the
            `intercepting_decomposer` and the default decomposer (the value's
            `_decompose_` method) both fail.
        keep: A predicate that determines if the initial operation or
            intermediate decomposed operations should be kept or else need to be
            decomposed further. If `keep` isn't specified, it defaults to "value
            can't be decomposed anymore".
        on_stuck_raise: If there is an operation that can't be decomposed and
            also can't be kept, `on_stuck_raise` is used to determine what error
            to raise. `on_stuck_raise` can either directly be an `Exception`, or
            a method that takes the problematic operation and returns an
            `Exception`. If `on_stuck_raise` is set to `None` or a method that
            returns `None`, non-decomposable operations are simply silently
            kept. `on_stuck_raise` defaults to a `ValueError` describing the
            unwanted non-decomposable operation.
        preserve_structure: Prevents subcircuits (i.e. `CircuitOperation`s)
            from being decomposed, but decomposes their contents. If this is
            True, `intercepting_decomposer` cannot be specified.
        context: Decomposition context specifying common configurable options for
            controlling the behavior of decompose.

    Returns:
        A list of operations that the given value was decomposed into. If
        `on_stuck_raise` isn't set to None, all operations in the list will
        satisfy the predicate specified by `keep`.

    Raises:
        TypeError:
            `val` isn't a `cirq.Operation` and can't be decomposed even once.
            (So it's not possible to return a list of operations.)

        ValueError:
            Default type of error raised if there's an non-decomposable
            operation that doesn't satisfy the given `keep` predicate.

        TError:
            Custom type of error raised if there's an non-decomposable operation
            that doesn't satisfy the given `keep` predicate.
    
cirq-core/cirq/protocols/decompose_protocol.py