[pypy-svn] r26111 - in pypy/dist/pypy: annotation rpython rpython/lltypesystem rpython/memory/test rpython/rctypes rpython/rctypes/test rpython/rctypes/tool rpython/test tool

arigo at codespeak.net arigo at codespeak.net
Fri Apr 21 19:30:27 CEST 2006


Author: arigo
Date: Fri Apr 21 19:30:22 2006
New Revision: 26111

Added:
   pypy/dist/pypy/tool/instancemethod.py   (contents, props changed)
Modified:
   pypy/dist/pypy/annotation/bookkeeper.py
   pypy/dist/pypy/annotation/model.py
   pypy/dist/pypy/rpython/extregistry.py
   pypy/dist/pypy/rpython/lltypesystem/lloperation.py
   pypy/dist/pypy/rpython/lltypesystem/rclass.py
   pypy/dist/pypy/rpython/memory/test/test_gctransform.py
   pypy/dist/pypy/rpython/rctypes/aarray.py
   pypy/dist/pypy/rpython/rctypes/achar_p.py
   pypy/dist/pypy/rpython/rctypes/afunc.py
   pypy/dist/pypy/rpython/rctypes/apointer.py
   pypy/dist/pypy/rpython/rctypes/aprimitive.py
   pypy/dist/pypy/rpython/rctypes/apyobject.py
   pypy/dist/pypy/rpython/rctypes/astringbuf.py
   pypy/dist/pypy/rpython/rctypes/astruct.py
   pypy/dist/pypy/rpython/rctypes/avoid_p.py
   pypy/dist/pypy/rpython/rctypes/implementation.py
   pypy/dist/pypy/rpython/rctypes/test/test_rfunc.py
   pypy/dist/pypy/rpython/rctypes/tool/cpyobjspace.py
   pypy/dist/pypy/rpython/rgenop.py
   pypy/dist/pypy/rpython/test/test_extregistry.py
Log:
Refactored the extregistry interface.  See mail to pypy-dev.

This is a massive diff, mostly because all rctypes/a*.py are
entierely modified.  Tedious, but the result looks quite nicer
than before in my humble opinion.

The original motivation was a problem with annotating built-in
functions: the 'analyser' attribute cannot be a local function
with a closure, at least as used in rctypes, because
re-building another closure with exactly the same values in
the closure makes a non-equal function object.  Instead, in
the new extregistry world, this 'analyser' is a bound method
on an ExtRegistryEntry instance.

Tests showing this problem:
  * rctypes.test.test_rfunc.test_annotate_reflow_bug
  * targetdemomodule.py with the change in the cpyobjspace

I then remembered the hard way that CPython bound method instances don't
have a sane __eq__ either, so I bite the bullet and wrote a custom
InstanceMethod class to use as the 'analyser'...


Modified: pypy/dist/pypy/annotation/bookkeeper.py
==============================================================================
--- pypy/dist/pypy/annotation/bookkeeper.py	(original)
+++ pypy/dist/pypy/annotation/bookkeeper.py	Fri Apr 21 19:30:22 2006
@@ -358,7 +358,7 @@
             _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).get_annotation(tp, x)
+            result = extregistry.lookup(x).compute_annotation()
 ##        elif hasattr(x, "compute_result_annotation"):
 ##            result = SomeBuiltin(x.compute_result_annotation, methodname=x.__name__)
 ##        elif hasattr(tp, "compute_annotation"):
@@ -522,7 +522,7 @@
 ##        elif hasattr(t, "compute_annotation"):
 ##            return t.compute_annotation()
         elif extregistry.is_registered_type(t):
-            return extregistry.lookup_type(t).get_annotation(t)
+            return extregistry.lookup_type(t).compute_annotation()
         elif t.__module__ != '__builtin__' and t not in self.pbctypes:
             classdef = self.getuniqueclassdef(t)
             return SomeInstance(classdef)

Modified: pypy/dist/pypy/annotation/model.py
==============================================================================
--- pypy/dist/pypy/annotation/model.py	(original)
+++ pypy/dist/pypy/annotation/model.py	Fri Apr 21 19:30:22 2006
@@ -29,7 +29,7 @@
 
 
 from types import BuiltinFunctionType, MethodType, FunctionType
-import pypy
+import pypy.tool.instancemethod
 from pypy.annotation.pairtype import pair, extendabletype
 from pypy.tool.tls import tlsobject
 from pypy.rpython.rarithmetic import r_uint, r_longlong, r_ulonglong
@@ -388,6 +388,11 @@
     immutable = True
 
     def __init__(self, analyser, s_self=None, methodname=None):
+        if isinstance(analyser, MethodType):
+            analyser = pypy.tool.instancemethod.InstanceMethod(
+                analyser.im_func,
+                analyser.im_self,
+                analyser.im_class)
         self.analyser = analyser
         self.s_self = s_self
         self.methodname = methodname

Modified: pypy/dist/pypy/rpython/extregistry.py
==============================================================================
--- pypy/dist/pypy/rpython/extregistry.py	(original)
+++ pypy/dist/pypy/rpython/extregistry.py	Fri Apr 21 19:30:22 2006
@@ -3,25 +3,69 @@
 from pypy.tool.uid import Hashable
 
 
-class ExtRegistryFunc(object):
-    def __init__(self, compute_result_annotation, specialize_call):
-        self.compute_result_annotation = compute_result_annotation
-        self.specialize_call = specialize_call
-    
-    def get_annotation(self, type, func=None):
+class AutoRegisteringType(type):
+
+    def __init__(selfcls, name, bases, dict):
+        super(AutoRegisteringType, selfcls).__init__(selfcls,
+                                                     name, bases, dict)
+        if '_about_' in dict:
+            selfcls._register_value(dict['_about_'])
+            del selfcls._about_   # avoid keeping a ref
+        if '_type_' in dict:
+            selfcls._register_type(dict['_type_'])
+            del selfcls._type_
+        if '_metatype_' in dict:
+            selfcls._register_metatype(dict['_metatype_'])
+            del selfcls._metatype_
+
+    def _register_value(selfcls, key):
+        assert key not in EXT_REGISTRY_BY_VALUE
+        EXT_REGISTRY_BY_VALUE[key] = selfcls
+
+    def _register_type(selfcls, key):
+        assert key not in EXT_REGISTRY_BY_TYPE
+        EXT_REGISTRY_BY_TYPE[key] = selfcls
+
+    def _register_metatype(selfcls, key):
+        assert key not in EXT_REGISTRY_BY_METATYPE
+        EXT_REGISTRY_BY_METATYPE[key] = selfcls
+
+
+class ExtRegistryEntry(object):
+    __metaclass__ = AutoRegisteringType
+
+    def __init__(self, type, instance=None):
+        self.type = type
+        self.instance = instance
+
+    # structural equality, and trying hard to be hashable: Entry instances
+    # are used as keys to map annotations to Reprs in the rtyper.
+    # Warning, it's based on only 'type' and 'instance'.
+    def __eq__(self, other):
+        return (self.__class__ is other.__class__ and
+                self.type == other.type and
+                self.instance == other.instance)
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __hash__(self):
+        return hash((self.__class__, self.type, Hashable(self.instance)))
+
+    def compute_annotation(self):
+        # default implementation useful for built-in functions,
+        # can be overriden
+        func = self.instance
         assert func is not None
         from pypy.annotation import model as annmodel
-        return annmodel.SomeBuiltin(self.compute_result_annotation,
-                                    methodname=getattr(func, '__name__', None))
-
-class ExtRegistryInstance(object):
-    def __init__(self, compute_annotation, specialize_call, get_repr):
-        self.compute_annotation = compute_annotation
-        self.specialize_call = specialize_call
-        self.get_repr = get_repr
-    
-    def get_annotation(self, type, instance=None):
-        return self.compute_annotation(type, instance)
+        analyser = self.compute_result_annotation
+        methodname = getattr(func, '__name__', None)
+        return annmodel.SomeBuiltin(analyser, methodname=methodname)
+
+    def compute_result_annotation(self, *args_s, **kwds_s):
+        # default implementation for built-in functions with a constant
+        # result annotation, can be overriden
+        return self.s_result_annotation
 
 # ____________________________________________________________
 
@@ -68,64 +112,39 @@
 EXT_REGISTRY_BY_TYPE = weakref.WeakKeyDictionary()
 EXT_REGISTRY_BY_METATYPE = weakref.WeakKeyDictionary()
 
-def create_annotation_callable(annotation):
-    from pypy.annotation import model as annmodel
-    if isinstance(annotation, annmodel.SomeObject) or annotation is None:
-        s_result = annotation
-        def annotation(*args):
-            return s_result
-        
-    return annotation
-
-undefined = object()
-
-def create_entry(compute_result_annotation=undefined, compute_annotation=None,
-                 specialize_call=None, get_repr=None):
-    if compute_result_annotation is not undefined:
-        compute_result_annotation = create_annotation_callable(
-            compute_result_annotation)
-        return ExtRegistryFunc(compute_result_annotation, specialize_call)
-    else:
-        return ExtRegistryInstance(compute_annotation, specialize_call, 
-            get_repr)
-
-def register_value(value, **kwargs):
-    assert value not in EXT_REGISTRY_BY_VALUE
-    EXT_REGISTRY_BY_VALUE[value] = create_entry(**kwargs)
-    return EXT_REGISTRY_BY_VALUE[value]
-    
-def register_type(t, **kwargs):
-    assert t not in EXT_REGISTRY_BY_TYPE
-    EXT_REGISTRY_BY_TYPE[t] = create_entry(**kwargs)
-    return EXT_REGISTRY_BY_TYPE[t]
-    
-def register_metatype(t, **kwargs):
-    assert t not in EXT_REGISTRY_BY_METATYPE
-    EXT_REGISTRY_BY_METATYPE[t] = create_entry(**kwargs)
-    return EXT_REGISTRY_BY_METATYPE[t]
+# ____________________________________________________________
+# Public interface to access the registry
 
