[pypy-svn] r10558 - in pypy/dist/pypy/translator: . genc

arigo at codespeak.net arigo at codespeak.net
Tue Apr 12 19:17:14 CEST 2005


Author: arigo
Date: Tue Apr 12 19:17:14 2005
New Revision: 10558

Added:
   pypy/dist/pypy/translator/genc/list_include.h   (contents, props changed)
   pypy/dist/pypy/translator/genc/list_template.h   (contents, props changed)
   pypy/dist/pypy/translator/genc/listtype.py   (contents, props changed)
Modified:
   pypy/dist/pypy/translator/genc/ctyper.py
   pypy/dist/pypy/translator/genc/functype.py
   pypy/dist/pypy/translator/genc/g_include.h
   pypy/dist/pypy/translator/genc/tupletype.py
   pypy/dist/pypy/translator/typer.py
Log:
- added a draft (disabled) list support.

- moved the control of how to specialize operations to the type of their first
  argument.



Modified: pypy/dist/pypy/translator/genc/ctyper.py
==============================================================================
--- pypy/dist/pypy/translator/genc/ctyper.py	(original)
+++ pypy/dist/pypy/translator/genc/ctyper.py	Tue Apr 12 19:17:14 2005
@@ -5,12 +5,13 @@
 from __future__ import generators
 from pypy.translator.typer import Specializer
 from pypy.objspace.flow.model import Constant, Variable, SpaceOperation
-from pypy.annotation.model import SomeInteger, SomePBC, SomeTuple
+from pypy.annotation.model import SomeInteger, SomePBC, SomeTuple, SomeList
 from pypy.translator.genc.pyobjtype import CPyObjectType
 from pypy.translator.genc.inttype import CIntType
 from pypy.translator.genc.nonetype import CNoneType
 from pypy.translator.genc.functype import CFuncPtrType
 from pypy.translator.genc.tupletype import CTupleType
+from pypy.translator.genc.listtype import CListType
 import types
 from pypy.interpreter.pycode import CO_VARARGS
 
@@ -65,59 +66,34 @@
                 besttype = self.annotator.translator.getconcretetype(
                     CTupleType, tuple(items_ct))
 
+            # -- DISABLED while it's incomplete
+            #elif isinstance(s_value, SomeList):
+            #    item_ct = self.annotation2concretetype(s_value.s_item)
+            #    besttype = self.annotator.translator.getconcretetype(
+            #        CListType, item_ct)
+
         return besttype
 
     def specialized_op(self, op, bindings):
-        if op.opname == 'simple_call':
-            s_callable = self.annotator.binding(op.args[0], True)
-            if s_callable is not None:
-                ct = self.annotation2concretetype(s_callable)
-                if isinstance(ct, CFuncPtrType):
-                    argtypes = [ct]
-                    argtypes += ct.argtypes
-                    yield self.typed_op(op, argtypes, ct.returntype,
-                                        newopname='direct_call')
-                    return
-
-        if op.opname == 'newtuple':
-            s_tuple = self.annotator.binding(op.result, True)
-            if s_tuple is not None:
-                ctup = self.annotation2concretetype(s_tuple)
-                if isinstance(ctup, CTupleType):
-                    TInt  = self.TInt
-                    TNone = self.TNone
-                    v2 = op.result
-                    yield self.typed_op(SpaceOperation('tuple_new', [], v2),
-                                                                    [], ctup)
-                    for i in range(len(ctup.itemtypes)):
-                        vitem = op.args[i]
-                        ct = ctup.itemtypes[i]
-                        v0 = Variable()
-                        yield self.typed_op(SpaceOperation('tuple_setitem',
-                                   [v2,   Constant(i), vitem], v0),  # args, ret
-                                   [ctup, TInt,        ct   ], TNone) # a_t, r_t
-                        yield self.incref_op(vitem)
-                    return
-
-        if op.opname == 'getitem':
-            s_obj = self.annotator.binding(op.args[0], True)
-            if s_obj is not None:
-                ctup = self.annotation2concretetype(s_obj)
-                if isinstance(ctup, CTupleType):
-                    if isinstance(op.args[1], Constant):
-                        index = op.args[1].value
-                        try:
-                            ct = ctup.itemtypes[index]
-                        except IndexError:
-                            print "*** getitem: IndexError in tuple access"
-                        else:
-                            yield self.typed_op(op, [ctup, self.TInt], ct,
-                                                newopname='tuple_getitem')
-                            yield self.incref_op(op.result)
-                            return
-
+        if op.opname in ('newtuple', 'newlist'):
+            # operations that are controlled by their return type
+            s_binding = self.annotator.binding(op.result, True)
+        elif bindings:
+            # operations are by default controlled by their 1st arg
+            s_binding = bindings[0]
+        else:
+            s_binding = None
+
+        if s_binding is not None:
+            ct = self.annotation2concretetype(s_binding)
+            meth = getattr(ct, 'spec_' + op.opname, None)
+            if meth:
+                try:
+                    return meth(self, op)
+                except NotImplementedError:
+                    pass
         # fall-back
