def checkfunction(translator): # make sure that there is a sensible comparison defined on the # symbolics bk = translator.annotator.bookkeeper rtyper = translator.rtyper base_classdef = bk.getuniqueclassdef(PBase) base_vtable = rclass.getclassrepr(rtyper, base_classdef).getruntime(CLASSTYPE) sub3_classdef = bk.getuniqueclassdef(Sub3) sub3_vtable = rclass.getclassrepr(rtyper, sub3_classdef).getruntime(CLASSTYPE) assert ll_issubclass(sub3_vtable, base_vtable) assert not ll_issubclass(base_vtable, sub3_vtable)
def checkfunction(translator): # make sure that there is a sensible comparison defined on the # symbolics bk = translator.annotator.bookkeeper rtyper = translator.rtyper base_classdef = bk.getuniqueclassdef(PBase) base_vtable = rclass.getclassrepr(rtyper, base_classdef).getruntime() sub3_classdef = bk.getuniqueclassdef(Sub3) sub3_vtable = rclass.getclassrepr(rtyper, sub3_classdef).getruntime() assert ll_issubclass(sub3_vtable, base_vtable) assert not ll_issubclass(base_vtable, sub3_vtable)
def initialize_prebuilt_data(self, value, classdef, result): # then add instance attributes from this level classrepr = getclassrepr(self.rtyper, self.classdef) for mangled, (oot, default) in self.lowleveltype._allfields().items(): if oot is ootype.Void: llattrvalue = None elif mangled == 'meta': llattrvalue = classrepr.get_meta_instance() else: name = unmangle(mangled, self.rtyper.getconfig()) try: attrvalue = getattr(value, name) except AttributeError: attrvalue = self.classdef.classdesc.read_attribute( name, None) if attrvalue is None: warning("prebuilt instance %r has no attribute %r" % (value, name)) continue llattrvalue = self.allfields[ mangled].convert_desc_or_const(attrvalue) else: llattrvalue = self.allfields[mangled].convert_const( attrvalue) setattr(result, mangled, llattrvalue)
def gettype_from_unboxed(self, llops, vinst, can_be_none=False): unboxedclass_repr = getclassrepr(self.rtyper, self.unboxedclassdef) cunboxedcls = inputconst(CLASSTYPE, unboxedclass_repr.getvtable()) if self.is_parent: # If the lltype of vinst shows that it cannot be a tagged value, # we can directly read the typeptr. Otherwise, call a helper that # checks if the tag bit is set in the pointer. unboxedinstance_repr = getinstancerepr(self.rtyper, self.unboxedclassdef) try: lltype.castable(unboxedinstance_repr.lowleveltype, vinst.concretetype) except lltype.InvalidCast: can_be_tagged = False else: can_be_tagged = True vinst = llops.genop('cast_pointer', [vinst], resulttype=self.common_repr()) if can_be_tagged: if can_be_none: func = ll_unboxed_getclass_canbenone else: func = ll_unboxed_getclass return llops.gendirectcall(func, vinst, cunboxedcls) elif can_be_none: return llops.gendirectcall(ll_inst_type, vinst) else: ctypeptr = inputconst(lltype.Void, 'typeptr') return llops.genop('getfield', [vinst, ctypeptr], resulttype = CLASSTYPE) else: return cunboxedcls
def __init__(self, rtyper, classdef): AbstractClassRepr.__init__(self, rtyper, classdef) # This is the Repr for a reference to the class 'classdef' or # any subclass. In the simple case, the lowleveltype is just # ootype.Class. If we need to store class attributes, we use a # "meta" class where the attributes are defined, and the class # reference is a reference to an instance of this meta class. extra_access_sets = self.rtyper.class_pbc_attributes.get( classdef, {}) has_class_attributes = bool(extra_access_sets) if self.classdef is not None: self.rbase = getclassrepr(self.rtyper, self.classdef.basedef) meta_base_type = self.rbase.lowleveltype baseclass_has_meta = meta_base_type != ootype.Class else: baseclass_has_meta = False if not has_class_attributes and not baseclass_has_meta: self.lowleveltype = ootype.Class # simple case else: if self.classdef is None: raise TyperError("the root 'object' class should not have" " class attributes") if self.classdef.classdesc.pyobj in standardexceptions: raise TyperError("Standard exception class %r should not have" " class attributes" % (self.classdef.name,)) if not baseclass_has_meta: meta_base_type = META self.lowleveltype = ootype.Instance( self.classdef.name + "_meta", meta_base_type)
def initialize_prebuilt_instance(self, value, classdef, result): if self.classdef is not None: # recursively build the parent part of the instance self.rbase.initialize_prebuilt_instance(value, classdef, result.super) # then add instance attributes from this level for name, (mangled_name, r) in self.fields.items(): if r.lowleveltype is Void: llattrvalue = None elif name == '_hash_cache_': # hash() support llattrvalue = hash(value) else: try: attrvalue = getattr(value, name) except AttributeError: attrvalue = self.classdef.classdesc.read_attribute(name, None) if attrvalue is None: warning("prebuilt instance %r has no attribute %r" % ( value, name)) llattrvalue = r.lowleveltype._defl() else: llattrvalue = r.convert_desc_or_const(attrvalue) else: llattrvalue = r.convert_const(attrvalue) setattr(result, mangled_name, llattrvalue) else: # OBJECT part rclass = getclassrepr(self.rtyper, classdef) result.typeptr = rclass.getvtable()
def new_instance(self, llops, classcallhop=None): """Build a new instance, without calling __init__.""" classrepr = getclassrepr(self.rtyper, self.classdef) v_instance = llops.genop("new", [inputconst(ootype.Void, self.lowleveltype)], self.lowleveltype) return v_instance
def gettype_from_unboxed(self, llops, vinst): unboxedclass_repr = getclassrepr(self.rtyper, self.unboxedclassdef) cunboxedcls = inputconst(CLASSTYPE, unboxedclass_repr.getvtable()) if self.is_parent: # If the lltype of vinst shows that it cannot be a tagged value, # we can directly read the typeptr. Otherwise, call a helper that # checks if the tag bit is set in the pointer. unboxedinstance_repr = getinstancerepr(self.rtyper, self.unboxedclassdef) try: lltype.castable(unboxedinstance_repr.lowleveltype, vinst.concretetype) except lltype.InvalidCast: can_be_tagged = False else: can_be_tagged = True vinst = llops.genop('cast_pointer', [vinst], resulttype=self.common_repr()) if can_be_tagged: return llops.gendirectcall(ll_unboxed_getclass, vinst, cunboxedcls) else: ctypeptr = inputconst(lltype.Void, 'typeptr') return llops.genop('getfield', [vinst, ctypeptr], resulttype=CLASSTYPE) else: return cunboxedcls
def __init__(self, rtyper, classdef): AbstractClassRepr.__init__(self, rtyper, classdef) # This is the Repr for a reference to the class 'classdef' or # any subclass. In the simple case, the lowleveltype is just # ootype.Class. If we need to store class attributes, we use a # "meta" class where the attributes are defined, and the class # reference is a reference to an instance of this meta class. extra_access_sets = self.rtyper.class_pbc_attributes.get(classdef, {}) has_class_attributes = bool(extra_access_sets) if self.classdef is not None: self.rbase = getclassrepr(self.rtyper, self.classdef.basedef) meta_base_type = self.rbase.lowleveltype baseclass_has_meta = meta_base_type != ootype.Class else: baseclass_has_meta = False if not has_class_attributes and not baseclass_has_meta: self.lowleveltype = ootype.Class # simple case else: if self.classdef is None: raise TyperError("the root 'object' class should not have" " class attributes") if self.classdef.classdesc.pyobj in standardexceptions: raise TyperError("Standard exception class %r should not have" " class attributes" % (self.classdef.name, )) if not baseclass_has_meta: meta_base_type = META self.lowleveltype = ootype.Instance(self.classdef.name + "_meta", meta_base_type)
def initialize_prebuilt_data(self, value, classdef, result): if self.classdef is not None: # recursively build the parent part of the instance self.rbase.initialize_prebuilt_data(value, classdef, result.super) # then add instance attributes from this level for name, (mangled_name, r) in self.fields.items(): if r.lowleveltype is Void: llattrvalue = None else: try: attrvalue = getattr(value, name) except AttributeError: attrvalue = self.classdef.classdesc.read_attribute( name, None) if attrvalue is None: warning( "prebuilt instance %r has no attribute %r" % (value, name)) llattrvalue = r.lowleveltype._defl() else: llattrvalue = r.convert_desc_or_const(attrvalue) else: llattrvalue = r.convert_const(attrvalue) setattr(result, mangled_name, llattrvalue) else: # OBJECT part rclass = getclassrepr(self.rtyper, classdef) result.typeptr = rclass.getvtable()
def convert_desc(self, desc): if desc not in self.s_pbc.descriptions: raise TyperError("%r not in %r" % (cls, self)) if self.lowleveltype is Void: return None subclassdef = desc.getuniqueclassdef() r_subclass = rclass.getclassrepr(self.rtyper, subclassdef) return r_subclass.getruntime(self.lowleveltype)
def _setup_repr(self, llfields=None, hints=None, adtmeths=None): # NOTE: don't store mutable objects like the dicts below on 'self' # before they are fully built, to avoid strange bugs in case # of recursion where other code would uses these # partially-initialized dicts. self.rclass = getclassrepr(self.rtyper, self.classdef) fields = {} allinstancefields = {} if self.classdef is None: fields['__class__'] = 'typeptr', get_type_repr(self.rtyper) else: # instance attributes if llfields is None: llfields = [] attrs = self.classdef.attrs.items() attrs.sort() for name, attrdef in attrs: if not attrdef.readonly: r = self.rtyper.getrepr(attrdef.s_value) mangled_name = 'inst_' + name fields[name] = mangled_name, r llfields.append((mangled_name, r.lowleveltype)) # # hash() support if self.rtyper.needs_hash_support(self.classdef): from pypy.rpython import rint fields['_hash_cache_'] = 'hash_cache', rint.signed_repr llfields.append(('hash_cache', Signed)) self.rbase = getinstancerepr(self.rtyper, self.classdef.basedef, self.gcflavor) self.rbase.setup() # # PyObject wrapper support if self.has_wrapper and '_wrapper_' not in self.rbase.allinstancefields: fields['_wrapper_'] = 'wrapper', pyobj_repr llfields.append(('wrapper', Ptr(PyObject))) MkStruct = lltype.STRUCT_BY_FLAVOR[LLFLAVOR[self.gcflavor]] if adtmeths is None: adtmeths = {} if hints is None: hints = {} if '_immutable_' in self.classdef.classdesc.classdict: hints = hints.copy() hints['immutable'] = True object_type = MkStruct(self.classdef.name, ('super', self.rbase.object_type), hints=hints, adtmeths=adtmeths, *llfields) self.object_type.become(object_type) allinstancefields.update(self.rbase.allinstancefields) allinstancefields.update(fields) self.fields = fields self.allinstancefields = allinstancefields if self.gcflavor in RTTIFLAVORS: attachRuntimeTypeInfo(self.object_type)
def specialize_call(self, hop): from pypy.rpython.rclass import getclassrepr from pypy.objspace.flow.model import Constant from pypy.rpython.lltypesystem import rclass Class = hop.args_s[0].const classdef = hop.rtyper.annotator.bookkeeper.getuniqueclassdef(Class) classrepr = getclassrepr(hop.rtyper, classdef) vtable = classrepr.getvtable() assert lltype.typeOf(vtable) == rclass.CLASSTYPE return Constant(vtable, concretetype=rclass.CLASSTYPE)
def new_instance(self, llops, classcallhop=None): """Build a new instance, without calling __init__.""" classrepr = getclassrepr(self.rtyper, self.classdef) v_instance = llops.genop("new", [inputconst(ootype.Void, self.lowleveltype)], self.lowleveltype) cmeta = inputconst(ootype.Void, "meta") cmeta_instance = inputconst(CLASSTYPE, classrepr.get_meta_instance()) llops.genop("oosetfield", [v_instance, cmeta, cmeta_instance], resulttype=ootype.Void) return v_instance
def getlowleveltype(self): classdescs = list(self.s_pbc.descriptions) # if any of the classdefs get the lowleveltype ootype.Class, # we can only pick ootype.Class for us too. Otherwise META. for classdesc in classdescs: for classdef in classdesc.getallclassdefs(): r_class = getclassrepr(self.rtyper, classdef) if r_class.lowleveltype == ootype.Class: return ootype.Class else: return META
def __init__(self, rtyper, classdef): AbstractClassRepr.__init__(self, rtyper, classdef) if self.classdef is not None: self.rbase = getclassrepr(self.rtyper, self.classdef.basedef) base_type = self.rbase.lowleveltype self.lowleveltype = ootype.Instance(self.classdef.name + "_meta", base_type) else: # we are ROOT self.lowleveltype = CLASSTYPE
def __init__(self, rtyper): self.make_standard_exceptions(rtyper) # (NB. rclass identifies 'Exception' and 'object') r_type = rclass.getclassrepr(rtyper, None) r_instance = rclass.getinstancerepr(rtyper, None) r_type.setup() r_instance.setup() self.r_exception_type = r_type self.r_exception_value = r_instance self.lltype_of_exception_type = r_type.lowleveltype self.lltype_of_exception_value = r_instance.lowleveltype
def __init__(self, rtyper, classdef): AbstractClassRepr.__init__(self, rtyper, classdef) if self.classdef is not None: self.rbase = getclassrepr(self.rtyper, self.classdef.basedef) base_type = self.rbase.lowleveltype self.lowleveltype = ootype.Instance( self.classdef.name + "_meta", base_type) else: # we are ROOT self.lowleveltype = CLASSTYPE
def _setup_repr(self, llfields=None, hints=None, adtmeths=None): # NOTE: don't store mutable objects like the dicts below on 'self' # before they are fully built, to avoid strange bugs in case # of recursion where other code would uses these # partially-initialized dicts. self.rclass = getclassrepr(self.rtyper, self.classdef) fields = {} allinstancefields = {} if self.classdef is None: fields['__class__'] = 'typeptr', get_type_repr(self.rtyper) else: # instance attributes if llfields is None: llfields = [] attrs = self.classdef.attrs.items() attrs.sort() for name, attrdef in attrs: if not attrdef.readonly: r = self.rtyper.getrepr(attrdef.s_value) mangled_name = 'inst_' + name fields[name] = mangled_name, r llfields.append((mangled_name, r.lowleveltype)) # # hash() support if self.rtyper.needs_hash_support(self.classdef): from pypy.rpython import rint fields['_hash_cache_'] = 'hash_cache', rint.signed_repr llfields.append(('hash_cache', Signed)) self.rbase = getinstancerepr(self.rtyper, self.classdef.basedef, self.gcflavor) self.rbase.setup() MkStruct = lltype.STRUCT_BY_FLAVOR[LLFLAVOR[self.gcflavor]] if adtmeths is None: adtmeths = {} if hints is None: hints = {} if '_immutable_' in self.classdef.classdesc.classdict: hints = hints.copy() hints['immutable'] = True object_type = MkStruct(self.classdef.name, ('super', self.rbase.object_type), hints=hints, adtmeths=adtmeths, *llfields) self.object_type.become(object_type) allinstancefields.update(self.rbase.allinstancefields) allinstancefields.update(fields) self.fields = fields self.allinstancefields = allinstancefields if self.gcflavor == 'gc': attachRuntimeTypeInfo(self.object_type)
def get_access_set(self, attrname): """Return the ClassAttrFamily corresponding to accesses to 'attrname' and the ClassRepr of the class which stores this attribute in its vtable. """ classdescs = self.s_pbc.descriptions.keys() access = classdescs[0].queryattrfamily(attrname) for classdesc in classdescs[1:]: access1 = classdesc.queryattrfamily(attrname) assert access1 is access # XXX not implemented if access is None: raise rclass.MissingRTypeAttribute(attrname) commonbase = access.commonbase class_repr = rclass.getclassrepr(self.rtyper, commonbase) return access, class_repr
def _setup_repr(self): # NOTE: don't store mutable objects like the dicts below on 'self' # before they are fully built, to avoid strange bugs in case # of recursion where other code would uses these # partially-initialized dicts. clsfields = {} pbcfields = {} allmethods = {} if self.classdef is not None: # class attributes llfields = [] attrs = self.classdef.attrs.items() attrs.sort() for name, attrdef in attrs: if attrdef.readonly: s_value = attrdef.s_value s_unboundmethod = self.prepare_method(s_value) if s_unboundmethod is not None: allmethods[name] = True s_value = s_unboundmethod r = self.rtyper.getrepr(s_value) mangled_name = 'cls_' + name clsfields[name] = mangled_name, r llfields.append((mangled_name, r.lowleveltype)) # attributes showing up in getattrs done on the class as a PBC extra_access_sets = self.rtyper.class_pbc_attributes.get( self.classdef, {}) for access_set, (attr, counter) in extra_access_sets.items(): r = self.rtyper.getrepr(access_set.s_value) mangled_name = mangle('pbc%d' % counter, attr) pbcfields[access_set, attr] = mangled_name, r llfields.append((mangled_name, r.lowleveltype)) # self.rbase = getclassrepr(self.rtyper, self.classdef.basedef) self.rbase.setup() kwds = {'hints': {'immutable': True}} vtable_type = Struct('%s_vtable' % self.classdef.name, ('super', self.rbase.vtable_type), *llfields, **kwds) self.vtable_type.become(vtable_type) allmethods.update(self.rbase.allmethods) self.clsfields = clsfields self.pbcfields = pbcfields self.allmethods = allmethods self.vtable = None
def _setup_repr(self, llfields=None, hints=None, adtmeths=None): # NOTE: don't store mutable objects like the dicts below on 'self' # before they are fully built, to avoid strange bugs in case # of recursion where other code would uses these # partially-initialized dicts. self.rclass = getclassrepr(self.rtyper, self.classdef) fields = {} allinstancefields = {} if self.classdef is None: fields['__class__'] = 'typeptr', get_type_repr(self.rtyper) else: # instance attributes if llfields is None: llfields = [] attrs = self.classdef.attrs.items() attrs.sort() for name, attrdef in attrs: if not attrdef.readonly: r = self.rtyper.getrepr(attrdef.s_value) mangled_name = 'inst_' + name fields[name] = mangled_name, r llfields.append((mangled_name, r.lowleveltype)) self.rbase = getinstancerepr(self.rtyper, self.classdef.basedef, self.gcflavor) self.rbase.setup() MkStruct = lltype.STRUCT_BY_FLAVOR[LLFLAVOR[self.gcflavor]] if adtmeths is None: adtmeths = {} if hints is None: hints = {} hints = self._check_for_immutable_hints(hints) object_type = MkStruct(self.classdef.name, ('super', self.rbase.object_type), hints=hints, adtmeths=adtmeths, *llfields) self.object_type.become(object_type) allinstancefields.update(self.rbase.allinstancefields) allinstancefields.update(fields) self.fields = fields self.allinstancefields = allinstancefields if self.gcflavor == 'gc': attachRuntimeTypeInfo(self.object_type)
def initialize_prebuilt_data(self, value, classdef, result): # then add instance attributes from this level classrepr = getclassrepr(self.rtyper, self.classdef) for mangled, (oot, default) in self.lowleveltype._allfields().items(): if oot is ootype.Void: llattrvalue = None elif mangled == 'meta': llattrvalue = classrepr.get_meta_instance() else: name = unmangle(mangled, self.rtyper.getconfig()) try: attrvalue = getattr(value, name) except AttributeError: attrvalue = self.classdef.classdesc.read_attribute(name, None) if attrvalue is None: warning("prebuilt instance %r has no attribute %r" % ( value, name)) continue llattrvalue = self.allfields[mangled].convert_desc_or_const(attrvalue) else: llattrvalue = self.allfields[mangled].convert_const(attrvalue) setattr(result, mangled, llattrvalue)
def _setup_repr(self, llfields=None, hints=None): if hints: self.lowleveltype._hints.update(hints) if self.classdef is None: self.allfields = {} self.allmethods = {} self.allclassattributes = {} self.classattributes = {} return if self.baserepr is not None: allfields = self.baserepr.allfields.copy() allmethods = self.baserepr.allmethods.copy() allclassattributes = self.baserepr.allclassattributes.copy() else: allfields = {} allmethods = {} allclassattributes = {} fields = {} fielddefaults = {} if llfields: fields.update(dict(llfields)) selfattrs = self.classdef.attrs for name, attrdef in selfattrs.iteritems(): mangled = mangle(name, self.rtyper.getconfig()) if not attrdef.readonly: repr = self.rtyper.getrepr(attrdef.s_value) allfields[mangled] = repr oot = repr.lowleveltype fields[mangled] = oot try: value = self.classdef.classdesc.read_attribute(name) fielddefaults[mangled] = repr.convert_desc_or_const(value) except AttributeError: pass else: s_value = attrdef.s_value if isinstance(s_value, annmodel.SomePBC): if len(s_value.descriptions) > 0 and s_value.getKind() == description.MethodDesc: # attrdef is for a method if mangled in allclassattributes: raise TyperError("method overrides class attribute") allmethods[mangled] = name, self.classdef.lookup_filter(s_value) continue # class attribute if mangled in allmethods: raise TyperError("class attribute overrides method") allclassattributes[mangled] = name, s_value special_methods = ["__init__", "__del__"] for meth_name in special_methods: if meth_name not in selfattrs and \ self.classdef.classdesc.find_source_for(meth_name) is not None: s_meth = self.classdef.classdesc.s_get_value(self.classdef, meth_name) if isinstance(s_meth, annmodel.SomePBC): mangled = mangle(meth_name, self.rtyper.getconfig()) allmethods[mangled] = meth_name, s_meth # else: it's the __init__ of a builtin exception ootype.addFields(self.lowleveltype, fields) self.rbase = getinstancerepr(self.rtyper, self.classdef.basedef) self.rbase.setup() classattributes = {} baseInstance = self.lowleveltype._superclass classrepr = getclassrepr(self.rtyper, self.classdef) # if this class has a corresponding metaclass, attach # a getmeta() method to get the corresponding meta_instance if classrepr.lowleveltype != ootype.Class: oovalue = classrepr.get_meta_instance() self.attach_class_attr_accessor('getmeta', oovalue) for classdef in self.classdef.getmro(): for name, attrdef in classdef.attrs.iteritems(): if not attrdef.readonly: continue mangled = mangle(name, self.rtyper.getconfig()) if mangled in allclassattributes: selfdesc = self.classdef.classdesc if name not in selfattrs: # if the attr was already found in a parent class, # we register it again only if it is overridden. if selfdesc.find_source_for(name) is None: continue value = selfdesc.read_attribute(name) else: # otherwise, for new attrs, we look in all parent # classes to see if it's defined in a parent but only # actually first used in self.classdef. value = selfdesc.read_attribute(name, None) # a non-method class attribute if not attrdef.s_value.is_constant(): classattributes[mangled] = attrdef.s_value, value self.allfields = allfields self.allmethods = allmethods self.allclassattributes = allclassattributes self.classattributes = classattributes # the following is done after the rest of the initialization because # convert_const can require 'self' to be fully initialized. # step 2: provide default values for fields for mangled, impl in fielddefaults.items(): oot = fields[mangled] ootype.addFields(self.lowleveltype, {mangled: (oot, impl)}, with_default=True)
def _setup_repr(self, llfields=None, hints=None, adtmeths=None): # NOTE: don't store mutable objects like the dicts below on 'self' # before they are fully built, to avoid strange bugs in case # of recursion where other code would uses these # partially-initialized dicts. AbstractInstanceRepr._setup_repr(self) self.rclass = getclassrepr(self.rtyper, self.classdef) fields = {} allinstancefields = {} if self.classdef is None: fields["__class__"] = "typeptr", get_type_repr(self.rtyper) else: # instance attributes attrs = self.classdef.attrs.items() attrs.sort() myllfields = [] for name, attrdef in attrs: if not attrdef.readonly: r = self.rtyper.getrepr(attrdef.s_value) mangled_name = "inst_" + name fields[name] = mangled_name, r myllfields.append((mangled_name, r.lowleveltype)) # Sort the instance attributes by decreasing "likely size", # as reported by rffi.sizeof(), to minimize padding holes in C. # Fields of the same size are sorted by name (by attrs.sort() # above) just to minimize randomness. def keysize((_, T)): if T is lltype.Void: return None from pypy.rpython.lltypesystem.rffi import sizeof try: return -sizeof(T) except StandardError: return None myllfields.sort(key=keysize) if llfields is None: llfields = myllfields else: llfields = llfields + myllfields self.rbase = getinstancerepr(self.rtyper, self.classdef.basedef, self.gcflavor) self.rbase.setup() MkStruct = lltype.STRUCT_BY_FLAVOR[LLFLAVOR[self.gcflavor]] if adtmeths is None: adtmeths = {} if hints is None: hints = {} hints = self._check_for_immutable_hints(hints) kwds = {} if self.gcflavor == "gc": kwds["rtti"] = True for name, attrdef in attrs: if not attrdef.readonly and self.is_quasi_immutable(name): llfields.append(("mutate_" + name, OBJECTPTR)) object_type = MkStruct( self.classdef.name, ("super", self.rbase.object_type), hints=hints, adtmeths=adtmeths, *llfields, **kwds ) self.object_type.become(object_type) allinstancefields.update(self.rbase.allinstancefields) allinstancefields.update(fields) self.fields = fields self.allinstancefields = allinstancefields
def finish(self, rtyper): bk = rtyper.annotator.bookkeeper for cls in self.standardexceptions: classdef = bk.getuniqueclassdef(cls) rclass.getclassrepr(rtyper, classdef).setup()
def _setup_repr(self, llfields=None, hints=None): if hints: self.lowleveltype._hints.update(hints) if self.classdef is None: self.fields = {} self.allfields = {} self.allmethods = {} self.allclassattributes = {} self.classattributes = {} return if self.baserepr is not None: allfields = self.baserepr.allfields.copy() allmethods = self.baserepr.allmethods.copy() allclassattributes = self.baserepr.allclassattributes.copy() else: allfields = {} allmethods = {} allclassattributes = {} fields = {} nonmangledfields = [] fielddefaults = {} if llfields: fields.update(dict(llfields)) selfattrs = self.classdef.attrs for name, attrdef in selfattrs.iteritems(): mangled = mangle(name, self.rtyper.getconfig()) if not attrdef.readonly: repr = self.rtyper.getrepr(attrdef.s_value) allfields[mangled] = repr oot = repr.lowleveltype fields[mangled] = oot nonmangledfields.append(name) try: value = self.classdef.classdesc.read_attribute(name) fielddefaults[mangled] = repr.convert_desc_or_const(value) except AttributeError: pass else: s_value = attrdef.s_value if isinstance(s_value, annmodel.SomePBC): if len(s_value.descriptions) > 0 and s_value.getKind( ) == description.MethodDesc: # attrdef is for a method if mangled in allclassattributes: raise TyperError( "method overrides class attribute") allmethods[ mangled] = name, self.classdef.lookup_filter( s_value) continue # class attribute if mangled in allmethods: raise TyperError("class attribute overrides method") allclassattributes[mangled] = name, s_value special_methods = ["__init__", "__del__"] for meth_name in special_methods: if meth_name not in selfattrs and \ self.classdef.classdesc.find_source_for(meth_name) is not None: s_meth = self.classdef.classdesc.s_get_value( self.classdef, meth_name) if isinstance(s_meth, annmodel.SomePBC): mangled = mangle(meth_name, self.rtyper.getconfig()) allmethods[mangled] = meth_name, s_meth # else: it's the __init__ of a builtin exception ootype.addFields(self.lowleveltype, fields) self.rbase = getinstancerepr(self.rtyper, self.classdef.basedef) self.rbase.setup() for name, attrdef in selfattrs.iteritems(): if not attrdef.readonly and self.is_quasi_immutable(name): name = mangle('mutable_' + name, self.rtyper.getconfig()) ootype.addFields(self.lowleveltype, {name: OBJECT}) classattributes = {} baseInstance = self.lowleveltype._superclass classrepr = getclassrepr(self.rtyper, self.classdef) # if this class has a corresponding metaclass, attach # a getmeta() method to get the corresponding meta_instance if classrepr.lowleveltype != ootype.Class: oovalue = classrepr.get_meta_instance() self.attach_class_attr_accessor('getmeta', oovalue) for classdef in self.classdef.getmro(): for name, attrdef in classdef.attrs.iteritems(): if not attrdef.readonly: continue mangled = mangle(name, self.rtyper.getconfig()) if mangled in allclassattributes: selfdesc = self.classdef.classdesc if name not in selfattrs: # if the attr was already found in a parent class, # we register it again only if it is overridden. if selfdesc.find_source_for(name) is None: continue value = selfdesc.read_attribute(name) else: # otherwise, for new attrs, we look in all parent # classes to see if it's defined in a parent but only # actually first used in self.classdef. value = selfdesc.read_attribute(name, None) # a non-method class attribute if not attrdef.s_value.is_constant(): classattributes[mangled] = attrdef.s_value, value self.fields = nonmangledfields self.allfields = allfields self.allmethods = allmethods self.allclassattributes = allclassattributes self.classattributes = classattributes # the following is done after the rest of the initialization because # convert_const can require 'self' to be fully initialized. # step 2: provide default values for fields for mangled, impl in fielddefaults.items(): oot = fields[mangled] ootype.addFields(self.lowleveltype, {mangled: (oot, impl)}, with_default=True)
def _setup_repr(self): if self.classdef is None: self.allfields = {} self.allmethods = {} self.allclassattributes = {} self.classattributes = {} return if self.baserepr is not None: allfields = self.baserepr.allfields.copy() allmethods = self.baserepr.allmethods.copy() allclassattributes = self.baserepr.allclassattributes.copy() else: allfields = {} allmethods = {} allclassattributes = {} fields = {} fielddefaults = {} selfattrs = self.classdef.attrs for name, attrdef in selfattrs.iteritems(): mangled = mangle(name, self.rtyper.getconfig()) if not attrdef.readonly: repr = self.rtyper.getrepr(attrdef.s_value) allfields[mangled] = repr oot = repr.lowleveltype fields[mangled] = oot try: value = self.classdef.classdesc.read_attribute(name) fielddefaults[mangled] = repr.convert_desc_or_const(value) except AttributeError: pass else: s_value = attrdef.s_value if isinstance(s_value, annmodel.SomePBC): if len(s_value.descriptions) > 0 and s_value.getKind() == description.MethodDesc: # attrdef is for a method if mangled in allclassattributes: raise TyperError("method overrides class attribute") allmethods[mangled] = name, self.classdef.lookup_filter(s_value) continue # class attribute if mangled in allmethods: raise TyperError("class attribute overrides method") allclassattributes[mangled] = name, s_value special_methods = ["__init__", "__del__"] for meth_name in special_methods: if meth_name not in selfattrs and \ self.classdef.classdesc.find_source_for(meth_name) is not None: s_meth = self.classdef.classdesc.s_get_value(self.classdef, meth_name) if isinstance(s_meth, annmodel.SomePBC): mangled = mangle(meth_name, self.rtyper.getconfig()) allmethods[mangled] = meth_name, s_meth # else: it's the __init__ of a builtin exception # # hash() support if self.rtyper.needs_hash_support(self.classdef): from pypy.rpython import rint allfields['_hash_cache_'] = rint.signed_repr fields['_hash_cache_'] = ootype.Signed ootype.addFields(self.lowleveltype, fields) self.rbase = getinstancerepr(self.rtyper, self.classdef.basedef) self.rbase.setup() methods = {} classattributes = {} baseInstance = self.lowleveltype._superclass classrepr = getclassrepr(self.rtyper, self.classdef) for mangled, (name, s_value) in allmethods.iteritems(): methdescs = s_value.descriptions origin = dict([(methdesc.originclassdef, methdesc) for methdesc in methdescs]) if self.classdef in origin: methdesc = origin[self.classdef] else: if name in selfattrs: for superdef in self.classdef.getmro(): if superdef in origin: # put in methods methdesc = origin[superdef] break else: # abstract method methdesc = None else: continue # get method implementation from pypy.rpython.ootypesystem.rpbc import MethodImplementations methimpls = MethodImplementations.get(self.rtyper, s_value) m_impls = methimpls.get_impl(mangled, methdesc, is_finalizer=name == "__del__") methods.update(m_impls) for classdef in self.classdef.getmro(): for name, attrdef in classdef.attrs.iteritems(): if not attrdef.readonly: continue mangled = mangle(name, self.rtyper.getconfig()) if mangled in allclassattributes: selfdesc = self.classdef.classdesc if name not in selfattrs: # if the attr was already found in a parent class, # we register it again only if it is overridden. if selfdesc.find_source_for(name) is None: continue value = selfdesc.read_attribute(name) else: # otherwise, for new attrs, we look in all parent # classes to see if it's defined in a parent but only # actually first used in self.classdef. value = selfdesc.read_attribute(name, None) # a non-method class attribute if not attrdef.s_value.is_constant(): classattributes[mangled] = attrdef.s_value, value ootype.addMethods(self.lowleveltype, methods) self.allfields = allfields self.allmethods = allmethods self.allclassattributes = allclassattributes self.classattributes = classattributes # the following is done after the rest of the initialization because # convert_const can require 'self' to be fully initialized. # step 2: provide default values for fields for mangled, impl in fielddefaults.items(): oot = fields[mangled] ootype.addFields(self.lowleveltype, {mangled: (oot, impl)})
def _setup_repr(self, llfields=None, hints=None, adtmeths=None): # NOTE: don't store mutable objects like the dicts below on 'self' # before they are fully built, to avoid strange bugs in case # of recursion where other code would uses these # partially-initialized dicts. AbstractInstanceRepr._setup_repr(self) self.rclass = getclassrepr(self.rtyper, self.classdef) fields = {} allinstancefields = {} if self.classdef is None: fields['__class__'] = 'typeptr', get_type_repr(self.rtyper) else: # instance attributes attrs = self.classdef.attrs.items() attrs.sort() myllfields = [] for name, attrdef in attrs: if not attrdef.readonly: r = self.rtyper.getrepr(attrdef.s_value) mangled_name = 'inst_' + name fields[name] = mangled_name, r myllfields.append((mangled_name, r.lowleveltype)) # Sort the instance attributes by decreasing "likely size", # as reported by rffi.sizeof(), to minimize padding holes in C. # Fields of the same size are sorted by name (by attrs.sort() # above) just to minimize randomness. def keysize((_, T)): if T is lltype.Void: return None from pypy.rpython.lltypesystem.rffi import sizeof try: return -sizeof(T) except StandardError: return None myllfields.sort(key=keysize) if llfields is None: llfields = myllfields else: llfields = llfields + myllfields self.rbase = getinstancerepr(self.rtyper, self.classdef.basedef, self.gcflavor) self.rbase.setup() MkStruct = lltype.STRUCT_BY_FLAVOR[LLFLAVOR[self.gcflavor]] if adtmeths is None: adtmeths = {} if hints is None: hints = {} hints = self._check_for_immutable_hints(hints) kwds = {} if self.gcflavor == 'gc': kwds['rtti'] = True for name, attrdef in attrs: if not attrdef.readonly and self.is_quasi_immutable(name): llfields.append(('mutate_' + name, OBJECTPTR)) object_type = MkStruct(self.classdef.name, ('super', self.rbase.object_type), hints=hints, adtmeths=adtmeths, *llfields, **kwds) self.object_type.become(object_type) allinstancefields.update(self.rbase.allinstancefields) allinstancefields.update(fields) self.fields = fields self.allinstancefields = allinstancefields
def _setup_repr(self): if self.classdef is None: self.allfields = {} self.allmethods = {} self.allclassattributes = {} self.classattributes = {} return if self.baserepr is not None: allfields = self.baserepr.allfields.copy() allmethods = self.baserepr.allmethods.copy() allclassattributes = self.baserepr.allclassattributes.copy() else: allfields = {} allmethods = {} allclassattributes = {} fields = {} fielddefaults = {} selfattrs = self.classdef.attrs for name, attrdef in selfattrs.iteritems(): mangled = mangle(name, self.rtyper.getconfig()) if not attrdef.readonly: repr = self.rtyper.getrepr(attrdef.s_value) allfields[mangled] = repr oot = repr.lowleveltype fields[mangled] = oot try: value = self.classdef.classdesc.read_attribute(name) fielddefaults[mangled] = repr.convert_desc_or_const(value) except AttributeError: pass else: s_value = attrdef.s_value if isinstance(s_value, annmodel.SomePBC): if len(s_value.descriptions) > 0 and s_value.getKind( ) == description.MethodDesc: # attrdef is for a method if mangled in allclassattributes: raise TyperError( "method overrides class attribute") allmethods[ mangled] = name, self.classdef.lookup_filter( s_value) continue # class attribute if mangled in allmethods: raise TyperError("class attribute overrides method") allclassattributes[mangled] = name, s_value special_methods = ["__init__", "__del__"] for meth_name in special_methods: if meth_name not in selfattrs and \ self.classdef.classdesc.find_source_for(meth_name) is not None: s_meth = self.classdef.classdesc.s_get_value( self.classdef, meth_name) if isinstance(s_meth, annmodel.SomePBC): mangled = mangle(meth_name, self.rtyper.getconfig()) allmethods[mangled] = meth_name, s_meth # else: it's the __init__ of a builtin exception # # hash() support if self.rtyper.needs_hash_support(self.classdef): from pypy.rpython import rint allfields['_hash_cache_'] = rint.signed_repr fields['_hash_cache_'] = ootype.Signed ootype.addFields(self.lowleveltype, fields) self.rbase = getinstancerepr(self.rtyper, self.classdef.basedef) self.rbase.setup() methods = {} classattributes = {} baseInstance = self.lowleveltype._superclass classrepr = getclassrepr(self.rtyper, self.classdef) for mangled, (name, s_value) in allmethods.iteritems(): methdescs = s_value.descriptions origin = dict([(methdesc.originclassdef, methdesc) for methdesc in methdescs]) if self.classdef in origin: methdesc = origin[self.classdef] else: if name in selfattrs: for superdef in self.classdef.getmro(): if superdef in origin: # put in methods methdesc = origin[superdef] break else: # abstract method methdesc = None else: continue # get method implementation from pypy.rpython.ootypesystem.rpbc import MethodImplementations methimpls = MethodImplementations.get(self.rtyper, s_value) m_impls = methimpls.get_impl(mangled, methdesc, is_finalizer=name == "__del__") methods.update(m_impls) for classdef in self.classdef.getmro(): for name, attrdef in classdef.attrs.iteritems(): if not attrdef.readonly: continue mangled = mangle(name, self.rtyper.getconfig()) if mangled in allclassattributes: selfdesc = self.classdef.classdesc if name not in selfattrs: # if the attr was already found in a parent class, # we register it again only if it is overridden. if selfdesc.find_source_for(name) is None: continue value = selfdesc.read_attribute(name) else: # otherwise, for new attrs, we look in all parent # classes to see if it's defined in a parent but only # actually first used in self.classdef. value = selfdesc.read_attribute(name, None) # a non-method class attribute if not attrdef.s_value.is_constant(): classattributes[mangled] = attrdef.s_value, value ootype.addMethods(self.lowleveltype, methods) self.allfields = allfields self.allmethods = allmethods self.allclassattributes = allclassattributes self.classattributes = classattributes # the following is done after the rest of the initialization because # convert_const can require 'self' to be fully initialized. # step 2: provide default values for fields for mangled, impl in fielddefaults.items(): oot = fields[mangled] ootype.addFields(self.lowleveltype, {mangled: (oot, impl)})