[pypy-svn] r19650 - in pypy/branch/somepbc-refactoring/pypy: annotation translator translator/test

arigo at codespeak.net arigo at codespeak.net
Tue Nov 8 17:14:07 CET 2005


Author: arigo
Date: Tue Nov  8 17:14:04 2005
New Revision: 19650

Modified:
   pypy/branch/somepbc-refactoring/pypy/annotation/binaryop.py
   pypy/branch/somepbc-refactoring/pypy/annotation/bookkeeper.py
   pypy/branch/somepbc-refactoring/pypy/annotation/classdef.py
   pypy/branch/somepbc-refactoring/pypy/annotation/desc.py
   pypy/branch/somepbc-refactoring/pypy/annotation/model.py
   pypy/branch/somepbc-refactoring/pypy/annotation/unaryop.py
   pypy/branch/somepbc-refactoring/pypy/translator/annrpython.py
   pypy/branch/somepbc-refactoring/pypy/translator/test/test_annrpython.py
   pypy/branch/somepbc-refactoring/pypy/translator/transform.py
Log:
(mwh, pedronis, arigo)

Intermediate check-in.

Progressing slowly on the branch.  The Desc classes look nice so far,
probably because they don't worry about specialization yet :-/

(But Samuele is optimistic)


Modified: pypy/branch/somepbc-refactoring/pypy/annotation/binaryop.py
==============================================================================
--- pypy/branch/somepbc-refactoring/pypy/annotation/binaryop.py	(original)
+++ pypy/branch/somepbc-refactoring/pypy/annotation/binaryop.py	Tue Nov  8 17:14:04 2005
@@ -15,7 +15,6 @@
 from pypy.annotation.model import unionof, UnionError, set, missing_operation, TLS
 from pypy.annotation.model import add_knowntypedata, merge_knowntypedata
 from pypy.annotation.bookkeeper import getbookkeeper
-from pypy.annotation.classdef import isclassdef
 from pypy.objspace.flow.model import Variable
 
 # convenience only!
@@ -555,8 +554,8 @@
 
 class __extend__(pairtype(SomePBC, SomePBC)):
     def union((pbc1, pbc2)):       
-        d = pbc1.prebuiltinstances.copy()
-        d.update(pbc2.prebuiltinstances)
+        d = pbc1.descriptions.copy()
+        d.update(pbc2.descriptions)
         return SomePBC(d, can_be_None = pbc1.can_be_None or pbc2.can_be_None)
 
 class __extend__(pairtype(SomeImpossibleValue, SomeObject)):

Modified: pypy/branch/somepbc-refactoring/pypy/annotation/bookkeeper.py
==============================================================================
--- pypy/branch/somepbc-refactoring/pypy/annotation/bookkeeper.py	(original)
+++ pypy/branch/somepbc-refactoring/pypy/annotation/bookkeeper.py	Tue Nov  8 17:14:04 2005
@@ -12,9 +12,10 @@
      SomeUnicodeCodePoint, SomeOOStaticMeth, s_None, \
      SomeLLADTMeth, SomeBool, SomeTuple, SomeOOClass, SomeImpossibleValue, \
      SomeList, SomeObject
-from pypy.annotation.classdef import ClassDef, isclassdef
+from pypy.annotation.classdef import ClassDef
 from pypy.annotation.listdef import ListDef, MOST_GENERAL_LISTDEF
 from pypy.annotation.dictdef import DictDef, MOST_GENERAL_DICTDEF
+from pypy.annotation import desc
 from pypy.interpreter.pycode import cpython_code_signature
 from pypy.interpreter.argument import Arguments, ArgErr
 from pypy.rpython.rarithmetic import r_uint
@@ -26,27 +27,6 @@
 
 from pypy.annotation.specialize import decide_callable
 
-class PBCAccessSet:
-    def __init__(self, obj):
-        self.objects = { obj: True }
-        self.read_locations = {}
-        self.attrs = {}
-        self.values = {}   # used in the typer 
-
-    def update(self, other):
-        self.objects.update(other.objects)
-        self.read_locations.update(other.read_locations)        
-        self.attrs.update(other.attrs)
-
-class PBCCallFamily:
-    def __init__(self, obj):
-        self.objects = { obj: True }
-        self.patterns = {}
-
-    def update(self, other):
-        self.objects.update(other.objects)
-        self.patterns.update(other.patterns)
-
 class Stats:
 
     def __init__(self, bookkeeper):
@@ -191,12 +171,8 @@
         # mapping position -> key, prev_result for specializations
         self.spec_callsite_keys_results = {}
 
-        self.pbc_maximal_access_sets = UnionFind(PBCAccessSet)
-        # can be precisely computed only at fix-point, see
-        # compute_at_fixpoint
-        self.pbc_maximal_call_families = None
-        self.pbc_callables = None
-        
+        self.pbc_maximal_access_sets = UnionFind(desc.AttrFamily)
+        self.pbc_maximal_call_families = UnionFind(desc.CallFamily)
         self.pbc_call_sites = {}
         self.emulated_pbc_calls = {}
 
@@ -225,21 +201,21 @@
         del self.position_key
 
     def compute_at_fixpoint(self):
