Ejemplo n.º 1
0
    def getclassdef(self, key):
        try:
            return self._classdefs[key]
        except KeyError:
            from rpython.annotator.classdef import (
                ClassDef, FORCE_ATTRIBUTES_INTO_CLASSES)
            classdef = ClassDef(self.bookkeeper, self)
            self.bookkeeper.classdefs.append(classdef)
            self._classdefs[key] = classdef

            # forced attributes
            cls = self.pyobj
            if cls in FORCE_ATTRIBUTES_INTO_CLASSES:
                for name, s_value in FORCE_ATTRIBUTES_INTO_CLASSES[cls].items(
                ):
                    classdef.generalize_attr(name, s_value)
                    classdef.find_attribute(name).modified(classdef)

            # register all class attributes as coming from this ClassDesc
            # (as opposed to prebuilt instances)
            classsources = {}
            for attr in self.classdict:
                classsources[attr] = self  # comes from this ClassDesc
            classdef.setup(classsources)
            # look for a __del__ method and annotate it if it's there
            if '__del__' in self.classdict:
                from rpython.annotator.model import s_None, SomeInstance
                s_func = self.s_read_attribute('__del__')
                args_s = [SomeInstance(classdef)]
                s = self.bookkeeper.emulate_pbc_call(classdef, s_func, args_s)
                assert s_None.contains(s)
            return classdef
Ejemplo n.º 2
0
 def improve((ins1, ins2)):
     if ins1.classdef is None:
         resdef = ins2.classdef
     elif ins2.classdef is None:
         resdef = ins1.classdef
     else:
         basedef = ins1.classdef.commonbase(ins2.classdef)
         if basedef is ins1.classdef:
             resdef = ins2.classdef
         elif basedef is ins2.classdef:
             resdef = ins1.classdef
         else:
             if ins1.can_be_None and ins2.can_be_None:
                 return s_None
             else:
                 return s_ImpossibleValue
     res = SomeInstance(resdef,
                        can_be_None=ins1.can_be_None and ins2.can_be_None)
     if ins1.contains(res) and ins2.contains(res):
         return res  # fine
     else:
         # this case can occur in the presence of 'const' attributes,
         # which we should try to preserve.  Fall-back...
         thistype = pairtype(SomeInstance, SomeInstance)
         return super(thistype, pair(ins1, ins2)).improve()
Ejemplo n.º 3
0
 def pycall(self, schedule, args, s_previous_result, op=None):
     from rpython.annotator.model import SomeInstance
     if self.selfclassdef is None:
         raise Exception("calling %r" % (self, ))
     s_instance = SomeInstance(self.selfclassdef, flags=self.flags)
     args = args.prepend(s_instance)
     return self.funcdesc.pycall(schedule, args, s_previous_result, op)
Ejemplo n.º 4
0
 def pycall(self, whence, args, s_previous_result, op=None):
     from rpython.annotator.model import SomeInstance, SomeImpossibleValue
     classdef = self.getuniqueclassdef()
     s_instance = SomeInstance(classdef)
     # look up __init__ directly on the class, bypassing the normal
     # lookup mechanisms ClassDef (to avoid influencing Attribute placement)
     s_init = self.s_read_attribute('__init__')
     if isinstance(s_init, SomeImpossibleValue):
         # no __init__: check that there are no constructor args
         if not self.is_exception_class():
             try:
                 args.fixedunpack(0)
             except ValueError:
                 raise Exception("default __init__ takes no argument"
                                 " (class %s)" % (self.name, ))
         elif self.pyobj is Exception:
             # check explicitly against "raise Exception, x" where x
             # is a low-level exception pointer
             try:
                 [s_arg] = args.fixedunpack(1)
             except ValueError:
                 pass
             else:
                 from rpython.rtyper.llannotation import SomePtr
                 assert not isinstance(s_arg, SomePtr)
     else:
         # call the constructor
         args = args.prepend(s_instance)
         s_init.call(args)
     return s_instance
