[pypy-svn] r12719 - in pypy/dist/pypy: rpython translator/c translator/c/test
arigo at codespeak.net
arigo at codespeak.net
Sat May 21 23:21:55 CEST 2005
Author: arigo
Date: Sat May 21 23:21:55 2005
New Revision: 12719
Modified:
pypy/dist/pypy/rpython/lltypes.py
pypy/dist/pypy/translator/c/database.py
pypy/dist/pypy/translator/c/node.py
pypy/dist/pypy/translator/c/test/test_database.py
Log:
Very strange code, but does the job.
Generating variable-length, predefined global arrays in C is rather fun.
Modified: pypy/dist/pypy/rpython/lltypes.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypes.py (original)
+++ pypy/dist/pypy/rpython/lltypes.py Sat May 21 23:21:55 2005
@@ -27,7 +27,7 @@
def __str__(self):
return self.__class__.__name__
- def _defl(self, parent=None):
+ def _defl(self, parent=None, parentindex=None):
raise NotImplementedError
def _freeze_(self):
@@ -95,8 +95,8 @@
return "%s %s { %s }" % (self.__class__.__name__,
self._name, self._str_fields())
- def _defl(self, parent=None):
- return _struct(self, parent=parent)
+ def _defl(self, parent=None, parentindex=None):
+ return _struct(self, parent=parent, parentindex=parentindex)
def _container_example(self):
if self._arrayfld is None:
@@ -173,7 +173,7 @@
def __str__(self):
return self._name
- def _defl(self, parent=None):
+ def _defl(self, parent=None, parentindex=None):
return self._default
_example = _defl
@@ -211,7 +211,7 @@
def __str__(self):
return 'ptr(%s) to %s' % (self._str_flags(), self.TO)
- def _defl(self, parent=None):
+ def _defl(self, parent=None, parentindex=None):
return _ptr(self, None)
def _example(self):
@@ -313,11 +313,16 @@
def parentlink(container):
parent = container._check()
if parent is not None:
- assert isinstance(parent, _struct)
- for name in parent._TYPE._names:
- if getattr(parent, name) is container:
- return parent, name
- raise RuntimeError("lost ourselves")
+ return parent, container._wrparent_index
+## if isinstance(parent, _struct):
+## for name in parent._TYPE._names:
+## if getattr(parent, name) is container:
+## return parent, name
+## raise RuntimeError("lost ourselves")
+## if isinstance(parent, _array):
+## raise TypeError("cannot fish a pointer to an array item or an "
+## "inlined substructure of it")
+## raise AssertionError("don't know about %r" % (parent,))
else:
return None, None
@@ -431,7 +436,7 @@
class _struct(object):
_wrparent = None
- def __init__(self, TYPE, n=None, parent=None):
+ def __init__(self, TYPE, n=None, parent=None, parentindex=None):
self._TYPE = TYPE
if n is not None and TYPE._arrayfld is None:
raise TypeError("%r is not variable-sized" % (TYPE,))
@@ -439,15 +444,16 @@
raise TypeError("%r is variable-sized" % (TYPE,))
for fld, typ in TYPE._flds.items():
if isinstance(typ, Struct):
- value = _struct(typ, parent=self)
+ value = _struct(typ, parent=self, parentindex=fld)
elif fld == TYPE._arrayfld:
- value = _array(typ, n, parent=self)
+ value = _array(typ, n, parent=self, parentindex=fld)
else:
value = typ._defl()
setattr(self, fld, value)
if parent is not None:
self._wrparent_type = typeOf(parent)
self._wrparent = weakref.ref(parent)
+ self._wrparent_index = parentindex
def _check(self):
if self._wrparent is not None:
@@ -481,16 +487,18 @@
class _array(object):
_wrparent = None
- def __init__(self, TYPE, n, parent=None):
+ def __init__(self, TYPE, n, parent=None, parentindex=None):
if not isinstance(n, int):
raise TypeError, "array length must be an int"
if n < 0:
raise ValueError, "negative array length"
self._TYPE = TYPE
- self.items = [TYPE.OF._defl(parent=self) for j in range(n)]
+ self.items = [TYPE.OF._defl(parent=self, parentindex=j)
+ for j in range(n)]
if parent is not None:
self._wrparent_type = typeOf(parent)
self._wrparent = weakref.ref(parent)
+ self._wrparent_index = parentindex
def _check(self):
if self._wrparent is not None:
Modified: pypy/dist/pypy/translator/c/database.py
==============================================================================
--- pypy/dist/pypy/translator/c/database.py (original)
+++ pypy/dist/pypy/translator/c/database.py Sat May 21 23:21:55 2005
@@ -32,28 +32,33 @@
else register union
''')
- def gettypedefnode(self, T):
+ def gettypedefnode(self, T, varlength=1):
+ if varlength <= 1:
+ varlength = 1 # it's C after all
+ key = T
+ else:
+ key = T, varlength
try:
- node = self.structdefnodes[T]
+ node = self.structdefnodes[key]
except KeyError:
if isinstance(T, Struct):
node = StructDefNode(self, T)
elif isinstance(T, Array):
- node = ArrayDefNode(self, T)
+ node = ArrayDefNode(self, T, varlength)
else:
raise Exception("don't know about %r" % (T,))
- self.structdefnodes[T] = node
+ self.structdefnodes[key] = node
self.structdeflist.append(node)
return node
- def gettype(self, T, who_asks=None):
+ def gettype(self, T, varlength=1, who_asks=None):
if isinstance(T, Primitive):
return PrimitiveType[T]
elif isinstance(T, _PtrType):
typename = self.gettype(T.TO) # who_asks not propagated
return typename.replace('@', '*@')
elif isinstance(T, (Struct, Array)):
- node = self.gettypedefnode(T)
+ node = self.gettypedefnode(T, varlength=varlength)
if who_asks is not None:
who_asks.dependencies[node] = True
return 'struct %s @' % node.name
Modified: pypy/dist/pypy/translator/c/node.py
==============================================================================
--- pypy/dist/pypy/translator/c/node.py (original)
+++ pypy/dist/pypy/translator/c/node.py Sat May 21 23:21:55 2005
@@ -40,6 +40,10 @@
def c_struct_field_name(self, name):
return self.prefix + name
+ def access_expr(self, baseexpr, fldname):
+ fldname = self.c_struct_field_name(fldname)
+ return '%s.%s' % (baseexpr, fldname)
+
def definition(self):
yield 'struct %s {' % self.name
if needs_refcount(self.STRUCT):
@@ -51,18 +55,28 @@
class ArrayDefNode:
- def __init__(self, db, ARRAY):
+ def __init__(self, db, ARRAY, varlength):
self.ARRAY = ARRAY
- self.name = db.namespace.uniquename('array')
+ if varlength == 1:
+ basename = 'array'
+ else:
+ basename = db.gettypedefnode(ARRAY).name
+ basename = '%s_len%d' % (basename, varlength)
+ self.name = db.namespace.uniquename(basename)
self.dependencies = {}
self.structname = db.gettype(ARRAY.OF, who_asks=self)
+ self.varlength = varlength
+
+ def access_expr(self, baseexpr, index):
+ return '%s.items[%d]' % (baseexpr, index)
def definition(self):
yield 'struct %s {' % self.name
if needs_refcount(self.ARRAY):
yield '\tlong refcount;'
yield '\tlong length;'
- yield '\t%s;' % self.structname.replace('@', 'items[1]')
+ yield '\t%s;' % self.structname.replace('@', 'items[%d]' %
+ self.varlength)
yield '};'
@@ -74,27 +88,36 @@
self.obj = obj
#self.dependencies = {}
self.typename = db.gettype(T) #, who_asks=self)
- parent, fldname = parentlink(obj)
+ self.implementationtypename = db.gettype(T, varlength=self.getlength())
+ parent, parentindex = parentlink(obj)
if parent is None:
self.name = db.namespace.uniquename('g_' + self.basename())
self.globalcontainer = True
else:
+ self.globalcontainer = False
parentnode = db.getcontainernode(parent)
defnode = db.gettypedefnode(parentnode.T)
- fldname = defnode.c_struct_field_name(fldname)
- self.name = parentnode.name + '.' + fldname
- self.globalcontainer = False
+ self.name = defnode.access_expr(parentnode.name, parentindex)
self.ptrname = '&%s' % self.name
+ if self.typename != self.implementationtypename:
+ self.ptrname = '((%s)(void*)%s)' % (self.typename.replace('@', '*'),
+ self.ptrname)
def forward_declaration(self):
- yield '%s; /* forward */' % self.typename.replace('@', self.name)
+ yield '%s; /* forward */' % (
+ self.implementationtypename.replace('@', self.name))
def implementation(self):
lines = list(self.initializationexpr())
- lines[0] = '%s = %s' % (self.typename.replace('@', self.name), lines[0])
+ lines[0] = '%s = %s' % (
+ self.implementationtypename.replace('@', self.name),
+ lines[0])
lines[-1] += ';'
return lines
+ def getlength(self):
+ return 1
+
class StructNode(ContainerNode):
@@ -126,11 +149,28 @@
class ArrayNode(ContainerNode):
+
def basename(self):
return 'array'
+
def enum_dependencies(self):
- for i in range(len(self.obj)):
- yield self.obj[i]
+ return self.obj.items
+
+ def getlength(self):
+ return len(self.obj.items)
+
+ def initializationexpr(self, prefix=''):
+ yield '{'
+ if needs_refcount(self.T):
+ yield '\t1,'
+ yield '\t%d,' % len(self.obj.items)
+ for j in range(len(self.obj.items)):
+ node = self.db.getcontainernode(self.obj.items[j])
+ expr = '\n'.join(node.initializationexpr('%s%d.' % (prefix, j)))
+ expr += ','
+ expr = expr.replace('\n', '\n\t') # indentation
+ yield '\t%s' % expr
+ yield '}'
class FuncNode(ContainerNode):
def basename(self):
Modified: pypy/dist/pypy/translator/c/test/test_database.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_database.py (original)
+++ pypy/dist/pypy/translator/c/test/test_database.py Sat May 21 23:21:55 2005
@@ -66,3 +66,22 @@
print '\n'.join(node.forward_declaration())
for node in db.globalcontainers():
print '\n'.join(node.implementation())
+
+def test_codegen_2():
+ db = LowLevelDatabase()
+ A = GcArray(('x', Signed))
+ S = GcStruct('test', ('aptr', GcPtr(A)))
+ a = malloc(A, 3)
+ a[0].x = 100
+ a[1].x = 101
+ a[2].x = 102
+ s = malloc(S)
+ s.aptr = a
+ db.get(s)
+ db.complete()
+ for node in db.structdeflist:
+ print '\n'.join(node.definition())
+ for node in db.globalcontainers():
+ print '\n'.join(node.forward_declaration())
+ for node in db.globalcontainers():
+ print '\n'.join(node.implementation())
More information about the Pypy-commit
mailing list