Source code for autoqasm.types.conversions

# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"). You
# may not use this file except in compliance with the License. A copy of
# the License is located at
#
#     http://aws.amazon.com/apache2.0/
#
# or in the "license" file accompanying this file. This file is
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.

"""Type conversions between Python and the autoqasm representation for types."""

from __future__ import annotations

import typing
from functools import singledispatch
from typing import Any

import numpy as np
import oqpy
from openpulse import ast

from autoqasm import errors
from autoqasm import types as aq_types


[docs] def map_parameter_type(python_type: type) -> type: """Maps a given Python function parameter type to the corresponding oqpy subroutine parameter type. Args: python_type (type): The Python type to be mapped. Returns: type: The corresponding oqpy type. """ origin_type = typing.get_origin(python_type) or python_type if python_type == aq_types.QubitIdentifierType: return oqpy.Qubit if issubclass(origin_type, bool): return oqpy.BoolVar if issubclass(origin_type, (int, np.integer)): return oqpy.IntVar if issubclass(origin_type, (float, np.floating)): return oqpy.FloatVar if issubclass(origin_type, tuple) or issubclass(origin_type, list): raise errors.ParameterTypeError( "Lists and tuples are not supported as parameters to AutoQASM functions; " "consider passing the values as multiple separate parameters." ) return python_type
[docs] def var_type_from_ast_type(ast_type: ast.ClassicalType) -> type: """Converts an OpenQASM AST type to the corresponding AutoQASM variable type. Args: ast_type (ast.ClassicalType): The OpenQASM AST type to be converted. Returns: type: The corresponding AutoQASM variable type. """ if isinstance(ast_type, ast.IntType): return aq_types.IntVar if isinstance(ast_type, ast.FloatType): return aq_types.FloatVar if isinstance(ast_type, ast.BoolType): return aq_types.BoolVar if isinstance(ast_type, ast.BitType): return aq_types.BitVar if isinstance(ast_type, ast.ArrayType): return aq_types.ArrayVar raise NotImplementedError
[docs] def var_type_from_oqpy(expr_or_var: oqpy.base.OQPyExpression | oqpy.base.Var) -> type: """Returns the AutoQASM variable type corresponding to the provided OQPy object. Args: expr_or_var (OQPyExpression | Var): An OQPy expression or variable. Returns: type: The corresponding AutoQASM variable type. """ if isinstance(expr_or_var, oqpy.base.OQPyExpression): return var_type_from_ast_type(expr_or_var.type) return type(expr_or_var)
[docs] @singledispatch def wrap_value(node: Any) -> Any: """Wraps an object in an autoqasm variable. Args: node (Any): The object to be wrapped. Raises: NotImplementedError: If logic for wrapping the given object type does not exist. Returns: Any: The autoqasm variable wrapping the given object. """ if node is None: return None # TODO add any missing cases raise NotImplementedError(node)
@wrap_value.register(tuple) def _(node: tuple): return tuple(wrap_value(item) for item in node) @wrap_value.register(bool) def _(node: bool): return aq_types.BoolVar(node) @wrap_value.register(int) @wrap_value.register(np.integer) def _(node: int | np.integer): return aq_types.IntVar(node) @wrap_value.register(float) @wrap_value.register(np.floating) def _(node: float | np.floating): return aq_types.FloatVar(node) @wrap_value.register def _(node: oqpy.base.Var): return node @wrap_value.register def _(node: oqpy.base.OQPyExpression): return node