[pypy-svn] r6880 - in pypy/trunk/src/pypy/translator: . test

arigo at codespeak.net arigo at codespeak.net
Sun Oct 10 11:15:45 CEST 2004


Author: arigo
Date: Sun Oct 10 11:15:44 2004
New Revision: 6880

Modified:
   pypy/trunk/src/pypy/translator/genc.h
   pypy/trunk/src/pypy/translator/genc.py
   pypy/trunk/src/pypy/translator/test/test_ctrans.py
Log:
Enabled all tests again (without type annotations), and made them pass:
* added most numeric operations to genc.h
* support for classes, implemented as regular Python heap types,
  with instances storing attributes as usual in their __dict__
* tuple constants

The short genc.{py,h} together with the flow objspace now implement most of
the equivalent of the old Python2C: translating Python bytecode to C code
calling the abstract.h functions, without any type-based optimizations.



Modified: pypy/trunk/src/pypy/translator/genc.h
==============================================================================
--- pypy/trunk/src/pypy/translator/genc.h	(original)
+++ pypy/trunk/src/pypy/translator/genc.h	Sun Oct 10 11:15:44 2004
@@ -22,12 +22,50 @@
 				}				\
 				Py_INCREF(r);
 
+#define OP_NEG(x,r,err)           if (!(r=PyNumber_Negative(x)))     goto err;
+#define OP_POS(x,r,err)           if (!(r=PyNumber_Positive(x)))     goto err;
+#define OP_INVERT(x,r,err)        if (!(r=PyNumber_Invert(x)))       goto err;
+
 #define OP_ADD(x,y,r,err)         if (!(r=PyNumber_Add(x,y)))        goto err;
 #define OP_SUB(x,y,r,err)         if (!(r=PyNumber_Subtract(x,y)))   goto err;
 #define OP_MUL(x,y,r,err)         if (!(r=PyNumber_Multiply(x,y)))   goto err;
+#define OP_TRUEDIV(x,y,r,err)     if (!(r=PyNumber_TrueDivide(x,y))) goto err;
+#define OP_FLOORDIV(x,y,r,err)    if (!(r=PyNumber_FloorDivide(x,y)))goto err;
 #define OP_DIV(x,y,r,err)         if (!(r=PyNumber_Divide(x,y)))     goto err;
 #define OP_MOD(x,y,r,err)         if (!(r=PyNumber_Remainder(x,y)))  goto err;
-#define OP_INPLACE_ADD(x,y,r,err) if(!(r=PyNumber_InPlaceAdd(x,y)))  goto err;
+#define OP_POW(x,y,r,err)         if (!(r=PyNumber_Power(x,y,Py_None)))goto err;
+#define OP_LSHIFT(x,y,r,err)      if (!(r=PyNumber_Lshift(x,y)))     goto err;
+#define OP_RSHIFT(x,y,r,err)      if (!(r=PyNumber_Rshift(x,y)))     goto err;
+#define OP_AND_(x,y,r,err)        if (!(r=PyNumber_And(x,y)))        goto err;
+#define OP_OR_(x,y,r,err)         if (!(r=PyNumber_Or(x,y)))         goto err;
+#define OP_XOR(x,y,r,err)         if (!(r=PyNumber_Xor(x,y)))        goto err;
+
+#define OP_INPLACE_ADD(x,y,r,err) if (!(r=PyNumber_InPlaceAdd(x,y)))           \
+								     goto err;
+#define OP_INPLACE_SUB(x,y,r,err) if (!(r=PyNumber_InPlaceSubtract(x,y)))      \
+								     goto err;
+#define OP_INPLACE_MUL(x,y,r,err) if (!(r=PyNumber_InPlaceMultiply(x,y)))      \
+								     goto err;
+#define OP_INPLACE_TRUEDIV(x,y,r,err) if (!(r=PyNumber_InPlaceTrueDivide(x,y)))\
+								     goto err;
+#define OP_INPLACE_FLOORDIV(x,y,r,err)if(!(r=PyNumber_InPlaceFloorDivide(x,y)))\
+								     goto err;
+#define OP_INPLACE_DIV(x,y,r,err) if (!(r=PyNumber_InPlaceDivide(x,y)))        \
+								     goto err;
+#define OP_INPLACE_MOD(x,y,r,err) if (!(r=PyNumber_InPlaceRemainder(x,y)))     \
+								     goto err;
+#define OP_INPLACE_POW(x,y,r,err) if (!(r=PyNumber_InPlacePower(x,y,Py_None))) \
+								     goto err;
+#define OP_INPLACE_LSHIFT(x,y,r,err) if (!(r=PyNumber_InPlaceLshift(x,y)))     \
+								     goto err;
+#define OP_INPLACE_RSHIFT(x,y,r,err) if (!(r=PyNumber_InPlaceRshift(x,y)))     \
+								     goto err;
+#define OP_INPLACE_AND(x,y,r,err)    if (!(r=PyNumber_InPlaceAnd(x,y)))        \
+								     goto err;
+#define OP_INPLACE_OR(x,y,r,err)     if (!(r=PyNumber_InPlaceOr(x,y)))         \
+								     goto err;
+#define OP_INPLACE_XOR(x,y,r,err)    if (!(r=PyNumber_InPlaceXor(x,y)))        \
+								     goto err;
 
 #define OP_GETITEM(x,y,r,err)     if (!(r=PyObject_GetItem(x,y)))    goto err;
 #define OP_SETITEM(x,y,z,r,err)   if ((PyObject_SetItem(x,y,z))<0)   goto err; \
