Ejemplo n.º 1
0
 def op_contains(dct, s_element):
     dct.dictdef.generalize_key(s_element)
     if dct._is_empty():
         s_bool = SomeBool()
         s_bool.const = False
         return s_bool
     return s_Bool
Ejemplo n.º 2
0
 def op_contains(dct, s_element):
     dct.dictdef.generalize_key(s_element)
     if dct._is_empty():
         s_bool = SomeBool()
         s_bool.const = False
         return s_bool
     return s_Bool
Ejemplo n.º 3
0
 def union((boo1, boo2)):
     s = SomeBool()
     if getattr(boo1, 'const', -1) == getattr(boo2, 'const', -2):
         s.const = boo1.const
     if hasattr(boo1, 'knowntypedata') and \
        hasattr(boo2, 'knowntypedata'):
         ktd = merge_knowntypedata(boo1.knowntypedata, boo2.knowntypedata)
         if ktd:
             s.knowntypedata = ktd
     return s
Ejemplo n.º 4
0
 def union((boo1, boo2)):
     s = SomeBool() 
     if getattr(boo1, 'const', -1) == getattr(boo2, 'const', -2): 
         s.const = boo1.const 
     if hasattr(boo1, 'knowntypedata') and \
        hasattr(boo2, 'knowntypedata'):
         ktd = merge_knowntypedata(boo1.knowntypedata, boo2.knowntypedata)
         if ktd:
             s.knowntypedata = ktd
     return s 
Ejemplo n.º 5
0
 def or_((boo1, boo2)):
     s = SomeBool()
     if boo1.is_constant():
         if boo1.const:
             s.const = True
         else:
             return boo2
     if boo2.is_constant():
         if boo2.const:
             s.const = True
     return s
Ejemplo n.º 6
0
 def and_((boo1, boo2)):
     s = SomeBool()
     if boo1.is_constant():
         if not boo1.const:
             s.const = False
         else:
             return boo2
     if boo2.is_constant():
         if not boo2.const:
             s.const = False
     return s
Ejemplo n.º 7
0
 def and_((boo1, boo2)):
     s = SomeBool()
     if boo1.is_constant():
         if not boo1.const:
             s.const = False
         else:
             return boo2
     if boo2.is_constant():
         if not boo2.const:
             s.const = False
     return s
Ejemplo n.º 8
0
def builtin_isinstance(s_obj, s_type, variables=None):
    r = SomeBool()
    if s_type.is_constant():
        typ = s_type.const
        if issubclass(typ, pypy.rlib.rarithmetic.base_int):
            r.const = issubclass(s_obj.knowntype, typ)
        else:
            if typ == long:
                getbookkeeper().warning("isinstance(., long) is not RPython")
                if s_obj.is_constant():
                    r.const = isinstance(s_obj.const, long)
                else:
                    if type(
                            s_obj
                    ) is not SomeObject:  # only SomeObjects could be longs
                        # type(s_obj) < SomeObject -> SomeBool(False)
                        # type(s_obj) == SomeObject -> SomeBool()
                        r.const = False
                return r

            assert not issubclass(
                typ, (int, long)) or typ in (bool, int, long), (
                    "for integers only isinstance(.,int|r_uint) are supported")

            if s_obj.is_constant():
                r.const = isinstance(s_obj.const, typ)
            elif our_issubclass(s_obj.knowntype, typ):
                if not s_obj.can_be_none():
                    r.const = True
            elif not our_issubclass(typ, s_obj.knowntype):
                r.const = False
            elif s_obj.knowntype == int and typ == bool:  # xxx this will explode in case of generalisation
                # from bool to int, notice that isinstance( , bool|int)
                # is quite border case for RPython
                r.const = False
        # XXX HACK HACK HACK
        # XXX HACK HACK HACK
        # XXX HACK HACK HACK
        bk = getbookkeeper()
        if variables is None:
            fn, block, i = bk.position_key
            op = block.operations[i]
            assert op.opname == "simple_call"
            assert len(op.args) == 3
            assert op.args[0] == Constant(isinstance)
            variables = [op.args[1]]
        for variable in variables:
            assert bk.annotator.binding(variable) == s_obj
        r.knowntypedata = {}
        if (not isinstance(s_type, SomeBuiltin)
                or typ.__module__ == '__builtin__'):
            add_knowntypedata(r.knowntypedata, True, variables,
                              bk.valueoftype(typ))
    return r
