[pypy-svn] r9754 - in pypy/dist/pypy: annotation objspace objspace/flow objspace/flow/test translator/test

pedronis at codespeak.net pedronis at codespeak.net
Sun Mar 13 02:13:47 CET 2005


Author: pedronis
Date: Sun Mar 13 02:13:47 2005
New Revision: 9754

Modified:
   pypy/dist/pypy/annotation/bookkeeper.py
   pypy/dist/pypy/objspace/dummy.py
   pypy/dist/pypy/objspace/flow/objspace.py
   pypy/dist/pypy/objspace/flow/test/test_objspace.py
   pypy/dist/pypy/translator/test/test_annrpython.py
Log:
possible _freeze_ handling in flowspace + tests

test_circular_mutable_getattr fix

_freeze_ adaption for dummy



Modified: pypy/dist/pypy/annotation/bookkeeper.py
==============================================================================
--- pypy/dist/pypy/annotation/bookkeeper.py	(original)
+++ pypy/dist/pypy/annotation/bookkeeper.py	Sun Mar 13 02:13:47 2005
@@ -31,6 +31,7 @@
         self.cachespecializations = {}
         self.pbccache = {}
         self.pbctypes = {}
+        self.seen_mutable = {}
         # import ordering hack
         global BUILTIN_ANALYZERS
         from pypy.annotation.builtin import BUILTIN_ANALYZERS
@@ -120,8 +121,12 @@
                 return self.getpbc(x)
             else:
                 clsdef = self.getclassdef(x.__class__)
-                for attr in x.__dict__:
-                    clsdef.add_source_for_attribute(attr, x)
+                
+                if x not in self.seen_mutable: # avoid circular reflowing, 
+                                               # see for example test_circular_mutable_getattr
+                    for attr in x.__dict__:
+                        clsdef.add_source_for_attribute(attr, x) # can trigger reflowing
+                    self.seen_mutable[x] = True
                 return SomeInstance(clsdef)
         elif x is None:
             return self.getpbc(None)

Modified: pypy/dist/pypy/objspace/dummy.py
==============================================================================
--- pypy/dist/pypy/objspace/dummy.py	(original)
+++ pypy/dist/pypy/objspace/dummy.py	Sun Mar 13 02:13:47 2005
@@ -56,15 +56,19 @@
     def __init__(self, spec):
         self.spec = spec
 
+class BuiltinModule(Module):
+    def __init__(self, space):
+        Module.__init__(self, space, space.wrap('__builtin__'), space.wrap({}))
 
+    def pick_builtin(self, w_globals):
+        return self
+    
 class DummyObjSpace(ObjSpace):
 
     def __init__(self):
         """NOT_RPYTHON"""
-        self.builtin    = Module(self, self.wrap('__builtin__'), self.wrap({}))
-        def pick_builtin(w_globals):
-            return self.builtin
-        self.builtin.pick_builtin = pick_builtin
+        self.builtin    = BuiltinModule(self)
+
         self.sys    = Module(self, self.wrap('sys'), self.wrap({}))
         self.sys.recursionlimit = 1000
 
@@ -131,6 +135,8 @@
             return w_obj
         return w_obj.unwrap()
 
+    def _freeze_(self):
+        return True
 
 if __name__ == '__main__':
   dummy_space = DummyObjSpace()

Modified: pypy/dist/pypy/objspace/flow/objspace.py
==============================================================================
--- pypy/dist/pypy/objspace/flow/objspace.py	(original)
+++ pypy/dist/pypy/objspace/flow/objspace.py	Sun Mar 13 02:13:47 2005
@@ -148,6 +148,23 @@
         else:
             raise TypeError("not wrapped: " + repr(w_obj))
 
+    def unwrap_for_computation(self, w_obj):
+        obj = self.unwrap(w_obj)
+        to_check = obj
+        if hasattr(to_check, 'im_self'):
+            to_check = to_check.im_self
+        if (not isinstance(to_check, (type, types.ClassType)) and # classes/types are assumed immutable
+            hasattr(to_check, '__class__') and to_check.__class__.__module__ != '__builtin__'):
+            frozen = hasattr(to_check, '_freeze_') and to_check._freeze_()
+            if not frozen:
+                if self.concrete_mode:
+                    # xxx do we want some warning? notice that some stuff is harmless
+                    # like setitem(dict, 'n', mutable)
+                    pass
+                else: # cannot count on it not mutating at runtime!
+                    raise UnwrapException
+        return obj
+
     def interpclass_w(self, w_obj):
         obj = self.unwrap(w_obj)
         if isinstance(obj, BaseWrappable):
