[pypy-svn] r23805 - in pypy/branch/rpython-ooclassattrs: . lltypesystem ootypesystem ootypesystem/test

nik at codespeak.net nik at codespeak.net
Wed Mar 1 01:59:53 CET 2006


Author: nik
Date: Wed Mar  1 01:59:39 2006
New Revision: 23805

Modified:
   pypy/branch/rpython-ooclassattrs/lltypesystem/lltype.py
   pypy/branch/rpython-ooclassattrs/ootypesystem/ootype.py
   pypy/branch/rpython-ooclassattrs/ootypesystem/rbuiltin.py
   pypy/branch/rpython-ooclassattrs/ootypesystem/rclass.py
   pypy/branch/rpython-ooclassattrs/ootypesystem/test/test_oopbc.py
   pypy/branch/rpython-ooclassattrs/rclass.py
   pypy/branch/rpython-ooclassattrs/rmodel.py
Log:
(pedronis, nik)
work-in-progress class attributes for ootypesystem.


Modified: pypy/branch/rpython-ooclassattrs/lltypesystem/lltype.py
==============================================================================
--- pypy/branch/rpython-ooclassattrs/lltypesystem/lltype.py	(original)
+++ pypy/branch/rpython-ooclassattrs/lltypesystem/lltype.py	Wed Mar  1 01:59:39 2006
@@ -64,6 +64,8 @@
     def __ne__(self, other):
         return not (self == other)
 
+    _is_compatible = __eq__
+
     def __hash__(self):
         # cannot use saferecursive() -- see test_lltype.test_hash().
         # NB. the __cached_hash should neither be used nor updated
@@ -1100,6 +1102,7 @@
     return result
 
 def isCompatibleType(TYPE1, TYPE2):
+    return TYPE1._is_compatible(TYPE2)
     return TYPE1 == TYPE2
 
 # mark type ADT methods

Modified: pypy/branch/rpython-ooclassattrs/ootypesystem/ootype.py
==============================================================================
--- pypy/branch/rpython-ooclassattrs/ootypesystem/ootype.py	(original)
+++ pypy/branch/rpython-ooclassattrs/ootypesystem/ootype.py	Wed Mar  1 01:59:39 2006
@@ -1,12 +1,23 @@
 from pypy.rpython.lltypesystem.lltype import LowLevelType, Signed, Unsigned, Float, Char
-from pypy.rpython.lltypesystem.lltype import Bool, Void, UniChar, typeOf, Primitive
-from pypy.rpython.lltypesystem.lltype import frozendict
+from pypy.rpython.lltypesystem.lltype import Bool, Void, UniChar, typeOf, \
+        Primitive, isCompatibleType
+from pypy.rpython.lltypesystem.lltype import frozendict, isCompatibleType
 
 class OOType(LowLevelType):
-    pass
+
+    def _is_compatible(TYPE1, TYPE2):
+        if TYPE1 == TYPE2:
+            return True
+        if isinstance(TYPE1, Instance) and isinstance(TYPE2, Instance):
+            return isSubclass(TYPE1, TYPE2)
+        else:
+            return False
 
 class Class(OOType):
-    pass
+
+    def _defl(self):
+        return nullruntimeclass
+    
 Class = Class()
 
 class Instance(OOType):
@@ -170,7 +181,7 @@
     def __setattr__(self, name, value):
         self.__getattr__(name)
             
-        if self._TYPE._field_type(name) != typeOf(value):
+        if not isCompatibleType(typeOf(value), self._TYPE._field_type(name)):
             raise TypeError("Expected type %r" % self._TYPE._field_type(name))
 
         self.__dict__[name] = value
@@ -333,14 +344,6 @@
         c = c._superclass
     return None
 
-def isCompatibleType(TYPE1, TYPE2):
-    if TYPE1 == TYPE2:
-        return True
-    if isinstance(TYPE1, Instance) and isinstance(TYPE2, Instance):
-        return isSubclass(TYPE1, TYPE2)
-    else:
-        return False
-        
 def ooupcast(INSTANCE, instance):
     assert instanceof(instance, INSTANCE)
     return instance

