Example #1
0
    def visit_DictComp(self, node):
        new_bindings = {}
        no_dict = False
        for generator in node.generators:
            test_types = set()
            for if_ in generator.ifs:
                test_types.update(self.visit(if_))
            test_types = normalize_test_ty(test_types)
            if test_types == {Cst[False]}:
                no_dict = True

            iter_types = self.visit(generator.iter)
            if isinstance(generator.target, ast.Name):
                iter_value_ty = self._iterator_value_ty(iter_types)
                new_bindings[generator.target.id] = iter_value_ty

        self.bindings.append(new_bindings)
        key_types = self.visit(node.key)
        value_types = self.visit(node.value)
        self.bindings.pop()
        if no_dict:
            return {Dict[set(), set()]}
        else:
            return {
                Dict[{astype(k)
                      for k in key_types}, {astype(v)
                                            for v in value_types}]
            }
Example #2
0
 def __call__(self, left_ty, right_ty):
     if issubclass(left_ty, Cst):
         if issubclass(right_ty, Cst):
             return Cst[left_ty.__args__[0] is not right_ty.__args__[0]]
         elif astype(left_ty) == right_ty:
             return bool
         else:
             return Cst[True]
     else:
         left_ty = astype(left_ty)
         right_ty = astype(right_ty)
         if left_ty == right_ty:
             return bool
         else:
             return Cst[True]
Example #3
0
    def _handle_is(self, prev, prev_ty, comparator, comparator_ty):
        def filtering(val, id_, new_type):
            assert not isinstance(new_type, tuple)
            return FilteringBool[val, id_, (new_type, )]

        cmp_ty = set()
        for pty, cty in itertools.product(prev_ty, comparator_ty):
            rem_pty = tuple(prev_ty - {pty})
            rem_cty = tuple(comparator_ty - {cty})
            if pty is cty:
                # special handling for singleton types
                if issubclass(pty, (Cst, Module, Type)):
                    tmp_ty = set()
                    if rem_pty and isinstance(prev, ast.Name):
                        tmp_ty.add(filtering(True, prev.id, pty))
                    if rem_cty and isinstance(comparator, ast.Name):
                        tmp_ty.add(filtering(True, comparator.id, cty))
                    if tmp_ty:
                        cmp_ty.update(tmp_ty)
                    else:
                        cmp_ty.add(Cst[True])
                else:
                    cmp_ty.add(bool)
            elif astype(pty) is astype(cty):
                if all(
                        issubclass(ty, (Cst, Module, Type))
                        for ty in (cty, pty)):
                    cmp_ty.add(Cst[False])
                else:
                    cmp_ty.add(bool)
            else:
                tmp_ty = set()
                if rem_pty and isinstance(prev, ast.Name):
                    tmp_ty.add(filtering(False, prev.id, pty))
                if rem_cty and isinstance(comparator, ast.Name):
                    tmp_ty.add(filtering(False, comparator.id, cty))
                if tmp_ty:
                    cmp_ty.update(tmp_ty)
                else:
                    tmp_ty = self._call(Ops[ast.Is], prev_ty, comparator_ty)
                    cmp_ty.update(tmp_ty)
        return cmp_ty
Example #4
0
    def __call__(self, left_ty, right_ty):
        if issubclass(left_ty, TypeOf):
            if issubclass(right_ty, (Cst, Type)):
                return FilteringBool[(left_ty.__args__[0] is right_ty.__args__[0]),
                                     left_ty.__args__[1], (left_ty.__args__[0],)]
            elif astype(left_ty) == right_ty:
                return bool
            else:
                return Cst[False]

        if issubclass(left_ty, (Cst, Type)):
            if issubclass(right_ty, (Cst, Type)):
                return Cst[left_ty.__args__[0] is right_ty.__args__[0]]
            elif astype(left_ty) == right_ty:
                return bool
            else:
                return Cst[False]
        else:
            left_ty = astype(left_ty)
            right_ty = astype(right_ty)
            if left_ty == right_ty:
                return bool
            else:
                return Cst[False]
Example #5
0
    def _handle_comp(self, node, container_ty):
        new_bindings = {}
        no_element = False
        for generator in node.generators:
            test_types = set()
            for if_ in generator.ifs:
                test_types.update(self.visit(if_))
            test_types = normalize_test_ty(test_types)
            if test_types == {Cst[False]}:
                no_element = True

            iter_types = self.visit(generator.iter)
            if isinstance(generator.target, ast.Name):
                iter_value_ty = self._iterator_value_ty(iter_types)
                new_bindings[generator.target.id] = iter_value_ty

        self.bindings.append(new_bindings)
        elt_types = self.visit(node.elt)
        self.bindings.pop()
        if no_element:
            return {container_ty[set()]}
        else:
            return {container_ty[{astype(elt_ty) for elt_ty in elt_types}]}
Example #6
0
    def visit_Loop(self, node):

        loop_bindings = {}
        self.bindings.append(loop_bindings)

        for stmt in node.body:
            prev = self.visit(stmt)
            if not prev:
                break
            if all(isinstance(p, (ast.Break, ast.Continue)) for p in prev):
                break

        reloop_bindings = {}

        if not all(isinstance(p, ast.Break) for p in prev):
            self.bindings.append(reloop_bindings)
            for stmt in node.body:
                prev = self.visit(stmt)
                if not prev:
                    break
                if all(isinstance(p, (ast.Break, ast.Continue)) for p in prev):
                    break

            self.bindings.pop()

        self.bindings.pop()

        for k, v in loop_bindings.items():
            if k not in self.bindings[-1]:
                self.bindings[-1][k] = v
            else:
                self.bindings[-1][k].update(v)

        for k, v in reloop_bindings.items():
            if k not in self.bindings[-1]:
                self.bindings[-1][k] = v
            elif not self.bindings[-1][k].issuperset(v):
                # get rid of constants that grows along the loop
                self.bindings[-1][k] = {
                    astype(ty)
                    for ty in self.bindings[-1][k]
                }

        if not prev:
            return ()

        if all(not isinstance(p, ast.Break) for p in prev):
            for stmt in node.orelse:
                prev = self.visit(stmt)
                if not prev:
                    break
        elif any(not isinstance(p, ast.Break) for p in prev):
            orelse_bindings = {}
            self.bindings.append(orelse_bindings)
            for stmt in node.orelse:
                prev = self.visit(stmt)
                if not prev:
                    break
            self.bindings.pop()
            for k, v in orelse_bindings.items():
                if k in self.bindings[-1]:
                    self.bindings[-1][k].update(v)
                else:
                    self.bindings[-1][k] = v

        return prev