[pypy-svn] r26542 - in pypy/dist/pypy: rpython rpython/lltypesystem translator/c translator/c/src translator/c/test

tismer at codespeak.net tismer at codespeak.net
Sat Apr 29 03:43:25 CEST 2006


Author: tismer
Date: Sat Apr 29 03:43:15 2006
New Revision: 26542

Modified:
   pypy/dist/pypy/rpython/lltypesystem/lloperation.py
   pypy/dist/pypy/rpython/robject.py
   pypy/dist/pypy/translator/c/pyobj.py
   pypy/dist/pypy/translator/c/src/pyobj.h
   pypy/dist/pypy/translator/c/src/support.h
   pypy/dist/pypy/translator/c/test/test_wrapping.py
   pypy/dist/pypy/translator/c/wrapper.py
Log:
support for true methods, properties, ...

checking in with a bug right now.

Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lloperation.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py	Sat Apr 29 03:43:15 2006
@@ -317,6 +317,7 @@
     'same_as':              LLOp(canfold=True),
     'hint':                 LLOp(),
     'check_no_more_arg':    LLOp(canraise=(Exception,)),
+    'check_self_nonzero':   LLOp(canraise=(Exception,)),
     'decode_arg':           LLOp(canraise=(Exception,)),
     'decode_arg_def':       LLOp(canraise=(Exception,)),
     'getslice':             LLOp(canraise=(Exception,)),

Modified: pypy/dist/pypy/rpython/robject.py
==============================================================================
--- pypy/dist/pypy/rpython/robject.py	(original)
+++ pypy/dist/pypy/rpython/robject.py	Sat Apr 29 03:43:15 2006
@@ -1,7 +1,7 @@
 from pypy.annotation.pairtype import pairtype
 from pypy.annotation import model as annmodel
 from pypy.rpython.lltypesystem.lltype import \
-     PyObject, Ptr, Void, pyobjectptr, nullptr
+     PyObject, Ptr, Void, pyobjectptr, nullptr, Bool
 from pypy.rpython.rmodel import Repr, VoidRepr, inputconst
 from pypy.rpython import rclass
 from pypy.tool.sourcetools import func_with_new_name
@@ -69,3 +69,10 @@
 for opname in annmodel.BINARY_OPERATIONS:
     make_operation(opname, pairtype(PyObjRepr, Repr))
     make_operation(opname, pairtype(Repr, PyObjRepr))
+
+    
+class __extend__(pairtype(PyObjRepr, PyObjRepr)): 
+    def rtype_contains((r_seq, r_item), hop):
+        v_seq, v_item = hop.inputargs(r_seq, r_item)
+        return hop.llops.gencapicall('PySequence_Contains_with_exc',
+                                     [v_seq, v_item], resulttype=Bool)

Modified: pypy/dist/pypy/translator/c/pyobj.py
==============================================================================
--- pypy/dist/pypy/translator/c/pyobj.py	(original)
+++ pypy/dist/pypy/translator/c/pyobj.py	Sat Apr 29 03:43:15 2006
@@ -81,6 +81,8 @@
         self.initcode.append("%s = %s" % (name, pyexpr))
 
     def nameof_object(self, value):
+        if isinstance(object, property):
+            return self.nameof_property(value)
         if type(value) is not object:
             raise Exception, "nameof(%r)" % (value,)
         name = self.uniquename('g_object')
@@ -579,6 +581,15 @@
                     self.name_for_meth[value] = fname
                     if self.use_true_methods:
                         self.is_method[value] = True
