def __init__(self, rtyper, s_pbc): self.rtyper = rtyper self.funcdesc = s_pbc.any_description().funcdesc # a hack to force the underlying function to show up in call_families # (generally not needed, as normalizecalls() should ensure this, # but needed for bound methods that are ll helpers) # XXX sort this out #call_families = rtyper.annotator.getpbccallfamilies() #call_families.find((None, self.function)) if s_pbc.can_be_none(): raise TyperError("unsupported: variable of type " "method-of-frozen-PBC or None") im_selves = [] for desc in s_pbc.descriptions: if desc.funcdesc is not self.funcdesc: raise TyperError( "You can't mix a set of methods on a frozen PBC in " "RPython that are different underlying functions") im_selves.append(desc.frozendesc) self.s_im_self = annmodel.SomePBC(im_selves) self.r_im_self = rtyper.getrepr(self.s_im_self) self.lowleveltype = self.r_im_self.lowleveltype
def redispatch_call(self, hop, call_args): from rpython.rtyper.lltypesystem.rpbc import (FunctionsPBCRepr, SmallFunctionSetPBCRepr) r_class = self.r_im_self.rclass mangled_name, r_func = r_class.clsfields[self.methodname] assert isinstance(r_func, (FunctionsPBCRepr, SmallFunctionSetPBCRepr)) # s_func = r_func.s_pbc -- not precise enough, see # test_precise_method_call_1. Build a more precise one... funcdescs = [desc.funcdesc for desc in hop.args_s[0].descriptions] s_func = annmodel.SomePBC(funcdescs, subset_of=r_func.s_pbc) v_im_self = hop.inputarg(self, arg=0) v_cls = self.r_im_self.getfield(v_im_self, '__class__', hop.llops) v_func = r_class.getclsfield(v_cls, self.methodname, hop.llops) hop2 = self.add_instance_arg_to_hop(hop, call_args) hop2.v_s_insertfirstarg(v_func, s_func) # insert 'function' if (type(hop2.args_r[0]) is SmallFunctionSetPBCRepr and type(r_func) is FunctionsPBCRepr): hop2.args_r[0] = FunctionsPBCRepr(self.rtyper, s_func) else: hop2.args_v[0] = hop2.llops.convertvar(hop2.args_v[0], r_func, hop2.args_r[0]) # now hop2 looks like simple_call(function, self, args...) return hop2.dispatch()
def prepare_method(self, s_value): # special-casing for methods: # if s_value is SomePBC([MethodDescs...]) # return a PBC representing the underlying functions if (isinstance(s_value, annmodel.SomePBC) and s_value.getKind() == description.MethodDesc): s_value = self.classdef.lookup_filter(s_value) funcdescs = [mdesc.funcdesc for mdesc in s_value.descriptions] return annmodel.SomePBC(funcdescs) return None # not a method
def convert_desc(self, frozendesc): try: return self.converted_pbc_cache[frozendesc] except KeyError: r = self.rtyper.getrepr(annmodel.SomePBC([frozendesc])) if r.lowleveltype is Void: # must create a new empty structure, as a placeholder pbc = self.create_instance() else: pbc = r.convert_desc(frozendesc) convpbc = self.convert_pbc(pbc) self.converted_pbc_cache[frozendesc] = convpbc return convpbc
def builtin_func_for_spec(rtyper, oopspec_name, ll_args, ll_res, extra=None, extrakey=None): assert (extra is None) == (extrakey is None) key = (oopspec_name, tuple(ll_args), ll_res, extrakey) try: return rtyper._builtin_func_for_spec_cache[key] except (KeyError, AttributeError): pass args_s = [lltype_to_annotation(v) for v in ll_args] if '.' not in oopspec_name: # 'newxxx' operations LIST_OR_DICT = ll_res else: LIST_OR_DICT = ll_args[0] s_result = lltype_to_annotation(ll_res) impl = setup_extra_builtin(rtyper, oopspec_name, len(args_s), extra) if getattr(impl, 'need_result_type', False): if hasattr(rtyper, 'annotator'): bk = rtyper.annotator.bookkeeper ll_restype = ll_res if impl.need_result_type != 'exact': ll_restype = ll_restype.TO desc = bk.getdesc(ll_restype) else: class TestingDesc(object): knowntype = int pyobj = None desc = TestingDesc() args_s.insert(0, annmodel.SomePBC([desc])) # if hasattr(rtyper, 'annotator'): # regular case mixlevelann = MixLevelHelperAnnotator(rtyper) c_func = mixlevelann.constfunc(impl, args_s, s_result) mixlevelann.finish() else: # for testing only c_func = Constant(oopspec_name, lltype.Ptr(lltype.FuncType(ll_args, ll_res))) # if not hasattr(rtyper, '_builtin_func_for_spec_cache'): rtyper._builtin_func_for_spec_cache = {} rtyper._builtin_func_for_spec_cache[key] = (c_func, LIST_OR_DICT) # return c_func, LIST_OR_DICT
def redispatch_call(self, hop, call_args): # XXX obscure, try to refactor... s_function = annmodel.SomePBC([self.funcdesc]) hop2 = hop.copy() hop2.args_s[0] = self.s_im_self # make the 1st arg stand for 'im_self' hop2.args_r[0] = self.r_im_self # (same lowleveltype as 'self') if isinstance(hop2.args_v[0], Constant): boundmethod = hop2.args_v[0].value hop2.args_v[0] = Constant(boundmethod.im_self) if call_args: hop2.swap_fst_snd_args() _, s_shape = hop2.r_s_popfirstarg() # temporarely remove shape adjust_shape(hop2, s_shape) # a marker that would crash if actually used... c = Constant("obscure-don't-use-me") hop2.v_s_insertfirstarg(c, s_function) # insert 'function' # now hop2 looks like simple_call(function, self, args...) return hop2.dispatch()
def __init__(self, rtyper, s_pbc): self.rtyper = rtyper funcdescs = set([desc.funcdesc for desc in s_pbc.descriptions]) assert len(funcdescs) == 1 self.funcdesc = funcdescs.pop() # a hack to force the underlying function to show up in call_families # (generally not needed, as normalizecalls() should ensure this, # but needed for bound methods that are ll helpers) # XXX sort this out #call_families = rtyper.annotator.getpbccallfamilies() #call_families.find((None, self.function)) if s_pbc.can_be_none(): raise TyperError("unsupported: variable of type " "method-of-frozen-PBC or None") im_selves = [desc.frozendesc for desc in s_pbc.descriptions] self.s_im_self = annmodel.SomePBC(im_selves) self.r_im_self = rtyper.getrepr(self.s_im_self) self.lowleveltype = self.r_im_self.lowleveltype
def compute_annotation(self): from rpython.annotator import model as annmodel bk = self.bookkeeper translator = bk.annotator.translator fn = getattr(translator, 'll_hash_string', ll_hash_string) return annmodel.SomePBC([bk.getdesc(fn)])
def get_s_callable(self): return annmodel.SomePBC([self.funcdesc])