[pypy-svn] r36773 - in pypy/dist/pypy: rpython/ootypesystem rpython/ootypesystem/test rpython/test translator/cli translator/js translator/jvm/test

antocuni at codespeak.net antocuni at codespeak.net
Mon Jan 15 13:00:45 CET 2007


Author: antocuni
Date: Mon Jan 15 13:00:35 2007
New Revision: 36773

Modified:
   pypy/dist/pypy/rpython/ootypesystem/ootype.py
   pypy/dist/pypy/rpython/ootypesystem/rclass.py
   pypy/dist/pypy/rpython/ootypesystem/test/test_ootype.py
   pypy/dist/pypy/rpython/test/test_rclass.py
   pypy/dist/pypy/translator/cli/class_.py
   pypy/dist/pypy/translator/js/_class.py
   pypy/dist/pypy/translator/jvm/test/test_class.py
Log:
Fix an ootypesystem bug that prevented the thunk object space to run
with gencli:

  - add support for overridden default values for fields to
    ootype.Instance

  - add logic that detect overridden default values on
    ootypesystem/rclass

  - fix gencli and genjs to cope with the new concept of overridden
    default values

  - skip the new test in genjvm because it's not trivial to fix it



Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/ootype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/ootype.py	Mon Jan 15 13:00:35 2007
@@ -57,6 +57,7 @@
 
         self._methods = frozendict()
         self._fields = frozendict()
+        self._overridden_defaults = frozendict()
 
         self._add_fields(fields)
         self._add_methods(methods)
@@ -115,6 +116,13 @@
 
         self._fields.update(fields)
 
+    def _override_default_for_fields(self, fields):
+        # sanity check
+        for field in fields:
+            INST, TYPE = self._superclass._lookup_field(field)
+            assert TYPE is not None, "Can't find field %s in superclasses" % field
+        self._overridden_defaults.update(fields)
+
     def _add_methods(self, methods):
         # Note to the unwary: _add_methods adds *methods* whereas
         # _add_fields adds *descriptions* of fields.  This is obvious
@@ -134,6 +142,9 @@
         for name, (ootype, default) in self._fields.iteritems():
             instance.__dict__[name] = enforce(ootype, default)
 
+        for name, (ootype, default) in self._overridden_defaults.iteritems():
+            instance.__dict__[name] = enforce(ootype, default)
+
     def _has_field(self, name):
         try:
             self._fields[name]
@@ -1380,6 +1391,9 @@
 def addMethods(INSTANCE, methods):
     INSTANCE._add_methods(methods)
 
+def overrideDefaultForFields(INSTANCE, fields):
+    INSTANCE._override_default_for_fields(fields)
+
 def runtimeClass(INSTANCE):
     assert isinstance(INSTANCE, Instance)
     return INSTANCE._class

Modified: pypy/dist/pypy/rpython/ootypesystem/rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rclass.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rclass.py	Mon Jan 15 13:00:35 2007
@@ -322,6 +322,34 @@
             r = self.rtyper.getrepr(s_value)
             m = self.attach_class_attr_accessor(mangled, value, r)
 
+        # step 4: do the same with instance fields whose default
+        # values are overridden in subclasses. Not sure it's the best
+        # way to do it.
+        overridden_defaults = {}
+
+        if self.classdef is not None:
+            for name, constant in self.classdef.classdesc.classdict.iteritems():
+                # look for the attrdef in the superclasses
+                classdef = self.classdef.basedef
+                attrdef = None
+                while classdef is not None:
+                    if name in classdef.attrs:
+                        attrdef = classdef.attrs[name]
+                        break
+                    classdef = classdef.basedef
+                if attrdef is not None and not attrdef.readonly:
+                    # it means that the default value for this field
+                    # is overridden in this subclass. Record we know
+                    # about it
+                    repr = self.rtyper.getrepr(attrdef.s_value)
+                    oot = repr.lowleveltype
+                    mangled = mangle(name)
+                    value = self.classdef.classdesc.read_attribute(name)
+                    default = repr.convert_desc_or_const(value)
+                    overridden_defaults[mangled] = oot, default
+
+        ootype.overrideDefaultForFields(self.lowleveltype, overridden_defaults)
+
     def attach_class_attr_accessor(self, mangled, value, r_value):
         def ll_getclassattr(self):
             return oovalue

Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/test/test_ootype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/test/test_ootype.py	Mon Jan 15 13:00:35 2007
@@ -74,6 +74,14 @@
 
     py.test.raises(TypeError, "Instance('test', ROOT, {'a': (Signed, 3.0)})")
 
