[pypy-svn] r31481 - in pypy/dist/pypy: annotation rpython rpython/test

arigo at codespeak.net arigo at codespeak.net
Tue Aug 22 16:36:38 CEST 2006


Author: arigo
Date: Tue Aug 22 16:36:33 2006
New Revision: 31481

Modified:
   pypy/dist/pypy/annotation/annrpython.py
   pypy/dist/pypy/annotation/bookkeeper.py
   pypy/dist/pypy/rpython/extregistry.py
   pypy/dist/pypy/rpython/test/test_extregistry.py
Log:
(pedronis, arigo)

An extension to extregistry: you can pass a policy object to the various
lookup functions, and register entries with conditions based on the
policy.  See test.  Purpose: special-casing rgenop when compiling to C
on a specific processor; but this could also be used e.g. to select
between lltypesystem and ootypesystem versions of built-in functions.



Modified: pypy/dist/pypy/annotation/annrpython.py
==============================================================================
--- pypy/dist/pypy/annotation/annrpython.py	(original)
+++ pypy/dist/pypy/annotation/annrpython.py	Tue Aug 22 16:36:33 2006
@@ -54,16 +54,15 @@
         self.reflowcounter = {}
         self.return_bindings = {} # map return Variables to their graphs
         # --- end of debugging information ---
-        if bookkeeper is None:
-            bookkeeper = Bookkeeper(self)
-        self.bookkeeper = bookkeeper
         self.frozen = False
-        # user-supplied annotation logic for functions we don't want to flow into
         if policy is None:
             from pypy.annotation.policy import AnnotatorPolicy
             self.policy = AnnotatorPolicy()
         else:
             self.policy = policy