-        yield Specializer.specialized_op(self, op, bindings)
+        return Specializer.specialized_op(self, op, bindings)
 
 
     def incref_op(self, v):

Modified: pypy/dist/pypy/translator/genc/functype.py
==============================================================================
--- pypy/dist/pypy/translator/genc/functype.py	(original)
+++ pypy/dist/pypy/translator/genc/functype.py	Tue Apr 12 19:17:14 2005
@@ -35,3 +35,9 @@
         yield genc.loadincludefile('func_template.h') % {
             'typename': self.typename,
             }
+
+    def spec_simple_call(self, typer, op):
+        argtypes = [self]
+        argtypes += self.argtypes
+        yield typer.typed_op(op, argtypes, self.returntype,
+                             newopname='direct_call')

Modified: pypy/dist/pypy/translator/genc/g_include.h
==============================================================================
--- pypy/dist/pypy/translator/genc/g_include.h	(original)
+++ pypy/dist/pypy/translator/genc/g_include.h	Tue Apr 12 19:17:14 2005
@@ -15,6 +15,7 @@
 #include "g_module.h"
 
 #include "int_include.h"
+#include "list_include.h"
 #include "none_include.h"
 #include "pyobj_include.h"
 #include "tuple_include.h"

Added: pypy/dist/pypy/translator/genc/list_include.h
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/genc/list_include.h	Tue Apr 12 19:17:14 2005
@@ -0,0 +1,23 @@
+
+/************************************************************/
+ /***  C header subsection: generic operations on lists    ***/
+
+
+#define OP_LIST_FASTGETITEM(s,i,r,err)    r = s->items[i];
+#define OP_LIST_FASTSETITEM(s,i,o,r,err)  s->items[i] = o;  r = 0;
+#define OP_LIST_SETCOUNT(s,n,r,err)   s->count = n;     r = 0;
+
+#define OP_LIST_GETITEM(s,i,r,err)					      \
+	if (((unsigned) i) >= s->count) {				      \
+		PyErr_SetString(PyExc_IndexError, "list index out of range"); \
+		FAIL(err)						      \
+	}								      \
+	r = s->items[i];
+
+#define OP_LIST_SETITEM(s,i,o,r,err)					      \
+	if (((unsigned) i) >= s->count) {				      \
+		PyErr_SetString(PyExc_IndexError, "list index out of range"); \
+		FAIL(err)						      \
+	}								      \
+	s->items[i] = o;						      \
+	r = 0;

