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 _compute_annotation(t, bookkeeper=None): from rpython.rtyper.lltypesystem import lltype from rpython.rtyper.llannotation import lltype_to_annotation if isinstance(t, SomeObject): return t elif isinstance(t, lltype.LowLevelType): return lltype_to_annotation(t) elif isinstance(t, list): assert len(t) == 1, "We do not support type joining in list" listdef = ListDef(bookkeeper, annotation(t[0]), mutated=True, resized=True) return SomeList(listdef) elif isinstance(t, tuple): return SomeTuple(tuple([annotation(i) for i in t])) elif isinstance(t, dict): assert len(t) == 1, "We do not support type joining in dict" result = SomeDict( DictDef(bookkeeper, annotation(t.keys()[0]), annotation(t.values()[0]))) return result elif type(t) is types.NoneType: return s_None elif extregistry.is_registered(t): entry = extregistry.lookup(t) entry.bookkeeper = bookkeeper return entry.compute_result_annotation() else: return annotationoftype(t, bookkeeper)
def union((tup1, tup2)): if len(tup1.items) != len(tup2.items): raise UnionError(tup1, tup2, "RPython cannot unify tuples of " "different length: %d versus %d" % \ (len(tup1.items), len(tup2.items))) else: unions = [unionof(x, y) for x, y in zip(tup1.items, tup2.items)] return SomeTuple(items=unions)
def next(self): if s_None.contains(self.s_container): return s_ImpossibleValue # so far if self.variant == ("enumerate", ): s_item = self.s_container.getanyitem() return SomeTuple((SomeInteger(nonneg=True), s_item)) variant = self.variant if variant == ("reversed", ): variant = () return self.s_container.getanyitem(*variant)
def next(self): position = getbookkeeper().position_key if s_None.contains(self.s_container): return s_ImpossibleValue # so far if self.variant and self.variant[0] == "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 getanyitem(self, position, variant='keys'): if variant == 'keys': return self.dictdef.read_key(position) elif variant == 'values': return self.dictdef.read_value(position) elif variant == 'items' or variant == 'items_with_hash': s_key = self.dictdef.read_key(position) s_value = self.dictdef.read_value(position) if (isinstance(s_key, SomeImpossibleValue) or isinstance(s_value, SomeImpossibleValue)): return s_ImpossibleValue elif variant == 'items': return SomeTuple((s_key, s_value)) elif variant == 'items_with_hash': return SomeTuple((s_key, s_value, s_Int)) elif variant == 'keys_with_hash': s_key = self.dictdef.read_key(position) if isinstance(s_key, SomeImpossibleValue): return s_ImpossibleValue return SomeTuple((s_key, s_Int)) raise ValueError(variant)
def getanyitem(self, variant='keys'): if variant == 'keys': return self.dictdef.read_key() elif variant == 'values': return self.dictdef.read_value() elif variant == 'items': s_key = self.dictdef.read_key() s_value = self.dictdef.read_value() if (isinstance(s_key, SomeImpossibleValue) or isinstance(s_value, SomeImpossibleValue)): return s_ImpossibleValue else: return SomeTuple((s_key, s_value)) else: raise ValueError
def test_ll_get_dict_item(): """ Tests the low-level implementation of get_dict_item. """ from rpython.annotator.annrpython import RPythonAnnotator from rpython.annotator.model import SomeTuple, SomeInteger, SomeString from rpython.rtyper.rtyper import RPythonTyper from rpython.rtyper.rmodel import inputconst from rpython.rtyper.annlowlevel import llstr, hlstr from rpython.rtyper.lltypesystem import lltype, rffi from rpython.rtyper.lltypesystem import rordereddict, rstr dummykeyobj = None dummyvalueobj = None def _get_str_dict(): # STR -> lltype.Signed DICT = rordereddict.get_ll_dict( lltype.Ptr(rstr.STR), lltype.Signed, ll_fasthash_function=rstr.LLHelpers.ll_strhash, ll_hash_function=rstr.LLHelpers.ll_strhash, ll_eq_function=rstr.LLHelpers.ll_streq, dummykeyobj=dummykeyobj, dummyvalueobj=dummyvalueobj) return DICT s_tuple = SomeTuple([SomeString(), SomeInteger()]) DICT = _get_str_dict() ll_d = rordereddict.ll_newdict(DICT) a = RPythonAnnotator() rtyper = RPythonTyper(a) a.translator.rtyper = rtyper r_tuple = rtyper.getrepr(s_tuple) cTUPLE = inputconst(lltype.Void, r_tuple.lowleveltype) s_tuple = rtyper.annotation(cTUPLE) rtyper.call_all_setups() for i in range(20): rordereddict.ll_dict_setitem(ll_d, llstr(str(i)), i) for i in range(20): element = ll_get_dict_item(s_tuple.const, ll_d, i) assert (str(i), i) == (hlstr(element.item0), element.item1)
def no_more_blocks_to_annotate(pol, annotator): bk = annotator.bookkeeper # hint to all pending specializers that we are done for callback in bk.pending_specializations: callback() del bk.pending_specializations[:] if annotator.added_blocks is not None: all_blocks = annotator.added_blocks else: all_blocks = annotator.annotated for block in list(all_blocks): for i, instr in enumerate(block.operations): if not isinstance(instr, (op.simple_call, op.call_args)): continue v_func = instr.args[0] s_func = annotator.annotation(v_func) if not hasattr(s_func, 'needs_sandboxing'): continue key = ('sandboxing', s_func.const) if key not in bk.emulated_pbc_calls: params_s = s_func.args_s s_result = s_func.s_result from rpython.translator.sandbox.rsandbox import make_sandbox_trampoline sandbox_trampoline = make_sandbox_trampoline( s_func.name, params_s, s_result) sandbox_trampoline._signature_ = [ SomeTuple(items=params_s) ], s_result bk.emulate_pbc_call(key, bk.immutablevalue(sandbox_trampoline), params_s) else: s_trampoline = bk.emulated_pbc_calls[key][0] sandbox_trampoline = s_trampoline.const new = instr.replace( {instr.args[0]: Constant(sandbox_trampoline)}) block.operations[i] = new
def mod((s_string, s_arg)): assert not isinstance(s_arg, SomeTuple) return pair(s_string, SomeTuple([s_arg])).mod()
def divmod((obj1, obj2)): return SomeTuple([pair(obj1, obj2).div(), pair(obj1, obj2).mod()])
def getslice(self, s_start, s_stop): assert s_start.is_immutable_constant( ), "tuple slicing: needs constants" assert s_stop.is_immutable_constant(), "tuple slicing: needs constants" items = self.items[s_start.const:s_stop.const] return SomeTuple(items)
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 consider(self, annotator): return SomeTuple(items=[annotator.annotation(arg) for arg in self.args])
def newtuple(self, items_s): return SomeTuple(items_s)
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
def add((tup1, tup2)): return SomeTuple(items=tup1.items + tup2.items)
def compute_result_annotation(self, s_d, s_i): from rpython.annotator.model import SomeTuple, SomeInteger s_key = s_d.dictdef.read_key() s_value = s_d.dictdef.read_value() return SomeTuple([s_key, s_value])