[pypy-svn] r12726 - in pypy/dist/pypy: rpython translator/c translator/c/test
arigo at codespeak.net
arigo at codespeak.net
Sun May 22 23:20:23 CEST 2005
Author: arigo
Date: Sun May 22 23:20:23 2005
New Revision: 12726
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:
Support for functions in c/database and c/node.
Missing: writing the body itself (duh).
Modified: pypy/dist/pypy/rpython/lltypes.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypes.py (original)
+++ pypy/dist/pypy/rpython/lltypes.py Sun May 22 23:20:23 2005
@@ -311,7 +311,7 @@
return val
def parentlink(container):
- parent = container._check()
+ parent = container._parentstructure()
if parent is not None:
return parent, container._wrparent_index
## if isinstance(parent, _struct):
@@ -455,18 +455,21 @@
self._wrparent = weakref.ref(parent)
self._wrparent_index = parentindex
- def _check(self):
+ def _parentstructure(self):
if self._wrparent is not None:
parent = self._wrparent()
if parent is None:
raise RuntimeError("accessing substructure %r,\n"
"but already garbage collected parent %r"
% (self, self._wrparent_type))
- else:
- parent._check()
- return parent
+ return parent
return None
+ def _check(self):
+ parent = self._parentstructure()
+ if parent is not None:
+ parent._check()
+
def __repr__(self):
return '<%s>' % (self,)
@@ -500,18 +503,21 @@
self._wrparent = weakref.ref(parent)
self._wrparent_index = parentindex
- def _check(self):
+ def _parentstructure(self):
if self._wrparent is not None:
parent = self._wrparent()
if parent is None:
raise RuntimeError("accessing subarray %r,\n"
"but already garbage collected parent %r"
% (self, self._wrparent_type))
- else:
- parent._check()
- return parent
+ return parent
return None
+ def _check(self):
+ parent = self._parentstructure()
+ if parent is not None:
+ parent._check()
+
def __repr__(self):
return '<%s>' % (self,)
@@ -526,6 +532,9 @@
self._callable = None
self.__dict__.update(attrs)
+ def _parentstructure(self):
+ return None
+
def _check(self):
if self._callable is None:
raise RuntimeError,"calling undefined function"
@@ -545,3 +554,8 @@
raise TypeError, "malloc for Structs and Arrays only"
return _ptr(GcPtr(T), o)
+def function(TYPE, name, **attrs):
+ if not isinstance(TYPE, FuncType):
+ raise TypeError, "function() for FuncTypes only"
+ o = _func(TYPE, _name=name, **attrs)
+ return _ptr(NonGcPtr(TYPE), o)
Modified: pypy/dist/pypy/translator/c/database.py
==============================================================================
--- pypy/dist/pypy/translator/c/database.py (original)
+++ pypy/dist/pypy/translator/c/database.py Sun May 22 23:20:23 2005
@@ -1,12 +1,12 @@
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 Struct, Array, FuncType, PyObject, Void
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
from pypy.translator.c.node import StructDefNode, ArrayDefNode
-from pypy.translator.c.node import ContainerNodeClass
+from pypy.translator.c.node import ContainerNodeClass, cdecl
# ____________________________________________________________
@@ -51,7 +51,7 @@
self.structdeflist.append(node)
return node
- def gettype(self, T, varlength=1, who_asks=None):
+ def gettype(self, T, varlength=1, who_asks=None, argnames=[]):
if isinstance(T, Primitive):
return PrimitiveType[T]
elif isinstance(T, _PtrType):
@@ -62,16 +62,20 @@
if who_asks is not None:
who_asks.dependencies[node] = True
return 'struct %s @' % node.name
- elif isinstance(T, PyObject):
+ elif T == PyObject:
return 'PyObject'
elif isinstance(T, FuncType):
resulttype = self.gettype(T.RESULT)
- argtypes = ', '.join([self.gettype(ARG) for ARG in T.ARGS
- if ARG != Void])
- if argtypes:
- argtypes = argtypes.replace('@', '')
- else:
- argtypes = 'void'
+ argtypes = []
+ for i in range(len(T.ARGS)):
+ if T.ARGS[i] != Void:
+ argtype = self.gettype(T.ARGS[i])
+ try:
+ argname = argnames[i]
+ except IndexError:
+ argname = ''
+ argtypes.append(cdecl(argtype, argname))
+ argtypes = ', '.join(argtypes) or 'void'
return resulttype.replace('@', '(@)(%s)' % argtypes)
else:
raise Exception("don't know about type %r" % (T,))
@@ -92,8 +96,11 @@
if isinstance(T, Primitive):
return PrimitiveName[T](obj)
elif isinstance(T, _PtrType):
- node = self.getcontainernode(obj._obj)
- return node.ptrname
+ if obj: # test if the ptr is non-NULL
+ node = self.getcontainernode(obj._obj)
+ return node.ptrname
+ else:
+ return 'NULL'
else:
raise Exception("don't know about %r" % (obj,))
@@ -109,3 +116,25 @@
for node in self.containerlist:
if node.globalcontainer:
yield node
+
+ def write_all_declarations(self, f):
+ print >> f
+ print >> f, '/********************************************************/'
+ print >> f, '/*** Structures definition ***/'
+ print >> f
+ for node in self.structdeflist:
+ print >> f, '\n'.join(node.definition())
+ print >> f
+ print >> f, '/********************************************************/'
+ print >> f, '/*** Forward declarations ***/'
+ print >> f
+ for node in self.globalcontainers():
+ print >> f, '\n'.join(node.forward_declaration())
+
+ def write_all_implementations(self, f):
+ print >> f
+ print >> f, '/********************************************************/'
+ print >> f, '/*** Implementations ***/'
+ print >> f
+ for node in self.globalcontainers():
+ print >> f, '\n'.join(node.implementation())
Modified: pypy/dist/pypy/translator/c/node.py
==============================================================================
--- pypy/dist/pypy/translator/c/node.py (original)
+++ pypy/dist/pypy/translator/c/node.py Sun May 22 23:20:23 2005
@@ -57,7 +57,7 @@
if needs_refcount(self.STRUCT):
yield '\tlong refcount;'
for name, typename in self.fields:
- yield '\t%s;' % typename.replace('@', name)
+ yield '\t%s;' % cdecl(typename, name)
yield '};'
@@ -83,8 +83,7 @@
if needs_refcount(self.ARRAY):
yield '\tlong refcount;'
yield '\tlong length;'
- yield '\t%s;' % self.structname.replace('@', 'items[%d]' %
- self.varlength)
+ yield '\t%s;' % cdecl(self.structname, 'items[%d]' % self.varlength)
yield '};'
@@ -113,12 +112,12 @@
def forward_declaration(self):
yield '%s; /* forward */' % (
- self.implementationtypename.replace('@', self.name))
+ cdecl(self.implementationtypename, self.name))
def implementation(self):
lines = list(self.initializationexpr())
lines[0] = '%s = %s' % (
- self.implementationtypename.replace('@', self.name),
+ cdecl(self.implementationtypename, self.name),
lines[0])
lines[-1] += ';'
return lines
@@ -188,11 +187,56 @@
yield '}'
+# XXX move FuncNode to funcdef.py
+from pypy.objspace.flow.model import *
+
class FuncNode(ContainerNode):
+
+ def __init__(self, db, T, obj):
+ graph = obj.graph # only user-defined functions with graphs for now
+ argnames = [v.name for v in graph.getargs()]
+ self.db = db
+ self.T = T
+ self.obj = obj
+ #self.dependencies = {}
+ self.typename = db.gettype(T) #, who_asks=self)
+ self.implementationtypename = db.gettype(T, argnames=argnames)
+ self.name = db.namespace.uniquename('g_' + self.basename())
+ self.globalcontainer = True
+ self.ptrname = self.name
+ # collect all variables and constants used in the body,
+ # and get their types now
+ result = []
+ def visit(block):
+ if isinstance(block, Block):
+ result.extend(block.inputargs)
+ for op in block.operations:
+ result.extend(op.args)
+ for link in block.exits:
+ result.extend(link.args)
+ traverse(visit, graph)
+ self.varmap = {}
+ for v in uniqueitems(result):
+ T = v.concretetype
+ self.varmap[v] = self.db.gettype(T)
+
def basename(self):
return self.obj._name
+
+ def allvariables(self):
+ return [v for v in self.varmap if isinstance(v, Variable)]
+
+ def allconstants(self):
+ return [v for v in self.varmap if isinstance(v, Constant)]
+
def enum_dependencies(self):
- Booom
+ return [c.value for c in self.allconstants()]
+
+ def implementation(self):
+ yield '%s {' % cdecl(self.implementationtypename, self.name)
+ yield '\tlots-of-strange-code'
+ yield '}'
+
class PyObjectNode(ContainerNode):
basename = 'BOOOM'
@@ -206,3 +250,16 @@
FuncType: FuncNode,
PyObject: PyObjectNode,
}
+
+#
+# helper
+#
+def cdecl(ctype, cname):
+ """
+ Produce a C declaration from a 'type template' and an identifier.
+ The type template must contain a '@' sign at the place where the
+ name should be inserted, according to the strange C syntax rules.
+ """
+ # the (@) case is for functions, where if there is a plain (@) around
+ # the function name, we don't need the very confusing parenthesis
+ return ctype.replace('(@)', '@').replace('@', cname).strip()
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 Sun May 22 23:20:23 2005
@@ -1,7 +1,8 @@
-import autopath
+import autopath, sys
from pypy.rpython.lltypes import *
from pypy.translator.c.database import LowLevelDatabase
-from pypy.objspace.flow.model import Constant
+from pypy.objspace.flow.model import Constant, Variable, SpaceOperation
+from pypy.objspace.flow.model import Block, Link, FunctionGraph
from pypy.rpython.lltypes import Struct, Array, malloc
@@ -60,12 +61,8 @@
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())
+ db.write_all_declarations(sys.stdout)
+ db.write_all_implementations(sys.stdout)
def test_codegen_2():
db = LowLevelDatabase()
@@ -79,12 +76,8 @@
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())
+ db.write_all_declarations(sys.stdout)
+ db.write_all_implementations(sys.stdout)
def test_codegen_3():
db = LowLevelDatabase()
@@ -103,9 +96,40 @@
s.anarray = cast_flags(NonGcPtr(A.y), a.y)
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())
+ db.write_all_declarations(sys.stdout)
+ db.write_all_implementations(sys.stdout)
+
+def test_func_simple():
+ # -------------------- flowgraph building --------------------
+ # def f(x):
+ # return x+1
+ x = Variable("x")
+ x.concretetype = Signed
+ result = Variable("result")
+ result.concretetype = Signed
+ one = Constant(1)
+ one.concretetype = Signed
+ op = SpaceOperation("int_add", [x, one], result)
+ block = Block([x])
+ graph = FunctionGraph("f", block)
+ block.operations.append(op)
+ block.closeblock(Link([result], graph.returnblock))
+ graph.getreturnvar().concretetype = Signed
+ # -------------------- end --------------------
+
+ F = FuncType([Signed], Signed)
+ f = function(F, "f", graph=graph)
+ db = LowLevelDatabase()
+ db.get(f)
+ db.complete()
+ db.write_all_declarations(sys.stdout)
+ db.write_all_implementations(sys.stdout)
+
+ S = GcStruct('testing', ('fptr', NonGcPtr(F)))
+ s = malloc(S)
+ s.fptr = f
+ db = LowLevelDatabase()
+ db.get(s)
+ db.complete()
+ db.write_all_declarations(sys.stdout)
+ db.write_all_implementations(sys.stdout)
More information about the Pypy-commit
mailing list