@@ -57,6 +95,69 @@
 
 #define MOVE(x, y)             y = x;
 
+#define INITCHK(expr)          if (!(expr)) return;
+
+
+/*** classes ***/
+
+#define SETUP_CLASS(t, name, base)				\
+	t = PyObject_CallFunction((PyObject*) &PyType_Type,	\
+				  "s(O){}", name, base)
+
+#define SETUP_CLASS_ATTR(t, attr, value)	\
+	(PyObject_SetAttrString(t, attr, value) >= 0)
+
+/* we need a subclass of 'builtin_function_or_method' which can be used
+   as methods: builtin function objects that can be bound on instances */
+static PyObject *
+gencfunc_descr_get(PyObject *func, PyObject *obj, PyObject *type)
+{
+	if (obj == Py_None)
+		obj = NULL;
+	return PyMethod_New(func, obj, type);
+}
+static PyTypeObject PyGenCFunction_Type = {
+	PyObject_HEAD_INIT(NULL)
+	0,
+	"pypy_generated_function",
+	sizeof(PyCFunctionObject),
+	0,
+	0,					/* tp_dealloc */
+	0,					/* tp_print */
+	0,					/* tp_getattr */
+	0,					/* tp_setattr */
+	0,					/* tp_compare */
+	0,					/* tp_repr */
+	0,					/* tp_as_number */
+	0,					/* tp_as_sequence */
+	0,					/* tp_as_mapping */
+	0,					/* tp_hash */
+	0,					/* tp_call */
+	0,					/* tp_str */
+	0,					/* tp_getattro */
+	0,					/* tp_setattro */
+	0,					/* tp_as_buffer */
+	Py_TPFLAGS_DEFAULT,			/* tp_flags */
+	0,					/* tp_doc */
+	0,					/* tp_traverse */
+	0,					/* tp_clear */
+	0,					/* tp_richcompare */
+	0,					/* tp_weaklistoffset */
+	0,					/* tp_iter */
+	0,					/* tp_iternext */
+	0,					/* tp_methods */
+	0,					/* tp_members */
+	0,					/* tp_getset */
+	/*&PyCFunction_Type set below*/ 0,	/* tp_base */
+	0,					/* tp_dict */
+	gencfunc_descr_get,			/* tp_descr_get */
+	0,					/* tp_descr_set */
+};
+
+#define SETUP_MODULE						\
+	PyGenCFunction_Type.tp_base = &PyCFunction_Type;	\
+	PyType_Ready(&PyGenCFunction_Type);
+
 
 /*** operations with a variable number of arguments ***/
 

Modified: pypy/trunk/src/pypy/translator/genc.py
==============================================================================
--- pypy/trunk/src/pypy/translator/genc.py	(original)
+++ pypy/trunk/src/pypy/translator/genc.py	Sun Oct 10 11:15:44 2004
@@ -69,7 +69,8 @@
         else:
             name = 'gint_minus%d' % abs(value)
         self.globaldecl.append('static PyObject* %s;' % name)
-        self.initcode.append('%s = PyInt_FromLong(%d);' % (name, value))
+        self.initcode.append('INITCHK(%s = '
+                             'PyInt_FromLong(%d))' % (name, value))
         return name
 
     def nameof_str(self, value):
@@ -87,15 +88,16 @@
         else:
             # printable string
             s = '"%s"' % value
-        self.initcode.append('%s = PyString_FromStringAndSize(%s, %d);' % (
-            name, s, len(value)))
+        self.initcode.append('INITCHK(%s = PyString_FromStringAndSize('
+                             '%s, %d))' % (name, s, len(value)))
         return name
 
     def nameof_function(self, func):
         name = self.uniquename('gfunc_' + func.__name__)
         self.globaldecl.append('static PyObject* %s;' % name)
-        self.initcode.append('%s = PyCFunction_New(&ml_%s, NULL);' % (name,
-                                                                      name))
+        self.initcode.append('INITCHK(%s = PyCFunction_New('
+                             '&ml_%s, NULL))' % (name, name))
+        self.initcode.append('\t%s->ob_type = &PyGenCFunction_Type;' % name)
         self.pendingfunctions.append(func)
         return name
 
