예제 #1
0
def __join_ssa_branches_types_of_members_for_object(obj, previous_context,
                                                    branch1, branch2):
    """
    Implementation of the SSA joining algorithm for two SSA branches, handling types of members
    :param previous_context:
    :param branch1: dict(obj, dict(name, type))
    :param branch2:
    :return:
    """
    type_dict = dict()

    # NOTE: Explanations in comments are done with an if/else control structure. Other structures are the same.

    # Proceed with the first branch (if)

    # For any variable stored in the first branch (note that we only deal with variables that change its type in the
    # active branch, not all the possible variables accessible within the SSA context. This is also a major speedup
    # over our previous version.
    for var_name in branch1:
        if var_name in branch2:
            # Variable defined in if and else body: Joins both types
            type_dict[var_name] = UnionType.add(branch1[var_name],
                                                branch2[var_name])
        else:
            # Variable defined in if and in the previous context: Joins the previous type and the if one
            previous_type = previous_context.get_type_of_member(
                Localization.get_current(), obj, var_name)
            if not isinstance(previous_type, StypyTypeError):
                type_dict[var_name] = UnionType.add(previous_type,
                                                    branch1[var_name])
            else:
                # Variable defined in if body, but did not exist in the previous context: Joins the if type with an
                # undefined type, as the if could not be executed
                type_dict[var_name] = UnionType.add(branch1[var_name],
                                                    UndefinedType)
                StypyTypeError.remove_error_msg(previous_type)

    # Now proceed with the second branch (else). If no else is present and empty dict is passed, and therefore no
    # processing is done.

    for var_name in branch2:
        if var_name in branch1:
            continue  # Already processed (above)
        else:
            # Variable defined only in the else body and in the previous context: Treat equally to the if branch
            # counterpart
            previous_type = previous_context.get_type_of_member(
                Localization.get_current(), obj, var_name)
            if not isinstance(previous_type, StypyTypeError):
                type_dict[var_name] = UnionType.add(previous_type,
                                                    branch2[var_name])
            else:
                # Variable defined in else body, but did not existed in the previous context: Same treatment as their
                # if branch counterpart
                type_dict[var_name] = UnionType.add(branch2[var_name],
                                                    UndefinedType)
                StypyTypeError.remove_error_msg(previous_type)

    # type_store_previous does not need to be iterated because it is included in the if and else stores
    return type_dict
예제 #2
0
    def unique(localization, proxy_obj, arguments):
        dvar = call_utilities.parse_varargs_and_kwargs(localization, arguments, ['return_index', 'return_inverse', 'return_counts'], {
            'return_index': bool,
            'return_inverse': bool,
            'return_counts': bool,
        }, 'unique')

        if isinstance(dvar, StypyTypeError):
            return dvar

        if Number == type(arguments[0]):
            ret_arr = call_utilities.create_numpy_array(arguments[0])
        else:
            ret_arr = call_utilities.create_numpy_array(get_contained_elements_type(localization, arguments[0]))

        if len(dvar.keys()) == 0:
            return ret_arr

        tup = wrap_type(tuple())
        union = UnionType.add(ret_arr, call_utilities.create_numpy_array(numpy.int32()))

        if len(dvar.keys()) == 1:
            set_contained_elements_type(localization, tup, union)
        if len(dvar.keys()) == 2:
            union = UnionType.add(union, call_utilities.create_numpy_array(numpy.int32()))
            set_contained_elements_type(localization, tup, union)
        if len(dvar.keys()) == 3:
            union = UnionType.add(union, call_utilities.create_numpy_array(numpy.int32()))
            union = UnionType.add(union, call_utilities.create_numpy_array(numpy.int32()))
            set_contained_elements_type(localization, tup, union)

        return tup
    def groups(localization, proxy_obj, arguments):
        t = UnionType.add(undefined_type.UndefinedType, str())
        t = UnionType.add(t, 0)
        t = UnionType.add(t, types.NoneType)
        tup = call_utilities.wrap_contained_type(tuple())
        tup.set_contained_type(t)

        return tup
