# 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
                axioms.append(And(class_type == types.all_types[t],
                                  Or(function_call_axioms(attr_type, args, result, types))))
    return axioms


def instancemethod_call(instance, args, result, attr, types, tvs):
    """Constraints for calls on instances

    There are two cases:
    - The called is an instance method
    - The called is a normal instance attribute which happens to be callable

    In the first case, check that it appears in the class instance methods and is not static method
    In the second case, check that it does not appear in the class instance methods but appears in the
        class attributes
        
    Add the receiver argument in the first case only
    `
    """
    axioms = []
    for t in types.all_types:
        # Check that attr is an instance method and "staticmethod" is not of its decorators,
        # if so, add call axioms with a receiver
        if attr in types.class_to_funcs[t]:
            decorators = types.class_to_funcs[t][attr][1]
            if "staticmethod" not in decorators and "property" not in decorators:
                attr_type = types.instance_attributes[t][attr]

                receiver_subtype = False
                if t in types.config.class_type_params:

# 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

                axioms.append(And(class_type == types.all_types[t],
                                  Or(function_call_axioms(attr_type, args, result, types))))
    return axioms


def instancemethod_call(instance, args, result, attr, types, tvs):
    """Constraints for calls on instances

    There are two cases:
    - The called is an instance method
    - The called is a normal instance attribute which happens to be callable

    In the first case, check that it appears in the class instance methods and is not static method
    In the second case, check that it does not appear in the class instance methods but appears in the
        class attributes
        
    Add the receiver argument in the first case only
    `
    """
    axioms = []
    for t in types.all_types:
        # Check that attr is an instance method and "staticmethod" is not of its decorators,
        # if so, add call axioms with a receiver
        if attr in types.class_to_funcs[t]:
            decorators = types.class_to_funcs[t][attr][1]
            if "staticmethod" not in decorators and "property" not in decorators:
                attr_type = types.instance_attributes[t][attr]

                receiver_subtype = False
                if t in types.config.class_type_params:

                    type_func = types.classes[t] if t not in ALIASES else getattr(types.type_sort, ALIASES[t])