# This file is automatically generated by pyo3_stub_gen
# ruff: noqa: E501, F401

import builtins
import quil.instructions
import typing
from enum import Enum

class EvaluationError(builtins.QuilError):
    r"""
    Errors that may occur while evaluation an ``Expression``.
    """
    ...

class Expression:
    r"""
    The type of Quil expressions.
    
    Quil expressions take advantage of *structural sharing*; if a Quil expression contains the same
    subexpression twice, such as `x + y` in `(x + y) * (x + y)`, the two children of the `*` node
    will be the *same pointer*.  This is implemented through *interning*, also known as
    *hash-consing*; the recursive references to child nodes are done via [`ArcIntern<Expression>`]s.
    Creating an [`ArcIntern`] from an `Expression` will always return the same pointer for the same
    expression.
    
    The structural sharing means that equality, cloning, and hashing on Quil expressions are all
    very cheap, as they do not need to be recursive: equality of [`ArcIntern`]s is a single-pointer
    comparison, cloning of [`ArcIntern`]s is a pointer copy and an atomic increment, and hashing of
    [`ArcIntern`]s hashes a single pointer.  It is also very cheap to key [`HashMap`]s by an
    [`ArcIntern<Expression>`], which can allow for cheap memoization of operations on `Expression`s.
    
    The structural sharing also means that Quil expressions are fundamentally *immutable*; it is
    *impossible* to get an owned or `&mut` reference to the child `Expression`s of any `Expression`,
    as the use of interning means there may be multiple references to that `Expression` at any time.
    
    Note that when comparing Quil expressions, any embedded NaNs are treated as *equal* to other
    NaNs, not unequal, in contravention of the IEEE 754 spec.
    """
    def __add__(self, other:Expression) -> Expression: ...
    def __getnewargs__(self) -> tuple[MemoryReference | FunctionCallExpression | InfixExpression | complex | PrefixExpression | str]: ...
    def __mul__(self, other:Expression) -> Expression: ...
    def __repr__(self) -> builtins.str: ...
    def __sub__(self, other:Expression) -> Expression: ...
    def __truediv__(self, other:Expression) -> Expression: ...
    def evaluate(self, variables:typing.Mapping[builtins.str, builtins.complex], memory_references:typing.Mapping[builtins.str, typing.Sequence[builtins.float]]) -> builtins.complex:
        r"""
        Evaluate an expression, expecting that it may be fully reduced to a single complex number.
        
        If it cannot be reduced to a complex number, this raises an error.
        """
    def into_simplified(self) -> Expression:
        r"""
        Return an expression derived from this one, simplified as much as possible.
        """
    @staticmethod
    def parse(input:builtins.str) -> Expression:
        r"""
        Parse an ``Expression`` from a string.
        
        Raises a ``ParseExpressionError`` error if the string isn't a valid Quil expression.
        """
    def substitute_variables(self, variable_values:typing.Mapping[builtins.str, Expression]) -> Expression:
        r"""
        Substitute an expression in the place of each matching variable.
        """
    def to_real(self) -> builtins.float:
        r"""
        If this is a number with imaginary part "equal to" zero (of _small_ absolute value), return
        that number. Otherwise, error with an evaluation error of a descriptive type.
        """
    class Address(Expression):
        __match_args__ = ("_0",)
        @property
        def _0(self) -> MemoryReference: ...
        def __getitem__(self, key:builtins.int) -> typing.Any: ...
        def __len__(self) -> builtins.int: ...
        def __new__(cls, _0:MemoryReference) -> Expression.Address: ...
    
    class FunctionCall(Expression):
        __match_args__ = ("_0",)
        @property
        def _0(self) -> FunctionCallExpression: ...
        def __getitem__(self, key:builtins.int) -> typing.Any: ...
        def __len__(self) -> builtins.int: ...
        def __new__(cls, _0:FunctionCallExpression) -> Expression.FunctionCall: ...
    
    class Infix(Expression):
        __match_args__ = ("_0",)
        @property
        def _0(self) -> InfixExpression: ...
        def __getitem__(self, key:builtins.int) -> typing.Any: ...
        def __len__(self) -> builtins.int: ...
        def __new__(cls, _0:InfixExpression) -> Expression.Infix: ...
    
    class Number(Expression):
        __match_args__ = ("_0",)
        @property
        def _0(self) -> builtins.complex: ...
        def __getitem__(self, key:builtins.int) -> typing.Any: ...
        def __len__(self) -> builtins.int: ...
        def __new__(cls, _0:builtins.complex) -> Expression.Number: ...
    
    class Pi(Expression):
        __match_args__ = ((),)
        def __getitem__(self, key:builtins.int) -> typing.Any: ...
        def __len__(self) -> builtins.int: ...
        def __new__(cls) -> Expression.Pi: ...
    
    class Prefix(Expression):
        __match_args__ = ("_0",)
        @property
        def _0(self) -> PrefixExpression: ...
        def __getitem__(self, key:builtins.int) -> typing.Any: ...
        def __len__(self) -> builtins.int: ...
        def __new__(cls, _0:PrefixExpression) -> Expression.Prefix: ...
    
    class Variable(Expression):
        __match_args__ = ("_0",)
        @property
        def _0(self) -> builtins.str: ...
        def __getitem__(self, key:builtins.int) -> typing.Any: ...
        def __len__(self) -> builtins.int: ...
        def __new__(cls, _0:builtins.str) -> Expression.Variable: ...
    