Added: pypy/dist/pypy/translator/genc/list_template.h
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/genc/list_template.h	Tue Apr 12 19:17:14 2005
@@ -0,0 +1,111 @@
+
+/************************************************************/
+ /***  C header template: list structure %(typename)s      ***/
+
+/* NB. list_N is the type "pointer to struct s_list_N" */
+
+typedef struct s_%(typename)s {
+	int refcount;
+	int count;
+	%(itemtypename)s* items;
+} *%(typename)s;
+
+static %(typename)s %(typename)s_allocate(int count)
+{
+	%(typename)s lst = (%(typename)s)
+		PyObject_Malloc(sizeof(struct s_%(typename)s));
+	if (lst == NULL)
+		return (%(typename)s) PyErr_NoMemory();
+	lst->refcount = 1;
+	lst->count = 0;   /* NOTE! initialized to 0, increase only when
+			     real items are put into the list */
+	if (count == 0) {
+		lst->items = NULL;
+	}
+	else {
+		size_t size = count * sizeof(%(itemtypename)s);
+		/* XXX overflow checking? */
+		lst->items = (%(itemtypename)s*) PyMem_Malloc(size);
+		if (lst->items == NULL) {
+			PyObject_Free(lst);
+			return (%(typename)s) PyErr_NoMemory();
+		}
+	}
+	return lst;
+}
+
+static int %(typename)s_resize(%(typename)s lst, int ncount)
+{
+	size_t nsize = ncount * sizeof(%(itemtypename)s);
+	/* XXX overflow checking? */
+	char* p = PyMem_Realloc((char*) lst->items, nsize);
+	if (p == NULL) {
+		PyErr_NoMemory();
+		return -1;
+	}
+	lst->count = ncount;
+	lst->items = (%(itemtypename)s*) p;
+	return 0;
+}
+
+static void %(typename)s_dealloc(%(typename)s lst)
+{
+	int i;
+	for (i=lst->count; i--; ) {
+		OP_DECREF_%(itemtypename)s(lst->items[i])
+	}
+	PyMem_Free((char*) lst->items);
+	PyObject_Free(lst);
+}
+
+#define OP_INCREF_%(typename)s(lst)   (lst)->refcount++;
+#define OP_DECREF_%(typename)s(lst)   if (!--(lst)->refcount) \
+						%(typename)s_dealloc(lst);
+
+/* Cannot convert between representations, because lists are mutable!
+   Changes to the original object don't show up in the converted one and
+   vice-versa. */
+
+#define CONV_TO_OBJ_%(typename)s     cannot do this!
+#define CONV_FROM_OBJ_%(typename)s   cannot do this!
+
+/* static PyObject* CONV_TO_OBJ_%(typename)s(%(typename)s lst) */
+/* { */
+/* 	int i, n = lst->count; */
+/* 	PyObject* result = PyList_New(n); */
+/* 	if (result == NULL) return NULL; */
+/* 	for (i=0; i<n; i++) { */
+/* 		PyObject* o = CONV_TO_OBJ_%(itemtypename)s(lst->items[i]); */
+/* 		if (o == NULL) { */
+/* 			Py_DECREF(result); */
+/* 			return NULL; */
+/* 		} */
+/* 		PyList_SET_ITEM(result, i, o); */
+/* 	} */
+/* 	return result; */
+/* } */
+
+/* static %(typename)s CONV_FROM_OBJ_%(typename)s(PyObject *lst) */
+/* { */
+/* 	%(typename)s result; */
+/* 	int i, n; */
+/* 	n = PyList_Size(lst); */
+/* 	if (n < 0) */
+/* 		return NULL; */
+/* 	result = %(typename)s_allocate(n); */
+/* 	if (result == NULL) */
+/* 		return NULL; */
+/* 	for (i=0; i<n; i++) { */
+/* 		result->items[i] = CONV_FROM_OBJ_%(itemtypename)s( */
+/* 			PyList_GET_ITEM(lst, i)); */
+/* 		if (PyErr_Occurred()) { */
+/* 			%(typename)s_dealloc(result); */
+/* 			return NULL; */
+/* 		} */
+/* 		result->count = i+1; */
+/* 	} */
+/* 	return result; */
+/* } */
+
+#define OP_ALLOC_%(TYPENAME)s(n, r, err)  \
+			if (!(r=%(typename)s_allocate(n))) FAIL(err)