def turn_to_type(obj):
    """
    As in our type analysis process we may have to deal with code whose sources are not available, calls to this code
    must be performed so we can obtain return values that can be used in our program analysis. This code is responsible
     of turning the values obtained from these calls to its types so stypy is able to use its return types to analyze
     the program.
    :param obj:
    :return:
    """
    # Already wrapped: it is already a type
    if type(obj) is StandardWrapper:
        return obj
    if type(obj) in types_without_value:
        obj = type(obj)()

    wrapped_obj = wrap_contained_type(obj)

    # Special handling for dicts and similar
    if type_containers.can_store_keypairs(wrapped_obj):
        collected_items = dict()
        keys = obj.keys()
        for key in keys:
            values_for_key = type_containers.get_contained_elements_type_for_key(obj, key)
            key_type = turn_to_type(key)
            value_types = turn_to_type(values_for_key)
            try:
                existing_values = collected_items[key_type]
            except:
                existing_values = None

            collected_items[key_type] = UnionType.add(value_types, existing_values)

        for key in keys:
            del obj[key]

        for key, value in collected_items.items():
            type_containers.set_contained_elements_type_for_key(wrapped_obj, key, value)

        return wrapped_obj

    # Special handling for containers
    if type_containers.can_store_elements(wrapped_obj):
        union_contained = None
        for elem in obj:
            elem = turn_to_type(elem)
            if elem is type:
                union_contained = UnionType.add(union_contained, elem)
            else:
                try:
                    union_contained = UnionType.add(union_contained, known_python_types.get_sample_instance_for_type(
                        type(elem).__name__))
                except Exception as exc:
                    union_contained = UnionType.add(union_contained, elem)

        wrapped_obj.set_contained_type(union_contained)
        return wrapped_obj

    return obj
예제 #5
0
    def test_merge_union_types(self):
        int_var = int

        def fun():
            pass

        class Foo:
            def method(self):
                pass

            def method_2(self):
                pass

        class_var = Foo
        method_var = Foo.method

        instance_var = Foo()
        import math

        module_var = math
        union1 = UnionType.create_from_type_list([int_var, fun, class_var])

        union2 = UnionType.create_from_type_list(
            [method_var, instance_var, module_var])

        compare_types(union1, [int_var, fun, class_var])

        compare_types(union2, [method_var, instance_var, module_var])

        fused_union = UnionType.add(union1, union2)
        compare_types(
            fused_union,
            [int_var, fun, class_var, method_var, instance_var, module_var])

        clone = UnionType.create_from_type_list(
            [int_var, fun, class_var, method_var, instance_var, module_var])
        compare_types(fused_union, clone)

        method2_var = Foo.method_2
        UnionType.add(clone, types)
        UnionType.add(clone, method2_var)

        compare_types(
            fused_union,
            [int_var, fun, class_var, method_var, instance_var, module_var])

        compare_types(clone, [
            int_var, fun, class_var, method_var, instance_var, module_var,
            method2_var, types
        ])

        clone2 = UnionType.create_from_type_list([
            int_var, fun, class_var, method_var, instance_var, module_var,
            method2_var, types
        ])
        self.assertFalse(fused_union == clone)
        compare_types(clone2, clone)
예제 #6
0
    def block(localization, proxy_obj, arguments):
        union = None
        for arg in arguments:
            if call_utilities.is_iterable(arg):
                union = UnionType.add(
                    union, get_contained_elements_type(localization, arg))
            else:
                union = UnionType.add(union, arg)

        return call_utilities.create_numpy_array(union)
예제 #7
0
    def test_create_union_type_with_vars(self):
        union = UnionType.add(int, str)
        compare_types(union, [int, str])

        union2 = UnionType(union, list)
        compare_types(union, [int, str])
        compare_types(union2, [int, str, list])

        self.assertFalse(union == union2)

        clone = UnionType.add(int, str)
        self.assertTrue(union == clone)