Ejemplo n.º 9
0
 def or_((boo1, boo2)):
     s = SomeBool()
     if boo1.is_constant():
         if boo1.const:
             s.const = True
         else:
             return boo2
     if boo2.is_constant():
         if boo2.const:
             s.const = True
     return s
Ejemplo n.º 10
0
def builtin_hasattr(s_obj, s_attr):
    if not s_attr.is_constant() or not isinstance(s_attr.const, str):
        getbookkeeper().warning("hasattr(%r, %r) is not RPythonic enough" % (s_obj, s_attr))
    r = SomeBool()
    if s_obj.is_immutable_constant():
        r.const = hasattr(s_obj.const, s_attr.const)
    elif isinstance(s_obj, SomePBC) and s_obj.getKind() is description.FrozenDesc:
        answers = {}
        for d in s_obj.descriptions:
            answer = d.s_read_attribute(s_attr.const) != s_ImpossibleValue
            answers[answer] = True
        if len(answers) == 1:
            r.const, = answers
    return r
Ejemplo n.º 11
0
def annotationoftype(t, bookkeeper=False):
    from pypy.rpython import extregistry
    """The most precise SomeValue instance that contains all
    objects of type t."""
    assert isinstance(t, (type, types.ClassType))
    if t is bool:
        return SomeBool()
    elif t is int:
        return SomeInteger()
    elif t is float:
        return SomeFloat()
    elif issubclass(t, str):  # py.lib uses annotated str subclasses
        return SomeString()
    elif t is unicode:
        return SomeUnicodeString()
    elif t is list:
        return SomeList(MOST_GENERAL_LISTDEF)
    elif t is dict:
        return SomeDict(MOST_GENERAL_DICTDEF)
    # can't do tuple
    elif t is types.NoneType:
        return s_None
    elif bookkeeper and extregistry.is_registered_type(t, bookkeeper.policy):
        entry = extregistry.lookup_type(t, bookkeeper.policy)
        return entry.compute_annotation_bk(bookkeeper)
    elif bookkeeper and t.__module__ != '__builtin__' and t not in bookkeeper.pbctypes:
        classdef = bookkeeper.getuniqueclassdef(t)
        return SomeInstance(classdef)
    else:
        o = SomeObject()
        if t != object:
            o.knowntype = t
        return o
Ejemplo n.º 12
0
def builtin_hasattr(s_obj, s_attr):
    if not s_attr.is_constant() or not isinstance(s_attr.const, str):
        getbookkeeper().warning('hasattr(%r, %r) is not RPythonic enough' %
                                (s_obj, s_attr))
    r = SomeBool()
    if s_obj.is_immutable_constant():
        r.const = hasattr(s_obj.const, s_attr.const)
    elif (isinstance(s_obj, SomePBC)
          and s_obj.getKind() is description.FrozenDesc):
       answers = {}    
       for d in s_obj.descriptions:
           answer = (d.s_read_attribute(s_attr.const) != s_ImpossibleValue)
           answers[answer] = True
       if len(answers) == 1:
           r.const, = answers
    return r
Ejemplo n.º 13
0
def builtin_isinstance(s_obj, s_type, variables=None):
    r = SomeBool()
    if s_type.is_constant():
        typ = s_type.const
        if issubclass(typ, pypy.rlib.rarithmetic.base_int):
            r.const = issubclass(s_obj.knowntype, typ)
        else:
            if typ == long:
                getbookkeeper().warning("isinstance(., long) is not RPython")
                if s_obj.is_constant():
                    r.const = isinstance(s_obj.const, long)
                else:
                    if type(s_obj) is not SomeObject:  # only SomeObjects could be longs
                        # type(s_obj) < SomeObject -> SomeBool(False)
                        # type(s_obj) == SomeObject -> SomeBool()
                        r.const = False
                return r

            assert not issubclass(typ, (int, long)) or typ in (
                bool,
                int,
                long,
            ), "for integers only isinstance(.,int|r_uint) are supported"

            if s_obj.is_constant():
                r.const = isinstance(s_obj.const, typ)
            elif our_issubclass(s_obj.knowntype, typ):
                if not s_obj.can_be_none():
                    r.const = True
            elif not our_issubclass(typ, s_obj.knowntype):
                r.const = False
            elif s_obj.knowntype == int and typ == bool:  # xxx this will explode in case of generalisation
                # from bool to int, notice that isinstance( , bool|int)
                # is quite border case for RPython
                r.const = False
        # XXX HACK HACK HACK
        # XXX HACK HACK HACK
        # XXX HACK HACK HACK
        bk = getbookkeeper()
        if variables is None:
            fn, block, i = bk.position_key
            op = block.operations[i]
            assert op.opname == "simple_call"
            assert len(op.args) == 3
            assert op.args[0] == Constant(isinstance)
            variables = [op.args[1]]
        for variable in variables:
            assert bk.annotator.binding(variable) == s_obj
        r.knowntypedata = {}
        if not isinstance(s_type, SomeBuiltin) or typ.__module__ == "__builtin__":
            add_knowntypedata(r.knowntypedata, True, variables, bk.valueoftype(typ))
    return r
