[pypy-svn] r12298 - in pypy/dist/pypy/translator: . c c/test

arigo at codespeak.net arigo at codespeak.net
Sun May 15 17:10:02 CEST 2005


Author: arigo
Date: Sun May 15 17:10:01 2005
New Revision: 12298

Added:
   pypy/dist/pypy/translator/c/   (props changed)
   pypy/dist/pypy/translator/c/__init__.py
      - copied unchanged from r12256, pypy/dist/pypy/translator/genc/__init__.py
   pypy/dist/pypy/translator/c/autopath.py
      - copied unchanged from r12256, pypy/dist/pypy/translator/genc/autopath.py
   pypy/dist/pypy/translator/c/database.py   (contents, props changed)
   pypy/dist/pypy/translator/c/funcdef.py
      - copied, changed from r12256, pypy/dist/pypy/translator/genc/funcdef.py
   pypy/dist/pypy/translator/c/node.py   (contents, props changed)
   pypy/dist/pypy/translator/c/primitive.py   (contents, props changed)
   pypy/dist/pypy/translator/c/pyobj.py
      - copied, changed from r12256, pypy/dist/pypy/translator/genc/pyobjtype.py
   pypy/dist/pypy/translator/c/repr.py   (contents, props changed)
   pypy/dist/pypy/translator/c/struct.py   (contents, props changed)
   pypy/dist/pypy/translator/c/test/   (props changed)
   pypy/dist/pypy/translator/c/test/__init__.py
      - copied unchanged from r12256, pypy/dist/pypy/translator/genc/test/__init__.py
   pypy/dist/pypy/translator/c/test/autopath.py
      - copied unchanged from r12256, pypy/dist/pypy/translator/genc/test/autopath.py
   pypy/dist/pypy/translator/c/test/test_database.py   (contents, props changed)
Modified:
   pypy/dist/pypy/translator/translator.py
Log:
Checking in an attempt at a cleaner C code generator, sitting in my working
copy from yesterday.  Not finished in any way!  Doesn't run!


Added: pypy/dist/pypy/translator/c/database.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/c/database.py	Sun May 15 17:10:01 2005
@@ -0,0 +1,86 @@
+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.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
+
+# ____________________________________________________________
+
+class LowLevelDatabase:
+
+    def __init__(self):
+        self.structdefnodes = {}
+        self.structdeflist = []
+        self.containernodes = {}
+        self.containerlist = []
+        self.namespace = NameManager()
+        # keywords cannot be reused.  This is the C99 draft's list.
+        self.namespace.make_reserved_names('''
+           auto      enum      restrict  unsigned
+           break     extern    return    void
+           case      float     short     volatile
+           char      for       signed    while
+           const     goto      sizeof    _Bool
+           continue  if        static    _Complex
+           default   inline    struct    _Imaginary
+           do        int       switch
+           double    long      typedef
+           else      register  union
+           ''')
+
+    def gettype(self, T, 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)):
+            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)
+            if who_asks is not None:
+                who_asks.dependencies[node] = True
+            return 'struct %s @' % node.name
+        elif isinstance(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'
+            return resulttype.replace('@', '(@)(%s)' % argtypes)
+        else:
+            raise Exception("don't know about type %r" % (T,))
+
+    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)
+            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)

Copied: pypy/dist/pypy/translator/c/funcdef.py (from r12256, pypy/dist/pypy/translator/genc/funcdef.py)
==============================================================================
--- pypy/dist/pypy/translator/genc/funcdef.py	(original)
+++ pypy/dist/pypy/translator/c/funcdef.py	Sun May 15 17:10:01 2005
@@ -6,10 +6,7 @@
 from pypy.objspace.flow.model import last_exception
 from pypy.translator.simplify import simplify_graph
 from pypy.translator.unsimplify import remove_direct_loops
-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.pyobjtype import CBorrowedPyObjectType
+from pypy.rpython.typer import PyObjPtr
 from pypy.interpreter.pycode import CO_VARARGS
 from pypy.tool.compile import compile2
 from types import FunctionType
@@ -98,15 +95,12 @@
 
 
     def ctypeof(self, var_or_const):
-        try:
-            return var_or_const.concretetype
-        except AttributeError:
-            return self.genc.pyobjtype
+        return getattr(var_or_const, 'concretetype', PyObjPtr)
 
     def get_globalobject(self):
         if self.globalobject_name is None:
             self.wrapper_name = 'py' + self.fast_name