@@ -105,11 +107,50 @@
             '%r is not from __builtin__' % (func,))
         name = self.uniquename('gbltin_' + func.__name__)
         self.globaldecl.append('static PyObject* %s;' % name)
-        self.initcode.append('%s = PyMapping_GetItemString('
-                             'PyEval_GetBuiltins(), "%s");' % (
+        self.initcode.append('INITCHK(%s = PyMapping_GetItemString('
+                             'PyEval_GetBuiltins(), "%s"))' % (
             name, func.__name__))
         return name
 
+    def nameof_classobj(self, cls):
+        name = self.uniquename('gcls_' + cls.__name__)
+        bases = [base for base in cls.__bases__ if base is not object]
+        assert len(bases) <= 1, "%r needs multiple inheritance" % (cls,)
+        if bases:
+            base = self.nameof(bases[0])
+        else:
+            base = '(PyObject*) &PyBaseObject_Type'
+        content = cls.__dict__.items()
+        content.sort()
+        lines = []
+        for key, value in content:
+            if key.startswith('__'):
+                continue
+            lines.append('INITCHK(SETUP_CLASS_ATTR(%s, "%s", %s))' % (
+                name, key, self.nameof(value)))
+        self.globaldecl.append('static PyObject* %s;' % name)
+        self.initcode.append('INITCHK(SETUP_CLASS(%s, "%s", %s))' % (
+            name, cls.__name__, base))
+        self.initcode.extend(lines)
+        return name
+
+    def nameof_type(self, cls):
+        assert hasattr(cls, '__weakref__'), (
+            "%r is not a user-defined class" % (cls,))
+        return self.nameof_classobj(cls)
+
+    def nameof_tuple(self, tup):
+        name = self.uniquename('g%dtuple' % len(tup))
+        lines = []
+        for i in range(len(tup)):
+            item = self.nameof(tup[i])
+            lines.append('\tPy_INCREF(%s);' % item)
+            lines.append('\tPyTuple_SET_ITEM(%s, %d, %s);' % (name, i, item))
+        self.globaldecl.append('static PyObject* %s;' % name)
+        self.initcode.append('INITCHK(%s = PyTuple_New(%d))' % (name, len(tup)))
+        self.initcode.extend(lines)
+        return name
+
     def gen_source(self):
         f = self.f
         info = {
@@ -245,7 +286,7 @@
             if len(block.exits) == 0:
                 yield 'return %s;' % expr(block.inputargs[0])
                 continue
-            if block.exitswitch is not None:
+            if len(block.exits) > 1:
                 for link in block.exits[:-1]:
                     yield 'if (EQ_%s(%s)) {' % (link.exitcase,
                                                 block.exitswitch.name)
@@ -277,6 +318,7 @@
 void init%(modname)s(void)
 {
 \tPyObject* m = Py_InitModule("%(modname)s", NULL);
+\tSETUP_MODULE
 '''
 
     C_INIT_FOOTER = '''

Modified: pypy/trunk/src/pypy/translator/test/test_ctrans.py
==============================================================================
--- pypy/trunk/src/pypy/translator/test/test_ctrans.py	(original)
+++ pypy/trunk/src/pypy/translator/test/test_ctrans.py	Sun Oct 10 11:15:44 2004
@@ -84,21 +84,20 @@
         self.assertEquals(sand(0, 6), "no")
         self.assertEquals(sand(0, 0), "no")
 
-if 0:
-  class TypedTestCase(testit.IntTestCase):
+class TypedTestCase(testit.IntTestCase):
 
     def getcompiled(self, func):
         t = Translator(func) 
         t.simplify()
-        # builds starting-types from func_defs 
-        argstypelist = []
-        if func.func_defaults:
-            for spec in func.func_defaults:
-                if isinstance(spec, tuple):
-                    spec = spec[0] # use the first type only for the tests
-                argstypelist.append(spec)
-        a = t.annotate(argstypelist)
-        a.simplify()
+##        # builds starting-types from func_defs 
+##        argstypelist = []
+##        if func.func_defaults:
+##            for spec in func.func_defaults:
+##                if isinstance(spec, tuple):
+##                    spec = spec[0] # use the first type only for the tests
+##                argstypelist.append(spec)
+##        a = t.annotate(argstypelist)
+##        a.simplify()
         return t.ccompile()
 
     def test_set_attr(self):
@@ -132,10 +131,10 @@
     def test_call_five(self):
         call_five = self.getcompiled(snippet.call_five)
         result = call_five()
-        #self.assertEquals(result, [5])
+        self.assertEquals(result, [5])
         # --  currently result isn't a real list, but a pseudo-array
         #     that can't be inspected from Python.
-        self.assertEquals(result.__class__.__name__[:8], "list of ")
+        #self.assertEquals(result.__class__.__name__[:8], "list of ")
 
     def test_call_unpack_56(self):
         call_unpack_56 = self.getcompiled(snippet.call_unpack_56)



More information about the Pypy-commit mailing list