# Path: typpete/src/constants.py
# ALIASES = {
#     'Dict': 'dict',
#     'Set': 'set',
#     'List': 'list',
#     'str': 'str'
# }
# 
# Path: typpete/src/z3_types.py
# class Dummy():
# class DummyOptimize:
# class TypesSolver(Solver):
# class Z3Types:
#     def add_soft(self, *args, **kwargs):
#     def add(self, *args, **kwargs):
#     def __init__(self, tree, solver=None, ctx=None, base_folder='',
#                  type_params:dict=None, class_type_params: dict=None):
#     def add(self, *args, fail_message):
#     def init_axioms(self):
#     def infer_stubs(self, context, infer_func):
#     def new_element_id(self):
#     def new_z3_const(self, name, sort=None):
#     def resolve_annotation(self, annotation, module):
#     def __init__(self, config, solver):
#     def subtype(self, t0, t1):
#     def create_class_tree(all_classes, type_sort):
#     def create_subst_axioms(self, tree):
#     def create_subtype_axioms(self, tree):
# def declare_type_sort(max_tuple_length, max_function_args, classes_to_base, type_vars):
# def create_classes_attributes(type_sort, classes_to_attrs, attributes_map):


from typpete.src.constants import ALIASES
from typpete.src.z3_types import And, Or, Implies, Not
            And(left == types.list(types.list_type(left)), right == left),
            And(left == types.set(types.set_type(left)), right == types.set(types.set_type(right))),
            And(types.subtype(left, types.tuple), types.subtype(right, types.tuple)),
            And(left == types.string, right == types.string),
            And(left == types.bytes, right == types.bytes),
        ]
        + overloading_axioms(left, right, types.bool, method_name, types)
        )
    ]



def add(left, right, result, types):
    """Constraints for the addition operation
    
    Cases:
        - Number_1 + Number_2 --> Stronger(Number_1, Number_2)
        - Sequence + Sequence --> Sequence
    
    Ex:
        - 1 + 2.0
        - [1, 2, 3] + [4]
        - "string" + "string2"
    
    TODO: Tuples addition
    """
    return [
        And(left != types.none, right != types.none),
        Or([
               And(types.subtype(left, types.complex), types.subtype(right, left), result == left),

# Path: typpete/src/constants.py
# ALIASES = {
#     'Dict': 'dict',
#     'Set': 'set',
#     'List': 'list',
#     'str': 'str'
# }
# 
# Path: typpete/src/z3_types.py
# class Dummy():
# class DummyOptimize:
# class TypesSolver(Solver):
# class Z3Types:
#     def add_soft(self, *args, **kwargs):
#     def add(self, *args, **kwargs):
#     def __init__(self, tree, solver=None, ctx=None, base_folder='',
#                  type_params:dict=None, class_type_params: dict=None):
#     def add(self, *args, fail_message):
#     def init_axioms(self):
#     def infer_stubs(self, context, infer_func):
#     def new_element_id(self):
#     def new_z3_const(self, name, sort=None):
#     def resolve_annotation(self, annotation, module):
#     def __init__(self, config, solver):
#     def subtype(self, t0, t1):
#     def create_class_tree(all_classes, type_sort):
#     def create_subst_axioms(self, tree):
#     def create_subtype_axioms(self, tree):
# def declare_type_sort(max_tuple_length, max_function_args, classes_to_base, type_vars):
# def create_classes_attributes(type_sort, classes_to_attrs, attributes_map):


# Path: typpete/src/z3_axioms.py
from typpete.src.constants import ALIASES
from typpete.src.z3_types import And, Or, Implies, Not

            And(left == types.list(types.list_type(left)), right == left),
            And(left == types.set(types.set_type(left)), right == types.set(types.set_type(right))),
            And(types.subtype(left, types.tuple), types.subtype(right, types.tuple)),
            And(left == types.string, right == types.string),
            And(left == types.bytes, right == types.bytes),
        ]
        + overloading_axioms(left, right, types.bool, method_name, types)
        )
    ]



def add(left, right, result, types):
    """Constraints for the addition operation
    
    Cases:
        - Number_1 + Number_2 --> Stronger(Number_1, Number_2)
        - Sequence + Sequence --> Sequence
    
    Ex:
        - 1 + 2.0
        - [1, 2, 3] + [4]
        - "string" + "string2"
    
    TODO: Tuples addition
    """
    return [
        And(left != types.none, right != types.none),
        Or([
               And(types.subtype(left, types.complex), types.subtype(right, left), result == left),

               And(types.subtype(right, types.complex), types.subtype(left, right), result == right),