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 mod((str, s_tuple)): for s_item in s_tuple.items: if isinstance(s_item, (SomeUnicodeCodePoint, SomeUnicodeString)): raise NotImplementedError( "string formatting mixing strings and unicode not supported") getbookkeeper().count('strformat', str, s_tuple) return SomeString()
def method_join(str, s_list): getbookkeeper().count("str_join", str) s_item = s_list.listdef.read_item() if isinstance(s_item, SomeImpossibleValue): if isinstance(str, SomeUnicodeString): return immutablevalue(u"") return immutablevalue("") return str.basestringclass()
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 isinstance(s_item, SomeImpossibleValue): 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 builtin_isinstance(s_obj, s_type, variables=None): r = SomeBool() if s_type.is_constant(): typ = s_type.const if issubclass(typ, pypy.rlib.rarithmetic.base_int): r.const = issubclass(s_obj.knowntype, typ) else: if typ == long: getbookkeeper().warning("isinstance(., long) is not RPython") if s_obj.is_constant(): r.const = isinstance(s_obj.const, long) else: if type(s_obj) is not SomeObject: # only SomeObjects could be longs # type(s_obj) < SomeObject -> SomeBool(False) # type(s_obj) == SomeObject -> SomeBool() 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 # XXX HACK HACK HACK # XXX HACK HACK HACK # XXX HACK HACK HACK bk = getbookkeeper() if variables is None: fn, block, i = bk.position_key op = block.operations[i] assert op.opname == "simple_call" assert len(op.args) == 3 assert op.args[0] == Constant(isinstance) variables = [op.args[1]] for variable in variables: assert bk.annotator.binding(variable) == s_obj r.knowntypedata = {} if not isinstance(s_type, SomeBuiltin) or typ.__module__ == "__builtin__": add_knowntypedata(r.knowntypedata, True, variables, bk.valueoftype(typ)) return r
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 getattr(obj, s_attr): # get a SomeBuiltin if the SomeObject has # a corresponding method to handle it if s_attr.is_constant() and isinstance(s_attr.const, str): attr = s_attr.const s_method = obj.find_method(attr) if s_method is not None: return s_method # if the SomeObject is itself a constant, allow reading its attrs if obj.is_immutable_constant() and hasattr(obj.const, attr): return immutablevalue(getattr(obj.const, attr)) else: getbookkeeper().warning("getattr(%r, %r) is not RPythonic enough" % (obj, s_attr)) return SomeObject()
def compute_result_annotation(self, s_rpytype, s_obj): from pypy.annotation.bookkeeper import getbookkeeper from pypy.annotation.model import SomeInstance assert s_rpytype.is_constant() rpytype = s_rpytype.const bk = getbookkeeper() return SomeInstance(bk.getuniqueclassdef(rpytype))
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 Exception, "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 Exception, "range() with step zero" if s_start.is_constant() and s_stop.is_constant(): if len(xrange(s_start.const, s_stop.const, step)) == 0: empty = True if empty: s_item = s_ImpossibleValue else: nonneg = False # so far if step > 0: 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 our_issubclass(cls1, cls2): """ we're going to try to be less silly in the face of old-style classes""" from pypy.annotation.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 mod((str, s_tuple)): for s_item in s_tuple.items: if isinstance(s_item, (SomeUnicodeCodePoint, SomeUnicodeString)): raise NotImplementedError( "string formatting mixing strings and unicode not supported") getbookkeeper().count('strformat', str, s_tuple) no_nul = str.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) and s_item.no_nul: pass else: no_nul = False break return SomeString(no_nul=no_nul)
def getbookkeeper(self): if self.bookkeeper is None: from pypy.annotation.bookkeeper import getbookkeeper return getbookkeeper() else: return self.bookkeeper
def getattr(ins, s_attr): if s_attr.is_constant() and isinstance(s_attr.const, str): attr = s_attr.const if attr == '__class__': return ins.classdef.read_attr__class__() attrdef = ins.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 ins.classdef. # XXX do it more nicely if isinstance(s_result, SomePBC): s_result = ins.classdef.lookup_filter(s_result, attr, ins.flags) elif isinstance(s_result, SomeImpossibleValue): ins.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 ins.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 = ins.classdef.classdesc.maybe_return_immutable_list( attr, s_result) return s_result return SomeObject()
def issubtype(obj, s_cls): if hasattr(obj, "is_type_of"): vars = obj.is_type_of annotator = getbookkeeper().annotator return builtin.builtin_isinstance(annotator.binding(vars[0]), s_cls, vars) if obj.is_constant() and s_cls.is_constant(): return immutablevalue(issubclass(obj.const, s_cls.const)) return s_Bool
def unioncheck(*somevalues): s_value = unionof(*somevalues) if isdegenerated(s_value): if not getattr(TLS, 'no_side_effects_in_union', 0): bookkeeper = getbookkeeper() if bookkeeper is not None: bookkeeper.ondegenerated('union', s_value) return s_value
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 read_key(self, position_key=None): if position_key is None: if self.bookkeeper is None: # for tests from pypy.annotation.bookkeeper import getbookkeeper position_key = getbookkeeper().position_key else: position_key = self.bookkeeper.position_key self.dictkey.read_locations[position_key] = True return self.dictkey.s_value
def record_call(func, args_s, symbol): from pypy.annotation import bookkeeper bk = bookkeeper.getbookkeeper() # this would be nice! #bk.pbc_call(bk.immutablevalue(func), # bk.build_args("simple_call", args_s), # emulated=True) bk.annotator.translator._implicitly_called_by_externals.append( (func, args_s, symbol))
def robjmodel_instantiate(s_clspbc): assert isinstance(s_clspbc, SomePBC) clsdef = None more_than_one = len(s_clspbc.descriptions) 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 builtin_slice(*args): bk = getbookkeeper() if len(args) == 1: return SomeSlice( bk.immutablevalue(None), args[0], bk.immutablevalue(None)) elif len(args) == 2: return SomeSlice( args[0], args[1], bk.immutablevalue(None)) elif len(args) == 3: return SomeSlice( args[0], args[1], args[2]) else: raise Exception, "bogus call to slice()"
def ann_startthr(s_bootstrap_function, s_argument_tuple): from pypy.annotation import model as annmodel from pypy.annotation.bookkeeper import getbookkeeper bookkeeper = getbookkeeper() assert (isinstance(s_argument_tuple, annmodel.SomeTuple) and len(s_argument_tuple.items) == 1), ( """thread.start_new_thread(f, arg) is only supported with a tuple of length 1 for arg""") s_arg, = s_argument_tuple.items # XXX hack hack hack: emulate a call to s_bootstrap_function s_result = bookkeeper.emulate_pbc_call(bookkeeper.position_key, s_bootstrap_function, [s_arg]) assert annmodel.s_None.contains(s_result), ( """thread.start_new_thread(f, arg): f() should return None""") return annmodel.SomeInteger()
def getattr(p, s_attr): assert s_attr.is_constant(), "getattr on ptr %r with non-constant field-name" % p.ll_ptrtype example = p.ll_ptrtype._example() try: v = example._lookup_adtmeth(s_attr.const) except AttributeError: v = getattr(example, s_attr.const) return ll_to_annotation(v) else: if isinstance(v, MethodType): from pypy.rpython.lltypesystem import lltype ll_ptrtype = lltype.typeOf(v.im_self) assert isinstance(ll_ptrtype, (lltype.Ptr, lltype.InteriorPtr)) return SomeLLADTMeth(ll_ptrtype, v.im_func) return getbookkeeper().immutablevalue(v)
def ll_to_annotation(v): if v is None: # i think we can only get here in the case of void-returning # functions return s_None if isinstance(v, MethodType): ll_ptrtype = lltype.typeOf(v.im_self) assert isinstance(ll_ptrtype, lltype.Ptr) return SomeLLADTMeth(ll_ptrtype, v.im_func) if isinstance(v, FunctionType): # this case should only be for staticmethod instances used in # adtmeths: the getattr() result is then a plain FunctionType object. from pypy.annotation.bookkeeper import getbookkeeper return getbookkeeper().immutablevalue(v) return lltype_to_annotation(lltype.typeOf(v))
def is_true(s_obj): r = SomeBool() s_obj.is_true_behavior(r) bk = getbookkeeper() knowntypedata = r.knowntypedata = {} fn, block, i = bk.position_key op = block.operations[i] assert op.opname == "is_true" or op.opname == "nonzero" assert len(op.args) == 1 arg = op.args[0] s_nonnone_obj = s_obj if s_obj.can_be_none(): s_nonnone_obj = s_obj.nonnoneify() add_knowntypedata(knowntypedata, True, [arg], s_nonnone_obj) return r
def compute_result_annotation(self, s_arg): from pypy.annotation.bookkeeper import getbookkeeper from atype import SomeVarSizedCTypesType if isinstance(s_arg, SomeVarSizedCTypesType): # POINTER(varsized_array_type): given that rctypes performs # no index checking, this pointer-to-array type is equivalent # to a pointer to an array of whatever size. # ('0' is a bad idea, though, as FixedSizeArrays of length 0 # tend to say they have impossible items.) RESTYPE = POINTER(s_arg.ctype_array._type_ * 1) else: # POINTER(constant_ctype) returns the constant annotation # corresponding to the POINTER(ctype). assert s_arg.is_constant(), ( "POINTER(%r): argument must be constant" % (s_arg,)) RESTYPE = POINTER(s_arg.const) return getbookkeeper().immutablevalue(RESTYPE)
def is_((obj1, obj2)): r = SomeBool() if obj2.is_constant(): if obj1.is_constant(): r.const = obj1.const is obj2.const if obj2.const is None and not obj1.can_be_none(): r.const = False elif obj1.is_constant(): if obj1.const is None and not obj2.can_be_none(): r.const = False # XXX HACK HACK HACK # XXX HACK HACK HACK # XXX HACK HACK HACK bk = getbookkeeper() if bk is not None: # for testing knowntypedata = r.knowntypedata = {} fn, block, i = bk.position_key annotator = bk.annotator op = block.operations[i] assert op.opname == "is_" assert len(op.args) == 2 def bind(src_obj, tgt_obj, tgt_arg): if hasattr(tgt_obj, 'is_type_of') and src_obj.is_constant(): add_knowntypedata(knowntypedata, True, tgt_obj.is_type_of, bk.valueoftype(src_obj.const)) assert annotator.binding(op.args[tgt_arg]) == tgt_obj add_knowntypedata(knowntypedata, True, [op.args[tgt_arg]], src_obj) nonnone_obj = tgt_obj if src_obj.is_constant( ) and src_obj.const is None and tgt_obj.can_be_none(): nonnone_obj = tgt_obj.nonnoneify() add_knowntypedata(knowntypedata, False, [op.args[tgt_arg]], nonnone_obj) bind(obj2, obj1, 0) bind(obj1, obj2, 1) return r
def type(obj, *moreargs): if moreargs: raise Exception, "type() called with more than one argument" if obj.is_constant(): if isinstance(obj, SomeInstance): r = SomePBC([obj.classdef.classdesc]) else: r = immutablevalue(obj.knowntype) else: r = SomeObject() r.knowntype = type bk = getbookkeeper() fn, block, i = bk.position_key annotator = bk.annotator op = block.operations[i] assert op.opname == "type" assert len(op.args) == 1 assert annotator.binding(op.args[0]) == obj r.is_type_of = [op.args[0]] return r
def ll_to_annotation(v): if v is None: # i think we can only get here in the case of void-returning # functions return s_None if isinstance(v, MethodType): ll_ptrtype = lltype.typeOf(v.im_self) assert isinstance(ll_ptrtype, (lltype.Ptr, lltype.InteriorPtr)) return SomeLLADTMeth(ll_ptrtype, v.im_func) if isinstance(v, FunctionType): # this case should only be for staticmethod instances used in # adtmeths: the getattr() result is then a plain FunctionType object. from pypy.annotation.bookkeeper import getbookkeeper return getbookkeeper().immutablevalue(v) if isinstance(v, lltype._interior_ptr): ob = v._parent if ob is None: raise RuntimeError T = lltype.InteriorPtr(lltype.typeOf(ob), v._T, v._offsets) return SomeInteriorPtr(T) return lltype_to_annotation(lltype.typeOf(v))
# The rest of the code propagates nonneg information between # the two arguments. # # Doing the right thing when int1 or int2 change from signed # to unsigned (r_uint) is almost impossible. See test_intcmp_bug. # Instead, we only deduce constrains on the operands in the # case where they are both signed. In other words, if y is # nonneg then "assert x>=y" will let the annotator know that # x is nonneg too, but it will not work if y is unsigned. # if not (rarithmetic.signedtype(int1.knowntype) and rarithmetic.signedtype(int2.knowntype)): return r knowntypedata = {} # XXX HACK HACK HACK fn, block, i = getbookkeeper().position_key op = block.operations[i] assert op.opname == opname assert len(op.args) == 2 def tointtype(int0): if int0.knowntype is bool: return int return int0.knowntype if int1.nonneg and isinstance(op.args[1], Variable): case = opname in ('lt', 'le', 'eq') add_knowntypedata( knowntypedata, case, [op.args[1]], SomeInteger(nonneg=True, knowntype=tointtype(int2)))
def sub((s_addr1, s_addr2)): if s_addr1.is_null_address() and s_addr2.is_null_address(): return getbookkeeper().immutablevalue(0) return SomeInteger()
def compute_result_annotation(self, s_value): assert s_value.is_constant() from pypy.annotation.bookkeeper import getbookkeeper bk = getbookkeeper() return bk.immutablevalue(VoidMarker(s_value.const))
def robjmodel_r_dict(s_eqfn, s_hashfn): dictdef = getbookkeeper().getdictdef(is_r_dict=True) dictdef.dictkey.update_rdict_annotations(s_eqfn, s_hashfn) return SomeDict(dictdef)
def override__ignore(pol, *args): bk = getbookkeeper() return bk.immutablevalue(None)