Ejemplo n.º 14
0
    def is_((obj1, obj2)):
        r = SomeBool()
        if obj2.is_constant():
            if obj1.is_constant():
                r.const = obj1.const is obj2.const
            if obj2.const is None and not obj1.can_be_none():
                r.const = False
        elif obj1.is_constant():
            if obj1.const is None and not obj2.can_be_none():
                r.const = False
        # XXX HACK HACK HACK
        # XXX HACK HACK HACK
        # XXX HACK HACK HACK
        bk = getbookkeeper()
        if bk is not None:  # for testing
            knowntypedata = r.knowntypedata = {}
            fn, block, i = bk.position_key

            annotator = bk.annotator
            op = block.operations[i]
            assert op.opname == "is_"
            assert len(op.args) == 2

            def bind(src_obj, tgt_obj, tgt_arg):
                if hasattr(tgt_obj, 'is_type_of') and src_obj.is_constant():
                    add_knowntypedata(knowntypedata, True, tgt_obj.is_type_of,
                                      bk.valueoftype(src_obj.const))

                assert annotator.binding(op.args[tgt_arg]) == tgt_obj
                add_knowntypedata(knowntypedata, True, [op.args[tgt_arg]],
                                  src_obj)

                nonnone_obj = tgt_obj
                if src_obj.is_constant(
                ) and src_obj.const is None and tgt_obj.can_be_none():
                    nonnone_obj = tgt_obj.nonnoneify()

                add_knowntypedata(knowntypedata, False, [op.args[tgt_arg]],
                                  nonnone_obj)

            bind(obj2, obj1, 0)
            bind(obj1, obj2, 1)

        return r
Ejemplo n.º 15
0
    def is_((obj1, obj2)):
        r = SomeBool()
        if obj2.is_constant():
            if obj1.is_constant():
                r.const = obj1.const is obj2.const
            if obj2.const is None and not obj1.can_be_none():
                r.const = False
        elif obj1.is_constant():
            if obj1.const is None and not obj2.can_be_none():
                r.const = False
        # XXX HACK HACK HACK
        # XXX HACK HACK HACK
        # XXX HACK HACK HACK
        bk = getbookkeeper()
        if bk is not None:  # for testing
            knowntypedata = r.knowntypedata = {}
            fn, block, i = bk.position_key

            annotator = bk.annotator
            op = block.operations[i]
            assert op.opname == "is_"
            assert len(op.args) == 2

            def bind(src_obj, tgt_obj, tgt_arg):
                if hasattr(tgt_obj, 'is_type_of') and src_obj.is_constant():
                    add_knowntypedata(knowntypedata, True, tgt_obj.is_type_of,
                                      bk.valueoftype(src_obj.const))

                assert annotator.binding(op.args[tgt_arg]) == tgt_obj
                add_knowntypedata(knowntypedata, True, [op.args[tgt_arg]],
                                  src_obj)

                nonnone_obj = tgt_obj
                if src_obj.is_constant(
                ) and src_obj.const is None and tgt_obj.can_be_none():
                    nonnone_obj = tgt_obj.nonnoneify()

                add_knowntypedata(knowntypedata, False, [op.args[tgt_arg]],
                                  nonnone_obj)

            bind(obj2, obj1, 0)
            bind(obj1, obj2, 1)

        return r
