[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