def method_matches(self, s_s, s_pos): assert model.SomeString().contains(s_s) assert model.SomeInteger(nonneg=True).contains(s_pos) bk = getbookkeeper() init_pbc = bk.immutablevalue(Match.__init__) bk.emulate_pbc_call((self, "match_init"), init_pbc, [ model.SomeInstance(bk.getuniqueclassdef(Match)), model.SomeInteger(nonneg=True), model.SomeInteger(nonneg=True) ]) init_pbc = bk.immutablevalue(rsre_core.StrMatchContext.__init__) bk.emulate_pbc_call((self, "str_match_context_init"), init_pbc, [ model.SomeInstance(bk.getuniqueclassdef(rsre_core.StrMatchContext)), bk.newlist(model.SomeInteger(nonneg=True)), model.SomeString(), model.SomeInteger(nonneg=True), model.SomeInteger(nonneg=True), model.SomeInteger(nonneg=True), ]) match_context_pbc = bk.immutablevalue(rsre_core.match_context) bk.emulate_pbc_call((self, "match_context"), match_context_pbc, [ model.SomeInstance(bk.getuniqueclassdef(rsre_core.StrMatchContext)), ]) return model.SomeInstance(getbookkeeper().getuniqueclassdef(Match), can_be_None=True)
def simple_call(bltn, *args): if bltn.s_self is not None: return bltn.analyser(bltn.s_self, *args) else: if bltn.methodname: getbookkeeper().count(bltn.methodname.replace('.', '_'), *args) return bltn.analyser(*args)
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)
def method_split(str, patt, max=-1): getbookkeeper().count("str_split", str, patt) if max == -1 and patt.is_constant() and patt.const == "\0": no_nul = True else: no_nul = str.no_nul s_item = str.basestringclass(no_nul=no_nul) return getbookkeeper().newlist(s_item)
def getitem((tup1, int2)): if int2.is_immutable_constant(): try: return tup1.items[int2.const] except IndexError: return s_ImpossibleValue else: getbookkeeper().count("tuple_random_getitem", tup1) return unionof(*tup1.items)
def method_join(str, s_list): if s_None.contains(s_list): return SomeImpossibleValue() getbookkeeper().count("str_join", str) s_item = s_list.listdef.read_item() if s_None.contains(s_item): if isinstance(str, SomeUnicodeString): return immutablevalue(u"") return immutablevalue("") no_nul = str.no_nul and s_item.no_nul return str.basestringclass(no_nul=no_nul)
def compute_result_annotation(self, s_eq_func=None, s_hash_func=None): assert s_eq_func is None or s_eq_func.is_constant() assert s_hash_func is None or s_hash_func.is_constant() if s_eq_func is None and s_hash_func is None: dictdef = getbookkeeper().getdictdef() else: dictdef = getbookkeeper().getdictdef(is_r_dict=True) dictdef.dictkey.update_rdict_annotations(s_eq_func, s_hash_func) return SomeOrderedDict(getbookkeeper(), dictdef,)
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
def setslice(self, s_start, s_stop, s_iterable): check_negative_slice(s_start, s_stop) if not isinstance(s_iterable, SomeList): raise Exception("list[start:stop] = x: x must be a list") self.listdef.mutate() self.listdef.agree(getbookkeeper(), s_iterable.listdef) self.listdef.resize()
def method_extend(self, s_iterable): self.listdef.resize() if isinstance(s_iterable, SomeList): # unify the two lists self.listdef.agree(getbookkeeper(), s_iterable.listdef) else: s_iter = s_iterable.iter() self.method_append(s_iter.next())
def _true_getattr(self, attr): if attr == '__class__': return self.classdef.read_attr__class__() attrdef = self.classdef.find_attribute(attr) position = getbookkeeper().position_key attrdef.read_locations[position] = True s_result = attrdef.getvalue() # hack: if s_result is a set of methods, discard the ones # that can't possibly apply to an instance of self.classdef. # XXX do it more nicely if isinstance(s_result, SomePBC): s_result = self.classdef.lookup_filter(s_result, attr, self.flags) elif isinstance(s_result, SomeImpossibleValue): self.classdef.check_missing_attribute_update(attr) # blocking is harmless if the attribute is explicitly listed # in the class or a parent class. for basedef in self.classdef.getmro(): if basedef.classdesc.all_enforced_attrs is not None: if attr in basedef.classdesc.all_enforced_attrs: raise HarmlesslyBlocked("get enforced attr") elif isinstance(s_result, SomeList): s_result = self.classdef.classdesc.maybe_return_immutable_list( attr, s_result) return s_result
def getbookkeeper(self): if self.bookkeeper is None: from rpython.annotator.bookkeeper import getbookkeeper return getbookkeeper() else: return self.bookkeeper
def our_issubclass(cls1, cls2): """ we're going to try to be less silly in the face of old-style classes""" from rpython.annotator.classdef import ClassDef if cls2 is object: return True def classify(cls): if isinstance(cls, ClassDef): return 'def' if cls.__module__ == '__builtin__': return 'builtin' else: return 'cls' kind1 = classify(cls1) kind2 = classify(cls2) if kind1 != 'def' and kind2 != 'def': return issubclass(cls1, cls2) if kind1 == 'builtin' and kind2 == 'def': return False elif kind1 == 'def' and kind2 == 'builtin': return issubclass(object, cls2) else: bk = getbookkeeper() def toclassdef(kind, cls): if kind != 'def': return bk.getuniqueclassdef(cls) else: return cls return toclassdef(kind1, cls1).issubclass(toclassdef(kind2, cls2))
def compute_result_annotation(self, s_d, s_i): from rpython.annotator.model import SomeTuple, SomeInteger from rpython.annotator.bookkeeper import getbookkeeper position = getbookkeeper().position_key s_key = s_d.dictdef.read_key(position) s_value = s_d.dictdef.read_value(position) return SomeTuple([s_key, s_value])
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)
def method_split(self, patt, max=-1): if max == -1 and patt.is_constant() and patt.const == "\0": no_nul = True else: no_nul = self.no_nul s_item = self.basestringclass(no_nul=no_nul) return getbookkeeper().newlist(s_item)
def len(self): from rpython.annotator.bookkeeper import getbookkeeper length = self.ll_ptrtype._example()._fixedlength() if length is None: return SomeObject.len(self) else: return getbookkeeper().immutablevalue(length)
def getattr(self, s_attr): assert s_attr.is_constant() if s_attr.const == '__name__': from rpython.annotator.description import ClassDesc if self.getKind() is ClassDesc: return SomeString() bookkeeper = getbookkeeper() return bookkeeper.pbc_getattr(self, s_attr)
def type(self, *moreargs): if moreargs: raise Exception('type() called with more than one argument') r = SomeType() bk = getbookkeeper() op = bk._find_current_op(opname="type", arity=1, pos=0, s_type=self) r.is_type_of = [op.args[0]] return r
def issubtype(self, s_cls): if hasattr(self, 'is_type_of'): vars = self.is_type_of annotator = getbookkeeper().annotator return builtin.builtin_isinstance(annotator.binding(vars[0]), s_cls, vars) if self.is_constant() and s_cls.is_constant(): return immutablevalue(issubclass(self.const, s_cls.const)) return s_Bool
def robjmodel_r_dict(s_eqfn, s_hashfn, s_force_non_null=None): if s_force_non_null is None: force_non_null = False else: assert s_force_non_null.is_constant() force_non_null = s_force_non_null.const dictdef = getbookkeeper().getdictdef(is_r_dict=True, force_non_null=force_non_null) dictdef.dictkey.update_rdict_annotations(s_eqfn, s_hashfn) return SomeDict(dictdef)
def method_split(self, patt, max=-1): # special-case for .split( '\x00') or .split(u'\x00') if max == -1 and patt.is_constant() and ( len(patt.const) == 1 and ord(patt.const) == 0): no_nul = True else: no_nul = self.no_nul s_item = self.basestringclass(no_nul=no_nul) return getbookkeeper().newlist(s_item)
def next(self): position = getbookkeeper().position_key if s_None.contains(self.s_container): return s_ImpossibleValue # so far if self.variant == ("enumerate",): s_item = self.s_container.getanyitem(position) return SomeTuple((SomeInteger(nonneg=True), s_item)) variant = self.variant if variant == ("reversed",): variant = () return self.s_container.getanyitem(position, *variant)
def op_contains(self, s_element): if s_element.is_constant() and s_element.const == "\0": r = SomeBool() bk = getbookkeeper() op = bk._find_current_op(opname="contains", arity=2, pos=0, s_type=self) knowntypedata = {} add_knowntypedata(knowntypedata, False, [op.args[0]], self.nonnulify()) r.set_knowntypedata(knowntypedata) return r else: return SomeObject.op_contains(self, s_element)
def method_join(self, s_list): if s_None.contains(s_list): return SomeImpossibleValue() position = getbookkeeper().position_key s_item = s_list.listdef.read_item(position) if s_None.contains(s_item): if isinstance(self, SomeUnicodeString): return immutablevalue(u"") return immutablevalue("") no_nul = self.no_nul and s_item.no_nul return self.basestringclass(no_nul=no_nul)
def builtin_isinstance(s_obj, s_type, variables=None): r = SomeBool() if s_type.is_constant(): typ = s_type.const if issubclass(typ, rpython.rlib.rarithmetic.base_int): try: r.const = issubclass(s_obj.knowntype, typ) except TypeError: # s_obj.knowntype is not a Python type at all r.const = False else: if typ == long: getbookkeeper().warning("isinstance(., long) is not RPython") 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 bk = getbookkeeper() if variables is None: op = bk._find_current_op("simple_call", 3) assert op.args[0] == Constant(isinstance) variables = [op.args[1]] for variable in variables: assert bk.annotator.binding(variable) == s_obj knowntypedata = {} if not hasattr(typ, '_freeze_') and isinstance(s_type, SomePBC): add_knowntypedata(knowntypedata, True, variables, bk.valueoftype(typ)) r.set_knowntypedata(knowntypedata) return r
def mod((s_string, s_tuple)): 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 NotImplementedError( "string formatting mixing strings and unicode not supported") getbookkeeper().count('strformat', s_string, s_tuple) 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)
def hint(self, *args_s): hints = args_s[-1].const if 'maxlength' in hints: # only for iteration over lists or dicts or strs at the moment, # not over an iterator object (because it has no known length) s_iterable = args_s[0] if isinstance(s_iterable, (SomeList, SomeDict, SomeString)): self = SomeList(self.listdef) # create a fresh copy self.listdef.resize() self.listdef.listitem.hint_maxlength = True elif 'fence' in hints: self = self.listdef.offspring(getbookkeeper()) return self
def modified(self, classdef='?'): self.readonly = False if not self.attr_allowed: from rpython.annotator.bookkeeper import getbookkeeper bk = getbookkeeper() classdesc = classdef.classdesc locations = bk.getattr_locations(classdesc, self.name) raise NoSuchAttrError( "Attribute %r on %r should be read-only.\n" % (self.name, classdef) + "This error can be caused by another 'getattr' that promoted\n" "the attribute here; the list of read locations is:\n" + '\n'.join([str(loc[0]) for loc in locations]))
def robjmodel_instantiate(s_clspbc): 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)
def method_items(self): return getbookkeeper().newlist(self.getanyitem('items'))
def bool(self): if self.is_immutable_constant(): return getbookkeeper().immutablevalue(bool(self.const)) return s_Bool
def mul((int1, lst2)): bk = getbookkeeper() return lst2.listdef.offspring(bk)
def mul((lst1, int2)): bk = getbookkeeper() return lst1.listdef.offspring(bk)
def add((lst1, lst2)): bk = getbookkeeper() return lst1.listdef.offspring(bk, lst2.listdef)
def method_rsplit(self, patt, max=-1): s_item = self.basestringclass(no_nul=self.no_nul) return getbookkeeper().newlist(s_item)
def method_getitem_with_hash(self, s_key, s_hash): # XXX: copy of binaryop.getitem_SomeDict self.dictdef.generalize_key(s_key) position = getbookkeeper().position_key return self.dictdef.read_value(position)
def method_contains_with_hash(self, s_key, s_hash): position = getbookkeeper().position_key return dict_contains(self, s_key, position)
def method_pop(self, s_key, s_dfl=None): self.dictdef.generalize_key(s_key) if s_dfl is not None: self.dictdef.generalize_value(s_dfl) position = getbookkeeper().position_key return self.dictdef.read_value(position)
def len(self): position = getbookkeeper().position_key if self._is_empty(position): return immutablevalue(0) return SomeObject.len(self)
def method_items(self): bk = getbookkeeper() return bk.newlist(self.getanyitem(bk.position_key, variant='items'))
def method_keys(self): return getbookkeeper().newlist(self.dictdef.read_key())
def method_values(self): bk = getbookkeeper() return bk.newlist(self.dictdef.read_value(bk.position_key))
def method_splitlines(self, s_keep_newlines=None): s_list = getbookkeeper().newlist(self.basestringclass()) # Force the list to be resizable because ll_splitlines doesn't # preallocate the list. s_list.listdef.listitem.resize() return s_list
def eq((lst1, lst2)): lst1.listdef.agree(getbookkeeper(), lst2.listdef) return s_Bool
def getslice(self, s_start, s_stop): bk = getbookkeeper() check_negative_slice(s_start, s_stop) return self.listdef.offspring(bk)
def getitem_idx((lst1, int2)): position = getbookkeeper().position_key return lst1.listdef.read_item(position)
def len(self): position = getbookkeeper().position_key s_item = self.listdef.read_item(position) if isinstance(s_item, SomeImpossibleValue): return immutablevalue(0) return SomeObject.len(self)
def delattr(self, s_attr): if self.__class__ != SomeObject or self.knowntype != object: getbookkeeper().warning( ("delattr on potentally non-SomeObjects is not RPythonic: delattr(%r,%r)" % (self, s_attr)))
def builtin_list(s_iterable): if isinstance(s_iterable, SomeList): return s_iterable.listdef.offspring() s_iter = s_iterable.iter() return getbookkeeper().newlist(s_iter.next())
def call(self, args): bookkeeper = getbookkeeper() return bookkeeper.pbc_call(self, args)
def builtin_zip(s_iterable1, s_iterable2): # xxx not actually implemented s_iter1 = s_iterable1.iter() s_iter2 = s_iterable2.iter() s_tup = SomeTuple((s_iter1.next(),s_iter2.next())) return getbookkeeper().newlist(s_tup)
def robjmodel_r_ordereddict(s_eqfn, s_hashfn): dictdef = getbookkeeper().getdictdef(is_r_dict=True) dictdef.dictkey.update_rdict_annotations(s_eqfn, s_hashfn) return SomeOrderedDict(dictdef)
def analyze(): return SomeOrderedDict(getbookkeeper().getdictdef())
def compute_result_annotation(self, s_value): assert s_value.is_constant() from rpython.annotator.bookkeeper import getbookkeeper bk = getbookkeeper() return bk.immutablevalue(VoidMarker(s_value.const))
def method_pop(self, s_index=None): position = getbookkeeper().position_key self.listdef.resize() return self.listdef.read_item(position)
def method_values(self): return getbookkeeper().newlist(self.dictdef.read_value())
def method_popitem(self): position = getbookkeeper().position_key return self.getanyitem(position, variant='items')
def method_get(self, key, dfl): position = getbookkeeper().position_key self.dictdef.generalize_key(key) self.dictdef.generalize_value(dfl) return self.dictdef.read_value(position)