Ejemplo n.º 16
0
    def is_true(s_obj):
        r = SomeBool()
        s_obj.is_true_behavior(r)

        bk = getbookkeeper()
        knowntypedata = r.knowntypedata = {}
        fn, block, i = bk.position_key
        op = block.operations[i]
        assert op.opname == "is_true" or op.opname == "nonzero"
        assert len(op.args) == 1
        arg = op.args[0]
        s_nonnone_obj = s_obj
        if s_obj.can_be_none():
            s_nonnone_obj = s_obj.nonnoneify()
        add_knowntypedata(knowntypedata, True, [arg], s_nonnone_obj)
        return r
Ejemplo n.º 17
0
    def test_str(self):
        from pypy.annotation.model import SomeBool

        def f(flag):
            if flag:
                x = 'a'
            else:
                x = 'brrrrrrr'
            return len(x + 'a')

        llinterp, graph = self.llinterpreter_for_transformed_graph(
            f, [SomeBool()])

        res = llinterp.eval_graph(graph, [True])
        assert res == f(True)
        res = llinterp.eval_graph(graph, [False])
        assert res == f(False)
Ejemplo n.º 18
0
 def xor((boo1, boo2)):
     s = SomeBool()
     if boo1.is_constant() and boo2.is_constant():
         s.const = boo1.const ^ boo2.const
     return s
Ejemplo n.º 19
0
 def xor((boo1, boo2)):
     s = SomeBool()
     if boo1.is_constant() and boo2.is_constant():
         s.const = boo1.const ^ boo2.const
     return s
Ejemplo n.º 20
0
 def immutablevalue(self, x, need_const=True):
     """The most precise SomeValue instance that contains the
     immutable value x."""
     # convert unbound methods to the underlying function
     if hasattr(x, 'im_self') and x.im_self is None:
         x = x.im_func
         assert not hasattr(x, 'im_self')
     if x is sys: # special case constant sys to someobject
         return SomeObject()
     tp = type(x)
     if issubclass(tp, Symbolic): # symbolic constants support
         result = x.annotation()
         result.const_box = Constant(x)
         return result
     if tp is bool:
         result = SomeBool()
     elif tp is int:
         result = SomeInteger(nonneg = x>=0)
     elif tp is long and 0 <= x <= (sys.maxint * 2 + 1):
         result = SomeInteger(unsigned = True)
     elif issubclass(tp, str): # py.lib uses annotated str subclasses
         if len(x) == 1:
             result = SomeChar()
         else:
             result = SomeString()
     elif tp is unicode and len(x) == 1:
         result = SomeUnicodeCodePoint()
     elif tp is tuple:
         result = SomeTuple(items = [self.immutablevalue(e, need_const) for e in x])
     elif tp is float:
         result = SomeFloat()
     elif tp is list:
         if need_const:
             key = Constant(x)
             try:
                 return self.immutable_cache[key]
             except KeyError:
                 result = SomeList(ListDef(self, s_ImpossibleValue))
                 self.immutable_cache[key] = result
                 for e in x:
                     result.listdef.generalize(self.immutablevalue(e))
                 result.const_box = key
                 return result
         else:
             listdef = ListDef(self, s_ImpossibleValue)
             for e in x:
                 listdef.generalize(self.immutablevalue(e, False))
             result = SomeList(listdef)    
     elif tp is dict or tp is r_dict:
         if need_const:
             key = Constant(x)
             try:
                 return self.immutable_cache[key]
             except KeyError:
                 result = SomeDict(DictDef(self, 
                                           s_ImpossibleValue,
                                           s_ImpossibleValue,
                                           is_r_dict = tp is r_dict))
                 self.immutable_cache[key] = result
                 if tp is r_dict:
                     s_eqfn = self.immutablevalue(x.key_eq)
                     s_hashfn = self.immutablevalue(x.key_hash)
                     result.dictdef.dictkey.update_rdict_annotations(s_eqfn,
                                                                     s_hashfn)
                 done = False
                 while not done:
                     try:
                         for ek, ev in x.iteritems():
                             result.dictdef.generalize_key(self.immutablevalue(ek))
                             result.dictdef.generalize_value(self.immutablevalue(ev))
                     except RuntimeError, r:
                         pass
                     else:
                         done = True
                 result.const_box = key
                 return result
         else:
             dictdef = DictDef(self, 
             s_ImpossibleValue,
             s_ImpossibleValue,
             is_r_dict = tp is r_dict)
             if tp is r_dict:
                 s_eqfn = self.immutablevalue(x.key_eq)
                 s_hashfn = self.immutablevalue(x.key_hash)
                 dictdef.dictkey.update_rdict_annotations(s_eqfn,
                     s_hashfn)
             for ek, ev in x.iteritems():
                 dictdef.generalize_key(self.immutablevalue(ek, False))
                 dictdef.generalize_value(self.immutablevalue(ev, False))
             result = SomeDict(dictdef)
