Beispiel #1
0
    def emulate_rdict_calls(self, other=None):
        myeq = (self, 'eq')
        myhash = (self, 'hash')
        if other:
            replace_othereq = [(other, 'eq')]
            replace_otherhash = [(other, 'hash')]
        else:
            replace_othereq = replace_otherhash = ()

        s_key = self.s_value

        s = self.bookkeeper.emulate_pbc_call(myeq,
                                             self.s_rdict_eqfn, [s_key, s_key],
                                             replace=replace_othereq)
        if not s_Bool.contains(s):
            raise AnnotatorError(
                "the custom eq function of an r_dict must return a boolean"
                " (got %r)" % (s, ))

        s = self.bookkeeper.emulate_pbc_call(myhash,
                                             self.s_rdict_hashfn, [s_key],
                                             replace=replace_otherhash)
        if not SomeInteger().contains(s):
            raise AnnotatorError(
                "the custom hash function of an r_dict must return an integer"
                " (got %r)" % (s, ))
Beispiel #2
0
def check_negative_slice(s_start, s_stop, error="slicing"):
    if isinstance(s_start, SomeInteger) and not s_start.nonneg:
        raise AnnotatorError("%s: not proven to have non-negative start" %
                             error)
    if isinstance(s_stop, SomeInteger) and not s_stop.nonneg and \
           getattr(s_stop, 'const', 0) != -1:
        raise AnnotatorError("%s: not proven to have non-negative stop" % error)
Beispiel #3
0
def weakref_ref(s_obj):
    if not isinstance(s_obj, SomeInstance):
        raise AnnotatorError("cannot take a weakref to %r" % (s_obj,))
    if s_obj.can_be_None:
        raise AnnotatorError("should assert that the instance we take "
                        "a weakref to cannot be None")
    return SomeWeakRef(s_obj.classdef)
Beispiel #4
0
 def method_decode(self, s_enc):
     if not s_enc.is_constant():
         raise AnnotatorError("Non-constant encoding not supported")
     enc = s_enc.const
     if enc not in ('ascii', 'latin-1', 'utf-8'):
         raise AnnotatorError("Encoding %s not supported for strings" % (enc,))
     return SomeUnicodeString(no_nul=self.no_nul)
Beispiel #5
0
 def mod((s_string, s_tuple)):
     if not s_string.is_constant():
         raise AnnotatorError("string formatting requires a constant "
                              "string/unicode on the left of '%'")
     is_string = isinstance(s_string, SomeString)
     is_unicode = isinstance(s_string, SomeUnicodeString)
     assert is_string or is_unicode
     for s_item in s_tuple.items:
         if (is_unicode and isinstance(s_item,
                                       (SomeChar, SomeString)) or is_string
                 and isinstance(s_item,
                                (SomeUnicodeCodePoint, SomeUnicodeString))):
             raise AnnotatorError(
                 "string formatting mixing strings and unicode not supported"
             )
     no_nul = s_string.no_nul
     for s_item in s_tuple.items:
         if isinstance(s_item, SomeFloat):
             pass  # or s_item is a subclass, like SomeInteger
         elif (isinstance(s_item, SomeString)
               or isinstance(s_item, SomeUnicodeString)) and s_item.no_nul:
             pass
         else:
             no_nul = False
             break
     return s_string.__class__(no_nul=no_nul)