Ejemplo n.º 5
0
def test_annotation_to_lltype():
    s_i = SomeInteger()
    s_pos = SomeInteger(nonneg=True)
    s_1 = SomeInteger(nonneg=True)
    s_1.const = 1
    s_m1 = SomeInteger(nonneg=False)
    s_m1.const = -1
    s_u = SomeInteger(nonneg=True, unsigned=True)
    s_u1 = SomeInteger(nonneg=True, unsigned=True)
    s_u1.const = r_uint(1)
    assert annotation_to_lltype(s_i) == lltype.Signed
    assert annotation_to_lltype(s_pos) == lltype.Signed
    assert annotation_to_lltype(s_1) == lltype.Signed
    assert annotation_to_lltype(s_m1) == lltype.Signed
    assert annotation_to_lltype(s_u) == lltype.Unsigned
    assert annotation_to_lltype(s_u1) == lltype.Unsigned
    assert annotation_to_lltype(SomeBool()) == lltype.Bool
    assert annotation_to_lltype(SomeChar()) == lltype.Char
    PS = lltype.Ptr(lltype.GcStruct('s'))
    s_p = SomePtr(ll_ptrtype=PS)
    assert annotation_to_lltype(s_p) == PS
    si0 = SomeInstance(DummyClassDef(), True)
    with py.test.raises(ValueError):
        annotation_to_lltype(si0)
    s_singlefloat = SomeSingleFloat()
    s_singlefloat.const = r_singlefloat(0.0)
    assert annotation_to_lltype(s_singlefloat) == lltype.SingleFloat
Ejemplo n.º 6
0
def annotationoftype(t, bookkeeper=False):
    from rpython.rtyper 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 types.NoneType:
        return s_None
    elif bookkeeper and extregistry.is_registered_type(t):
        entry = extregistry.lookup_type(t)
        return entry.compute_annotation_bk(bookkeeper)
    elif t is type:
        return SomeType()
    elif bookkeeper and not hasattr(t, '_freeze_'):
        classdef = bookkeeper.getuniqueclassdef(t)
        return SomeInstance(classdef)
    else:
        raise AssertionError("annotationoftype(%r)" % (t, ))
Ejemplo n.º 7
0
 def get_exception(self, operation):
     """
     Return the annotation for all exceptions that `operation` may raise.
     """
     can_only_throw = operation.get_can_only_throw(self)
     if can_only_throw is None:
         return SomeInstance(self.bookkeeper.getuniqueclassdef(Exception))
     else:
         return self.bookkeeper.new_exception(can_only_throw)
Ejemplo n.º 8
0
def robjmodel_instantiate(s_clspbc, s_nonmovable=None):
    assert isinstance(s_clspbc, SomePBC)
    clsdef = None
    more_than_one = len(s_clspbc.descriptions) > 1
    for desc in s_clspbc.descriptions:
        cdef = desc.getuniqueclassdef()
        if more_than_one:
            getbookkeeper().needs_generic_instantiate[cdef] = True
        if not clsdef:
            clsdef = cdef
        else:
            clsdef = clsdef.commonbase(cdef)
    return SomeInstance(clsdef)
Ejemplo n.º 9
0
 def compute_result_annotation(self, x_s, type_s):
     assert isinstance(x_s, SomeOOInstance)
     assert isinstance(x_s.ootype, NativeInstance)
     assert type_s.is_constant()
     TYPE = type_s.const
     if isinstance(TYPE, (type, types.ClassType)):
         # it's a user-defined class, so we return SomeInstance
         # can_be_None == True because it can always return None, if it fails
         classdef = self.bookkeeper.getuniqueclassdef(TYPE)
         return SomeInstance(classdef, can_be_None=True)
     elif TYPE in BOXABLE_TYPES:
         return OverloadingResolver.lltype_to_annotation(TYPE)
     elif isinstance(TYPE, ootype.StaticMethod):
         return SomeOOStaticMeth(TYPE)
     elif isinstance(TYPE, ootype.OOType):
         return SomeOOInstance(TYPE)
     else:
         assert False