+                elif isinstance(value, property):
+                    fget, fset, fdel, doc = value.fget, value.fset, value.fdel, value.__doc__
+                    for f in fget, fset, fdel:
+                        if f and self.use_true_methods:
+                            self.is_method[f] = True
+                    stuff = [self.nameof(x) for x in fget, fset, fdel, doc]
+                    yield '%s.%s = property(%s, %s, %s, %s)' % ((name, key) +
+                                                                tuple(stuff))
+                    continue
                 yield '%s.%s = %s' % (name, key, self.nameof(value))
             if not init_seen:
                 log.WARNING('No __init__ found for %s - you cannot build instances' %
@@ -603,3 +614,13 @@
         pycfunctionobj = self.uniquename('gfunc_' + newname)
         self.wrappers[pycfunctionobj] = g.func.__name__, self.getvalue(fwrapper), g.func.__doc__
         return pycfunctionobj
+
+    def nameof_property(self, p):
+        fget, fset, fdel, doc = p.fget, p.fset, p.fdel, p.__doc__
+        for f in fget, fset, fdel:
+            if f and self.use_true_methods:
+                self.is_method[f] = True
+        stuff = [self.nameof(x) for x in fget, fset, fdel, doc]
+        name = self.uniquename('gprop')
+        expr = 'property(%s, %s, %s, %s)' % (tuple(stuff))
+        self.initcode_python(name, expr)

Modified: pypy/dist/pypy/translator/c/src/pyobj.h
==============================================================================
--- pypy/dist/pypy/translator/c/src/pyobj.h	(original)
+++ pypy/dist/pypy/translator/c/src/pyobj.h	Sat Apr 29 03:43:15 2006
@@ -225,7 +225,9 @@
 #define OP_DECODE_ARG_DEF(fname, pos, name, vargs, vkwds, def, r)	\
 	if (!(r=decode_arg(fname, pos, name, vargs, vkwds, def))) CFAIL()
 #define OP_CHECK_NO_MORE_ARG(fname, n, vargs, r)	\
-	if (check_no_more_arg(fname, n, vargs) < 0) CFAIL()
+	if ((r=check_no_more_arg(fname, n, vargs)) < 0) CFAIL()
+#define OP_CHECK_SELF_NONZERO(fname, self, r)	\
+	if ((r=check_self_nonzero(fname, self)) < 0) CFAIL()
 
 unsigned long long RPyLong_AsUnsignedLongLong(PyObject *v);
 long long RPyLong_AsLongLong(PyObject *v);

Modified: pypy/dist/pypy/translator/c/src/support.h
==============================================================================
--- pypy/dist/pypy/translator/c/src/support.h	(original)
+++ pypy/dist/pypy/translator/c/src/support.h	Sat Apr 29 03:43:15 2006
@@ -46,9 +46,10 @@
 PyObject* decode_arg(PyObject* fname, int position, PyObject* name,
 			    PyObject* vargs, PyObject* vkwds, PyObject* def);
 int check_no_more_arg(PyObject* fname, int n, PyObject* vargs);
+int check_self_nonzero(PyObject* fname, PyObject* self);
 PyObject *PyTuple_GetItem_WithIncref(PyObject *tuple, int index);
 int PyTuple_SetItem_WithIncref(PyObject *tuple, int index, PyObject *o);
-
+int PySequence_Contains_with_exc(PyObject *seq, PyObject *ob);
 
 /* implementations */
 
@@ -387,6 +388,17 @@
 	return 0;
 }
 
+int check_self_nonzero(PyObject* fname, PyObject* self)
+{
+	if (!self) {
+		    PyErr_Format(PyExc_TypeError,
+				"%s() expects instance first arg",
+				PyString_AS_STRING(fname));
+		    return -1;
+	}
+	return 0;
+}
+		
 /************************************************************/
 
 PyObject *PyTuple_GetItem_WithIncref(PyObject *tuple, int index)
@@ -402,6 +414,15 @@
 	return PyTuple_SetItem(tuple, index, o);
 }
 
+int PySequence_Contains_with_exc(PyObject *seq, PyObject *ob)
+{
+	int ret = PySequence_Contains(seq, ob);
+	
+	if (ret < 0) 
+		CFAIL();
+	return ret;
+}
+
 #endif /* PYPY_STANDALONE */
 
 #endif /* PYPY_NOT_MAIN_FILE */

Modified: pypy/dist/pypy/translator/c/test/test_wrapping.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_wrapping.py	(original)
+++ pypy/dist/pypy/translator/c/test/test_wrapping.py	Sat Apr 29 03:43:15 2006
@@ -4,15 +4,15 @@
 from pypy.rpython.extregistry import ExtRegistryEntry
 from pypy.annotation import model as annmodel
 from pypy.rpython.lltypesystem import lltype
-from pypy.rpython import robject, rclass
+from pypy.rpython import robject, rclass, rint
 from pypy.translator.tool.cbuild import enable_fast_compilation
 
 import sys, types
 
 P = False  # debug printing
 
-def get_annotation(func):
-    argstypelist = []
+def get_annotation(func, pre=[]):
+    argstypelist = pre[:]
     if func.func_defaults:
         for spec in func.func_defaults:
             if isinstance(spec, tuple):
@@ -46,15 +46,26 @@
 
     for obj in exports:
         if isinstance(obj, type):
-            clsdef = bk.getuniqueclassdef(obj)
+            cls = obj
+            clsdef = bk.getuniqueclassdef(cls)
             rtyper.add_wrapper(clsdef)
+            for obj in cls.__dict__.values():
+                if isinstance(obj, types.FunctionType):
+                    if not ann.bookkeeper.getdesc(obj).querycallfamily():
+                        # not annotated, so enforce it
+                        ann.build_types(obj, get_annotation(obj, [cls]), complete_now=False)
+                elif isinstance(obj, property):
+                    for obj in obj.fget, obj.fset, obj.fdel:
+                        if obj and not ann.bookkeeper.getdesc(obj).querycallfamily():
+                            ann.build_types(obj, get_annotation(obj, [cls]), complete_now=False)
         elif isinstance(obj, types.FunctionType):
             if not ann.bookkeeper.getdesc(obj).querycallfamily():
                 # not annotated, so enforce it
-                ann.build_types(obj, get_annotation(obj))
+                ann.build_types(obj, get_annotation(obj), complete_now=False)
             if obj.__name__ == '__init__':
                 pyobj_options['use_true_methods'] = True
 
+    ann.build_types(func, get_annotation(func))
     if view:
         t.viewcg()
     rtyper.specialize()