-def lookup_type(tp):
+def _lookup_type_cls(tp):
     try:
         return EXT_REGISTRY_BY_TYPE[tp]
     except (KeyError, TypeError):
         return EXT_REGISTRY_BY_METATYPE[type(tp)]
 
+def lookup_type(tp):
+    Entry = _lookup_type_cls(tp)
+    return Entry(tp)
+
 def is_registered_type(tp):
     try:
-        lookup_type(tp)
+        _lookup_type_cls(tp)
     except KeyError:
         return False
     return True
 
-def lookup(instance):
+def _lookup_cls(instance):
     try:
         return EXT_REGISTRY_BY_VALUE[instance]
     except (KeyError, TypeError):
-        return lookup_type(type(instance))
-        
+        return _lookup_type_cls(type(instance))
+
+def lookup(instance):
+    Entry = _lookup_cls(instance)
+    return Entry(type(instance), instance)
+
 def is_registered(instance):
     try:
-        lookup(instance)
+        _lookup_cls(instance)
     except KeyError:
         return False
     return True

Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lloperation.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py	Fri Apr 21 19:30:22 2006
@@ -2,7 +2,7 @@
 The table of all LL operations.
 """
 
-from pypy.rpython import extregistry
+from pypy.rpython.extregistry import ExtRegistryEntry
 
 
 class LLOp(object):
@@ -28,11 +28,6 @@
         # The operation manipulates PyObjects
         self.pyobj = pyobj
 
-        # XXX refactor extregistry to allow a single registration
-        extregistry.register_value(self,
-                compute_result_annotation = self.compute_result_annotation,
-                specialize_call           = self.specialize)
-
     # __________ make the LLOp instances callable from LL helpers __________
 
     __name__ = property(lambda self: 'llop_'+self.opname)
@@ -40,16 +35,6 @@
     def __call__(self, RESULTTYPE, *args):
         raise TypeError, "llop is meant to be rtyped and not called direclty"
 
-    def compute_result_annotation(self, RESULTTYPE, *args):
-        from pypy.annotation.model import lltype_to_annotation
-        assert RESULTTYPE.is_constant()
-        return lltype_to_annotation(RESULTTYPE.const)
-
-    def specialize(self, hop):
-        args_v = [hop.inputarg(r, i+1) for i, r in enumerate(hop.args_r[1:])]
-        hop.exception_is_here()
-        return hop.genop(self.opname, args_v, resulttype=hop.r_result.lowleveltype)
-
 
 def enum_ops_without_sideeffects(raising_is_ok=False):
     """Enumerate operations that have no side-effects
@@ -66,6 +51,22 @@
             if not opdesc.canraise or raising_is_ok:
                 yield opname
 
+
+class Entry(ExtRegistryEntry):
+    "Annotation and rtyping of LLOp instances, which are callable."
+    _type_ = LLOp
+
+    def compute_result_annotation(self, RESULTTYPE, *args):
+        from pypy.annotation.model import lltype_to_annotation
+        assert RESULTTYPE.is_constant()
+        return lltype_to_annotation(RESULTTYPE.const)
+
+    def specialize_call(self, hop):
+        op = self.instance    # the LLOp object that was called
+        args_v = [hop.inputarg(r, i+1) for i, r in enumerate(hop.args_r[1:])]
+        hop.exception_is_here()
+        return hop.genop(op.opname, args_v, resulttype=hop.r_result.lowleveltype)
+
 # ____________________________________________________________
 #
 # This list corresponds to the operations implemented by the LLInterpreter.

Modified: pypy/dist/pypy/rpython/lltypesystem/rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rclass.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rclass.py	Fri Apr 21 19:30:22 2006
@@ -18,7 +18,7 @@
      Array, Char, Void, attachRuntimeTypeInfo, \
      FuncType, Bool, Signed, functionptr, FuncType, PyObject
 from pypy.rpython.robject import PyObjRepr, pyobj_repr
-from pypy.rpython import extregistry
+from pypy.rpython.extregistry import ExtRegistryEntry
 from pypy.annotation import model as annmodel
 
 #
@@ -602,18 +602,21 @@
 def ll_call_destructor(thang, repr):
     return 42 # will be mapped
 
-def rtype_destruct_object(hop):
-    v_inst, c_spec = hop.inputargs(*hop.args_r)
-    repr = c_spec.value
-    if repr.has_wrapper:
-        null = hop.inputconst(Ptr(PyObject), nullptr(PyObject))
-        # XXX this is a hack! We need an operation to remove a broken PyObject
-        repr.setfield(v_inst, '_wrapper_', null, hop.llops, opname='bare_setfield')
-    hop.genop('gc_unprotect', [v_inst])
-
-extregistry.register_value(ll_call_destructor, 
-    compute_result_annotation=lambda *args: None,
-    specialize_call=rtype_destruct_object)
+class Entry(ExtRegistryEntry):
+    _about_ = ll_call_destructor
+    s_result_annotation = None
+
+    def specialize_call(self, hop):
+        v_inst, c_spec = hop.inputargs(*hop.args_r)
+        repr = c_spec.value
+        if repr.has_wrapper:
+            null = hop.inputconst(Ptr(PyObject), nullptr(PyObject))
+            # XXX this is a hack! We need an operation to remove a broken
+            # PyObject
+            repr.setfield(v_inst, '_wrapper_', null, hop.llops,
+                          opname='bare_setfield')
+        hop.genop('gc_unprotect', [v_inst])
+
 
 def create_pywrapper(thing, repr):
     return ll_create_pywrapper(thing, repr)
@@ -635,24 +638,26 @@
     llops.genop('gc_protect', [v_inst])
     return v_inst
 
-def rtype_wrap_object_create(hop):
-    v_inst, c_spec = hop.inputargs(*hop.args_r)
-    repr = c_spec.value
-    v_res = into_cobject(v_inst, repr, hop.llops)
-    v_cobj = v_res
-    c_cls = hop.inputconst(pyobj_repr, repr.classdef.classdesc.pyobj)
-    c_0 = hop.inputconst(Signed, 0)
-    v_res = hop.llops.gencapicall('PyType_GenericAlloc', [c_cls, c_0], resulttype=pyobj_repr)
-    c_self = hop.inputconst(pyobj_repr, '__self__')
-    hop.genop('setattr', [v_res, c_self, v_cobj], resulttype=pyobj_repr)
-    if repr.has_wrapper:
-        repr.setfield(v_inst, '_wrapper_', v_res, hop.llops)
-        hop.genop('gc_unprotect', [v_res]) # yes a weak ref
-    return v_res
-
-extregistry.register_value(ll_create_pywrapper, 
-    compute_result_annotation=annmodel.SomePtr(Ptr(PyObject)), 
-    specialize_call=rtype_wrap_object_create)
+class Entry(ExtRegistryEntry):
+    _about_ = ll_create_pywrapper
+    s_result_annotation = annmodel.SomePtr(Ptr(PyObject))
+
+    def specialize_call(self, hop):
+        v_inst, c_spec = hop.inputargs(*hop.args_r)
+        repr = c_spec.value
+        v_res = into_cobject(v_inst, repr, hop.llops)
+        v_cobj = v_res
+        c_cls = hop.inputconst(pyobj_repr, repr.classdef.classdesc.pyobj)
+        c_0 = hop.inputconst(Signed, 0)
+        v_res = hop.llops.gencapicall('PyType_GenericAlloc', [c_cls, c_0],
+                                      resulttype=pyobj_repr)
+        c_self = hop.inputconst(pyobj_repr, '__self__')
+        hop.genop('setattr', [v_res, c_self, v_cobj], resulttype=pyobj_repr)
+        if repr.has_wrapper:
+            repr.setfield(v_inst, '_wrapper_', v_res, hop.llops)
+            hop.genop('gc_unprotect', [v_res]) # yes a weak ref
+        return v_res
+
 
 def fetch_pywrapper(thing, repr):
     return ll_fetch_pywrapper(thing, repr)
@@ -660,19 +665,20 @@
 def ll_fetch_pywrapper(thing, repr):
     return 42
 
-def rtype_wrap_object_fetch(hop):
-    v_inst, c_spec = hop.inputargs(*hop.args_r)
-    repr = c_spec.value
-    if repr.has_wrapper:
-        return repr.getfield(v_inst, '_wrapper_', hop.llops)
-    else:
-        null = hop.inputconst(Ptr(PyObject), nullptr(PyObject))
-        return null
+class Entry(ExtRegistryEntry):
+    _about_ = ll_fetch_pywrapper
+    s_result_annotation = annmodel.SomePtr(Ptr(PyObject))
+
+    def specialize_call(self, hop):
+        v_inst, c_spec = hop.inputargs(*hop.args_r)
+        repr = c_spec.value
+        if repr.has_wrapper:
+            return repr.getfield(v_inst, '_wrapper_', hop.llops)
+        else:
+            null = hop.inputconst(Ptr(PyObject), nullptr(PyObject))
+            return null
+
 
-extregistry.register_value(ll_fetch_pywrapper, 
-    compute_result_annotation=annmodel.SomePtr(Ptr(PyObject)), 
-    specialize_call=rtype_wrap_object_fetch)
-    
 def ll_wrap_object(obj, repr):
     ret = fetch_pywrapper(obj, repr)
     if not ret:

Modified: pypy/dist/pypy/rpython/memory/test/test_gctransform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_gctransform.py	(original)
+++ pypy/dist/pypy/rpython/memory/test/test_gctransform.py	Fri Apr 21 19:30:22 2006
@@ -6,7 +6,7 @@
 from pypy.rpython.lltypesystem import lltype
 from pypy.objspace.flow.model import Variable
 from pypy.annotation import model as annmodel
-from pypy.rpython import extregistry
+from pypy.rpython.extregistry import ExtRegistryEntry
 from pypy import conftest
 
 import py
@@ -248,12 +248,18 @@
 
 def protect(obj): RaiseNameError
 def unprotect(obj): RaiseNameError
-def rtype_protect(hop): hop.genop('gc_protect', [hop.inputargs(hop.args_r[0])[0]])
-def rtype_unprotect(hop): hop.genop('gc_unprotect', [hop.inputargs(hop.args_r[0])[0]])
-extregistry.register_value(protect,
-    compute_result_annotation=lambda *args: None, specialize_call=rtype_protect)
-extregistry.register_value(unprotect,
-    compute_result_annotation=lambda *args: None, specialize_call=rtype_unprotect)
+
+class Entry(ExtRegistryEntry):
+    _about_ = protect
+    s_result_annotation = None
+    def specialize_call(self, hop):
+        hop.genop('gc_protect', hop.inputargs(hop.args_r[0]))
+
+class Entry(ExtRegistryEntry):
+    _about_ = unprotect
+    s_result_annotation = None
+    def specialize_call(self, hop):
+        hop.genop('gc_unprotect', hop.inputargs(hop.args_r[0]))
 
 def test_protect_unprotect():
     def p():    protect('this is an object')
@@ -270,14 +276,15 @@
         assert len(ops.get('direct_call', [])) == ex
 
 def generic_op(*args): RaiseNameError
-def rtype_generic_op(hop):
-    args = hop.inputargs(*hop.args_r)
-    args.pop(0)
-    op = hop.args_s[0].const
-    hop.genop(op, args)
-              
-extregistry.register_value(generic_op,
-    compute_result_annotation=lambda *args: None, specialize_call=rtype_generic_op)
+
+class Entry(ExtRegistryEntry):
+    _about_ = generic_op
+    s_result_annotation = None
+    def specialize_call(self, hop):
+        args = hop.inputargs(*hop.args_r)
+        args.pop(0)
+        op = hop.args_s[0].const
+        hop.genop(op, args)
 
 def test_bare_setfield():
     class A:

Modified: pypy/dist/pypy/rpython/rctypes/aarray.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/aarray.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/aarray.py	Fri Apr 21 19:30:22 2006
@@ -1,46 +1,40 @@
 from ctypes import ARRAY, c_int, c_char
-from pypy.annotation.model import SomeCTypesObject, SomeBuiltin, SomeString
-from pypy.rpython import extregistry
+from pypy.annotation.model import SomeCTypesObject, SomeString
+from pypy.rpython.rctypes.implementation import CTypesCallEntry, CTypesObjEntry
 from pypy.rpython.lltypesystem import lltype
 
 ArrayType = type(ARRAY(c_int, 10))
 
-def arraytype_specialize_call(hop):
-    from pypy.rpython.error import TyperError
-    from pypy.rpython.rmodel import inputconst
-    r_array = hop.r_result
-    v_result = r_array.allocate_instance(hop.llops)
-    if hop.nb_args > r_array.length:
-        raise TyperError("too many arguments for an array of length %d" % (
-            r_array.length,))
-    for i in range(hop.nb_args):
-        v_item = hop.inputarg(r_array.r_item, arg=i)
-        c_index = inputconst(lltype.Signed, i)
-        r_array.setitem(hop.llops, v_result, c_index, v_item)
-    return v_result
-
-def arraytype_compute_annotation(metatype, type):
-    def compute_result_annotation(*arg_s):
-        return SomeCTypesObject(type, SomeCTypesObject.OWNSMEMORY)
-    return SomeBuiltin(compute_result_annotation, methodname=type.__name__)
-
-extregistry.register_type(ArrayType, 
-    compute_annotation=arraytype_compute_annotation,
-    specialize_call=arraytype_specialize_call)
-
-def array_instance_compute_annotation(type, instance):
-    return SomeCTypesObject(type, SomeCTypesObject.OWNSMEMORY)
-
-def arraytype_get_repr(rtyper, s_array):
-    from pypy.rpython.rctypes.rarray import ArrayRepr
-    return ArrayRepr(rtyper, s_array)
-
-entry = extregistry.register_metatype(ArrayType,
-    compute_annotation=array_instance_compute_annotation,
-    get_repr=arraytype_get_repr)
-def char_array_get_field_annotation(s_array, fieldname):
-    assert fieldname == 'value'
-    if s_array.knowntype._type_ != c_char:
-        raise Exception("only arrays of chars have a .value attribute")
-    return SomeString()   # can_be_None = False
-entry.get_field_annotation = char_array_get_field_annotation
+
+class CallEntry(CTypesCallEntry):
+    "Annotation and rtyping of calls to array types."
+    _type_ = ArrayType
+
+    def specialize_call(self, hop):
+        from pypy.rpython.error import TyperError
+        from pypy.rpython.rmodel import inputconst
+        r_array = hop.r_result
+        v_result = r_array.allocate_instance(hop.llops)
+        if hop.nb_args > r_array.length:
+            raise TyperError("too many arguments for an array of length %d" % (
+                r_array.length,))
+        for i in range(hop.nb_args):
+            v_item = hop.inputarg(r_array.r_item, arg=i)
+            c_index = inputconst(lltype.Signed, i)
+            r_array.setitem(hop.llops, v_result, c_index, v_item)
+        return v_result
+
+
+class ObjEntry(CTypesObjEntry):
+    "Annotation and rtyping of array instances."
+    _metatype_ = ArrayType
+
+    def get_field_annotation(self, s_array, fieldname):
+        assert fieldname == 'value'
+        if self.type._type_ != c_char:
+            raise Exception("only arrays of chars have a .value attribute")
+        return SomeString()   # can_be_None = False
+
+    def get_repr(self, rtyper, s_array):
+        from pypy.rpython.rctypes.rarray import ArrayRepr
+        return ArrayRepr(rtyper, s_array)

Modified: pypy/dist/pypy/rpython/rctypes/achar_p.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/achar_p.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/achar_p.py	Fri Apr 21 19:30:22 2006
@@ -1,42 +1,33 @@
-from pypy.rpython import extregistry
-from pypy.annotation import model as annmodel
+from pypy.rpython.rctypes.implementation import CTypesCallEntry, CTypesObjEntry
+from pypy.annotation.model import SomeString
 
 from ctypes import c_char_p
 
 
-def c_char_p_compute_result_annotation(s_arg=None):
-    return annmodel.SomeCTypesObject(c_char_p,
-            annmodel.SomeCTypesObject.OWNSMEMORY)
-
-def c_char_p_specialize_call(hop):
-    from pypy.rpython.rstr import string_repr
-    r_char_p = hop.r_result
-    v_result = r_char_p.allocate_instance(hop.llops)
-    if len(hop.args_s):
-        v_value, = hop.inputargs(string_repr)
-        r_char_p.setstring(hop.llops, v_result, v_value)
-    return v_result
-
-extregistry.register_value(c_char_p,
-    compute_result_annotation=c_char_p_compute_result_annotation,
-    specialize_call=c_char_p_specialize_call
-    )
-
-def c_char_compute_annotation(the_type, instance):
-    return annmodel.SomeCTypesObject(c_char_p,
-                                     annmodel.SomeCTypesObject.OWNSMEMORY)
-
-def c_char_p_get_repr(rtyper, s_char_p):
-    from pypy.rpython.rctypes import rchar_p
-    return rchar_p.CCharPRepr(rtyper, s_char_p, rchar_p.CCHARP)
-
-entry = extregistry.register_type(c_char_p,
-        compute_annotation = c_char_compute_annotation,
-        get_repr           = c_char_p_get_repr,
-        )
-s_value_annotation = annmodel.SomeString(can_be_None=True)
-def c_char_p_get_field_annotation(s_char_p, fieldname):
-    assert fieldname == 'value'
-    return s_value_annotation
-entry.get_field_annotation = c_char_p_get_field_annotation
-entry.s_return_trick = s_value_annotation
+class CallEntry(CTypesCallEntry):
+    "Annotation and rtyping of calls to c_char_p."
+    _about_ = c_char_p
+
+    def specialize_call(self, hop):
+        from pypy.rpython.rstr import string_repr
+        r_char_p = hop.r_result
+        v_result = r_char_p.allocate_instance(hop.llops)
+        if len(hop.args_s):
+            v_value, = hop.inputargs(string_repr)
+            r_char_p.setstring(hop.llops, v_result, v_value)
+        return v_result
+
+
+class ObjEntry(CTypesObjEntry):
+    "Annotation and rtyping of c_char_p instances."
+    _type_ = c_char_p
+
+    s_return_trick = SomeString(can_be_None=True)
+
+    def get_field_annotation(self, s_char_p, fieldname):
+        assert fieldname == 'value'
+        return self.s_return_trick
+
+    def get_repr(self, rtyper, s_char_p):
+        from pypy.rpython.rctypes import rchar_p
+        return rchar_p.CCharPRepr(rtyper, s_char_p, rchar_p.CCHARP)