예제 #8
0
    def test_create_union_type_with_classes(self):
        class Foo:
            pass

        union = UnionType.add(Foo, AssertionError)
        compare_types(union, [Foo, AssertionError])

        union2 = UnionType(union, object)
        compare_types(union2, [Foo, AssertionError, object])

        clone = UnionType.add(Foo, AssertionError)
        self.assertFalse(union == union2)
        self.assertTrue(union == clone)
예제 #9
0
    def test_create_union_type_with_funcs(self):
        def foo():
            pass

        union = UnionType.add(foo, range)
        compare_types(union, [foo, range])

        union2 = UnionType(union, getattr)
        compare_types(union, [foo, range])
        compare_types(union2, [foo, range, getattr])

        self.assertFalse(union == union2)

        clone = UnionType.add(foo, range)
        self.assertTrue(union == clone)
예제 #10
0
    def test_create_union_type_with_modules(self):
        import math
        import sys
        import types

        union = UnionType.add(math, sys)
        compare_types(union, [math, sys])

        clone = UnionType.add(math, sys)
        compare_types(union, clone.types)

        union2 = UnionType.add(clone, types)
        compare_types(union2, [math, sys, types])

        self.assertFalse(union == union2)
예제 #11
0
def assign_ssa_finally_branch_types_of_members_for_object(
        obj, branch_rest, branch_finally):
    """
    Assign all the types contained on the dictionary branch2 to the dictionary branch1, overwriting them if the same
    name exist in both branches. This is needed for the implementation of the finally branch, that do not follow the
    same behaviour as the other branches when implementing the SSA algorithm.
    :param obj:
    :param branch_rest:
    :param branch_finally:
    :return:
    """
    for name in branch_finally:
        if isinstance(branch_finally[name], UnionType):
            types = branch_finally[name].get_types()
            types_without_undefined = filter(lambda t: t is not UndefinedType,
                                             types)
            if len(types_without_undefined) < len(
                    types):  # There were undefined types
                union_without_undefined = UnionType.create_from_type_list(
                    types_without_undefined)
                branch_rest[name] = UnionType.add(branch_rest[name],
                                                  union_without_undefined)
                continue

        # if obj not in branch_rest:
        #     branch_rest[obj] = dict()

        branch_rest[name] = branch_finally[name]
    return branch_rest
 def __setitem__(localization, proxy_obj, arguments):
     r = TypeWrapper.get_wrapper_of(proxy_obj.__self__)
     existing = r.get_contained_type()
     if existing is types.NoneType or type(existing) is types.NoneType:
         r.set_contained_type(arguments[1])
     else:
         r.set_contained_type(UnionType.add(arguments[1], existing))
def create_union_type(types_):
    ret = None

    for elem in types_:
        ret = UnionType.add(ret, elem)

    return ret
    def fit(localization, proxy_obj, arguments):
        dvar = call_utilities.parse_varargs_and_kwargs(
            localization, arguments,
            ['domain', 'rcond', 'full', 'w', 'window'], {
                'domain': IterableDataStructure,
                'rcond': RealNumber,
                'full': bool,
                'w': IterableDataStructure,
                'window': IterableDataStructure,
            }, 'fit', 3)

        if isinstance(dvar, StypyTypeError):
            return dvar

        ret = call_utilities.create_numpy_array_n_dimensions(
            call_utilities.get_inner_type(localization, arguments[0]),
            call_utilities.get_dimensions(localization, arguments[0]))
        ret = numpy.polynomial.Chebyshev(ret.get_wrapped_type())

        if 'full' in dvar.keys():
            tup = wrap_contained_type(tuple())
            ld = wrap_contained_type(list())
            ld.set_contained_type(
                call_utilities.get_inner_type(localization, arguments[0]))
            un = UnionType.add(ret, ld)
            tup.set_contained_type(un)
            return tup

        return ret
    def __getitem__(localization, proxy_obj, arguments):
        r = TypeWrapper.get_wrapper_of(proxy_obj.__self__)
        index_selector = arguments[0]
        if isinstance(index_selector, tuple):
            index_selector = index_selector[0]

        dims = call_utilities.get_dimensions(localization, r)
        if dims > 1:
            if call_utilities.is_iterable(arguments[0]):
                if call_utilities.is_iterable(arguments[0].get_contained_type()):
                    return call_utilities.create_numpy_array_n_dimensions(
                        call_utilities.cast_to_numpy_type(call_utilities.get_inner_type(localization, r)), dims - 1)

            contained = call_utilities.cast_to_numpy_type(call_utilities.get_inner_type(localization, r))
            for i in range(dims - 1):
                contained = UnionType.add(contained,
                                          call_utilities.create_numpy_array_n_dimensions(r.get_contained_type(), i + 1))
        else:
            contained = r.get_contained_type()

        if isinstance(index_selector, TypeWrapper):
            if isinstance(index_selector.wrapped_type, slice) or (
                        call_utilities.is_iterable(index_selector) and not isinstance(index_selector.wrapped_type,
                                                                                      tuple)):
                l = call_utilities.create_numpy_array(contained)
                return l
        return contained  # proxy_obj.__self__.dtype.type()
 def heappush(localization, proxy_obj, arguments):
     ex_type = get_contained_elements_type(localization, arguments[0])
     if ex_type is UndefinedType:
         u = arguments[1]
     else:
         u = UnionType.add(ex_type, arguments[1])
     set_contained_elements_type(localization, arguments[0], u)
     return types.NoneType