class FunctionCallExpression:
    r"""
    The type of function call Quil expressions, e.g. `sin(e)`.
    
    Quil expressions take advantage of *structural sharing*, which is why the `expression` here is
    wrapped in an [`ArcIntern`]; for more details, see the documentation for [`Expression`].
    
    Note that when comparing Quil expressions, any embedded NaNs are treated as *equal* to other
    NaNs, not unequal, in contravention of the IEEE 754 spec.
    """
    @property
    def expression(self) -> Expression: ...
    @property
    def function(self) -> ExpressionFunction: ...
    def __eq__(self, other:builtins.object) -> builtins.bool: ...
    def __getnewargs__(self) -> tuple[ExpressionFunction, Expression]: ...
    def __hash__(self) -> builtins.int: ...
    def __new__(cls, function:ExpressionFunction, expression:Expression) -> FunctionCallExpression: ...
    def __repr__(self) -> builtins.str: ...

class InfixExpression:
    r"""
    The type of infix Quil expressions, e.g. `e1 + e2`.
    
    Quil expressions take advantage of *structural sharing*, which is why the `left` and `right`
    expressions here are wrapped in [`ArcIntern`]s; for more details, see the documentation for
    [`Expression`].
    
    Note that when comparing Quil expressions, any embedded NaNs are treated as *equal* to other
    NaNs, not unequal, in contravention of the IEEE 754 spec.
    """
    @property
    def left(self) -> Expression: ...
    @property
    def operator(self) -> InfixOperator: ...
    @property
    def right(self) -> Expression: ...
    def __eq__(self, other:builtins.object) -> builtins.bool: ...
    def __getnewargs__(self) -> tuple[Expression, InfixOperator, Expression]: ...
    def __hash__(self) -> builtins.int: ...
    def __new__(cls, left:Expression, operator:InfixOperator, right:Expression) -> InfixExpression: ...
    def __repr__(self) -> builtins.str: ...

class ParseExpressionError(builtins.QuilError):
    r"""
    Errors that may occur while parsing an ``Expression``.
    """
    ...

class PrefixExpression:
    r"""
    The type of prefix Quil expressions, e.g. `-e`.
    
    Quil expressions take advantage of *structural sharing*, which is why the `expression` here is
    wrapped in an [`ArcIntern`]; for more details, see the documentation for [`Expression`].
    
    Note that when comparing Quil expressions, any embedded NaNs are treated as *equal* to other
    NaNs, not unequal, in contravention of the IEEE 754 spec.
    """
    @property
    def expression(self) -> Expression: ...
    @property
    def operator(self) -> PrefixOperator: ...
    def __eq__(self, other:builtins.object) -> builtins.bool: ...
    def __getnewargs__(self) -> tuple[PrefixOperator, Expression]: ...
    def __hash__(self) -> builtins.int: ...
    def __new__(cls, operator:PrefixOperator, expression:Expression) -> PrefixExpression: ...
    def __repr__(self) -> builtins.str: ...

class ExpressionFunction(Enum):
    r"""
    A function defined within Quil syntax.
    """
    Cis = ...
    Cosine = ...
    Exponent = ...
    Sine = ...
    SquareRoot = ...

    def __getnewargs__(self) -> tuple[builtins.int]: ...
    def __new__(cls, value:builtins.int) -> ExpressionFunction: ...
    def __repr__(self) -> builtins.str: ...

class InfixOperator(Enum):
    Caret = ...
    Plus = ...
    Minus = ...
    Slash = ...
    Star = ...

    def __getnewargs__(self) -> tuple[builtins.int]: ...
    def __new__(cls, value:builtins.int) -> InfixOperator: ...
    def __repr__(self) -> builtins.str: ...

class PrefixOperator(Enum):
    Plus = ...
    Minus = ...

    def __getnewargs__(self) -> tuple[builtins.int]: ...
    def __new__(cls, value:builtins.int) -> PrefixOperator: ...
    def __repr__(self) -> builtins.str: ...