Beispiel #6
0
 def getdesc(self, pyobj):
     # get the XxxDesc wrapper for the given Python object, which must be
     # one of:
     #  * a user-defined Python function
     #  * a Python type or class (but not a built-in one like 'int')
     #  * a user-defined bound or unbound method object
     #  * a frozen pre-built constant (with _freeze_() == True)
     #  * a bound method of a frozen pre-built constant
     obj_key = Constant(pyobj)
     try:
         return self.descs[obj_key]
     except KeyError:
         if isinstance(pyobj, types.FunctionType):
             result = self.newfuncdesc(pyobj)
         elif isinstance(pyobj, (type, types.ClassType)):
             if pyobj is object:
                 raise AnnotatorError("ClassDesc for object not supported")
             if pyobj.__module__ == '__builtin__':  # avoid making classdefs for builtin types
                 result = self.getfrozen(pyobj)
             else:
                 result = ClassDesc(self, pyobj)
         elif isinstance(pyobj, types.MethodType):
             if pyobj.im_self is None:  # unbound
                 return self.getdesc(pyobj.im_func)
             if hasattr(pyobj.im_self, '_cleanup_'):
                 pyobj.im_self._cleanup_()
             if hasattr(pyobj.im_self, '_freeze_'):  # method of frozen
                 assert pyobj.im_self._freeze_() is True
                 result = description.MethodOfFrozenDesc(
                     self,
                     self.getdesc(pyobj.im_func),  # funcdesc
                     self.getdesc(pyobj.im_self))  # frozendesc
             else:  # regular method
                 origincls, name = origin_of_meth(pyobj)
                 classdef = self.getuniqueclassdef(pyobj.im_class)
                 classdef.see_instance(pyobj.im_self)
                 assert pyobj == getattr(
                     pyobj.im_self, name), ("%r is not %s.%s ??" %
                                            (pyobj, pyobj.im_self, name))
                 # emulate a getattr to make sure it's on the classdef
                 classdef.find_attribute(name)
                 result = self.getmethoddesc(
                     self.getdesc(pyobj.im_func),  # funcdesc
                     self.getuniqueclassdef(origincls),  # originclassdef
                     classdef,  # selfclassdef
                     name)
         else:
             # must be a frozen pre-built constant, but let's check
             if hasattr(pyobj, '_freeze_'):
                 assert pyobj._freeze_() is True
             else:
                 if hasattr(pyobj, '__call__'):
                     msg = "object with a __call__ is not RPython"
                 else:
                     msg = "unexpected prebuilt constant"
                 raise AnnotatorError("%s: %r" % (msg, pyobj))
             result = self.getfrozen(pyobj)
         self.descs[obj_key] = result
         return result
Beispiel #7
0
 def getattr(self, s_attr):
     # get a SomeBuiltin if the SomeObject has
     # a corresponding method to handle it
     if not s_attr.is_constant() or not isinstance(s_attr.const, str):
         raise AnnotatorError("getattr(%r, %r) has non-constant argument" %
                              (self, s_attr))
     attr = s_attr.const
     s_method = self.find_method(attr)
     if s_method is not None:
         return s_method
     # if the SomeObject is itself a constant, allow reading its attrs
     if self.is_immutable_constant() and hasattr(self.const, attr):
         return immutablevalue(getattr(self.const, attr))
     raise AnnotatorError("Cannot find attribute %r on %r" % (attr, self))
Beispiel #8
0
 def _dispatch(cls, Some_cls):
     for c in Some_cls.__mro__:
         try:
             return cls._registry[c]
         except KeyError:
             pass
     raise AnnotatorError("Unknown operation")
Beispiel #9
0
 def setslice(self, s_start, s_stop, s_iterable):
     check_negative_slice(s_start, s_stop)
     if not isinstance(s_iterable, SomeList):
         raise AnnotatorError("list[start:stop] = x: x must be a list")
     self.listdef.mutate()
     self.listdef.agree(getbookkeeper(), s_iterable.listdef)
     self.listdef.resize()
Beispiel #10
0
    def mutated(self, homedef): # reflow from attr read positions
        s_newvalue = self.getvalue()

        for position in self.read_locations:
            self.bookkeeper.annotator.reflowfromposition(position)

        # check for method demotion and after-the-fact method additions
        if isinstance(s_newvalue, SomePBC):
            attr = self.name
            if s_newvalue.getKind() == description.MethodDesc:
                # is method
                if homedef.classdesc.read_attribute(attr, None) is None:
                    if not homedef.check_missing_attribute_update(attr):
                        for desc in s_newvalue.descriptions:
                            if desc.selfclassdef is None:
                                if homedef.classdesc.settled:
                                    raise AnnotatorError(
                                        "demoting method %s to settled class "
                                        "%s not allowed" % (self.name, homedef)
                                    )
                                break

        # check for attributes forbidden by slots or _attrs_
        if homedef.classdesc.all_enforced_attrs is not None:
            if self.name not in homedef.classdesc.all_enforced_attrs:
                self.attr_allowed = False
                if not self.readonly:
                    raise NoSuchAttrError(
                        "the attribute %r goes here to %r, "
                        "but it is forbidden here" % (
                        self.name, homedef))