def add_key_and_value_type(container, key, type_):
    try:
        existing = container[key]
    except KeyError:
        existing = None

    to_add = UnionType.add(existing, type_)
    container[key] = to_add
예제 #18
0
    def test_simple_union_invoke(self):
        union = UnionType.add(int(), str())

        islower = self.type_store.get_type_of_member(self.loc, union,
                                                     "islower")
        res = invoke(self.loc, islower)

        self.assertTrue(len(TypeWarning.get_warning_msgs()) == 1)
        compare_types(res, False)
예제 #19
0
    def test_create_union_type_with_mixed_types(self):
        int_var = int

        def fun():
            pass

        class Foo:
            def method(self):
                pass

            def method_2(self):
                pass

        class_var = Foo
        method_var = Foo.method

        instance_var = Foo()
        import math

        module_var = math
        union = UnionType.create_from_type_list(
            [int_var, fun, class_var, method_var, instance_var, module_var])

        compare_types(
            union,
            [int_var, fun, class_var, method_var, instance_var, module_var])

        clone = UnionType.create_from_type_list(
            [int_var, fun, class_var, method_var, instance_var, module_var])

        compare_types(union, clone)

        method2_var = Foo.method_2
        UnionType.add(clone, types)
        UnionType.add(clone, method2_var)

        compare_types(
            union,
            [int_var, fun, class_var, method_var, instance_var, module_var])

        compare_types(clone, [
            int_var, fun, class_var, method_var, instance_var, module_var,
            method2_var, types
        ])
예제 #20
0
    def einsum(localization, proxy_obj, arguments):
        if isinstance(arguments[-1], dict):
            if Str == type(arguments[0]):
                arg_num = 2
            else:
                arg_num = 1

            dvar = call_utilities.parse_varargs_and_kwargs(localization, arguments,
                                                           ['out', 'dtype', 'order', 'casting', 'optimize'], {
                                                               'out': IterableDataStructure,
                                                               'dtype': type,
                                                               'order': Str,
                                                               'casting': Str,
                                                               'optimize': [bool, Str]
                                                           }, 'einsum', arg_num)

            if isinstance(dvar, StypyTypeError):
                return dvar

            val_temp = call_utilities.check_possible_values(dvar, 'order', ['C', 'F', 'A', 'K'])
            if isinstance(val_temp, StypyTypeError):
                return val_temp

            val_temp = call_utilities.check_possible_values(dvar, 'casting', ['no', 'equiv', 'safe', 'same_kind', 'unsafe'])
            if isinstance(val_temp, StypyTypeError):
                return val_temp

            val_temp = call_utilities.check_possible_values(dvar, 'optimize', ['greedy', 'optimal', False, True])
            if isinstance(val_temp, StypyTypeError):
                return val_temp

            arguments = arguments[:-1]
        else:
            dvar = dict()

        typ = None
        if Str == type(arguments[0]):
            arg_list = arguments[1:]
            if Number == type(arguments[1]) and 'out' in dvar:
                return dvar['out']
        else:
            arg_list = arguments

        for arg in arg_list:
            if call_utilities.is_iterable(arg):
                typ_temp = call_utilities.cast_to_numpy_type(call_utilities.get_inner_type(localization, arg))
                typ = call_utilities.cast_to_greater_numpy_type(typ, typ_temp)

        union = UnionType.add(typ, call_utilities.create_numpy_array(DynamicType))

        if 'out' in dvar:
            set_contained_elements_type(localization, dvar['out'], DynamicType)
            return call_utilities.create_numpy_array(DynamicType)

        return union