Modified: pypy/branch/rpython-ooclassattrs/ootypesystem/rbuiltin.py
==============================================================================
--- pypy/branch/rpython-ooclassattrs/ootypesystem/rbuiltin.py	(original)
+++ pypy/branch/rpython-ooclassattrs/ootypesystem/rbuiltin.py	Wed Mar  1 01:59:39 2006
@@ -40,7 +40,7 @@
 
     v_obj, v_cls = hop.inputargs(instance_repr, class_repr)
     if isinstance(v_cls, Constant):
-        c_cls = hop.inputconst(ootype.Void, v_cls.value._INSTANCE)
+        c_cls = hop.inputconst(ootype.Void, v_cls.value.class_._INSTANCE)
         return hop.genop('instanceof', [v_obj, c_cls], resulttype=ootype.Bool)
     else:
         raise TyperError("XXX missing impl of isinstance(x, variable)")

Modified: pypy/branch/rpython-ooclassattrs/ootypesystem/rclass.py
==============================================================================
--- pypy/branch/rpython-ooclassattrs/ootypesystem/rclass.py	(original)
+++ pypy/branch/rpython-ooclassattrs/ootypesystem/rclass.py	Wed Mar  1 01:59:39 2006
@@ -8,24 +8,122 @@
 from pypy.annotation.pairtype import pairtype
 from pypy.tool.sourcetools import func_with_new_name
 
-CLASSTYPE = ootype.Class
+CLASSTYPE = ootype.Instance("Object_meta", ootype.ROOT,
+        fields={"class_": ootype.Class})
+OBJECT = ootype.Instance("Object", ootype.ROOT,
+        fields={'meta': CLASSTYPE})
+
 
 class ClassRepr(AbstractClassRepr):
     def __init__(self, rtyper, classdef):
         AbstractClassRepr.__init__(self, rtyper, classdef)
 
-        self.lowleveltype = ootype.Class
+        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):
-        pass # not actually needed?
+        clsfields = {}
+        pbcfields = {}
+        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, counter in extra_access_sets.items():
+                for attr, s_value in access_set.attrs.items():
+                    r = self.rtyper.getrepr(s_value)
+                    mangled_name = mangle('pbc%d' % counter, attr)
+                    pbcfields[access_set, attr] = mangled_name, r
+                    llfields.append((mangled_name, r.lowleveltype))
+            
+            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.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)
+        return meta_instance
 
-    def getruntime(self):
-        return getinstancerepr(self.rtyper, self.classdef).lowleveltype._class
+    def setup_meta_instance(self, meta_instance, rsubcls):
+        if self.classdef is None:
+            rinstance = getinstancerepr(self.rtyper, rsubcls.classdef)
+            setattr(meta_instance, 'class_', rinstance.lowleveltype._class)
+        else:
+            # setup class attributes: for each attribute name at the level
+            # of 'self', look up its value in the subclass rsubcls
+            def assign(mangled_name, value):
+                if isinstance(value, Constant) and isinstance(value.value, staticmethod):
+                    value = Constant(value.value.__get__(42))   # staticmethod => bare function
+                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:
+                    continue   # only for the classes in the same pbc access set
+                if r.lowleveltype is Void:
+                    continue
+                attrvalue = rsubcls.classdef.classdesc.read_attribute(attr, None)
+                if attrvalue is not None:
+                    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)
+
+    getruntime = get_meta_instance
+    
+    #def getruntime(self):
+    #    return getinstancerepr(self.rtyper, self.classdef).lowleveltype._class
 
     def rtype_issubtype(self, hop):
         class_repr = get_type_repr(self.rtyper)
-        vlist = hop.inputargs(class_repr, class_repr)
-        return hop.genop('subclassof', vlist, resulttype=ootype.Bool)
+        vmeta1, vmeta2 = hop.inputargs(class_repr, class_repr)
+        return hop.gendirectcall(ll_issubtype, vmeta1, vmeta2)
+
+def ll_issubtype(meta1, meta2):
+    class1 = meta1.class_
+    class2 = meta2.class_
+    return ootype.subclassof(class1, class2)
 
 # ____________________________________________________________
 
@@ -45,14 +143,14 @@
 
         self.baserepr = None
         if self.classdef is None:
-            self.lowleveltype = ootype.ROOT
+            self.lowleveltype = OBJECT
         else:
             b = self.classdef.basedef
             if b is not None:
                 self.baserepr = getinstancerepr(rtyper, b)
                 b = self.baserepr.lowleveltype
             else:
-                b = ootype.ROOT
+                b = OBJECT
 
             self.lowleveltype = ootype.Instance(classdef.shortname, b, {}, {})
         self.prebuiltinstances = {}   # { id(x): (x, _ptr) }
@@ -259,7 +357,8 @@
         if hop.args_s[0].can_be_none():
             return hop.gendirectcall(ll_inst_type, vinst)
         else:
-            return hop.genop('classof', [vinst], resulttype=ootype.Class)
+            cmeta = inputconst(ootype.Void, "meta")
+            return hop.genop('oogetfield', [vinst, cmeta], resulttype=CLASSTYPE)
 
     def rtype_hash(self, hop):
         if self.classdef is None:
@@ -305,15 +404,23 @@
 
     def new_instance(self, llops):
         """Build a new instance, without calling __init__."""
-
-        return llops.genop("new",
+        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, 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()
             elif mangled == '_hash_cache_': # hash() support
                 llattrvalue = hash(value)
             else:
@@ -370,7 +477,7 @@
 
 def ll_inst_type(obj):
     if obj:
-        return ootype.classof(obj)
+        return obj.meta
     else:
         # type(None) -> NULL  (for now)
-        return ootype.nullruntimeclass
+        return ootype.null(CLASSTYPE)

Modified: pypy/branch/rpython-ooclassattrs/ootypesystem/test/test_oopbc.py
==============================================================================
--- pypy/branch/rpython-ooclassattrs/ootypesystem/test/test_oopbc.py	(original)
+++ pypy/branch/rpython-ooclassattrs/ootypesystem/test/test_oopbc.py	Wed Mar  1 01:59:39 2006
@@ -64,3 +64,20 @@
     assert 3 == interpret(f1, [], type_system="ootype")
     assert 6 == interpret(f2, [], type_system="ootype")
 
+def test_classes_attribute():
+    class A: 
+        a = 3
+    class B(A): 
+        a = 2
+    def f(i):
+        if i == 1:
+            cls = B
+        else:
+            cls = A
+        instance = cls()
+        return cls.a
+    res = interpret(f, [0], type_system='ootype')
+    assert res == 3
+    res = interpret(f, [1], type_system='ootype')
+    assert res == 2
+

Modified: pypy/branch/rpython-ooclassattrs/rclass.py
==============================================================================
--- pypy/branch/rpython-ooclassattrs/rclass.py	(original)
+++ pypy/branch/rpython-ooclassattrs/rclass.py	Wed Mar  1 01:59:39 2006
@@ -71,7 +71,7 @@
             if self.classdef.commonbase(subclassdef) != self.classdef:
                 raise TyperError("not a subclass of %r: %r" % (
                     self.classdef.name, desc))
-        #
+        
         return getclassrepr(self.rtyper, subclassdef).getruntime()
 
     def convert_const(self, value):

Modified: pypy/branch/rpython-ooclassattrs/rmodel.py
==============================================================================
--- pypy/branch/rpython-ooclassattrs/rmodel.py	(original)
+++ pypy/branch/rpython-ooclassattrs/rmodel.py	Wed Mar  1 01:59:39 2006
@@ -4,7 +4,7 @@
 from pypy.objspace.flow.model import Constant
 from pypy.rpython.lltypesystem.lltype import \
      Void, Bool, Float, Signed, Char, UniChar, \
-     typeOf, LowLevelType, Ptr, PyObject
+     typeOf, LowLevelType, Ptr, PyObject, isCompatibleType
 from pypy.rpython.ootypesystem import ootype
 from pypy.rpython.error import TyperError, MissingRTypeOperation 
 
@@ -329,7 +329,7 @@
             realtype = typeOf(value)
         except (AssertionError, AttributeError):
             realtype = '???'
-        if realtype != lltype:
+        if not isCompatibleType(realtype, lltype):
             raise TyperError("inputconst(reqtype = %s, value = %s):\n"
                              "expected a %r,\n"
                              "     got a %r" % (reqtype, value,



More information about the Pypy-commit mailing list