+def test_overridden_default():
+    A = Instance("A", ROOT, {"a": (Signed, 3)})
+    B = Instance("B", A)
+    overrideDefaultForFields(B, {"a": (Signed, 5)})
+
+    b = new(B)e
+    assert b.a == 5
+
 def test_simple_null():
     C = Instance("test", ROOT, {"a": Signed})
 

Modified: pypy/dist/pypy/rpython/test/test_rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_rclass.py	(original)
+++ pypy/dist/pypy/rpython/test/test_rclass.py	Mon Jan 15 13:00:35 2007
@@ -115,6 +115,28 @@
         res = self.interpret(dummyfn, [])
         assert res == 13
 
+    def test_overridden_classattr_as_defaults(self):
+        class W_Root(object):
+            pass
+        class W_Thunk(W_Root):
+            pass
+
+        THUNK_PLACEHOLDER = W_Thunk()
+        W_Root.w_thunkalias = None
+        W_Thunk.w_thunkalias = THUNK_PLACEHOLDER
+
+        def dummyfn(x):
+            if x == 1:
+                t = W_Thunk()
+            elif x == 2:
+                t = W_Thunk()
+                t.w_thunkalias = W_Thunk()
+            else:
+                t = W_Root()
+            return t.w_thunkalias is THUNK_PLACEHOLDER
+        res = self.interpret(dummyfn, [1])
+        assert res == True
+
     def test_prebuilt_instance(self):
         a = EmptyBase()
         a.x = 5

Modified: pypy/dist/pypy/translator/cli/class_.py
==============================================================================
--- pypy/dist/pypy/translator/cli/class_.py	(original)
+++ pypy/dist/pypy/translator/cli/class_.py	Mon Jan 15 13:00:35 2007
@@ -110,6 +110,7 @@
                            if ARG is not ootype.Void]
                 returntype = self.cts.lltype_to_cts(METH.RESULT)
                 ilasm.begin_function(m_name, arglist, returntype, False, 'virtual') #, 'abstract')
+                ilasm.add_comment('abstract method')
                 if isinstance(METH.RESULT, ootype.OOType):
                     ilasm.opcode('ldnull')
                 else:
@@ -127,7 +128,9 @@
         self.ilasm.opcode('ldarg.0')
         self.ilasm.call('instance void %s::.ctor()' % self.get_base_class())
         # set default values for fields
-        for f_name, (F_TYPE, f_default) in self.INSTANCE._fields.iteritems():
+        default_values = self.INSTANCE._fields.copy()
+        default_values.update(self.INSTANCE._overridden_defaults)
+        for f_name, (F_TYPE, f_default) in default_values.iteritems():
             cts_type = self.cts.lltype_to_cts(F_TYPE)
             f_name = self.cts.escape_name(f_name)
             if cts_type != 'void':

Modified: pypy/dist/pypy/translator/js/_class.py
==============================================================================
--- pypy/dist/pypy/translator/js/_class.py	(original)
+++ pypy/dist/pypy/translator/js/_class.py	Mon Jan 15 13:00:35 2007
@@ -77,7 +77,9 @@
         self.db.record_class(self.classdef, self.name)
     
     def copy_class_attributes(self, ilasm):
-        for field_name, (field_type, field_value) in self.classdef._fields.items():
+        default_values = self.classdef._fields.copy()
+        default_values.update(self.classdef._overridden_defaults)
+        for field_name, (field_type, field_value) in default_values.iteritems():
             ilasm.load_str("this")
             self.db.load_const(field_type, field_value, ilasm)
             ilasm.set_field(None, field_name)

Modified: pypy/dist/pypy/translator/jvm/test/test_class.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/test/test_class.py	(original)
+++ pypy/dist/pypy/translator/jvm/test/test_class.py	Mon Jan 15 13:00:35 2007
@@ -4,7 +4,8 @@
 from pypy.rpython.test.test_rspecialcase import BaseTestRspecialcase
 
 class TestJvmClass(JvmTest, BaseTestRclass):    
-    pass
+    def test_overridden_classattr_as_defaults(self):
+        py.test.skip("JVM doesn't support overridden default value yet")
 
 #class TestCliSpecialCase(CliTest, BaseTestRspecialcase):
 #    pass



More information about the Pypy-commit mailing list