예제 #21
0
    def test_create_union_type_with_instances(self):
        class Foo:
            pass

        foo_inst = Foo()
        assert_inst = AssertionError()
        object_inst = object()

        union = UnionType.add(foo_inst, assert_inst)
        compare_types(union, [foo_inst, assert_inst])

        union2 = UnionType(union, object_inst)
        compare_types(union2, [foo_inst, assert_inst, object_inst])

        clone = UnionType.add(foo_inst, assert_inst)
        self.assertFalse(union == union2)
        self.assertTrue(union == clone)

        clone2 = UnionType.add(foo_inst, AssertionError())
        self.assertFalse(union == clone2)
예제 #22
0
    def dstack(localization, proxy_obj, arguments):
        elem_list = wrap_contained_type(list())
        for arg in arguments:
            if call_utilities.is_iterable(arg):
                cont = get_contained_elements_type(localization, arg)
                if call_utilities.is_iterable(cont):
                    union2 = UnionType.add(elem_list.get_contained_type(),
                                           cont.get_contained_type())
                    elem_list.set_contained_type(union2)
                else:
                    union2 = UnionType.add(elem_list.get_contained_type(),
                                           cont)
                    elem_list.set_contained_type(union2)
            else:
                return StypyTypeError(
                    localization,
                    "A non-iterable parameter {0} was passed to the dstack function"
                    .format(str(arg)))

        return call_utilities.create_numpy_array(elem_list)
예제 #23
0
    def concatenate(localization, proxy_obj, arguments):
        union = None
        for arg in arguments:
            if call_utilities.is_iterable(arg):
                union = UnionType.add(
                    union, get_contained_elements_type(localization, arg))
            else:
                return StypyTypeError(
                    localization,
                    "A non-iterable parameter {0} was passed to the concatenate function"
                    .format(str(arg)))

        return call_utilities.create_numpy_array(union)
예제 #24
0
    def hstack(localization, proxy_obj, arguments):
        union = None
        for arg in arguments:
            if call_utilities.is_iterable(arg):
                union = UnionType.add(
                    union, call_utilities.get_inner_type(localization, arg))
            else:
                return StypyTypeError(
                    localization,
                    "A non-iterable parameter {0} was passed to the hstack function"
                    .format(str(arg)))

        return call_utilities.create_numpy_array(union)
예제 #25
0
    def iadd(localization, proxy_obj, arguments):
        if call_utilities.is_iterable(
                arguments[0]) and call_utilities.is_iterable(arguments[1]):
            if isinstance(
                    arguments[0].get_wrapped_type(), list) and isinstance(
                        arguments[1].get_wrapped_type(), tuple):
                t1 = get_contained_elements_type(localization, arguments[0])
                t2 = get_contained_elements_type(localization, arguments[1])

                tEnd = UnionType.add(t1, t2)

                set_contained_elements_type(localization, arguments[0], tEnd)
                return arguments[0]

        return None