Ejemplo n.º 10
0
 def union((ins1, ins2)):
     if ins1.classdef is None or ins2.classdef is None:
         # special case only
         basedef = None
     else:
         basedef = ins1.classdef.commonbase(ins2.classdef)
         if basedef is None:
             raise UnionError(ins1, ins2, "RPython cannot unify instances "
                     "with no common base class")
     flags = ins1.flags
     if flags:
         flags = flags.copy()
         for key, value in flags.items():
             if key not in ins2.flags or ins2.flags[key] != value:
                 del flags[key]
     return SomeInstance(basedef,
                         can_be_None=ins1.can_be_None or ins2.can_be_None,
                         flags=flags)
Ejemplo n.º 11
0
 def union((ins1, ins2)):
     if ins1.classdef is None or ins2.classdef is None:
         # special case only
         basedef = None
     else:
         basedef = ins1.classdef.commonbase(ins2.classdef)
         if basedef is None:
             print "\n\nUnionError will be thrown, basically there are 2 or more classes that are on a same context (variable, function args, or function return) that aren't compatible. Here are their __dict__:"
             print '\n', ins1.classdef.classdesc.classdict
             print '\n', ins2.classdef.classdesc.classdict, '\n'
             raise UnionError(ins1, ins2, "RPython cannot unify instances "
                     "with no common base class")
     flags = ins1.flags
     if flags:
         flags = flags.copy()
         for key, value in flags.items():
             if key not in ins2.flags or ins2.flags[key] != value:
                 del flags[key]
     return SomeInstance(basedef,
                         can_be_None=ins1.can_be_None or ins2.can_be_None,
                         flags=flags)
Ejemplo n.º 12
0
 def compute_result_annotation(self, s_w_obj):
     cls = self.instance.expecting
     s_inst = SomeInstance(self.bookkeeper.getuniqueclassdef(cls),
                           can_be_None=True)
     assert s_inst.contains(s_w_obj)
     return s_None
Ejemplo n.º 13
0
 def simple_call(self):
     if self.classdef is None:
         return s_None  # known to be a dead weakref
     else:
         return SomeInstance(self.classdef, can_be_None=True)
Ejemplo n.º 14
0
 def immutablevalue(self, x):
     """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')
     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 bytearray:
         result = SomeByteArray()
     elif tp is tuple:
         result = SomeTuple(items=[self.immutablevalue(e) for e in x])
     elif tp is float:
         result = SomeFloat()
     elif tp is list:
         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
     elif (tp is dict or tp is r_dict or tp is SomeOrderedDict.knowntype
           or tp is r_ordereddict):
         key = Constant(x)
         try:
             return self.immutable_cache[key]
         except KeyError:
             if tp is SomeOrderedDict.knowntype or tp is r_ordereddict:
                 cls = SomeOrderedDict
             else:
                 cls = SomeDict
             is_r_dict = issubclass(tp, r_dict)
             result = cls(
                 DictDef(self,
                         s_ImpossibleValue,
                         s_ImpossibleValue,
                         is_r_dict=is_r_dict))
             self.immutable_cache[key] = result
             if 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
     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 tp is property:
         return SomeProperty(x)
     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):
         entry = extregistry.lookup(x)
         result = entry.compute_annotation_bk(self)
     elif tp is type:
         result = SomeConstantType(x, self)
     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)
             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__)
             result = s_self.find_method(x.__name__)
             assert result is not None
         else:
             result = None
         if result is None:
             result = SomePBC([self.getdesc(x)])
     elif hasattr(x, '_freeze_'):
         assert x._freeze_() is True
         # 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__':
         if hasattr(x, '_cleanup_'):
             x._cleanup_()
         self.see_mutable(x)
         result = SomeInstance(self.getuniqueclassdef(x.__class__))
     elif x is None:
         return s_None
     else:
         raise Exception("Don't know how to represent %r" % (x, ))
     result.const = x
     return result
Ejemplo n.º 15
0
 def compute_result_annotation(self, s_w_obj):
     cls = self.instance.expecting
     s_inst = SomeInstance(self.bookkeeper.getuniqueclassdef(cls),
                           can_be_None=True)
     assert s_inst.contains(s_w_obj)
     return s_None
Ejemplo n.º 16
0
 def func_args(self, args):
     from rpython.annotator.model import SomeInstance
     if self.selfclassdef is None:
         raise Exception("calling %r" % (self, ))
     s_instance = SomeInstance(self.selfclassdef, flags=self.flags)
     return args.prepend(s_instance)