PageRenderTime 61ms CodeModel.GetById 21ms app.highlight 30ms RepoModel.GetById 1ms app.codeStats 0ms

/pypy/annotation/model.py

https://bitbucket.org/pypy/pypy/
Python | 799 lines | 728 code | 52 blank | 19 comment | 63 complexity | a15215416db2f4e531c957be0e545eee MD5 | raw file
  1"""
  2This file defines the 'subset' SomeValue classes.
  3
  4An instance of a SomeValue class stands for a Python object that has some
  5known properties, for example that is known to be a list of non-negative
  6integers.  Each instance can be considered as an object that is only
  7'partially defined'.  Another point of view is that each instance is a
  8generic element in some specific subset of the set of all objects.
  9
 10"""
 11
 12# Old terminology still in use here and there:
 13#    SomeValue means one of the SomeXxx classes in this file.
 14#    Cell is an instance of one of these classes.
 15#
 16# Think about cells as potato-shaped circles in a diagram:
 17#    ______________________________________________________
 18#   / SomeObject()                                         \
 19#  /   ___________________________          ______________  \
 20#  |  / SomeInteger(nonneg=False) \____    / SomeString() \  \
 21#  | /     __________________________  \   |              |  |
 22#  | |    / SomeInteger(nonneg=True) \ |   |      "hello" |  |
 23#  | |    |   0    42       _________/ |   \______________/  |
 24#  | \ -3 \________________/           /                     |
 25#  \  \                     -5   _____/                      /
 26#   \  \________________________/              3.1416       /
 27#    \_____________________________________________________/
 28#
 29
 30
 31from types import BuiltinFunctionType, MethodType, FunctionType
 32import pypy
 33from pypy.tool import descriptor
 34from pypy.tool.pairtype import pair, extendabletype
 35from pypy.rlib.rarithmetic import r_uint, r_ulonglong, base_int
 36from pypy.rlib.rarithmetic import r_singlefloat, r_longfloat
 37import inspect, weakref
 38
 39DEBUG = False    # set to False to disable recording of debugging information
 40
 41class State(object):
 42    # A global attribute :-(  Patch it with 'True' to enable checking of
 43    # the no_nul attribute...
 44    check_str_without_nul = False
 45TLS = State()
 46
 47class SomeObject(object):
 48    """The set of all objects.  Each instance stands
 49    for an arbitrary object about which nothing is known."""
 50    __metaclass__ = extendabletype
 51    knowntype = object
 52    immutable = False
 53
 54    def __eq__(self, other):
 55        return (self.__class__ is other.__class__ and
 56                self.__dict__  == other.__dict__)
 57    def __ne__(self, other):
 58        return not (self == other)
 59    def __repr__(self):
 60        try:
 61            reprdict = TLS.reprdict
 62        except AttributeError:
 63            reprdict = TLS.reprdict = {}
 64        if self in reprdict:
 65            kwds = '...'
 66        else:
 67            reprdict[self] = True
 68            try:
 69                items = self.__dict__.items()
 70                items.sort()
 71                args = []
 72                for k, v in items:
 73                    m = getattr(self, 'fmt_' + k, repr)
 74                    r = m(v)
 75                    if r is not None:
 76                        args.append('%s=%s'%(k, r))
 77                kwds = ', '.join(args)
 78            finally:
 79                del reprdict[self]
 80        return '%s(%s)' % (self.__class__.__name__, kwds)
 81
 82    def fmt_knowntype(self, t):
 83        return t.__name__
 84    
 85    def contains(self, other):
 86        if self == other:
 87            return True
 88        try:
 89            TLS.no_side_effects_in_union += 1
 90        except AttributeError:
 91            TLS.no_side_effects_in_union = 1
 92        try:
 93            try:
 94                return pair(self, other).union() == self
 95            except UnionError:
 96                return False
 97        finally:
 98            TLS.no_side_effects_in_union -= 1
 99
