[pypy-svn] r53335 - in pypy/branch/less-meta-instances/pypy: annotation rpython rpython/lltypesystem rpython/ootypesystem

arigo at codespeak.net arigo at codespeak.net
Fri Apr 4 17:42:50 CEST 2008


Author: arigo
Date: Fri Apr  4 17:42:50 2008
New Revision: 53335

Modified:
   pypy/branch/less-meta-instances/pypy/annotation/description.py
   pypy/branch/less-meta-instances/pypy/rpython/lltypesystem/rpbc.py
   pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/exceptiondata.py
   pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rclass.py
   pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rpbc.py
   pypy/branch/less-meta-instances/pypy/rpython/rpbc.py
Log:
(antocuni, arigo, niko earlier) In-progress.


Modified: pypy/branch/less-meta-instances/pypy/annotation/description.py
==============================================================================
--- pypy/branch/less-meta-instances/pypy/annotation/description.py	(original)
+++ pypy/branch/less-meta-instances/pypy/annotation/description.py	Fri Apr  4 17:42:50 2008
@@ -466,6 +466,9 @@
         for name, value in cls.__dict__.items():
             self.add_source_attribute(name, value, mixin)
 
+    def getallclassdefs(self):
+        return self._classdefs.values()
+
     def getclassdef(self, key):
         try:
             return self._classdefs[key]

Modified: pypy/branch/less-meta-instances/pypy/rpython/lltypesystem/rpbc.py
==============================================================================
--- pypy/branch/less-meta-instances/pypy/rpython/lltypesystem/rpbc.py	(original)
+++ pypy/branch/less-meta-instances/pypy/rpython/lltypesystem/rpbc.py	Fri Apr  4 17:42:50 2008
@@ -373,6 +373,8 @@
         v_inst1 = hop.gendirectcall(ll_instantiate, vtypeptr)
         return hop.genop('cast_pointer', [v_inst1], resulttype = r_instance)
 
+    def getlowleveltype(self):
+        return rclass.CLASSTYPE
 
 
 # ____________________________________________________________

Modified: pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/exceptiondata.py
==============================================================================
--- pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/exceptiondata.py	(original)
+++ pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/exceptiondata.py	Fri Apr  4 17:42:50 2008
@@ -26,8 +26,8 @@
         self.fn_raise_OSError    = self.make_raise_OSError(rtyper)        
 
     def make_exception_matcher(self, rtyper):
-        # ll_exception_matcher(real_exception_meta, match_exception_meta)
-        s_classtype = annmodel.SomeOOInstance(self.lltype_of_exception_type)
+        # ll_exception_matcher(real_exception_class, match_exception_class)
+        s_classtype = annmodel.SomeOOClass(ootype.ROOT)
         helper_fn = rtyper.annotate_helper_fn(rclass.ll_issubclass, [s_classtype, s_classtype])
         return helper_fn
 
@@ -63,7 +63,6 @@
         r_class = rclass.getclassrepr(rtyper, None)
         r_class.setup()
         default_excinst = ootype.new(self.lltype_of_exception_value)
-        default_excinst.meta = r_class.get_meta_instance()
 
         # build the table in order base classes first, subclasses last
         sortedtable = []

Modified: pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rclass.py
==============================================================================
--- pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rclass.py	(original)
+++ pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rclass.py	Fri Apr  4 17:42:50 2008
@@ -7,49 +7,52 @@
 from pypy.rpython.rclass import AbstractClassRepr, AbstractInstanceRepr, \
                                 getinstancerepr, getclassrepr, get_type_repr
 from pypy.rpython.ootypesystem import ootype
+from pypy.rpython.exceptiondata import standardexceptions
 from pypy.tool.pairtype import pairtype
 from pypy.tool.sourcetools import func_with_new_name
 
-CLASSTYPE = ootype.Instance("Object_meta", ootype.ROOT,
-        fields={"class_": ootype.Class})
-OBJECT = ootype.Instance("Object", ootype.ROOT,
-        fields={'meta': CLASSTYPE})
+OBJECT = ootype.Instance("Object", ootype.ROOT)
+META = ootype.Instance("Meta", ootype.ROOT,
+                       fields={"class_": ootype.Class})
 
 
 class ClassRepr(AbstractClassRepr):
     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)
-            base_type = self.rbase.lowleveltype
-            self.lowleveltype = ootype.Instance(
-                    self.classdef.name + "_meta", base_type)
+            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:
-            # we are ROOT
-            self.lowleveltype = CLASSTYPE
+            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 _setup_repr(self):
-        clsfields = {}
         pbcfields = {}
-        if self.classdef is not None:
+        if self.lowleveltype != ootype.Class:
             # 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, {})
@@ -61,18 +64,20 @@
             
             self.rbase.setup()
             ootype.addFields(self.lowleveltype, dict(llfields))
-        #self.clsfields = clsfields
         self.pbcfields = pbcfields
         self.meta_instance = None
  
     def get_meta_instance(self, cast_to_root_meta=True):