Ejemplo n.º 21
0
    def pow((int1, int2), obj3):
        knowntype = rarithmetic.compute_restype(int1.knowntype, int2.knowntype)
        return SomeInteger(nonneg=int1.nonneg, knowntype=knowntype)

    pow.can_only_throw = [ZeroDivisionError]
    pow_ovf = _clone(pow, [ZeroDivisionError, OverflowError])

    def inplace_pow((int1, int2)):
        knowntype = rarithmetic.compute_restype(int1.knowntype, int2.knowntype)
        return SomeInteger(nonneg=int1.nonneg, knowntype=knowntype)

    inplace_pow.can_only_throw = [ZeroDivisionError]

    def _compare_helper((int1, int2), opname, operation):
        r = SomeBool()
        if int1.is_immutable_constant() and int2.is_immutable_constant():
            r.const = operation(int1.const, int2.const)
        #
        # The rest of the code propagates nonneg information between
        # the two arguments.
        #
        # Doing the right thing when int1 or int2 change from signed
        # to unsigned (r_uint) is almost impossible.  See test_intcmp_bug.
        # Instead, we only deduce constrains on the operands in the
        # case where they are both signed.  In other words, if y is
        # nonneg then "assert x>=y" will let the annotator know that
        # x is nonneg too, but it will not work if y is unsigned.
        #
        if not (rarithmetic.signedtype(int1.knowntype)
                and rarithmetic.signedtype(int2.knowntype)):
Ejemplo n.º 22
0
    def pow((int1, int2), obj3):
        knowntype = rarithmetic.compute_restype(int1.knowntype, int2.knowntype)
        return SomeInteger(nonneg = int1.nonneg,
                           knowntype=knowntype)
    pow.can_only_throw = [ZeroDivisionError]
    pow_ovf = _clone(pow, [ZeroDivisionError, OverflowError])

    def inplace_pow((int1, int2)):
        knowntype = rarithmetic.compute_restype(int1.knowntype, int2.knowntype)
        return SomeInteger(nonneg = int1.nonneg,
                           knowntype=knowntype)
    inplace_pow.can_only_throw = [ZeroDivisionError]

    def _compare_helper((int1, int2), opname, operation):
        r = SomeBool()
        if int1.is_immutable_constant() and int2.is_immutable_constant():
            r.const = operation(int1.const, int2.const)
        #
        # The rest of the code propagates nonneg information between
        # the two arguments.
        #
        # Doing the right thing when int1 or int2 change from signed
        # to unsigned (r_uint) is almost impossible.  See test_intcmp_bug.
        # Instead, we only deduce constrains on the operands in the
        # case where they are both signed.  In other words, if y is
        # nonneg then "assert x>=y" will let the annotator know that
        # x is nonneg too, but it will not work if y is unsigned.
        #
        if not (rarithmetic.signedtype(int1.knowntype) and
                rarithmetic.signedtype(int2.knowntype)):