Modified: pypy/dist/pypy/rpython/rctypes/afunc.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/afunc.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/afunc.py	Fri Apr 21 19:30:22 2006
@@ -1,5 +1,5 @@
-from pypy.annotation import model as annmodel
-from pypy.rpython import extregistry
+from pypy.annotation.model import SomeCTypesObject
+from pypy.rpython.extregistry import ExtRegistryEntry
 from pypy.rpython.lltypesystem import lltype
 
 import ctypes
@@ -7,86 +7,78 @@
 
 CFuncPtrType = type(ctypes.CFUNCTYPE(None))
 
-def cfuncptrtype_compute_annotation(type, instance):
 
-    def compute_result_annotation(*args_s):
+class CallEntry(ExtRegistryEntry):
+    """Annotation and rtyping of calls to external functions
+    declared with ctypes.
+    """
+    _metatype_ = CFuncPtrType
+
+    def compute_result_annotation(self, *args_s):
         """
         Answer the annotation of the external function's result
         """
-        result_ctype = instance.restype
+        result_ctype = self.instance.restype
         if result_ctype is None:
             return None
-        s_result = annmodel.SomeCTypesObject(result_ctype,
-                                         annmodel.SomeCTypesObject.OWNSMEMORY)
+        s_result = SomeCTypesObject(result_ctype, SomeCTypesObject.OWNSMEMORY)
         return s_result.return_annotation()
 
-    return annmodel.SomeBuiltin(compute_result_annotation, 
-        methodname=getattr(instance, '__name__', None))
+    def specialize_call(self, hop):
+        from pypy.rpython.rctypes.rmodel import CTypesValueRepr
+        cfuncptr = self.instance
+        fnname = cfuncptr.__name__
+
+        args_r = []
+        for ctype in cfuncptr.argtypes:
+            s_arg = SomeCTypesObject(ctype, SomeCTypesObject.MEMORYALIAS)
+            r_arg = hop.rtyper.getrepr(s_arg)
+            args_r.append(r_arg)
+
+        vlist = hop.inputargs(*args_r)
+        unwrapped_args_v = []
+        ARGTYPES = []
+        for r_arg, v in zip(args_r, vlist):
+            if isinstance(r_arg, CTypesValueRepr):
+                # ValueRepr case
+                unwrapped_args_v.append(r_arg.getvalue(hop.llops, v))
+                ARGTYPES.append(r_arg.ll_type)
+            else:
+                # RefRepr case -- i.e. the function argument that we pass by
+                # value is e.g. a complete struct; we pass a pointer to it
+                # in the low-level graphs and it's up to the back-end to
+                # generate the correct dereferencing
+                unwrapped_args_v.append(r_arg.get_c_data(hop.llops, v))
+                ARGTYPES.append(r_arg.c_data_type)
+        if cfuncptr.restype is not None:
+            s_res = SomeCTypesObject(cfuncptr.restype,
+                                     SomeCTypesObject.OWNSMEMORY)
+            r_res = hop.rtyper.getrepr(s_res)
+            RESTYPE = r_res.ll_type
+        else:
+            RESTYPE = lltype.Void
 
-def cfuncptrtype_specialize_call(hop):
-    from pypy.rpython.rctypes.rmodel import CTypesValueRepr
+        kwds = {}
+        if hasattr(cfuncptr, 'llinterp_friendly_version'):
+            kwds['_callable'] = cfuncptr.llinterp_friendly_version
+        if (cfuncptr._flags_ & ctypes._FUNCFLAG_PYTHONAPI) == 0:
+            kwds['includes'] = getattr(cfuncptr, 'includes', ())
+        #else:
+        #   no 'includes': hack to trigger in GenC a PyErr_Occurred() check
+
+        v_result = hop.llops.gencapicall(fnname, unwrapped_args_v,
+                                         resulttype = RESTYPE,
+                                         **kwds)
+        # XXX hack! hack! temporary! I promize!
+        FUNCTYPE = lltype.FuncType(ARGTYPES, RESTYPE)
+        last_op = hop.llops[-1]
+        assert last_op.opname == 'direct_call'
+        last_op.args[0].concretetype = lltype.Ptr(FUNCTYPE)
+        last_op.args[0].value._set_TYPE(last_op.args[0].concretetype)
+        last_op.args[0].value._set_T(FUNCTYPE)
+        last_op.args[0].value._obj._TYPE = FUNCTYPE
 
-    # this is necessary to get the original function pointer when specializing
-    # the metatype
-    assert hop.spaceop.opname == "simple_call"
-    cfuncptr = hop.spaceop.args[0].value
-    fnname = cfuncptr.__name__
-
-    args_r = []
-    for ctype in cfuncptr.argtypes:
-        s_arg = annmodel.SomeCTypesObject(ctype,
-                              annmodel.SomeCTypesObject.MEMORYALIAS)
-        r_arg = hop.rtyper.getrepr(s_arg)
-        args_r.append(r_arg)
-
-    vlist = hop.inputargs(*args_r)
-    unwrapped_args_v = []
-    ARGTYPES = []
-    for r_arg, v in zip(args_r, vlist):
-        if isinstance(r_arg, CTypesValueRepr):
-            # ValueRepr case
-            unwrapped_args_v.append(r_arg.getvalue(hop.llops, v))
-            ARGTYPES.append(r_arg.ll_type)
+        if RESTYPE is lltype.Void:
+            return None
         else:
-            # RefRepr case -- i.e. the function argument that we pass by
-            # value is e.g. a complete struct; we pass a pointer to it
-            # in the low-level graphs and it's up to the back-end to
-            # generate the correct dereferencing
-            unwrapped_args_v.append(r_arg.get_c_data(hop.llops, v))
-            ARGTYPES.append(r_arg.c_data_type)
-    if cfuncptr.restype is not None:
-        s_res = annmodel.SomeCTypesObject(cfuncptr.restype,
-                                          annmodel.SomeCTypesObject.OWNSMEMORY)
-        r_res = hop.rtyper.getrepr(s_res)
-        RESTYPE = r_res.ll_type
-    else:
-        RESTYPE = lltype.Void
-
-    kwds = {}
-    if hasattr(cfuncptr, 'llinterp_friendly_version'):
-        kwds['_callable'] = cfuncptr.llinterp_friendly_version
-    if (cfuncptr._flags_ & ctypes._FUNCFLAG_PYTHONAPI) == 0:
-        kwds['includes'] = getattr(cfuncptr, 'includes', ())
-    #else:
-    #   no 'includes': hack to trigger in GenC a PyErr_Occurred() check
-
-    v_result = hop.llops.gencapicall(fnname, unwrapped_args_v,
-                                     resulttype = RESTYPE,
-                                     **kwds)
-    # XXX hack! hack! temporary! I promize!
-    FUNCTYPE = lltype.FuncType(ARGTYPES, RESTYPE)
-    last_op = hop.llops[-1]
-    assert last_op.opname == 'direct_call'
-    last_op.args[0].concretetype = lltype.Ptr(FUNCTYPE)
-    last_op.args[0].value._set_TYPE(last_op.args[0].concretetype)
-    last_op.args[0].value._set_T(FUNCTYPE)
-    last_op.args[0].value._obj._TYPE = FUNCTYPE
-
-    if RESTYPE is lltype.Void:
-        return None
-    else:
-        return r_res.return_value(hop.llops, v_result)
-
-extregistry.register_metatype(CFuncPtrType, 
-    compute_annotation=cfuncptrtype_compute_annotation,
-    specialize_call=cfuncptrtype_specialize_call)
+            return r_res.return_value(hop.llops, v_result)

Modified: pypy/dist/pypy/rpython/rctypes/apointer.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/apointer.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/apointer.py	Fri Apr 21 19:30:22 2006
@@ -1,81 +1,73 @@
-from pypy.rpython import extregistry
-from pypy.annotation import model as annmodel
-from pypy.annotation.pairtype import pairtype
+from pypy.rpython.extregistry import ExtRegistryEntry
+from pypy.rpython.rctypes.implementation import CTypesCallEntry, CTypesObjEntry
+from pypy.annotation.model import SomeCTypesObject
 from pypy.rpython.lltypesystem import lltype
 
 from ctypes import pointer, POINTER, byref, c_int
 
 
-def pointertype_compute_annotation(metatype, type):
-    def compute_result_annotation(*arg_s):
-        return annmodel.SomeCTypesObject(type,
-                annmodel.SomeCTypesObject.OWNSMEMORY)
-    return annmodel.SomeBuiltin(compute_result_annotation, 
-                                methodname=type.__name__)
-
-def pointertype_specialize_call(hop):
-    r_ptr = hop.r_result
-    v_result = r_ptr.allocate_instance(hop.llops)
-    if len(hop.args_s):
-        v_contentsbox, = hop.inputargs(r_ptr.r_contents)
-        r_ptr.setcontents(hop.llops, v_result, v_contentsbox)
-    return v_result
-
-def pointerinstance_compute_annotation(type, instance):
-    return annmodel.SomeCTypesObject(type,
-            annmodel.SomeCTypesObject.OWNSMEMORY)
-
-def pointerinstance_field_annotation(s_pointer, fieldname):
-    assert fieldname == "contents"
-    ptrtype = s_pointer.knowntype
-    return annmodel.SomeCTypesObject(ptrtype._type_,
-                                     annmodel.SomeCTypesObject.MEMORYALIAS)
-
-def pointerinstance_get_repr(rtyper, s_pointer):
-    from pypy.rpython.rctypes.rpointer import PointerRepr
-    return PointerRepr(rtyper, s_pointer)
-
 PointerType = type(POINTER(c_int))
