[pypy-svn] r26553 - in pypy/branch/picklesupport: doc/discussion interpreter interpreter/test module/__builtin__ module/_pickle_support objspace/flow rpython rpython/lltypesystem rpython/ootypesystem rpython/rctypes rpython/rctypes/test rpython/rctypes/tool rpython/test

ericvrp at codespeak.net ericvrp at codespeak.net
Sat Apr 29 06:22:09 CEST 2006


Author: ericvrp
Date: Sat Apr 29 06:21:31 2006
New Revision: 26553

Added:
   pypy/branch/picklesupport/doc/discussion/cli-optimizations.txt
      - copied unchanged from r26551, pypy/dist/pypy/doc/discussion/cli-optimizations.txt
Modified:
   pypy/branch/picklesupport/interpreter/test/test_pickle.py
   pypy/branch/picklesupport/interpreter/typedef.py
   pypy/branch/picklesupport/module/__builtin__/__init__.py
   pypy/branch/picklesupport/module/__builtin__/app_functional.py
   pypy/branch/picklesupport/module/_pickle_support/maker.py
   pypy/branch/picklesupport/objspace/flow/model.py
   pypy/branch/picklesupport/rpython/llinterp.py
   pypy/branch/picklesupport/rpython/lltypesystem/lloperation.py
   pypy/branch/picklesupport/rpython/lltypesystem/rstr.py
   pypy/branch/picklesupport/rpython/ootypesystem/ootype.py
   pypy/branch/picklesupport/rpython/ootypesystem/rstr.py
   pypy/branch/picklesupport/rpython/rctypes/rpointer.py
   pypy/branch/picklesupport/rpython/rctypes/rstringbuf.py
   pypy/branch/picklesupport/rpython/rctypes/rvoid_p.py
   pypy/branch/picklesupport/rpython/rctypes/test/test_rfunc.py
   pypy/branch/picklesupport/rpython/rctypes/test/test_rstruct.py
   pypy/branch/picklesupport/rpython/rctypes/tool/ctypes_platform.py
   pypy/branch/picklesupport/rpython/robject.py
   pypy/branch/picklesupport/rpython/rstr.py
   pypy/branch/picklesupport/rpython/test/test_rstr.py
Log:
get changes from the trunk


Modified: pypy/branch/picklesupport/interpreter/test/test_pickle.py
==============================================================================
--- pypy/branch/picklesupport/interpreter/test/test_pickle.py	(original)
+++ pypy/branch/picklesupport/interpreter/test/test_pickle.py	Sat Apr 29 06:21:31 2006
@@ -128,15 +128,39 @@
 
     def test_pickle_method(self):
         skip("work in progress")
-        class C(object):
+        class myclass(object):
             def f(self):
                 pass
         import pickle
-        method   = C.f
+        method   = myclass.f
         pckl     = pickle.dumps(method)
         result   = pickle.loads(pckl)
         assert method == result
         
+    def test_pickle_staticmethod(self):
+        skip("work in progress")
+        class myclass(object):
+            def f(self):
+                pass
+            f = staticmethod(f)
+        import pickle
+        method   = myclass.f
+        pckl     = pickle.dumps(method)
+        result   = pickle.loads(pckl)
+        assert method == result
+
+    def test_pickle_classmethod(self):
+        skip("work in progress")
+        class myclass(object):
+            def f(self):
+                pass
+            f = classmethod(f)
+        import pickle
+        method   = myclass.f
+        pckl     = pickle.dumps(method)
+        result   = pickle.loads(pckl)
+        assert method == result
+
     def test_pickle_dictiter(self):
         skip("work in progress")
         import pickle
@@ -146,7 +170,7 @@
         assert diter == result
 
     def test_pickle_enum(self):
-        skip("work in progress")
+        #skip("work in progress")
         import pickle
         e      = enumerate([])
         pckl   = pickle.dumps(e)
@@ -170,12 +194,14 @@
         assert liter == result
 
     def test_pickle_xrangeiter(self):
-        skip("work in progress")
         import pickle
         riter  = iter(xrange(5))
+        riter.next()
+        riter.next()
         pckl   = pickle.dumps(riter)
         result = pickle.loads(pckl)
-        assert riter == result
+        assert type(riter) is type(result)
+        assert list(result) == [2,3,4]
 
     def test_pickle_generator(self):
         skip("work in progress")

Modified: pypy/branch/picklesupport/interpreter/typedef.py
==============================================================================
--- pypy/branch/picklesupport/interpreter/typedef.py	(original)
+++ pypy/branch/picklesupport/interpreter/typedef.py	Sat Apr 29 06:21:31 2006
@@ -23,20 +23,20 @@
         # xxx used by faking
         self.fakedcpytype = None
         self.add_entries(**rawdict)
-
+    
     def add_entries(self, **rawdict):
         # xxx fix the names of the methods to match what app-level expects
         for key, value in rawdict.items():
             if isinstance(value, (interp2app, GetSetProperty)):
                 value.name = key
         self.rawdict.update(rawdict)
-
+    
     def _freeze_(self):
         # hint for the annotator: track individual constant instances of TypeDef
         return True
 
 
-def get_unique_interplevel_subclass(cls, hasdict, wants_slots, needsdel=False): 
+def get_unique_interplevel_subclass(cls, hasdict, wants_slots, needsdel=False):
     key = cls, hasdict, wants_slots, needsdel
     try:
         return _subclass_cache[key]
@@ -53,10 +53,10 @@
 def _buildusercls(cls, hasdict, wants_slots, wants_del):
     "NOT_RPYTHON: initialization-time only"
     typedef = cls.typedef
-
+    
     if hasdict and typedef.hasdict:
         return get_unique_interplevel_subclass(cls, False, wants_slots, wants_del)
-
+    
     name = ['User']
     if not hasdict:
         name.append('NoDict')
@@ -65,9 +65,9 @@
     if wants_del:
         name.append('WithDel')
     name.append(cls.__name__)
-
+    
     name = ''.join(name)
-
+    
     if wants_del:
         supercls = get_unique_interplevel_subclass(cls, hasdict, wants_slots, False)
         class Proto(object):
@@ -79,29 +79,29 @@
                     e.clear(self.space)   # break up reference cycles
     elif wants_slots:
         supercls = get_unique_interplevel_subclass(cls, hasdict, False, False)