Beispiel #11
0
 def getattr(self, s_attr):
     if not(s_attr.is_constant() and isinstance(s_attr.const, str)):
         raise AnnotatorError("A variable argument to getattr is not RPython")
     attr = s_attr.const
     if attr == '__class__':
         return self.classdef.read_attr__class__()
     getbookkeeper().record_getattr(self.classdef.classdesc, attr)
     return self.classdef.s_getattr(attr, self.flags)
Beispiel #12
0
def builtin_enumerate(s_obj, s_start=None):
    const = None
    if s_start is not None:
        if not s_start.is_constant():
            raise AnnotatorError(
                "second argument to enumerate must be constant")
        const = s_start.const
    return SomeIterator(s_obj, "enumerate", const)
Beispiel #13
0
    def compute_result_annotation(self, s_sizehint):
        from rpython.annotator.model import SomeInteger, AnnotatorError

        if not isinstance(s_sizehint, SomeInteger):
            raise AnnotatorError("newlist_hint() argument must be an int")
        s_l = self.bookkeeper.newlist()
        s_l.listdef.listitem.resize()
        return s_l
Beispiel #14
0
 def method_encode(self, s_enc):
     if not s_enc.is_constant():
         raise AnnotatorError("Non-constant encoding not supported")
     enc = s_enc.const
     if enc not in ('ascii', 'latin-1', 'utf-8', 'utf8'):
         raise AnnotatorError("Encoding %s not supported for unicode" % (enc,))
     if enc == 'utf-8':
         from rpython.rlib import runicode
         bookkeeper = getbookkeeper()
         s_func = bookkeeper.immutablevalue(
                          runicode.unicode_encode_utf_8_elidable)
         s_errors = bookkeeper.immutablevalue('strict')
         s_errorhandler = bookkeeper.immutablevalue(
                                 runicode.default_unicode_error_encode)
         s_allow_surr = bookkeeper.immutablevalue(True)
         args = [self, self.len(), s_errors, s_errorhandler, s_allow_surr]
         bookkeeper.emulate_pbc_call(bookkeeper.position_key, s_func, args)
     return SomeString(no_nul=self.no_nul)
Beispiel #15
0
class __extend__(pairtype(SomePtr, SomeObject)):
    def union((p, obj)):
        raise UnionError(p, obj)

    def getitem((p, obj)):
        raise AnnotatorError("ptr %r getitem index not an int: %r" %
                             (p.ll_ptrtype, obj))

    def setitem((p, obj), s_value):
        raise AnnotatorError("ptr %r setitem index not an int: %r" %
                             (p.ll_ptrtype, obj))
Beispiel #16
0
def origin_of_meth(boundmeth):
    func = boundmeth.im_func
    candname = func.__name__
    for cls in inspect.getmro(boundmeth.im_class):
        dict = cls.__dict__
        if dict.get(candname) is func:
            return cls, candname
        for name, value in dict.iteritems():
            if value is func:
                return cls, name
    raise AnnotatorError("could not match bound-method to attribute name: %r" %
                         (boundmeth, ))
Beispiel #17
0
def setattr_SomeInstance(annotator, v_obj, v_attr, v_value):
    s_attr = annotator.annotation(v_attr)
    if not s_attr.is_constant() or not isinstance(s_attr.const, str):
        return
    attr = s_attr.const
    setters = _find_property_meth(annotator.annotation(v_obj), attr, 'fset')
    if setters:
        if all(setters):
            get_setter = op.getattr(v_obj, const(attr + '__setter__'))
            return [get_setter, op.simple_call(get_setter.result, v_value)]
        elif not any(setters):
            raise AnnotatorError("Attribute %r is unwritable" % attr)