+        if self.lowleveltype == ootype.Class:
+            raise TyperError("no meta-instance for class %r" % 
+                             (self.classdef,))
         if self.meta_instance is None:
             self.meta_instance = ootype.new(self.lowleveltype) 
             self.setup_meta_instance(self.meta_instance, self)
         
         meta_instance = self.meta_instance
         if cast_to_root_meta:
-            meta_instance = ootype.ooupcast(CLASSTYPE, meta_instance)
+            meta_instance = ootype.ooupcast(META, meta_instance)
         return meta_instance
 
     def setup_meta_instance(self, meta_instance, rsubcls):
@@ -88,14 +93,6 @@
                 llvalue = r.convert_desc_or_const(value)
                 setattr(meta_instance, mangled_name, llvalue)
 
-            #mro = list(rsubcls.classdef.getmro())
-            #for fldname in self.clsfields:
-            #    mangled_name, r = self.clsfields[fldname]
-            #    if r.lowleveltype is Void:
-            #        continue
-            #    value = rsubcls.classdef.classdesc.read_attribute(fldname, None)
-            #    if value is not None:
-            #        assign(mangled_name, value)
             # extra PBC attributes
             for (access_set, attr), (mangled_name, r) in self.pbcfields.items():
                 if rsubcls.classdef.classdesc not in access_set.descs:
@@ -107,15 +104,20 @@
                     assign(mangled_name, attrvalue)
 
             # then initialize the 'super' portion of the vtable
-            meta_instance_super = ootype.ooupcast(
-                    self.rbase.lowleveltype, meta_instance)
-            self.rbase.setup_meta_instance(meta_instance_super, rsubcls)
+            self.rbase.setup_meta_instance(meta_instance, rsubcls)
 
     getruntime = get_meta_instance
     
     def fromclasstype(self, vclass, llops):
-        return llops.genop('oodowncast', [vclass],
-                resulttype=self.lowleveltype)
+        assert ootype.isSubclass(vclass.concretetype, META)
+        if self.lowleveltype == ootype.Class:
+            c_class_ = inputconst(ootype.Void, 'class_')
+            return llops.genop('oogetfield', [vclass, c_class_],
+                    resulttype=ootype.Class)
+        else:
+            assert ootype.isSubclass(self.lowleveltype, vclass.concretetype)
+            return llops.genop('oodowncast', [vclass],
+                    resulttype=self.lowleveltype)
 
     def getpbcfield(self, vcls, access_set, attr, llops):
         if (access_set, attr) not in self.pbcfields:
@@ -127,12 +129,11 @@
 
     def rtype_issubtype(self, hop):
         class_repr = get_type_repr(self.rtyper)
-        vmeta1, vmeta2 = hop.inputargs(class_repr, class_repr)
-        return hop.gendirectcall(ll_issubclass, vmeta1, vmeta2)
+        vcls1, vcls2 = hop.inputargs(class_repr, class_repr)
+        return hop.genop('subclassof', [vcls1, vcls2], resulttype=ootype.Bool)
 
-def ll_issubclass(meta1, meta2):
-    class1 = meta1.class_
-    class2 = meta2.class_
+def ll_issubclass(class1, class2):
+    # helper for exceptiondata.py
     return ootype.subclassof(class1, class2)
 
 # ____________________________________________________________
@@ -237,7 +238,7 @@
                     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):