-
+        
         class Proto(object):
             def user_setup_slots(self, nslots):
-                self.slots_w = [None] * nslots 
-
+                self.slots_w = [None] * nslots
+            
             def setslotvalue(self, index, w_value):
                 self.slots_w[index] = w_value
-
+            
             def getslotvalue(self, index):
                 return self.slots_w[index]
     elif hasdict:
         supercls = get_unique_interplevel_subclass(cls, False, False, False)
-
+        
         class Proto(object):
             def getdict(self):
                 return self.w__dict__
-
+            
             def setdict(self, space, w_dict):
                 if not space.is_true(space.isinstance(w_dict, space.w_dict)):
                     raise OperationError(space.w_TypeError,
                             space.wrap("setting dictionary to a non-dict"))
                 self.w__dict__ = w_dict
-
+            
             def user_setup(self, space, w_subtype, nslots):
                 self.space = space
                 self.w__class__ = w_subtype
@@ -111,29 +111,29 @@
         supercls = cls
         
         class Proto(object):
-
+            
             def getclass(self, space):
                 return self.w__class__
-        
+            
             def setclass(self, space, w_subtype):
                 # only used by descr_set___class__
                 self.w__class__ = w_subtype
-
-
+            
+            
             def user_setup(self, space, w_subtype, nslots):
                 self.space = space
                 self.w__class__ = w_subtype
                 self.user_setup_slots(nslots)
-
+            
             def user_setup_slots(self, nslots):
                 assert nslots == 0
-
+    
     body = dict([(key, value)
                  for key, value in Proto.__dict__.items()
                  if not key.startswith('_') or key == '__del__'])
     
     subcls = type(name, (supercls,), body)
-
+    
     return subcls
 
 def make_descr_typecheck_wrapper(func, extraargs=(), cls=None):
@@ -144,7 +144,7 @@
     if hasattr(func, 'im_func'):
         assert func.im_class is cls
         func = func.im_func