Added: pypy/dist/pypy/translator/genc/listtype.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/genc/listtype.py	Tue Apr 12 19:17:14 2005
@@ -0,0 +1,88 @@
+from __future__ import generators
+from pypy.translator.genc.basetype import CType
+from pypy.objspace.flow.model import SpaceOperation, Constant, Variable
+
+
+class CListType(CType):
+    error_return  = 'NULL'
+
+    Counter = 0
+
+    def __init__(self, translator, itemtype):
+        super(CListType, self).__init__(translator)
+        self.itemtype = itemtype
+        self.itemtypename = itemtype.typename
+        self.typename = 'list_%d' % CListType.Counter
+        CListType.Counter += 1
+        self.cnames = {}
+        self.globaldecl = []
+
+    def debugname(self):
+        # a nice textual name for debugging...
+        return 'list(%s)' % (self.itemtype.debugname(),)
+
+    def init_globals(self, genc):
+        yield genc.loadincludefile('list_template.h') % {
+            'typename'    : self.typename,
+            'TYPENAME'    : self.typename.upper(),
+            'itemtypename': self.itemtypename,
+            }
+
+    def collect_globals(self, genc):
+        result = self.globaldecl
+        self.globaldecl = []
+        return result
+
+    def nameof(self, lst, debug=None):
+        key = Constant(lst).key
+        try:
+            return self.cnames[key]
+        except KeyError:
+            genc = self.genc()
+            name = genc.namespace.uniquename('g%dlst' % len(lst))
+            self.globaldecl.append('struct s_%s %s = {' % (self.typename, name))
+            self.globaldecl.append('\t1,  /* refcount */')
+            self.globaldecl.append('\t%d, /* count */' % len(lst))
+            if len(lst) == 0:
+                self.globaldecl.append('\tNULL /* items */')
+            else:
+                self.globaldecl.append('\t{   /* items */')
+                ct = self.itemtype
+                trail = [','] * (len(lst)-1) + ['']
+                for x, comma in zip(lst, trail):
+                    self.globaldecl.append('\t\t' +
+                                           genc.nameofvalue(x, ct) +
+                                           comma)
+                self.globaldecl.append('\t}')
+            self.globaldecl.append('}')
+            self.cnames[key] = name
+            return name
+
+    # ____________________________________________________________
+
+    def spec_newlist(self, typer, op):
+        TInt  = typer.TInt
+        TNone = typer.TNone
+        ct = self.itemtype
+        n = len(op.args)
+        v2 = op.result
+        yield typer.typed_op(SpaceOperation('alloc_'+self.typename,
+                       [Constant(n)], v2),    # args, ret
+                       [TInt       ], self)   # args_t, ret_t
+        for i in range(len(op.args)):
+            vitem = op.args[i]
+            v0 = Variable()
+            yield typer.typed_op(SpaceOperation('list_fastsetitem',
+                       [v2,   Constant(i), vitem], v0), # args, ret
+                       [self, TInt,        ct   ], TNone) # a_t,r_t
+            yield typer.incref_op(vitem)
+        v0 = Variable()
+        yield typer.typed_op(SpaceOperation('list_setcount',
+                       [v2,   Constant(n)], v0), # args, ret
+                       [self, TInt,      ], TNone) # a_t,r_t
+
+    def spec_getitem(self, typer, op):
+        ct = self.itemtype
+        yield typer.typed_op(op, [self, typer.TInt], ct,
+                             newopname='list_getitem')
+        yield typer.incref_op(op.result)

Modified: pypy/dist/pypy/translator/genc/tupletype.py
==============================================================================
--- pypy/dist/pypy/translator/genc/tupletype.py	(original)
+++ pypy/dist/pypy/translator/genc/tupletype.py	Tue Apr 12 19:17:14 2005
@@ -35,6 +35,7 @@
         self.generate_xxxref('DEC')
         self.generate_conv_to_obj()
         self.generate_conv_from_obj()
+        self.generate_new_tuple()
 
     def collect_globals(self, genc):
         result = self.globaldecl
@@ -127,3 +128,35 @@
             "\treturn %s;" % self.error_return,
             "}",
             ]
+
+    def generate_new_tuple(self):
+        macroargs = ', '.join(['x%d' % i for i in range(len(self.itemtypes))]
+                              + ['res', 'err'])
+        self.globaldecl += [
+            "#define OP_NEW_%s(%s) \\" % (self.typename.upper(), macroargs),
+            ]
+        for i, ct in zip(range(len(self.itemtypes)), self.itemtypes):
+            self.globaldecl += [
+                "\tres.f%d = x%d; OP_INCREF_%s(res.f%d) \\" %
+                    (i, i, ct.typename, i),
+                ]
+        self.globaldecl.append('\t/* end */')
+
+    # ____________________________________________________________
+
+    def spec_newtuple(self, typer, op):
+        yield typer.typed_op(op, self.itemtypes, self,
+                             newopname = 'new_%s' % self.typename)
+
+    def spec_getitem(self, typer, op):
+        if not isinstance(op.args[1], Constant):
+            raise NotImplementedError
+        index = op.args[1].value
+        try:
+            ct = self.itemtypes[index]
+        except IndexError:
+            print "*** getitem: IndexError in tuple access"
+            raise NotImplementedError
+        yield typer.typed_op(op, [self, typer.TInt], ct,
+                             newopname='tuple_getitem')
+        yield typer.incref_op(op.result)

Modified: pypy/dist/pypy/translator/typer.py
==============================================================================
--- pypy/dist/pypy/translator/typer.py	(original)
+++ pypy/dist/pypy/translator/typer.py	Tue Apr 12 19:17:14 2005
@@ -36,7 +36,8 @@
     def settype(self, a, concretetype):
         """Set the concretetype of a Variable or Constant."""
         if hasattr(a, 'concretetype') and a.concretetype != concretetype:
-            raise TyperError, "inconsitent type for %r" % (a,)
+            raise TyperError, "inconsitent type for %r: %r != %r" % (
+                a, a.concretetype, concretetype)
         a.concretetype = concretetype
 
     def setbesttype(self, a):



More information about the Pypy-commit mailing list