@@ -255,6 +256,12 @@
         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 mangled, (name, s_value) in allmethods.iteritems():
             methdescs = s_value.descriptions
             origin = dict([(methdesc.originclassdef, methdesc) for
@@ -329,7 +336,12 @@
         
         for mangled, (s_value, value) in self.classattributes.items():
             r = self.rtyper.getrepr(s_value)
-            m = self.attach_class_attr_accessor(mangled, value, r)
+            if value is None:
+                self.attach_abstract_class_attr_accessor(mangled,
+                                                         r.lowleveltype)
+            else:
+                oovalue = r.convert_desc_or_const(value)
+                self.attach_class_attr_accessor(mangled, oovalue)
 
         # step 4: do the same with instance fields whose default
         # values are overridden in subclasses. Not sure it's the best
@@ -359,21 +371,21 @@
 
         ootype.overrideDefaultForFields(self.lowleveltype, overridden_defaults)
 
-    def attach_class_attr_accessor(self, mangled, value, r_value):
+    def attach_abstract_class_attr_accessor(self, mangled, attrtype):
+        M = ootype.Meth([], attrtype)
+        m = ootype.meth(M, _name=mangled, abstract=True)
+        ootype.addMethods(self.lowleveltype, {mangled: m})
+
+    def attach_class_attr_accessor(self, mangled, oovalue):
         def ll_getclassattr(self):
             return oovalue
 
-        M = ootype.Meth([], r_value.lowleveltype)
-        if value is None:
-            m = ootype.meth(M, _name=mangled, abstract=True)
-        else:
-            oovalue = r_value.convert_desc_or_const(value)
-            ll_getclassattr = func_with_new_name(ll_getclassattr,
-                                                 'll_get_' + mangled)
-            graph = self.rtyper.annotate_helper(ll_getclassattr, [self.lowleveltype])
-            m = ootype.meth(M, _name=mangled, _callable=ll_getclassattr,
-                            graph=graph)
-
+        M = ootype.Meth([], ootype.typeOf(oovalue))
+        ll_getclassattr = func_with_new_name(ll_getclassattr,
+                                             'll_get_' + mangled)
+        graph = self.rtyper.annotate_helper(ll_getclassattr, [self.lowleveltype])
+        m = ootype.meth(M, _name=mangled, _callable=ll_getclassattr,
+                        graph=graph)
         ootype.addMethods(self.lowleveltype, {mangled: m})
 
     def get_ll_hash_function(self):
@@ -446,8 +458,7 @@
         if hop.args_s[0].can_be_none():
             return hop.gendirectcall(ll_inst_type, vinst)
         else:
-            cmeta = inputconst(ootype.Void, "meta")
-            return hop.genop('oogetfield', [vinst, cmeta], resulttype=CLASSTYPE)
+            return hop.genop('classof', [vinst], resulttype=ootype.Class)
 
     def null_instance(self):
         return ootype.null(self.lowleveltype)
@@ -463,10 +474,6 @@
         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 initialize_prebuilt_instance(self, value, classdef, result):
@@ -539,7 +546,7 @@
 
 def ll_inst_type(obj):
     if obj:
-        return obj.meta
+        return ootype.classof(obj)
     else:
         # type(None) -> NULL  (for now)
-        return ootype.null(CLASSTYPE)
+        return ootype.nullruntimeclass

Modified: pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rpbc.py
==============================================================================
--- pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rpbc.py	(original)
+++ pypy/branch/less-meta-instances/pypy/rpython/ootypesystem/rpbc.py	Fri Apr  4 17:42:50 2008
@@ -4,11 +4,12 @@
         AbstractFunctionsPBCRepr, AbstractMultipleUnrelatedFrozenPBCRepr, \
         none_frozen_pbc_repr
 from pypy.rpython.rclass import rtype_new_instance, getinstancerepr
+from pypy.rpython.rclass import getclassrepr, get_type_repr
 from pypy.rpython.rpbc import get_concrete_calltable
 from pypy.rpython import callparse
 from pypy.rpython.ootypesystem import ootype
 from pypy.rpython.ootypesystem.rclass import ClassRepr, InstanceRepr 
-from pypy.rpython.ootypesystem.rclass import mangle
+from pypy.rpython.ootypesystem.rclass import mangle, META
 from pypy.annotation import model as annmodel
 from pypy.annotation import description
 from pypy.tool.pairtype import pairtype
@@ -42,17 +43,24 @@
         
 class ClassesPBCRepr(AbstractClassesPBCRepr):
     
-    def _instantiate_runtime_class(self, hop, v_meta, r_instance):
+    def _instantiate_runtime_class(self, hop, v_class, r_instance):
         classdef = hop.s_result.classdef            
-        c_class_ = hop.inputconst(ootype.Void, "class_")
-        v_class = hop.genop('oogetfield', [v_meta, c_class_],
-                resulttype=ootype.Class)
         resulttype = getinstancerepr(hop.rtyper, classdef).lowleveltype
-        v_instance = hop.genop('runtimenew', [v_class], resulttype=resulttype)
-        c_meta = hop.inputconst(ootype.Void, "meta")
-        hop.genop('oosetfield', [v_instance, c_meta, v_meta],
-                resulttype=ootype.Void)
-        return v_instance
+        # convert v_class from META to ootype.Class if necessary:
+        v_class = get_type_repr(hop.rtyper).fromclasstype(v_class, hop.llops)
+        return hop.genop('runtimenew', [v_class], resulttype=resulttype)
+
+    def getlowleveltype(self):
+        classdescs = self.s_pbc.descriptions.keys()
+        # 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 row_method_name(methodname, rowname):

Modified: pypy/branch/less-meta-instances/pypy/rpython/rpbc.py
==============================================================================
--- pypy/branch/less-meta-instances/pypy/rpython/rpbc.py	(original)
+++ pypy/branch/less-meta-instances/pypy/rpython/rpbc.py	Fri Apr  4 17:42:50 2008
@@ -642,7 +642,7 @@
         if s_pbc.is_constant():
             self.lowleveltype = Void
         else:
-            self.lowleveltype = rtyper.type_system.rclass.CLASSTYPE
+            self.lowleveltype = self.getlowleveltype()
 
     def get_access_set(self, attrname):
         """Return the ClassAttrFamily corresponding to accesses to 'attrname'
@@ -774,8 +774,6 @@
         if r_clspbc.lowleveltype is Void:
             return inputconst(r_cls, r_clspbc.s_pbc.const)
         # convert from ptr-to-object-vtable to ptr-to-more-precise-vtable
-        assert (r_clspbc.lowleveltype ==
-            r_clspbc.rtyper.type_system.rclass.CLASSTYPE)
         return r_cls.fromclasstype(v, llops)
 
 class __extend__(pairtype(AbstractClassesPBCRepr, AbstractClassesPBCRepr)):


More information about the pypy-svn mailing list