def rtype_method_join(self, hop): hop.exception_cannot_occur() rstr = hop.args_r[0] if hop.s_result.is_constant(): return inputconst(rstr.repr, hop.s_result.const) r_lst = hop.args_r[1] if not isinstance(r_lst, hop.rtyper.type_system.rlist.BaseListRepr): raise TyperError("string.join of non-list: %r" % r_lst) v_str, v_lst = hop.inputargs(rstr.repr, r_lst) v_length, v_items = self._list_length_items(hop, v_lst, r_lst.lowleveltype) if hop.args_s[0].is_constant() and hop.args_s[0].const == '': if r_lst.item_repr == rstr.repr: llfn = self.ll.ll_join_strs elif (r_lst.item_repr == hop.rtyper.type_system.rstr.char_repr or r_lst.item_repr == hop.rtyper.type_system.rstr.unichar_repr): v_tp = hop.inputconst(Void, self.lowleveltype) return hop.gendirectcall(self.ll.ll_join_chars, v_length, v_items, v_tp) else: raise TyperError("''.join() of non-string list: %r" % r_lst) return hop.gendirectcall(llfn, v_length, v_items) else: if r_lst.item_repr == rstr.repr: llfn = self.ll.ll_join else: raise TyperError("sep.join() of non-string list: %r" % r_lst) return hop.gendirectcall(llfn, v_str, v_length, v_items)
def __init__(self, rtyper, s_pbc): self.rtyper = rtyper self.s_pbc = s_pbc if s_pbc.isNone(): raise TyperError("unsupported: variable of type " "bound-method-object or None") mdescs = s_pbc.descriptions.keys() methodname = mdescs[0].name classdef = mdescs[0].selfclassdef flags = mdescs[0].flags for mdesc in mdescs[1:]: if mdesc.name != methodname: raise TyperError("cannot find a unique name under which the " "methods can be found: %r" % (mdescs, )) if mdesc.flags != flags: raise TyperError("inconsistent 'flags': %r versus %r" % (mdesc.flags, flags)) classdef = classdef.commonbase(mdesc.selfclassdef) if classdef is None: raise TyperError("mixing methods coming from instances of " "classes with no common base: %r" % (mdescs, )) self.methodname = methodname self.classdef = classdef.locate_attribute(methodname) # the low-level representation is just the bound 'self' argument. self.s_im_self = annmodel.SomeInstance(self.classdef, flags=flags) self.r_im_self = rclass.getinstancerepr(rtyper, self.classdef) self.lowleveltype = self.r_im_self.lowleveltype
def call_args_expand(hop, takes_kwds = True): hop = hop.copy() from pypy.interpreter.argument import Arguments arguments = Arguments.fromshape(None, hop.args_s[1].const, # shape range(hop.nb_args-2)) if arguments.w_starstararg is not None: raise TyperError("**kwds call not implemented") if arguments.w_stararg is not None: # expand the *arg in-place -- it must be a tuple from pypy.rpython.rtuple import AbstractTupleRepr if arguments.w_stararg != hop.nb_args - 3: raise TyperError("call pattern too complex") hop.nb_args -= 1 v_tuple = hop.args_v.pop() s_tuple = hop.args_s.pop() r_tuple = hop.args_r.pop() if not isinstance(r_tuple, AbstractTupleRepr): raise TyperError("*arg must be a tuple") for i in range(len(r_tuple.items_r)): v_item = r_tuple.getitem_internal(hop.llops, v_tuple, i) hop.nb_args += 1 hop.args_v.append(v_item) hop.args_s.append(s_tuple.items[i]) hop.args_r.append(r_tuple.items_r[i]) kwds = arguments.kwds_w or {} if not takes_kwds and kwds: raise TyperError("kwds args not supported") # prefix keyword arguments with 'i_' kwds_i = {} for key, index in kwds.items(): kwds_i['i_'+key] = index return hop, kwds_i
def rtype_method_find(self, hop, reverse=False): # XXX binaryop string_repr = hop.args_r[0].repr char_repr = hop.args_r[0].char_repr v_str = hop.inputarg(string_repr, arg=0) if hop.args_r[1] == char_repr: v_value = hop.inputarg(char_repr, arg=1) llfn = reverse and self.ll.ll_rfind_char or self.ll.ll_find_char else: v_value = hop.inputarg(string_repr, arg=1) llfn = reverse and self.ll.ll_rfind or self.ll.ll_find if hop.nb_args > 2: v_start = hop.inputarg(Signed, arg=2) if not hop.args_s[2].nonneg: raise TyperError( "str.find() start must be proven non-negative") else: v_start = hop.inputconst(Signed, 0) if hop.nb_args > 3: v_end = hop.inputarg(Signed, arg=3) if not hop.args_s[3].nonneg: raise TyperError("str.find() end must be proven non-negative") else: v_end = hop.gendirectcall(self.ll.ll_strlen, v_str) hop.exception_cannot_occur() return hop.gendirectcall(llfn, v_str, v_value, v_start, v_end)
def rtypedelegate(callable, hop, revealargs=[0], revealresult=False): bk = hop.rtyper.annotator.bookkeeper c_meth = Constant(callable) s_meth = bk.immutablevalue(callable) hop2 = hop.copy() for index in revealargs: r_controlled = hop2.args_r[index] if not isinstance(r_controlled, ControlledInstanceRepr): raise TyperError( "args_r[%d] = %r, expected ControlledInstanceRepr" % (index, r_controlled)) s_new, r_new = r_controlled.s_real_obj, r_controlled.r_real_obj hop2.args_s[index], hop2.args_r[index] = s_new, r_new v = hop2.args_v[index] if isinstance(v, Constant): real_value = r_controlled.controller.convert(v.value) hop2.args_v[index] = Constant(real_value) if revealresult: r_controlled = hop2.r_result if not isinstance(r_controlled, ControlledInstanceRepr): raise TyperError("r_result = %r, expected ControlledInstanceRepr" % (r_controlled, )) s_new, r_new = r_controlled.s_real_obj, r_controlled.r_real_obj hop2.s_result, hop2.r_result = s_new, r_new hop2.v_s_insertfirstarg(c_meth, s_meth) hop2.forced_opname = 'simple_call' return hop2.dispatch()
def rtype_getattr(self, hop): s_attr = hop.args_s[1] if s_attr.is_constant() and isinstance(s_attr.const, str): attr = s_attr.const s_obj = hop.args_s[0] if s_obj.find_method(attr) is None: raise TyperError("no method %s on %r" % (attr, s_obj)) else: # implement methods (of a known name) as just their 'self' return hop.inputarg(self, arg=0) else: raise TyperError("getattr() with a non-constant attribute name")
def rtype_method_decode(self, hop): if not hop.args_s[1].is_constant(): raise TyperError("encoding must be a constant") encoding = hop.args_s[1].const v_self = hop.inputarg(self.repr, 0) hop.exception_is_here() if encoding == 'ascii': return hop.gendirectcall(self.ll.ll_str2unicode, v_self) elif encoding == 'latin-1': return hop.gendirectcall(self.ll_decode_latin1, v_self) else: raise TyperError("encoding %s not implemented" % (encoding, ))
def rtype_r_dict(hop): r_dict = hop.r_result if not r_dict.custom_eq_hash: raise TyperError("r_dict() call does not return an r_dict instance") cDICT = hop.inputconst(ootype.Void, r_dict.DICT) hop.exception_cannot_occur() # the signature of oonewcustomdict is a bit complicated because we # can have three different ways to pass the equal (and hash) # callables: # 1. pass a plain function: v_eqfn is a StaticMethod, v_eqobj # and c_eq_method_name are None # 2. pass a bound method: v_eqfn is None, v_eqobj is the # instance, c_method_name is the name of the method, # 3. pass a method of a frozen PBC: v_eqfn is a StaticMethod, # v_eqobj is the PBC to be pushed in front of the StaticMethod, # c_eq_method_name is None s_key = r_dict.dictkey.s_value v_eqfn, v_eqobj, c_eq_method_name =\ _get_call_vars(hop, r_dict.r_rdict_eqfn, 0, [s_key, s_key]) v_hashfn, v_hashobj, c_hash_method_name =\ _get_call_vars(hop, r_dict.r_rdict_hashfn, 1, [s_key]) return hop.genop("oonewcustomdict", [ cDICT, v_eqfn, v_eqobj, c_eq_method_name, v_hashfn, v_hashobj, c_hash_method_name ], resulttype=hop.r_result.lowleveltype)
def rtype_builtin_range(hop): vstep = hop.inputconst(Signed, 1) if hop.nb_args == 1: vstart = hop.inputconst(Signed, 0) vstop, = hop.inputargs(Signed) elif hop.nb_args == 2: vstart, vstop = hop.inputargs(Signed, Signed) else: vstart, vstop, vstep = hop.inputargs(Signed, Signed, Signed) if isinstance(vstep, Constant) and vstep.value == 0: # not really needed, annotator catches it. Just in case... raise TyperError("range cannot have a const step of zero") if isinstance(hop.r_result, AbstractRangeRepr): if hop.r_result.step != 0: c_rng = hop.inputconst(Void, hop.r_result.RANGE) hop.exception_is_here() return hop.gendirectcall(hop.r_result.ll_newrange, c_rng, vstart, vstop) else: hop.exception_is_here() return hop.gendirectcall(hop.r_result.ll_newrangest, vstart, vstop, vstep) else: # cannot build a RANGE object, needs a real list r_list = hop.r_result ITEMTYPE = r_list.lowleveltype if isinstance(ITEMTYPE, Ptr): ITEMTYPE = ITEMTYPE.TO cLIST = hop.inputconst(Void, ITEMTYPE) hop.exception_is_here() return hop.gendirectcall(ll_range2list, cLIST, vstart, vstop, vstep)
def merge_classpbc_getattr_into_classdef(rtyper): # code like 'some_class.attr' will record an attribute access in the # PBC access set of the family of classes of 'some_class'. If the classes # have corresponding ClassDefs, they are not updated by the annotator. # We have to do it now. all_families = rtyper.annotator.bookkeeper.classpbc_attr_families for attrname, access_sets in all_families.items(): for access_set in access_sets.infos(): descs = access_set.descs if len(descs) <= 1: continue if not isinstance(descs.iterkeys().next(), description.ClassDesc): continue classdefs = [desc.getuniqueclassdef() for desc in descs] commonbase = classdefs[0] for cdef in classdefs[1:]: commonbase = commonbase.commonbase(cdef) if commonbase is None: raise TyperError("reading attribute %r: no common base " "class for %r" % (attrname, descs.keys())) extra_access_sets = rtyper.class_pbc_attributes.setdefault( commonbase, {}) if commonbase in rtyper.class_reprs: assert access_set in extra_access_sets # minimal sanity check continue access_set.commonbase = commonbase if access_set not in extra_access_sets: counter = len(extra_access_sets) extra_access_sets[access_set] = attrname, counter
def rtype_r_dict(hop): from pypy.rlib import jit r_dict = hop.r_result if not r_dict.custom_eq_hash: raise TyperError("r_dict() call does not return an r_dict instance") cDICT = hop.inputconst(ootype.Void, r_dict.DICT) hop.exception_cannot_occur() # the signature of oonewcustomdict is a bit complicated because we # can have three different ways to pass the equal (and hash) # callables: # 1. pass a plain function: eqfn is a StaticMethod, v_eqobj # and eq_method_name are None # 2. pass a bound method: eqfn is None, v_eqobj is the # instance, eq_method_name is the name of the method, # 3. pass a method of a frozen PBC: eqfn is a StaticMethod, v_eqobj is a # non-None Void value (to be ignored by all the backends except the # llinterp), eq_method_name is None s_key = r_dict.dictkey.s_value eqfn, v_eqobj, eq_method_name =\ _get_call_args(hop, r_dict.r_rdict_eqfn, 0, [s_key, s_key]) hashfn, v_hashobj, hash_method_name =\ _get_call_args(hop, r_dict.r_rdict_hashfn, 1, [s_key]) @jit.dont_look_inside def ll_newcustomdict(DICT, v_eqobj, v_hashobj): from pypy.rpython.lltypesystem.lloperation import llop return llop.oonewcustomdict(DICT, DICT, eqfn, v_eqobj, eq_method_name, hashfn, v_hashobj, hash_method_name) ll_newcustomdict._dont_inline_ = True return hop.gendirectcall(ll_newcustomdict, cDICT, v_eqobj, v_hashobj)
def buildinstancerepr(rtyper, classdef, gcflavor='gc'): if classdef is None: unboxed = [] virtualizable = False else: unboxed = [subdef for subdef in classdef.getallsubdefs() if subdef.classdesc.pyobj is not None and issubclass(subdef.classdesc.pyobj, UnboxedValue)] virtualizable = classdef.classdesc.read_attribute('_virtualizable_', Constant(False)).value if virtualizable: assert len(unboxed) == 0 assert gcflavor == 'gc' from pypy.rpython.lltypesystem import rvirtualizable return rvirtualizable.VirtualizableInstanceRepr(rtyper, classdef) elif len(unboxed) == 0: return InstanceRepr(rtyper, classdef, gcflavor) else: # the UnboxedValue class and its parent classes need a # special repr for their instances if len(unboxed) != 1: raise TyperError("%r has several UnboxedValue subclasses" % ( classdef,)) assert gcflavor == 'gc' from pypy.rpython.lltypesystem import rtagged return rtagged.TaggedInstanceRepr(rtyper, classdef, unboxed[0])
def convert_desc(self, funcdesc): # get the whole "column" of the call table corresponding to this desc try: return self.funccache[funcdesc] except KeyError: pass if self.lowleveltype is Void: result = None else: llfns = {} found_anything = False for row in self.uniquerows: if funcdesc in row: llfn = row[funcdesc] found_anything = True else: # missing entry -- need a 'null' of the type that matches # this row llfn = self.rtyper.type_system.null_callable(row.fntype) llfns[row.attrname] = llfn if not found_anything: raise TyperError("%r not in %r" % (funcdesc, self.s_pbc.descriptions)) if len(self.uniquerows) == 1: result = llfn # from the loop above else: # build a Struct with all the values collected in 'llfns' result = self.create_specfunc() for attrname, llfn in llfns.items(): setattr(result, attrname, llfn) self.funccache[funcdesc] = result return result
def specialize_call(self, hop): from pypy.rpython.rcontrollerentry import ControlledInstanceRepr if not isinstance(hop.r_result, ControlledInstanceRepr): raise TyperError("box() should return ControlledInstanceRepr,\n" "got %r" % (hop.r_result,)) hop.exception_cannot_occur() return hop.inputarg(hop.r_result.r_real_obj, arg=1)
def parse_fmt_string(fmt): # we support x, d, s, f, [r] it = iter(fmt) r = [] curstr = '' for c in it: if c == '%': f = it.next() if f == '%': curstr += '%' continue if curstr: r.append(curstr) curstr = '' if f not in 'xdosrf': raise TyperError( "Unsupported formatting specifier: %r in %r" % (f, fmt)) r.append((f, )) else: curstr += c if curstr: r.append(curstr) return r
def rtype_hlinvoke(hop): _, s_repr = hop.r_s_popfirstarg() r_callable = s_repr.const r_func, nimplicitarg = r_callable.get_r_implfunc() s_callable = r_callable.get_s_callable() nbargs = len(hop.args_s) - 1 + nimplicitarg s_sigs = r_func.get_s_signatures((nbargs, (), False, False)) if len(s_sigs) != 1: raise TyperError("cannot hlinvoke callable %r with not uniform" "annotations: %r" % (r_callable, s_sigs)) args_s, s_ret = s_sigs[0] rinputs = [hop.rtyper.getrepr(s_obj) for s_obj in args_s] rresult = hop.rtyper.getrepr(s_ret) args_s = args_s[nimplicitarg:] rinputs = rinputs[nimplicitarg:] new_args_r = [r_callable] + rinputs for i in range(len(new_args_r)): assert hop.args_r[i].lowleveltype == new_args_r[i].lowleveltype hop.args_r = new_args_r hop.args_s = [s_callable] + args_s hop.s_result = s_ret assert hop.r_result.lowleveltype == rresult.lowleveltype hop.r_result = rresult return hop.dispatch()
def buildinstancerepr(rtyper, classdef, gcflavor='gc'): from pypy.rlib.objectmodel import UnboxedValue from pypy.objspace.flow.model import Constant if classdef is None: unboxed = [] virtualizable2 = False else: unboxed = [subdef for subdef in classdef.getallsubdefs() if subdef.classdesc.pyobj is not None and issubclass(subdef.classdesc.pyobj, UnboxedValue)] virtualizable2 = classdef.classdesc.read_attribute('_virtualizable2_', Constant(False)).value config = rtyper.annotator.translator.config usetagging = len(unboxed) != 0 and config.translation.taggedpointers if virtualizable2: assert len(unboxed) == 0 assert gcflavor == 'gc' return rtyper.type_system.rvirtualizable2.Virtualizable2InstanceRepr(rtyper, classdef) elif usetagging and rtyper.type_system.name == 'lltypesystem': # the UnboxedValue class and its parent classes need a # special repr for their instances if len(unboxed) != 1: raise TyperError("%r has several UnboxedValue subclasses" % ( classdef,)) assert gcflavor == 'gc' from pypy.rpython.lltypesystem import rtagged return rtagged.TaggedInstanceRepr(rtyper, classdef, unboxed[0]) else: return rtyper.type_system.rclass.InstanceRepr(rtyper, classdef, gcflavor)
def rtype_method_encode(self, hop): if not hop.args_s[1].is_constant(): raise TyperError("encoding must be constant") encoding = hop.args_s[1].const if encoding == "ascii" and self.lowleveltype == UniChar: expect = UniChar # only for unichar.encode('ascii') else: expect = self.repr # must be a regular unicode string v_self = hop.inputarg(expect, 0) hop.exception_is_here() if encoding == "ascii": return hop.gendirectcall(self.ll_str, v_self) elif encoding == "latin-1": return hop.gendirectcall(self.ll_encode_latin1, v_self) else: raise TyperError("encoding %s not implemented" % (encoding, ))
def rtype_raw_free(hop): s_addr = hop.args_s[0] if s_addr.is_null_address(): raise TyperError("raw_free(x) where x is the constant NULL") v_addr, = hop.inputargs(llmemory.Address) hop.exception_cannot_occur() return hop.genop('raw_free', [v_addr])
def rtype_raw_memcopy(hop): for s_addr in hop.args_s[:2]: if s_addr.is_null_address(): raise TyperError("raw_memcopy() with a constant NULL") v_list = hop.inputargs(llmemory.Address, llmemory.Address, lltype.Signed) hop.exception_cannot_occur() return hop.genop('raw_memcopy', v_list)
def commonbase(classdefs): result = classdefs[0] for cdef in classdefs[1:]: result = result.commonbase(cdef) if result is None: raise TyperError("no common base class in %r" % (classdefs, )) return result
def getpbcfield(self, vcls, access_set, attr, llops): if (access_set, attr) not in self.pbcfields: raise TyperError("internal error: missing PBC field") mangled_name, r = self.pbcfields[access_set, attr] v_vtable = self.fromtypeptr(vcls, llops) cname = inputconst(Void, mangled_name) return llops.genop('getfield', [v_vtable, cname], resulttype=r)
def exception_cannot_occur(self): self.llops._called_exception_is_here_or_cannot_occur = True if self.llops.llop_raising_exceptions is not None: raise TyperError("cannot catch an exception at more than one llop") if not self.exceptionlinks: return # ignored for high-level ops before the last one in the block self.llops.llop_raising_exceptions = "removed"
class __extend__(pairtype(ArrayRepr, Repr)): def rtype_getitem((r_array, r_key), hop): v_array, v_key = hop.inputargs(r_array, r_key) if isinstance(r_key, IntegerRepr): r_tuple, v_tuple = convert_int_to_tuple(r_key, v_key, hop.llops) elif isinstance(r_key, AbstractSliceRepr): r_tuple, v_tuple = convert_slice_to_tuple(r_key, v_key, hop.llops) elif isinstance(r_key, TupleRepr): r_tuple, v_tuple = r_key, v_key else: raise TyperError("bad key: %s" % r_key) ndim = get_view_ndim(r_array, r_tuple) if ndim == 0: # return a scalar cARRAY = hop.inputconst(Void, r_array.ARRAY.TO) get_item, set_item = gen_getset_item(r_array.ndim) return hop.gendirectcall(get_item, cARRAY, v_array, v_tuple) r_result = hop.r_result ARRAY = r_result.ARRAY assert dim_of_ARRAY(ARRAY) == ndim cARRAY = hop.inputconst(Void, ARRAY.TO) ll_get_view = gen_get_view(r_array, r_tuple, hop) return hop.gendirectcall(ll_get_view, cARRAY, v_array, v_tuple)
def rtype_raw_memclear(hop): s_addr = hop.args_s[0] if s_addr.is_null_address(): raise TyperError("raw_memclear(x, n) where x is the constant NULL") v_list = hop.inputargs(llmemory.Address, lltype.Signed) hop.exception_cannot_occur() return hop.genop('raw_memclear', v_list)