@@ -172,6 +183,10 @@
         #return type(self)(self.a + other.a, self.b + other.b)
         return DemoClass(self.a + other.a, self.b + other.b)
 
+    def ab(self):
+        return self.a + self.b
+    ab = property(ab)
+
 # see if we get things exported with subclassing
 class DemoSubclass(DemoClass):
     def __init__(self, a, b, c):
@@ -252,6 +267,10 @@
 
     def specialize_call(self, hop):
         v_idx, = hop.inputargs(*hop.args_r)
+        if hop.args_r[0] <> rint.signed_repr:
+            v_idx = hop.llops.convertvar(v_idx,
+                                         r_from=hop.args_r[0],
+                                           r_to=rint.signed_repr)
         v_res = hop.llops.gencapicall('postsetup_get_methodname', [v_idx],
                                       resulttype=robject.pyobj_repr)
         return v_res
@@ -265,6 +284,12 @@
 
     def specialize_call(self, hop):
         v_idx, v_type = hop.inputargs(*hop.args_r)
+        if hop.args_r[0] <> rint.signed_repr:
+            v_idx = hop.llops.convertvar(v_idx,
+                                         r_from=hop.args_r[0],
+                                           r_to=rint.signed_repr)
+        assert hop.args_r[1] == robject.pyobj_repr, (
+            'build_method works for Python types only')                                            
         v_res = hop.llops.gencapicall('postsetup_build_method', [v_idx, v_type],
                                       resulttype=robject.pyobj_repr)
         return v_res
@@ -278,6 +303,8 @@
 
     def specialize_call(self, hop):
         v_type, = hop.inputargs(*hop.args_r)
+        assert hop.args_r[0] == robject.pyobj_repr, (
+            'get_typedict works for Python types only')                                            
         v_res = hop.llops.gencapicall('postsetup_get_typedict', [v_type],
                                       resulttype=robject.pyobj_repr)
         return v_res
@@ -307,6 +334,43 @@
                     dic[methname] = meth
         idx += 1
 
+def __init__(mod):
+    import types
+    import __builtin__ as bltn
+    hasattr = bltn.hasattr
+    isinstance = bltn.isinstance
+
+    funcs = bltn.dict() # no hashing function for PyObject
+    idx = 0
+    while 1:
+        name = get_methodname(idx)
+        if not name:
+            break
+        func = getattr(mod, name)
+        funcs[func] = idx
+        idx += 1
+    
+    for name in mod.__all__:
+        obj = getattr(mod, name)
+        if isinstance(obj, type) and hasattr(obj, '__self__'):
+            cls = obj
+            dic = get_typedict(cls)
+            for name, value in dic.items():
+                if isinstance(value, types.BuiltinFunctionType) and value in funcs:
+                    idx = funcs[value]
+                    meth = build_method(idx, cls)
+                    dic[name] = meth
+                elif isinstance(value, property):
+                    stuff = [value.fget, value.fset, value.fdel, value.__doc__]
+                    for i, fn in enumerate(stuff):
+                        if fn in funcs:
+                            idx = funcs[fn]
+                            stuff[i] = build_method(idx, cls)
+                    if not stuff[-1]:
+                        # use fget's doc if we don't ahve one
+                        stuff[-1] = getattr(stuff[0], '__doc__', None)
+                    dic[name] = property(*stuff)
+
 # creating an object, wrapping, unwrapping, call function, check whether __del__ is called
 def test_wrap_call_dtor():
     f = getcompiled(democlass_helper, use_boehm=not True, exports=[DemoSubclass])
@@ -317,7 +381,7 @@
 # exposing and using classes from a generasted extension module
 def test_expose_classes():
     m = get_compiled_module(democlass_helper2, use_boehm=not True, exports=[
-        DemoClass, DemoSubclass, DemoNotAnnotated, __init__])
+        DemoClass, DemoSubclass, __init__, DemoNotAnnotated])
     obj = m.DemoClass(2, 3)
     res = obj.demo()
     assert res == DemoClass(2, 3).demo()

Modified: pypy/dist/pypy/translator/c/wrapper.py
==============================================================================
--- pypy/dist/pypy/translator/c/wrapper.py	(original)
+++ pypy/dist/pypy/translator/c/wrapper.py	Sat Apr 29 03:43:15 2006
@@ -101,12 +101,14 @@
                  inputconst(Signed, nb_positional_args),
                  vargs,
                  ]
-        newops.genop('check_no_more_arg', vlist)
+        newops.genop('check_no_more_arg', vlist, resulttype=Signed)
 
     # use the rtyper to produce the conversions
     inputargs = f._obj.graph.getargs()
     if as_method:
         varguments.insert(0, vself)
+        vlist = [vfname, vself]
+        newops.genop('check_self_nonzero', vlist, resulttype=Signed)
     for i in range(len(varguments)):
         if FUNCTYPE.ARGS[i] != PyObjPtr:
             # "argument_i = type_conversion_operations(argument_i)"



More information about the Pypy-commit mailing list