[pypy-svn] r10263 - in pypy/dist/pypy/translator: . genc

arigo at codespeak.net arigo at codespeak.net
Sun Apr 3 00:43:42 CEST 2005


Author: arigo
Date: Sun Apr  3 00:43:42 2005
New Revision: 10263

Added:
   pypy/dist/pypy/translator/genc/parametric.py   (contents, props changed)
   pypy/dist/pypy/translator/genc/t_func.py   (contents, props changed)
Modified:
   pypy/dist/pypy/translator/genc/ctyper.py
   pypy/dist/pypy/translator/genc/funcdef.py
   pypy/dist/pypy/translator/typer.py
Log:
(Draft) support for the type "function pointer", which allows direct
shortcutting calls between generated functions to be reintroduced.

Uses a parametrization mecanism: for each C type "function taking arguments of
type T1,..,Tn and returning a T", there is a corresponding Python class that
is a dynamically created subclass, using the [] operator:

  pypy.translator.genc.t_func.CType_FuncPtr[T1, .., Tn, T]



Modified: pypy/dist/pypy/translator/genc/ctyper.py
==============================================================================
--- pypy/dist/pypy/translator/genc/ctyper.py	(original)
+++ pypy/dist/pypy/translator/genc/ctyper.py	Sun Apr  3 00:43:42 2005
@@ -3,9 +3,12 @@
 """
 
 from pypy.translator.typer import Specializer, TypeMatch
-from pypy.annotation.model import SomeInteger
+from pypy.annotation.model import SomeInteger, SomePBC
 from pypy.translator.genc.t_pyobj import CType_PyObject
 from pypy.translator.genc.t_int import CType_Int
+from pypy.translator.genc.t_func import CType_FuncPtr
+import types
+from pypy.interpreter.pycode import CO_VARARGS
 
 class GenCSpecializer(Specializer):
 
@@ -14,8 +17,42 @@
     defaulttypecls = CType_PyObject
 
     specializationtable = [
-        ## op      specialized op   arg types   concrete return type
-        ('add',     'int_add',     TInt, TInt,   CType_Int),
-        ('sub',     'int_sub',     TInt, TInt,   CType_Int),
-        ('is_true', 'int_is_true', TInt,         CType_Int),
+        ## op         specialized op   arg types   concrete return type
+        ('add',         'int_add',     TInt, TInt,   CType_Int),
+        ('inplace_add', 'int_add',     TInt, TInt,   CType_Int),
+        ('sub',         'int_sub',     TInt, TInt,   CType_Int),
+        ('inplace_sub', 'int_sub',     TInt, TInt,   CType_Int),
+        ('is_true',     'int_is_true', TInt,         CType_Int),
         ]
+
+    def annotation2typecls(self, s_value):
+        besttype = Specializer.annotation2typecls(self, s_value)
+        if besttype is None:
+
+            if isinstance(s_value, SomePBC):
+                # XXX! must be somehow unified with bookkeeper.pycall()!
+                # XXX  for now, we support the very simplest case only.
+                if (s_value.is_constant() and
+                    isinstance(s_value.const, types.FunctionType) and
+                    not (s_value.const.func_code.co_flags & CO_VARARGS) and
+                    s_value.const in self.annotator.translator.flowgraphs):
+                    
+                    graph = self.annotator.translator.flowgraphs[s_value.const]
+                    args_ct = [self.setbesttype(a) for a in graph.getargs()]
+                    res_ct = self.setbesttype(graph.getreturnvar())
+                    key = tuple(args_ct + [res_ct])
+                    besttype = CType_FuncPtr[key]
+
+        return besttype
+
+    def getspecializedop(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.annotation2typecls(s_callable)
+                if ct is not None and issubclass(ct, CType_FuncPtr):
+                    args_typecls = [ct]
+                    args_typecls += ct.args_typecls
+                    return 'direct_call', args_typecls, ct.return_typecls
+
+        return Specializer.getspecializedop(self, op, bindings)

Modified: pypy/dist/pypy/translator/genc/funcdef.py
==============================================================================
--- pypy/dist/pypy/translator/genc/funcdef.py	(original)
+++ pypy/dist/pypy/translator/genc/funcdef.py	Sun Apr  3 00:43:42 2005
@@ -475,6 +475,11 @@
         args = [arg.compute() for arg in args]
         return 'OP_CALL_ARGS((%s), %s, %s)' % (', '.join(args), r, err)
 
+    def OP_DIRECT_CALL(self, args, r, err):
+        args = [arg.compute() for arg in args]
+        return '%s = %s(%s); if (PyErr_Occurred()) FAIL(%s)' % (
+            r, args[0], ', '.join(args[1:]), err)
+
 # ____________________________________________________________
 
 class lazy:

Added: pypy/dist/pypy/translator/genc/parametric.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/genc/parametric.py	Sun Apr  3 00:43:42 2005
@@ -0,0 +1,41 @@
+import types
+
+
+class parametrictype(type):
+    """The metaclass of parametric type classes."""
+
+    def __getitem__(cls, key):
+        if '_parametrizedinstances_' not in cls.__dict__:
+            cls._parametrizedinstances_ = {}
+        elif cls._parametrizedinstances_ is None:
+            raise TypeError, "'%s' is already specialized" % cls.__name__
+        try:
+            return cls._parametrizedinstances_[key]
+        except KeyError:
+            keyrepr = recrepr(key)
+            if keyrepr.startswith('(') and keyrepr.endswith(')') and key != ():
+                keyrepr = keyrepr[1:-1]
+            newname = '%s[%s]' % (cls.__name__, keyrepr)
+            CType_Parametrized = type(cls)(newname, (cls,), {
+                '_parametrizedinstances_': None,
+                '__module__': cls.__module__,
+                })
+            cls._parametrizedinstances_[key] = CType_Parametrized
+            for basecls in CType_Parametrized.__mro__:
+                raw = basecls.__dict__.get('__initsubclass__')
+                if isinstance(raw, types.FunctionType):
+                    raw(CType_Parametrized, key)   # call it as a class method
+            return CType_Parametrized
+
+
+def recrepr(key):
+    if isinstance(key, tuple):
+        items = [recrepr(x) for x in key]
+        if len(items) == 1:
+            return '(%s,)' % (items[0],)
+        else:
+            return '(%s)' % (', '.join(items),)
+    try:
+        return key.__name__
+    except AttributeError:
+        return repr(key)

Added: pypy/dist/pypy/translator/genc/t_func.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/genc/t_func.py	Sun Apr  3 00:43:42 2005
@@ -0,0 +1,19 @@
+from pypy.translator.genc.parametric import parametrictype
+
+
+class CType_FuncPtr:
+    __metaclass__ = parametrictype
+
+    def __initsubclass__(cls, key):
+        cls.args_typecls = key[:-1]
+        cls.return_typecls = key[-1]
+        arglist = [tc.ctypetemplate % ('',) for tc in cls.args_typecls]
+        argtemplate = ', '.join(arglist or ['void'])
+        header = '(*%s)(' + argtemplate + ')'
+        cls.ctypetemplate = cls.return_typecls.ctypetemplate % (header,)
+
+    def __init__(self, genc):
+        self.genc = genc
+
+    def nameof(self, func, debug=None):
+        return self.genc.getfuncdef(func).fast_name

Modified: pypy/dist/pypy/translator/typer.py
==============================================================================
--- pypy/dist/pypy/translator/typer.py	(original)
+++ pypy/dist/pypy/translator/typer.py	Sun Apr  3 00:43:42 2005
@@ -50,13 +50,16 @@
             besttype = self.defaulttypecls
             s_value = self.annotator.binding(a, True)
             if s_value is not None:
-                for tmatch in self.typematches:
-                    if tmatch.s_type.contains(s_value):
-                        besttype = tmatch.type_cls
-                        break
+                besttype = self.annotation2typecls(s_value) or besttype
             self.settype(a, besttype)
             return besttype
 
+    def annotation2typecls(self, s_value):
+        for tmatch in self.typematches:
+            if tmatch.s_type.contains(s_value):
+                return tmatch.type_cls
+        return None
+
     def convertvar(self, v, type_cls):
         """Get the operation(s) needed to convert 'v' to the given type."""
         ops = []
@@ -111,6 +114,7 @@
 
             # look for a specialized version of the current operation
             opname2, argtypes, restypecls = self.getspecializedop(op, bindings)
+            assert len(argtypes) == len(args)
 
             # type-convert the input arguments
             for i in indices:



More information about the Pypy-commit mailing list