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

arigo at codespeak.net arigo at codespeak.net
Fri Apr 8 13:29:43 CEST 2005


Author: arigo
Date: Fri Apr  8 13:29:42 2005
New Revision: 10430

Added:
   pypy/dist/pypy/translator/genc/g_simple.h
      - copied unchanged from r10428, pypy/dist/pypy/translator/genc/g_int.h
   pypy/dist/pypy/translator/genc/t_simple.py
      - copied, changed from r10428, pypy/dist/pypy/translator/genc/t_int.py
Removed:
   pypy/dist/pypy/translator/genc/g_int.h
   pypy/dist/pypy/translator/genc/parametric.py
   pypy/dist/pypy/translator/genc/t_int.py
Modified:
   pypy/dist/pypy/translator/genc/ctyper.py
   pypy/dist/pypy/translator/genc/funcdef.py
   pypy/dist/pypy/translator/genc/g_include.h
   pypy/dist/pypy/translator/genc/genc.py
   pypy/dist/pypy/translator/genc/t_func.py
   pypy/dist/pypy/translator/genc/t_pyobj.py
   pypy/dist/pypy/translator/tool/graphpage.py
   pypy/dist/pypy/translator/translator.py
   pypy/dist/pypy/translator/typer.py
   pypy/dist/pypy/translator/unsimplify.py
Log:
A good clean-up of the CType_Xxx classes: it is no more creating parametrized
subclasses on-the-fly.  Instead, the CXxxType classes are instantiated and
cached in the translator.  Each instance stands for a specific concrete type
in the code generator.  For example, there is one CIntType instance in the
translator, but generally several CFuncPtrType instances, one per function
signature.



