docs: def qasm(val: Any,
           *,
           args: Optional[QasmArgs] = None,
           qubits: Optional[Iterable['cirq.Qid']] = None,
           default: TDefault = RaiseTypeErrorIfNotProvided
           ) -> Union[str, TDefault]:
      """Returns QASM code for the given value, if possible.
  
      Different values require different sets of arguments. The general rule of
      thumb is that circuits don't need any, operations need a `QasmArgs`, and
      gates need both a `QasmArgs` and `qubits`.
  
      Args:
          val: The value to turn into QASM code.
          args: A `QasmArgs` object to pass into the value's `_qasm_` method.
              This is for needed for objects that only have a local idea of what's
              going on, e.g. a `cirq.Operation` in a bigger `cirq.Circuit`
              involving qubits that the operation wouldn't otherwise know about.
          qubits: A list of qubits that the value is being applied to. This is
              needed for `cirq.Gate` values, which otherwise wouldn't know what
              qubits to talk about.
          default: A default result to use if the value doesn't have a
              `_qasm_` method or that method returns `NotImplemented` or
              `None`. If not specified, undecomposable values cause a `TypeError`.
  
      Returns:
          The result of `val._qasm_(...)`, if `val` has a `_qasm_`
          method and it didn't return `NotImplemented` or `None`. Otherwise
          `default` is returned, if it was specified. Otherwise an error is
          raised.
  
      TypeError:
          `val` didn't have a `_qasm_` method (or that method returned
          `NotImplemented` or `None`) and `default` wasn't set.
      """
      method = getattr(val, '_qasm_', None)
      result = NotImplemented
      if method is not None:
          kwargs = {}  # type: Dict[str, Any]
          if args is not None:
              kwargs['args'] = args
          if qubits is not None:
              kwargs['qubits'] = tuple(qubits)
          result = method(**kwargs)
      if result is not None and result is not NotImplemented:
          return result
  
      if default is not RaiseTypeErrorIfNotProvided:
          return default
      if method is None:
          raise TypeError("object of type '{}' "
                          "has no _qasm_ method.".format(type(val)))
      raise TypeError("object of type '{}' does have a _qasm_ method, "
                      "but it returned NotImplemented or None.".format(type(val)))