-        if self.pbc_maximal_call_families is None:
-            self.pbc_maximal_call_families = UnionFind(PBCCallFamily)
-        if self.pbc_callables is None:
-            self.pbc_callables = {}
-
-        for (fn, block, i), shape in self.pbc_call_sites.iteritems():
-            spaceop = block.operations[i]
-            assert spaceop.opname in ('call_args', 'simple_call')
-            pbc = self.annotator.binding(spaceop.args[0], extquery=True)
-            self.consider_pbc_call(pbc, shape, spaceop)
-        self.pbc_call_sites = {}
-
-        for pbc, shape in self.emulated_pbc_calls.itervalues():
-            self.consider_pbc_call(pbc, shape)
-        self.emulated_pbc_calls = {}
+##        if self.pbc_maximal_call_families is None:
+##            ...
+##        if self.pbc_callables is None:
+##            self.pbc_callables = {}
+
+##        for (fn, block, i), shape in self.pbc_call_sites.iteritems():
+##            spaceop = block.operations[i]
+##            assert spaceop.opname in ('call_args', 'simple_call')
+##            pbc = self.annotator.binding(spaceop.args[0], extquery=True)
+##            self.consider_pbc_call(pbc, shape, spaceop)
+##        self.pbc_call_sites = {}
+
+##        for pbc, shape in self.emulated_pbc_calls.itervalues():
+##            self.consider_pbc_call(pbc, shape)
+##        self.emulated_pbc_calls = {}
 
         for cls in self.needs_hash_support.keys():
             for cls2 in self.needs_hash_support:
@@ -377,9 +353,7 @@
             if frozen:
                 result = SomePBC([self.getdesc(x)])
             else:
-                clsdef = self.getclassdef(x.__class__)
-                if x.__class__.__dict__.get('_annspecialcase_', '').endswith('ctr_location'):
-                    raise Exception, "encountered a pre-built mutable instance of a class needing specialization: %s" % x.__class__.__name__
+                clsdef = self.getuniqueclassdef(x.__class__)
                 if x not in self.seen_mutable: # avoid circular reflowing, 
                                                # see for example test_circular_mutable_getattr
                     self.seen_mutable[x] = True
@@ -405,17 +379,16 @@
         try:
             return self.descs[pyobj]
         except KeyError:
-            from pypy.annotation import desc
             if isinstance(pyobj, types.FunctionType):
-                result = desc.FunctionDesc(pyobj)
-            elif isintance(pyobj, (type, types.ClassType)):
-                result = desc.ClassDesc(pyobj)
+                result = desc.FunctionDesc(self, pyobj)
+            elif isinstance(pyobj, (type, types.ClassType)):
+                result = desc.ClassDesc(self, pyobj)
             elif isinstance(pyobj, types.MethodType):
                 if pyobj.im_self is None:   # unbound
-                    result = desc.FunctionDesc(pyobj.im_func)
+                    result = desc.FunctionDesc(self, pyobj.im_func)
                 elif (hasattr(pyobj.im_self, '_freeze_') and
                       pyobj.im_self._freeze_()):  # method of frozen