@@ -248,7 +265,7 @@
     
     def is_true(self, w_obj):
         try:
-            obj = self.unwrap(w_obj)
+            obj = self.unwrap_for_computation(w_obj)
         except UnwrapException:
             pass
         else:
@@ -398,7 +415,7 @@
             args = []
             for w_arg in args_w:
                 try:
-                    arg = self.unwrap(w_arg)
+                    arg = self.unwrap_for_computation(w_arg)
                 except UnwrapException:
                     break
                 else:

Modified: pypy/dist/pypy/objspace/flow/test/test_objspace.py
==============================================================================
--- pypy/dist/pypy/objspace/flow/test/test_objspace.py	(original)
+++ pypy/dist/pypy/objspace/flow/test/test_objspace.py	Sun Mar 13 02:13:47 2005
@@ -1,5 +1,5 @@
 import autopath
-from pypy.objspace.flow.model import Constant, Block, traverse
+from pypy.objspace.flow.model import Constant, Block, Link, Variable, traverse
 from pypy.interpreter.argument import Arguments
 from pypy.translator.simplify import simplify_graph
 
@@ -367,6 +367,88 @@
                     assert op.opname != 'mul', "mul should have disappeared"
         traverse(visitor, x)
 
+    #__________________________________________________________
+    def test_unfrozen_user_class1(self):
+        class C:
+            def __nonzero__(self):
+                return True
+        c = C()
+        def f():
+            if c:
+                return 1
+            else:
+                return 2
+        graph = self.codetest(f)
+
+        results = []
+        def visit(link):
+            if isinstance(link, Link):
+                if link.target == graph.returnblock:
+                    results.extend(link.args)
+        traverse(visit, graph)
+        assert len(results) == 2
+
+    def test_unfrozen_user_class2(self):
+        class C:
+            def __add__(self, other):
+                return 4
+        c = C()
+        d = C()
+        def f():
+            return c+d
+        graph = self.codetest(f)
+
+        results = []
+        def visit(link):
+            if isinstance(link, Link):
+                if link.target == graph.returnblock:
+                    results.extend(link.args)
+        traverse(visit, graph)
+        assert not isinstance(results[0], Constant)
+
+    def test_frozen_user_class1(self):
+        class C:
+            def __nonzero__(self):
+                return True
+            def _freeze_(self):
+                return True
+        c = C()
+        def f():
+            if c:
+                return 1
+            else:
+                return 2
+
+        graph = self.codetest(f)
+
+        results = []
+        def visit(link):
+            if isinstance(link, Link):
+                if link.target == graph.returnblock:
+                    results.extend(link.args)
+        traverse(visit, graph)
+        assert len(results) == 1
+
+    def test_frozen_user_class2(self):
+        class C:
+            def __add__(self, other):
+                return 4
+            def _freeze_(self):
+                return True
+        c = C()
+        d = C()
+        def f():
+            return c+d
+        graph = self.codetest(f)
+
+        results = []
+        def visit(link):
+            if isinstance(link, Link):
+                if link.target == graph.returnblock:
+                    results.extend(link.args)
+        traverse(visit, graph)
+        assert results == [Constant(4)]
+
 DATA = {'x': 5,
         'y': 6}
 

Modified: pypy/dist/pypy/translator/test/test_annrpython.py
==============================================================================
--- pypy/dist/pypy/translator/test/test_annrpython.py	(original)
+++ pypy/dist/pypy/translator/test/test_annrpython.py	Sun Mar 13 02:13:47 2005
@@ -613,6 +613,16 @@
         assert myobj.called
         assert s == annmodel.SomeInstance(a.bookkeeper.getclassdef(Stuff))
 
+    def test_circular_mutable_getattr(self):
+        class C:
+            pass
+        c = C()
+        c.x = c
+        def f():
+            return c.x
+        a = RPythonAnnotator()
+        s = a.build_types(f, [])
+        assert s.knowntype == C
 
 def g(n):
     return [0,1,2,n]



More information about the Pypy-commit mailing list