Modified: pypy/dist/pypy/translator/genc/ctyper.py
==============================================================================
--- pypy/dist/pypy/translator/genc/ctyper.py	(original)
+++ pypy/dist/pypy/translator/genc/ctyper.py	Fri Apr  8 13:29:42 2005
@@ -2,36 +2,46 @@
 GenC-specific type specializer
 """
 
-from pypy.translator.typer import Specializer, TypeMatch
-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, CType_None
-from pypy.translator.genc.t_func import CType_FuncPtr
+from __future__ import generators
+from pypy.translator.typer import Specializer
+from pypy.objspace.flow.model import Constant, Variable, SpaceOperation
+from pypy.annotation.model import SomeInteger, SomePBC, SomeTuple
+from pypy.translator.genc.t_pyobj import CPyObjectType
+from pypy.translator.genc.t_simple import CIntType, CNoneType
+from pypy.translator.genc.t_func import CFuncPtrType
 import types
 from pypy.interpreter.pycode import CO_VARARGS
 
 class GenCSpecializer(Specializer):
 
-    TInt  = TypeMatch(SomeInteger(), CType_Int)
-    TNone = TypeMatch(SomePBC({None: True}), CType_None)
-
-    # in more-specific-first, more-general-last order
-    typematches = [TNone, TInt]
-
-    defaulttypecls = CType_PyObject
-
-    specializationtable = [
-        ## 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:
+    def __init__(self, annotator):
+        # instantiate the common concrete types
+        t = annotator.translator
+        TInt      = t.getconcretetype(CIntType)
+        TNone     = t.getconcretetype(CNoneType)
+        TPyObject = t.getconcretetype(CPyObjectType)
+
+        # initialization
+        Specializer.__init__(
+            self, annotator,
+            defaultconcretetype = TPyObject,
+
+            # in more-specific-first, more-general-last order
+            typematches = [TNone, TInt],
+
+            specializationtable = [
+                ## op         specialized op   arg types   concrete return type
+                ('add',         'int_add',     TInt, TInt,   TInt),
+                ('inplace_add', 'int_add',     TInt, TInt,   TInt),
+                ('sub',         'int_sub',     TInt, TInt,   TInt),
+                ('inplace_sub', 'int_sub',     TInt, TInt,   TInt),
+                ('is_true',     'int_is_true', TInt,         TInt),
+                ],
+            )
+
+    def annotation2concretetype(self, s_value):
+        besttype = Specializer.annotation2concretetype(self, s_value)
+        if besttype == self.defaultconcretetype:
 
             if isinstance(s_value, SomePBC):
                 # XXX! must be somehow unified with bookkeeper.pycall()!
@@ -44,19 +54,59 @@
                     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]
+                    besttype = self.annotator.translator.getconcretetype(
+                        CFuncPtrType, tuple(args_ct), res_ct)
+
+##            elif isinstance(s_value, SomeTuple):
+##                key = tuple([self.annotation2concretetype(s_item)
+##                             for s_item in s_value.items])
+##                besttype = CType_Tuple[key]
 
         return besttype
 
-    def getspecializedop(self, op, bindings):
+    def make_specialized_op(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
+                ct = self.annotation2concretetype(s_callable)
+                if isinstance(ct, CFuncPtrType):
+                    argtypes = [ct]
+                    argtypes += ct.argtypes
+                    self.make_typed_op(op, argtypes, ct.returntype,
+                                       newopname='direct_call')
+                    return
+
+##        if op.opname == 'getitem':
+##            s_obj = self.annotator.binding(op.args[0], True)
+##            if s_obj is not None:
+##                ct = self.annotation2typecls(s_obj)
+##                if issubclass(ct, CType_Tuple):
+##                    if isinstance(op.args[1], Constant):
+##                        index = op.args[1].value
+##                        try:
+##                            ct1 = ct.items_typecls[index]
+##                        except IndexError:
+##                            print "*** getitem: IndexError in tuple access"
+##                        else:
+##                            self.make_typed_op(op, [ct, CType_Int], ct1,
+##                                               newopname='tuple_getitem')
+##                            return
+
+##        if op.opname == 'newtuple':
+##            s_tuple = self.annotator.binding(op.result, True)
+##            if s_tuple is not None:
+##                ct = self.annotation2typecls(s_tuple)
+##                if issubclass(ct, CType_Tuple):
+##                    op1 = SpaceOperation('tuple_new', [], op.result)
+##                    self.make_typed_op(op1, [], ct)
+##                    for i in range(len(ct.items_typecls)):
+##                        op1 = SpaceOperation('tuple_inititem',
+##                                         [op.result, Constant(i), op.args[i]],
+##                                         Variable())
+##                        ct1 = ct.items_typecls[i]
+##                        self.make_typed_op(op1,
+##                                           [ct, CType_Int, ct1],
+##                                           CType_None)
+##                    return
 
-        return Specializer.getspecializedop(self, op, bindings)
+        Specializer.make_specialized_op(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	Fri Apr  8 13:29:42 2005
@@ -8,7 +8,6 @@
 from types import FunctionType
 
 from pypy.translator.gensupp import c_string
-from pypy.translator.genc.t_pyobj import ctypeof
 
 # Set this if you want call trace frames to be built
 USE_CALL_TRACE = False
@@ -68,12 +67,12 @@
             declare_fast_args.insert(0, 'TRACE_ARGS')
         declare_fast_args = ', '.join(declare_fast_args) or 'void'
         name_and_arguments = '%s(%s)' % (self.fast_name, declare_fast_args)
-        ctret = ctypeof(graph.getreturnvar())
+        ctret = self.ctypeof(graph.getreturnvar())
         fast_function_header = 'static ' + (
             ctret.ctypetemplate % (name_and_arguments,))
 
-        name_of_defaults = [self.genc.pyobjrepr.nameof(x, debug=('Default argument of',
-                                                       self))
+        name_of_defaults = [self.genc.nameofvalue(x, debug=(
+                                                   'Default argument of', self))
                             for x in (func.func_defaults or ())]
 
         # store misc. information
@@ -91,10 +90,16 @@
         self.genc.globaldecl.append(fast_function_header + ';  /* forward */')
 
 
+    def ctypeof(self, var_or_const):
+        try:
+            return var_or_const.concretetype
+        except AttributeError:
+            return self.genc.pyobjtype
+
     def get_globalobject(self):
         if self.globalobject_name is None:
             self.wrapper_name = 'py' + self.fast_name
-            self.globalobject_name = self.genc.pyobjrepr.uniquename('gfunc_' +
+            self.globalobject_name = self.genc.pyobjtype.uniquename('gfunc_' +
                                                           self.base_name)
         return self.globalobject_name
 
@@ -105,7 +110,8 @@
 
     def decl(self, v):
         assert isinstance(v, Variable)
-        return ctypeof(v).ctypetemplate % (self.localscope.localname(v.name),)
+        ct = self.ctypeof(v)
+        return ct.ctypetemplate % (self.localscope.localname(v.name),)
 
     def expr(self, v):
         if isinstance(v, Variable):
@@ -119,6 +125,8 @@
     # ____________________________________________________________
 
     def gen_wrapper(self, f):
+        # XXX this is a huge mess.  Think about producing the wrapper by
+        #     generating its content as a flow graph...
         func             = self.func
         f_name           = self.wrapper_name
         name_of_defaults = self.name_of_defaults
@@ -151,13 +159,12 @@
         conversions = []
         call_fast_args = []
         for a, numberedname in zip(graphargs, numberednames):
-            try:
-                convert_from_obj = a.type_cls.convert_from_obj
-            except AttributeError:
+            ct = self.ctypeof(a)
+            if ct == self.genc.pyobjtype:
                 call_fast_args.append(numberedname)
             else:
+                convert_from_obj = ct.opname_conv_from_obj  # simple conv only!
                 convertedname = numberedname.replace('o', 'a')
-                ct = ctypeof(a)
                 print >> f, '\t%s;' % (ct.ctypetemplate % (convertedname,))
                 conversions.append('\tOP_%s(%s, %s, type_error)' % (
                     convert_from_obj.upper(), numberedname, convertedname))
@@ -165,13 +172,13 @@
                 # XXX even though they are not PyObjects
                 call_fast_args.append(convertedname)
         # return value conversion
-        try:
-            convert_to_obj = self.ctret.convert_to_obj
-        except AttributeError:
+        ct = self.ctret
+        if ct == self.genc.pyobjtype:
             putresultin = 'oret'
             footer = None
         else:
-            print >> f, '\t%s;' % (self.ctret.ctypetemplate % ('aret',))
+            convert_to_obj = ct.opname_conv_to_obj  # simple conv only for now!
+            print >> f, '\t%s;' % (ct.ctypetemplate % ('aret',))
             putresultin = 'aret'
             footer = 'OP_%s(aret, oret, type_error)' % convert_to_obj.upper()
         print >> f
@@ -254,7 +261,7 @@
         
         # generate an incref for each input argument
         for a in self.graphargs:
-            cincref = getattr(ctypeof(a), 'cincref', None)
+            cincref = self.ctypeof(a).cincref
             if cincref:
                 print >> f, '\t' + cincref % (self.expr(a),)
 
@@ -297,15 +304,14 @@
                 if a1 in has_ref:
                     del has_ref[a1]
                 else:
-                    ct1 = ctypeof(a1)
-                    ct2 = ctypeof(a2)
+                    ct1 = self.ctypeof(a1)
+                    ct2 = self.ctypeof(a2)
                     assert ct1 == ct2
-                    cincref = getattr(ct1, 'cincref', None)
-                    if cincref:
-                        line += '\t' + cincref % (self.expr(a2),)
+                    if ct1.cincref:
+                        line += '\t' + ct1.cincref % (self.expr(a2),)
                 yield line
             for v in has_ref:
-                cdecref = getattr(ctypeof(v), 'cdecref', None)
+                cdecref = self.ctypeof(v).cdecref
                 if cdecref:
                     yield cdecref % (linklocalvars[v],)
             yield 'goto block%d;' % blocknum[link.target]
@@ -370,7 +376,7 @@
                 for link in block.exits[1:]:
                     assert issubclass(link.exitcase, Exception)
                     yield 'if (PyErr_ExceptionMatches(%s)) {' % (
-                        self.genc.pyobjrepr.nameof(link.exitcase),)
+                        self.genc.nameofvalue(link.exitcase),)
                     yield '\tPyObject *exc_cls, *exc_value, *exc_tb;'
                     yield '\tPyErr_Fetch(&exc_cls, &exc_value, &exc_tb);'
                     yield '\tif (exc_value == NULL) {'
@@ -386,7 +392,7 @@
                 err_reachable = True
             else:
                 # block ending in a switch on a value
-                ct = ctypeof(block.exitswitch)
+                ct = self.ctypeof(block.exitswitch)
                 for link in block.exits[:-1]:
                     assert link.exitcase in (False, True)
                     yield 'if (%s == %s) {' % (self.expr(block.exitswitch),
@@ -405,12 +411,12 @@
             while to_release:
                 v = to_release.pop()
                 if err_reachable:
-                    if not hasattr(v, 'type_cls'):
-                        yield 'ERR_DECREF(%s)' % self.expr(v)
+                    if not hasattr(v, 'concretetype'):
+                        cdecref = 'ERR_DECREF(%s)'
                     else:
-                        cdecref = getattr(ctypeof(v), 'cdecref', None)
-                        if cdecref:
-                            yield cdecref % (self.expr(v),)
+                        cdecref = v.concretetype.cdecref
+                    if cdecref:
+                        yield cdecref % (self.expr(v),)
                 yield 'err%d_%d:' % (blocknum[block], len(to_release))
                 err_reachable = True
             if err_reachable:

Modified: pypy/dist/pypy/translator/genc/g_include.h
==============================================================================
--- pypy/dist/pypy/translator/genc/g_include.h	(original)
+++ pypy/dist/pypy/translator/genc/g_include.h	Fri Apr  8 13:29:42 2005
@@ -11,7 +11,7 @@
 #include "eval.h"
 
 #include "g_operation.h"
-#include "g_int.h"
+#include "g_simple.h"
 #include "g_trace.h"
 #include "g_support.h"
 #include "g_module.h"

Deleted: /pypy/dist/pypy/translator/genc/g_int.h
==============================================================================
--- /pypy/dist/pypy/translator/genc/g_int.h	Fri Apr  8 13:29:42 2005
+++ (empty file)
@@ -1,16 +0,0 @@
-
-/************************************************************/
- /***  C header subsection: operations between ints        ***/
-
-
-#define OP_INT2OBJ(i,r,err)   if (!(r=PyInt_FromLong(i))) FAIL(err)
-#define OP_OBJ2INT(o,r,err)   if ((r=PyInt_AsLong(o))==-1 && PyErr_Occurred()) \
-							  FAIL(err)
-
-#define OP_NONE2OBJ(n,r,err)  r = Py_None; Py_INCREF(r);
-#define OP_OBJ2NONE(o,n,err)  assert(o == Py_None); n = 0;
-
-#define OP_INT_IS_TRUE(x,r,err)   r = (x != 0);
-
-#define OP_INT_ADD(x,y,r,err)     r = x + y;
-#define OP_INT_SUB(x,y,r,err)     r = x - y;

Modified: pypy/dist/pypy/translator/genc/genc.py
==============================================================================
--- pypy/dist/pypy/translator/genc/genc.py	(original)
+++ pypy/dist/pypy/translator/genc/genc.py	Fri Apr  8 13:29:42 2005
@@ -5,11 +5,11 @@
 import autopath, os
 from pypy.objspace.flow.model import Variable, Constant
 
+from pypy.interpreter.miscutils import getthreadlocals
 from pypy.translator.gensupp import uniquemodulename
-from pypy.translator.gensupp import NameManager
 
 from pypy.translator.genc.funcdef import FunctionDef, USE_CALL_TRACE
-from pypy.translator.genc.t_pyobj import CType_PyObject, ctypeof
+from pypy.translator.genc.t_pyobj import CPyObjectType
 
 # ____________________________________________________________
 
@@ -27,42 +27,29 @@
         self.translator = translator
         self.modname = (modname or
                         uniquemodulename(translator.functions[0].__name__))
-        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
-           ''')
         self.globaldecl = []
         self.pendingfunctions = []
         self.funcdefs = {}
         self.allfuncdefs = []
-        self.ctyperepresenters = {}
-        self.pyobjrepr = self.getrepresenter(CType_PyObject)
-        self.gen_source()
+        self.pyobjtype = translator.getconcretetype(CPyObjectType)
+        self.namespace = self.pyobjtype.namespace
 
-    def getrepresenter(self, type_cls):
+        assert not hasattr(getthreadlocals(), 'genc')
+        getthreadlocals().genc = self
         try:
-            return self.ctyperepresenters[type_cls]
-        except KeyError:
-            crepr = self.ctyperepresenters[type_cls] = type_cls(self)
-            return crepr
+            self.gen_source()
+        finally:
+            del getthreadlocals().genc
 
     def nameofconst(self, c, debug=None):
-        crepr = self.getrepresenter(ctypeof(c))
-        return crepr.nameof(c.value, debug=debug)
+        try:
+            concretetype = c.concretetype
+        except AttributeError:
+            concretetype = self.pyobjtype
+        return concretetype.nameof(c.value, debug=debug)
 
-    def nameofvalue(self, value, type_cls):
-        crepr = self.getrepresenter(type_cls)
-        return crepr.nameof(value)
+    def nameofvalue(self, value, concretetype=None, debug=None):
+        return (concretetype or self.pyobjtype).nameof(value, debug=debug)
 
     def getfuncdef(self, func):
         if func not in self.funcdefs:
@@ -86,7 +73,7 @@
         info = {
             'modname': self.modname,
             'entrypointname': self.translator.functions[0].__name__,
-            'entrypoint': self.pyobjrepr.nameof(self.translator.functions[0]),
+            'entrypoint': self.pyobjtype.nameof(self.translator.functions[0]),
             }
         # header
         if USE_CALL_TRACE:
@@ -97,10 +84,6 @@
         while self.pendingfunctions:
             funcdef = self.pendingfunctions.pop()
             self.gen_cfunction(funcdef)
-            # collect more of the latercode after each function
-            for crepr in self.ctyperepresenters.values():
-                if hasattr(crepr, 'collect_globals'):
-                    crepr.collect_globals()
             self.gen_global_declarations()
 
         # after all the ff_xxx() functions we generate the pyff_xxx() wrappers
@@ -110,7 +93,7 @@
 
         # global object table
         print >> f, self.C_OBJECT_TABLE
-        for name in self.pyobjrepr.globalobjects:
+        for name in self.pyobjtype.globalobjects:
             if not name.startswith('gfunc_'):
                 print >> f, '\t{&%s, "%s"},' % (name, name)
         print >> f, self.C_TABLE_END
@@ -128,7 +111,7 @@
 
         # frozen init bytecode
         print >> f, self.C_FROZEN_BEGIN
-        bytecode = self.pyobjrepr.getfrozenbytecode()
+        bytecode = self.pyobjtype.getfrozenbytecode(self)
         def char_repr(c):
             if c in '\\"': return '\\' + c
             if ' ' <= c < '\x7F': return c
@@ -144,6 +127,11 @@
         print >> f, self.C_FOOTER % info
 
     def gen_global_declarations(self):
+        # collect more of the latercode between the functions,
+        # and produce the corresponding global declarations
+        for ct in self.translator.concretetypes.values():
+            if hasattr(ct, 'collect_globals'):
+                self.globaldecl += ct.collect_globals(self)
         g = self.globaldecl
         if g:
             f = self.f

Deleted: /pypy/dist/pypy/translator/genc/parametric.py
==============================================================================
--- /pypy/dist/pypy/translator/genc/parametric.py	Fri Apr  8 13:29:42 2005
+++ (empty file)
@@ -1,41 +0,0 @@
-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)

Modified: pypy/dist/pypy/translator/genc/t_func.py
==============================================================================
--- pypy/dist/pypy/translator/genc/t_func.py	(original)
+++ pypy/dist/pypy/translator/genc/t_func.py	Fri Apr  8 13:29:42 2005
@@ -1,19 +1,29 @@
-from pypy.translator.genc.parametric import parametrictype
+from pypy.translator.genc.t_simple import CType
 
 
-class CType_FuncPtr:
-    __metaclass__ = parametrictype
+class CFuncPtrType(CType):
+    error_return = 'NULL'
 
-    def __initsubclass__(cls, key):
-        cls.args_typecls = key[:-1]
-        cls.return_typecls = key[-1]
-        arglist = [tc.ctypetemplate % ('',) for tc in cls.args_typecls]
+    def __init__(self, translator, argtypes, returntype):
+        super(CFuncPtrType, self).__init__(translator)
+        self.argtypes = argtypes
+        self.returntype = returntype
+        # build a type declaration template matching the strange C syntax
+        # for function pointer types:
+        #    <returntype> (*<name_to_insert_here>) (<argument types>)
+        # which becomes funny when <returntype> itself is a complex type;
+        # in that case, the whole rest of the line, i.e. the "(*..)(...)",
+        # is what should be inserted into the returntype's "%s".
+        arglist = [ct.ctypetemplate % ('',) for ct in argtypes]
         argtemplate = ', '.join(arglist or ['void'])
         header = '(*%s)(' + argtemplate + ')'
-        cls.ctypetemplate = cls.return_typecls.ctypetemplate % (header,)
+        self.ctypetemplate = returntype.ctypetemplate % (header,)
 
-    def __init__(self, genc):
-        self.genc = genc
+    def debugname(self):
+        # a nice textual name for debugging...
+        argnames = [ct.debugname() for ct in self.argtypes]
+        returnname = self.returntype.debugname()
+        return 'fn (%s) -> %s' % (', '.join(argnames), returnname)
 
     def nameof(self, func, debug=None):
-        return self.genc.getfuncdef(func).fast_name
+        return self.genc().getfuncdef(func).fast_name

Deleted: /pypy/dist/pypy/translator/genc/t_int.py
==============================================================================
--- /pypy/dist/pypy/translator/genc/t_int.py	Fri Apr  8 13:29:42 2005
+++ (empty file)
@@ -1,27 +0,0 @@
-
-
-class CType_Int:
-    ctypetemplate    = 'int %s'
-    convert_to_obj   = 'int2obj'
-    convert_from_obj = 'obj2int'
-    error_return     = '-1'
-
-    def __init__(self, genc):
-        pass
-
-    def nameof(self, v, debug=None):
-        return '%d' % v
-
-
-class CType_None:
-    ctypetemplate    = 'int %s'
-    convert_to_obj   = 'none2obj'
-    convert_from_obj = 'obj2none'
-    error_return     = '-1'
-
-    def __init__(self, genc):
-        pass
-
-    def nameof(self, v, debug=None):
-        assert v is None
-        return '0'

Modified: pypy/dist/pypy/translator/genc/t_pyobj.py
==============================================================================
--- pypy/dist/pypy/translator/genc/t_pyobj.py	(original)
+++ pypy/dist/pypy/translator/genc/t_pyobj.py	Fri Apr  8 13:29:42 2005
@@ -1,13 +1,14 @@
 from __future__ import generators
 import autopath, os, sys, __builtin__, marshal, zlib
 from pypy.objspace.flow.model import Variable, Constant
-from pypy.translator.gensupp import builtin_base
+from pypy.translator.gensupp import builtin_base, NameManager
+from pypy.translator.genc.t_simple import CType
 from types import FunctionType, CodeType, InstanceType, ClassType
 
 from pypy.objspace.std.restricted_int import r_int, r_uint
 
 
-class CType_PyObject:
+class CPyObjectType(CType):
     """The PyObject* C type.
     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