-extregistry.register_type(PointerType,
-        compute_annotation=pointertype_compute_annotation,
-        specialize_call=pointertype_specialize_call)
-
-entry = extregistry.register_metatype(PointerType,
-        compute_annotation=pointerinstance_compute_annotation,
-        get_repr=pointerinstance_get_repr)
-entry.get_field_annotation = pointerinstance_field_annotation
-
-def pointerfn_compute_annotation(s_arg):
-    assert isinstance(s_arg, annmodel.SomeCTypesObject)
-    ctype = s_arg.knowntype
-    result_ctype = POINTER(ctype)
-    return annmodel.SomeCTypesObject(result_ctype,
-                                     annmodel.SomeCTypesObject.OWNSMEMORY)
-
-extregistry.register_value(pointer,
-        compute_result_annotation=pointerfn_compute_annotation,
-        # same rtyping for calling pointer() or calling a specific instance
-        # of PointerType:
-        specialize_call=pointertype_specialize_call)
+
+class CallEntry(CTypesCallEntry):
+    "Annotation and rtyping of calls to POINTER types."
+    _type_ = PointerType
+
+    def specialize_call(self, hop):
+        # delegate calls to the logic for calls to ctypes.pointer()
+        return PointerFnEntry.specialize_call(hop)
+
+
+class ObjEntry(CTypesObjEntry):
+    "Annotation and rtyping of pointer instances."
+    _metatype_ = PointerType
+
+    def get_field_annotation(self, s_pointer, fieldname):
+        assert fieldname == "contents"
+        ptrtype = self.type
+        assert s_pointer.knowntype == ptrtype
+        return SomeCTypesObject(ptrtype._type_,
+                                SomeCTypesObject.MEMORYALIAS)
+
+    def get_repr(self, rtyper, s_pointer):
+        from pypy.rpython.rctypes.rpointer import PointerRepr
+        return PointerRepr(rtyper, s_pointer)
+
+
+class PointerFnEntry(ExtRegistryEntry):
+    "Annotation and rtyping of calls to ctypes.pointer()."
+    _about_ = pointer
+
+    def compute_result_annotation(self, s_arg):
+        assert isinstance(s_arg, SomeCTypesObject)
+        ctype = s_arg.knowntype
+        result_ctype = POINTER(ctype)
+        return SomeCTypesObject(result_ctype, SomeCTypesObject.OWNSMEMORY)
+
+    def specialize_call(hop):
+        r_ptr = hop.r_result
+        v_result = r_ptr.allocate_instance(hop.llops)
+        if len(hop.args_s):
+            v_contentsbox, = hop.inputargs(r_ptr.r_contents)
+            r_ptr.setcontents(hop.llops, v_result, v_contentsbox)
+        return v_result
+    specialize_call = staticmethod(specialize_call)
 
 # byref() is equivalent to pointer() -- the difference is only an
 # optimization that is useful in ctypes but not in rctypes.
-extregistry.register_value(byref,
-        compute_result_annotation=pointerfn_compute_annotation,
-        specialize_call=pointertype_specialize_call)
-
-# constant-fold POINTER(CONSTANT_CTYPE) calls
-def POINTER_compute_annotation(s_arg):
-    from pypy.annotation.bookkeeper import getbookkeeper
-    assert s_arg.is_constant(), "POINTER(%r): argument must be constant" % (
-        s_arg,)
-    RESTYPE = POINTER(s_arg.const)
-    return getbookkeeper().immutablevalue(RESTYPE)
-
-def POINTER_specialize_call(hop):
-    assert hop.s_result.is_constant()
-    return hop.inputconst(lltype.Void, hop.s_result.const)
-
-extregistry.register_value(POINTER,
-        compute_result_annotation=POINTER_compute_annotation,
-        specialize_call=POINTER_specialize_call)
+PointerFnEntry._register_value(byref)
+
+
+class POINTERFnEntry(ExtRegistryEntry):
+    "Annotation and rtyping of calls to ctypes.POINTER(): constant-folded."
+    _about_ = POINTER
+
+    def compute_result_annotation(self, s_arg):
+        from pypy.annotation.bookkeeper import getbookkeeper
+        assert s_arg.is_constant(), (
+            "POINTER(%r): argument must be constant" % (s_arg,))
+        RESTYPE = POINTER(s_arg.const)
+        return getbookkeeper().immutablevalue(RESTYPE)
+
+    def specialize_call(self, hop):
+        assert hop.s_result.is_constant()
+        return hop.inputconst(lltype.Void, hop.s_result.const)

Modified: pypy/dist/pypy/rpython/rctypes/aprimitive.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/aprimitive.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/aprimitive.py	Fri Apr 21 19:30:22 2006
@@ -2,7 +2,7 @@
 from ctypes import c_long, c_ulong, c_longlong, c_ulonglong, c_float
 from ctypes import c_double, c_wchar, c_char_p
 from pypy.annotation import model as annmodel
-from pypy.rpython import extregistry
+from pypy.rpython.rctypes.implementation import CTypesCallEntry, CTypesObjEntry
 from pypy.rpython.lltypesystem import lltype
 
 ctypes_annotation_list = {
@@ -20,45 +20,40 @@
     c_ulonglong:     lltype.UnsignedLongLong,
     c_float:         lltype.Float,
     c_double:        lltype.Float,
-}.items()   # nb. platform-dependent duplicate ctypes are removed
+}   # nb. platform-dependent duplicate ctypes are removed
 
 
-def primitive_specialize_call(hop):
-    r_primitive = hop.r_result
-    v_result = r_primitive.allocate_instance(hop.llops)
-    if len(hop.args_s):
-        v_value, = hop.inputargs(r_primitive.ll_type)
-        r_primitive.setvalue(hop.llops, v_result, v_value)
-    return v_result
-
-def do_register(the_type, ll_type):
-    def compute_result_annotation_function(s_arg=None):
-        return annmodel.SomeCTypesObject(the_type,
-                annmodel.SomeCTypesObject.OWNSMEMORY)
-
-    extregistry.register_value(the_type,
-        compute_result_annotation=compute_result_annotation_function,
-        specialize_call=primitive_specialize_call
-        )
-
-    def compute_prebuilt_instance_annotation(the_type, instance):
-        return annmodel.SomeCTypesObject(the_type,
-                annmodel.SomeCTypesObject.OWNSMEMORY)
+class CallEntry(CTypesCallEntry):
+    "Annotation and rtyping of calls to primitive c_xxx types."
 
-    def primitive_get_repr(rtyper, s_primitive):
+    def specialize_call(self, hop):
+        r_primitive = hop.r_result
+        v_result = r_primitive.allocate_instance(hop.llops)
+        if len(hop.args_s):
+            v_value, = hop.inputargs(r_primitive.ll_type)
+            r_primitive.setvalue(hop.llops, v_result, v_value)
+        return v_result
+
+
+class ObjEntry(CTypesObjEntry):
+    "Annotation and rtyping of instances of the primitive c_xxx type."
+
+    def get_repr(self, rtyper, s_primitive):
         from pypy.rpython.rctypes.rprimitive import PrimitiveRepr
+        ll_type = ctypes_annotation_list[self.type]
         return PrimitiveRepr(rtyper, s_primitive, ll_type)
 
-    entry = extregistry.register_type(the_type,
-            compute_annotation=compute_prebuilt_instance_annotation,
-            get_repr=primitive_get_repr,
-            )
-    s_value_annotation = annmodel.lltype_to_annotation(ll_type)
-    def primitive_get_field_annotation(s_primitive, fieldname):
+    def get_field_annotation(self, s_primitive, fieldname):
         assert fieldname == 'value'
-        return s_value_annotation
-    entry.get_field_annotation = primitive_get_field_annotation
-    entry.s_return_trick = s_value_annotation
+        return self.get_s_value()
+
+    def get_s_value(self):
+        ll_type = ctypes_annotation_list[self.type]
+        return annmodel.lltype_to_annotation(ll_type)
+
+    s_return_trick = property(get_s_value)
+
 
-for the_type, ll_type in ctypes_annotation_list:
-    do_register(the_type, ll_type)
+for _ctype in ctypes_annotation_list:
+    CallEntry._register_value(_ctype)
+    ObjEntry._register_type(_ctype)

Modified: pypy/dist/pypy/rpython/rctypes/apyobject.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/apyobject.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/apyobject.py	Fri Apr 21 19:30:22 2006
@@ -1,37 +1,28 @@
 from ctypes import py_object
 from pypy.annotation.model import SomeCTypesObject
-from pypy.rpython import extregistry
+from pypy.rpython.rctypes.implementation import CTypesCallEntry, CTypesObjEntry
 from pypy.rpython.lltypesystem import lltype
 
 