+        if bookkeeper is None:
+            bookkeeper = Bookkeeper(self)
+        self.bookkeeper = bookkeeper
 
     def __getstate__(self):
         attrs = """translator pendingblocks bindings annotated links_followed

Modified: pypy/dist/pypy/annotation/bookkeeper.py
==============================================================================
--- pypy/dist/pypy/annotation/bookkeeper.py	(original)
+++ pypy/dist/pypy/annotation/bookkeeper.py	Tue Aug 22 16:36:33 2006
@@ -156,6 +156,7 @@
 
     def __init__(self, annotator):
         self.annotator = annotator
+        self.policy = annotator.policy
         self.descs = {}          # map Python objects to their XxxDesc wrappers
         self.methoddescs = {}    # map (funcdesc, classdef) to the MethodDesc
         self.classdefs = []      # list of all ClassDefs
@@ -363,8 +364,9 @@
         elif ishashable(x) and x in BUILTIN_ANALYZERS:
             _module = getattr(x,"__module__","unknown")
             result = SomeBuiltin(BUILTIN_ANALYZERS[x], methodname="%s.%s" % (_module, x.__name__))
-        elif extregistry.is_registered(x):
-            result = extregistry.lookup(x).compute_annotation()
+        elif extregistry.is_registered(x, self.policy):
+            entry = extregistry.lookup(x, self.policy)
+            result = entry.compute_annotation_bk(self)
 ##        elif hasattr(x, "compute_result_annotation"):
 ##            result = SomeBuiltin(x.compute_result_annotation, methodname=x.__name__)
 ##        elif hasattr(tp, "compute_annotation"):
@@ -473,8 +475,9 @@
         elif ishashable(x) and x in BUILTIN_ANALYZERS:
             _module = getattr(x,"__module__","unknown")
             result = SomeBuiltin(BUILTIN_ANALYZERS[x], methodname="%s.%s" % (_module, x.__name__))
-        elif extregistry.is_registered(x):
-            result = extregistry.lookup(x).compute_annotation()
+        elif extregistry.is_registered(x, self.policy):
+            entry = extregistry.lookup(x, self.policy)
+            result = entry.compute_annotation_bk(self)
 ##        elif hasattr(x, "compute_result_annotation"):
 ##            result = SomeBuiltin(x.compute_result_annotation, methodname=x.__name__)
 ##        elif hasattr(tp, "compute_annotation"):
@@ -638,8 +641,9 @@
             return SomeExternalObject(t)
 ##        elif hasattr(t, "compute_annotation"):
 ##            return t.compute_annotation()
-        elif extregistry.is_registered_type(t):
-            return extregistry.lookup_type(t).compute_annotation()
+        elif extregistry.is_registered_type(t, self.policy):
+            entry = extregistry.lookup_type(t, self.policy)
+            return entry.compute_annotation_bk(self)
         elif t.__module__ != '__builtin__' and t not in self.pbctypes:
             classdef = self.getuniqueclassdef(t)
             return SomeInstance(classdef)

Modified: pypy/dist/pypy/rpython/extregistry.py
==============================================================================
--- pypy/dist/pypy/rpython/extregistry.py	(original)
+++ pypy/dist/pypy/rpython/extregistry.py	Tue Aug 22 16:36:33 2006
@@ -18,29 +18,45 @@
             selfcls._register_metatype(dict['_metatype_'])
             del selfcls._metatype_
 
-    def _register_value(selfcls, key):
+    def _register(selfcls, dict, key):
         if isinstance(key, tuple):
             for k in key:
-                selfcls._register_value(k)
+                selfcls._register(dict, k)
         else:
-            assert key not in EXT_REGISTRY_BY_VALUE
-            EXT_REGISTRY_BY_VALUE[key] = selfcls
+            for basecls in selfcls.__mro__:
+                if '_condition_' in basecls.__dict__:
+                    cond = basecls.__dict__['_condition_']
+                    break
+            else:
+                cond = None
+            try:
+                family = dict[key]
+            except KeyError:
+                family = dict[key] = ClassFamily()
+            family.add(selfcls, cond)
+
+    def _register_value(selfcls, key):
+        selfcls._register(EXT_REGISTRY_BY_VALUE, key)
 
     def _register_type(selfcls, key):
-        if isinstance(key, tuple):
-            for k in key:
-                selfcls._register_type(k)
-        else:
-            assert key not in EXT_REGISTRY_BY_TYPE
-            EXT_REGISTRY_BY_TYPE[key] = selfcls
+        selfcls._register(EXT_REGISTRY_BY_TYPE, key)
 
     def _register_metatype(selfcls, key):
-        if isinstance(key, tuple):
-            for k in key:
-                selfcls._register_metatype(k)
+        selfcls._register(EXT_REGISTRY_BY_METATYPE, key)
+
+class ClassFamily(object):
+
+    def __init__(self):
+        self.default = None
+        self.conditionals = []
+
+    def add(self, cls, cond=None):
+        if cond is None:
+            assert self.default is None, (
+                "duplicate extregistry entry %r" % (cls,))
+            self.default = cls
         else:
-            assert key not in EXT_REGISTRY_BY_METATYPE
-            EXT_REGISTRY_BY_METATYPE[key] = selfcls
+            self.conditionals.append((cls, cond))
 
 
 class ExtRegistryEntry(object):
@@ -64,6 +80,9 @@
     def __hash__(self):
         return hash((self.__class__, self.type, Hashable(self.instance)))
 
+    def compute_annotation_bk(self, bk):
+        return self.compute_annotation()
+
     def compute_annotation(self):
         # default implementation useful for built-in functions,
         # can be overriden
@@ -127,36 +146,49 @@
 # ____________________________________________________________
 # Public interface to access the registry
 
-def _lookup_type_cls(tp):
+def _lookup_from(dict, key, config):
+    family = dict[key]
+    if config is not None:
+        matches = [cls for cls, cond in family.conditionals
+                       if cond(config)]
+        if matches:
+            assert len(matches) == 1, "multiple extregistry matches: %r" % (
+                matches,)
+            return matches[0]
+    if family.default:
+        return family.default
+    raise KeyError(key)
+
+def _lookup_type_cls(tp, config):
     try:
-        return EXT_REGISTRY_BY_TYPE[tp]
+        return _lookup_from(EXT_REGISTRY_BY_TYPE, tp, config)
     except (KeyError, TypeError):
-        return EXT_REGISTRY_BY_METATYPE[type(tp)]
+        return _lookup_from(EXT_REGISTRY_BY_METATYPE, type(tp), config)
 
-def lookup_type(tp):
-    Entry = _lookup_type_cls(tp)
+def lookup_type(tp, config=None):
+    Entry = _lookup_type_cls(tp, config)
     return Entry(tp)
 
-def is_registered_type(tp):
+def is_registered_type(tp, config=None):
     try:
-        _lookup_type_cls(tp)
+        _lookup_type_cls(tp, config)
     except KeyError:
         return False
     return True
 
-def _lookup_cls(instance):
+def _lookup_cls(instance, config):
     try:
-        return EXT_REGISTRY_BY_VALUE[instance]
+        return _lookup_from(EXT_REGISTRY_BY_VALUE, instance, config)
     except (KeyError, TypeError):
-        return _lookup_type_cls(type(instance))
+        return _lookup_type_cls(type(instance), config)
 
-def lookup(instance):
-    Entry = _lookup_cls(instance)
+def lookup(instance, config=None):
+    Entry = _lookup_cls(instance, config)
     return Entry(type(instance), instance)
 
-def is_registered(instance):
+def is_registered(instance, config=None):
     try:
-        _lookup_cls(instance)
+        _lookup_cls(instance, config)
     except KeyError:
         return False
     return True

Modified: pypy/dist/pypy/rpython/test/test_extregistry.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_extregistry.py	(original)
+++ pypy/dist/pypy/rpython/test/test_extregistry.py	Tue Aug 22 16:36:33 2006
@@ -177,3 +177,26 @@
         _about_ = n1
     assert isinstance(extregistry.lookup(n1), Entry)
     assert isinstance(extregistry.lookup(n2), Entry)
+
+def test_condition():
+    stuff = object()
+    class Entry(ExtRegistryEntry):
+        _about_ = stuff
+        _condition_ = lambda n: n == 'yes'
+    assert isinstance(extregistry.lookup(stuff, 'yes'), Entry)
+    py.test.raises(KeyError, "extregistry.lookup(stuff, 'no')")
+    py.test.raises(KeyError, "extregistry.lookup(stuff)")
+
+    class Entry2(ExtRegistryEntry):
+        _about_ = stuff
+    assert isinstance(extregistry.lookup(stuff, 'yes'), Entry)
+    assert isinstance(extregistry.lookup(stuff, 'no'), Entry2)
+    assert isinstance(extregistry.lookup(stuff), Entry2)
+
+    otherstuff = object()
+    class Entry3(Entry):
+        _about_ = otherstuff
+        # _condition_ is inherited from Entry
+    assert isinstance(extregistry.lookup(otherstuff, 'yes'), Entry3)
+    py.test.raises(KeyError, "extregistry.lookup(otherstuff, 'no')")
+    py.test.raises(KeyError, "extregistry.lookup(otherstuff)")



More information about the Pypy-commit mailing list