[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