[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