-                    result = desc.MethodOfFrozenDesc(
+                    result = desc.MethodOfFrozenDesc(self,
                         self.getdesc(pyobj.im_func),            # funcdesc
                         self.getdesc(pyobj.im_self))            # frozendesc
                 else: # regular method
@@ -425,7 +398,7 @@
             else:
                 # must be a frozen pre-built constant, but let's check
                 assert pyobj._freeze_()
-                result = desc.FrozenDesc(pyobj)
+                result = desc.FrozenDesc(self, pyobj)
                 cls = result.knowntype
                 if cls not in self.pbctypes:
                     self.pbctypes[cls] = True
@@ -439,8 +412,7 @@
         try:
             return self.methoddescs[funcdesc, classdef]
         except KeyError:
-            from pypy.annotation import desc
-            result = desc.MethodDesc(funcdesc, classdef)
+            result = desc.MethodDesc(self, funcdesc, classdef)
             self.methoddescs[funcdesc, classdef] = result
             return result
 
@@ -468,7 +440,7 @@
         elif t in EXTERNAL_TYPE_ANALYZERS:
             return SomeExternalObject(t)
         elif t.__module__ != '__builtin__' and t not in self.pbctypes:
-            classdef = self.getclassdef(t)
+            classdef = self.getuniqueclassdef(t)
             return SomeInstance(classdef)
         else:
             o = SomeObject()
@@ -480,29 +452,25 @@
         assert s_attr.is_constant()
         attr = s_attr.const
 
-        access_sets = self.pbc_maximal_access_sets
-        descs = pbc.prebuiltinstances.keys()
+        descs = pbc.descriptions.keys()
         if not descs:
             return SomeImpossibleValue()
         first = descs[0]
-
-        change, rep, access = access_sets.find(first)
-        for desc in descs:
-            change1, rep, access = access_sets.union(rep, desc)
-            change = change or change1
+        change = first.mergeattrfamilies(*descs[1:])
+        attrfamily = first.getattrfamily()
 
         position = self.position_key
-        access.read_locations[position] = True
+        attrfamily.read_locations[position] = True
 
         actuals = []
-        for desc in access.objects:
+        for desc in attrfamily.descs:
             actuals.append(desc.s_read_attribute(attr))
         s_result = unionof(*actuals)
 
-        access.attrs[attr] = s_result
+        attrfamily.attrs[attr] = s_result
 
         if change:
-            for position in access.read_locations:
+            for position in attrfamily.read_locations:
                 self.annotator.reflowfromposition(position)
                 
         return s_result
@@ -551,8 +519,29 @@
                     dontcare, rep, callfamily = call_families.union(rep, obj)
 
             callfamily.patterns.update({shape: True})
- 
-    def pbc_call(self, pbc, args, implicit_init=False, emulated=None):
+
+    def pbc_call(self, pbc, args):
+        """Analyse a call to a SomePBC() with the given args (list of
+        annotations).
+        """
+        descs = pbc.descriptions.keys()
+        if not descs:
+            return SomeImpossibleValue()
+        first = descs[0]
+        first.mergecallfamilies(*descs[1:])
+        callfamily = first.getcallfamily()
+
+        def schedule(graph, inputcells):
+            whence = self.position_key
+            return self.annotator.recursivecall(graph, whence, inputcells)
+
+        results = []
+        for desc in descs:
+            results.append(desc.pycall(schedule, args))
+        s_result = unionof(*results)
+        return s_result
+
+    def DISABLED_pbc_call(self, pbc, args, implicit_init=False, emulated=None):
         if not implicit_init and not emulated:
             fn, block, i = self.position_key
             assert block.operations[i].opname in ('call_args', 'simple_call')
@@ -765,8 +754,9 @@
 
         return r
 
-    def ondegenerated(self, what, s_value, where=None, called_from=None):
-        self.annotator.ondegenerated(what, s_value, where=where, called_from=called_from)
+    def ondegenerated(self, what, s_value, where=None, called_from_graph=None):
+        self.annotator.ondegenerated(what, s_value, where=where,
+                                     called_from_graph=called_from_graph)
         
     def whereami(self):
         return self.annotator.whereami(self.position_key)

Modified: pypy/branch/somepbc-refactoring/pypy/annotation/classdef.py
==============================================================================
--- pypy/branch/somepbc-refactoring/pypy/annotation/classdef.py	(original)
+++ pypy/branch/somepbc-refactoring/pypy/annotation/classdef.py	Tue Nov  8 17:14:04 2005
@@ -6,6 +6,7 @@
 from types import FunctionType
 from pypy.annotation.model import SomeImpossibleValue, SomePBC, unionof
 from pypy.annotation.model import SomeInteger, isdegenerated
+from pypy.annotation.desc import MethodDesc
 
 
 # The main purpose of a ClassDef is to collect information about class/instance
@@ -119,8 +120,8 @@
         if isinstance(s_newvalue, SomePBC):
             attr = self.name
             meth = False
-            for func, classdef  in s_newvalue.prebuiltinstances.items():
-                if isclassdef(classdef):
+            for desc in s_newvalue.descriptions:
+                if isinstance(desc, MethodDesc):
                     meth = True
                     break
             if meth and getattr(homedef.cls, attr, None) is None:
@@ -167,7 +168,7 @@
                 base = b1
         mixeddict.update(cls.__dict__)
 
-        self.basedef = bookkeeper.getclassdef(base)
+        self.basedef = bookkeeper.getuniqueclassdef(base)
         if self.basedef:
             self.basedef.subdefs[cls] = self
 
@@ -417,9 +418,6 @@
         else:
             return False
 
-def isclassdef(x):
-    return isinstance(x, ClassDef)
-
 # ____________________________________________________________
 
 FORCE_ATTRIBUTES_INTO_CLASSES = {

Modified: pypy/branch/somepbc-refactoring/pypy/annotation/desc.py
==============================================================================
--- pypy/branch/somepbc-refactoring/pypy/annotation/desc.py	(original)
+++ pypy/branch/somepbc-refactoring/pypy/annotation/desc.py	Tue Nov  8 17:14:04 2005
@@ -1,11 +1,40 @@
 import types
 from pypy.interpreter.pycode import cpython_code_signature
-from pypy.annotation.classdef import ClassDef
-from pypy.annotation import model as annmodel
+from pypy.interpreter.argument import ArgErr
 
 
+class CallFamily:
+    """A family of Desc objects that could be called from common call sites.
+    """
+    def __init__(self, desc):
+        self.descs = { desc: True }
+        self.patterns = {}    # set of "call shapes" in the sense of
+                              # pypy.interpreter.argument.Argument
+
+    def update(self, other):
+        self.descs.update(other.descs)
+        self.patterns.update(other.patterns)
+
+class AttrFamily:
+    """A family of Desc objects that have common 'getattr' sites.
+    """
+    def __init__(self, desc):
+        self.descs = { desc: True }
+        self.read_locations = {}     # set of position_keys
+        self.attrs = {}              # { attr: s_value }
+
+    def update(self, other):
+        self.descs.update(other.descs)
+        self.read_locations.update(other.read_locations)
+        self.attrs.update(other.attrs)
+
+# ____________________________________________________________
+
 class Desc(object):
-    pyobj = None   # non-None if there is an associated underlying Python obj
+    def __init__(self, bookkeeper, pyobj=None):
+        self.bookkeeper = bookkeeper
+        # 'pyobj' is non-None if there is an associated underlying Python obj
+        self.pyobj = pyobj
 
     def __repr__(self):
         pyobj = self.pyobj
@@ -13,23 +42,89 @@
             return object.__repr__(self)
         return '<%s for %r>' % (self.__class__.__name__, pyobj)
 
+    def getcallfamily(self):
+        """Get the CallFamily object."""
+        call_families = self.bookkeeper.pbc_maximal_call_families
+        _, _, callfamily = call_families.find(self)
+        return callfamily
+
+    def mergecallfamilies(self, *others):
+        """Merge the call families of the given Descs into one."""
+        call_families = self.bookkeeper.pbc_maximal_call_families
+        changed, rep, callfamily = call_families.find(self)
+        for desc in others:
+            changed1, rep, callfamily = call_families.union(rep, desc)
+            changed = changed or changed1
+        return changed
+
+    def getattrfamily(self):
+        """Get the AttrFamily object."""
+        access_sets = self.bookkeeper.pbc_maximal_access_sets
+        _, _, attrfamily = access_sets.find(self)
+        return attrfamily
+
+    def mergeattrfamilies(self, *others):
+        """Merge the attr families of the given Descs into one."""
+        access_sets = self.bookkeeper.pbc_maximal_access_sets
+        changed, rep, attrfamily = access_sets.find(self)
+        for desc in others:
+            changed1, rep, attrfamily = access_sets.union(rep, desc)
+            changed = changed or changed1
+        return changed
+
+    def bind(self, classdef):
+        return self
+
 
 class FunctionDesc(Desc):
     knowntype = types.FunctionType
     
-    def __init__(self, pyobj=None, signature=None):
-        self.pyobj = pyobj
+    def __init__(self, bookkeeper, pyobj=None,
+                 name=None, signature=None, defaults=None, graph=None):
+        super(FunctionDesc, self).__init__(bookkeeper, pyobj)
+        if name is None:
+            name = pyobj.func_name
         if signature is None:
             signature = cpython_code_signature(pyobj.func_code)
+        if defaults is None:
+            defaults = pyobj.func_defaults
+        self.name = name
         self.signature = signature
+        self.defaults = defaults or ()
+        self._graph = graph
+
+    def getgraph(self):  # for now
+        if self._graph is None:
+            translator = self.bookkeeper.annotator.translator
+            self._graph = translator.buildflowgraph(self.pyobj)
+        return self._graph
+
+    def parse_arguments(self, args):
+        defs_s = []
+        for x in self.defaults:
+            defs_s.append(self.bookkeeper.immutablevalue(x))
+        try:
+            inputcells = args.match_signature(self.signature, defs_s)
+        except ArgErr, e:
+            raise TypeError, "signature mismatch: %s" % e.getmsg(args, self.name)
+        return inputcells
+
+    def pycall(self, schedule, args):
+        inputcells = self.parse_arguments(args)
+        graph = self.getgraph()
+        s_result = schedule(graph, inputcells)
+        return s_result
+
+    def bind(self, classdef):
+        # XXX static methods
+        return self.bookkeeper.getmethoddesc(self, classdef)
 
 
 class ClassDesc(Desc):
     knowntype = type
 
     def __init__(self, bookkeeper, pyobj, specialize=None):
-        self.bookkeeper = bookkeeper
-        self.pyobj = pyobj
+        super(ClassDesc, self).__init__(bookkeeper, pyobj)
         self.name = pyobj.__module__ + '.' + pyobj.__name__
         if specialize is None:
             tag = pyobj.__dict__.get('_annspecialcase_', '')
@@ -42,17 +137,37 @@
             raise Exception("not supported on class %r because it needs "
                             "specialization" % (self.name,))
         if self._classdef is None:
+            from pypy.annotation.classdef import ClassDef
             classdef = ClassDef(self.pyobj, self.bookkeeper)
             self.bookkeeper.classdefs.append(classdef)
             self._classdef = classdef
             classdef.setup()
         return self._classdef
 
+    def pycall(self, schedule, args):
+        from pypy.annotation.model import SomeInstance
+        classdef = self.getuniqueclassdef()
+        s_instance = SomeInstance(classdef)
+        init = getattr(self.pyobj, '__init__', None)  # xxx
+        if init is not None and init != object.__init__:
+            # call the constructor
+            s_init = self.bookkeeper.immutablevalue(init)
+            args = args.prepend(s_instance)
+            s_init.call(args)
+        else:
+            try:
+                args.fixedunpack(0)
+            except ValueError:
+                raise Exception("default __init__ takes no argument"
+                                " (class %s)" % (self.name,))
+        return s_instance
+
 
 class MethodDesc(Desc):
     knowntype = types.MethodType
 
-    def __init__(self, funcdesc, classdef):
+    def __init__(self, bookkeeper, funcdesc, classdef):
+        super(MethodDesc, self).__init__(bookkeeper)
         self.funcdesc = funcdesc
         self.classdef = classdef
 
@@ -60,6 +175,16 @@
         return '<MethodDesc %r of %r>' % (self.funcdesc,
                                           self.classdef)
 
+    def pycall(self, schedule, args):
+        from pypy.annotation.model import SomeInstance
+        s_instance = SomeInstance(self.classdef)
+        args = args.prepend(s_instance)
+        return self.funcdesc.pycall(schedule, args)
+
+    def bind(self, classdef):
+        self.bookkeeper.warning("rebinding an already bound %r" % (self,))
+        return self.funcdesc.bind(classdef)
+
 
 def new_or_old_class(c):
     if hasattr(c, '__class__'):
@@ -67,12 +192,10 @@
     else:
         return type(c)
 
-
 class FrozenDesc(Desc):
 
     def __init__(self, bookkeeper, pyobj):
-        self.bookkeeper = bookkeeper
-        self.pyobj = pyobj
+        super(FrozenDesc, self).__init__(bookkeeper, pyobj)
         self.attributes = self.pyobj.__dict__.copy()
         self.knowntype = new_or_old_class(pyobj)
 
@@ -80,13 +203,15 @@
         if attr in self.attributes:
             return self.bookkeeper.immutablevalue(self.attributes[attr])
         else:
-            return annmodel.SomeImpossibleValue()
+            from pypy.annotation.model import s_ImpossibleValue
+            return s_ImpossibleValue
 
 
 class MethodOfFrozenDesc(Desc):
     knowntype = types.MethodType
 
-    def __init__(self, funcdesc, frozendesc):
+    def __init__(self, bookkeeper, funcdesc, frozendesc):
+        super(MethodOfFrozenDesc, self).__init__(bookkeeper)
         self.funcdesc = funcdesc
         self.frozendesc = frozendesc
 

Modified: pypy/branch/somepbc-refactoring/pypy/annotation/model.py
==============================================================================
--- pypy/branch/somepbc-refactoring/pypy/annotation/model.py	(original)
+++ pypy/branch/somepbc-refactoring/pypy/annotation/model.py	Tue Nov  8 17:14:04 2005
@@ -297,10 +297,10 @@
 class SomePBC(SomeObject):
     """Stands for a global user instance, built prior to the analysis,
     or a set of such instances."""
-    def __init__(self, prebuiltinstances, can_be_None=False):
-        # prebuiltinstances is a set of Desc instances.
-        prebuiltinstances = dict.fromkeys(prebuiltinstances)
-        self.prebuiltinstances = prebuiltinstances
+    def __init__(self, descriptions, can_be_None=False):
+        # descriptions is a set of Desc instances.
+        descriptions = dict.fromkeys(descriptions)
+        self.descriptions = descriptions
         self.can_be_None = can_be_None
         self.check()
         if self.isNone():
@@ -308,31 +308,31 @@
             self.const = None
         else:
             knowntype = reduce(commonbase,
-                               [x.knowntype for x in prebuiltinstances])
+                               [x.knowntype for x in descriptions])
             if knowntype == type(Exception):
                 knowntype = type
             if knowntype != object:
                 self.knowntype = knowntype
-            if len(prebuiltinstances) == 1:
-                desc, = prebuiltinstances
+            if len(descriptions) == 1:
+                # hack for the convenience of direct callers to SomePBC():
+                # only if there is a single object in descriptions
+                desc, = descriptions
                 if desc.pyobj is not None:
-                    # hack for the convenience of direct callers to SomePBC():
-                    # only if there is a single object in prebuiltinstances
                     self.const = desc.pyobj
 
     def check(self):
         # We check that the set only contains a single kind of Desc instance
         kinds = {}
-        for x in self.prebuiltinstances:
+        for x in self.descriptions:
             assert type(x).__name__.endswith('Desc')  # avoid import nightmares
             kinds[x.__class__] = True
         assert len(kinds) <= 1, (
             "mixing several kinds of PBCs: %r" % (kinds.keys(),))
-        assert self.prebuiltinstances or self.can_be_None, (
+        assert self.descriptions or self.can_be_None, (
             "use s_ImpossibleValue")
 
     def isNone(self):
-        return len(self.prebuiltinstances) == 0
+        return len(self.descriptions) == 0
 
     def can_be_none(self):
         return self.can_be_None
@@ -341,9 +341,9 @@
         if self.isNone():
             return s_ImpossibleValue
         else:
-            return SomePBC(self.prebuiltinstances, can_be_None=False)
+            return SomePBC(self.descriptions, can_be_None=False)
 
-    def fmt_prebuiltinstances(self, pbis):
+    def fmt_descriptions(self, pbis):
         if hasattr(self, 'const'):
             return None
         else:

Modified: pypy/branch/somepbc-refactoring/pypy/annotation/unaryop.py
==============================================================================
--- pypy/branch/somepbc-refactoring/pypy/annotation/unaryop.py	(original)
+++ pypy/branch/somepbc-refactoring/pypy/annotation/unaryop.py	Tue Nov  8 17:14:04 2005
@@ -10,7 +10,6 @@
      SomeExternalObject, SomeTypedAddressAccess, SomeAddress, \
      unionof, set, missing_operation, add_knowntypedata
 from pypy.annotation.bookkeeper import getbookkeeper
-from pypy.annotation.classdef import isclassdef
 from pypy.annotation import builtin
 
 from pypy.annotation.binaryop import _clone ## XXX where to put this?
@@ -502,39 +501,19 @@
     def setattr(pbc, s_attr, s_value):
         getbookkeeper().warning("setattr not wanted on %r" % (pbc,))
 
-    def call(pbc, args, implicit_init=False):
+    def call(pbc, args):
         bookkeeper = getbookkeeper()
-        return bookkeeper.pbc_call(pbc, args, implicit_init=implicit_init)
-
-        #bookkeeper = getbookkeeper()
-        #results = []
-        #for func, classdef in pbc.prebuiltinstances.items():
-        #    if isclassdef(classdef):
-        #        s_self = SomeInstance(classdef)
-        #        args1 = args.prepend(s_self)
-        #    else:
-        #        args1 = args
-        #    results.append(bookkeeper.pycall(func, args1))
-        #return unionof(*results)
+        return bookkeeper.pbc_call(pbc, args)
 
     def bindcallables(pbc, classdef):
         """ turn the callables in the given SomeCallable 'cal'
             into bound versions.
         """
-        d = {}
-        for func, value in pbc.prebuiltinstances.items():
-            if isinstance(func, FunctionType):
-                if isclassdef(value):
-                    getbookkeeper().warning("rebinding an already bound "
-                                            "method %r with %r" % (func, value))
-                d[func] = classdef
-            elif isinstance(func, staticmethod):
-                d[func.__get__(43)] = value
-            else:
-                d[func] = value
+        d = [desc.bind(classdef) for desc in pbc.descriptions]
         return SomePBC(d)
 
     def is_true_behavior(pbc):
+        FIXME_BY_THE_WAY
         outcome = None
         for c in pbc.prebuiltinstances:
             if c is not None and not bool(c):

Modified: pypy/branch/somepbc-refactoring/pypy/translator/annrpython.py
==============================================================================
--- pypy/branch/somepbc-refactoring/pypy/translator/annrpython.py	(original)
+++ pypy/branch/somepbc-refactoring/pypy/translator/annrpython.py	Tue Nov  8 17:14:04 2005
@@ -116,21 +116,9 @@
             raise TypeError, ("Variable or Constant instance expected, "
                               "got %r" % (variable,))
 
-    def getuserclasses(self):
-        """Return a set of known user classes."""
-        return self.bookkeeper.userclasses
-
     def getuserclassdefinitions(self):
         """Return a list of ClassDefs."""
-        return self.bookkeeper.userclasseslist
-
-    def getuserattributes(self, cls):
-        """Enumerate the attributes of the given user class, as Variable()s."""
-        clsdef = self.bookkeeper.userclasses[cls]
-        for attr, s_value in clsdef.attrs.items():
-            v = Variable(name=attr)
-            self.bindings[v] = s_value
-            yield v
+        return self.bookkeeper.classdefs
 
     def getpbcaccesssets(self):
         """Return mapping const obj -> PBCAccessSet"""
@@ -188,11 +176,10 @@
         # make sure that the return variables of all graphs is annotated
         if self.translator is not None:
             if self.added_blocks is not None:
-                newgraphs = [self.translator.flowgraphs[self.annotated[block]]
-                             for block in self.added_blocks]
+                newgraphs = [self.annotated[block] for block in self.added_blocks]
                 newgraphs = dict.fromkeys(newgraphs)
             else:
-                newgraphs = self.translator.flowgraphs.itervalues() #all of them
+                newgraphs = self.translator.graphs  #all of them
             for graph in newgraphs:
                 v = graph.getreturnvar()
                 if v not in self.bindings:

Modified: pypy/branch/somepbc-refactoring/pypy/translator/test/test_annrpython.py
==============================================================================
--- pypy/branch/somepbc-refactoring/pypy/translator/test/test_annrpython.py	(original)
+++ pypy/branch/somepbc-refactoring/pypy/translator/test/test_annrpython.py	Tue Nov  8 17:14:04 2005
@@ -33,6 +33,14 @@
 def somedict(s_key=annmodel.SomeObject(), s_value=annmodel.SomeObject()):
     return annmodel.SomeDict(DictDef(None, s_key, s_value))
 
+def graphof(a, func):
+    result = []
+    for graph in a.translator.graphs:
+        if getattr(graph, 'func', None) is func:
+            result.append(graph)
+    assert len(result) == 1
+    return result[0]
+
 
 class TestAnnotateTestCase:
     def setup_class(cls): 
@@ -223,11 +231,11 @@
         a = self.RPythonAnnotator()
         a.build_types(snippet._methodcall1, [int])
         # the user classes should have the following attributes:
-        classes = a.bookkeeper.userclasses
-        assert classes[snippet.F].attrs.keys() == ['m']
-        assert classes[snippet.G].attrs.keys() == ['m2']
-        assert classes[snippet.H].attrs.keys() == ['attr'] 
-        assert classes[snippet.H].about_attribute('attr') == (
+        getcdef = a.bookkeeper.getuniqueclassdef
+        assert getcdef(snippet.F).attrs.keys() == ['m']
+        assert getcdef(snippet.G).attrs.keys() == ['m2']
+        assert getcdef(snippet.H).attrs.keys() == ['attr'] 
+        assert getcdef(snippet.H).about_attribute('attr') == (
                           a.bookkeeper.immutablevalue(1))
 
     def DISABLED_test_knownkeysdict(self):
@@ -259,13 +267,13 @@
         a = self.RPythonAnnotator()
         s = a.build_types(snippet.with_more_init, [int, bool])
         # the user classes should have the following attributes:
-        classes = a.bookkeeper.userclasses
+        getcdef = a.bookkeeper.getuniqueclassdef
         # XXX on which class should the attribute 'a' appear?  We only
         #     ever flow WithInit.__init__ with a self which is an instance
         #     of WithMoreInit, so currently it appears on WithMoreInit.
-        assert classes[snippet.WithMoreInit].about_attribute('a') == (
+        assert getcdef(snippet.WithMoreInit).about_attribute('a') == (
                           annmodel.SomeInteger())
-        assert classes[snippet.WithMoreInit].about_attribute('b') == (
+        assert getcdef(snippet.WithMoreInit).about_attribute('b') == (
                           annmodel.SomeBool())
 
     def test_global_instance(self):
@@ -293,21 +301,16 @@
         #a.translator.simplify()
         # must return "yadda"
         assert s == a.bookkeeper.immutablevalue("yadda")
-        keys = a.translator.flowgraphs.keys()
-        keys.sort()
-        expected = [snippet.constant_result,
-                    snippet.forty_two,
-                    # and not snippet.never_called
-                    ]
-        expected.sort()
-        assert keys == expected
+        graphs = a.translator.graphs
+        assert len(graphs) == 2
+        assert graphs[0].func is snippet.constant_result
+        assert graphs[1].func is snippet.forty_two
         a.simplify()
         #a.translator.view()
 
     def test_flow_type_info(self):
         a = self.RPythonAnnotator()
         s = a.build_types(snippet.flow_type_info, [object])
-        a.translator.simplify()
         a.simplify()
         #a.translator.view()
         assert s.knowntype == int
@@ -335,7 +338,6 @@
     def test_flow_identity_info(self):
         a = self.RPythonAnnotator()
         s = a.build_types(snippet.flow_identity_info, [object, object])
-        a.translator.simplify()
         a.simplify()
         #a.translator.view()
         assert s == a.bookkeeper.immutablevalue((None, None))
@@ -377,7 +379,7 @@
 
     def test_isinstance_and_knowntype_data(self): 
         a = self.RPythonAnnotator()
-        x = annmodel.SomePBC({snippet.apbc: True}) 
+        x = a.bookkeeper.immutablevalue(snippet.apbc)
         s = a.build_types(snippet.isinstance_and_knowntype, [x]) 
         #a.simplify()
         #a.translator.view()
@@ -409,14 +411,13 @@
 
     def test_simple_slicing0(self):
         a = self.RPythonAnnotator()
-        s = a.build_types(snippet.simple_slice, [list])
-        g = a.translator.getflowgraph(snippet.simple_slice)
-        for thing in flatten(g):
-            if isinstance(thing, Block):
-                for op in thing.operations:
-                    if op.opname == "newslice":
-                        assert isinstance(a.binding(op.result),
-                                          annmodel.SomeSlice)
+        a.build_types(snippet.simple_slice, [list])
+        g = graphof(a, snippet.simple_slice)
+        for block in g.iterblocks():
+            for op in block.operations:
+                if op.opname == "newslice":
+                    assert isinstance(a.binding(op.result),
+                                      annmodel.SomeSlice)
 
     def test_simple_slicing(self):
         a = self.RPythonAnnotator()
@@ -540,8 +541,8 @@
     def test_bltin_code_frame_confusion(self):
         a = self.RPythonAnnotator()
         a.build_types(snippet.bltin_code_frame_confusion,[])
-        f_flowgraph = a.translator.getflowgraph(snippet.bltin_code_frame_f)
-        g_flowgraph = a.translator.getflowgraph(snippet.bltin_code_frame_g)
+        f_flowgraph = graphof(a, snippet.bltin_code_frame_f)
+        g_flowgraph = graphof(a, snippet.bltin_code_frame_g)
         # annotator confused by original bltin code/frame setup, we just get SomeObject here
         assert a.binding(f_flowgraph.getreturnvar()).__class__ is annmodel.SomeObject
         assert a.binding(g_flowgraph.getreturnvar()).__class__ is annmodel.SomeObject
@@ -549,8 +550,8 @@
     def test_bltin_code_frame_reorg(self):
         a = self.RPythonAnnotator()
         a.build_types(snippet.bltin_code_frame_reorg,[])
-        f_flowgraph = a.translator.getflowgraph(snippet.bltin_code_frame_f)
-        g_flowgraph = a.translator.getflowgraph(snippet.bltin_code_frame_g)
+        f_flowgraph = graphof(a, snippet.bltin_code_frame_f)
+        g_flowgraph = graphof(a, snippet.bltin_code_frame_g)
         assert isinstance(a.binding(f_flowgraph.getreturnvar()),
                             annmodel.SomeInteger)
         assert isinstance(a.binding(g_flowgraph.getreturnvar()),
@@ -565,7 +566,7 @@
         a = self.RPythonAnnotator()
         s = a.build_types(snippet.make_r, [int])
         assert s.knowntype == snippet.R
-        Rdef = a.getuserclasses()[snippet.R]
+        Rdef = a.bookkeeper.getuniqueclassdef(snippet.R)
         assert Rdef.attrs['r'].s_value.knowntype == snippet.R
         assert Rdef.attrs['n'].s_value.knowntype == int
         assert Rdef.attrs['m'].s_value.knowntype == int
@@ -575,8 +576,8 @@
         a = self.RPythonAnnotator()
         s = a.build_types(snippet.make_eo, [int])
         assert s.knowntype == snippet.B
-        Even_def = a.getuserclasses()[snippet.Even]
-        Odd_def = a.getuserclasses()[snippet.Odd]
+        Even_def = a.bookkeeper.getuniqueclassdef(snippet.Even)
+        Odd_def = a.bookkeeper.getuniqueclassdef(snippet.Odd)
         assert listitem(Even_def.attrs['x'].s_value).knowntype == snippet.Odd
         assert listitem(Even_def.attrs['y'].s_value).knowntype == snippet.Even
         assert listitem(Odd_def.attrs['x'].s_value).knowntype == snippet.Even
@@ -591,11 +592,11 @@
     def test_methodcall_is_precise(self):
         a = self.RPythonAnnotator()
         s = a.build_types(snippet.methodcall_is_precise, [bool])
-        classes = a.bookkeeper.userclasses
-        assert 'x' not in classes[snippet.CBase].attrs
-        assert (classes[snippet.CSub1].attrs['x'].s_value ==
+        getcdef = a.bookkeeper.getuniqueclassdef
+        assert 'x' not in getcdef(snippet.CBase).attrs
+        assert (getcdef(snippet.CSub1).attrs['x'].s_value ==
                 a.bookkeeper.immutablevalue(42))
-        assert (classes[snippet.CSub2].attrs['x'].s_value ==
+        assert (getcdef(snippet.CSub2).attrs['x'].s_value ==
                 a.bookkeeper.immutablevalue('world'))
         assert s == a.bookkeeper.immutablevalue(42)
 
@@ -896,7 +897,7 @@
         callables = a.getpbccallables()        
         call_families = a.getpbccallfamilies()
 
-        clsdef = lambda cls: a.getuserclasses()[cls]
+        clsdef = a.bookkeeper.getuniqueclassdef
 
         fc = lambda x: {(None, x): True}
         mc = lambda x: {(clsdef(x.im_class), x.im_func): True}
@@ -974,9 +975,9 @@
                         spec_alloc = spec_alloc.const
                         assert spec_alloc in callb
                         assert callb[spec_alloc] == {(None, spec_alloc): True}
-                        assert (a.binding(a.translator.getflowgraph(spec_alloc).getreturnvar()).knowntype 
+                        assert (a.binding(graphof(a, spec_alloc).getreturnvar()).knowntype 
                                 == spaceop.args[1].value)
-        traverse(visit, a.translator.getflowgraph(f))
+        traverse(visit, graphof(a, f))
 
     def test_assert_list_doesnt_lose_info(self):
         class T(object):
@@ -1085,7 +1086,7 @@
                 raise
         a = self.RPythonAnnotator()
         a.build_types(f, [dict])
-        fg = a.translator.getflowgraph(f)
+        fg = graphof(a, f)
         et, ev = fg.exceptblock.inputargs
         t = annmodel.SomeObject()
         t.knowntype = type
@@ -1102,7 +1103,7 @@
                 raise
         a = self.RPythonAnnotator()
         a.build_types(f, [dict])
-        fg = a.translator.getflowgraph(f)
+        fg = graphof(a, f)
         et, ev = fg.exceptblock.inputargs
         t = annmodel.SomeObject()
         t.knowntype = type
@@ -1138,7 +1139,7 @@
                     h()
         a = self.RPythonAnnotator()
         a.build_types(f, [int, list])
-        fg = a.translator.getflowgraph(f)
+        fg = graphof(a, f)
         et, ev = fg.exceptblock.inputargs
         t = annmodel.SomeObject()
         t.knowntype = type
@@ -1161,7 +1162,7 @@
                 h()
         a = self.RPythonAnnotator()
         a.build_types(f, [])
-        fg = a.translator.getflowgraph(f)
+        fg = graphof(a, f)
         et, ev = fg.exceptblock.inputargs
         t = annmodel.SomeObject()
         t.knowntype = type
@@ -1294,8 +1295,8 @@
                 witness2(x)
         a = self.RPythonAnnotator()
         s = a.build_types(f, [annmodel.SomeInteger(unsigned=True)])
-        wg1 = a.translator.getflowgraph(witness1)
-        wg2 = a.translator.getflowgraph(witness2)        
+        wg1 = graphof(a, witness1)
+        wg2 = graphof(a, witness2)        
         assert a.binding(wg1.getargs()[0]).unsigned is True
         assert a.binding(wg2.getargs()[0]).unsigned is True        
         
@@ -1445,7 +1446,7 @@
             mutr(k, x, i)
         a = self.RPythonAnnotator()
         a.build_types(f, [bool, K,  int, int])
-        g = a.translator.getflowgraph(witness)
+        g = graphof(a, witness)
         assert a.binding(g.getargs()[0]).knowntype == int
 
     # check RPython static semantics of isinstance(x,bool|int) as needed for wrap

Modified: pypy/branch/somepbc-refactoring/pypy/translator/transform.py
==============================================================================
--- pypy/branch/somepbc-refactoring/pypy/translator/transform.py	(original)
+++ pypy/branch/somepbc-refactoring/pypy/translator/transform.py	Tue Nov  8 17:14:04 2005
@@ -18,8 +18,7 @@
 def checkgraphs(self, blocks):
     seen = {}
     for block in blocks:
-        fn = self.annotated[block]
-        graph = self.translator.flowgraphs[fn]
+        graph = self.annotated[block]
         if graph not in seen:
             checkgraph(graph)
             seen[graph] = True



More information about the Pypy-commit mailing list