-            self.globalobject_name = self.genc.pyobjtype.uniquename('gfunc_' +
+            self.globalobject_name = self.genc.pyobj.uniquename('gfunc_' +
                                                           self.base_name)
         return self.globalobject_name
 

Added: pypy/dist/pypy/translator/c/node.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/c/node.py	Sun May 15 17:10:01 2005
@@ -0,0 +1,67 @@
+from __future__ import generators
+from pypy.translator.gensupp import C_IDENTIFIER
+from pypy.rpython.lltypes import Struct, Array, FuncType, PyObject
+
+
+class StructDefNode:
+
+    def __init__(self, db, STRUCT):
+        self.STRUCT = STRUCT
+        self.name = db.namespace.uniquename(STRUCT._name)
+        self.dependencies = {}
+        self.typenames = []
+        for name in STRUCT._names:
+            T = STRUCT._flds[name]
+            self.typenames.append(db.gettype(T, who_asks=self))
+
+
+class ArrayDefNode:
+
+    def __init__(self, db, ARRAY):
+        self.ARRAY = ARRAY
+        self.name = db.namespace.uniquename('array')
+        self.dependencies = {}
+        self.structname = db.gettype(ARRAY.OF, who_asks=self)
+
+
+class ContainerNode:
+
+    def __init__(self, db, T, obj):
+        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)
+
+
+class StructNode(ContainerNode):
+    def basename(self):
+        return self.T._name
+    def enum_dependencies(self, db):
+        for name in self.T._names:
+            yield getattr(self.obj, name)
+
+class ArrayNode(ContainerNode):
+    def basename(self):
+        return 'array'
+    def enum_dependencies(self, db):
+        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):
+        Booom
+
+class PyObjectNode(ContainerNode):
+    basename = 'BOOOM'
+
+
+ContainerNodeClass = {
+    Struct:   StructNode,
+    Array:    ArrayNode,
+    FuncType: FuncNode,
+    PyObject: PyObjectNode,
+    }

Added: pypy/dist/pypy/translator/c/primitive.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/c/primitive.py	Sun May 15 17:10:01 2005
@@ -0,0 +1,42 @@
+from pypy.rpython.lltypes import *
+
+# ____________________________________________________________
+#
+# Primitives
+
+def name_signed(value):
+    return '%d' % value
+
+def name_unsigned(value):
+    assert value >= 0
+    return '%d' % value
+
+def name_char(value):
+    value = value
+    assert type(value) is str and len(value) == 1
+    if ' ' <= value < '\x7f':
+        return "'%s'" % (value.replace("'", r"\'"),)
+    else:
+        return '%d' % ord(value)
+
+def name_bool(value):
+    return '%d' % value
+
+def name_void(value):
+    return '/* nothing */'
+
+PrimitiveName = {
+    Signed:   name_signed,
+    Unsigned: name_unsigned,
+    Char:     name_char,
+    Bool:     name_bool,
+    Void:     name_void,
+    }
+
+PrimitiveType = {
+    Signed:   'long @',
+    Unsigned: 'unsigned long @',
+    Char:     'char @',
+    Bool:     'char @',
+    Void:     'void @',
+    }

Copied: pypy/dist/pypy/translator/c/pyobj.py (from r12256, pypy/dist/pypy/translator/genc/pyobjtype.py)
==============================================================================
--- pypy/dist/pypy/translator/genc/pyobjtype.py	(original)
+++ pypy/dist/pypy/translator/c/pyobj.py	Sun May 15 17:10:01 2005
@@ -1,9 +1,12 @@
 from __future__ import generators
 import autopath, os, sys, __builtin__, marshal, zlib
+from types import FunctionType, CodeType, InstanceType, ClassType
+
 from pypy.objspace.flow.model import Variable, Constant
 from pypy.translator.gensupp import builtin_base, NameManager
-from pypy.translator.genc.basetype import CType
-from types import FunctionType, CodeType, InstanceType, ClassType
+from pypy.translator.c.repr import Repr
+
+from pypy.translator.gensupp import builtin_base, NameManager
 
 from pypy.rpython.rarithmetic import r_int, r_uint
 
@@ -13,17 +16,16 @@
 # Should this be registered with the annotator?
 from pypy.interpreter.baseobjspace import ObjSpace
 