예제 #26
0
    def add(localization, proxy_obj, arguments):
        if call_utilities.is_iterable(
                arguments[0]) and call_utilities.is_iterable(arguments[1]):
            if isinstance(arguments[0].get_wrapped_type(),
                          tuple) and isinstance(
                              arguments[1].get_wrapped_type(), tuple):
                t1 = call_utilities.get_contained_elements_type(
                    localization, arguments[0])
                t2 = call_utilities.get_contained_elements_type(
                    localization, arguments[1])
                if isinstance(t1, UnionType):
                    t1 = t1.duplicate()
                tEnd = UnionType.add(t1, t2)
                wrap = call_utilities.wrap_contained_type((tEnd, ))
                wrap.set_contained_type(tEnd)
                return wrap

        return None  # Type rule results
예제 #27
0
    def stack(localization, proxy_obj, arguments):
        dvar = call_utilities.parse_varargs_and_kwargs(localization, arguments,
                                                       ['axis'], {
                                                           'axis': Integer,
                                                       }, 'stack')

        if isinstance(dvar, StypyTypeError):
            return dvar

        union = None
        for arg in arguments:
            if call_utilities.is_iterable(arg):
                union = UnionType.add(
                    union, get_contained_elements_type(localization, arg))
            else:
                return StypyTypeError(
                    localization,
                    "A non-iterable parameter {0} was passed to the stack function"
                    .format(str(arg)))

        return call_utilities.create_numpy_array(union)
    def linspace(localization, proxy_obj, arguments):
        dvar = call_utilities.parse_varargs_and_kwargs(
            localization, arguments, ['num', 'endpoint'
                                      'retstep'
                                      'dtype'], {
                                          'num': Integer,
                                          'endpoint': bool,
                                          'retstep': bool,
                                          'dtype': type,
                                      }, 'linspace', 2)

        if isinstance(dvar, StypyTypeError):
            return dvar

        temp_ret = call_utilities.create_numpy_array(numpy.float64())
        if 'retstep' in dvar.keys():
            union = UnionType.add(temp_ret, numpy.float64())
            out_tuple = wrap_contained_type((union, ))
            out_tuple.set_contained_type(union)
            return out_tuple

        return temp_ret
예제 #29
0
 def func(*args, **kwargs):
     frame = inspect.currentframe()
     while True:
         if frame.f_code is f.func_code:
             # Constructors don't return values
             if f.__name__ == "__init__":
                 return None
             try:
                 call = frame.f_globals[frame.f_code.co_name]
                 # Check call arguments of the recursive call to detect recursive call argument errors prior to
                 # return a RecursionType.
                 arguments = process_argument_values(
                     args[0], call.stypy_type_of_self,
                     call.stypy_type_store, call.stypy_function_name,
                     call.stypy_param_names_list,
                     call.stypy_varargs_param_name,
                     call.stypy_kwargs_param_name, call.stypy_call_defaults,
                     args[1:], kwargs)
                 if is_error_type(arguments):
                     return arguments
             except:
                 pass
             try:
                 # Return the most up-to-date calculated return type in a recursive call. Pair it with a
                 # RecursionType() to indicate it may be composed by more types.
                 context = call.stypy_type_store.get_current_active_context(
                 )
                 if default_function_ret_var_name in context:
                     return UnionType.add(
                         context.get_type_of(call.stypy_localization,
                                             default_function_ret_var_name),
                         RecursionType())
                 return RecursionType()
             except:
                 return RecursionType()
         frame = frame.f_back
         if frame is None:
             break
     return f(*args, **kwargs)
예제 #30
0
    def test_union_invoke_return_types(self):
        class Foo:
            def method(self, localization):
                return True

            def method_2(self, localization):
                return str()

        class Foo2:
            def method(self, localization):
                return False

            def method_2(self, localization):
                return int()

        # Access a member that can be provided only by some of the types in the union
        union = UnionType.add(Foo(), Foo2())

        method = self.type_store.get_type_of_member(self.loc, union,
                                                    "method_2")
        res = invoke(self.loc, method)
        self.assertTrue(len(TypeWarning.get_warning_msgs()) == 0)

        compare_types(res, [str(), int()])