Beispiel #18
0
def builtin_range(*args):
    s_step = immutablevalue(1)
    if len(args) == 1:
        s_start = immutablevalue(0)
        s_stop = args[0]
    elif len(args) == 2:
        s_start, s_stop = args
    elif len(args) == 3:
        s_start, s_stop = args[:2]
        s_step = args[2]
    else:
        raise AnnotatorError("range() takes 1 to 3 arguments")
    empty = False  # so far
    if not s_step.is_constant():
        step = 0 # this case signals a variable step
    else:
        step = s_step.const
        if step == 0:
            raise AnnotatorError("range() with step zero")
        if s_start.is_constant() and s_stop.is_constant():
            try:
                if len(xrange(s_start.const, s_stop.const, step)) == 0:
                    empty = True
            except TypeError:   # if one of the .const is a Symbolic
                pass
    if empty:
        s_item = s_ImpossibleValue
    else:
        nonneg = False # so far
        if step > 0 or s_step.nonneg:
            nonneg = s_start.nonneg
        elif step < 0:
            nonneg = s_stop.nonneg or (s_stop.is_constant() and
                                       s_stop.const >= -1)
        s_item = SomeInteger(nonneg=nonneg)
    return getbookkeeper().newlist(s_item, range_step=step)
Beispiel #19
0
 def consider_call_site(descs, args, s_result, op):
     descs[0].getcallfamily()
     descs[0].mergecallfamilies(*descs[1:])
     from rpython.annotator.model import SomeInstance, SomePBC, s_None
     if len(descs) == 1:
         # call to a single class, look at the result annotation
         # in case it was specialized
         if not isinstance(s_result, SomeInstance):
             raise Exception("calling a class didn't return an instance??")
         classdefs = [s_result.classdef]
     else:
         # call to multiple classes: specialization not supported
         classdefs = [desc.getuniqueclassdef() for desc in descs]
         # If some of the classes have an __init__ and others not, then
         # we complain, even though in theory it could work if all the
         # __init__s take no argument.  But it's messy to implement, so
         # let's just say it is not RPython and you have to add an empty
         # __init__ to your base class.
         has_init = False
         for desc in descs:
             s_init = desc.s_read_attribute('__init__')
             has_init |= isinstance(s_init, SomePBC)
         basedesc = ClassDesc.getcommonbase(descs)
         s_init = basedesc.s_read_attribute('__init__')
         parent_has_init = isinstance(s_init, SomePBC)
         if has_init and not parent_has_init:
             raise AnnotatorError(
                 "some subclasses among %r declare __init__(),"
                 " but not the common parent class" % (descs, ))
     # make a PBC of MethodDescs, one for the __init__ of each class
     initdescs = []
     for desc, classdef in zip(descs, classdefs):
         s_init = desc.s_read_attribute('__init__')
         if isinstance(s_init, SomePBC):
             assert len(
                 s_init.descriptions) == 1, ("unexpected dynamic __init__?")
             initfuncdesc, = s_init.descriptions
             if isinstance(initfuncdesc, FunctionDesc):
                 from rpython.annotator.bookkeeper import getbookkeeper
                 initmethdesc = getbookkeeper().getmethoddesc(
                     initfuncdesc, classdef, classdef, '__init__')
                 initdescs.append(initmethdesc)
     # register a call to exactly these __init__ methods
     if initdescs:
         initdescs[0].mergecallfamilies(*initdescs[1:])
         MethodDesc.consider_call_site(initdescs, args, s_None, op)
Beispiel #20
0
    def setattr(self, s_attr, s_value):
        if s_attr.is_constant() and isinstance(s_attr.const, str):
            attr = s_attr.const
            # find the (possibly parent) class where this attr is defined
            clsdef = self.classdef.locate_attribute(attr)
            attrdef = clsdef.attrs[attr]
            attrdef.modified(clsdef)

            # if the attrdef is new, this must fail
            if attrdef.getvalue().contains(s_value):
                return
            # create or update the attribute in clsdef
            clsdef.generalize_attr(attr, s_value)

            if isinstance(s_value, SomeList):
                clsdef.classdesc.maybe_return_immutable_list(attr, s_value)
        else:
            raise AnnotatorError("setattr(instance, variable_attr, value)")
Beispiel #21
0
def transform_varargs(annotator, v_func, v_shape, *data_v):
    callspec = CallSpec.fromshape(v_shape.value, list(data_v))
    v_vararg = callspec.w_stararg
    if callspec.w_stararg:
        s_vararg = annotator.annotation(callspec.w_stararg)
        if not isinstance(s_vararg, SomeTuple):
            raise AnnotatorError(
                "Calls like f(..., *arg) require 'arg' to be a tuple")
        n_items = len(s_vararg.items)
        ops = [op.getitem(v_vararg, const(i)) for i in range(n_items)]
        new_args = callspec.arguments_w + [hlop.result for hlop in ops]
        if callspec.keywords:
            newspec = CallSpec(new_args, callspec.keywords)
            shape, data_v = newspec.flatten()
            call_op = op.call_args(v_func, const(shape), *data_v)
        else:
            call_op = op.simple_call(v_func, *new_args)
        ops.append(call_op)
        return ops