Ejemplo n.º 23
0
 def immutablevalue(self, x, need_const=True):
     """The most precise SomeValue instance that contains the
     immutable value x."""
     # convert unbound methods to the underlying function
     if hasattr(x, 'im_self') and x.im_self is None:
         x = x.im_func
         assert not hasattr(x, 'im_self')
     if x is sys:  # special case constant sys to someobject
         return SomeObject()
     tp = type(x)
     if issubclass(tp, Symbolic):  # symbolic constants support
         result = x.annotation()
         result.const_box = Constant(x)
         return result
     if tp is bool:
         result = SomeBool()
     elif tp is int:
         result = SomeInteger(nonneg=x >= 0)
     elif tp is long:
         if -sys.maxint - 1 <= x <= sys.maxint:
             x = int(x)
             result = SomeInteger(nonneg=x >= 0)
         else:
             raise Exception("seeing a prebuilt long (value %s)" % hex(x))
     elif issubclass(tp, str):  # py.lib uses annotated str subclasses
         if len(x) == 1:
             result = SomeChar()
         else:
             result = SomeString()
     elif tp is unicode:
         if len(x) == 1:
             result = SomeUnicodeCodePoint()
         else:
             result = SomeUnicodeString()
     elif tp is tuple:
         result = SomeTuple(
             items=[self.immutablevalue(e, need_const) for e in x])
     elif tp is float:
         result = SomeFloat()
     elif tp is list:
         if need_const:
             key = Constant(x)
             try:
                 return self.immutable_cache[key]
             except KeyError:
                 result = SomeList(ListDef(self, s_ImpossibleValue))
                 self.immutable_cache[key] = result
                 for e in x:
                     result.listdef.generalize(self.immutablevalue(e))
                 result.const_box = key
                 return result
         else:
             listdef = ListDef(self, s_ImpossibleValue)
             for e in x:
                 listdef.generalize(self.immutablevalue(e, False))
             result = SomeList(listdef)
     elif tp is dict or tp is r_dict:
         if need_const:
             key = Constant(x)
             try:
                 return self.immutable_cache[key]
             except KeyError:
                 result = SomeDict(
                     DictDef(self,
                             s_ImpossibleValue,
                             s_ImpossibleValue,
                             is_r_dict=tp is r_dict))
                 self.immutable_cache[key] = result
                 if tp is r_dict:
                     s_eqfn = self.immutablevalue(x.key_eq)
                     s_hashfn = self.immutablevalue(x.key_hash)
                     result.dictdef.dictkey.update_rdict_annotations(
                         s_eqfn, s_hashfn)
                 seen_elements = 0
                 while seen_elements != len(x):
                     items = x.items()
                     for ek, ev in items:
                         result.dictdef.generalize_key(
                             self.immutablevalue(ek))
                         result.dictdef.generalize_value(
                             self.immutablevalue(ev))
                         result.dictdef.seen_prebuilt_key(ek)
                     seen_elements = len(items)
                     # if the dictionary grew during the iteration,
                     # start over again
                 result.const_box = key
                 return result
         else:
             dictdef = DictDef(self,
                               s_ImpossibleValue,
                               s_ImpossibleValue,
                               is_r_dict=tp is r_dict)
             if tp is r_dict:
                 s_eqfn = self.immutablevalue(x.key_eq)
                 s_hashfn = self.immutablevalue(x.key_hash)
                 dictdef.dictkey.update_rdict_annotations(s_eqfn, s_hashfn)
             for ek, ev in x.iteritems():
                 dictdef.generalize_key(self.immutablevalue(ek, False))
                 dictdef.generalize_value(self.immutablevalue(ev, False))
                 dictdef.seen_prebuilt_key(ek)
             result = SomeDict(dictdef)
     elif tp is weakref.ReferenceType:
         x1 = x()
         if x1 is None:
             result = SomeWeakRef(None)  # dead weakref
         else:
             s1 = self.immutablevalue(x1)
             assert isinstance(s1, SomeInstance)
             result = SomeWeakRef(s1.classdef)
     elif ishashable(x) and x in BUILTIN_ANALYZERS:
         _module = getattr(x, "__module__", "unknown")
         result = SomeBuiltin(BUILTIN_ANALYZERS[x],
                              methodname="%s.%s" % (_module, x.__name__))
     elif extregistry.is_registered(x, self.policy):
         entry = extregistry.lookup(x, self.policy)
         result = entry.compute_annotation_bk(self)
     elif isinstance(x, lltype._ptr):
         result = SomePtr(lltype.typeOf(x))
     elif isinstance(x, llmemory.fakeaddress):
         result = SomeAddress()
     elif isinstance(x, ootype._static_meth):
         result = SomeOOStaticMeth(ootype.typeOf(x))
     elif isinstance(x, ootype._class):
         result = SomeOOClass(x._INSTANCE)  # NB. can be None
     elif isinstance(x, ootype.instance_impl):  # XXX
         result = SomeOOInstance(ootype.typeOf(x))
     elif isinstance(x, (ootype._record, ootype._string)):
         result = SomeOOInstance(ootype.typeOf(x))
     elif isinstance(x, (ootype._object)):
         result = SomeOOObject()
     elif callable(x):
         if hasattr(x, 'im_self') and hasattr(x, 'im_func'):
             # on top of PyPy, for cases like 'l.append' where 'l' is a
             # global constant list, the find_method() returns non-None
             s_self = self.immutablevalue(x.im_self, need_const)
             result = s_self.find_method(x.im_func.__name__)
         elif hasattr(x, '__self__') and x.__self__ is not None:
             # for cases like 'l.append' where 'l' is a global constant list
             s_self = self.immutablevalue(x.__self__, need_const)
             result = s_self.find_method(x.__name__)
             if result is None:
                 result = SomeObject()
         else:
             result = None
         if result is None:
             if (self.annotator.policy.allow_someobjects
                     and getattr(x, '__module__', None) == '__builtin__'
                     # XXX note that the print support functions are __builtin__
                     and tp not in (types.FunctionType, types.MethodType)):
                 result = SomeObject()
                 result.knowntype = tp  # at least for types this needs to be correct
             else:
                 result = SomePBC([self.getdesc(x)])
     elif hasattr(x, '_freeze_') and x._freeze_():
         # user-defined classes can define a method _freeze_(), which
         # is called when a prebuilt instance is found.  If the method
         # returns True, the instance is considered immutable and becomes
         # a SomePBC().  Otherwise it's just SomeInstance().
         result = SomePBC([self.getdesc(x)])
     elif hasattr(x, '__class__') \
              and x.__class__.__module__ != '__builtin__':
         self.see_mutable(x)
         result = SomeInstance(self.getuniqueclassdef(x.__class__))
     elif x is None:
         return s_None
     else:
         result = SomeObject()
     if need_const:
         result.const = x
     return result