100    def is_constant(self):
101        d = self.__dict__
102        return 'const' in d or 'const_box' in d
103
104    def is_immutable_constant(self):
105        return self.immutable and 'const' in self.__dict__
106
107    # delegate accesses to 'const' to accesses to 'const_box.value',
108    # where const_box is a Constant.  XXX the idea is to eventually
109    # use systematically 'const_box' instead of 'const' for
110    # non-immutable constant annotations
111    class ConstAccessDelegator(object):
112        def __get__(self, obj, cls=None):
113            return obj.const_box.value
114    const = ConstAccessDelegator()
115    del ConstAccessDelegator
116
117    # for debugging, record where each instance comes from
118    # this is disabled if DEBUG is set to False
119    def __new__(cls, *args, **kw):
120        new = super(SomeObject, cls).__new__
121        if new is object.__new__:
122            # Since python 2.6, object.__new__ warns
123            # when parameters are passed
124            self = new(cls)
125        else:
126            self = new(cls, *args, **kw)
127        if DEBUG:
128            try:
129                bookkeeper = pypy.annotation.bookkeeper.getbookkeeper()
130                position_key = bookkeeper.position_key
131            except AttributeError:
132                pass
133            else:
134                bookkeeper._isomeobject_coming_from[self] = position_key, None
135        return self
136
137    def origin(self):
138        bookkeeper = pypy.annotation.bookkeeper.getbookkeeper()
139        if bookkeeper is None:
140            return None
141        return bookkeeper._isomeobject_coming_from.get(self, (None, None))[0]
142    origin = property(origin)
143
144    def caused_by_merge(self):
145        bookkeeper = pypy.annotation.bookkeeper.getbookkeeper()
146        if bookkeeper is None:
147            return None
148        return bookkeeper._isomeobject_coming_from.get(self, (None, None))[1]
149    def set_caused_by_merge(self, nvalue):
150        bookkeeper = pypy.annotation.bookkeeper.getbookkeeper()
151        if bookkeeper is None:
152            return
153        bookkeeper._isomeobject_coming_from[self] = self.origin, nvalue
154    caused_by_merge = property(caused_by_merge, set_caused_by_merge)
155    del set_caused_by_merge
156
157    def can_be_none(self):
158        return True
159        
160    def nonnoneify(self):
161        return self
162
163class SomeFloat(SomeObject):
164    "Stands for a float or an integer."
165    knowntype = float   # if we don't know if it's a float or an int,
166                        # pretend it's a float.
167    immutable = True
168
169    def __eq__(self, other):
170        if (type(self) is SomeFloat and type(other) is SomeFloat and
171            self.is_constant() and other.is_constant()):
172            from pypy.rlib.rfloat import isnan, copysign
173            # NaN unpleasantness.
174            if isnan(self.const) and isnan(other.const):
175                return True
176            # 0.0 vs -0.0 unpleasantness.
177            if not self.const and not other.const:
178                return copysign(1., self.const) == copysign(1., other.const)
179            #
180        return super(SomeFloat, self).__eq__(other)
181
182    def can_be_none(self):
183        return False
184
185class SomeSingleFloat(SomeObject):
186    "Stands for an r_singlefloat."
187    # No operation supported, not even union with a regular float
188    knowntype = r_singlefloat
189    immutable = True
190
191    def can_be_none(self):
192        return False
193
194class SomeLongFloat(SomeObject):
195    "Stands for an r_longfloat."
196    # No operation supported, not even union with a regular float
197    knowntype = r_longfloat
198    immutable = True
199
200    def can_be_none(self):
201        return False
202
203class SomeInteger(SomeFloat):
204    "Stands for an object which is known to be an integer."
205    knowntype = int
206    # size is in multiples of C's sizeof(long)!
207    def __init__(self, nonneg=False, unsigned=None, knowntype=None):
208        assert (knowntype is None or knowntype is int or
209                issubclass(knowntype, base_int))
210        if knowntype is None:
211            if unsigned:
212                knowntype = r_uint
213            else:
214                knowntype = int
215        elif unsigned is not None:
216            raise TypeError('Conflicting specification for SomeInteger')
217        self.knowntype = knowntype
218        unsigned = self.knowntype(-1) > 0
219        self.nonneg = unsigned or nonneg
220        self.unsigned = unsigned  # pypy.rlib.rarithmetic.r_uint
221
222class SomeBool(SomeInteger):
223    "Stands for true or false."
224    knowntype = bool
225    nonneg = True
226    unsigned = False
227    def __init__(self):
228        pass
229
230class SomeStringOrUnicode(SomeObject):
231    immutable = True
232    can_be_None=False
233    no_nul = False  # No NUL character in the string.
234
235    def __init__(self, can_be_None=False, no_nul=False):
236        if can_be_None:
237            self.can_be_None = True
238        if no_nul:
239            self.no_nul = True
240
241    def can_be_none(self):
242        return self.can_be_None
243
244    def __eq__(self, other):
245        if self.__class__ is not other.__class__:
246            return False
247        d1 = self.__dict__
248        d2 = other.__dict__
249        if not TLS.check_str_without_nul:
250            d1 = d1.copy(); d1['no_nul'] = 0   # ignored
251            d2 = d2.copy(); d2['no_nul'] = 0   # ignored
252        return d1 == d2
253
254class SomeString(SomeStringOrUnicode):
255    "Stands for an object which is known to be a string."
256    knowntype = str
257
258    def nonnoneify(self):
259        return SomeString(can_be_None=False, no_nul=self.no_nul)
260
261class SomeUnicodeString(SomeStringOrUnicode):
262    "Stands for an object which is known to be an unicode string"
263    knowntype = unicode
264
265    def nonnoneify(self):
266        return SomeUnicodeString(can_be_None=False, no_nul=self.no_nul)
267
268class SomeChar(SomeString):
269    "Stands for an object known to be a string of length 1."
270    can_be_None = False
271    def __init__(self, no_nul=False):    # no 'can_be_None' argument here
272        if no_nul:
273            self.no_nul = True
274
275class SomeUnicodeCodePoint(SomeUnicodeString):
276    "Stands for an object known to be a unicode codepoint."
277    can_be_None = False
278    def __init__(self, no_nul=False):    # no 'can_be_None' argument here
279        if no_nul:
280            self.no_nul = True
281
282SomeString.basestringclass = SomeString
283SomeString.basecharclass = SomeChar
284SomeUnicodeString.basestringclass = SomeUnicodeString
285SomeUnicodeString.basecharclass = SomeUnicodeCodePoint
286
287class SomeList(SomeObject):
288    "Stands for a homogenous list of any length."
289    knowntype = list
290    def __init__(self, listdef):
291        self.listdef = listdef
292    def __eq__(self, other):
293        if self.__class__ is not other.__class__:
294            return False
295        if not self.listdef.same_as(other.listdef):
296            return False
297        selfdic = self.__dict__.copy()
298        otherdic = other.__dict__.copy()
299        del selfdic['listdef']
300        del otherdic['listdef']
301        return selfdic == otherdic
302
303    def can_be_none(self):
304        return True
305
306class SomeTuple(SomeObject):
307    "Stands for a tuple of known length."
308    knowntype = tuple
309    immutable = True
310    def __init__(self, items):
311        self.items = tuple(items)   # tuple of s_xxx elements
312        for i in items:
313            if not i.is_constant():
314                break
315        else:
316            self.const = tuple([i.const for i in items])
317
318    def can_be_none(self):
319        return False
320
321class SomeDict(SomeObject):
322    "Stands for a dict."
323    knowntype = dict
324    def __init__(self, dictdef):
325        self.dictdef = dictdef
326    def __eq__(self, other):
327        if self.__class__ is not other.__class__:
328            return False
329        if not self.dictdef.same_as(other.dictdef):
330            return False
331        selfdic = self.__dict__.copy()
332        otherdic = other.__dict__.copy()
333        del selfdic['dictdef']
334        del otherdic['dictdef']
335        return selfdic == otherdic
336
337    def can_be_none(self):
338        return True
339
340    def fmt_const(self, const):
341        if len(const) < 20:
342            return repr(const)
343        else:
344            return '{...%s...}'%(len(const),)
345
346
347class SomeIterator(SomeObject):
348    "Stands for an iterator returning objects from a given container."
349    knowntype = type(iter([]))  # arbitrarily chose seqiter as the type
350    def __init__(self, s_container, *variant):
351        self.variant = variant
352        self.s_container = s_container
353
354    def can_be_none(self):
355        return False
356
357class SomeInstance(SomeObject):
358    "Stands for an instance of a (user-defined) class."
359
360    def __init__(self, classdef, can_be_None=False, flags={}):
361        self.classdef = classdef
362        self.knowntype = classdef or object
363        self.can_be_None = can_be_None
364        self.flags = flags
365
366    def fmt_knowntype(self, kt):
367        return None
368    def fmt_classdef(self, cdef):
369        if cdef is None:
370            return 'object'
371        else:
372            return cdef.name
373    def fmt_flags(self, flags):
374        if flags:
375            return repr(flags)
376        else:
377            return None
378
379    def can_be_none(self):
380        return self.can_be_None
381
382    def nonnoneify(self):
383        return SomeInstance(self.classdef, can_be_None=False)
384
385
386class SomePBC(SomeObject):
387    """Stands for a global user instance, built prior to the analysis,
388    or a set of such instances."""
389    immutable = True
390
391    def __init__(self, descriptions, can_be_None=False, subset_of=None):
392        # descriptions is a set of Desc instances
393        descriptions = set(descriptions)
394        self.descriptions = descriptions
395        self.can_be_None = can_be_None
396        self.subset_of = subset_of
397        self.simplify()
398        if self.isNone():
399            self.knowntype = type(None)
400            self.const = None
401        else:
402            knowntype = reduce(commonbase,
403                               [x.knowntype for x in descriptions])
404            if knowntype == type(Exception):
405                knowntype = type
406            if knowntype != object:
407                self.knowntype = knowntype
408            if len(descriptions) == 1 and not can_be_None:
409                # hack for the convenience of direct callers to SomePBC():
410                # only if there is a single object in descriptions
411                desc, = descriptions
412                if desc.pyobj is not None:
413                    self.const = desc.pyobj
414
415    def any_description(self):
416        return iter(self.descriptions).next()
417
418    def getKind(self):
419        "Return the common Desc class of all descriptions in this PBC."
420        kinds = {}
421        for x in self.descriptions:
422            assert type(x).__name__.endswith('Desc')  # avoid import nightmares
423            kinds[x.__class__] = True
424        assert len(kinds) <= 1, (
425            "mixing several kinds of PBCs: %r" % (kinds.keys(),))
426        if not kinds:
427            raise ValueError("no 'kind' on the 'None' PBC")
428        return kinds.keys()[0]
429
430    def simplify(self):
431        if self.descriptions:
432            # We check that the set only contains a single kind of Desc instance
433            kind = self.getKind()
434            # then we remove unnecessary entries in self.descriptions:
435            # some MethodDescs can be 'shadowed' by others
436            if len(self.descriptions) > 1:
437                kind.simplify_desc_set(self.descriptions)
438        else:
439            assert self.can_be_None, "use s_ImpossibleValue"
440
441    def isNone(self):
442        return len(self.descriptions) == 0
443
444    def can_be_none(self):
445        return self.can_be_None
446
447    def nonnoneify(self):
448        if self.isNone():
449            return s_ImpossibleValue
450        else:
451            return SomePBC(self.descriptions, can_be_None=False)
452
453    def fmt_descriptions(self, pbis):
454        if hasattr(self, 'const'):
455            return None
456        else:
457            return '{...%s...}'%(len(pbis),)
458
459    def fmt_knowntype(self, kt):
460        if self.is_constant():
461            return None
462        else:
463            return kt.__name__
464
465class SomeGenericCallable(SomeObject):
466    """ Stands for external callable with known signature
467    """
468    def __init__(self, args, result):
469        self.args_s = args
470        self.s_result = result
471
472    def can_be_None(self):
473        return True
474
475class SomeBuiltin(SomeObject):
476    "Stands for a built-in function or method with special-cased analysis."
477    knowntype = BuiltinFunctionType  # == BuiltinMethodType
478    immutable = True
479
480    def __init__(self, analyser, s_self=None, methodname=None):
481        if isinstance(analyser, MethodType):
482            analyser = descriptor.InstanceMethod(
483                analyser.im_func,
484                analyser.im_self,
485                analyser.im_class)
486        self.analyser = analyser
487        self.s_self = s_self
488        self.methodname = methodname
489
490    def can_be_none(self):
491        return False
492
493class SomeBuiltinMethod(SomeBuiltin):
494    """ Stands for a built-in method which has got special meaning
495    """
496    knowntype = MethodType
497
498class SomeExternalObject(SomeObject):
499    """Stands for an object of 'external' type.  External types have a Repr
500    controlled by pypy.rpython.extregistry."""
501
502    def __init__(self, knowntype):
503        self.knowntype = knowntype
504
505    def can_be_none(self):
506        return True
507
508class SomeImpossibleValue(SomeObject):
509    """The empty set.  Instances are placeholders for objects that
510    will never show up at run-time, e.g. elements of an empty list."""
511    immutable = True
512    annotationcolor = (160,160,160)
513
514    def can_be_none(self):
515        return False
516
517
518s_None = SomePBC([], can_be_None=True)
519s_Bool = SomeBool()
520s_ImpossibleValue = SomeImpossibleValue()
521s_Str0 = SomeString(no_nul=True)
522
523# ____________________________________________________________
524# weakrefs
525
526class SomeWeakRef(SomeObject):
527    knowntype = weakref.ReferenceType
528    immutable = True
529    def __init__(self, classdef):
530        # 'classdef' is None for known-to-be-dead weakrefs.
531        self.classdef = classdef
532
533# ____________________________________________________________
534# memory addresses
535
536from pypy.rpython.lltypesystem import llmemory
537
538class SomeAddress(SomeObject):
539    immutable = True
540
541    def can_be_none(self):
542        return False
543
544    def is_null_address(self):
545        return self.is_immutable_constant() and not self.const
546
547# The following class is used to annotate the intermediate value that
548# appears in expressions of the form:
549# addr.signed[offset] and addr.signed[offset] = value
550
551class SomeTypedAddressAccess(SomeObject):
552    def __init__(self, type):
553        self.type = type
554
555    def can_be_none(self):
556        return False
557
558#____________________________________________________________
559# annotation of low-level types
560
561from pypy.rpython.lltypesystem import lltype
562from pypy.rpython.ootypesystem import ootype
563
564class SomePtr(SomeObject):
565    knowntype = lltype._ptr
566    immutable = True
567    def __init__(self, ll_ptrtype):
568        assert isinstance(ll_ptrtype, lltype.Ptr)
569        self.ll_ptrtype = ll_ptrtype
570
571    def can_be_none(self):
572        return False
573
574class SomeInteriorPtr(SomePtr):
575    def __init__(self, ll_ptrtype):
576        assert isinstance(ll_ptrtype, lltype.InteriorPtr)
577        self.ll_ptrtype = ll_ptrtype
578
579class SomeLLADTMeth(SomeObject):
580    immutable = True
581    def __init__(self, ll_ptrtype, func):
582        self.ll_ptrtype = ll_ptrtype
583        self.func = func 
584
585    def can_be_none(self):
586        return False
587
588class SomeOOObject(SomeObject):
589    def __init__(self):
590        self.ootype = ootype.Object
591
592class SomeOOClass(SomeObject):
593    def __init__(self, ootype):
594        self.ootype = ootype
595
596class SomeOOInstance(SomeObject):
597    def __init__(self, ootype, can_be_None=False):
598        self.ootype = ootype
599        self.can_be_None = can_be_None
600
601class SomeOOBoundMeth(SomeObject):
602    immutable = True
603    def __init__(self, ootype, name):
604        self.ootype = ootype
605        self.name = name
606
607class SomeOOStaticMeth(SomeObject):
608    immutable = True
609    def __init__(self, method):
610        self.method = method
611
612annotation_to_ll_map = [
613    (SomeSingleFloat(), lltype.SingleFloat),
614    (s_None, lltype.Void),   # also matches SomeImpossibleValue()
615    (s_Bool, lltype.Bool),
616    (SomeFloat(), lltype.Float),
617    (SomeLongFloat(), lltype.LongFloat),
618    (SomeChar(), lltype.Char),
619    (SomeUnicodeCodePoint(), lltype.UniChar),
620    (SomeAddress(), llmemory.Address),
621]
622
623def annotation_to_lltype(s_val, info=None):
624    if isinstance(s_val, SomeOOInstance):
625        return s_val.ootype
626    if isinstance(s_val, SomeOOStaticMeth):
627        return s_val.method
628    if isinstance(s_val, SomeOOClass):
629        return ootype.Class
630    if isinstance(s_val, SomeOOObject):
631        return s_val.ootype
632    if isinstance(s_val, SomeInteriorPtr):
633        p = s_val.ll_ptrtype
634        if 0 in p.offsets:
635            assert list(p.offsets).count(0) == 1
636            return lltype.Ptr(lltype.Ptr(p.PARENTTYPE)._interior_ptr_type_with_index(p.TO))
637        else:
638            return lltype.Ptr(p.PARENTTYPE)
639    if isinstance(s_val, SomePtr):
640        return s_val.ll_ptrtype
641    if type(s_val) is SomeInteger:
642        return lltype.build_number(None, s_val.knowntype)
643
644    for witness, T in annotation_to_ll_map:
645        if witness.contains(s_val):
646            return T
647    if info is None:
648        info = ''
649    else:
650        info = '%s: ' % info
651    raise ValueError("%sshould return a low-level type,\ngot instead %r" % (
652        info, s_val))
653
654ll_to_annotation_map = dict([(ll, ann) for ann, ll in annotation_to_ll_map])
655
656def lltype_to_annotation(T):
657    try:
658        s = ll_to_annotation_map.get(T)
659    except TypeError:
660        s = None    # unhashable T, e.g. a Ptr(GcForwardReference())
661    if s is None:
662        if isinstance(T, lltype.Typedef):
663            return lltype_to_annotation(T.OF)
664        if isinstance(T, lltype.Number):
665            return SomeInteger(knowntype=T._type)
666        if isinstance(T, (ootype.Instance, ootype.BuiltinType)):
667            return SomeOOInstance(T)
668        elif isinstance(T, ootype.StaticMethod):
669            return SomeOOStaticMeth(T)
670        elif T == ootype.Class:
671            return SomeOOClass(ootype.ROOT)
672        elif T == ootype.Object:
673            return SomeOOObject()
674        elif isinstance(T, lltype.InteriorPtr):
675            return SomeInteriorPtr(T)
676        else:
677            return SomePtr(T)
678    else:
679        return s
680
681def ll_to_annotation(v):
682    if v is None:
683        # i think we can only get here in the case of void-returning
684        # functions
685        return s_None
686    if isinstance(v, lltype._interior_ptr):
687        ob = v._parent
688        if ob is None:
689            raise RuntimeError
690        T = lltype.InteriorPtr(lltype.typeOf(ob), v._T, v._offsets)
691        return SomeInteriorPtr(T)
692    return lltype_to_annotation(lltype.typeOf(v))
693    
694# ____________________________________________________________
695
696class UnionError(Exception):
697    """Signals an suspicious attempt at taking the union of
698    deeply incompatible SomeXxx instances."""
699
700def unionof(*somevalues):
701    "The most precise SomeValue instance that contains all the values."
702    try:
703        s1, s2 = somevalues
704    except ValueError:
705        s1 = s_ImpossibleValue
706        for s2 in somevalues:
707            if s1 != s2:
708                s1 = pair(s1, s2).union()
709    else:
710        # this is just a performance shortcut
711        if s1 != s2:
712            s1 = pair(s1, s2).union()
713    if DEBUG:
714        if s1.caused_by_merge is None and len(somevalues) > 1:
715            s1.caused_by_merge = somevalues
716    return s1
717
718def isdegenerated(s_value):
719    return s_value.__class__ is SomeObject and s_value.knowntype is not type
720
721# make knowntypedata dictionary
722
723def add_knowntypedata(ktd, truth, vars, s_obj):
724    for v in vars:
725        ktd[(truth, v)] = s_obj
726
727def merge_knowntypedata(ktd1, ktd2):
728    r = {}
729    for truth_v in ktd1:
730        if truth_v in ktd2:
731            r[truth_v] = unionof(ktd1[truth_v], ktd2[truth_v])
732    return r
733
734def not_const(s_obj):
735    if s_obj.is_constant():
736        new_s_obj = SomeObject.__new__(s_obj.__class__)
737        dic = new_s_obj.__dict__ = s_obj.__dict__.copy()
738        if 'const' in dic:
739            del new_s_obj.const
740        else:
741            del new_s_obj.const_box
742        s_obj = new_s_obj
743    return s_obj
744
745# ____________________________________________________________
746# internal
747
748def commonbase(cls1, cls2):   # XXX single inheritance only  XXX hum
749    l1 = inspect.getmro(cls1)
750    l2 = inspect.getmro(cls2) 
751    if l1[-1] != object: 
752        l1 = l1 + (object,) 
753    if l2[-1] != object: 
754        l2 = l2 + (object,) 
755    for x in l1: 
756        if x in l2: 
757            return x 
758    assert 0, "couldn't get to commonbase of %r and %r" % (cls1, cls2)
759
760def missing_operation(cls, name):
761    def default_op(*args):
762        if args and isinstance(args[0], tuple):
763            flattened = tuple(args[0]) + args[1:]
764        else:
765            flattened = args
766        for arg in flattened:
767            if arg.__class__ is SomeObject and arg.knowntype is not type:
768                return  SomeObject()
769        bookkeeper = pypy.annotation.bookkeeper.getbookkeeper()
770        bookkeeper.warning("no precise annotation supplied for %s%r" % (name, args))
771        return s_ImpossibleValue
772    setattr(cls, name, default_op)
773
774class HarmlesslyBlocked(Exception):
775    """Raised by the unaryop/binaryop to signal a harmless kind of
776    BlockedInference: the current block is blocked, but not in a way
777    that gives 'Blocked block' errors at the end of annotation."""
778
779
780def read_can_only_throw(opimpl, *args):
781    can_only_throw = getattr(opimpl, "can_only_throw", None)
782    if can_only_throw is None or isinstance(can_only_throw, list):
783        return can_only_throw
784    return can_only_throw(*args)
785
786#
787# safety check that no-one is trying to make annotation and translation
788# faster by providing the -O option to Python.
789try:
790    assert False
791except AssertionError:
792    pass   # fine
793else:
794    raise RuntimeError("The annotator relies on 'assert' statements from the\n"
795                     "\tannotated program: you cannot run it with 'python -O'.")
796
797# this has the side-effect of registering the unary and binary operations
798from pypy.annotation.unaryop  import UNARY_OPERATIONS
799from pypy.annotation.binaryop import BINARY_OPERATIONS