def defgate_to_cirq(defgate: DefGate):
    """Convert a Quil DefGate to a Cirq Gate class.

    For non-parametric gates, it's recommended to create `MatrixGate` object. This function is
    intended for the case of parametric gates.

    Args:
        defgate: A quil gate defintion.
    Returns:
        A subclass of `Gate` corresponding to the DefGate.
    """
    name = defgate.name
    matrix = defgate.matrix
    parameters = defgate.parameters
    dim = int(np.sqrt(matrix.shape[0]))
    if parameters:
        parameter_names = set(p.name for p in parameters)

        def constructor(self, **kwargs):
            for p, val in kwargs.items():
                assert p in parameter_names, f"{p} is not a known parameter"
                setattr(self, p, val)

        def unitary(self, *args):
            if parameters:
                parameter_map = {p: getattr(self, p.name) for p in parameters}
                return substitute_array(matrix, parameter_map)

    else:

        def constructor(self, **kwards: Any): ...

        def unitary(self, *args):  # pragma: no cover
            return matrix

    def circuit_diagram_info(
        self, args: CircuitDiagramInfoArgs
    ) -> CircuitDiagramInfo:  # pragma: no cover
        return CircuitDiagramInfo(wire_symbols=tuple(name for _ in range(dim)))

    def num_qubits(self):
        return defgate.num_args()

    gate = type(
        name,
        (Gate,),
        {
            "__init__": constructor,
            "_num_qubits_": num_qubits,
            "_unitary_": unitary,
            "_circuit_diagram_info_": circuit_diagram_info,
        },
    )
    return gate
Convert a Quil DefGate to a Cirq Gate class.

    For non-parametric gates, it's recommended to create `MatrixGate` object. This function is
    intended for the case of parametric gates.

    Args:
        defgate: A quil gate defintion.
    Returns:
        A subclass of `Gate` corresponding to the DefGate.
    
cirq-rigetti/cirq_rigetti/quil_input.py