-
+    
     miniglobals = {
          func.__name__: func,
         'OperationError': OperationError
@@ -171,12 +171,12 @@
             return %(name)s(space, obj, %(extra)s)
         """
         miniglobals[cls_name] = cls
-
+    
     name = func.__name__
     extra = ', '.join(extraargs)
     source = py.code.Source(source % locals())
     exec source.compile() in miniglobals
-    return miniglobals['descr_typecheck_%s' % func.__name__]    
+    return miniglobals['descr_typecheck_%s' % func.__name__]
 
 def unknown_objclass_getter(space):
     raise OperationError(space.w_TypeError,
@@ -213,16 +213,16 @@
     def __init__(self, fget, fset=None, fdel=None, doc=None, cls=None):
         "NOT_RPYTHON: initialization-time only"
         objclass_getter, cls = make_objclass_getter(fget, cls)
-        fget = make_descr_typecheck_wrapper(fget, cls=cls) 
+        fget = make_descr_typecheck_wrapper(fget, cls=cls)
         fset = make_descr_typecheck_wrapper(fset, ('w_value',), cls=cls)
-        fdel = make_descr_typecheck_wrapper(fdel, cls=cls) 
+        fdel = make_descr_typecheck_wrapper(fdel, cls=cls)
         self.fget = fget
         self.fset = fset
         self.fdel = fdel
         self.doc = doc
         self.name = '<generic property>'
         self.objclass_getter = objclass_getter
-
+    
     def descr_property_get(space, property, w_obj, w_cls=None):
         """property.__get__(obj[, type]) -> value
         Read the value of the property of the given obj."""
@@ -233,7 +233,7 @@
             return space.wrap(property)
         else:
             return property.fget(space, w_obj)
-
+    
     def descr_property_set(space, property, w_obj, w_value):
         """property.__set__(obj, value)
         Change the value of the property of the given obj."""
@@ -242,7 +242,7 @@
             raise OperationError(space.w_TypeError,
                                  space.wrap("readonly attribute"))
         fset(space, w_obj, w_value)
-
+    
     def descr_property_del(space, property, w_obj):
         """property.__delete__(obj)
         Delete the value of the property from the given obj."""
@@ -251,7 +251,7 @@
             raise OperationError(space.w_AttributeError,
                                  space.wrap("cannot delete attribute"))
         fdel(space, w_obj)
-
+    
     def descr_get_objclass(space, property):
         return property.objclass_getter(space)
 
@@ -268,8 +268,8 @@
         if w_value is None:
             return space.w_None
         else:
-            return w_value 
-
+            return w_value
+    
     return GetSetProperty(fget, cls=cls)
 
 GetSetProperty.typedef = TypeDef(
@@ -294,13 +294,13 @@
         self.index = index
         self.name = name
         self.w_cls = w_cls
-
+    
     def typecheck(self, space, w_obj):
         if not space.is_true(space.isinstance(w_obj, self.w_cls)):
             raise OperationError(space.w_TypeError,
                                  space.wrap("descriptor '%s' for '%s' objects doesn't apply to '%s' object" %
                                             (self.name, self.w_cls.name, space.type(w_obj).name)))
-
+    
     def descr_member_get(space, member, w_obj, w_w_cls=None):
         """member.__get__(obj[, type]) -> value
         Read the slot 'member' of the given 'obj'."""
@@ -314,14 +314,14 @@
                 raise OperationError(space.w_AttributeError,
                                      space.wrap(self.name)) # XXX better message
             return w_result
-
+    
     def descr_member_set(space, member, w_obj, w_value):
         """member.__set__(obj, value)
         Write into the slot 'member' of the given 'obj'."""
         self = member
         self.typecheck(space, w_obj)
         w_obj.setslotvalue(self.index, w_value)
-
+    
     def descr_member_del(space, member, w_obj):
         """member.__delete__(obj)
         Delete the value of the slot 'member' from the given 'obj'."""
@@ -355,7 +355,7 @@
 from pypy.interpreter.function import Function, Method, StaticMethod
 from pypy.interpreter.function import BuiltinFunction, descr_function_get
 from pypy.interpreter.pytraceback import PyTraceback
-from pypy.interpreter.generator import GeneratorIterator 
+from pypy.interpreter.generator import GeneratorIterator
 from pypy.interpreter.nestedscope import Cell
 from pypy.interpreter.special import NotImplemented, Ellipsis
 
@@ -415,7 +415,7 @@
     __new__ = interp2app(PyCode.descr_code__new__.im_func),
     __eq__ = interp2app(PyCode.descr_code__eq__),
     __ne__ = descr_generic_ne,
-    __reduce__   = interp2app(PyCode.descr__reduce__, 
+    __reduce__   = interp2app(PyCode.descr__reduce__,
                               unwrap_spec=['self', ObjSpace]),
     co_argcount = interp_attrproperty('co_argcount', cls=PyCode),
     co_nlocals = interp_attrproperty('co_nlocals', cls=PyCode),
@@ -438,7 +438,7 @@
     f_lineno = GetSetProperty(PyFrame.fget_f_lineno, PyFrame.fset_f_lineno),
     f_back = GetSetProperty(PyFrame.fget_f_back),
     f_lasti = GetSetProperty(PyFrame.fget_f_lasti),
-    f_trace = GetSetProperty(PyFrame.fget_f_trace, PyFrame.fset_f_trace, 
+    f_trace = GetSetProperty(PyFrame.fget_f_trace, PyFrame.fset_f_trace,
                              PyFrame.fdel_f_trace),
     f_exc_type = GetSetProperty(PyFrame.fget_f_exc_type),
     f_exc_value = GetSetProperty(PyFrame.fget_f_exc_value),
@@ -450,7 +450,7 @@
     __new__ = interp2app(Module.descr_module__new__.im_func,
                          unwrap_spec=[ObjSpace, W_Root, Arguments]),
     __init__ = interp2app(Module.descr_module__init__),
-    __reduce__ = interp2app(Module.descr__reduce__, 
+    __reduce__ = interp2app(Module.descr__reduce__,
                             unwrap_spec=['self', ObjSpace]),
     __dict__ = GetSetProperty(descr_get_dict, cls=Module), # module dictionaries are readonly attributes
     __doc__ = 'module(name[, doc])\n\nCreate a module object.\nThe name must be a string; the optional doc argument can have any type.'
@@ -480,14 +480,14 @@
 getset_func_dict = GetSetProperty(descr_get_dict, descr_set_dict, cls=Function)
 
 Function.typedef = TypeDef("function",
-    __new__ = interp2app(Function.descr_method__new__.im_func),                           
+    __new__ = interp2app(Function.descr_method__new__.im_func),
     __call__ = interp2app(Function.descr_function_call,
                           unwrap_spec=['self', Arguments]),
     __get__ = interp2app(descr_function_get),
     __repr__ = interp2app(Function.descr_function_repr),
-    __reduce__ = interp2app(Function.descr_function__reduce__, 
+    __reduce__ = interp2app(Function.descr_function__reduce__,
                             unwrap_spec=['self', ObjSpace]),
-    func_code = getset_func_code, 
+    func_code = getset_func_code,
     func_doc = getset_func_doc,
     func_name = getset_func_name,
     func_dict = getset_func_dict,
@@ -506,16 +506,16 @@
     __call__ = interp2app(Method.descr_method_call,
                           unwrap_spec=['self', Arguments]),
     __get__ = interp2app(Method.descr_method_get),
-    im_func  = interp_attrproperty_w('w_function', cls=Method), 
-    im_self  = interp_attrproperty_w('w_instance', cls=Method), 
+    im_func  = interp_attrproperty_w('w_function', cls=Method),
+    im_self  = interp_attrproperty_w('w_instance', cls=Method),
     im_class = interp_attrproperty_w('w_class', cls=Method),
     __getattribute__ = interp2app(Method.descr_method_getattribute),
     __eq__ = interp2app(Method.descr_method_eq),
     __ne__ = descr_generic_ne,
-    __repr__ = interp2app(Method.descr_method_repr), 
-    __reduce__ = interp2app(Method.descr_method__reduce__, 
-                            unwrap_spec=['self', ObjSpace]), 
-    # XXX getattribute/setattribute etc.pp 
+    __repr__ = interp2app(Method.descr_method_repr),
+    __reduce__ = interp2app(Method.descr_method__reduce__,
+                            unwrap_spec=['self', ObjSpace]),
+    # XXX getattribute/setattribute etc.pp
     )
 
 StaticMethod.typedef = TypeDef("staticmethod",
@@ -543,31 +543,29 @@
 GeneratorIterator.typedef = TypeDef("generator",
     next       = interp2app(GeneratorIterator.descr_next),
     __iter__   = interp2app(GeneratorIterator.descr__iter__),
-    gi_running = interp_attrproperty('running', cls=GeneratorIterator), 
-    gi_frame   = interp_attrproperty('frame', cls=GeneratorIterator), 
+    gi_running = interp_attrproperty('running', cls=GeneratorIterator),
+    gi_frame   = interp_attrproperty('frame', cls=GeneratorIterator),
 )
 
 Cell.typedef = TypeDef("cell",
     __eq__       = interp2app(Cell.descr__eq__,
                               unwrap_spec=['self', ObjSpace, W_Root]),
     __ne__       = descr_generic_ne,
-    __reduce__   = interp2app(Cell.descr__reduce__, 
+    __reduce__   = interp2app(Cell.descr__reduce__,
                               unwrap_spec=['self', ObjSpace]),
     __setstate__ = interp2app(Cell.descr__setstate__,
-                              unwrap_spec=['self', ObjSpace, W_Root]), 
+                              unwrap_spec=['self', ObjSpace, W_Root]),
 )
 
-Ellipsis.typedef = TypeDef("Ellipsis", 
+Ellipsis.typedef = TypeDef("Ellipsis",
     __repr__   = interp2app(Ellipsis.descr__repr__),
 )
 
-NotImplemented.typedef = TypeDef("NotImplemented", 
-    __repr__   = interp2app(NotImplemented.descr__repr__), 
+NotImplemented.typedef = TypeDef("NotImplemented",
+    __repr__   = interp2app(NotImplemented.descr__repr__),
 )
 
 ControlFlowException.typedef = TypeDef("ControlFlowException")
 
 
 interptypes = [ val.typedef for name,val in globals().items() if hasattr(val,'__bases__') and hasattr(val,'typedef')  ]
-
-    

Modified: pypy/branch/picklesupport/module/__builtin__/__init__.py
==============================================================================
--- pypy/branch/picklesupport/module/__builtin__/__init__.py	(original)
+++ pypy/branch/picklesupport/module/__builtin__/__init__.py	Sat Apr 29 06:21:31 2006
@@ -31,6 +31,8 @@
         'any'           : 'app_functional.any',
         'enumerate'     : 'app_functional.enumerate',
         'xrange'        : 'app_functional.xrange',
+        '_install_pickle_support_for_xrange_iterator':
+        'app_functional._install_pickle_support_for_xrange_iterator',
         'sorted'        : 'app_functional.sorted',
         'reversed'      : 'app_functional.reversed',
 
@@ -137,3 +139,15 @@
        builtin = module.Module(space, None)
        space.setitem(builtin.w_dict, space.wrap('None'), space.w_None)
        return builtin
+
+    def setup_after_space_initialization(self):
+        """NOT_RPYTHON"""
+        space = self.space
+        # call installations for pickle support
+        for name in self.loaders.keys():
+            if name.startswith('_install_pickle_support_for_'):
+                w_install = self.get(name)
+                space.call_function(w_install)
+                # xxx hide the installer
+                space.delitem(self.w_dict, space.wrap(name))
+                del self.loaders[name]
\ No newline at end of file

Modified: pypy/branch/picklesupport/module/__builtin__/app_functional.py
==============================================================================
--- pypy/branch/picklesupport/module/__builtin__/app_functional.py	(original)
+++ pypy/branch/picklesupport/module/__builtin__/app_functional.py	Sat Apr 29 06:21:31 2006
@@ -362,6 +362,18 @@
     def __len__(self):
         return self._remaining
 
+    def __reduce__(self):
+        tup = (self._current, self._remaining, self._step)
+        return (make_xrange_iterator, tup)
+
+def make_xrange_iterator(*args):
+    return xrange_iterator(*args)
+    
+def _install_pickle_support_for_xrange_iterator():
+    import _pickle_support
+    make_xrange_iterator.__module__ = '_pickle_support'
+    _pickle_support.make_xrange_iterator = make_xrange_iterator
+ 
 # ____________________________________________________________
 
 def sorted(lst, cmp=None, key=None, reverse=None):

Modified: pypy/branch/picklesupport/module/_pickle_support/maker.py
==============================================================================
--- pypy/branch/picklesupport/module/_pickle_support/maker.py	(original)
+++ pypy/branch/picklesupport/module/_pickle_support/maker.py	Sat Apr 29 06:21:31 2006
@@ -24,11 +24,11 @@
     return space.call_args(w_type, __args__)
 func_new.unwrap_spec = [ObjSpace, Arguments]
 
-def module_new(space, w_name, w_dict): #XXX untested
+def module_new(space, w_name, w_dict):
     new_mod = Module(space, w_name, w_dict)
     return space.wrap(new_mod)
 
-def method_new(space, __args__): #XXX untested
+def method_new(space, __args__):
     w_type = space.gettypeobject(Method.typedef)
     return space.call_args(w_type, __args__)
 method_new.unwrap_spec = [ObjSpace, Arguments]

Modified: pypy/branch/picklesupport/objspace/flow/model.py
==============================================================================
--- pypy/branch/picklesupport/objspace/flow/model.py	(original)
+++ pypy/branch/picklesupport/objspace/flow/model.py	Sat Apr 29 06:21:31 2006
@@ -67,12 +67,14 @@
         return getsource(self.func)
     source = roproperty(getsource)
 
-    def __repr__(self):
+    def __str__(self):
         if hasattr(self, 'func'):
-            fnrepr = nice_repr_for_func(self.func, self.name)
+            return nice_repr_for_func(self.func, self.name)
         else:
-            fnrepr = self.name
-        return '<FunctionGraph of %s at 0x%x>' % (fnrepr, uid(self))
+            return self.name
+
+    def __repr__(self):
+        return '<FunctionGraph of %s at 0x%x>' % (self, uid(self))
 
     def iterblocks(self):
         block = self.startblock

Modified: pypy/branch/picklesupport/rpython/llinterp.py
==============================================================================
--- pypy/branch/picklesupport/rpython/llinterp.py	(original)
+++ pypy/branch/picklesupport/rpython/llinterp.py	Sat Apr 29 06:21:31 2006
@@ -36,6 +36,8 @@
 class LLInterpreter(object):
     """ low level interpreter working with concrete values. """
 
+    TRACING = True
+
     def __init__(self, typer, heap=lltype):
         self.bindings = {}
         self.typer = typer
@@ -47,19 +49,41 @@
         if hasattr(heap, "prepare_graphs_and_create_gc"):
             flowgraphs = typer.annotator.translator.graphs
             self.gc = heap.prepare_graphs_and_create_gc(self, flowgraphs)
+        if self.TRACING:
+            self.tracer = Tracer()
+        else:
+            self.tracer = None
 
     def eval_graph(self, graph, args=()):
         llframe = LLFrame(graph, args, self)
+        if self.tracer:
+            self.tracer.start()
+        retval = None
         try:
-            return llframe.eval()
-        except LLException, e:
-            log.error("LLEXCEPTION: %s" % (e, ))
-            self.print_traceback()
-            raise
-        except Exception, e:
-            log.error("AN ERROR OCCURED: %s" % (e, ))
-            self.print_traceback()
-            raise
+            try:
+                retval = llframe.eval()
+            except LLException, e:
+                log.error("LLEXCEPTION: %s" % (e, ))
+                self.print_traceback()
+                if self.tracer:
+                    self.tracer.dump('LLException: %s\n' % (e,))
+                raise
+            except Exception, e:
+                log.error("AN ERROR OCCURED: %s" % (e, ))
+                self.print_traceback()
+                if self.tracer:
+                    line = str(e)
+                    if line:
+                        line = ': ' + line
+                    line = '* %s' % (e.__class__.__name__,) + line
+                    self.tracer.dump(line + '\n')
+                raise
+        finally:
+            if self.tracer:
+                if retval is not None:
+                    self.tracer.dump('   ---> %r\n' % (retval,))
+                self.tracer.stop()
+        return retval
 
     def print_traceback(self):
         frame = self.active_frame
@@ -68,11 +92,12 @@
             frames.append(frame)
             frame = frame.f_back
         frames.reverse()
+        lines = []
         for frame in frames:
             logline = frame.graph.name
             if frame.curr_block is None:
                 logline += " <not running yet>"
-                log.traceback(logline)
+                lines.append(logline)
                 continue
             try:
                 logline += " " + self.typer.annotator.annotated[frame.curr_block].__module__
@@ -80,13 +105,19 @@
                 # if the graph is from the GC it was not produced by the same
                 # translator :-(
                 logline += " <unknown module>"
-            log.traceback(logline)
+            lines.append(logline)
             for i, operation in enumerate(frame.curr_block.operations):
                 if i == frame.curr_operation_index:
                     logline = "E  %s"
                 else:
                     logline = "   %s"
-                log.traceback(logline % (operation, ))
+                lines.append(logline % (operation, ))
+        if self.tracer:
+            self.tracer.dump('Traceback\n', bold=True)
+            for line in lines:
+                self.tracer.dump(line + '\n')
+        for line in lines:
+            log.traceback(line)
 
     def find_roots(self):
         #log.findroots("starting")
@@ -204,19 +235,25 @@
     def eval(self):
         self.llinterpreter.active_frame = self
         graph = self.graph
-        #log.frame("evaluating", graph.name)
-        nextblock = graph.startblock
-        args = self.args
-        while 1:
-            self.clear()
-            self.fillvars(nextblock, args)
-            nextblock, args = self.eval_block(nextblock)
-            if nextblock is None:
-                self.llinterpreter.active_frame = self.f_back
-                for obj in self.alloca_objects:
-                    #XXX slighly unclean
-                    obj._setobj(None)
-                return args
+        tracer = self.llinterpreter.tracer
+        if tracer:
+            tracer.enter(graph)
+        try:
+            nextblock = graph.startblock
+            args = self.args
+            while 1:
+                self.clear()
+                self.fillvars(nextblock, args)
+                nextblock, args = self.eval_block(nextblock)
+                if nextblock is None:
+                    self.llinterpreter.active_frame = self.f_back
+                    for obj in self.alloca_objects:
+                        #XXX slighly unclean
+                        obj._setobj(None)
+                    return args
+        finally:
+            if tracer:
+                tracer.leave()
 
     def eval_block(self, block):
         """ return (nextblock, values) tuple. If nextblock
@@ -237,16 +274,20 @@
         # determine nextblock and/or return value
         if len(block.exits) == 0:
             # return block
+            tracer = self.llinterpreter.tracer
             if len(block.inputargs) == 2:
                 # exception
+                if tracer:
+                    tracer.dump('raise')
                 etypevar, evaluevar = block.getvariables()
                 etype = self.getval(etypevar)
                 evalue = self.getval(evaluevar)
                 # watch out, these are _ptr's
                 raise LLException(etype, evalue)
+            if tracer:
+                tracer.dump('return')
             resultvar, = block.getvariables()
             result = self.getval(resultvar)
-            #log.operation("returning", repr(result))
             return None, result
         elif block.exitswitch is None:
             # single-exit block
@@ -283,7 +324,9 @@
         return link.target, [self.getval(x) for x in link.args]
 
     def eval_operation(self, operation):
-        #log.operation("considering", operation)
+        tracer = self.llinterpreter.tracer
+        if tracer:
+            tracer.dump(str(operation))
         ophandler = self.getoperationhandler(operation.opname)
         # XXX slighly unnice but an important safety check
         if operation.opname == 'direct_call':
@@ -313,6 +356,11 @@
         else:
             self.handle_cleanup(operation)
         self.setvar(operation.result, retval)
+        if tracer:
+            if retval is None:
+                tracer.dump('\n')
+            else:
+                tracer.dump('   ---> %r\n' % (retval,))
 
     def handle_cleanup(self, operation, exception=False):
         cleanup = getattr(operation, 'cleanup', None)
@@ -953,6 +1001,86 @@
     def op_ooidentityhash(self, inst):
         return ootype.ooidentityhash(inst)
 
+
+class Tracer(object):
+    Counter = 0
+    file = None
+
+    HEADER = """<html><head>
+        <script language=javascript type='text/javascript'>
+        function togglestate(name) {
+          item = document.getElementById(name)
+          if (item.style.display == 'none')
+            item.style.display = 'block';
+          else
+            item.style.display = 'none';
+        }
+        </script>
+        </head>
+
+        <body><pre>
+    """
+
+    FOOTER = """</pre></body></html>"""
+
+    ENTER = ('''\n\t<a href="javascript:togglestate('div%d')">%s</a>'''
+             '''\n<div id="div%d" style="display: %s">\t''')
+    LEAVE = '''\n</div>\t'''
+
+    def htmlquote(self, s, text_to_html={}):
+        # HTML quoting, lazily initialized
+        if not text_to_html:
+            import htmlentitydefs
+            for key, value in htmlentitydefs.entitydefs.items():
+                text_to_html[value] = '&' + key + ';'
+        return ''.join([text_to_html.get(c, c) for c in s])
+
+    def start(self):
+        # start of a dump file
+        from pypy.tool.udir import udir
+        n = Tracer.Counter
+        Tracer.Counter += 1
+        self.file = udir.join('llinterp_trace_%d.html' % n).open('w')
+        print >> self.file, self.HEADER
+        self.count = 0
+        self.indentation = ''
+
+    def stop(self):
+        # end of a dump file
+        if self.file:
+            print >> self.file, self.FOOTER
+            self.file.close()
+            self.file = None
+
+    def enter(self, graph):
+        # enter evaluation of a graph
+        if self.file:
+            s = self.htmlquote(str(graph))
+            i = s.rfind(')')
+            s = s[:i+1] + '<b>' + s[i+1:] + '</b>'
+            if self.count == 0:
+                display = 'block'
+            else:
+                display = 'none'
+            text = self.ENTER % (self.count, s, self.count, display)
+            self.indentation += '    '
+            self.file.write(text.replace('\t', self.indentation))
+            self.count += 1
+
+    def leave(self):
+        # leave evaluation of a graph
+        if self.file:
+            self.indentation = self.indentation[:-4]
+            self.file.write(self.LEAVE.replace('\t', self.indentation))
+
+    def dump(self, text, bold=False):
+        if self.file:
+            text = self.htmlquote(text)
+            if bold:
+                text = '<b>%s</b>' % (text,)
+            self.file.write(text.replace('\n', '\n'+self.indentation))
+
+
 # by default we route all logging messages to nothingness
 # e.g. tests can then switch on logging to get more help
 # for failing tests

Modified: pypy/branch/picklesupport/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/branch/picklesupport/rpython/lltypesystem/lloperation.py	(original)
+++ pypy/branch/picklesupport/rpython/lltypesystem/lloperation.py	Sat Apr 29 06:21:31 2006
@@ -317,6 +317,7 @@
     'same_as':              LLOp(canfold=True),
     'hint':                 LLOp(),
     'check_no_more_arg':    LLOp(canraise=(Exception,)),
+    'check_self_nonzero':   LLOp(canraise=(Exception,)),
     'decode_arg':           LLOp(canraise=(Exception,)),
     'decode_arg_def':       LLOp(canraise=(Exception,)),
     'getslice':             LLOp(canraise=(Exception,)),

Modified: pypy/branch/picklesupport/rpython/lltypesystem/rstr.py
==============================================================================
--- pypy/branch/picklesupport/rpython/lltypesystem/rstr.py	(original)
+++ pypy/branch/picklesupport/rpython/lltypesystem/rstr.py	Sat Apr 29 06:21:31 2006
@@ -1,6 +1,9 @@
-from pypy.rpython.rstr import AbstractStringRepr, STR, AbstractStringIteratorRepr, \
-        ll_strconcat
-from pypy.rpython.lltypesystem.lltype import malloc, GcStruct, Ptr, Signed
+from weakref import WeakValueDictionary
+from pypy.rpython.rstr import AbstractStringRepr, char_repr, STR, AbstractStringIteratorRepr, \
+        ll_strconcat, do_stringformat, ll_strhash
+from pypy.rpython.lltypesystem.lltype import malloc, GcStruct, Ptr, nullptr, Signed
+
+CONST_STR_CACHE = WeakValueDictionary()
 
 class StringRepr(AbstractStringRepr):
 
@@ -13,6 +16,22 @@
         self.ll_lower = ll_lower
         self.ll_join = ll_join
 
+    def convert_const(self, value):
+        if value is None:
+            return nullptr(STR)
+        #value = getattr(value, '__self__', value)  # for bound string methods
+        if not isinstance(value, str):
+            raise TyperError("not a str: %r" % (value,))
+        try:
+            return CONST_STR_CACHE[value]
+        except KeyError:
+            p = malloc(STR, len(value))
+            for i in range(len(value)):
+                p.chars[i] = value[i]
+            ll_strhash(p)   # precompute the hash
+            CONST_STR_CACHE[value] = p
+            return p
+
     def make_iterator_repr(self):
         return string_iterator_repr
 
@@ -115,6 +134,11 @@
         i += 1
     return result
 
+char_repr.ll_strip = ll_strip
+char_repr.ll_upper = ll_upper
+char_repr.ll_lower = ll_lower
+char_repr.ll_join = ll_join
+
 string_repr = StringRepr()
 
 emptystr = string_repr.convert_const("")

Modified: pypy/branch/picklesupport/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/branch/picklesupport/rpython/ootypesystem/ootype.py	(original)
+++ pypy/branch/picklesupport/rpython/ootypesystem/ootype.py	Sat Apr 29 06:21:31 2006
@@ -181,6 +181,13 @@
         StaticMethod.__init__(self, args, result)
 
 
+class String(OOType):
+
+    def _defl(self):
+        return ""
+
+String = String()
+
 class BuiltinType(OOType):
 
     def _example(self):
@@ -642,6 +649,10 @@
 else:
     instance_impl = _instance
 
+def make_string(value):
+    assert isinstance(value, str)
+    return _string(value)
+
 def make_instance(INSTANCE):
     inst = _instance(INSTANCE)
     if STATICNESS:
@@ -724,6 +735,9 @@
        callb, checked_args = self.meth._checkargs(args)
        return callb(self.inst, *checked_args)
 
+class _string(str):
+    _TYPE = String
+
 class _builtin_type(object):
     def __getattribute__(self, name):
         TYPE = object.__getattribute__(self, "_TYPE")

Modified: pypy/branch/picklesupport/rpython/ootypesystem/rstr.py
==============================================================================
--- pypy/branch/picklesupport/rpython/ootypesystem/rstr.py	(original)
+++ pypy/branch/picklesupport/rpython/ootypesystem/rstr.py	Sat Apr 29 06:21:31 2006
@@ -1,10 +1,18 @@
 from pypy.rpython.rstr import AbstractStringRepr, STR, AbstractStringIteratorRepr
 from pypy.rpython.lltypesystem.lltype import Ptr
-from pypy.rpython.ootypesystem.ootype import Signed, Record
+from pypy.rpython.ootypesystem.ootype import Signed, Record, String, make_string
 
 class StringRepr(AbstractStringRepr):
 
-    lowleveltype = Ptr(STR)
+    lowleveltype = String
+
+    def convert_const(self, value):
+        # XXX what do we do about null strings?
+        #if value is None:
+        #    return nullptr(STR)
+        if not isinstance(value, str):
+            raise TyperError("not a str: %r" % (value,))
+        return make_string(value)
 
     def make_iterator_repr(self):
         return string_iterator_repr

Modified: pypy/branch/picklesupport/rpython/rctypes/rpointer.py
==============================================================================
--- pypy/branch/picklesupport/rpython/rctypes/rpointer.py	(original)
+++ pypy/branch/picklesupport/rpython/rctypes/rpointer.py	Sat Apr 29 06:21:31 2006
@@ -9,20 +9,27 @@
 
 class PointerRepr(CTypesValueRepr):
     def __init__(self, rtyper, s_pointer):
-        ptr_ctype = s_pointer.knowntype
-        ref_ctype = ptr_ctype._type_
+        # For recursive types, getting the r_contents is delayed until
+        # _setup_repr().
+        ll_contents = lltype.Ptr(lltype.ForwardReference())
+        self.keepalive_box_type = lltype.GcForwardReference()
+        super(PointerRepr, self).__init__(rtyper, s_pointer, ll_contents)
 
+    def _setup_repr(self):
         # Find the repr and low-level type of the contents from its ctype
+        rtyper = self.rtyper
+        ref_ctype = self.ctype._type_
         self.r_contents = rtyper.getrepr(SomeCTypesObject(ref_ctype,
                                                SomeCTypesObject.MEMORYALIAS))
-
-        ll_contents = lltype.Ptr(self.r_contents.c_data_type)
-
-        super(PointerRepr, self).__init__(rtyper, s_pointer, ll_contents)
+        if isinstance(self.ll_type.TO, lltype.ForwardReference):
+            self.ll_type.TO.become(self.r_contents.c_data_type)
+        if isinstance(self.keepalive_box_type, lltype.GcForwardReference):
+            self.keepalive_box_type.become(
+                self.r_contents.r_memoryowner.lowleveltype.TO)
 
     def get_content_keepalive_type(self):
         "Keepalive for the box that holds the data that 'self' points to."
-        return self.r_contents.r_memoryowner.lowleveltype
+        return lltype.Ptr(self.keepalive_box_type)
 
     def setkeepalive(self, llops, v_box, v_owner):
         inputargs = [v_box, inputconst(lltype.Void, 'keepalive'),

Modified: pypy/branch/picklesupport/rpython/rctypes/rstringbuf.py
==============================================================================
--- pypy/branch/picklesupport/rpython/rctypes/rstringbuf.py	(original)
+++ pypy/branch/picklesupport/rpython/rctypes/rstringbuf.py	Sat Apr 29 06:21:31 2006
@@ -4,7 +4,7 @@
 from pypy.rpython.rctypes.rmodel import CTypesRefRepr
 from pypy.objspace.flow.model import Constant
 from pypy.rpython.rslice import AbstractSliceRepr
-from pypy.rpython.rstr import string_repr
+from pypy.rpython.lltypesystem.rstr import string_repr
 
 class StringBufRepr(CTypesRefRepr):
 

Modified: pypy/branch/picklesupport/rpython/rctypes/rvoid_p.py
==============================================================================
--- pypy/branch/picklesupport/rpython/rctypes/rvoid_p.py	(original)
+++ pypy/branch/picklesupport/rpython/rctypes/rvoid_p.py	Sat Apr 29 06:21:31 2006
@@ -1,5 +1,30 @@
-from pypy.rpython.rctypes.rmodel import CTypesValueRepr
-
+from pypy.rpython.rctypes.rmodel import CTypesValueRepr, C_ZERO
+from pypy.rpython.rctypes.rstringbuf import StringBufRepr
+from pypy.annotation.pairtype import pairtype
+from pypy.rpython.rctypes.rchar_p import CCharPRepr
+from pypy.rpython.lltypesystem import llmemory
 
 class CVoidPRepr(CTypesValueRepr):
     pass  # No operations supported on c_void_p instances so far
+
+class __extend__(pairtype(StringBufRepr, CVoidPRepr)):
+    def convert_from_to((r_from, r_to), v, llops):
+        # warning: no keepalives, only for short-lived conversions like
+        # in argument passing
+        r_temp = r_to.r_memoryowner
+        v_owned_box = r_temp.allocate_instance(llops)
+        v_c_array = r_from.get_c_data_of_item(llops, v, C_ZERO)
+        v_adr = llops.genop('cast_ptr_to_adr', [v_c_array],
+                            resulttype = llmemory.Address)
+        r_temp.setvalue(llops, v_owned_box, v_adr)
+        return llops.convertvar(v_owned_box, r_temp, r_to)
+        # XXX some code duplication above
+
+class __extend__(pairtype(CCharPRepr, CVoidPRepr)):
+    def convert_from_to((r_from, r_to), v, llops):
+        v_ptr = r_from.getvalue(llops, v)
+        v_adr = llops.genop('cast_ptr_to_adr', [v_ptr],
+                            resulttype = llmemory.Address)
+                            
+        return r_to.return_value(llops, v_adr)
+

Modified: pypy/branch/picklesupport/rpython/rctypes/test/test_rfunc.py
==============================================================================
--- pypy/branch/picklesupport/rpython/rctypes/test/test_rfunc.py	(original)
+++ pypy/branch/picklesupport/rpython/rctypes/test/test_rfunc.py	Sat Apr 29 06:21:31 2006
@@ -11,10 +11,11 @@
 from pypy.translator.c.test.test_genc import compile
 from pypy import conftest
 from pypy.rpython.lltypesystem.rstr import string_repr
-from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.lltypesystem import lltype, llmemory
 
 from ctypes import cdll, pythonapi, PyDLL, _FUNCFLAG_PYTHONAPI
-from ctypes import c_int, c_long, c_char_p, c_char, create_string_buffer
+from ctypes import c_int, c_long, c_char_p, c_void_p, c_char
+from ctypes import create_string_buffer, cast
 from ctypes import POINTER, py_object, byref, Structure
 from pypy.rpython.rctypes.tool import util      # ctypes.util from 0.9.9.6
 
@@ -63,6 +64,18 @@
 ##PyIntIntCallback = CALLBACK_FUNCTYPE(c_int, c_int, callconv=PyDLL)
 ##pycallback = PyIntIntCallback(mycallback)
 
+def ll_memcpy(dst, src, length):
+    C_ARRAY = lltype.Ptr(lltype.FixedSizeArray(lltype.Char, 1))
+    c_src = llmemory.cast_adr_to_ptr(src, C_ARRAY)
+    c_dst = llmemory.cast_adr_to_ptr(dst, C_ARRAY)
+    for i in range(length):
+        c_dst[i] = c_src[i]
+    return dst
+
+memcpy = mylib.memcpy
+memcpy.argtypes = [c_void_p, c_void_p, c_long]
+memcpy.restype = c_void_p
+memcpy.llinterp_friendly_version = ll_memcpy
 
 def test_labs(n=6):
     assert labs(n) == abs(n)
@@ -159,6 +172,18 @@
         a.build_types(ep, [])
         if conftest.option.view:
             a.translator.view()
+    def test_annotate_call_void_p_arg_with_stringbuf(self):
+        string = 'abc xyz'
+        def f(x):
+            buf = create_string_buffer(len(string) + 1)
+            res = memcpy(buf, string, len(string))
+            return buf.value
+        a = RPythonAnnotator()
+        s = a.build_types(f, [int])
+        if conftest.option.view:
+            a.translator.view()
+        assert s.knowntype == str
+        
 
 ##    def test_annotate_callback(self):
 ##        def fn(n):
@@ -232,6 +257,17 @@
         res = interpret(fn, [11])
         assert res == 42
 
+    def test_specialize_call_void_p_arg_with_stringbuf(self):
+        string = 'abc xyz'
+        def f():
+            buf = create_string_buffer(len(string) + 1)
+            res = memcpy(buf, c_char_p(string), len(string))
+            return buf.value
+        assert f() == string
+        res = interpret(f, [])
+        assert ''.join(res.chars) == string
+        
+
 class Test_compile:
     def test_compile_labs(self):
         fn = compile(test_labs, [int])
@@ -300,3 +336,14 @@
         s1 = time.ctime(N)
         s2 = fn(N)
         assert s1.strip() == s2.strip()
+
+    def test_compile_call_void_p_arg_with_stringbuf(self):
+        string = 'abc xyz'
+        def f():
+            buf = create_string_buffer(len(string) + 1)
+            res = memcpy(buf, c_char_p(string), len(string))
+            return buf.value
+        assert f() == string
+        fn = compile(f, [])
+        assert fn() == string
+        

Modified: pypy/branch/picklesupport/rpython/rctypes/test/test_rstruct.py
==============================================================================
--- pypy/branch/picklesupport/rpython/rctypes/test/test_rstruct.py	(original)
+++ pypy/branch/picklesupport/rpython/rctypes/test/test_rstruct.py	Sat Apr 29 06:21:31 2006
@@ -13,7 +13,7 @@
 from pypy.rpython.test.test_llinterp import interpret
 
 from ctypes import c_int, c_short, Structure, POINTER, pointer, c_char_p
-from ctypes import c_char
+from ctypes import c_char, SetPointerType
 
 class tagpoint(Structure):
     _fields_ = [("x", c_int),
@@ -151,6 +151,23 @@
         res = interpret(func, [])
         assert res == 121
 
+    def test_struct_with_pointer_to_self(self):
+        PS = POINTER('S')
+        class S(Structure):
+            _fields_ = [('l', PS), ('r', PS)]
+        SetPointerType(PS, S)
+
+        def func():
+            s0 = S()
+            s0.r.contents = s0
+            s0.l.contents = S()
+            s0.l.contents.r.contents = s0
+
+            return bool(s0.r.contents.l.contents.l)
+        assert not func()
+        res = interpret(func, [])
+        assert res is False
+        
     def test_specialize_keepalive(self):
         class S(Structure):
             _fields_ = [('x', c_int)]

Modified: pypy/branch/picklesupport/rpython/rctypes/tool/ctypes_platform.py
==============================================================================
--- pypy/branch/picklesupport/rpython/rctypes/tool/ctypes_platform.py	(original)
+++ pypy/branch/picklesupport/rpython/rctypes/tool/ctypes_platform.py	Sat Apr 29 06:21:31 2006
@@ -187,7 +187,7 @@
         for i, cell in enumerate(layout):
             if cell is not None:
                 continue
-            layout_addfield(layout, i, ctypes.c_char, '_pad%d' % (n,))
+            layout_addfield(layout, i, ctypes.c_char, 'pad%d' % (n,))
             n += 1
 
         # build the ctypes Structure

Modified: pypy/branch/picklesupport/rpython/robject.py
==============================================================================
--- pypy/branch/picklesupport/rpython/robject.py	(original)
+++ pypy/branch/picklesupport/rpython/robject.py	Sat Apr 29 06:21:31 2006
@@ -1,7 +1,7 @@
 from pypy.annotation.pairtype import pairtype
 from pypy.annotation import model as annmodel
 from pypy.rpython.lltypesystem.lltype import \
-     PyObject, Ptr, Void, pyobjectptr, nullptr
+     PyObject, Ptr, Void, pyobjectptr, nullptr, Bool
 from pypy.rpython.rmodel import Repr, VoidRepr, inputconst
 from pypy.rpython import rclass
 from pypy.tool.sourcetools import func_with_new_name
@@ -69,3 +69,10 @@
 for opname in annmodel.BINARY_OPERATIONS:
     make_operation(opname, pairtype(PyObjRepr, Repr))
     make_operation(opname, pairtype(Repr, PyObjRepr))
+
+    
+class __extend__(pairtype(PyObjRepr, PyObjRepr)): 
+    def rtype_contains((r_seq, r_item), hop):
+        v_seq, v_item = hop.inputargs(r_seq, r_item)
+        return hop.llops.gencapicall('PySequence_Contains_with_exc',
+                                     [v_seq, v_item], resulttype=Bool)

Modified: pypy/branch/picklesupport/rpython/rstr.py
==============================================================================
--- pypy/branch/picklesupport/rpython/rstr.py	(original)
+++ pypy/branch/picklesupport/rpython/rstr.py	Sat Apr 29 06:21:31 2006
@@ -247,7 +247,8 @@
         return hop.gendirectcall(llfn, v_str, v_index)
 
     def rtype_mod(_, hop):
-        return do_stringformat(hop, [(hop.args_v[1], hop.args_r[1])])
+        rstr = hop.rtyper.type_system.rstr
+        return rstr.do_stringformat(hop, [(hop.args_v[1], hop.args_r[1])])
 
 
 class __extend__(pairtype(AbstractStringRepr, SliceRepr)):
@@ -313,7 +314,8 @@
                          resulttype=Bool)
 
     def rtype_mod(_, hop):
-        return do_stringformat(hop, [(hop.args_v[1], hop.args_r[1])])
+        rstr = hop.rtyper.type_system.rstr
+        return rstr.do_stringformat(hop, [(hop.args_v[1], hop.args_r[1])])
 
 class __extend__(pairtype(AbstractStringRepr, CharRepr)):
     def rtype_contains(_, hop):
@@ -410,7 +412,8 @@
                               resulttype=r_arg)
             sourcevars.append((vitem, r_arg))
 
-        return do_stringformat(hop, sourcevars)
+        rstr = hop.rtyper.type_system.rstr
+        return rstr.do_stringformat(hop, sourcevars)
                 
 
 class __extend__(CharRepr):

Modified: pypy/branch/picklesupport/rpython/test/test_rstr.py
==============================================================================
--- pypy/branch/picklesupport/rpython/test/test_rstr.py	(original)
+++ pypy/branch/picklesupport/rpython/test/test_rstr.py	Sat Apr 29 06:21:31 2006
@@ -302,6 +302,9 @@
 
     res = interpret(lambda: ''.join(['abc', 'de', 'fghi']), [])
     assert ''.join(res.chars) == "abcdefghi"
+
+    res = interpret(lambda: '.'.join(['abc', 'def']), [])
+    assert ''.join(res.chars) == 'abc.def'
     
     def fn(i, j):
         s1 = [ '', ',', ' and ']



More information about the Pypy-commit mailing list