-# __________ py_object() calls __________
-
-def py_object_compute_result_annotation(s_obj=None):
-    return SomeCTypesObject(py_object, SomeCTypesObject.OWNSMEMORY)
-
-def py_object_specialize_call(hop):
-    from pypy.rpython.robject import pyobj_repr
-    r_pyobject = hop.r_result
-    v_result = r_pyobject.allocate_instance(hop.llops)
-    if len(hop.args_s):
-        [v_input] = hop.inputargs(pyobj_repr)
-        r_pyobject.setvalue(hop.llops, v_result, v_input)
-    return v_result
-
-extregistry.register_value(py_object, 
-    compute_result_annotation=py_object_compute_result_annotation,
-    specialize_call=py_object_specialize_call)
-
-# __________ prebuilt py_object instances __________
-
-def py_object_instance_compute_annotation(type, instance):
-    return SomeCTypesObject(py_object, SomeCTypesObject.OWNSMEMORY)
-
-def py_object_instance_get_repr(rtyper, s_pyobject):
-    from pypy.rpython.rctypes.rpyobject import CTypesPyObjRepr
-    lowleveltype = lltype.Ptr(lltype.PyObject)
-    return CTypesPyObjRepr(rtyper, s_pyobject, lowleveltype)
-
-extregistry.register_type(py_object, 
-    compute_annotation=py_object_instance_compute_annotation,
-    get_repr=py_object_instance_get_repr)
+class CallEntry(CTypesCallEntry):
+    "Annotation and rtyping of calls to py_object."
+    _about_ = py_object
+
+    def specialize_call(self, hop):
+        from pypy.rpython.robject import pyobj_repr
+        r_pyobject = hop.r_result
+        v_result = r_pyobject.allocate_instance(hop.llops)
+        if len(hop.args_s):
+            [v_input] = hop.inputargs(pyobj_repr)
+            r_pyobject.setvalue(hop.llops, v_result, v_input)
+        return v_result
+
+
+class ObjEntry(CTypesObjEntry):
+    "Annotation and rtyping of py_object instances."
+    _type_ = py_object
+
+    def get_repr(self, rtyper, s_pyobject):
+        from pypy.rpython.rctypes.rpyobject import CTypesPyObjRepr
+        lowleveltype = lltype.Ptr(lltype.PyObject)
+        return CTypesPyObjRepr(rtyper, s_pyobject, lowleveltype)

Modified: pypy/dist/pypy/rpython/rctypes/astringbuf.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/astringbuf.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/astringbuf.py	Fri Apr 21 19:30:22 2006
@@ -1,5 +1,6 @@
-from pypy.rpython import extregistry
-from pypy.annotation import model as annmodel
+from pypy.rpython.extregistry import ExtRegistryEntry
+from pypy.rpython.rctypes.implementation import CTypesObjEntry
+from pypy.annotation.model import SomeCTypesObject, SomeString
 
 from ctypes import create_string_buffer, c_char
 
@@ -13,34 +14,35 @@
     #_length_ = unspecified
 
 
-def stringbuf_compute_result_annotation(s_length):
-    if s_length.knowntype != int:
-        raise Exception("rctypes only supports create_string_buffer(length)")
-    return annmodel.SomeCTypesObject(StringBufferType,
-            annmodel.SomeCTypesObject.OWNSMEMORY)
-
-def stringbuf_specialize_call(hop):
-    from pypy.rpython.lltypesystem import lltype
-    [v_length] = hop.inputargs(lltype.Signed)
-    r_stringbuf = hop.r_result
-    return hop.genop("malloc_varsize", [
-        hop.inputconst(lltype.Void, r_stringbuf.lowleveltype.TO),
-        v_length,
-        ], resulttype=r_stringbuf.lowleveltype,
-    )
-
-extregistry.register_value(create_string_buffer,
-    compute_result_annotation=stringbuf_compute_result_annotation,
-    specialize_call=stringbuf_specialize_call,
-    )
-
-def stringbuf_get_repr(rtyper, s_stringbuf):
-    from pypy.rpython.rctypes import rstringbuf
-    return rstringbuf.StringBufRepr(rtyper, s_stringbuf, rstringbuf.STRBUFTYPE)
-
-entry = extregistry.register_type(StringBufferType,
-    get_repr=stringbuf_get_repr)
-def stringbuf_get_field_annotation(s_array, fieldname):
-    assert fieldname == 'value'
-    return annmodel.SomeString()   # can_be_None = False
-entry.get_field_annotation = stringbuf_get_field_annotation
+class CreateStringBufferFnEntry(ExtRegistryEntry):
+    "Annotation and rtyping of calls to ctypes.create_string_buffer()"
+    _about_ = create_string_buffer
+
+    def compute_result_annotation(self, s_length):
+        if s_length.knowntype != int:
+            raise Exception("only supports create_string_buffer(length)")
+        return SomeCTypesObject(StringBufferType, SomeCTypesObject.OWNSMEMORY)
+
+    def specialize_call(self, hop):
+        from pypy.rpython.lltypesystem import lltype
+        [v_length] = hop.inputargs(lltype.Signed)
+        r_stringbuf = hop.r_result
+        return hop.genop("malloc_varsize", [
+            hop.inputconst(lltype.Void, r_stringbuf.lowleveltype.TO),
+            v_length,
+            ], resulttype=r_stringbuf.lowleveltype,
+        )
+
+
+class ObjEntry(CTypesObjEntry):
+    "Annotation and rtyping of instances of the pseudo-ctype StringBufferType"
+    _type_ = StringBufferType
+
+    def get_field_annotation(self, s_array, fieldname):
+        assert fieldname == 'value'
+        return SomeString()   # can_be_None = False
+
+    def get_repr(self, rtyper, s_stringbuf):
+        from pypy.rpython.rctypes import rstringbuf
+        return rstringbuf.StringBufRepr(rtyper, s_stringbuf,
+                                        rstringbuf.STRBUFTYPE)

Modified: pypy/dist/pypy/rpython/rctypes/astruct.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/astruct.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/astruct.py	Fri Apr 21 19:30:22 2006
@@ -1,69 +1,62 @@
 from ctypes import Structure
-from pypy.annotation.model import SomeCTypesObject, SomeBuiltin
-from pypy.rpython import extregistry
+from pypy.annotation.model import SomeCTypesObject
+from pypy.rpython.rctypes.implementation import CTypesCallEntry, CTypesObjEntry
 from pypy.rpython.lltypesystem import lltype
 
 StructType = type(Structure)
 
 
-def structtype_specialize_call(hop, **kwds_i):
-    from pypy.rpython.error import TyperError
-    r_struct = hop.r_result
-    v_result = r_struct.allocate_instance(hop.llops)
-    index_by_name = {}
-    name_by_index = {}
-    # collect the keyword arguments
-    for key, index in kwds_i.items():
-        assert key.startswith('i_')
-        name = key[2:]
-        assert index not in name_by_index
-        index_by_name[name] = index
-        name_by_index[index] = name
-    # add the positional arguments
-    fieldsiter = iter(r_struct.c_data_type._names)
-    for i in range(hop.nb_args):
-        if i not in name_by_index:
-            try:
-                name = fieldsiter.next()
-            except StopIteration:
-                raise TyperError("too many arguments in struct construction")
+class CallEntry(CTypesCallEntry):
+    "Annotation and rtyping of calls to structure types."
+    _type_ = StructType
+
+    def specialize_call(self, hop, **kwds_i):
+        from pypy.rpython.error import TyperError
+        r_struct = hop.r_result
+        v_result = r_struct.allocate_instance(hop.llops)
+        index_by_name = {}
+        name_by_index = {}
+        # collect the keyword arguments
+        for key, index in kwds_i.items():
+            assert key.startswith('i_')
+            name = key[2:]
+            assert index not in name_by_index
+            index_by_name[name] = index
+            name_by_index[index] = name
+        # add the positional arguments
+        ctype = self.instance
+        fieldsiter = iter(ctype._fields_)
+        for i in range(hop.nb_args):
+            if i not in name_by_index:
+                try:
+                    name, _ = fieldsiter.next()
+                except StopIteration:
+                    raise TyperError("too many arguments in struct construction")
+                if name in index_by_name:
+                    raise TyperError("multiple values for field %r" % (name,))
+                index_by_name[name] = i
+                name_by_index[i] = name
+        # initialize the fields from the arguments, as far as they are present
+        for name, _ in ctype._fields_:
             if name in index_by_name:
-                raise TyperError("multiple values for field %r" % (name,))
-            index_by_name[name] = i
-            name_by_index[i] = name
-    # initialize the fields from the arguments, as far as they are present
-    for name in r_struct.c_data_type._names:
-        if name in index_by_name:
-            index = index_by_name[name]
-            v_valuebox = hop.inputarg(r_struct.r_fields[name], arg=index)
-            r_struct.setfield(hop.llops, v_result, name, v_valuebox)
-    return v_result
-
-def structtype_compute_annotation(metatype, type):
-    def compute_result_annotation(*arg_s, **kwds_s):
-        return SomeCTypesObject(type, SomeCTypesObject.OWNSMEMORY)
-    return SomeBuiltin(compute_result_annotation, methodname=type.__name__)
-
-extregistry.register_type(StructType, 
-    compute_annotation=structtype_compute_annotation,
-    specialize_call=structtype_specialize_call)
-
-def struct_instance_compute_annotation(type, instance):
-    return SomeCTypesObject(type, SomeCTypesObject.OWNSMEMORY)
-
-def struct_instance_field_annotation(s_struct, fieldname):
-    structtype = s_struct.knowntype
-    for name, ctype in structtype._fields_:
-        if name == fieldname:
-            s_result = SomeCTypesObject(ctype, SomeCTypesObject.MEMORYALIAS)
-            return s_result.return_annotation()
-    raise AttributeError('%r has no field %r' % (structtype, fieldname))
-
-def structtype_get_repr(rtyper, s_struct):
-    from pypy.rpython.rctypes.rstruct import StructRepr
-    return StructRepr(rtyper, s_struct)
-
-entry = extregistry.register_metatype(StructType,
-    compute_annotation=struct_instance_compute_annotation,
-    get_repr=structtype_get_repr)
-entry.get_field_annotation = struct_instance_field_annotation
+                index = index_by_name[name]
+                v_valuebox = hop.inputarg(r_struct.r_fields[name], arg=index)
+                r_struct.setfield(hop.llops, v_result, name, v_valuebox)
+        return v_result
+
+
+class ObjEntry(CTypesObjEntry):
+    "Annotation and rtyping of structure instances."
+    _metatype_ = StructType
+
+    def get_field_annotation(self, s_struct, fieldname):
+        for name, ctype in self.type._fields_:
+            if name == fieldname:
+                s_result = SomeCTypesObject(ctype,
+                                            SomeCTypesObject.MEMORYALIAS)
+                return s_result.return_annotation()
+        raise AttributeError('%r has no field %r' % (self.type, fieldname))
+
+    def get_repr(self, rtyper, s_struct):
+        from pypy.rpython.rctypes.rstruct import StructRepr
+        return StructRepr(rtyper, s_struct)