-class CPyObjectType(CType):
-    """The PyObject* C type.
+
+class ReprPyObject(Repr):
+    """Handles 'PyObject*'; factored out from GenC.
     This class contains all the nameof_xxx() methods that allow a wild variety
     of Python objects to be 'pickled' as Python source code that will
     reconstruct them.
     """
-    typename      = 'pyobj'
-    error_return  = 'NULL'
 
     def __init__(self, translator):
-        super(CPyObjectType, self).__init__(translator)
+        self.translator = translator
         self.namespace = NameManager()
         # keywords cannot be reused.  This is the C99 draft's list.
         self.namespace.make_reserved_names('''
@@ -435,9 +437,6 @@
     def later(self, gen):
         self.latercode.append((gen, self.debugstack))
 
-    def init_globals(self, genc):
-        yield 'typedef PyObject* pyobj;'
-
     def collect_globals(self, genc):
         while self.latercode:
             gen, self.debugstack = self.latercode.pop()
@@ -471,11 +470,3 @@
         co = compile(source, genc.modname, 'exec')
         del source
         return marshal.dumps(co)
-
-
-class CBorrowedPyObjectType(CType):
-    typename      = 'borrowedpyobj'
-    error_return  = 'NULL'
-
-    def init_globals(self, genc):
-        yield 'typedef PyObject* borrowedpyobj;'

Added: pypy/dist/pypy/translator/c/repr.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/c/repr.py	Sun May 15 17:10:01 2005
@@ -0,0 +1,17 @@
+
+class Repr:
+    """Base class: a representation of a constant value of a specific type.
+    Each Repr instance knows how to generate C code that defines the
+    corresponding value, and which C expression can be used to read it.
+    """
+    def __init__(self, db, lowleveltype, value):
+        self.db = db
+        self.lowleveltype = lowleveltype
+        self.value = value
+
+    def follow_references(self):
+        pass
+
+    def follow_type_references(db, lowleveltype):
+        pass
+    follow_type_references = staticmethod(follow_type_references)

Added: pypy/dist/pypy/translator/c/struct.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/c/struct.py	Sun May 15 17:10:01 2005
@@ -0,0 +1,12 @@
+from pypy.rpython.lltypes import *
+from pypy.translator.c.repr import Repr
+
+
+class ReprStruct(Repr):
+
+    def follow_type_references(db, lowleveltype):
+        T = lowleveltype.TO
+        assert isinstance(T, Struct)
+        for name in T._names:
+            db.getlltype(T._flds[name])
+    follow_type_references = staticmethod(follow_type_references)

Added: pypy/dist/pypy/translator/c/test/test_database.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/c/test/test_database.py	Sun May 15 17:10:01 2005
@@ -0,0 +1,49 @@
+import autopath
+from pypy.rpython.lltypes import *
+from pypy.translator.c.database import LowLevelDatabase
+from pypy.objspace.flow.model import Constant
+from pypy.rpython.lltypes import Struct, Array, malloc
+
+
+
+def test_primitive():
+    db = LowLevelDatabase()
+    assert db.get(5) == '5'
+    assert db.get(True) == '1'
+
+def test_struct():
+    db = LowLevelDatabase()
+    S = Struct('test', ('x', Signed))
+    s = malloc(S)
+    s.x = 42
+    assert db.get(s).startswith('&g_')
+    assert db.containernodes.keys() == [s]
+    assert db.structdefnodes.keys() == [S]
+
+def test_inlined_struct():
+    db = LowLevelDatabase()
+    S = Struct('test', ('x', Struct('subtest', ('y', Signed))))
+    s = malloc(S)
+    s.x.y = 42
+    assert db.get(s).startswith('&g_')
+    assert db.containernodes.keys() == [s]
+    assert len(db.structdefnodes) == 2
+    assert S in db.structdefnodes
+    assert S.x in db.structdefnodes
+
+def test_complete():
+    db = LowLevelDatabase()
+    T = Struct('subtest', ('y', Signed))
+    S = Struct('test', ('x', GcPtr(T)))
+    s = malloc(S)
+    s.x = malloc(T)
+    s.x.y = 42
+    assert db.get(s).startswith('&g_')
+    assert db.containernodes.keys() == [s]
+    db.complete()
+    assert len(db.containernodes) == 2
+    assert s in db.containernodes
+    assert s.x in db.containernodes
+    assert len(db.structdefnodes) == 2
+    assert S in db.structdefnodes
+    assert S.x.TO in db.structdefnodes

Modified: pypy/dist/pypy/translator/translator.py
==============================================================================
--- pypy/dist/pypy/translator/translator.py	(original)
+++ pypy/dist/pypy/translator/translator.py	Sun May 15 17:10:01 2005
@@ -279,6 +279,7 @@
 ##            return impossiblevalue
 
     def getconcretetype(self, cls, *args):
+        "DEPRECATED.  To be removed"
         # Return a (cached) 'concrete type' object attached to this translator.
         # Concrete types are what is put in the 'concretetype' attribute of
         # the Variables and Constants of the flow graphs by typer.py to guide



More information about the Pypy-commit mailing list