Ejemplo n.º 24
0
 def immutablevalue(self, x, need_const=True):
     """The most precise SomeValue instance that contains the
     immutable value x."""
     # convert unbound methods to the underlying function
     if hasattr(x, 'im_self') and x.im_self is None:
         x = x.im_func
         assert not hasattr(x, 'im_self')
     if x is sys: # special case constant sys to someobject
         return SomeObject()
     tp = type(x)
     if issubclass(tp, Symbolic): # symbolic constants support
         result = x.annotation()
         result.const_box = Constant(x)
         return result
     if tp is bool:
         result = SomeBool()
     elif tp is int:
         result = SomeInteger(nonneg = x>=0)
     elif tp is long:
         if -sys.maxint-1 <= x <= sys.maxint:
             x = int(x)
             result = SomeInteger(nonneg = x>=0)
         else:
             raise Exception("seeing a prebuilt long (value %s)" % hex(x))
     elif issubclass(tp, str): # py.lib uses annotated str subclasses
         no_nul = not '\x00' in x
         if len(x) == 1:
             result = SomeChar(no_nul=no_nul)
         else:
             result = SomeString(no_nul=no_nul)
     elif tp is unicode:
         if len(x) == 1:
             result = SomeUnicodeCodePoint()
         else:
             result = SomeUnicodeString()
     elif tp is tuple:
         result = SomeTuple(items = [self.immutablevalue(e, need_const) for e in x])
     elif tp is float:
         result = SomeFloat()
     elif tp is list:
         if need_const:
             key = Constant(x)
             try:
                 return self.immutable_cache[key]
             except KeyError:
                 result = SomeList(ListDef(self, s_ImpossibleValue))
                 self.immutable_cache[key] = result
                 for e in x:
                     result.listdef.generalize(self.immutablevalue(e))
                 result.const_box = key
                 return result
         else:
             listdef = ListDef(self, s_ImpossibleValue)
             for e in x:
                 listdef.generalize(self.immutablevalue(e, False))
             result = SomeList(listdef)    
     elif tp is dict or tp is r_dict:
         if need_const:
             key = Constant(x)
             try:
                 return self.immutable_cache[key]
             except KeyError:
                 result = SomeDict(DictDef(self, 
                                           s_ImpossibleValue,
                                           s_ImpossibleValue,
                                           is_r_dict = tp is r_dict))
                 self.immutable_cache[key] = result
                 if tp is r_dict:
                     s_eqfn = self.immutablevalue(x.key_eq)
                     s_hashfn = self.immutablevalue(x.key_hash)
                     result.dictdef.dictkey.update_rdict_annotations(s_eqfn,
                                                                     s_hashfn)
                 seen_elements = 0
                 while seen_elements != len(x):
                     items = x.items()
                     for ek, ev in items:
                         result.dictdef.generalize_key(self.immutablevalue(ek))
                         result.dictdef.generalize_value(self.immutablevalue(ev))
                         result.dictdef.seen_prebuilt_key(ek)
                     seen_elements = len(items)
                     # if the dictionary grew during the iteration,
                     # start over again
                 result.const_box = key
                 return result
         else:
             dictdef = DictDef(self, 
             s_ImpossibleValue,
             s_ImpossibleValue,
             is_r_dict = tp is r_dict)
             if tp is r_dict:
                 s_eqfn = self.immutablevalue(x.key_eq)
                 s_hashfn = self.immutablevalue(x.key_hash)
                 dictdef.dictkey.update_rdict_annotations(s_eqfn,
                     s_hashfn)
             for ek, ev in x.iteritems():
                 dictdef.generalize_key(self.immutablevalue(ek, False))
                 dictdef.generalize_value(self.immutablevalue(ev, False))
                 dictdef.seen_prebuilt_key(ek)
             result = SomeDict(dictdef)
     elif tp is weakref.ReferenceType:
         x1 = x()
         if x1 is None:
             result = SomeWeakRef(None)    # dead weakref
         else:
             s1 = self.immutablevalue(x1)
             assert isinstance(s1, SomeInstance)
             result = SomeWeakRef(s1.classdef)
     elif ishashable(x) and x in BUILTIN_ANALYZERS:
         _module = getattr(x,"__module__","unknown")
         result = SomeBuiltin(BUILTIN_ANALYZERS[x], methodname="%s.%s" % (_module, x.__name__))
     elif extregistry.is_registered(x, self.policy):
         entry = extregistry.lookup(x, self.policy)
         result = entry.compute_annotation_bk(self)
     elif isinstance(x, lltype._ptr):
         result = SomePtr(lltype.typeOf(x))
     elif isinstance(x, llmemory.fakeaddress):
         result = SomeAddress()
     elif isinstance(x, ootype._static_meth):
         result = SomeOOStaticMeth(ootype.typeOf(x))
     elif isinstance(x, ootype._class):
         result = SomeOOClass(x._INSTANCE)   # NB. can be None
     elif isinstance(x, ootype.instance_impl): # XXX
         result = SomeOOInstance(ootype.typeOf(x))
     elif isinstance(x, (ootype._record, ootype._string)):
         result = SomeOOInstance(ootype.typeOf(x))
     elif isinstance(x, (ootype._object)):
         result = SomeOOObject()
     elif callable(x):
         if hasattr(x, 'im_self') and hasattr(x, 'im_func'):
             # on top of PyPy, for cases like 'l.append' where 'l' is a
             # global constant list, the find_method() returns non-None
             s_self = self.immutablevalue(x.im_self, need_const)
             result = s_self.find_method(x.im_func.__name__)
         elif hasattr(x, '__self__') and x.__self__ is not None:
             # for cases like 'l.append' where 'l' is a global constant list
             s_self = self.immutablevalue(x.__self__, need_const)
             result = s_self.find_method(x.__name__)
             if result is None:
                 result = SomeObject()
         else:
             result = None
         if result is None:
             if (self.annotator.policy.allow_someobjects
                 and getattr(x, '__module__', None) == '__builtin__'
                 # XXX note that the print support functions are __builtin__
                 and tp not in (types.FunctionType, types.MethodType)):
                 result = SomeObject()
                 result.knowntype = tp # at least for types this needs to be correct
             else:
                 result = SomePBC([self.getdesc(x)])
     elif hasattr(x, '_freeze_') and x._freeze_():
         # user-defined classes can define a method _freeze_(), which
         # is called when a prebuilt instance is found.  If the method
         # returns True, the instance is considered immutable and becomes
         # a SomePBC().  Otherwise it's just SomeInstance().
         result = SomePBC([self.getdesc(x)])
     elif hasattr(x, '__class__') \
              and x.__class__.__module__ != '__builtin__':
         self.see_mutable(x)
         result = SomeInstance(self.getuniqueclassdef(x.__class__))
     elif x is None:
         return s_None
     else:
         result = SomeObject()
     if need_const:
         result.const = x
     return result