Modified: pypy/dist/pypy/rpython/rctypes/avoid_p.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/avoid_p.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/avoid_p.py	Fri Apr 21 19:30:22 2006
@@ -1,77 +1,65 @@
-from pypy.rpython import extregistry
-from pypy.annotation import model as annmodel
+from pypy.rpython.extregistry import ExtRegistryEntry
+from pypy.rpython.rctypes.implementation import CTypesCallEntry, CTypesObjEntry
+from pypy.annotation.model import SomeCTypesObject
 
 from ctypes import c_void_p, c_int, POINTER, cast
 
 PointerType = type(POINTER(c_int))
 
 
-# c_void_p() as a function
-def c_void_p_compute_result_annotation():
-    return annmodel.SomeCTypesObject(c_void_p,
-                                     annmodel.SomeCTypesObject.OWNSMEMORY)
-
-def c_void_specialize_call(hop):
-    r_void_p = hop.r_result
-    v_result = r_void_p.allocate_instance(hop.llops)
-    return v_result
-
-extregistry.register_value(c_void_p,
-    compute_result_annotation=c_void_p_compute_result_annotation,
-    specialize_call=c_void_specialize_call,
-    )
-
-# c_void_p instances
-def c_void_compute_annotation(the_type, instance):
-    return annmodel.SomeCTypesObject(c_void_p,
-                                     annmodel.SomeCTypesObject.OWNSMEMORY)
-
-def c_void_p_get_repr(rtyper, s_void_p):
-    from pypy.rpython.rctypes.rvoid_p import CVoidPRepr
-    from pypy.rpython.lltypesystem import llmemory
-    return CVoidPRepr(rtyper, s_void_p, llmemory.Address)
-
-extregistry.register_type(c_void_p,
-    compute_annotation = c_void_compute_annotation,
-    get_repr           = c_void_p_get_repr,
-    )
-
-# cast() support
-def cast_compute_result_annotation(s_arg, s_type):
-    assert s_type.is_constant(), "cast(p, %r): argument 2 must be constant" % (
-        s_type,)
-    type = s_type.const
+class CallEntry(CTypesCallEntry):
+    "Annotation and rtyping of calls to c_void_p."
+    _about_ = c_void_p
 
-    def checkptr(ctype):
+    def specialize_call(self, hop):
+        r_void_p = hop.r_result
+        v_result = r_void_p.allocate_instance(hop.llops)
+        return v_result
+
+
+class ObjEntry(CTypesObjEntry):
+    "Annotation and rtyping of c_void_p instances."
+    _type_ = c_void_p
+
+    def get_repr(self, rtyper, s_void_p):
+        from pypy.rpython.rctypes.rvoid_p import CVoidPRepr
+        from pypy.rpython.lltypesystem import llmemory
+        return CVoidPRepr(rtyper, s_void_p, llmemory.Address)
+
+
+class CastFnEntry(ExtRegistryEntry):
+    "Annotation and rtyping of calls to ctypes.cast()"
+    _about_ = cast
+
+    def checkptr(self, ctype):
         assert isinstance(ctype, PointerType) or ctype == c_void_p, (
             "cast(): can only cast between pointers so far, not %r" % (ctype,))
-    checkptr(s_arg.knowntype)
-    checkptr(type)
-    return annmodel.SomeCTypesObject(type,
-                                     annmodel.SomeCTypesObject.OWNSMEMORY)
-
-def cast_specialize_call(hop):
-    from pypy.rpython.rctypes.rpointer import PointerRepr
-    from pypy.rpython.rctypes.rvoid_p import CVoidPRepr
-    from pypy.rpython.lltypesystem import lltype, llmemory
-    assert isinstance(hop.args_r[0], (PointerRepr, CVoidPRepr))
-    targetctype = hop.args_s[1].const
-    v_box, c_targetctype = hop.inputargs(hop.args_r[0], lltype.Void)
-    v_adr = hop.args_r[0].getvalue(hop.llops, v_box)
-    if v_adr.concretetype != llmemory.Address:
-        v_adr = hop.genop('cast_ptr_to_adr', [v_adr],
-                          resulttype = llmemory.Address)
-
-    if targetctype == c_void_p:
-        # cast to void
-        v_result = v_adr
-    else:
-        # cast to pointer
-        v_result = hop.genop('cast_adr_to_ptr', [v_adr],
-                             resulttype = hop.r_result.ll_type)
-    return hop.r_result.return_value(hop.llops, v_result)
-
-extregistry.register_value(cast,
-    compute_result_annotation=cast_compute_result_annotation,
-    specialize_call=cast_specialize_call,
-    )
+
+    def compute_result_annotation(self, s_arg, s_type):
+        assert s_type.is_constant(), (
+            "cast(p, %r): argument 2 must be constant" % (s_type,))
+        type = s_type.const
+        self.checkptr(s_arg.knowntype)
+        self.checkptr(type)
+        return SomeCTypesObject(type, SomeCTypesObject.OWNSMEMORY)
+
+    def specialize_call(self, hop):
+        from pypy.rpython.rctypes.rpointer import PointerRepr
+        from pypy.rpython.rctypes.rvoid_p import CVoidPRepr
+        from pypy.rpython.lltypesystem import lltype, llmemory
+        assert isinstance(hop.args_r[0], (PointerRepr, CVoidPRepr))
+        targetctype = hop.args_s[1].const
+        v_box, c_targetctype = hop.inputargs(hop.args_r[0], lltype.Void)
+        v_adr = hop.args_r[0].getvalue(hop.llops, v_box)
+        if v_adr.concretetype != llmemory.Address:
+            v_adr = hop.genop('cast_ptr_to_adr', [v_adr],
+                              resulttype = llmemory.Address)
+
+        if targetctype == c_void_p:
+            # cast to void
+            v_result = v_adr
+        else:
+            # cast to pointer
+            v_result = hop.genop('cast_adr_to_ptr', [v_adr],
+                                 resulttype = hop.r_result.ll_type)
+        return hop.r_result.return_value(hop.llops, v_result)

Modified: pypy/dist/pypy/rpython/rctypes/implementation.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/implementation.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/implementation.py	Fri Apr 21 19:30:22 2006
@@ -1,3 +1,25 @@
+# Base classes describing annotation and rtyping
+from pypy.annotation.model import SomeCTypesObject
+from pypy.rpython import extregistry
+from pypy.rpython.extregistry import ExtRegistryEntry
+
+
+class CTypesCallEntry(ExtRegistryEntry):
+    "Annotation and rtyping of calls to ctypes types."
+
+    def compute_result_annotation(self, *args_s, **kwds_s):
+        ctype = self.instance    # the ctype is the called object
+        return SomeCTypesObject(ctype, SomeCTypesObject.OWNSMEMORY)
+
+
+class CTypesObjEntry(ExtRegistryEntry):
+    "Annotation and rtyping of ctypes instances."
+
+    def compute_annotation(self):
+        ctype = self.type
+        return SomeCTypesObject(ctype, SomeCTypesObject.OWNSMEMORY)
+
+
 # Importing for side effect of registering types with extregistry
 import pypy.rpython.rctypes.aprimitive
 import pypy.rpython.rctypes.apointer
@@ -13,9 +35,6 @@
 # Register the correspondance between SomeCTypesObject and the get_repr()
 # functions attached to the extregistry to create CTypesReprs
 
-from pypy.annotation.model import SomeCTypesObject
-from pypy.rpython import extregistry
-
 class __extend__( SomeCTypesObject ):
     def rtyper_makerepr( self, rtyper ):
         entry = extregistry.lookup_type(self.knowntype)

Modified: pypy/dist/pypy/rpython/rctypes/test/test_rfunc.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/test/test_rfunc.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/test/test_rfunc.py	Fri Apr 21 19:30:22 2006
@@ -111,6 +111,24 @@
         if conftest.option.view:
             a.translator.view()
 
+    def test_annotate_reflow_bug(self):
+        class Space:
+            meth = staticmethod(labs)
+            def _freeze_(self):
+                return True
+        def g(x):
+            return x
+        def fn(space):
+            space.meth(g(0))
+            g(-1)
+        space = Space()
+        def ep():
+            return fn(space)
+        a = RPythonAnnotator()
+        a.build_types(ep, [])
+        if conftest.option.view:
+            a.translator.view()
+
 class Test_specialization:
     def test_specialize_labs(self):
         res = interpret(test_labs, [-11])

Modified: pypy/dist/pypy/rpython/rctypes/tool/cpyobjspace.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/tool/cpyobjspace.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/tool/cpyobjspace.py	Fri Apr 21 19:30:22 2006
@@ -67,8 +67,7 @@
         raise TypeError("wrap(%r)" % (x,))
     wrap._annspecialcase_ = "specialize:wrap"
 
-    def getattr(self, w_obj, w_attr):
-        return PyObject_GetAttr(w_obj, w_attr)
+    getattr = staticmethod(PyObject_GetAttr)
 
     def call_function(self, w_callable):
         return PyObject_Call(w_callable, PyTuple_New(0), PyDict_New())

