[pypy-svn] r10538 - in pypy/dist/pypy: annotation tool translator/test

pedronis at codespeak.net pedronis at codespeak.net
Mon Apr 11 18:22:31 CEST 2005


Author: pedronis
Date: Mon Apr 11 18:22:31 2005
New Revision: 10538

Added:
   pypy/dist/pypy/tool/unionfind.py   (contents, props changed)
Modified:
   pypy/dist/pypy/annotation/bookkeeper.py
   pypy/dist/pypy/annotation/unaryop.py
   pypy/dist/pypy/translator/test/test_annrpython.py
Log:
first stab at keeping track of the maximal pbc sets for getattr accesses.

using a union-find datastructure (maybe it's overkill).

ignore, rep, access = bookeper.pbc_maximal_access_sets.find(const_obj)

will find the set and info for const_obj, access is an instance of PBCAccessSet in bookkeeper.py




Modified: pypy/dist/pypy/annotation/bookkeeper.py
==============================================================================
--- pypy/dist/pypy/annotation/bookkeeper.py	(original)
+++ pypy/dist/pypy/annotation/bookkeeper.py	Mon Apr 11 18:22:31 2005
@@ -13,9 +13,22 @@
 from pypy.interpreter.pycode import cpython_code_signature
 from pypy.interpreter.argument import ArgErr
 from pypy.tool.rarithmetic import r_uint
+from pypy.tool.unionfind import UnionFind
 
 import inspect, new
 
+class PBCAccessSet:
+    def __init__(self, obj):
+        self.objects = { obj: True }
+        self.read_locations = {}
+        self.attrs = {}
+
+    def update(self, other):
+        self.objects.update(other.objects)
+        self.read_locations.update(other.read_locations)        
+        self.attrs.update(other.attrs)
+
+
 class Bookkeeper:
     """The log of choices that have been made while analysing the operations.
     It ensures that the same 'choice objects' will be returned if we ask
@@ -33,6 +46,9 @@
         self.pbccache = {}
         self.pbctypes = {}
         self.seen_mutable = {}
+
+        self.pbc_maximal_access_sets = UnionFind(PBCAccessSet)
+        
         # import ordering hack
         global BUILTIN_ANALYZERS
         from pypy.annotation.builtin import BUILTIN_ANALYZERS
@@ -184,6 +200,34 @@
             o.knowntype = t
             return o
 
+    def pbc_getattr(self, pbc, s_attr):
+        assert s_attr.is_constant()
+        attr = s_attr.const
+
+        access_sets = self.pbc_maximal_access_sets
+        objects = pbc.prebuiltinstances.keys()
+
+        change, rep, access = access_sets.find(objects[0])
+        for obj in objects:
+            change1, rep, access = access_sets.union(rep, obj)
+            change = change or change1
+
+        access.attrs[attr] = True
+        position = self.position_key
+        access.read_locations[position] = True
+
+        actuals = []
+
+        for c in access.objects:
+            if hasattr(c, attr):
+                actuals.append(self.immutablevalue(getattr(c, attr)))
+
+        if change:
+            for position in access.read_locations:
+                self.annotator.reflowfromposition(position)
+                
+        return unionof(*actuals)        
+
     def pycall(self, func, args):
         if func is None:   # consider None as a NULL function pointer
             return SomeImpossibleValue()

Modified: pypy/dist/pypy/annotation/unaryop.py
==============================================================================
--- pypy/dist/pypy/annotation/unaryop.py	(original)
+++ pypy/dist/pypy/annotation/unaryop.py	Mon Apr 11 18:22:31 2005
@@ -298,17 +298,19 @@
 
     def getattr(pbc, s_attr):
         bookkeeper = getbookkeeper()
-        assert s_attr.is_constant()
-        attr = s_attr.const
-        actuals = []
-        for c in pbc.prebuiltinstances:
-            if hasattr(c, attr):
-                # force the attribute to be considered on the class
-                ##classdef = bookkeeper.getclassdef(new_or_old_class(c))
-                ##classdef.find_attribute(attr).getvalue()
-                # but only return the more precise result getattr(c, attr)
-                actuals.append(immutablevalue(getattr(c, attr)))
-        return unionof(*actuals)
+        return bookkeeper.pbc_getattr(pbc, s_attr)
+        
+##         assert s_attr.is_constant()
+##         attr = s_attr.const
+##         actuals = []
+##         for c in pbc.prebuiltinstances:
+##             if hasattr(c, attr):
+##                 # force the attribute to be considered on the class
+##                 ##classdef = bookkeeper.getclassdef(new_or_old_class(c))
+##                 ##classdef.find_attribute(attr).getvalue()
+##                 # but only return the more precise result getattr(c, attr)
+##                 actuals.append(immutablevalue(getattr(c, attr)))
+##         return unionof(*actuals)
 
     def setattr(pbc, s_attr, s_value):
         getbookkeeper().warning("setattr not wanted on %r" % (pbc,))

Added: pypy/dist/pypy/tool/unionfind.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/tool/unionfind.py	Mon Apr 11 18:22:31 2005
@@ -0,0 +1,60 @@
+
+# union-find impl, a info object is attached to the roots
+
+class UnionFind(object):
+
+    def __init__(self, info_factory):
+        self.link_to_parent = {}
+        self.weight = {}
+        self.info_factory = info_factory
+        self.root_info = {}
+
+    def find(self, obj):  # -> new_root, obj, info
+        if obj not in self.link_to_parent:
+            info = self.root_info[obj] = self.info_factory(obj)
+            self.weight[obj] = 1
+            self.link_to_parent[obj] = obj
+            return True, obj, info
+
+        to_root = [obj]
+        parent = self.link_to_parent[obj]
+        while parent is not to_root[-1]:
+            to_root.append(parent)
+            parent = self.link_to_parent[parent]
+
+        for obj in to_root:
+            self.link_to_parent[obj] = parent
+
+        return False, parent, self.root_info[parent]
+
+
+    def union(self, obj1, obj2): # -> not_noop, rep, info
+
+        new1, rep1, info1 = self.find(obj1)
+        new2, rep2, info2 = self.find(obj2)
+
+        if rep1 is rep2:
+            return new1 or new2, rep1, info1
+
+        w1 = self.weight[rep1]
+        w2 = self.weight[rep2]
+
+        w = w1 + w2
+
+        if w1 < w2:
+            rep1, rep2, info1, info2, = rep2, rep1, info2, info1
+
+        info1.update(info2)
+
+        self.link_to_parent[rep2] = rep1
+
+        del self.weight[rep2]
+        del self.root_info[rep2]
+
+        self.weight[rep1] = w
+        self.root_info[rep1] = info1
+
+        return True, rep1, info1
+        
+
+    

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	Mon Apr 11 18:22:31 2005
@@ -724,6 +724,51 @@
         s = a.build_types(f, [r_uint])
         assert s == annmodel.SomeInteger(nonneg = True, unsigned = True)
 
+    def test_pbc_getattr(self):
+        class C:
+            def __init__(self, v1, v2):
+                self.v2 = v2
+                self.v1 = v1
+
+            def _freeze_(self):
+                return True
+
+        c1 = C(1,'a')
+        c2 = C(2,'b')
+        c3 = C(3,'c')
+
+        def f1(l, c):
+            l.append(c.v1)
+        def f2(l, c):
+            l.append(c.v2)
+
+        def g():
+            l1 = []
+            l2 = []
+            f1(l1, c1)
+            f1(l1, c2)
+            f2(l2, c2)
+            f2(l2, c3)
+            return l1,l2
+
+        a = RPythonAnnotator()
+        s = a.build_types(g,[])
+        l1, l2 = s.items
+        assert l1.s_item.knowntype == int
+        assert l2.s_item.knowntype == str
+
+        ign, rep1,acc1 = a.bookkeeper.pbc_maximal_access_sets.find(c1)
+        ign, rep2,acc2 = a.bookkeeper.pbc_maximal_access_sets.find(c2)
+        ing, rep3,acc3 = a.bookkeeper.pbc_maximal_access_sets.find(c3)
+
+        assert rep1 is rep2 is rep3
+        assert acc1 is acc2 is acc3
+
+        assert len(acc1.objects) == 3
+        assert acc1.attrs == {'v1': True, 'v2': True}
+        
+        
+
 
 def g(n):
     return [0,1,2,n]



More information about the Pypy-commit mailing list