@@ -16,9 +17,24 @@
     ctypetemplate = 'PyObject *%s'
     cincref       = 'Py_INCREF(%s);'
     cdecref       = 'Py_DECREF(%s);'
+    error_return  = 'NULL'
 
-    def __init__(self, genc):
-        self.genc = genc
+    def __init__(self, translator):
+        self.translator = translator
+        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
+           ''')
         self.cnames = {Constant(None).key:  'Py_None',
                        Constant(False).key: 'Py_False',
                        Constant(True).key:  'Py_True',
@@ -30,6 +46,7 @@
             'Py_True  = True',
             ]
 
+        self.globaldecl = []
         self.latercode = []    # list of generators generating extra lines
                                #   for later in initxxx() -- for recursive
                                #   objects
@@ -66,9 +83,9 @@
             return name
 
     def uniquename(self, basename):
-        name = self.genc.namespace.uniquename(basename)
+        name = self.namespace.uniquename(basename)
         self.globalobjects.append(name)
-        self.genc.globaldecl.append('static PyObject *%s;' % (name,))
+        self.globaldecl.append('static PyObject *%s;' % (name,))
         return name
 
     def initcode_python(self, name, pyexpr):
@@ -136,7 +153,7 @@
     def skipped_function(self, func):
         # debugging only!  Generates a placeholder for missing functions
         # that raises an exception when called.
-        if self.genc.translator.frozen:
+        if self.translator.frozen:
             warning = 'NOT GENERATING'
         else:
             warning = 'skipped'
@@ -152,10 +169,10 @@
 
     def nameof_function(self, func, progress=['-\x08', '\\\x08',
                                               '|\x08', '/\x08']):
-        funcdef = self.genc.getfuncdef(func)
+        funcdef = self.genc().getfuncdef(func)
         if funcdef is None:
             return self.skipped_function(func)
-        if not self.genc.translator.frozen:
+        if not self.translator.frozen:
             p = progress.pop(0)
             sys.stderr.write(p)
             progress.append(p)
@@ -183,7 +200,7 @@
             return name
 
     def should_translate_attr(self, pbc, attr):
-        ann = self.genc.translator.annotator
+        ann = self.translator.annotator
         if ann is None:
             ignore = getattr(pbc.__class__, 'NOT_RPYTHON_ATTRIBUTES', [])
             if attr in ignore:
@@ -288,12 +305,12 @@
                         continue
                     # XXX some __NAMES__ are important... nicer solution sought
                     #raise Exception, "unexpected name %r in class %s"%(key, cls)
-                if isinstance(value, staticmethod) and value.__get__(1) not in self.genc.translator.flowgraphs and self.genc.translator.frozen:
+                if isinstance(value, staticmethod) and value.__get__(1) not in self.translator.flowgraphs and self.translator.frozen:
                     print value
                     continue
                 if isinstance(value, classmethod) and value.__get__(cls).__doc__.lstrip().startswith("NOT_RPYTHON"):
                     continue
-                if isinstance(value, FunctionType) and value not in self.genc.translator.flowgraphs and self.genc.translator.frozen:
+                if isinstance(value, FunctionType) and value not in self.translator.flowgraphs and self.translator.frozen:
                     print value
                     continue
                     
@@ -408,26 +425,29 @@
     def later(self, gen):
         self.latercode.append((gen, self.debugstack))
 
-    def collect_globals(self):
+    def collect_globals(self, genc):
         while self.latercode:
             gen, self.debugstack = self.latercode.pop()
             #self.initcode.extend(gen) -- eats TypeError! bad CPython!
             for line in gen:
                 self.initcode.append(line)
             self.debugstack = ()
-        if self.genc.f2 is not None:
+        if genc.f2 is not None:
             for line in self.initcode:
-                print >> self.genc.f2, line
+                print >> genc.f2, line
             del self.initcode[:]
-
-    def getfrozenbytecode(self):
-        if self.genc.f2 is not None:
-            self.genc.f2.seek(0)
-            self.initcode.insert(0, self.genc.f2.read())
+        result = self.globaldecl
+        self.globaldecl = []
+        return result
+
+    def getfrozenbytecode(self, genc):
+        if genc.f2 is not None:
+            genc.f2.seek(0)
+            self.initcode.insert(0, genc.f2.read())
         self.initcode.append('')
         source = '\n'.join(self.initcode)
         del self.initcode[:]
-        co = compile(source, self.genc.modname, 'exec')
+        co = compile(source, genc.modname, 'exec')
         del source
         small = zlib.compress(marshal.dumps(co))
         source = """if 1:
@@ -435,10 +455,6 @@
             exec marshal.loads(zlib.decompress(%r))""" % small
         # Python 2.2 SyntaxError without newline: Bug #501622
         source += '\n'
-        co = compile(source, self.genc.modname, 'exec')
+        co = compile(source, genc.modname, 'exec')
         del source
         return marshal.dumps(co)
-
-
-def ctypeof(v):
-    return getattr(v, 'type_cls', CType_PyObject)

Copied: pypy/dist/pypy/translator/genc/t_simple.py (from r10428, pypy/dist/pypy/translator/genc/t_int.py)
==============================================================================
--- pypy/dist/pypy/translator/genc/t_int.py	(original)
+++ pypy/dist/pypy/translator/genc/t_simple.py	Fri Apr  8 13:29:42 2005
@@ -1,26 +1,47 @@
+from pypy.annotation.model import SomeInteger, SomePBC
+from pypy.objspace.flow.model import SpaceOperation
+from pypy.interpreter.miscutils import getthreadlocals
 
 
-class CType_Int:
-    ctypetemplate    = 'int %s'
-    convert_to_obj   = 'int2obj'
-    convert_from_obj = 'obj2int'
-    error_return     = '-1'
+class CType(object):
+    cincref = None
+    cdecref = None
 
-    def __init__(self, genc):
-        pass
+    def __init__(self, translator):
+        self.translator = translator
 
-    def nameof(self, v, debug=None):
-        return '%d' % v
+    def convert_to_obj(self, v1, v2):
+        return [SpaceOperation(self.opname_conv_to_obj, [v1], v2)]
+
+    def convert_from_obj(self, v1, v2):
+        return [SpaceOperation(self.opname_conv_from_obj, [v1], v2)]
+
+    def debugname(self):
+        return self.__class__.__name__
+
+    def genc():
+        """A hack to get at the currently running GenC instance."""
+        return getthreadlocals().genc
+    genc = staticmethod(genc)
 
 
-class CType_None:
-    ctypetemplate    = 'int %s'
-    convert_to_obj   = 'none2obj'
-    convert_from_obj = 'obj2none'
-    error_return     = '-1'
+class CIntType(CType):
+    error_return  = '-1'
+    ctypetemplate = 'int %s'
+    s_annotation  = SomeInteger()
+    opname_conv_to_obj   = 'int2obj'
+    opname_conv_from_obj = 'obj2int'
+
+    def nameof(self, v, debug=None):
+        return '%d' % (v,)
+
 
-    def __init__(self, genc):
-        pass
+class CNoneType(CType):
+    error_return  = '-1'
+    ctypetemplate = 'int %s'
+    s_annotation  = SomePBC({None: True})
+    opname_conv_to_obj   = 'none2obj'
+    opname_conv_from_obj = 'obj2none'
 
     def nameof(self, v, debug=None):
         assert v is None

Modified: pypy/dist/pypy/translator/tool/graphpage.py
==============================================================================
--- pypy/dist/pypy/translator/tool/graphpage.py	(original)
+++ pypy/dist/pypy/translator/tool/graphpage.py	Fri Apr  8 13:29:42 2005
@@ -127,9 +127,10 @@
         def visit(node):
             if isinstance(node, Block):
                 for var in node.getvariables():
-                    if hasattr(var, 'type_cls'):
+                    if hasattr(var, 'concretetype'):
+                        typename = var.concretetype.debugname()
                         info = self.links.get(var.name, var.name)
-                        info = '(%s) %s' % (var.type_cls.__name__, info)
+                        info = '(%s) %s' % (typename, info)
                         self.links[var.name] = info
         for graph in graphs:
             traverse(visit, graph)

Modified: pypy/dist/pypy/translator/translator.py
==============================================================================
--- pypy/dist/pypy/translator/translator.py	(original)
+++ pypy/dist/pypy/translator/translator.py	Fri Apr  8 13:29:42 2005
@@ -63,6 +63,7 @@
         self.functions = []   # the keys of self.flowgraphs, in creation order
         self.callgraph = {}   # {opaque_tag: (caller, callee)}
         self.frozen = False   # when frozen, no more flowgraphs can be generated
+        self.concretetypes = {}  # see getconcretetype()
         if self.entrypoint:
             self.getflowgraph()
 
@@ -265,6 +266,17 @@
 ##            # not actually start the analysis of the called function yet.
 ##            return impossiblevalue
 
+    def getconcretetype(self, cls, *args):
+        # 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
+        # the code generators.
+        try:
+            return self.concretetypes[cls, args]
+        except KeyError:
+            result = self.concretetypes[cls, args] = cls(self, *args)
+            return result
+
 
 if __name__ == '__main__':
     from pypy.translator.test import snippet as test

Modified: pypy/dist/pypy/translator/typer.py
==============================================================================
--- pypy/dist/pypy/translator/typer.py	(original)
+++ pypy/dist/pypy/translator/typer.py	Fri Apr  8 13:29:42 2005
@@ -4,91 +4,89 @@
 from pypy.translator.unsimplify import insert_empty_block
 
 
-class TypeMatch:
-    def __init__(self, s_type, type_cls):
-        self.s_type = s_type
-        self.type_cls = type_cls
-
 class TyperError(Exception):
     pass
 
 
 class Specializer:
-    specializationdict = {}
 
-    def __init__(self, annotator):
-        if not self.specializationdict:
-            # setup the class
-            d = self.specializationdict
-            for e in self.specializationtable:
-                opname1    = e[0]
-                opname2    = e[1]
-                spectypes  = e[2:-1]
-                restypecls = e[-1]
-                info = opname2, spectypes, restypecls
-                d.setdefault(opname1, []).append(info)
-                d.setdefault(opname2, []).append(info)
+    def __init__(self, annotator, defaultconcretetype, typematches,
+                 specializationtable):
         self.annotator = annotator
+        self.defaultconcretetype = defaultconcretetype
+        self.typematches = typematches
+        # turn the table into a dict for faster look-ups
+        d = {}
+        for e in specializationtable:
+            opname1    = e[0]
+            opname2    = e[1]
+            spectypes  = e[2:-1]
+            restype    = e[-1]
+            info = opname2, spectypes, restype
+            d.setdefault(opname1, []).append(info)
+            d.setdefault(opname2, []).append(info)
+        self.specializationdict = d
 
     def specialize(self):
         for block in self.annotator.annotated:
             if block.operations != ():
                 self.specialize_block(block)
 
-    def settype(self, a, type_cls):
-        """Set the type_cls of a Variable or Constant."""
-        if hasattr(a, 'type_cls') and a.type_cls != type_cls:
+    def settype(self, a, concretetype):
+        """Set the concretetype of a Variable or Constant."""
+        if hasattr(a, 'concretetype') and a.concretetype != concretetype:
             raise TyperError, "inconsitent type for %r" % (a,)
-        a.type_cls = type_cls
+        a.concretetype = concretetype
 
     def setbesttype(self, a):
-        """Set the best type_cls for a Variable or Constant according to
+        """Set the best concretetype for a Variable or Constant according to
         the annotations."""
         try:
-            return a.type_cls
+            return a.concretetype
         except AttributeError:
-            besttype = self.defaulttypecls
             s_value = self.annotator.binding(a, True)
             if s_value is not None:
-                besttype = self.annotation2typecls(s_value) or besttype
+                besttype = self.annotation2concretetype(s_value)
+            else:
+                besttype = self.defaultconcretetype
             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 annotation2concretetype(self, s_value):
+        for concretetype in self.typematches:
+            if concretetype.s_annotation.contains(s_value):
+                return concretetype
+        return self.defaultconcretetype
 
-    def convertvar(self, v, type_cls):
+    def convertvar(self, v, concretetype):
         """Get the operation(s) needed to convert 'v' to the given type."""
         ops = []
         if isinstance(v, Constant):
             try:
                 # mark the concrete type of the Constant
-                self.settype(v, type_cls)
+                self.settype(v, concretetype)
             except TyperError:
                 v = Constant(v.value)   # need a copy of the Constant
-                self.settype(v, type_cls)
+                self.settype(v, concretetype)
 
-        elif v.type_cls is not type_cls:
+        elif v.concretetype != concretetype:
             # XXX do we need better conversion paths?
 
             # 1) convert to the generic type
-            if v.type_cls is not self.defaulttypecls:
+            if v.concretetype != self.defaultconcretetype:
                 v2 = Variable()
-                v2.type_cls = self.defaulttypecls
-                op = SpaceOperation(v.type_cls.convert_to_obj, [v], v2)
+                v2.concretetype = self.defaultconcretetype
+                newops = list(v.concretetype.convert_to_obj(v, v2))
                 v = v2
-                ops.append(op)
+                ops += newops
 
             # 2) convert back from the generic type
-            if type_cls is not self.defaulttypecls:
+            if concretetype != self.defaultconcretetype:
                 v2 = Variable()
-                v2.type_cls = type_cls
-                op = SpaceOperation(type_cls.convert_from_obj, [v], v2)
+                v2.concretetype = concretetype
+                newops = list(concretetype.convert_from_obj(v, v2))
                 v = v2
-                ops.append(op)
+                ops += newops
 
         return v, ops
 
@@ -98,41 +96,46 @@
             self.setbesttype(a)
 
         # specialize all the operations, as far as possible
-        newops = []
+        self.newops = []
         for op in block.operations:
 
-            indices = range(len(op.args))
             args = list(op.args)
             bindings = [self.annotator.binding(a, True) for a in args]
 
             # replace constant annotations with real Constants
-            for i in indices:
+            for i in range(len(op.args)):
                 if isinstance(args[i], Variable) and bindings[i] is not None:
                     if bindings[i].is_constant():
                         args[i] = Constant(bindings[i].const)
                         op = SpaceOperation(op.opname, args, op.result)
 
-            # 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:
-                args[i], convops = self.convertvar(args[i], argtypes[i])
-                newops += convops
-
-            # store the result variable's type
-            self.settype(op.result, restypecls)
-
-            # store the possibly modified SpaceOperation
-            if opname2 != op.opname or args != op.args:
-                op = SpaceOperation(opname2, args, op.result)
-            newops.append(op)
-
-        block.operations[:] = newops
+            # make a specialized version of the current operation
+            # (which may become several operations)
+            self.make_specialized_op(op, bindings)
 
+        block.operations[:] = self.newops
         self.insert_link_conversions(block)
 
+
+    def make_typed_op(self, op, argtypes, restype, newopname=None):
+        """Make a typed copy of the given SpaceOperation."""
+        args = list(op.args)
+        assert len(argtypes) == len(args)
+
+        # type-convert the input arguments
+        for i in range(len(args)):
+            args[i], convops = self.convertvar(args[i], argtypes[i])
+            self.newops += convops
+
+        # store the result variable's type
+        self.settype(op.result, restype)
+
+        # store the possibly modified SpaceOperation
+        if newopname is not None or args != op.args:
+            op = SpaceOperation(newopname or op.opname, args, op.result)
+        self.newops.append(op)
+
+
     def insert_link_conversions(self, block):
         # insert the needed conversions on the links
         can_insert_here = block.exitswitch is None and len(block.exits) == 1
@@ -154,23 +157,20 @@
                 block.operations += convops
                 link.args[i] = a1
 
-    def getspecializedop(self, op, bindings):
+
+    def make_specialized_op(self, op, bindings):
         specializations = self.specializationdict.get(op.opname, ())
-        for opname2, spectypes, restypecls in specializations:
+        for opname2, spectypes, restype in specializations:
             assert len(spectypes) == len(op.args) == len(bindings)
             for i in range(len(spectypes)):
                 if bindings[i] is None:
                     break
-                if not spectypes[i].s_type.contains(bindings[i]):
+                if not spectypes[i].s_annotation.contains(bindings[i]):
                     break
             else:
                 # specialization found
-                # opname2 and restypecls are set above by the for loop
-                argtypes = [tmatch.type_cls for tmatch in spectypes]
-                break
-        else:
-            # specialization not found
-            opname2 = op.opname
-            argtypes = [self.defaulttypecls] * len(op.args)
-            restypecls = self.defaulttypecls
-        return opname2, argtypes, restypecls
+                self.make_typed_op(op, spectypes, restype, newopname=opname2)
+                return
+        # specialization not found
+        argtypes = [self.defaultconcretetype] * len(op.args)
+        self.make_typed_op(op, argtypes, self.defaultconcretetype)

Modified: pypy/dist/pypy/translator/unsimplify.py
==============================================================================
--- pypy/dist/pypy/translator/unsimplify.py	(original)
+++ pypy/dist/pypy/translator/unsimplify.py	Fri Apr  8 13:29:42 2005
@@ -1,14 +1,14 @@
 from pypy.objspace.flow.model import *
 
 def copyvar(translator, v):
-    """Make a copy of the Variable v, preserving annotations and type_cls."""
+    """Make a copy of the Variable v, preserving annotations and concretetype."""
     assert isinstance(v, Variable)
     newvar = Variable(v)
     annotator = translator.annotator
     if annotator is not None and v in annotator.bindings:
         annotator.bindings[newvar] = annotator.bindings[v]
-    if hasattr(v, 'type_cls'):
-        newvar.type_cls = v.type_cls
+    if hasattr(v, 'concretetype'):
+        newvar.concretetype = v.concretetype
     return newvar
 
 def insert_empty_block(translator, link):



More information about the Pypy-commit mailing list