Modified: pypy/dist/pypy/rpython/rgenop.py
==============================================================================
--- pypy/dist/pypy/rpython/rgenop.py	(original)
+++ pypy/dist/pypy/rpython/rgenop.py	Fri Apr 21 19:30:22 2006
@@ -10,7 +10,7 @@
 from pypy.rpython.module.support import init_opaque_object
 from pypy.rpython.module.support import to_opaque_object, from_opaque_object
 from pypy.rpython.module.support import from_rstr
-from pypy.rpython import extregistry
+from pypy.rpython.extregistry import ExtRegistryEntry
 
 
 # for debugging, sanity checks in non-RPython code
@@ -256,24 +256,31 @@
 
 # helpers
 def setannotation(func, annotation, specialize_as_constant=False):
-    if specialize_as_constant:
-        def specialize(hop):
-            llvalue = func(hop.args_s[0].const)
-            return hop.inputconst(lltype.typeOf(llvalue), llvalue)
-    else:
-        # specialize as direct_call
-        def specialize(hop):
-            FUNCTYPE = lltype.FuncType([r.lowleveltype for r in hop.args_r],
-                                       hop.r_result.lowleveltype)
-            args_v = hop.inputargs(*hop.args_r)
-            funcptr = lltype.functionptr(FUNCTYPE, func.__name__,
-                                         _callable=func)
-            cfunc = hop.inputconst(lltype.Ptr(FUNCTYPE), funcptr)
-            return hop.genop('direct_call', [cfunc] + args_v, hop.r_result)
-
-    extregistry.register_value(func,
-           compute_result_annotation = annotation,
-           specialize_call = specialize)
+
+    class Entry(ExtRegistryEntry):
+        "Annotation and specialization for calls to 'func'."
+        _about_ = func
+
+        if annotation is None or isinstance(annotation, annmodel.SomeObject):
+            s_result_annotation = annotation
+        else:
+            def compute_result_annotation(self, *args_s):
+                return annotation(*args_s)
+
+        if specialize_as_constant:
+            def specialize_call(self, hop):
+                llvalue = func(hop.args_s[0].const)
+                return hop.inputconst(lltype.typeOf(llvalue), llvalue)
+        else:
+            # specialize as direct_call
+            def specialize_call(self, hop):
+                FUNCTYPE = lltype.FuncType([r.lowleveltype for r in hop.args_r],
+                                           hop.r_result.lowleveltype)
+                args_v = hop.inputargs(*hop.args_r)
+                funcptr = lltype.functionptr(FUNCTYPE, func.__name__,
+                                             _callable=func)
+                cfunc = hop.inputconst(lltype.Ptr(FUNCTYPE), funcptr)
+                return hop.genop('direct_call', [cfunc] + args_v, hop.r_result)
 
 # annotations
 from pypy.annotation import model as annmodel

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	Fri Apr 21 19:30:22 2006
@@ -3,6 +3,7 @@
 ##py.test.skip('In progress at PyCon')
 
 from pypy.rpython import extregistry
+from pypy.rpython.extregistry import ExtRegistryEntry
 from pypy.annotation import model as annmodel
 from pypy.annotation.annrpython import RPythonAnnotator
 from pypy.translator.translator import TranslationContext
@@ -13,8 +14,9 @@
 def dummy(): 
     raiseNameError
 
-extregistry.register_value(dummy,
-        compute_result_annotation=annmodel.SomeInteger())
+class Entry(ExtRegistryEntry):
+    _about_ = dummy
+    s_result_annotation = annmodel.SomeInteger()
 
 def test_call_dummy():
     def func():
@@ -28,13 +30,13 @@
 def test_callable_annotation():
     def dummy2():
         raiseNameError
-    
-    def return_annotation():
-        return annmodel.SomeInteger()
-    
-    extregistry.register_value(dummy2,
-            compute_result_annotation=return_annotation)
-    
+
+    class Entry(ExtRegistryEntry):
+        _about_ = dummy2
+
+        def compute_result_annotation(self):
+            return annmodel.SomeInteger()
+
     def func():
         x = dummy2()
         return x
@@ -52,12 +54,12 @@
     def func():
         return dummy_type
     
-    def get_annotation(type, instance):
-        assert instance is dummy_type
-        return annmodel.SomeInteger()
-    
-    extregistry.register_type(DummyType, compute_annotation=get_annotation)
-    
+    class Entry(ExtRegistryEntry):
+        _type_ = DummyType
+        def compute_annotation(self):
+            assert self.instance is dummy_type
+            return annmodel.SomeInteger()
+
     a = RPythonAnnotator()
     s = a.build_types(func, [])
     assert isinstance(s, annmodel.SomeInteger)
@@ -74,13 +76,13 @@
     def func():
         return real_class
     
-    def get_annotation(t, x=None):
-        assert t is RealClass
-        assert x is real_class
-        return annmodel.SomeInteger()
-    
-    extregistry.register_metatype(MetaType, compute_annotation=get_annotation)
-    
+    class Entry(ExtRegistryEntry):
+        _metatype_ = MetaType
+        def compute_annotation(self):
+            assert self.type is RealClass
+            assert self.instance is real_class
+            return annmodel.SomeInteger()
+
     a = RPythonAnnotator()
     s = a.build_types(func, [])
     assert isinstance(s, annmodel.SomeInteger)
@@ -95,13 +97,13 @@
     def func(real_class):
         return real_class
     
-    def get_annotation(t, x=None):
-        assert t is RealClass
-        assert x is None
-        return annmodel.SomeInteger()
-    
-    extregistry.register_metatype(MetaType, compute_annotation=get_annotation)
-    
+    class Entry(ExtRegistryEntry):
+        _metatype_ = MetaType
+        def compute_annotation(self):
+            assert self.type is RealClass
+            assert self.instance is None
+            return annmodel.SomeInteger()
+
     a = RPythonAnnotator()
     s = a.build_types(func, [RealClass])
     assert isinstance(s, annmodel.SomeInteger)
@@ -110,13 +112,12 @@
     def dummy_func():
         raiseNameError
 
-    def dummy_specialize(hop):
-        return hop.inputconst(lltype.Signed, 42)
-    
-    extregistry.register_value(dummy_func, 
-        compute_result_annotation=annmodel.SomeInteger(), 
-        specialize_call=dummy_specialize)
-    
+    class Entry(ExtRegistryEntry):
+        _about_ = dummy_func
+        s_result_annotation = annmodel.SomeInteger()
+        def specialize_call(self, hop):
+            return hop.inputconst(lltype.Signed, 42)
+
     def func():
         return dummy_func()
     
@@ -135,25 +136,25 @@
             
         def rtyper_makekey( self ):
             return self.__class__, self.knowntype
-    
-    def get_annotation(type, instance=None):
-        assert type is DummyClass
-        dummy_object = SomeDummyObject()
-        dummy_object.knowntype = DummyClass
-        return dummy_object
-    
+
     class DummyRepr(Repr):
         lowleveltype = lltype.Signed
         
         def convert_const(self, value):
             return 42
-    
-    def get_repr(rtyper, s_instance):
-        return DummyRepr()
-    
-    extregistry.register_type(DummyClass, compute_annotation=get_annotation,
-        get_repr=get_repr)
-    
+
+    class Entry(ExtRegistryEntry):
+        _type_ = DummyClass
+
+        def compute_annotation(self):
+            assert self.type is DummyClass
+            dummy_object = SomeDummyObject()
+            dummy_object.knowntype = DummyClass
+            return dummy_object
+
+        def get_repr(self, rtyper, s_instance):
+            return DummyRepr()
+
     dummy_class = DummyClass()
     
     def func():
@@ -166,13 +167,15 @@
 def test_register_unhashable():
     lst1 = [5, 6]
     lst2 = [5, 6]
-    entry = extregistry.register_value(lst1)
-    assert extregistry.lookup(lst1) is entry
+    class Entry(ExtRegistryEntry):
+        _about_ = lst1
+    assert isinstance(extregistry.lookup(lst1), Entry)
     py.test.raises(KeyError, "extregistry.lookup(lst2)")
 
 def test_register_non_weakly_refable(n=6):
     tup1 = (5, 6)
     tup2 = (5, n)
-    entry = extregistry.register_value(tup1)
-    assert extregistry.lookup(tup1) is entry
-    assert extregistry.lookup(tup2) is entry
+    class Entry(ExtRegistryEntry):
+        _about_ = tup1
+    assert isinstance(extregistry.lookup(tup1), Entry)
+    assert isinstance(extregistry.lookup(tup2), Entry)

Added: pypy/dist/pypy/tool/instancemethod.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/tool/instancemethod.py	Fri Apr 21 19:30:22 2006
@@ -0,0 +1,30 @@
+
+class InstanceMethod(object):
+    "Like types.InstanceMethod, but with a reasonable (structural) equality."
+
+    def __init__(self, im_func, im_self, im_class):
+        self.im_func = im_func
+        self.im_self = im_self
+        self.im_class = im_class
+
+    def __call__(__self, *args, **kwds):
+        firstarg = __self.im_self
+        if firstarg is None:
+            if not args or not isinstance(args[0], __self.im_class):
+                raise TypeError(
+                    "must be called with %r instance as first argument" % (
+                    __self.im_class,))
+            firstarg = args[0]
+            args = args[1:]
+        return __self.im_func(firstarg, *args, **kwds)
+
+    def __eq__(self, other):
+        return isinstance(other, InstanceMethod) and (
+            self.im_func == other.im_func and
+            self.im_self == other.im_self)
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __hash__(self):
+        return hash((self.im_func, self.im_self))



More information about the Pypy-commit mailing list