Beispiel #22
0
 def s_get_value(self, classdef, name):
     obj = self.classdict[name]
     if isinstance(obj, Constant):
         value = obj.value
         if isinstance(value, staticmethod):  # special case
             value = value.__get__(42)
             classdef = None  # don't bind
         elif isinstance(value, classmethod):
             raise AnnotatorError("classmethods are not supported")
         s_value = self.bookkeeper.immutablevalue(value)
         if classdef is not None:
             s_value = s_value.bind_callables_under(classdef, name)
     elif isinstance(obj, Desc):
         if classdef is not None:
             obj = obj.bind_under(classdef, name)
         s_value = SomePBC([obj])
     else:
         raise TypeError("classdict should not contain %r" % (obj, ))
     return s_value
Beispiel #23
0
 def parse_arguments(self, args, graph=None):
     defs_s = []
     if graph is None:
         signature = self.signature
         defaults = self.defaults
     else:
         signature = graph.signature
         defaults = graph.defaults
     if defaults:
         for x in defaults:
             if x is NODEFAULT:
                 defs_s.append(None)
             else:
                 defs_s.append(self.bookkeeper.immutablevalue(x))
     try:
         inputcells = args.match_signature(signature, defs_s)
     except ArgErr, e:
         raise AnnotatorError("signature mismatch: %s() %s" %
                              (self.name, e.getmsg()))
    def normalize_args(self, inputs_s):
        """
        Canonicalize argument annotations into the exact parameter
        annotations of a specific specialized graph.

        Note: this method has no return value but mutates its argument instead.
        """
        enforceargs = getattr(self.pyobj, '_annenforceargs_', None)
        signature = getattr(self.pyobj, '_signature_', None)
        if enforceargs and signature:
            raise AnnotatorError(
                "%r: signature and enforceargs cannot both be "
                "used" % (self, ))
        if enforceargs:
            if not callable(enforceargs):
                from rpython.annotator.signature import Sig
                enforceargs = Sig(*enforceargs)
                self.pyobj._annenforceargs_ = enforceargs
            enforceargs(self, inputs_s)  # can modify inputs_s in-place
        if signature:
            enforce_signature_args(self, signature[0],
                                   inputs_s)  # mutates inputs_s
Beispiel #25
0
def constpropagate(func, args_s, s_result):
    """Returns s_result unless all args are constants, in which case the
    func() is called and a constant result is returned (it must be contained
    in s_result).
    """
    args = []
    for s in args_s:
        if not s.is_immutable_constant():
            return s_result
        args.append(s.const)
    try:
        realresult = func(*args)
    except (ValueError, OverflowError):
        # no possible answer for this precise input.  Be conservative
        # and keep the computation non-constant.  Example:
        # unichr(constant-that-doesn't-fit-16-bits) on platforms where
        # the underlying Python has sys.maxunicode == 0xffff.
        return s_result
    s_realresult = immutablevalue(realresult)
    if not s_result.contains(s_realresult):
        raise AnnotatorError("%s%r returned %r, which is not contained in %s" %
                             (func, args, realresult, s_result))
    return s_realresult
Beispiel #26
0
 def add((o, pbc)):
     raise AnnotatorError('add on %r' % pbc)
Beispiel #27
0
 def add((pbc, o)):
     raise AnnotatorError('add on %r' % pbc)
Beispiel #28
0
 def getitem((pbc, o)):
     raise AnnotatorError("getitem on %r" % pbc)
Beispiel #29
0
class __extend__(pairtype(SomePBC, SomeObject)):
    def getitem((pbc, o)):
        raise AnnotatorError("getitem on %r" % pbc)

    def setitem((pbc, o), s_value):
        raise AnnotatorError("setitem on %r" % pbc)
Beispiel #30
0
 def ge((tup1, tup2)):
     raise AnnotatorError("unsupported: (...) >= (...)")