[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