[pypy-svn] r12717 - in pypy/dist/pypy: rpython translator/c translator/c/test
arigo at codespeak.net
arigo at codespeak.net
Sat May 21 22:14:43 CEST 2005
Author: arigo
Date: Sat May 21 22:14:42 2005
New Revision: 12717
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:
Generating now static structure definitions, possibly nested ones.
Modified: pypy/dist/pypy/rpython/lltypes.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypes.py (original)
+++ pypy/dist/pypy/rpython/lltypes.py Sat May 21 22:14:42 2005
@@ -310,6 +310,17 @@
val = _ptr(_TmpPtr(T), val)
return val
+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")
+ else:
+ return None, None
+
class _ptr(object):
@@ -447,6 +458,8 @@
% (self, self._wrparent_type))
else:
parent._check()
+ return parent
+ return None
def __repr__(self):
return '<%s>' % (self,)
@@ -465,7 +478,6 @@
def __str__(self):
return 'struct %s { %s }' % (self._TYPE._name, self._str_fields())
-
class _array(object):
_wrparent = None
@@ -489,6 +501,8 @@
% (self, self._wrparent_type))
else:
parent._check()
+ return parent
+ return None
def __repr__(self):
return '<%s>' % (self,)
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 22:14:42 2005
@@ -1,6 +1,7 @@
from pypy.translator.gensupp import NameManager
from pypy.rpython.lltypes import Primitive, _PtrType, typeOf
from pypy.rpython.lltypes import Struct, Array, FuncType, PyObject
+from pypy.rpython.lltypes import ContainerType
from pypy.rpython.typer import PyObjPtr
from pypy.objspace.flow.model import Constant
from pypy.translator.c.primitive import PrimitiveName, PrimitiveType
@@ -31,6 +32,20 @@
else register union
''')
+ def gettypedefnode(self, T):
+ try:
+ node = self.structdefnodes[T]
+ except KeyError:
+ if isinstance(T, Struct):
+ node = StructDefNode(self, T)
+ elif isinstance(T, Array):
+ node = ArrayDefNode(self, T)
+ else:
+ raise Exception("don't know about %r" % (T,))
+ self.structdefnodes[T] = node
+ self.structdeflist.append(node)
+ return node
+
def gettype(self, T, who_asks=None):
if isinstance(T, Primitive):
return PrimitiveType[T]
@@ -38,15 +53,7 @@
typename = self.gettype(T.TO) # who_asks not propagated
return typename.replace('@', '*@')
elif isinstance(T, (Struct, Array)):
- try:
- node = self.structdefnodes[T]
- except KeyError:
- if isinstance(T, Struct):
- node = StructDefNode(self, T)
- else:
- node = ArrayDefNode(self, T)
- self.structdefnodes[T] = node
- self.structdeflist.append(node)
+ node = self.gettypedefnode(T)
if who_asks is not None:
who_asks.dependencies[node] = True
return 'struct %s @' % node.name
@@ -64,23 +71,36 @@
else:
raise Exception("don't know about type %r" % (T,))
+ def getcontainernode(self, container):
+ try:
+ node = self.containernodes[container]
+ except KeyError:
+ T = typeOf(container)
+ nodecls = ContainerNodeClass[T.__class__]
+ node = nodecls(self, T, container)
+ self.containernodes[container] = node
+ self.containerlist.append(node)
+ return node
+
def get(self, obj):
T = typeOf(obj)
if isinstance(T, Primitive):
return PrimitiveName[T](obj)
elif isinstance(T, _PtrType):
- try:
- node = self.containernodes[obj]
- except KeyError:
- nodecls = ContainerNodeClass[T.TO.__class__]
- node = nodecls(self, T.TO, obj)
- self.containernodes[obj] = node
- self.containerlist.append(node)
+ node = self.getcontainernode(obj._obj)
return node.ptrname
else:
raise Exception("don't know about %r" % (obj,))
def complete(self):
for node in self.containerlist:
- for value in node.enum_dependencies(self):
- self.get(value)
+ for value in node.enum_dependencies():
+ if isinstance(typeOf(value), ContainerType):
+ self.getcontainernode(value)
+ else:
+ self.get(value)
+
+ def globalcontainers(self):
+ for node in self.containerlist:
+ if node.globalcontainer:
+ yield node
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 22:14:42 2005
@@ -1,7 +1,27 @@
from __future__ import generators
from pypy.translator.gensupp import C_IDENTIFIER
-from pypy.rpython.lltypes import Struct, Array, FuncType, PyObject
-from pypy.rpython.lltypes import GcStruct, GcArray
+from pypy.rpython.lltypes import Struct, Array, FuncType, PyObject, typeOf
+from pypy.rpython.lltypes import GcStruct, GcArray, GC_CONTAINER, ContainerType
+from pypy.rpython.lltypes import parentlink
+
+
+def needs_refcount(T):
+ if not isinstance(T, GC_CONTAINER):
+ return False
+ if isinstance(T, GcStruct):
+ if T._names and isinstance(T._flds[T._names[0]], GC_CONTAINER):
+ return False # refcount already in the first first
+ return True
+
+def somelettersfrom(s):
+ upcase = [c for c in s if c.isupper()]
+ if not upcase:
+ upcase = [c for c in s.title() if c.isupper()]
+ locase = [c for c in s if c.islower()]
+ if locase and upcase:
+ return ''.join(upcase).lower()
+ else:
+ return s[:2].lower()
class StructDefNode:
@@ -10,10 +30,23 @@
self.STRUCT = STRUCT
self.name = db.namespace.uniquename(STRUCT._name)
self.dependencies = {}
- self.typenames = []
+ self.fields = []
+ self.prefix = somelettersfrom(STRUCT._name) + '_'
for name in STRUCT._names:
T = STRUCT._flds[name]
- self.typenames.append(db.gettype(T, who_asks=self))
+ typename = db.gettype(T, who_asks=self)
+ self.fields.append((self.c_struct_field_name(name), typename))
+
+ def c_struct_field_name(self, name):
+ return self.prefix + name
+
+ def definition(self):
+ yield 'struct %s {' % self.name
+ if needs_refcount(self.STRUCT):
+ yield '\tlong refcount;'
+ for name, typename in self.fields:
+ yield '\t%s;' % typename.replace('@', name)
+ yield '};'
class ArrayDefNode:
@@ -24,36 +57,85 @@
self.dependencies = {}
self.structname = db.gettype(ARRAY.OF, who_asks=self)
+ 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 '};'
+
class ContainerNode:
def __init__(self, db, T, obj):
+ self.db = db
self.T = T
self.obj = obj
- self.name = db.namespace.uniquename('g_' + self.basename())
- self.ptrname = '&' + self.name
- self.dependencies = {}
- self.typename = db.gettype(T, who_asks=self)
+ #self.dependencies = {}
+ self.typename = db.gettype(T) #, who_asks=self)
+ parent, fldname = parentlink(obj)
+ if parent is None:
+ self.name = db.namespace.uniquename('g_' + self.basename())
+ self.globalcontainer = True
+ else:
+ 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.ptrname = '&%s' % self.name
+
+ def forward_declaration(self):
+ yield '%s; /* forward */' % self.typename.replace('@', self.name)
+
+ def implementation(self):
+ lines = list(self.initializationexpr())
+ lines[0] = '%s = %s' % (self.typename.replace('@', self.name), lines[0])
+ lines[-1] += ';'
+ return lines
class StructNode(ContainerNode):
+
def basename(self):
return self.T._name
- def enum_dependencies(self, db):
+
+ def enum_dependencies(self):
for name in self.T._names:
yield getattr(self.obj, name)
+ def initializationexpr(self, prefix=''):
+ yield '{'
+ if needs_refcount(self.T):
+ yield '\t1,'
+ for name in self.T._names:
+ value = getattr(self.obj, name)
+ if isinstance(typeOf(value), ContainerType):
+ node = self.db.getcontainernode(value)
+ expr = '\n'.join(node.initializationexpr(prefix+name+'.'))
+ expr += ','
+ else:
+ expr = self.db.get(value)
+ i = expr.find('\n')
+ if i<0: i = len(expr)
+ expr = '%s,\t/* %s%s */%s' % (expr[:i], prefix, name, expr[i:])
+ expr = expr.replace('\n', '\n\t') # indentation
+ yield '\t%s' % expr
+ yield '}'
+
+
class ArrayNode(ContainerNode):
def basename(self):
return 'array'
- def enum_dependencies(self, db):
+ def enum_dependencies(self):
for i in range(len(self.obj)):
yield self.obj[i]
class FuncNode(ContainerNode):
def basename(self):
return self.obj._name
- def enum_dependencies(self, db):
+ def enum_dependencies(self):
Booom
class PyObjectNode(ContainerNode):
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 22:14:42 2005
@@ -17,7 +17,7 @@
s = malloc(S)
s.x = 42
assert db.get(s).startswith('&g_')
- assert db.containernodes.keys() == [s]
+ assert db.containernodes.keys() == [s._obj]
assert db.structdefnodes.keys() == [S]
def test_inlined_struct():
@@ -26,7 +26,7 @@
s = malloc(S)
s.x.y = 42
assert db.get(s).startswith('&g_')
- assert db.containernodes.keys() == [s]
+ assert db.containernodes.keys() == [s._obj]
assert len(db.structdefnodes) == 2
assert S in db.structdefnodes
assert S.x in db.structdefnodes
@@ -39,11 +39,30 @@
s.x = malloc(T)
s.x.y = 42
assert db.get(s).startswith('&g_')
- assert db.containernodes.keys() == [s]
+ assert db.containernodes.keys() == [s._obj]
db.complete()
assert len(db.containernodes) == 2
- assert s in db.containernodes
- assert s.x in db.containernodes
+ assert s._obj in db.containernodes
+ assert s.x._obj in db.containernodes
assert len(db.structdefnodes) == 2
assert S in db.structdefnodes
assert S.x.TO in db.structdefnodes
+
+def test_codegen():
+ db = LowLevelDatabase()
+ U = Struct('inlined', ('z', Signed))
+ T = GcStruct('subtest', ('y', Signed))
+ S = GcStruct('test', ('x', GcPtr(T)), ('u', U), ('p', NonGcPtr(U)))
+ s = malloc(S)
+ s.x = malloc(T)
+ s.x.y = 42
+ s.u.z = -100
+ s.p = cast_flags(NonGcPtr(U), s.u)
+ 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