Beispiel #1
0
 def _getitem_can_only_throw(s_c1, s_o2):
     impl = pair(s_c1, s_o2).getitem
     return read_can_only_throw(impl, s_c1, s_o2)
Beispiel #2
0
def _getitem_can_only_throw(s_c1, s_o2):
    impl = op.getitem.get_specialization(s_c1, s_o2)
    return read_can_only_throw(impl, s_c1, s_o2)
Beispiel #3
0
    def flowin(self, graph, block):
        try:
            for i, op in enumerate(block.operations):
                self.bookkeeper.enter((graph, block, i))
                try:
                    self.consider_op(op)
                finally:
                    self.bookkeeper.leave()

        except BlockedInference as e:
            if (e.op is block.operations[-1] and
                block.exitswitch == c_last_exception):
                # this is the case where the last operation of the block will
                # always raise an exception which is immediately caught by
                # an exception handler.  We then only follow the exceptional
                # branches.
                exits = [link for link in block.exits
                              if link.exitcase is not None]

            elif e.op.opname in ('simple_call', 'call_args', 'next'):
                # XXX warning, keep the name of the call operations in sync
                # with the flow object space.  These are the operations for
                # which it is fine to always raise an exception.  We then
                # swallow the BlockedInference and that's it.
                # About 'next': see test_annotate_iter_empty_container().
                return

            else:
                # other cases are problematic (but will hopefully be solved
                # later by reflowing).  Throw the BlockedInference up to
                # processblock().
                e.opindex = i
                raise

        except annmodel.HarmlesslyBlocked:
            return

        except annmodel.AnnotatorError as e: # note that UnionError is a subclass
            e.source = gather_error(self, graph, block, i)
            raise

        else:
            # dead code removal: don't follow all exits if the exitswitch
            # is known
            exits = block.exits
            if isinstance(block.exitswitch, Variable):
                s_exitswitch = self.bindings[block.exitswitch]
                if s_exitswitch.is_constant():
                    exits = [link for link in exits
                                  if link.exitcase == s_exitswitch.const]

        # filter out those exceptions which cannot
        # occour for this specific, typed operation.
        if block.exitswitch == c_last_exception:
            op = block.operations[-1]
            if op.dispatch == 2:
                arg1 = self.binding(op.args[0])
                arg2 = self.binding(op.args[1])
                binop = getattr(pair(arg1, arg2), op.opname, None)
                can_only_throw = annmodel.read_can_only_throw(binop, arg1, arg2)
            elif op.dispatch == 1:
                arg1 = self.binding(op.args[0])
                opname = op.opname
                if opname == 'contains': opname = 'op_contains'
                unop = getattr(arg1, opname, None)
                can_only_throw = annmodel.read_can_only_throw(unop, arg1)
            else:
                can_only_throw = None

            if can_only_throw is not None:
                candidates = can_only_throw
                candidate_exits = exits
                exits = []
                for link in candidate_exits:
                    case = link.exitcase
                    if case is None:
                        exits.append(link)
                        continue
                    covered = [c for c in candidates if issubclass(c, case)]
                    if covered:
                        exits.append(link)
                        candidates = [c for c in candidates if c not in covered]

        # mapping (exitcase, variable) -> s_annotation
        # that can be attached to booleans, exitswitches
        knowntypedata = getattr(self.bindings.get(block.exitswitch),
                                "knowntypedata", {})
        for link in exits:
            self.follow_link(graph, link, knowntypedata)
        if block in self.notify:
            # reflow from certain positions when this block is done
            for callback in self.notify[block]:
                if isinstance(callback, tuple):
                    self.reflowfromposition(callback) # callback is a position
                else:
                    callback()
Beispiel #4
0
 def get_can_only_throw(self, annotator):
     args_s = [annotator.annotation(v) for v in self.args]
     spec = type(self).get_specialization(*args_s)
     return read_can_only_throw(spec, args_s[0], args_s[1])
Beispiel #5
0
def _getitem_can_only_throw(s_c1, s_o2):
    impl = op.getitem.get_specialization(s_c1, s_o2)
    return read_can_only_throw(impl, s_c1, s_o2)
Beispiel #6
0
 def _getitem_can_only_throw(s_c1, s_o2):
     impl = pair(s_c1, s_o2).getitem
     return read_can_only_throw(impl, s_c1, s_o2)