[pypy-svn] r69002 - in pypy/branch/avm/pypy: . interpreter interpreter/test module objspace/std objspace/std/test

magcius at codespeak.net magcius at codespeak.net
Thu Nov 5 20:27:33 CET 2009


Author: magcius
Date: Thu Nov  5 20:27:32 2009
New Revision: 69002

Added:
   pypy/branch/avm/pypy/TODO
      - copied unchanged from r4823, pypy/trunk/src/pypy/TODO
   pypy/branch/avm/pypy/interpreter/autopath.py
      - copied unchanged from r4823, pypy/trunk/src/pypy/interpreter/autopath.py
   pypy/branch/avm/pypy/interpreter/extmodule.py
      - copied unchanged from r4823, pypy/trunk/src/pypy/interpreter/extmodule.py
   pypy/branch/avm/pypy/interpreter/py.py
      - copied unchanged from r4823, pypy/trunk/src/pypy/interpreter/py.py
   pypy/branch/avm/pypy/interpreter/test/autopath.py
      - copied unchanged from r4823, pypy/trunk/src/pypy/interpreter/test/autopath.py
   pypy/branch/avm/pypy/interpreter/test/foomodule.py
      - copied unchanged from r4823, pypy/trunk/src/pypy/interpreter/test/foomodule.py
   pypy/branch/avm/pypy/interpreter/test/test_extmodule.py
      - copied unchanged from r4823, pypy/trunk/src/pypy/interpreter/test/test_extmodule.py
   pypy/branch/avm/pypy/interpreter/unittest_w.py
      - copied unchanged from r4823, pypy/trunk/src/pypy/interpreter/unittest_w.py
   pypy/branch/avm/pypy/module/__builtin__interp.py
      - copied unchanged from r4823, pypy/trunk/src/pypy/module/__builtin__interp.py
   pypy/branch/avm/pypy/module/__builtin__module.py
      - copied unchanged from r4823, pypy/trunk/src/pypy/module/__builtin__module.py
   pypy/branch/avm/pypy/module/sysinterp.py
      - copied unchanged from r4823, pypy/trunk/src/pypy/module/sysinterp.py
   pypy/branch/avm/pypy/module/sysmodule.py
      - copied unchanged from r4823, pypy/trunk/src/pypy/module/sysmodule.py
   pypy/branch/avm/pypy/objspace/std/test/broken_test_floatobject.py
      - copied unchanged from r4823, pypy/trunk/src/pypy/objspace/std/test/broken_test_floatobject.py
   pypy/branch/avm/pypy/objspace/std/userobject.py
      - copied unchanged from r4823, pypy/trunk/src/pypy/objspace/std/userobject.py
Modified:
   pypy/branch/avm/pypy/   (props changed)
   pypy/branch/avm/pypy/interpreter/   (props changed)
   pypy/branch/avm/pypy/interpreter/baseobjspace.py
   pypy/branch/avm/pypy/interpreter/executioncontext.py
   pypy/branch/avm/pypy/interpreter/interactive.py
   pypy/branch/avm/pypy/interpreter/pyframe.py
   pypy/branch/avm/pypy/interpreter/test/test_interpreter.py
   pypy/branch/avm/pypy/objspace/std/intobject.py
   pypy/branch/avm/pypy/objspace/std/listobject.py
   pypy/branch/avm/pypy/objspace/std/noneobject.py
   pypy/branch/avm/pypy/objspace/std/sliceobject.py
   pypy/branch/avm/pypy/objspace/std/stringobject.py
   pypy/branch/avm/pypy/objspace/std/test/test_multimethod.py
Log:
Finally. More work on AVM2.

Modified: pypy/branch/avm/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/branch/avm/pypy/interpreter/baseobjspace.py	(original)
+++ pypy/branch/avm/pypy/interpreter/baseobjspace.py	Thu Nov  5 20:27:32 2009
@@ -1,594 +1,130 @@
-from pypy.interpreter.executioncontext import ExecutionContext, ActionFlag
-from pypy.interpreter.executioncontext import UserDelAction, FrameTraceAction
+from pypy.interpreter.executioncontext import ExecutionContext
 from pypy.interpreter.error import OperationError
-from pypy.interpreter.argument import Arguments, ArgumentsFromValuestack
-from pypy.interpreter.pycompiler import CPythonCompiler, PythonAstCompiler
-from pypy.interpreter.miscutils import ThreadLocals
-from pypy.tool.cache import Cache
-from pypy.tool.uid import HUGEVAL_BYTES
-from pypy.rlib.objectmodel import we_are_translated
-from pypy.rlib.debug import make_sure_not_resized
-from pypy.rlib.timer import DummyTimer, Timer
-import os, sys
-
-__all__ = ['ObjSpace', 'OperationError', 'Wrappable', 'W_Root']
-
-
-class W_Root(object):
-    """This is the abstract root class of all wrapped objects that live
-    in a 'normal' object space like StdObjSpace."""
-    __slots__ = ()
-    _settled_ = True
-
-    def getdict(self):
-        return None
-
-    def getdictvalue_w(self, space, attr):
-        return self.getdictvalue(space, space.wrap(attr))
-
-    def getdictvalue(self, space, w_attr):
-        w_dict = self.getdict()
-        if w_dict is not None:
-            return space.finditem(w_dict, w_attr)
-        return None
-
-    def getdictvalue_attr_is_in_class(self, space, w_attr):
-        return self.getdictvalue(space, w_attr)
-
-    def setdictvalue(self, space, w_attr, w_value, shadows_type=True):
-        w_dict = self.getdict()
-        if w_dict is not None:
-            space.set_str_keyed_item(w_dict, w_attr, w_value, shadows_type)
-            return True
-        return False
+from pypy.interpreter.miscutils import Stack, getthreadlocals
+import pypy.module
 
-    def deldictvalue(self, space, w_name):
-        w_dict = self.getdict()
-        if w_dict is not None:
-            try:
-                space.delitem(w_dict, w_name)
-                return True
-            except OperationError, ex:
-                if not ex.match(space, space.w_KeyError):
-                    raise
-        return False
+__all__ = ['ObjSpace', 'OperationError', 'NoValue']
 
-    def setdict(self, space, w_dict):
-        typename = space.type(self).getname(space, '?')
-        raise OperationError(space.w_TypeError,
-                             space.wrap("attribute '__dict__' of %s objects "
-                                        "is not writable" % typename))
-
-    # to be used directly only by space.type implementations
-    def getclass(self, space):
-        return space.gettypeobject(self.typedef)
-
-    def setclass(self, space, w_subtype):
-        raise OperationError(space.w_TypeError,
-                             space.wrap("__class__ assignment: only for heap types"))
 
-    def user_setup(self, space, w_subtype):
-        assert False, "only for interp-level user subclasses from typedef.py"
+class Wrappable(object):
+    """A subclass of Wrappable is an internal, interpreter-level class
+    that can nevertheless be exposed at application-level by space.wrap()."""
 
-    def getname(self, space, default):
+    def get_wdict(self):
+        space = self.space
         try:
-            return space.str_w(space.getattr(self, space.wrap('__name__')))
-        except OperationError, e:
-            if e.match(space, space.w_TypeError) or e.match(space, space.w_AttributeError):
-                return default
-            raise
-
-    def getaddrstring(self, space):
-        # XXX slowish
-        w_id = space.id(self)
-        w_4 = space.wrap(4)
-        w_0x0F = space.wrap(0x0F)
-        i = 2 * HUGEVAL_BYTES
-        addrstring = [' '] * i
-        while True:
-            n = space.int_w(space.and_(w_id, w_0x0F))
-            n += ord('0')
-            if n > ord('9'):
-                n += (ord('a') - ord('9') - 1)
-            i -= 1
-            addrstring[i] = chr(n)
-            if i == 0:
-                break
-            w_id = space.rshift(w_id, w_4)
-        return ''.join(addrstring)
-
-    def getrepr(self, space, info, moreinfo=''):
-        addrstring = self.getaddrstring(space)
-        return space.wrap("<%s at 0x%s%s>" % (info, addrstring,
-                                              moreinfo))
-
-    def getslotvalue(self, index):
-        raise NotImplementedError
+            return self.w_dict
+        except AttributeError:
+            w_dict = self.w_dict = space.newdict([])
+            for name,w_value in self.app_visible():
+                space.setitem(w_dict,space.wrap(name),w_value)
+            return w_dict
 
-    def setslotvalue(self, index, w_val):
+    def app_visible(self):
+        """ returns [(name,w_value)...] for application-level visible attributes """ 
         raise NotImplementedError
 
-    def descr_call_mismatch(self, space, opname, RequiredClass, args):
-        if RequiredClass is None:
-            classname = '?'
-        else:
-            classname = wrappable_class_name(RequiredClass)
-        msg = "'%s' object expected, got '%s' instead" % (
-            classname, self.getclass(space).getname(space, '?'))
-        raise OperationError(space.w_TypeError, space.wrap(msg))
-
-    # used by _weakref implemenation
-
-    def getweakref(self):
-        return None
-
-    def setweakref(self, space, weakreflifeline):
-        typename = space.type(self).getname(space, '?')
-        raise OperationError(space.w_TypeError, space.wrap(
-            "cannot create weak reference to '%s' object" % typename))
-
-    def clear_all_weakrefs(self):
-        """Call this at the beginning of interp-level __del__() methods
-        in subclasses.  It ensures that weakrefs (if any) are cleared
-        before the object is further destroyed.
-        """
-        lifeline = self.getweakref()
-        if lifeline is not None:
-            # Clear all weakrefs to this object before we proceed with
-            # the destruction of the object.  We detach the lifeline
-            # first: if the code following before_del() calls the
-            # app-level, e.g. a user-defined __del__(), and this code
-            # tries to use weakrefs again, it won't reuse the broken
-            # (already-cleared) weakrefs from this lifeline.
-            self.setweakref(lifeline.space, None)
-            lifeline.clear_all_weakrefs()
-
-    __already_enqueued_for_destruction = False
-
-    def _enqueue_for_destruction(self, space):
-        """Put the object in the destructor queue of the space.
-        At a later, safe point in time, UserDelAction will use
-        space.userdel() to call the object's app-level __del__ method.
-        """
-        # this function always resurect the object, so when
-        # running on top of CPython we must manually ensure that
-        # we enqueue it only once
-        if not we_are_translated():
-            if self.__already_enqueued_for_destruction:
-                return
-            self.__already_enqueued_for_destruction = True
-        self.clear_all_weakrefs()
-        space.user_del_action.register_dying_object(self)
-
-    def _call_builtin_destructor(self):
-        pass     # method overridden in typedef.py
-
+    def pypy_getattr(self, w_name):
+        space = self.space 
+        w_dict = self.get_wdict()
+        try:
+            return space.getitem(w_dict,w_name)
+        except OperationError,e:
+            if not e.match(space,space.w_KeyError):
+                raise
+            raise OperationError(space.w_AttributeError,w_name)
 
-class Wrappable(W_Root):
-    """A subclass of Wrappable is an internal, interpreter-level class
-    that can nevertheless be exposed at application-level by space.wrap()."""
-    __slots__ = ()
-    _settled_ = True
 
-    def __spacebind__(self, space):
-        return self
+class NoValue(Exception):
+    """Raised to signal absence of value, e.g. in the iterator accessing
+    method 'op.next()' of object spaces."""
 
-class InternalSpaceCache(Cache):
-    """A generic cache for an object space.  Arbitrary information can
-    be attached to the space by defining a function or class 'f' which
-    can be called as 'f(space)'.  Its result is stored in this
-    ObjSpaceCache.
-    """
-    def __init__(self, space):
-        Cache.__init__(self)
-        self.space = space
-    def _build(self, callable):
-        return callable(self.space)
-
-class SpaceCache(Cache):
-    """A base class for all our concrete caches."""
-    def __init__(self, space):
-        Cache.__init__(self)
-        self.space = space
-    def _build(self, key):
-        val = self.space.enter_cache_building_mode()
-        try:
-            return self.build(key)
-        finally:
-            self.space.leave_cache_building_mode(val)
-    def _ready(self, result):
-        val = self.space.enter_cache_building_mode()
-        try:
-            return self.ready(result)
-        finally:
-            self.space.leave_cache_building_mode(val)
-    def ready(self, result):
-        pass
-
-class UnpackValueError(ValueError):
-    def __init__(self, msg):
-        self.msg = msg
-    def __str__(self):
-        return self.msg
-
-class DescrMismatch(Exception):
-    pass
-
-def wrappable_class_name(Class):
-    try:
-        return Class.typedef.name
-    except AttributeError:
-        return 'internal subclass of %s' % (Class.__name__,)
-wrappable_class_name._annspecialcase_ = 'specialize:memo'
 
-# ____________________________________________________________
-
-class ObjSpace(object):
+class ObjSpace:
     """Base class for the interpreter-level implementations of object spaces.
-    http://codespeak.net/pypy/dist/pypy/doc/objspace.html"""
-
+    http://codespeak.net/moin/pypy/moin.cgi/ObjectSpace"""
+    
     full_exceptions = True  # full support for exceptions (normalization & more)
 
-    def __init__(self, config=None):
-        "NOT_RPYTHON: Basic initialization of objects."
-        self.fromcache = InternalSpaceCache(self).getorbuild
-        self.threadlocals = ThreadLocals()
-        # set recursion limit
-        # sets all the internal descriptors
-        if config is None:
-            from pypy.config.pypyoption import get_pypy_config
-            config = get_pypy_config(translating=False)
-        self.config = config
-
-        # import extra modules for side-effects
-        import pypy.interpreter.nestedscope     # register *_DEREF bytecodes
-
-        self.interned_strings = {}
-        self.actionflag = ActionFlag()    # changed by the signal module
-        self.user_del_action = UserDelAction(self)
-        self.frame_trace_action = FrameTraceAction(self)
-        self.actionflag.register_action(self.user_del_action)
-        self.actionflag.register_action(self.frame_trace_action)
-
-        from pypy.interpreter.pyframe import PyFrame
-        self.FrameClass = PyFrame    # can be overridden to a subclass
-
-        if self.config.objspace.logbytecodes:
-            self.bytecodecounts = [0] * 256
-            self.bytecodetransitioncount = {}
-
-        if self.config.objspace.timing:
-            self.timer = Timer()
-        else:
-            self.timer = DummyTimer()
-
+    def __init__(self):
+        "Basic initialization of objects."
         self.initialize()
 
-    def startup(self):
-        # To be called before using the space
-
-        # Initialize all builtin modules
-        from pypy.interpreter.module import Module
-        for w_modname in self.unpackiterable(
-                                self.sys.get('builtin_module_names')):
-            modname = self.str_w(w_modname)
-            mod = self.interpclass_w(self.getbuiltinmodule(modname))
-            if isinstance(mod, Module):
-                import time
-                self.timer.start("startup " + modname)
-                mod.startup(self)
-                self.timer.stop("startup " + modname)
-
-    def finish(self):
-        w_exitfunc = self.sys.getdictvalue_w(self, 'exitfunc')
-        if w_exitfunc is not None:
-            self.call_function(w_exitfunc)
-        from pypy.interpreter.module import Module
-        for w_modname in self.unpackiterable(
-                                self.sys.get('builtin_module_names')):
-            modname = self.str_w(w_modname)
-            mod = self.interpclass_w(self.getbuiltinmodule(modname))
-            if isinstance(mod, Module):
-                mod.shutdown(self)
-        if self.config.objspace.std.withdictmeasurement:
-            from pypy.objspace.std.dictmultiobject import report
-            report()
-        if self.config.objspace.logbytecodes:
-            self.reportbytecodecounts()
-        if self.config.objspace.std.logspaceoptypes:
-            for s in self.FrameClass._space_op_types:
-                print s
-
-    def reportbytecodecounts(self):
-        os.write(2, "Starting bytecode report.\n")
-        fd = os.open('bytecode.txt', os.O_CREAT|os.O_WRONLY|os.O_TRUNC, 0644)
-        os.write(fd, "bytecodecounts = {\n")
-        for opcode in range(len(self.bytecodecounts)):
-            count = self.bytecodecounts[opcode]
-            if not count:
-                continue
-            os.write(fd, "    %s: %s,\n" % (opcode, count))
-        os.write(fd, "}\n")
-        os.write(fd, "bytecodetransitioncount = {\n")
-        for opcode, probs in self.bytecodetransitioncount.iteritems():
-            os.write(fd, "    %s: {\n" % (opcode, ))
-            for nextcode, count in probs.iteritems():
-                os.write(fd, "        %s: %s,\n" % (nextcode, count))
-            os.write(fd, "    },\n")
-        os.write(fd, "}\n")
-        os.close(fd)
-        os.write(2, "Reporting done.\n")
-
-    def __repr__(self):
-        try:
-            return self._this_space_repr_
-        except AttributeError:
-            return self.__class__.__name__
-
-    def setbuiltinmodule(self, importname):
-        """NOT_RPYTHON. load a lazy pypy/module and put it into sys.modules"""
-        import sys
-
-        fullname = "pypy.module.%s" % importname
-
-        Module = __import__(fullname,
-                            None, None, ["Module"]).Module
-        if Module.applevel_name is not None:
-            name = Module.applevel_name
-        else:
-            name = importname
-
-        w_name = self.wrap(name)
-        w_mod = self.wrap(Module(self, w_name))
-        w_modules = self.sys.get('modules')
-        self.setitem(w_modules, w_name, w_mod)
-        return name
-
-    def getbuiltinmodule(self, name):
-        w_name = self.wrap(name)
-        w_modules = self.sys.get('modules')
-        return self.getitem(w_modules, w_name)
-
-    def get_builtinmodule_to_install(self):
-        """NOT_RPYTHON"""
-        try:
-            return self._builtinmodule_list
-        except AttributeError:
-            pass
-
-        modules = []
-
-        # You can enable more modules by specifying --usemodules=xxx,yyy
-        for name, value in self.config.objspace.usemodules:
-            if value and name not in modules:
-                modules.append(name)
-
-        # a bit of custom logic: time2 or rctime take precedence over time
-        # XXX this could probably be done as a "requires" in the config
-        if ('time2' in modules or 'rctime' in modules) and 'time' in modules:
-            modules.remove('time')
-
-        import pypy
-        if not self.config.objspace.nofaking:
-            for modname in self.ALL_BUILTIN_MODULES:
-                if not (os.path.exists(
-                        os.path.join(os.path.dirname(pypy.__file__),
-                                     'lib', modname+'.py'))):
-                    modules.append('faked+'+modname)
-
-        self._builtinmodule_list = modules
-        return self._builtinmodule_list
-
-    ALL_BUILTIN_MODULES = [
-        'posix', 'nt', 'os2', 'mac', 'ce', 'riscos',
-        'math', 'array', 'select',
-        '_random', '_sre', 'time', '_socket', 'errno',
-        'unicodedata',
-        'parser', 'fcntl', '_codecs', 'binascii'
-    ]
-
     def make_builtins(self):
-        "NOT_RPYTHON: only for initializing the space."
-
-        from pypy.module.sys import Module
-        w_name = self.wrap('sys')
-        self.sys = Module(self, w_name)
-        w_modules = self.sys.get('modules')
-        self.setitem(w_modules, w_name, self.wrap(self.sys))
-
-        from pypy.module.__builtin__ import Module
-        w_name = self.wrap('__builtin__')
-        self.builtin = Module(self, w_name)
-        w_builtin = self.wrap(self.builtin)
-        self.setitem(w_modules, w_name, w_builtin)
-        self.setitem(self.builtin.w_dict, self.wrap('__builtins__'), w_builtin)
-
-        bootstrap_modules = ['sys', '__builtin__', 'exceptions']
-        installed_builtin_modules = bootstrap_modules[:]
+        # initializing builtins may require creating a frame which in
+        # turn already accesses space.w_builtins, provide a dummy one ...
+        self.w_builtins = self.newdict([])
+
+        assert not hasattr(self, 'builtin')
+        if not hasattr(self, 'sys'):
+            self.make_sys()
+
+        from pypy.interpreter.extmodule import BuiltinModule
+
+        # the builtins are iteratively initialized
+        self.builtin = BuiltinModule(self, '__builtin__', self.w_builtins)
+        self.w_builtin = self.wrap(self.builtin)
 
         # initialize with "bootstrap types" from objspace  (e.g. w_None)
         for name, value in self.__dict__.items():
-            if name.startswith('w_') and not name.endswith('Type'):
+            if name.startswith('w_'):
                 name = name[2:]
+                if name.startswith('builtin') or name.startswith('sys'):
+                    continue
                 #print "setitem: space instance %-20s into builtins" % name
-                self.setitem(self.builtin.w_dict, self.wrap(name), value)
+                self.setitem(self.w_builtins, self.wrap(name), value)
 
-        # install mixed and faked modules and set builtin_module_names on sys
-        for mixedname in self.get_builtinmodule_to_install():
-            if (mixedname not in bootstrap_modules
-                and not mixedname.startswith('faked+')):
-                self.install_mixedmodule(mixedname, installed_builtin_modules)
-        for mixedname in self.get_builtinmodule_to_install():
-            if mixedname.startswith('faked+'):
-                modname = mixedname[6:]
-                self.install_faked_module(modname, installed_builtin_modules)
-
-        installed_builtin_modules.sort()
-        w_builtin_module_names = self.newtuple(
-            [self.wrap(fn) for fn in installed_builtin_modules])
-
-        # force this value into the dict without unlazyfying everything
-        self.setitem(self.sys.w_dict, self.wrap('builtin_module_names'),
-                     w_builtin_module_names)
-
-    def install_mixedmodule(self, mixedname, installed_builtin_modules):
-        """NOT_RPYTHON"""
-        modname = self.setbuiltinmodule(mixedname)
-        if modname:
-            assert modname not in installed_builtin_modules, (
-                "duplicate interp-level module enabled for the "
-                "app-level module %r" % (modname,))
-            installed_builtin_modules.append(modname)
-
-    def load_cpython_module(self, modname):
-        "NOT_RPYTHON. Steal a module from CPython."
-        cpy_module = __import__(modname, {}, {}, ['*'])
-        return cpy_module
-
-    def install_faked_module(self, modname, installed_builtin_modules):
-        """NOT_RPYTHON"""
-        if modname in installed_builtin_modules:
-            return
-        try:
-            module = self.load_cpython_module(modname)
-        except ImportError:
-            return
-        else:
-            w_modules = self.sys.get('modules')
-            self.setitem(w_modules, self.wrap(modname), self.wrap(module))
-            installed_builtin_modules.append(modname)
-
-    def setup_builtin_modules(self):
-        "NOT_RPYTHON: only for initializing the space."
-        from pypy.interpreter.module import Module
-        for w_modname in self.unpackiterable(self.sys.get('builtin_module_names')):
-            modname = self.unwrap(w_modname)
-            mod = self.getbuiltinmodule(modname)
-            if isinstance(mod, Module):
-                mod.setup_after_space_initialization()
+        self.sys.setbuiltinmodule(self.w_builtin, '__builtin__')
 
-    def initialize(self):
-        """NOT_RPYTHON: Abstract method that should put some minimal
-        content into the w_builtins."""
+    def make_sys(self):
+        from pypy.interpreter.extmodule import BuiltinModule
+        assert not hasattr(self, 'sys')
+        self.sys = BuiltinModule(self, 'sys')
+        self.w_sys = self.wrap(self.sys)
+        self.sys.setbuiltinmodule(self.w_sys, 'sys')
+        
+    def get_builtin_module(self, name):
+        if name not in self.sys.builtin_modules:
+            return None
+        module = self.sys.builtin_modules[name]
+        if module is None:
+            from pypy.interpreter.extmodule import BuiltinModule
+            module = BuiltinModule(self, name)
+            self.sys.builtin_modules[name] = module
+        w_module = self.wrap(module)
+        self.sys.setbuiltinmodule(w_module, name)
+        return w_module
 
-    def enter_cache_building_mode(self):
-        "hook for the flow object space"
-    def leave_cache_building_mode(self, val):
-        "hook for the flow object space"
+    def initialize(self):
+        """Abstract method that should put some minimal content into the
+        w_builtins."""
 
     def getexecutioncontext(self):
         "Return what we consider to be the active execution context."
-        # Important: the annotator must not see a prebuilt ExecutionContext
-        # for reasons related to the specialization of the framestack attribute
-        # so we make sure that the threadlocals never *have* an
-        # ExecutionContext during translation.
-        if self.config.translating and not we_are_translated():
-            assert self.threadlocals.getvalue() is None, (
-                "threadlocals got an ExecutionContext during translation!")
-            try:
-                return self._ec_during_translation
-            except AttributeError:
-                ec = self.createexecutioncontext()
-                self._ec_during_translation = ec
-                return ec
-        # normal case follows.  The 'thread' module installs a real
-        # thread-local object in self.threadlocals, so this builds
-        # and caches a new ec in each thread.
-        ec = self.threadlocals.getvalue()
+        ec = getthreadlocals().executioncontext  #it's allways None (dec. 2003)
         if ec is None:
             ec = self.createexecutioncontext()
-            self.threadlocals.setvalue(ec)
         return ec
 
-    def _freeze_(self):
-        return True
-
     def createexecutioncontext(self):
         "Factory function for execution contexts."
         return ExecutionContext(self)
 
-    def createcompiler(self):
-        "Factory function creating a compiler object."
-        # XXX simple selection logic for now
-        try:
-            return self.default_compiler
-        except AttributeError:
-            if self.config.objspace.compiler == 'cpython':
-                compiler = CPythonCompiler(self)
-            elif self.config.objspace.compiler == 'ast':
-                compiler = PythonAstCompiler(self)
-            else:
-                raise ValueError('unknown --compiler option value: %r' % (
-                    self.config.objspace.compiler,))
-            self.default_compiler = compiler
-            return compiler
-
-    def createframe(self, code, w_globals, closure=None):
-        "Create an empty PyFrame suitable for this code object."
-        return self.FrameClass(self, code, w_globals, closure)
-
-    def allocate_lock(self):
-        """Return an interp-level Lock object if threads are enabled,
-        and a dummy object if they are not."""
-        if self.config.objspace.usemodules.thread:
-            # we use a sub-function to avoid putting the 'import' statement
-            # here, where the flow space would see it even if thread=False
-            return self.__allocate_lock()
-        else:
-            return dummy_lock
-
-    def __allocate_lock(self):
-        from pypy.module.thread.ll_thread import allocate_lock, error
-        try:
-            return allocate_lock()
-        except error:
-            raise OperationError(self.w_RuntimeError,
-                                 self.wrap("out of resources"))
-
     # Following is a friendly interface to common object space operations
     # that can be defined in term of more primitive ones.  Subclasses
     # may also override specific functions for performance.
 
-    #def is_(self, w_x, w_y):   -- not really useful.  Must be subclassed
-    #    "'x is y'."
-    #    w_id_x = self.id(w_x)
-    #    w_id_y = self.id(w_y)
-    #    return self.eq(w_id_x, w_id_y)
-
-    def not_(self, w_obj):
-        return self.wrap(not self.is_true(w_obj))
-
-    def eq_w(self, w_obj1, w_obj2):
-        """shortcut for space.is_true(space.eq(w_obj1, w_obj2))"""
-        return self.is_w(w_obj1, w_obj2) or self.is_true(self.eq(w_obj1, w_obj2))
-
-    def is_w(self, w_obj1, w_obj2):
-        """shortcut for space.is_true(space.is_(w_obj1, w_obj2))"""
-        return self.is_true(self.is_(w_obj1, w_obj2))
-
-    def hash_w(self, w_obj):
-        """shortcut for space.int_w(space.hash(w_obj))"""
-        return self.int_w(self.hash(w_obj))
-
-    def set_str_keyed_item(self, w_obj, w_key, w_value, shadows_type=True):
-        return self.setitem(w_obj, w_key, w_value)
-
-    def finditem(self, w_obj, w_key):
-        try:
-            return self.getitem(w_obj, w_key)
-        except OperationError, e:
-            if e.match(self, self.w_KeyError):
-                return None
-            raise
-
-    def findattr(self, w_object, w_name):
-        try:
-            return self.getattr(w_object, w_name)
-        except OperationError, e:
-            # a PyPy extension: let SystemExit and KeyboardInterrupt go through
-            if e.async(self):
-                raise
-            return None
+    def is_(self, w_x, w_y):
+        "'x is y'."
+        w_id_x = self.id(w_x)
+        w_id_y = self.id(w_y)
+        return self.eq(w_id_x, w_id_y)
+
+    def unwrapdefault(self, w_value, default):
+        if w_value is None or w_value == self.w_None:
+            return default
+        else:
+            return self.unwrap(w_value)
 
     def newbool(self, b):
         if b:
@@ -596,462 +132,78 @@
         else:
             return self.w_False
 
-    def new_interned_w_str(self, w_s):
-        s = self.str_w(w_s)
-        try:
-            return self.interned_strings[s]
-        except KeyError:
-            pass
-        self.interned_strings[s] = w_s
-        return w_s
-
-    def new_interned_str(self, s):
-        try:
-            return self.interned_strings[s]
-        except KeyError:
-            pass
-        w_s = self.interned_strings[s] = self.wrap(s)
-        return w_s
-
-    def interpclass_w(space, w_obj):
-        """
-         If w_obj is a wrapped internal interpreter class instance unwrap to it,
-         otherwise return None.  (Can be overridden in specific spaces; you
-     should generally use the helper space.interp_w() instead.)
-        """
-        if isinstance(w_obj, Wrappable):
-            return w_obj
-        return None
-
-    def descr_self_interp_w(self, RequiredClass, w_obj):
-        obj = self.interpclass_w(w_obj)
-        if not isinstance(obj, RequiredClass):
-            raise DescrMismatch()
-        return obj
-    descr_self_interp_w._annspecialcase_ = 'specialize:arg(1)'
-
-    def interp_w(self, RequiredClass, w_obj, can_be_None=False):
-        """
-        Unwrap w_obj, checking that it is an instance of the required internal
-        interpreter class (a subclass of Wrappable).
-        """
-        assert RequiredClass is not None
-        if can_be_None and self.is_w(w_obj, self.w_None):
-            return None
-        obj = self.interpclass_w(w_obj)
-        if not isinstance(obj, RequiredClass):   # or obj is None
-            msg = "'%s' object expected, got '%s' instead" % (
-                wrappable_class_name(RequiredClass),
-                w_obj.getclass(self).getname(self, '?'))
-            raise OperationError(self.w_TypeError, self.wrap(msg))
-        return obj
-    interp_w._annspecialcase_ = 'specialize:arg(1)'
-
-    def unpackiterable(self, w_iterable, expected_length=-1):
+    def unpackiterable(self, w_iterable, expected_length=None):
         """Unpack an iterable object into a real (interpreter-level) list.
-        Raise a real (subclass of) ValueError if the length is wrong."""
+        Raise a real ValueError if the length is wrong."""
         w_iterator = self.iter(w_iterable)
         items = []
         while True:
             try:
                 w_item = self.next(w_iterator)
-            except OperationError, e:
-                if not e.match(self, self.w_StopIteration):
-                    raise
+            except NoValue:
                 break  # done
-            if expected_length != -1 and len(items) == expected_length:
-                raise UnpackValueError("too many values to unpack")
+            if expected_length is not None and len(items) == expected_length:
+                raise ValueError, "too many values to unpack"
             items.append(w_item)
-        if expected_length != -1 and len(items) < expected_length:
+        if expected_length is not None and len(items) < expected_length:
             i = len(items)
             if i == 1:
                 plural = ""
             else:
                 plural = "s"
-            raise UnpackValueError("need more than %d value%s to unpack" %
-                                   (i, plural))
+            raise ValueError, "need more than %d value%s to unpack" % (i, plural)
         return items
 
-    def viewiterable(self, w_iterable, expected_length=-1):
-        """ More or less the same as unpackiterable, but does not return
-        a copy. Please don't modify the result
-        """
-        return make_sure_not_resized(self.unpackiterable(w_iterable,
-                                                         expected_length)[:])
+    def unpacktuple(self, w_tuple, expected_length=None):
+        """Same as unpackiterable(), but only for tuples.
+        Only use for bootstrapping or performance reasons."""
+        tuple_length = self.unwrap(self.len(w_tuple))
+        if expected_length is not None and tuple_length != expected_length:
+            raise ValueError, "got a tuple of length %d instead of %d" % (
+                tuple_length, expected_length)
+        items = [
+            self.getitem(w_tuple, self.wrap(i)) for i in range(tuple_length)]
+        return items
 
     def exception_match(self, w_exc_type, w_check_class):
         """Checks if the given exception type matches 'w_check_class'."""
-        if self.is_w(w_exc_type, w_check_class):
-            return True   # fast path (also here to handle string exceptions)
-        try:
-            return self.abstract_issubclass_w(w_exc_type, w_check_class)
-        except OperationError, e:
-            if e.match(self, self.w_TypeError):   # string exceptions maybe
-                return False
-            raise
-
-    def call_obj_args(self, w_callable, w_obj, args):
-        if not self.config.objspace.disable_call_speedhacks:
-            # XXX start of hack for performance            
-            from pypy.interpreter.function import Function        
-            if isinstance(w_callable, Function):
-                return w_callable.call_obj_args(w_obj, args)
-            # XXX end of hack for performance
-        return self.call_args(w_callable, args.prepend(w_obj))
-
-    def call(self, w_callable, w_args, w_kwds=None):
-        args = Arguments.frompacked(self, w_args, w_kwds)
-        return self.call_args(w_callable, args)
-
-    def call_function(self, w_func, *args_w):
-        nargs = len(args_w) # used for pruning funccall versions
-        if not self.config.objspace.disable_call_speedhacks and nargs < 5:
-            # XXX start of hack for performance
-            from pypy.interpreter.function import Function, Method
-            if isinstance(w_func, Method):
-                w_inst = w_func.w_instance
-                if w_inst is not None:
-                    if nargs < 4:
-                        func = w_func.w_function
-                        if isinstance(func, Function):
-                            return func.funccall(w_inst, *args_w)
-                elif args_w and (
-                        self.abstract_isinstance_w(args_w[0], w_func.w_class)):
-                    w_func = w_func.w_function
-
-            if isinstance(w_func, Function):
-                return w_func.funccall(*args_w)
-            # XXX end of hack for performance
-
-        args = Arguments(self, list(args_w))
-        return self.call_args(w_func, args)
-
-    def call_valuestack(self, w_func, nargs, frame):
-        from pypy.interpreter.function import Function, Method, is_builtin_code
-        if frame.is_being_profiled and is_builtin_code(w_func):
-            # XXX: this code is copied&pasted :-( from the slow path below
-            # call_valuestack().
-            args = frame.make_arguments(nargs)
+        check_list = [w_check_class]
+        while check_list:
+            w_item = check_list.pop()
+            # Match identical items.
+            if self.is_true(self.is_(w_exc_type, w_item)):
+                return True
             try:
-                return self.call_args_and_c_profile(frame, w_func, args)
-            finally:
-                if isinstance(args, ArgumentsFromValuestack):
-                    args.frame = None
-
-        if not self.config.objspace.disable_call_speedhacks:
-            # XXX start of hack for performance
-            if isinstance(w_func, Method):
-                w_inst = w_func.w_instance
-                if w_inst is not None:
-                    w_func = w_func.w_function
-                    # reuse callable stack place for w_inst
-                    frame.settopvalue(w_inst, nargs)
-                    nargs += 1
-                elif nargs > 0 and (
-                    self.abstract_isinstance_w(frame.peekvalue(nargs-1),   #    :-(
-                                               w_func.w_class)):
-                    w_func = w_func.w_function
-
-            if isinstance(w_func, Function):
-                return w_func.funccall_valuestack(nargs, frame)
-            # XXX end of hack for performance
+                # Match subclasses.
+                if self.is_true(self.issubtype(w_exc_type, w_item)):
+                    return True
+            except OperationError:
+                # Assume that this is a TypeError: w_item not a type,
+                # and assume that w_item is then actually a tuple.
+                exclst = self.unpackiterable(w_item)
+                check_list.extend(exclst)
+        return False
 
-        args = frame.make_arguments(nargs)
-        try:
-            return self.call_args(w_func, args)
-        finally:
-            if isinstance(args, ArgumentsFromValuestack):
-                args.frame = None
-
-    def call_args_and_c_profile(self, frame, w_func, args):
-        ec = self.getexecutioncontext()
-        ec.c_call_trace(frame, w_func)
-        try:
-            w_res = self.call_args(w_func, args)
-        except OperationError, e:
-            ec.c_exception_trace(frame, e.w_value)
-            raise
-        ec.c_return_trace(frame, w_func)
-        return w_res
+    def call_function(self, w_func, *args_w, **kw_w):
+        w_kw = self.newdict([(self.wrap(k), w_v) for k, w_v in kw_w.iteritems()])
+        return self.call(w_func, self.newtuple(list(args_w)), w_kw)
 
-    def call_method(self, w_obj, methname, *arg_w):
+    def call_method(self, w_obj, methname, *arg_w, **kw_w):
         w_meth = self.getattr(w_obj, self.wrap(methname))
-        return self.call_function(w_meth, *arg_w)
-
-    def lookup(self, w_obj, name):
-        w_type = self.type(w_obj)
-        w_mro = self.getattr(w_type, self.wrap("__mro__"))
-        for w_supertype in self.unpackiterable(w_mro):
-            w_value = w_supertype.getdictvalue_w(self, name)
-            if w_value is not None:
-                return w_value
-        return None
-
-    def is_oldstyle_instance(self, w_obj):
-        # xxx hack hack hack
-        from pypy.module.__builtin__.interp_classobj import W_InstanceObject
-        obj = self.interpclass_w(w_obj)
-        return obj is not None and isinstance(obj, W_InstanceObject)
-
-    def callable(self, w_obj):
-        if self.lookup(w_obj, "__call__") is not None:
-            if self.is_oldstyle_instance(w_obj):
-                # ugly old style class special treatment, but well ...
-                try:
-                    self.getattr(w_obj, self.wrap("__call__"))
-                    return self.w_True
-                except OperationError, e:
-                    if not e.match(self, self.w_AttributeError):
-                        raise
-                    return self.w_False
-            else:
-                return self.w_True
-        return self.w_False
+        return self.call_function(w_meth, *arg_w, **kw_w)
 
     def isinstance(self, w_obj, w_type):
         w_objtype = self.type(w_obj)
         return self.issubtype(w_objtype, w_type)
 
-    def abstract_issubclass_w(self, w_cls1, w_cls2):
-        # Equivalent to 'issubclass(cls1, cls2)'.  The code below only works
-        # for the simple case (new-style class, new-style class).
-        # This method is patched with the full logic by the __builtin__
-        # module when it is loaded.
-        return self.is_true(self.issubtype(w_cls1, w_cls2))
-
-    def abstract_isinstance_w(self, w_obj, w_cls):
-        # Equivalent to 'isinstance(obj, cls)'.  The code below only works
-        # for the simple case (new-style instance, new-style class).
-        # This method is patched with the full logic by the __builtin__
-        # module when it is loaded.
-        return self.is_true(self.isinstance(w_obj, w_cls))
-
-    def abstract_isclass_w(self, w_obj):
-        # Equivalent to 'isinstance(obj, type)'.  The code below only works
-        # for the simple case (new-style instance without special stuff).
-        # This method is patched with the full logic by the __builtin__
-        # module when it is loaded.
-        return self.is_true(self.isinstance(w_obj, self.w_type))
-
-    def abstract_getclass(self, w_obj):
-        # Equivalent to 'obj.__class__'.  The code below only works
-        # for the simple case (new-style instance without special stuff).
-        # This method is patched with the full logic by the __builtin__
-        # module when it is loaded.
-        return self.type(w_obj)
-
-    def eval(self, expression, w_globals, w_locals, hidden_applevel=False):
-        "NOT_RPYTHON: For internal debugging."
-        import types
-        from pypy.interpreter.pycode import PyCode
-        if isinstance(expression, str):
-            expression = compile(expression, '?', 'eval')
-        if isinstance(expression, types.CodeType):
-            expression = PyCode._from_code(self, expression,
-                                          hidden_applevel=hidden_applevel)
-        if not isinstance(expression, PyCode):
-            raise TypeError, 'space.eval(): expected a string, code or PyCode object'
-        return expression.exec_code(self, w_globals, w_locals)
-
-    def exec_(self, statement, w_globals, w_locals, hidden_applevel=False):
-        "NOT_RPYTHON: For internal debugging."
-        import types
-        from pypy.interpreter.pycode import PyCode
-        if isinstance(statement, str):
-            statement = compile(statement, '?', 'exec')
-        if isinstance(statement, types.CodeType):
-            statement = PyCode._from_code(self, statement,
-                                          hidden_applevel=hidden_applevel)
-        if not isinstance(statement, PyCode):
-            raise TypeError, 'space.exec_(): expected a string, code or PyCode object'
-        w_key = self.wrap('__builtins__')
-        if not self.is_true(self.contains(w_globals, w_key)):
-            self.setitem(w_globals, w_key, self.wrap(self.builtin))
-        return statement.exec_code(self, w_globals, w_locals)
-
-    def appexec(self, posargs_w, source):
-        """ return value from executing given source at applevel.
-            EXPERIMENTAL. The source must look like
-               '''(x, y):
-                       do_stuff...
-                       return result
-               '''
-        """
-        w_func = self.fromcache(AppExecCache).getorbuild(source)
-        args = Arguments(self, list(posargs_w))
-        return self.call_args(w_func, args)
-    appexec._annspecialcase_ = 'specialize:arg(2)'
-
-    def decode_index(self, w_index_or_slice, seqlength):
-        """Helper for custom sequence implementations
-             -> (index, 0, 0) or
-                (start, stop, step)
-        """
-        if self.is_true(self.isinstance(w_index_or_slice, self.w_slice)):
-            w_indices = self.call_method(w_index_or_slice, "indices",
-                                         self.wrap(seqlength))
-            w_start, w_stop, w_step = self.unpackiterable(w_indices, 3)
-            start = self.int_w(w_start)
-            stop  = self.int_w(w_stop)
-            step  = self.int_w(w_step)
-            if step == 0:
-                raise OperationError(self.w_ValueError,
-                                     self.wrap("slice step cannot be zero"))
-            if start < 0:
-                start = 0
-            if stop < start:
-                stop = start
-            assert stop <= seqlength
-        else:
-            start = self.int_w(w_index_or_slice)
-            if start < 0:
-                start += seqlength
-            if not (0 <= start < seqlength):
-                raise OperationError(self.w_IndexError,
-                                     self.wrap("index out of range"))
-            stop  = 0
-            step  = 0
-        return start, stop, step
-
-    def getindex_w(self, w_obj, w_exception, objdescr=None):
-        """Return w_obj.__index__() as an RPython int.
-        If w_exception is None, silently clamp in case of overflow;
-        else raise w_exception.
-        """
-        try:
-            w_index = self.index(w_obj)
-        except OperationError, err:
-            if objdescr is None or not err.match(self, self.w_TypeError):
-                raise
-            msg = "%s must be an integer, not %s" % (
-                objdescr, self.type(w_obj).getname(self, '?'))
-            raise OperationError(self.w_TypeError, self.wrap(msg))
-        try:
-            index = self.int_w(w_index)
-        except OperationError, err:
-            if not err.match(self, self.w_OverflowError):
-                raise
-            if not w_exception:
-                # w_index should be a long object, but can't be sure of that
-                if self.is_true(self.lt(w_index, self.wrap(0))):
-                    return -sys.maxint-1
-                else:
-                    return sys.maxint
-            else:
-                raise OperationError(
-                    w_exception, self.wrap(
-                    "cannot fit '%s' into an index-sized "
-                    "integer" % self.type(w_obj).getname(self, '?')))
-        else:
-            return index
-
-    def r_longlong_w(self, w_obj):
-        bigint = self.bigint_w(w_obj)
-        try:
-            return bigint.tolonglong()
-        except OverflowError:
-            raise OperationError(self.w_OverflowError,
-                                 self.wrap('integer too large'))
-
-    def r_ulonglong_w(self, w_obj):
-        bigint = self.bigint_w(w_obj)
-        try:
-            return bigint.toulonglong()
-        except OverflowError:
-            raise OperationError(self.w_OverflowError,
-                                 self.wrap('integer too large'))
-        except ValueError:
-            raise OperationError(self.w_ValueError,
-                                 self.wrap('cannot convert negative integer '
-                                           'to unsigned int'))
-
-    def buffer_w(self, w_obj):
-        # returns a Buffer instance
-        from pypy.interpreter.buffer import Buffer
-        w_buffer = self.buffer(w_obj)
-        return self.interp_w(Buffer, w_buffer)
-
-    def rwbuffer_w(self, w_obj):
-        # returns a RWBuffer instance
-        from pypy.interpreter.buffer import RWBuffer
-        buffer = self.buffer_w(w_obj)
-        if not isinstance(buffer, RWBuffer):
-            raise OperationError(self.w_TypeError,
-                                 self.wrap('read-write buffer expected'))
-        return buffer
-
-    def bufferstr_w(self, w_obj):
-        # Directly returns an interp-level str.  Note that if w_obj is a
-        # unicode string, this is different from str_w(buffer(w_obj)):
-        # indeed, the latter returns a string with the raw bytes from
-        # the underlying unicode buffer, but bufferstr_w() just converts
-        # the unicode to an ascii string.  This inconsistency is kind of
-        # needed because CPython has the same issue.  (Well, it's
-        # unclear if there is any use at all for getting the bytes in
-        # the unicode buffer.)
-        try:
-            return self.str_w(w_obj)
-        except OperationError, e:
-            if not e.match(self, self.w_TypeError):
-                raise
-            buffer = self.buffer_w(w_obj)
-            return buffer.as_str()
-
-    def bool_w(self, w_obj):
-        # Unwraps a bool, also accepting an int for compatibility.
-        # This is here mostly just for gateway.int_unwrapping_space_method().
-        return bool(self.int_w(w_obj))
-
-    def nonnegint_w(self, w_obj):
-        # Like space.int_w(), but raises an app-level ValueError if
-        # the integer is negative.  Mostly here for gateway.py.
-        value = self.int_w(w_obj)
-        if value < 0:
-            raise OperationError(self.w_ValueError,
-                                 self.wrap("expected a non-negative integer"))
-        return value
-
-    def warn(self, msg, w_warningcls):
-        self.appexec([self.wrap(msg), w_warningcls], """(msg, warningcls):
-            import warnings
-            warnings.warn(msg, warningcls, stacklevel=2)
-        """)
-
-    def resolve_target(self, w_obj):
-        """ A space method that can be used by special object spaces (like
-        thunk) to replace an object by another. """
-        return w_obj
-
-
-class AppExecCache(SpaceCache):
-    def build(cache, source):
-        """ NOT_RPYTHON """
-        space = cache.space
-        # XXX will change once we have our own compiler
-        import py
-        source = source.lstrip()
-        assert source.startswith('('), "incorrect header in:\n%s" % (source,)
-        source = py.code.Source("def anonymous%s\n" % source)
-        w_glob = space.newdict()
-        space.exec_(source.compile(), w_glob, w_glob)
-        return space.getitem(w_glob, space.wrap('anonymous'))
-
-class DummyLock(object):
-    def acquire(self, flag):
-        return True
-    def release(self):
-        pass
-    def _freeze_(self):
-        return True
-dummy_lock = DummyLock()
 
 ## Table describing the regular part of the interface of object spaces,
 ## namely all methods which only take w_ arguments and return a w_ result
-## (if any).  Note: keep in sync with pypy.objspace.flow.operation.Table.
+## (if any).  XXX Maybe we should say that these methods must be accessed
+## as 'space.op.xxx()' instead of directly 'space.xxx()'.
 
 ObjSpace.MethodTable = [
 # method name # symbol # number of arguments # special method name(s)
-    ('is_',             'is',        2, []),
     ('id',              'id',        1, []),
     ('type',            'type',      1, []),
     ('issubtype',       'issubtype', 2, []),  # not for old-style classes
@@ -1065,15 +217,13 @@
     ('getitem',         'getitem',   2, ['__getitem__']),
     ('setitem',         'setitem',   3, ['__setitem__']),
     ('delitem',         'delitem',   2, ['__delitem__']),
-    ('getslice',        'getslice',  3, ['__getslice__']),
-    ('setslice',        'setslice',  4, ['__setslice__']),
-    ('delslice',        'delslice',  3, ['__delslice__']),
     ('pos',             'pos',       1, ['__pos__']),
     ('neg',             'neg',       1, ['__neg__']),
-    ('nonzero',         'truth',     1, ['__nonzero__']),
+    ('not_',            'not',       1, []),
     ('abs' ,            'abs',       1, ['__abs__']),
     ('hex',             'hex',       1, ['__hex__']),
     ('oct',             'oct',       1, ['__oct__']),
+    ('round',           'round',     2, []),
     ('ord',             'ord',       1, []),
     ('invert',          '~',         1, ['__invert__']),
     ('add',             '+',         2, ['__add__', '__radd__']),
@@ -1091,9 +241,7 @@
     ('or_',             '|',         2, ['__or__', '__ror__']),
     ('xor',             '^',         2, ['__xor__', '__rxor__']),
     ('int',             'int',       1, ['__int__']),
-    ('index',           'index',     1, ['__index__']),
     ('float',           'float',     1, ['__float__']),
-    ('long',            'long',      1, ['__long__']),
     ('inplace_add',     '+=',        2, ['__iadd__']),
     ('inplace_sub',     '-=',        2, ['__isub__']),
     ('inplace_mul',     '*=',        2, ['__imul__']),
@@ -1113,17 +261,12 @@
     ('ne',              '!=',        2, ['__ne__', '__ne__']),
     ('gt',              '>',         2, ['__gt__', '__lt__']),
     ('ge',              '>=',        2, ['__ge__', '__le__']),
-    ('cmp',             'cmp',       2, ['__cmp__']),   # rich cmps preferred
-    ('coerce',          'coerce',    2, ['__coerce__', '__coerce__']),
     ('contains',        'contains',  2, ['__contains__']),
     ('iter',            'iter',      1, ['__iter__']),
-    ('next',            'next',      1, ['next']),
-#    ('call',            'call',      3, ['__call__']),
+    ('call',            'call',      3, ['__call__']),
     ('get',             'get',       3, ['__get__']),
     ('set',             'set',       3, ['__set__']),
     ('delete',          'delete',    2, ['__delete__']),
-    ('userdel',         'del',       1, ['__del__']),
-    ('buffer',          'buffer',    1, ['__buffer__']),   # see buffer.py
     ]
 
 ObjSpace.BuiltinModuleTable = [
@@ -1176,38 +319,13 @@
 
 ## Irregular part of the interface:
 #
-#                                   wrap(x) -> w_x
-#                              str_w(w_str) -> str
-#              int_w(w_ival or w_long_ival) -> ival
-#                       float_w(w_floatval) -> floatval
-#             uint_w(w_ival or w_long_ival) -> r_uint_val (unsigned int value)
-#             bigint_w(w_ival or w_long_ival) -> rbigint
-#interpclass_w(w_interpclass_inst or w_obj) -> interpclass_inst|w_obj
-#                               unwrap(w_x) -> x
-#                              is_true(w_x) -> True or False
-#                  newtuple([w_1, w_2,...]) -> w_tuple
-#                   newlist([w_1, w_2,...]) -> w_list
-#                                 newdict() -> empty w_dict
-#           newslice(w_start,w_stop,w_step) -> w_slice
-#              call_args(w_obj,Arguments()) -> w_result
-
-ObjSpace.IrregularOpTable = [
-    'wrap',
-    'str_w',
-    'int_w',
-    'float_w',
-    'uint_w',
-    'bigint_w',
-    'unicode_w',
-    'interpclass_w',
-    'unwrap',
-    'is_true',
-    'is_w',
-    'newtuple',
-    'newlist',
-    'newdict',
-    'newslice',
-    'call_args',
-    'marshal_w',
-    ]
-
+#                        wrap(x) -> w_x
+#                    unwrap(w_x) -> x
+#                   is_true(w_x) -> True or False
+#       newtuple([w_1, w_2,...]) -> w_tuple
+#        newlist([w_1, w_2,...]) -> w_list
+#      newstring([w_1, w_2,...]) -> w_string from ascii numbers (bytes)
+# newdict([(w_key,w_value),...]) -> w_dict
+#newslice(w_start,w_stop,w_step) -> w_slice (any argument may be a real None)
+#                   next(w_iter) -> w_value or raise NoValue
+#

Modified: pypy/branch/avm/pypy/interpreter/executioncontext.py
==============================================================================
--- pypy/branch/avm/pypy/interpreter/executioncontext.py	(original)
+++ pypy/branch/avm/pypy/interpreter/executioncontext.py	Thu Nov  5 20:27:32 2009
@@ -1,173 +1,48 @@
-import sys
-from pypy.interpreter.miscutils import Stack
-from pypy.interpreter.error import OperationError
-from pypy.rlib.rarithmetic import LONG_BIT
-from pypy.rlib.unroll import unrolling_iterable
-
-def new_framestack():
-    return Stack()
-
-def app_profile_call(space, w_callable, frame, event, w_arg):
-    space.call_function(w_callable,
-                        space.wrap(frame),
-                        space.wrap(event), w_arg)
+from pypy.interpreter.miscutils import getthreadlocals, Stack
 
 class ExecutionContext:
     """An ExecutionContext holds the state of an execution thread
     in the Python interpreter."""
-
+    
     def __init__(self, space):
+        # Note that self.framestack only contains PyFrames
         self.space = space
-        self.framestack = new_framestack()
-        # tracing: space.frame_trace_action.fire() must be called to ensure
-        # that tracing occurs whenever self.w_tracefunc or self.is_tracing
-        # is modified.
-        self.w_tracefunc = None
-        self.is_tracing = 0
-        self.compiler = space.createcompiler()
-        self.profilefunc = None
-        self.w_profilefuncarg = None
+        self.framestack = Stack()
 
     def enter(self, frame):
-        if self.framestack.depth() > self.space.sys.recursionlimit:
-            raise OperationError(self.space.w_RuntimeError,
-                                 self.space.wrap("maximum recursion depth exceeded"))
-        try:
-            frame.f_back = self.framestack.top()
-        except IndexError:
-            frame.f_back = None
-
-        if not frame.hide():
-            self.framestack.push(frame)
-
-    def leave(self, frame):
-        if self.profilefunc:
-            self._trace(frame, 'leaveframe', self.space.w_None)
-                
-        if not frame.hide():
-            self.framestack.pop()
-            if self.w_tracefunc is not None:
-                self.space.frame_trace_action.fire()
-
-
-    class Subcontext(object):
-        # coroutine: subcontext support
-
-        def __init__(self):
-            self.framestack = new_framestack()
-            self.w_tracefunc = None
-            self.profilefunc = None
-            self.w_profilefuncarg = None
-            self.is_tracing = 0
-
-        def enter(self, ec):
-            ec.framestack = self.framestack
-            ec.w_tracefunc = self.w_tracefunc
-            ec.profilefunc = self.profilefunc
-            ec.w_profilefuncarg = self.w_profilefuncarg
-            ec.is_tracing = self.is_tracing
-            ec.space.frame_trace_action.fire()
-
-        def leave(self, ec):
-            self.framestack = ec.framestack
-            self.w_tracefunc = ec.w_tracefunc
-            self.profilefunc = ec.profilefunc
-            self.w_profilefuncarg = ec.w_profilefuncarg 
-            self.is_tracing = ec.is_tracing
-
-        # the following interface is for pickling and unpickling
-        def getstate(self, space):
-            # we just save the framestack
-            items = [space.wrap(item) for item in self.framestack.items]
-            return space.newtuple(items)
-
-        def setstate(self, space, w_state):
-            from pypy.interpreter.pyframe import PyFrame
-            items = [space.interp_w(PyFrame, w_item)
-                     for w_item in space.unpackiterable(w_state)]
-            self.framestack.items = items
-        # coroutine: I think this is all, folks!
-
-
-    def get_builtin(self):
-        try:
-            return self.framestack.top().builtin
-        except IndexError:
-            return self.space.builtin
+        locals = getthreadlocals()
+        self.framestack.push(frame)
+        previous_ec = locals.executioncontext
+        locals.executioncontext = self
+        return previous_ec
+
+    def leave(self, previous_ec):
+        locals = getthreadlocals()
+        locals.executioncontext = previous_ec
+        self.framestack.pop()
+
+    def get_w_builtins(self):
+        if self.framestack.empty():
+            return self.space.w_builtins
+        else:
+            return self.framestack.top().w_builtins
 
-    # XXX this one should probably be dropped in favor of a module
     def make_standard_w_globals(self):
         "Create a new empty 'globals' dictionary."
         w_key = self.space.wrap("__builtins__")
-        w_value = self.space.wrap(self.get_builtin())
-        w_globals = self.space.newdict()
-        space.setitem(w_globals, w_key, w_value)
+        w_value = self.get_w_builtins()
+        w_globals = self.space.newdict([(w_key, w_value)])
         return w_globals
 
-    def c_call_trace(self, frame, w_func):
-        "Profile the call of a builtin function"
-        if self.profilefunc is None:
-            frame.is_being_profiled = False
-        else:
-            self._trace(frame, 'c_call', w_func)
-
-    def c_return_trace(self, frame, w_retval):
-        "Profile the return from a builtin function"
-        if self.profilefunc is None:
-            frame.is_being_profiled = False
-        else:
-            self._trace(frame, 'c_return', w_retval)
-
-    def c_exception_trace(self, frame, w_exc):
-        "Profile function called upon OperationError."
-        if self.profilefunc is None:
-            frame.is_being_profiled = False
-        else:
-            self._trace(frame, 'c_exception', w_exc)
-
-    def _llprofile(self, event, w_arg):
-        fr = self.framestack.items
-        space = self.space
-        w_callback = self.profilefunc
-        if w_callback is not None:
-            frame = None
-            if fr:
-                frame = fr[0]
-            self.profilefunc(space, self.w_profilefuncarg, frame, event, w_arg)
-
-    def call_trace(self, frame):
-        "Trace the call of a function"
-        if self.w_tracefunc is not None or self.profilefunc is not None:
-            self._trace(frame, 'call', self.space.w_None)
-            if self.profilefunc:
-                frame.is_being_profiled = True
-
-    def return_trace(self, frame, w_retval):
-        "Trace the return from a function"
-        if self.w_tracefunc is not None:
-            self._trace(frame, 'return', w_retval)
-
     def bytecode_trace(self, frame):
         "Trace function called before each bytecode."
-        # this is split into a fast path and a slower path that is
-        # not invoked every time bytecode_trace() is.
-        actionflag = self.space.actionflag
-        ticker = actionflag.get()
-        if actionflag.has_bytecode_counter:    # this "if" is constant-folded
-            ticker += 1
-            actionflag.set(ticker)
-        if ticker & actionflag.interesting_bits:  # fast check
-            actionflag.action_dispatcher(self, frame)     # slow path
-    bytecode_trace._always_inline_ = True
 
-    def exception_trace(self, frame, operationerr):
+    def exception_trace(self, operationerr):
         "Trace function called upon OperationError."
         operationerr.record_interpreter_traceback()
-        if self.w_tracefunc is not None:
-            self._trace(frame, 'exception', None, operationerr)
         #operationerr.print_detailed_traceback(self.space)
 
-    def sys_exc_info(self): # attn: the result is not the wrapped sys.exc_info() !!!
+    def sys_exc_info(self):
         """Implements sys.exc_info().
         Return an OperationError instance or None."""
         for i in range(self.framestack.depth()):
@@ -175,339 +50,3 @@
             if frame.last_exception is not None:
                 return frame.last_exception
         return None
-
-    def settrace(self, w_func):
-        """Set the global trace function."""
-        if self.space.is_w(w_func, self.space.w_None):
-            self.w_tracefunc = None
-        else:
-            self.w_tracefunc = w_func
-            self.space.frame_trace_action.fire()
-
-    def setprofile(self, w_func):
-        """Set the global trace function."""
-        if self.space.is_w(w_func, self.space.w_None):
-            self.profilefunc = None
-            self.w_profilefuncarg = None
-        else:
-            self.setllprofile(app_profile_call, w_func)
-
-    def setllprofile(self, func, w_arg):
-        self.profilefunc = func
-        if func is not None:
-            if w_arg is None:
-                raise ValueError("Cannot call setllprofile with real None")
-            for frame in self.framestack.items:
-                frame.is_being_profiled = True
-        self.w_profilefuncarg = w_arg
-
-    def call_tracing(self, w_func, w_args):
-        is_tracing = self.is_tracing
-        self.is_tracing = 0
-        try:
-            self.space.frame_trace_action.fire()
-            return self.space.call(w_func, w_args)
-        finally:
-            self.is_tracing = is_tracing
-
-    def _trace(self, frame, event, w_arg, operr=None):
-        if self.is_tracing or frame.hide():
-            return
-
-        space = self.space
-        
-        # Tracing cases
-        if event == 'call':
-            w_callback = self.w_tracefunc
-        else:
-            w_callback = frame.w_f_trace
-
-        if w_callback is not None and event != "leaveframe":
-            if operr is not None:
-                w_arg =  space.newtuple([operr.w_type, operr.w_value,
-                                     space.wrap(operr.application_traceback)])
-
-            frame.fast2locals()
-            self.is_tracing += 1
-            try:
-                try:
-                    w_result = space.call_function(w_callback, space.wrap(frame), space.wrap(event), w_arg)
-                    if space.is_w(w_result, space.w_None):
-                        frame.w_f_trace = None
-                    else:
-                        frame.w_f_trace = w_result
-                except:
-                    self.settrace(space.w_None)
-                    frame.w_f_trace = None
-                    raise
-            finally:
-                self.is_tracing -= 1
-                frame.locals2fast()
-                space.frame_trace_action.fire()
-
-        # Profile cases
-        if self.profilefunc is not None:
-            if event not in ['leaveframe', 'call', 'c_call',
-                             'c_return', 'c_exception']:
-                return
-
-            last_exception = None
-            if event == 'leaveframe':
-                last_exception = frame.last_exception
-                event = 'return'
-
-            assert self.is_tracing == 0 
-            self.is_tracing += 1
-            try:
-                try:
-                    self.profilefunc(space, self.w_profilefuncarg,
-                                     frame, event, w_arg)
-                except:
-                    self.profilefunc = None
-                    self.w_profilefuncarg = None
-                    raise
-
-            finally:
-                frame.last_exception = last_exception
-                self.is_tracing -= 1
-
-    def _freeze_(self):
-        raise Exception("ExecutionContext instances should not be seen during"
-                        " translation.  Now is a good time to inspect the"
-                        " traceback and see where this one comes from :-)")
-
-
-class AbstractActionFlag:
-    """This holds the global 'action flag'.  It is a single bitfield
-    integer, with bits corresponding to AsyncAction objects that need to
-    be immediately triggered.  The correspondance from bits to
-    AsyncAction instances is built at translation time.  We can quickly
-    check if there is anything at all to do by checking if any of the
-    relevant bits is set.  If threads are enabled, they consume the 20
-    lower bits to hold a counter incremented at each bytecode, to know
-    when to release the GIL.
-    """
-    def __init__(self):
-        self._periodic_actions = []
-        self._nonperiodic_actions = []
-        self.unused_bits = self.FREE_BITS[:]
-        self.has_bytecode_counter = False
-        self.interesting_bits = 0
-        self._rebuild_action_dispatcher()
-
-    def fire(self, action):
-        """Request for the action to be run before the next opcode.
-        The action must have been registered at space initalization time."""
-        ticker = self.get()
-        self.set(ticker | action.bitmask)
-
-    def register_action(self, action):
-        "NOT_RPYTHON"
-        assert isinstance(action, AsyncAction)
-        if action.bitmask == 0:
-            while True:
-                action.bitmask = self.unused_bits.pop(0)
-                if not (action.bitmask & self.interesting_bits):
-                    break
-        self.interesting_bits |= action.bitmask
-        if action.bitmask & self.BYTECODE_COUNTER_OVERFLOW_BIT:
-            assert action.bitmask == self.BYTECODE_COUNTER_OVERFLOW_BIT
-            self._periodic_actions.append(action)
-            self.has_bytecode_counter = True
-            self.force_tick_counter()
-        else:
-            self._nonperiodic_actions.append((action, action.bitmask))
-        self._rebuild_action_dispatcher()
-
-    def setcheckinterval(self, space, interval):
-        if interval < self.CHECK_INTERVAL_MIN:
-            interval = self.CHECK_INTERVAL_MIN
-        elif interval > self.CHECK_INTERVAL_MAX:
-            interval = self.CHECK_INTERVAL_MAX
-        space.sys.checkinterval = interval
-        self.force_tick_counter()
-
-    def force_tick_counter(self):
-        # force the tick counter to a valid value -- this actually forces
-        # it to reach BYTECODE_COUNTER_OVERFLOW_BIT at the next opcode.
-        ticker = self.get()
-        ticker &= ~ self.BYTECODE_COUNTER_OVERFLOW_BIT
-        ticker |= self.BYTECODE_COUNTER_MASK
-        self.set(ticker)
-
-    def _rebuild_action_dispatcher(self):
-        periodic_actions = unrolling_iterable(self._periodic_actions)
-        nonperiodic_actions = unrolling_iterable(self._nonperiodic_actions)
-        has_bytecode_counter = self.has_bytecode_counter
-
-        def action_dispatcher(ec, frame):
-            # periodic actions
-            if has_bytecode_counter:
-                ticker = self.get()
-                if ticker & self.BYTECODE_COUNTER_OVERFLOW_BIT:
-                    # We must run the periodic actions now, but first
-                    # reset the bytecode counter (the following line
-                    # works by assuming that we just overflowed the
-                    # counter, i.e. BYTECODE_COUNTER_OVERFLOW_BIT is
-                    # set but none of the BYTECODE_COUNTER_MASK bits
-                    # are).
-                    ticker -= ec.space.sys.checkinterval
-                    self.set(ticker)
-                    for action in periodic_actions:
-                        action.perform(ec, frame)
-
-            # nonperiodic actions
-            for action, bitmask in nonperiodic_actions:
-                ticker = self.get()
-                if ticker & bitmask:
-                    self.set(ticker & ~ bitmask)
-                    action.perform(ec, frame)
-
-        action_dispatcher._dont_inline_ = True
-        self.action_dispatcher = action_dispatcher
-
-    # Bits reserved for the bytecode counter, if used
-    BYTECODE_COUNTER_MASK = (1 << 20) - 1
-    BYTECODE_COUNTER_OVERFLOW_BIT = (1 << 20)
-
-    # Free bits
-    FREE_BITS = [1 << _b for _b in range(21, LONG_BIT-1)]
-
-    # The acceptable range of values for sys.checkinterval, so that
-    # the bytecode_counter fits in 20 bits
-    CHECK_INTERVAL_MIN = 1
-    CHECK_INTERVAL_MAX = BYTECODE_COUNTER_OVERFLOW_BIT
-
-
-class ActionFlag(AbstractActionFlag):
-    """The normal class for space.actionflag.  The signal module provides
-    a different one."""
-    _flags = 0
-
-    def get(self):
-        return self._flags
-
-    def set(self, value):
-        self._flags = value
-
-
-class AsyncAction(object):
-    """Abstract base class for actions that must be performed
-    asynchronously with regular bytecode execution, but that still need
-    to occur between two opcodes, not at a completely random time.
-    """
-    bitmask = 0      # means 'please choose one bit automatically'
-
-    def __init__(self, space):
-        self.space = space
-
-    def fire(self):
-        """Request for the action to be run before the next opcode.
-        The action must have been registered at space initalization time."""
-        self.space.actionflag.fire(self)
-
-    def fire_after_thread_switch(self):
-        """Bit of a hack: fire() the action but only the next time the GIL
-        is released and re-acquired (i.e. after a portential thread switch).
-        Don't call this if threads are not enabled.
-        """
-        from pypy.module.thread.gil import spacestate
-        spacestate.set_actionflag_bit_after_thread_switch |= self.bitmask
-
-    def perform(self, executioncontext, frame):
-        """To be overridden."""
-
-
-class PeriodicAsyncAction(AsyncAction):
-    """Abstract base class for actions that occur automatically
-    every sys.checkinterval bytecodes.
-    """
-    bitmask = ActionFlag.BYTECODE_COUNTER_OVERFLOW_BIT
-
-
-class UserDelAction(AsyncAction):
-    """An action that invokes all pending app-level __del__() method.
-    This is done as an action instead of immediately when the
-    interp-level __del__() is invoked, because the latter can occur more
-    or less anywhere in the middle of code that might not be happy with
-    random app-level code mutating data structures under its feet.
-    """
-
-    def __init__(self, space):
-        AsyncAction.__init__(self, space)
-        self.dying_objects_w = []
-        self.finalizers_lock_count = 0
-
-    def register_dying_object(self, w_obj):
-        self.dying_objects_w.append(w_obj)
-        self.fire()
-
-    def perform(self, executioncontext, frame):
-        if self.finalizers_lock_count > 0:
-            return
-        # Each call to perform() first grabs the self.dying_objects_w
-        # and replaces it with an empty list.  We do this to try to
-        # avoid too deep recursions of the kind of __del__ being called
-        # while in the middle of another __del__ call.
-        pending_w = self.dying_objects_w
-        self.dying_objects_w = []
-        space = self.space
-        for w_obj in pending_w:
-            try:
-                space.userdel(w_obj)
-            except OperationError, e:
-                e.write_unraisable(space, 'method __del__ of ', w_obj)
-                e.clear(space)   # break up reference cycles
-            # finally, this calls the interp-level destructor for the
-            # cases where there is both an app-level and a built-in __del__.
-            w_obj._call_builtin_destructor()
-
-
-class FrameTraceAction(AsyncAction):
-    """An action that calls the local trace functions (w_f_trace)."""
-
-    def perform(self, executioncontext, frame):
-        if frame.w_f_trace is None or executioncontext.is_tracing:
-            return
-        code = frame.pycode
-        if frame.instr_lb <= frame.last_instr < frame.instr_ub:
-            if frame.last_instr <= frame.instr_prev:
-                # We jumped backwards in the same line.
-                executioncontext._trace(frame, 'line', self.space.w_None)
-        else:
-            size = len(code.co_lnotab) / 2
-            addr = 0
-            line = code.co_firstlineno
-            p = 0
-            lineno = code.co_lnotab
-            while size > 0:
-                c = ord(lineno[p])
-                if (addr + c) > frame.last_instr:
-                    break
-                addr += c
-                if c:
-                    frame.instr_lb = addr
-
-                line += ord(lineno[p + 1])
-                p += 2
-                size -= 1
-
-            if size > 0:
-                while True:
-                    size -= 1
-                    if size < 0:
-                        break
-                    addr += ord(lineno[p])
-                    if ord(lineno[p + 1]):
-                        break
-                    p += 2
-                frame.instr_ub = addr
-            else:
-                frame.instr_ub = sys.maxint
-
-            if frame.instr_lb == frame.last_instr: # At start of line!
-                frame.f_lineno = line
-                executioncontext._trace(frame, 'line', self.space.w_None)
-
-        frame.instr_prev = frame.last_instr
-        self.space.frame_trace_action.fire()     # continue tracing

Modified: pypy/branch/avm/pypy/interpreter/interactive.py
==============================================================================
--- pypy/branch/avm/pypy/interpreter/interactive.py	(original)
+++ pypy/branch/avm/pypy/interpreter/interactive.py	Thu Nov  5 20:27:32 2009
@@ -1,229 +1,72 @@
-from pypy.interpreter import error
-from pypy.interpreter import baseobjspace, module, main
+import autopath
+
+from pypy.interpreter import executioncontext, pyframe, baseobjspace
 import sys
 import code
-import time
-
-
-class Completer:
-    """ Stolen mostly from CPython's rlcompleter.py """
-    def __init__(self, space, w_globals):
-        self.space = space
-        self.w_globals = w_globals
-
-    def complete(self, text, state):
-        if state == 0:
-            if "." in text:
-                self.matches = self.attr_matches(text)
-            else:
-                self.matches = self.global_matches(text)
-        try:
-            return self.matches[state]
-
-        except IndexError:
-            return None
-
-    def global_matches(self, text):
-        import keyword
-        w_res = self.space.call_method(self.w_globals, "keys")
-        namespace_keys = self.space.unwrap(w_res)
-        w_res = self.space.call_method(self.space.builtin.getdict(), "keys")
-        builtin_keys = self.space.unwrap(w_res)
-        
-        matches = []
-        n = len(text)
-
-        for l in [namespace_keys, builtin_keys, keyword.kwlist]:
-            for word in l:
-                if word[:n] == text and word != "__builtins__":
-                    matches.append(word)
-
-        return matches
-
-    def attr_matches(self, text):
-        import re
-        m = re.match(r"(\w+(\.\w+)*)\.(\w*)", text)
-        if not m:
-            return
-
-        expr, attr = m.group(1, 3)
-        s = self.space
-        w_obj = s.eval(expr, self.w_globals, self.w_globals)
-        words = self.get_words(w_obj)
-
-        w_clz = s.getattr(w_obj, s.wrap("__class__"))
-        words += self.get_class_members(w_clz)
-
-        matches = []
-        n = len(attr)
-        for word in words:
-            if word[:n] == attr and word != "__builtins__":
-                matches.append("%s.%s" % (expr, word))
-
-        return matches
-
-    def get_words(self, w_clz):
-        s = self.space
-        w_dir_func = s.builtin.get("dir")
-        w_res = s.call_function(w_dir_func, w_clz)
-        return s.unwrap(w_res)
-
-    def get_class_members(self, w_clz):
-        s = self.space
-        words = self.get_words(w_clz)
-        try:                
-            w_bases = s.getattr(w_clz, s.wrap("__bases__"))             
-            bases_w = s.viewiterable(w_bases)
-
-        except error.OperationError:
-            return words
+import linecache
 
-        for w_clz in bases_w:
-            words += self.get_class_members(w_clz)
-
-        return words
 
 class PyPyConsole(code.InteractiveConsole):
-    def __init__(self, objspace, verbose=0, completer=False):
+    def __init__(self, objspace):
         code.InteractiveConsole.__init__(self)
         self.space = objspace
-        self.verbose = verbose
-        space = self.space
-        self.console_compiler_flags = 0
-
-        mainmodule = main.ensure__main__(space)
-        self.w_globals = mainmodule.w_dict
-        space.setitem(self.w_globals, space.wrap('__builtins__'), space.builtin)
-        if completer:
-            self.enable_command_line_completer()
-
-        # forbidden:
-        #space.exec_("__pytrace__ = 0", self.w_globals, self.w_globals)
-        space.setitem(self.w_globals, space.wrap('__pytrace__'),space.wrap(0))
-        self.tracelevel = 0
-        self.console_locals = {}
-
-    def enable_command_line_completer(self):
-        try:
-            import readline
-            # Keep here to save windoze tears
-            readline.set_completer(Completer(self.space, self.w_globals).complete)
-            readline.parse_and_bind("tab: complete")
-            readline.set_history_length(25000)
-
-            try:
-                readline.read_history_file()
-            except IOError:
-                pass # guess it doesn't exit 
-
-            import atexit
-            atexit.register(readline.write_history_file)
-        except:
-            pass
+        self.ec = executioncontext.ExecutionContext(self.space)
+        self.w_globals = self.ec.make_standard_w_globals()
+        self.space.setitem(self.w_globals,
+                           self.space.wrap("__name__"),
+                           self.space.wrap("__main__"))
 
     def interact(self, banner=None):
-        #banner = "Python %s in pypy\n%s / %s" % (
-        #    sys.version, self.__class__.__name__,
-        #    self.space.__class__.__name__)
-        w_sys = self.space.sys
-        major, minor, micro, _, _ = self.space.unwrap(self.space.sys.get('pypy_version_info'))
-        elapsed = time.time() - self.space._starttime
-        banner = "PyPy %d.%d.%d in %r on top of Python %s (startuptime: %.2f secs)" % (
-            major, minor, micro, self.space, sys.version.split()[0], elapsed)
+        if banner is None:
+            banner = "Python %s in pypy\n%s / %s" % (
+                sys.version, self.__class__.__name__,
+                self.space.__class__.__name__)
         code.InteractiveConsole.interact(self, banner)
 
     def raw_input(self, prompt=""):
         # add a character to the PyPy prompt so that you know where you
         # are when you debug it with "python -i py.py"
-        try:
-            return code.InteractiveConsole.raw_input(self, prompt[0] + prompt)
-        except KeyboardInterrupt:
-            # fires into an interpreter-level console
-            print
-            banner = ("Python %s on %s\n" % (sys.version, sys.platform) +
-                      "*** Entering interpreter-level console ***")
-            local = self.console_locals
-            # don't copy attributes that look like names that came
-            # from self.w_globals (itself the main offender) as they
-            # would then get copied back into the applevel namespace.
-            local.update(dict([(k,v) for (k, v) in self.__dict__.iteritems()
-                               if not k.startswith('w_')]))
-            del local['locals']
-            for w_name in self.space.unpackiterable(self.w_globals):
-                local['w_' + self.space.str_w(w_name)] = (
-                    self.space.getitem(self.w_globals, w_name))
-            code.interact(banner=banner, local=local)
-            # copy back 'w_' names
-            for name in local:
-                if name.startswith('w_'):
-                    self.space.setitem(self.w_globals,
-                                       self.space.wrap(name[2:]),
-                                       local[name])
-            print '*** Leaving interpreter-level console ***'
-            raise
+        return code.InteractiveConsole.raw_input(self, prompt[0] + prompt)
 
     def runcode(self, code):
-        raise NotImplementedError
-
-    def runsource(self, source, ignored_filename="<input>", symbol="single"):
-        # the following hacked file name is recognized specially by error.py
-        hacked_filename = '<inline>\n' + source
-        compiler = self.space.getexecutioncontext().compiler
-
-        # CPython 2.6 turns console input into unicode
-        if isinstance(source, unicode):
-            source = source.encode(sys.stdin.encoding)
-
-        def doit():
-            # compile the provided input
-            code = compiler.compile_command(source, hacked_filename, symbol,
-                                            self.console_compiler_flags)
-            if code is None:
-                raise IncompleteInput
-            self.console_compiler_flags |= compiler.getcodeflags(code)
-
-            # execute it
-            self.settrace()
+        # 'code' is a CPython code object
+        from pypy.interpreter.pycode import PyCode
+        pycode = PyCode()._from_code(code)
+        try:
+            pycode.exec_code(self.space, self.w_globals, self.w_globals)
+        except baseobjspace.OperationError, operationerr:
+            # XXX insert exception info into the application-level sys.last_xxx
+            operationerr.print_detailed_traceback(self.space)
+        else:
             try:
-                code.exec_code(self.space, self.w_globals, self.w_globals)
-            finally:
-                if self.tracelevel:
-                    self.space.unsettrace()
-            self.checktrace()
+                if sys.stdout.softspace:
+                    print
+            except AttributeError:
+                # Don't crash if user defined stdout doesn't have softspace
+                pass
 
-        # run doit() in an exception-catching box
+    def runsource(self, source, ignored_filename="<input>", symbol="single"):
+        hacked_filename = '<inline>\n'+source
         try:
-            main.run_toplevel(self.space, doit, verbose=self.verbose)
-        except IncompleteInput:
-            return 1
-        else:
+            code = self.compile(source, hacked_filename, symbol)
+        except (OverflowError, SyntaxError, ValueError):
+            self.showsyntaxerror(self.filename)
             return 0
+        if code is None:
+            return 1
+        self.runcode(code)
+        return 0
 
-    def settrace(self):
-        if self.tracelevel:
-            self.space.settrace()
-
-    def checktrace(self):
-        from pypy.objspace import trace
-
-        s = self.space
-
-        # Did we modify __pytrace__
-        tracelevel = s.int_w(s.getitem(self.w_globals,
-                                       s.wrap("__pytrace__")))
-
-        if self.tracelevel > 0 and tracelevel == 0:
-            s.reset_trace()
-            print "Tracing disabled"
-            
-        if self.tracelevel == 0 and tracelevel > 0:
-            trace.create_trace_space(s)
-            self.space.unsettrace()
-            print "Tracing enabled"
-                        
-        self.tracelevel = tracelevel
-
-
-class IncompleteInput(Exception):
-    pass
-
+if __name__ == '__main__':
+    try:
+        import readline
+    except ImportError:
+        pass
+
+    from pypy.tool import option
+    from pypy.tool import testit
+    args = option.process_options(option.get_standard_options(),
+                                  option.Options)
+    objspace = option.objspace()
+    con = PyPyConsole(objspace)
+    con.interact()

Modified: pypy/branch/avm/pypy/interpreter/pyframe.py
==============================================================================
--- pypy/branch/avm/pypy/interpreter/pyframe.py	(original)
+++ pypy/branch/avm/pypy/interpreter/pyframe.py	Thu Nov  5 20:27:32 2009
@@ -1,604 +1,299 @@
 """ PyFrame class implementation with the interpreter main loop.
 """
 
-from pypy.tool.pairtype import extendabletype
-from pypy.interpreter import eval, baseobjspace, pycode
-from pypy.interpreter.argument import Arguments, ArgumentsFromValuestack
+from pypy.interpreter import eval, baseobjspace, gateway
+from pypy.interpreter.miscutils import Stack
 from pypy.interpreter.error import OperationError
 from pypy.interpreter import pytraceback
-import opcode
-from pypy.rlib.objectmodel import we_are_translated, instantiate
-from pypy.rlib.jit import we_are_jitted, hint
-from pypy.rlib.debug import make_sure_not_resized
-
-# Define some opcodes used
-g = globals()
-for op in '''DUP_TOP POP_TOP SETUP_LOOP SETUP_EXCEPT SETUP_FINALLY
-POP_BLOCK END_FINALLY'''.split():
-    g[op] = opcode.opmap[op]
-HAVE_ARGUMENT = opcode.HAVE_ARGUMENT
 
-class PyFrame(eval.Frame):
+
+class PyFrame(eval.Frame, baseobjspace.Wrappable):
     """Represents a frame for a regular Python function
     that needs to be interpreted.
 
-    See also pyopcode.PyStandardFrame and nestedscope.PyNestedScopeFrame.
+    See also pyopcode.PyStandardFrame and pynestedscope.PyNestedScopeFrame.
 
     Public fields:
      * 'space' is the object space this frame is running in
      * 'code' is the PyCode object this frame runs
      * 'w_locals' is the locals dictionary to use
      * 'w_globals' is the attached globals dictionary
-     * 'builtin' is the attached built-in module
-     * 'valuestack_w', 'blockstack', control the interpretation
+     * 'w_builtins' is the attached built-ins dictionary
+     * 'valuestack', 'blockstack', 'next_instr' control the interpretation
     """
 
-    __metaclass__ = extendabletype
-
-    frame_finished_execution = False
-    last_instr               = -1
-    last_exception           = None
-    f_back                   = None
-    w_f_trace                = None
-    # For tracing
-    instr_lb                 = 0
-    instr_ub                 = -1
-    instr_prev               = -1
-    is_being_profiled        = False
-
     def __init__(self, space, code, w_globals, closure):
-        #self = hint(self, access_directly=True)
-        assert isinstance(code, pycode.PyCode)
-        self.pycode = code
-        eval.Frame.__init__(self, space, w_globals, code.co_nlocals)
-        self.valuestack_w = [None] * code.co_stacksize
-        self.valuestackdepth = 0
-        self.blockstack = []
-        if space.config.objspace.honor__builtins__:
-            self.builtin = space.builtin.pick_builtin(w_globals)
+        eval.Frame.__init__(self, space, code, w_globals, code.co_nlocals)
+        self.valuestack = Stack()
+        self.blockstack = Stack()
+        self.last_exception = None
+        self.next_instr = 0
+        self.w_builtins = self.space.w_builtins
         # regular functions always have CO_OPTIMIZED and CO_NEWLOCALS.
         # class bodies only have CO_NEWLOCALS.
-        self.initialize_frame_scopes(closure)
-        self.fastlocals_w = [None]*self.numlocals
-        make_sure_not_resized(self.fastlocals_w)
-        self.f_lineno = self.pycode.co_firstlineno
-
-    def get_builtin(self):
-        if self.space.config.objspace.honor__builtins__:
-            return self.builtin
-        else:
-            return self.space.builtin
-        
-    def initialize_frame_scopes(self, closure): 
-        # regular functions always have CO_OPTIMIZED and CO_NEWLOCALS.
-        # class bodies only have CO_NEWLOCALS.
-        # CO_NEWLOCALS: make a locals dict unless optimized is also set
-        # CO_OPTIMIZED: no locals dict needed at all
-        # NB: this method is overridden in nestedscope.py
-        flags = self.pycode.co_flags
-        if flags & pycode.CO_OPTIMIZED: 
-            return 
-        if flags & pycode.CO_NEWLOCALS:
-            self.w_locals = self.space.newdict()
-        else:
-            assert self.w_globals is not None
-            self.w_locals = self.w_globals
-
-    def run(self):
-        """Start this frame's execution."""
-        if self.pycode.co_flags & pycode.CO_GENERATOR:
-            from pypy.interpreter.generator import GeneratorIterator
-            return self.space.wrap(GeneratorIterator(self))
-        else:
-            return self.execute_frame()
-
-    def execute_generator_frame(self, w_inputvalue, ex=False):
-        # opcode semantic change in CPython 2.5: we must pass an input value
-        # when resuming a generator, which goes into the value stack.
-        # It's not working because the value of magic must be changed in PyCode
-        if self.pycode.magic >= 0xa0df294 and self.last_instr != -1 and not ex:
-            self.pushvalue(w_inputvalue)
-        return self.execute_frame()
-
-    def execute_frame(self):
-        """Execute this frame.  Main entry point to the interpreter."""
-        from pypy.rlib import rstack
-        # the following 'assert' is an annotation hint: it hides from
-        # the annotator all methods that are defined in PyFrame but
-        # overridden in the FrameClass subclass of PyFrame.
-        assert isinstance(self, self.space.FrameClass)
-        executioncontext = self.space.getexecutioncontext()
-        executioncontext.enter(self)
-        try:
-            executioncontext.call_trace(self)
-            # Execution starts just after the last_instr.  Initially,
-            # last_instr is -1.  After a generator suspends it points to
-            # the YIELD_VALUE instruction.
-            next_instr = self.last_instr + 1
-            try:
-                w_exitvalue = self.dispatch(self.pycode, next_instr,
-                                            executioncontext)
-                rstack.resume_point("execute_frame", self, executioncontext,
-                                    returns=w_exitvalue)
-            except Exception:
-                executioncontext.return_trace(self, self.space.w_None)
-                raise
-            executioncontext.return_trace(self, w_exitvalue)
-            # on exit, we try to release self.last_exception -- breaks an
-            # obvious reference cycle, so it helps refcounting implementations
-            self.last_exception = None
-        finally:
-            executioncontext.leave(self)
-        return w_exitvalue
-    execute_frame.insert_stack_check_here = True
-
-    # stack manipulation helpers
-    def pushvalue(self, w_object):
-        depth = self.valuestackdepth
-        self.valuestack_w[depth] = w_object
-        self.valuestackdepth = depth + 1
-
-    def popvalue(self):
-        depth = self.valuestackdepth - 1
-        assert depth >= 0, "pop from empty value stack"
-        w_object = self.valuestack_w[depth]
-        self.valuestack_w[depth] = None
-        self.valuestackdepth = depth
-        return w_object
-
-    def popstrdictvalues(self, n):
-        dic_w = {}
-        while True:
-            n -= 1
-            if n < 0:
-                break
-            w_value = self.popvalue()
-            w_key   = self.popvalue()
-            key = self.space.str_w(w_key)
-            dic_w[key] = w_value
-        return dic_w
-
-    # we need two popvalues that return different data types:
-    # one in case we want list another in case of tuple
-    def _new_popvalues():
-        def popvalues(self, n):
-            values_w = [None] * n
-            while True:
-                n -= 1
-                if n < 0:
-                    break
-                values_w[n] = self.popvalue()
-            return values_w
-        return popvalues
-    popvalues = _new_popvalues()
-    popvalues_mutable = _new_popvalues()
-    del _new_popvalues
-
-    def peekvalues(self, n):
-        values_w = [None] * n
-        base = self.valuestackdepth - n
-        assert base >= 0
-        while True:
-            n -= 1
-            if n < 0:
-                break
-            values_w[n] = self.valuestack_w[base+n]
-        return values_w
-
-    def dropvalues(self, n):
-        finaldepth = self.valuestackdepth - n
-        assert finaldepth >= 0, "stack underflow in dropvalues()"        
-        while True:
-            n -= 1
-            if n < 0:
-                break
-            self.valuestack_w[finaldepth+n] = None
-        self.valuestackdepth = finaldepth
-
-    def pushrevvalues(self, n, values_w): # n should be len(values_w)
-        while True:
-            n -= 1
-            if n < 0:
-                break
-            self.pushvalue(values_w[n])
-
-    def dupvalues(self, n):
-        delta = n-1
-        while True:
-            n -= 1
-            if n < 0:
-                break
-            w_value = self.peekvalue(delta)
-            self.pushvalue(w_value)
-        
-    def peekvalue(self, index_from_top=0):
-        index = self.valuestackdepth + ~index_from_top
-        assert index >= 0, "peek past the bottom of the stack"
-        return self.valuestack_w[index]
-
-    def settopvalue(self, w_object, index_from_top=0):
-        index = self.valuestackdepth + ~index_from_top
-        assert index >= 0, "settop past the bottom of the stack"
-        self.valuestack_w[index] = w_object
-
-    def dropvaluesuntil(self, finaldepth):
-        depth = self.valuestackdepth - 1
-        while depth >= finaldepth:
-            self.valuestack_w[depth] = None
-            depth -= 1
-        self.valuestackdepth = finaldepth
-
-    def savevaluestack(self):
-        return self.valuestack_w[:self.valuestackdepth]
-
-    def restorevaluestack(self, items_w):
-        assert None not in items_w
-        self.valuestack_w[:len(items_w)] = items_w
-        self.dropvaluesuntil(len(items_w))
-
-    def make_arguments(self, nargs):
-        if we_are_jitted():
-            return Arguments(self.space, self.peekvalues(nargs))
-        else:
-            return ArgumentsFromValuestack(self.space, self, nargs)
-            
-    def descr__reduce__(self, space):
-        from pypy.interpreter.mixedmodule import MixedModule
-        from pypy.module._pickle_support import maker # helper fns
-        w_mod    = space.getbuiltinmodule('_pickle_support')
-        mod      = space.interp_w(MixedModule, w_mod)
-        new_inst = mod.get('frame_new')
-        w        = space.wrap
-        nt = space.newtuple
-
-        cells = self._getcells()
-        if cells is None:
-            w_cells = space.w_None
-        else:
-            w_cells = space.newlist([space.wrap(cell) for cell in cells])
-
-        if self.w_f_trace is None:
-            f_lineno = self.get_last_lineno()
-        else:
-            f_lineno = self.f_lineno
-
-        values_w = self.valuestack_w[0:self.valuestackdepth]
-        w_valuestack = maker.slp_into_tuple_with_nulls(space, values_w)
-        
-        w_blockstack = nt([block._get_state_(space) for block in self.blockstack])
-        w_fastlocals = maker.slp_into_tuple_with_nulls(space, self.fastlocals_w)
-        if self.last_exception is None:
-            w_exc_value = space.w_None
-            w_tb = space.w_None
-        else:
-            w_exc_value = self.last_exception.w_value
-            w_tb = w(self.last_exception.application_traceback)
-        
-        tup_state = [
-            w(self.f_back),
-            w(self.get_builtin()),
-            w(self.pycode),
-            w_valuestack,
-            w_blockstack,
-            w_exc_value, # last_exception
-            w_tb,        #
-            self.w_globals,
-            w(self.last_instr),
-            w(self.frame_finished_execution),
-            w(f_lineno),
-            w_fastlocals,
-            space.w_None,           #XXX placeholder for f_locals
-            
-            #f_restricted requires no additional data!
-            space.w_None, ## self.w_f_trace,  ignore for now
+        if code.dictscope_needed():
+            self.w_locals = space.newdict([])  # set to None by Frame.__init__
 
-            w(self.instr_lb), #do we need these three (that are for tracing)
-            w(self.instr_ub),
-            w(self.instr_prev),
-            w_cells,
-            ]
-
-        return nt([new_inst, nt([]), nt(tup_state)])
-
-    def descr__setstate__(self, space, w_args):
-        from pypy.module._pickle_support import maker # helper fns
-        from pypy.interpreter.pycode import PyCode
-        from pypy.interpreter.module import Module
-        args_w = space.unpackiterable(w_args)
-        w_f_back, w_builtin, w_pycode, w_valuestack, w_blockstack, w_exc_value, w_tb,\
-            w_globals, w_last_instr, w_finished, w_f_lineno, w_fastlocals, w_f_locals, \
-            w_f_trace, w_instr_lb, w_instr_ub, w_instr_prev, w_cells = args_w
-
-        new_frame = self
-        pycode = space.interp_w(PyCode, w_pycode)
-
-        if space.is_w(w_cells, space.w_None):
-            closure = None
-            cellvars = []
-        else:
-            from pypy.interpreter.nestedscope import Cell
-            cells_w = space.unpackiterable(w_cells)
-            cells = [space.interp_w(Cell, w_cell) for w_cell in cells_w]
-            ncellvars = len(pycode.co_cellvars)
-            cellvars = cells[:ncellvars]
-            closure = cells[ncellvars:]
-        
-        # do not use the instance's __init__ but the base's, because we set
-        # everything like cells from here
-        PyFrame.__init__(self, space, pycode, w_globals, closure)
-        new_frame.f_back = space.interp_w(PyFrame, w_f_back, can_be_None=True)
-        new_frame.builtin = space.interp_w(Module, w_builtin)
-        new_frame.blockstack = [unpickle_block(space, w_blk)
-                                for w_blk in space.unpackiterable(w_blockstack)]
-        values_w = maker.slp_from_tuple_with_nulls(space, w_valuestack)
-        for w_value in values_w:
-            new_frame.pushvalue(w_value)
-        if space.is_w(w_exc_value, space.w_None):
-            new_frame.last_exception = None
-        else:
-            from pypy.interpreter.pytraceback import PyTraceback
-            tb = space.interp_w(PyTraceback, w_tb)
-            new_frame.last_exception = OperationError(space.type(w_exc_value),
-                                                      w_exc_value, tb
-                                                      )
-        new_frame.last_instr = space.int_w(w_last_instr)
-        new_frame.frame_finished_execution = space.is_true(w_finished)
-        new_frame.f_lineno = space.int_w(w_f_lineno)
-        new_frame.fastlocals_w = maker.slp_from_tuple_with_nulls(space, w_fastlocals)
-
-        if space.is_w(w_f_trace, space.w_None):
-            new_frame.w_f_trace = None
-        else:
-            new_frame.w_f_trace = w_f_trace
-
-        new_frame.instr_lb = space.int_w(w_instr_lb)   #the three for tracing
-        new_frame.instr_ub = space.int_w(w_instr_ub)
-        new_frame.instr_prev = space.int_w(w_instr_prev)
-
-        self._setcellvars(cellvars)
-        space.frame_trace_action.fire()
-
-    def hide(self):
-        return self.pycode.hidden_applevel
-
-    def getcode(self):
-        return hint(self.pycode, promote=True)
-
-    def getfastscope(self):
-        "Get the fast locals as a list."
-        return self.fastlocals_w
-
-    def setfastscope(self, scope_w):
-        """Initialize the fast locals from a list of values,
-        where the order is according to self.pycode.signature()."""
-        scope_len = len(scope_w)
-        if scope_len > len(self.fastlocals_w):
-            raise ValueError, "new fastscope is longer than the allocated area"
-        self.fastlocals_w[:scope_len] = scope_w
-        self.init_cells()
-
-    def init_cells(self):
-        """Initialize cellvars from self.fastlocals_w
-        This is overridden in nestedscope.py"""
-        pass
-    
     def getclosure(self):
         return None
 
-    def _getcells(self):
-        return None
-
-    def _setcellvars(self, cellvars):
-        pass
-
-    ### line numbers ###
-
-    # for f*_f_* unwrapping through unwrap_spec in typedef.py
-
-    def fget_f_lineno(space, self): 
-        "Returns the line number of the instruction currently being executed."
-        if self.w_f_trace is None:
-            return space.wrap(self.get_last_lineno())
-        else:
-            return space.wrap(self.f_lineno)
-
-    def fset_f_lineno(space, self, w_new_lineno):
-        "Returns the line number of the instruction currently being executed."
+    def eval(self, executioncontext):
+        "Interpreter main loop!"
         try:
-            new_lineno = space.int_w(w_new_lineno)
-        except OperationError, e:
-            raise OperationError(space.w_ValueError,
-                                 space.wrap("lineno must be an integer"))
+            while True:
+                try:
+                    executioncontext.bytecode_trace(self)
+                    last_instr = self.next_instr
+                    try:
+                        # fetch and dispatch the next opcode
+                        # dispatch() is abstract, see pyopcode.
+                        self.dispatch()
+                    except OperationError, e:
+                        pytraceback.record_application_traceback(
+                            self.space, e, self, last_instr)
+                        # convert an OperationError into a control flow
+                        # exception
+                        import sys
+                        tb = sys.exc_info()[2]
+                        raise SApplicationException(e, tb)
+                    # XXX some other exceptions could be caught here too,
+                    #     like KeyboardInterrupt
+
+                except ControlFlowException, ctlflowexc:
+                    # we have a reason to change the control flow
+                    # (typically unroll the stack)
+                    ctlflowexc.action(self, last_instr, executioncontext)
             
-        if self.w_f_trace is None:
-            raise OperationError(space.w_ValueError,
-                  space.wrap("f_lineo can only be set by a trace function."))
-
-        if new_lineno < self.pycode.co_firstlineno:
-            raise OperationError(space.w_ValueError,
-                  space.wrap("line %d comes before the current code." % new_lineno))
-        code = self.pycode.co_code
-        addr = 0
-        line = self.pycode.co_firstlineno
-        new_lasti = -1
-        offset = 0
-        lnotab = self.pycode.co_lnotab
-        for offset in xrange(0, len(lnotab), 2):
-            addr += ord(lnotab[offset])
-            line += ord(lnotab[offset + 1])
-            if line >= new_lineno:
-                new_lasti = addr
-                new_lineno = line
+        except ExitFrame, e:
+            # leave that frame
+            w_exitvalue = e.args[0]
+            return w_exitvalue
+
+    ### exception stack ###
+
+    def clean_exceptionstack(self):
+        # remove all exceptions that can no longer be re-raised
+        # because the current valuestack is no longer deep enough
+        # to hold the corresponding information
+        while self.exceptionstack:
+            ctlflowexc, valuestackdepth = self.exceptionstack.top()
+            if valuestackdepth <= self.valuestack.depth():
                 break
+            self.exceptionstack.pop()
+    
+    ### application level visible attributes ###
+    def app_visible(self):
+        def makedict(**kw): return kw
+        space = self.space
+        d = makedict(
+            f_code = space.wrap(self.code),
+            f_locals = self.getdictscope(),
+            f_globals = self.w_globals,
+            f_builtins = self.w_builtins,
+            # XXX f_lasti, f_back, f_exc*, f_restricted need to do pypy_getattr directly
+            )
+        return d.items() 
+
+### Frame Blocks ###
+
+class FrameBlock:
+
+    """Abstract base class for frame blocks from the blockstack,
+    used by the SETUP_XXX and POP_BLOCK opcodes."""
+
+    def __init__(self, frame, handlerposition):
+        self.handlerposition = handlerposition
+        self.valuestackdepth = frame.valuestack.depth()
+
+    def __eq__(self, other):
+        return (self.__class__ is other.__class__ and
+                self.handlerposition == other.handlerposition and
+                self.valuestackdepth == other.valuestackdepth)
+
+    def __ne__(self, other):
+        return not (self == other)
+
+    def __hash__(self):
+        return hash((self.handlerposition, self.valuestackdepth))
+
+    def cleanupstack(self, frame):
+        for i in range(self.valuestackdepth, frame.valuestack.depth()):
+            frame.valuestack.pop()
+
+    def cleanup(self, frame):
+        "Clean up a frame when we normally exit the block."
+        self.cleanupstack(frame)
+
+    def unroll(self, frame, unroller):
+        "Clean up a frame when we abnormally exit the block."
+        self.cleanupstack(frame)
+        return False  # continue to unroll
+
+
+class LoopBlock(FrameBlock):
+    """A loop block.  Stores the end-of-loop pointer in case of 'break'."""
+
+    def unroll(self, frame, unroller):
+        if isinstance(unroller, SContinueLoop):
+            # re-push the loop block without cleaning up the value stack,
+            # and jump to the beginning of the loop, stored in the
+            # exception's argument
+            frame.blockstack.push(self)
+            jump_to = unroller.args[0]
+            frame.next_instr = jump_to
+            return True  # stop unrolling
+        self.cleanupstack(frame)
+        if isinstance(unroller, SBreakLoop):
+            # jump to the end of the loop
+            frame.next_instr = self.handlerposition
+            return True  # stop unrolling
+        return False
+
+
+class ExceptBlock(FrameBlock):
+    """An try:except: block.  Stores the position of the exception handler."""
+
+    def unroll(self, frame, unroller):
+        self.cleanupstack(frame)
+        if isinstance(unroller, SApplicationException):
+            # push the exception to the value stack for inspection by the
+            # exception handler (the code after the except:)
+            operationerr = unroller.args[0]
+            w_type  = operationerr.w_type
+            w_value = operationerr.w_value
+            if frame.space.full_exceptions:
+                w_normalized = normalize_exception(frame.space, w_type, w_value)
+                w_type, w_value = frame.space.unpacktuple(w_normalized, 2)
+            # the stack setup is slightly different than in CPython:
+            # instead of the traceback, we store the unroller object,
+            # wrapped.
+            frame.valuestack.push(frame.space.wrap(unroller))
+            frame.valuestack.push(w_value)
+            frame.valuestack.push(w_type)
+            frame.next_instr = self.handlerposition   # jump to the handler
+            return True  # stop unrolling
+        return False
+
+def app_normalize_exception(etype, evalue):
+    # XXX should really be defined as a method on OperationError,
+    # but this is not so easy because OperationError cannot be
+    # at the same time an old-style subclass of Exception and a
+    # new-style subclass of Wrappable :-(
+    # moreover, try importing gateway from errors.py and you'll see :-(
+    
+    # mistakes here usually show up as infinite recursion, which is fun.
+    if isinstance(evalue, etype):
+        return etype, evalue
+    if isinstance(etype, type) and issubclass(etype, Exception):
+        if evalue is None:
+            evalue = ()
+        elif not isinstance(evalue, tuple):
+            evalue = (evalue,)
+        evalue = etype(*evalue)
+    else:
+        raise Exception, "?!"   # XXX
+    return etype, evalue
+normalize_exception = gateway.app2interp(app_normalize_exception)
+
+
+class FinallyBlock(FrameBlock):
+    """A try:finally: block.  Stores the position of the exception handler."""
+
+    def cleanup(self, frame):
+        # upon normal entry into the finally: part, the standard Python
+        # bytecode pushes a single None for END_FINALLY.  In our case we
+        # always push three values into the stack: the wrapped ctlflowexc,
+        # the exception value and the exception type (which are all None
+        # here).
+        self.cleanupstack(frame)
+        # one None already pushed by the bytecode
+        frame.valuestack.push(frame.space.w_None)
+        frame.valuestack.push(frame.space.w_None)
+
+    def unroll(self, frame, unroller):
+        # any abnormal reason for unrolling a finally: triggers the end of
+        # the block unrolling and the entering the finally: handler.
+        # see comments in cleanup().
+        self.cleanupstack(frame)
+        frame.valuestack.push(frame.space.wrap(unroller))
+        frame.valuestack.push(frame.space.w_None)
+        frame.valuestack.push(frame.space.w_None)
+        frame.next_instr = self.handlerposition   # jump to the handler
+        return True  # stop unrolling
+
+
+### Internal exceptions that change the control flow ###
+### and (typically) unroll the block stack           ###
+
+class ControlFlowException(Exception):
+    """Abstract base class for interpreter-level exceptions that
+    instruct the interpreter to change the control flow and the
+    block stack.
+
+    The concrete subclasses correspond to the various values WHY_XXX
+    values of the why_code enumeration in ceval.c:
+
+		WHY_NOT,	OK, not this one :-)
+		WHY_EXCEPTION,	SApplicationException
+		WHY_RERAISE,	we don't think this is needed
+		WHY_RETURN,	SReturnValue
+		WHY_BREAK,	SBreakLoop
+		WHY_CONTINUE,	SContinueLoop
+		WHY_YIELD	SYieldValue
 
-        if new_lasti == -1:
-            raise OperationError(space.w_ValueError,
-                  space.wrap("line %d comes after the current code." % new_lineno))
-
-        # Don't jump to a line with an except in it.
-        if ord(code[new_lasti]) in (DUP_TOP, POP_TOP):
-            raise OperationError(space.w_ValueError,
-                  space.wrap("can't jump to 'except' line as there's no exception"))
-            
-        # Don't jump into or out of a finally block.
-        f_lasti_setup_addr = -1
-        new_lasti_setup_addr = -1
-        blockstack = []
-        addr = 0
-        while addr < len(code):
-            op = ord(code[addr])
-            if op in (SETUP_LOOP, SETUP_EXCEPT, SETUP_FINALLY):
-                blockstack.append([addr, False])
-            elif op == POP_BLOCK:
-                setup_op = ord(code[blockstack[-1][0]])
-                if setup_op == SETUP_FINALLY:
-                    blockstack[-1][1] = True
-                else:
-                    blockstack.pop()
-            elif op == END_FINALLY:
-                if len(blockstack) > 0:
-                    setup_op = ord(code[blockstack[-1][0]])
-                    if setup_op == SETUP_FINALLY:
-                        blockstack.pop()
-
-            if addr == new_lasti or addr == self.last_instr:
-                for ii in range(len(blockstack)):
-                    setup_addr, in_finally = blockstack[~ii]
-                    if in_finally:
-                        if addr == new_lasti:
-                            new_lasti_setup_addr = setup_addr
-                        if addr == self.last_instr:
-                            f_lasti_setup_addr = setup_addr
-                        break
-                    
-            if op >= HAVE_ARGUMENT:
-                addr += 3
-            else:
-                addr += 1
-                
-        assert len(blockstack) == 0
-
-        if new_lasti_setup_addr != f_lasti_setup_addr:
-            raise OperationError(space.w_ValueError,
-                  space.wrap("can't jump into or out of a 'finally' block %d -> %d" %
-                             (f_lasti_setup_addr, new_lasti_setup_addr)))
-
-        if new_lasti < self.last_instr:
-            min_addr = new_lasti
-            max_addr = self.last_instr
-        else:
-            min_addr = self.last_instr
-            max_addr = new_lasti
-
-        delta_iblock = min_delta_iblock = 0
-        addr = min_addr
-        while addr < max_addr:
-            op = ord(code[addr])
-
-            if op in (SETUP_LOOP, SETUP_EXCEPT, SETUP_FINALLY):
-                delta_iblock += 1
-            elif op == POP_BLOCK:
-                delta_iblock -= 1
-                if delta_iblock < min_delta_iblock:
-                    min_delta_iblock = delta_iblock
-
-            if op >= opcode.HAVE_ARGUMENT:
-                addr += 3
-            else:
-                addr += 1
-
-        f_iblock = len(self.blockstack)
-        min_iblock = f_iblock + min_delta_iblock
-        if new_lasti > self.last_instr:
-            new_iblock = f_iblock + delta_iblock
+    """
+    def action(self, frame, last_instr, executioncontext):
+        "Default unroller implementation."
+        while not frame.blockstack.empty():
+            block = frame.blockstack.pop()
+            if block.unroll(frame, self):
+                break
         else:
-            new_iblock = f_iblock - delta_iblock
+            self.emptystack(frame)
 
-        if new_iblock > min_iblock:
-            raise OperationError(space.w_ValueError,
-                                 space.wrap("can't jump into the middle of a block"))
-
-        while f_iblock > new_iblock:
-            block = self.blockstack.pop()
-            block.cleanup(self)
-            f_iblock -= 1
-            
-        self.f_lineno = new_lineno
-        self.last_instr = new_lasti
-            
-    def get_last_lineno(self):
-        "Returns the line number of the instruction currently being executed."
-        return pytraceback.offset2lineno(self.pycode, self.last_instr)
-
-    def fget_f_builtins(space, self):
-        return self.get_builtin().getdict()
-
-    def fget_f_back(space, self):
-        return self.space.wrap(self.f_back)
+    def emptystack(self, frame):
+        "Default behavior when the block stack is exhausted."
+        # could occur e.g. when a BREAK_LOOP is not actually within a loop
+        raise BytecodeCorruption, "block stack exhausted"
+
+class SApplicationException(ControlFlowException):
+    """Unroll the stack because of an application-level exception
+    (i.e. an OperationException)."""
+
+    def action(self, frame, last_instr, executioncontext):
+        e = self.args[0]
+        frame.last_exception = e
+        executioncontext.exception_trace(e)
+
+        ControlFlowException.action(self, frame,
+                                    last_instr, executioncontext)
+
+    def emptystack(self, frame):
+        # propagate the exception to the caller
+        if len(self.args) == 2:
+            operationerr, tb = self.args
+            raise operationerr.__class__, operationerr, tb
+        else:
+            operationerr = self.args[0]
+            raise operationerr
+
+class SBreakLoop(ControlFlowException):
+    """Signals a 'break' statement."""
+
+class SContinueLoop(ControlFlowException):
+    """Signals a 'continue' statement.
+    Argument is the bytecode position of the beginning of the loop."""
+
+class SReturnValue(ControlFlowException):
+    """Signals a 'return' statement.
+    Argument is the wrapped object to return."""
+    def emptystack(self, frame):
+        w_returnvalue = self.args[0]
+        raise ExitFrame(w_returnvalue)
+
+class ExitFrame(Exception):
+    """Signals the end of the frame execution.
+    The argument is the returned or yielded value, already wrapped."""
 
-    def fget_f_lasti(space, self):
-        return self.space.wrap(self.last_instr)
-
-    def fget_f_trace(space, self):
-        return self.w_f_trace
-
-    def fset_f_trace(space, self, w_trace):
-        if space.is_w(w_trace, space.w_None):
-            self.w_f_trace = None
-        else:
-            self.w_f_trace = w_trace
-            self.f_lineno = self.get_last_lineno()
-            space.frame_trace_action.fire()
-
-    def fdel_f_trace(space, self): 
-        self.w_f_trace = None 
-
-    def fget_f_exc_type(space, self):
-        if self.last_exception is not None:
-            f = self.f_back
-            while f is not None and f.last_exception is None:
-                f = f.f_back
-            if f is not None:
-                return f.last_exception.w_type
-        return space.w_None
-         
-    def fget_f_exc_value(space, self):
-        if self.last_exception is not None:
-            f = self.f_back
-            while f is not None and f.last_exception is None:
-                f = f.f_back
-            if f is not None:
-                return f.last_exception.w_value
-        return space.w_None
-
-    def fget_f_exc_traceback(space, self):
-        if self.last_exception is not None:
-            f = self.f_back
-            while f is not None and f.last_exception is None:
-                f = f.f_back
-            if f is not None:
-                return space.wrap(f.last_exception.application_traceback)
-        return space.w_None
-         
-    def fget_f_restricted(space, self):
-        if space.config.objspace.honor__builtins__:
-            return space.wrap(self.builtin is not space.builtin)
-        return space.w_False
-
-# ____________________________________________________________
-
-def get_block_class(opname):
-    # select the appropriate kind of block
-    from pypy.interpreter.pyopcode import block_classes
-    return block_classes[opname]
-
-def unpickle_block(space, w_tup):
-    w_opname, w_handlerposition, w_valuestackdepth = space.unpackiterable(w_tup)
-    opname = space.str_w(w_opname)
-    handlerposition = space.int_w(w_handlerposition)
-    valuestackdepth = space.int_w(w_valuestackdepth)
-    assert valuestackdepth >= 0
-    blk = instantiate(get_block_class(opname))
-    blk.handlerposition = handlerposition
-    blk.valuestackdepth = valuestackdepth
-    return blk
+class BytecodeCorruption(ValueError):
+    """Detected bytecode corruption.  Never caught; it's an error."""

Modified: pypy/branch/avm/pypy/interpreter/test/test_interpreter.py
==============================================================================
--- pypy/branch/avm/pypy/interpreter/test/test_interpreter.py	(original)
+++ pypy/branch/avm/pypy/interpreter/test/test_interpreter.py	Thu Nov  5 20:27:32 2009
@@ -1,81 +1,75 @@
-import py 
-import sys
+import autopath
+from pypy.tool import testit
 
-class TestInterpreter: 
-    from pypy.interpreter.pycompiler import CPythonCompiler as CompilerClass
+class TestInterpreter(testit.TestCase):
 
     def codetest(self, source, functionname, args):
         """Compile and run the given code string, and then call its function
         named by 'functionname' with arguments 'args'."""
-        from pypy.interpreter import baseobjspace
+        from pypy.interpreter import baseobjspace, executioncontext
         from pypy.interpreter import pyframe, gateway, module
         space = self.space
 
-        source = str(py.code.Source(source).strip()) + '\n'
-
+        compile = space.builtin.compile
         w = space.wrap
-        w_code = space.builtin.call('compile', 
-                w(source), w('<string>'), w('exec'), w(0), w(0))
+        w_code = compile(w(source), w('<string>'), w('exec'), w(0), w(0))
+
+        ec = executioncontext.ExecutionContext(space)
 
         tempmodule = module.Module(space, w("__temp__"))
         w_glob = tempmodule.w_dict
-        space.setitem(w_glob, w("__builtins__"), space.builtin)
+        space.setitem(w_glob, w("__builtins__"), space.w_builtins)
 
         code = space.unwrap(w_code)
         code.exec_code(space, w_glob, w_glob)
 
-        wrappedargs = [w(a) for a in args]
+        wrappedargs = w(args)
         wrappedfunc = space.getitem(w_glob, w(functionname))
+        wrappedkwds = space.newdict([])
         try:
-            w_output = space.call_function(wrappedfunc, *wrappedargs)
+            w_output = space.call(wrappedfunc, wrappedargs, wrappedkwds)
         except baseobjspace.OperationError, e:
             #e.print_detailed_traceback(space)
             return '<<<%s>>>' % e.errorstr(space)
         else:
             return space.unwrap(w_output)
 
-    def setup_method(self, arg):
-        ec = self.space.getexecutioncontext() 
-        self.saved_compiler = ec.compiler
-        ec.compiler = self.CompilerClass(self.space)
-
-    def teardown_method(self, arg):
-        ec = self.space.getexecutioncontext() 
-        ec.compiler = self.saved_compiler
+    def setUp(self):
+        self.space = testit.objspace()
 
     def test_exception_trivial(self):
-        x = self.codetest('''\
-                def f():
-                    try:
-                        raise Exception()
-                    except Exception, e:
-                        return 1
-                    return 2
-            ''', 'f', [])
-        assert x == 1
+        x = self.codetest('''
+def f():
+    try:
+        raise Exception()
+    except Exception, e:
+        return 1
+    return 2
+''', 'f', [])
+        self.assertEquals(x, 1)
 
     def test_exception(self):
         x = self.codetest('''
-            def f():
-                try:
-                    raise Exception, 1
-                except Exception, e:
-                    return e.args[0]
-            ''', 'f', [])
-        assert x == 1
+def f():
+    try:
+        raise Exception, 1
+    except Exception, e:
+        return e.args[0]
+''', 'f', [])
+        self.assertEquals(x, 1)
 
     def test_finally(self):
         code = '''
-            def f(a):
-                try:
-                    if a:
-                        raise Exception
-                    a = -12
-                finally:
-                    return a
-        '''
-        assert self.codetest(code, 'f', [0]) == -12
-        assert self.codetest(code, 'f', [1]) == 1
+def f(a):
+    try:
+        if a:
+            raise Exception
+        a = -12
+    finally:
+        return a
+'''
+        self.assertEquals(self.codetest(code, 'f', [0]), -12)
+        self.assertEquals(self.codetest(code, 'f', [1]), 1)
 
 ##     def test_raise(self):
 ##         x = self.codetest('''
@@ -86,206 +80,137 @@
 
     def test_except2(self):
         x = self.codetest('''
-            def f():
-                try:
-                    z = 0
-                    try:
-                        "x"+1
-                    except TypeError, e:
-                        z = 5
-                        raise e
-                except TypeError:
-                    return z
-            ''', 'f', [])
-        assert x == 5
+def f():
+    try:
+        z = 0
+        try:
+            "x"+1
+        except TypeError, e:
+            z = 5
+            raise e
+    except TypeError:
+        return z
+''', 'f', [])
+        self.assertEquals(x, 5)
 
     def test_except3(self):
         code = '''
-                def f(v):
-                    z = 0
-                    try:
-                        z = 1//v
-                    except ZeroDivisionError, e:
-                        z = "infinite result"
-                    return z
-                '''
-        assert self.codetest(code, 'f', [2]) == 0
-        assert self.codetest(code, 'f', [0]) == "infinite result"
+def f(v):
+    z = 0
+    try:
+        z = 1//v
+    except ZeroDivisionError, e:
+        z = "infinite result"
+    return z
+'''
+        self.assertEquals(self.codetest(code, 'f', [2]), 0)
+        self.assertEquals(self.codetest(code, 'f', [0]), "infinite result")
         ess = "TypeError: unsupported operand type"
         res = self.codetest(code, 'f', ['x'])
-        assert res.find(ess) >= 0
+        self.failUnless(res.find(ess) >= 0)
         # the following (original) test was a bit too strict...:
         # self.assertEquals(self.codetest(code, 'f', ['x']), "<<<TypeError: unsupported operand type(s) for //: 'int' and 'str'>>>")
 
     def test_break(self):
         code = '''
-                def f(n):
-                    total = 0
-                    for i in range(n):
-                        try:
-                            if i == 4:
-                                break
-                        finally:
-                            total += i
-                    return total
-                '''
-        assert self.codetest(code, 'f', [4]) == 1+2+3
-        assert self.codetest(code, 'f', [9]) == 1+2+3+4
+def f(n):
+    total = 0
+    for i in range(n):
+        try:
+            if i == 4:
+                break
+        finally:
+            total += i
+    return total
+'''
+        self.assertEquals(self.codetest(code, 'f', [4]), 1+2+3)
+        self.assertEquals(self.codetest(code, 'f', [9]), 1+2+3+4)
 
     def test_continue(self):
         code = '''
-                def f(n):
-                    total = 0
-                    for i in range(n):
-                        try:
-                            if i == 4:
-                                continue
-                        finally:
-                            total += 100
-                        total += i
-                    return total
-                '''
-        assert self.codetest(code, 'f', [4]) == 1+2+3+400
-        assert self.codetest(code, 'f', [9]) == (
+def f(n):
+    total = 0
+    for i in range(n):
+        try:
+            if i == 4:
+                continue
+        finally:
+            total += 100
+        total += i
+    return total
+'''
+        self.assertEquals(self.codetest(code, 'f', [4]), 1+2+3+400)
+        self.assertEquals(self.codetest(code, 'f', [9]),
                           1+2+3 + 5+6+7+8+900)
 
-    def test_import(self):
-        # Regression test for a bug in PyFrame.IMPORT_NAME: when an
-        # import statement was executed in a function without a locals dict, a
-        # plain unwrapped None could be passed into space.call_function causing
-        # assertion errors later on.
-        real_call_function = self.space.call_function
-        def safe_call_function(w_obj, *arg_w):
-            for arg in arg_w:
-                assert arg is not None
-            return real_call_function(w_obj, *arg_w)
-        self.space.call_function = safe_call_function
-        code = '''
-            def f():
-                import sys
-            '''
-        self.codetest(code, 'f', [])
-
-    def test_extended_arg(self):
-        longexpr = 'x = x or ' + '-x' * 2500
-        code = '''
-                def f(x):
-                    %s
-                    %s
-                    %s
-                    %s
-                    %s
-                    %s
-                    %s
-                    %s
-                    %s
-                    %s
-                    while x:
-                        x -= 1   # EXTENDED_ARG is for the JUMP_ABSOLUTE at the end of the loop
-                    return x
-                ''' % ((longexpr,)*10)
-        assert self.codetest(code, 'f', [3]) == 0
-
-    def test_call_star_starstar(self):
-        code = '''\
-            def f1(n):
-                return n*2
-            def f38(n):
-                f = f1
-                r = [
-                    f(n, *[]),
-                    f(n),
-                    apply(f, (n,)),
-                    apply(f, [n]),
-                    f(*(n,)),
-                    f(*[n]),
-                    f(n=n),
-                    f(**{'n': n}),
-                    apply(f, (n,), {}),
-                    apply(f, [n], {}),
-                    f(*(n,), **{}),
-                    f(*[n], **{}),
-                    f(n, **{}),
-                    f(n, *[], **{}),
-                    f(n=n, **{}),
-                    f(n=n, *[], **{}),
-                    f(*(n,), **{}),
-                    f(*[n], **{}),
-                    f(*[], **{'n':n}),
-                    ]
-                return r
-            '''
-        assert self.codetest(code, 'f38', [117]) == [234]*19
-
-    def test_star_arg(self):
-        code = ''' 
-            def f(x, *y):
-                return y
-            def g(u, v):
-                return f(u, *v)
-            '''
-        assert self.codetest(code, 'g', [12, ()]) ==    ()
-        assert self.codetest(code, 'g', [12, (3,4)]) == (3,4)
-        assert self.codetest(code, 'g', [12, []]) ==    ()
-        assert self.codetest(code, 'g', [12, [3,4]]) == (3,4)
-        assert self.codetest(code, 'g', [12, {}]) ==    ()
-        assert self.codetest(code, 'g', [12, {3:1}]) == (3,)
-
-    def test_closure(self):
-        code = '''
-            def f(x, y):
-                def g(u, v):
-                    return u - v + 7*x
-                return g
-            def callme(x, u, v):
-                return f(x, 123)(u, v)
-            '''
-        assert self.codetest(code, 'callme', [1, 2, 3]) == 6
+class AppTestInterpreter(testit.AppTestCase):
+    def test_exception(self):
+        try:
+            raise Exception, 1
+        except Exception, e:
+            self.assertEquals(e.args[0], 1)
 
-    def test_list_comprehension(self):
-        code = '''
-            def f():
-                return [dir() for i in [1]][0]
-        '''
-        assert self.codetest(code, 'f', [])[0] == '_[1]'
-
-    def test_import_statement(self):
-        for x in range(10):
-            import os
-        code = '''
-            def f():
-                for x in range(10):
-                    import os
-                return os.name
-            '''
-        assert self.codetest(code, 'f', []) == os.name
+    def test_trivial(self):
+        x = 42
+        self.assertEquals(x, 42)
 
+    def test_raise(self):
+        def f():
+            raise Exception
+        self.assertRaises(Exception, f)
 
-class TestPyPyInterpreter(TestInterpreter):
-    """Runs the previous test with the pypy parser"""
-    from pypy.interpreter.pycompiler import PythonAstCompiler as CompilerClass
+    def test_exception(self):
+        try:
+            raise Exception
+            self.fail("exception failed to raise")
+        except:
+            pass
+        else:
+            self.fail("exception executing else clause!")
 
-    def test_extended_arg(self):
-        py.test.skip("expression too large for the recursive parser")
+    def test_raise2(self):
+        def f(r):
+            try:
+                raise r
+            except LookupError:
+                return 1
+        self.assertRaises(Exception, f, Exception)
+        self.assertEquals(f(IndexError), 1)
 
+    def test_raise3(self):
+        try:
+            raise 1
+        except TypeError:
+            pass
+        else:
+            self.fail("shouldn't be able to raise 1")
 
-class AppTestInterpreter: 
-    def test_trivial(self):
-        x = 42
-        assert x == 42
+    def test_raise_three_args(self):
+        import sys
+        try:
+            raise ValueError
+        except:
+            exc_type,exc_val,exc_tb = sys.exc_info()
+        try:
+            raise exc_type,exc_val,exc_tb
+        except:
+            exc_type2,exc_val2,exc_tb2 = sys.exc_info()
+        self.assertEquals(exc_type,exc_type2)
+        self.assertEquals(exc_val,exc_val2)
+        self.assertEquals(exc_tb,exc_tb2)
 
     def test_trivial_call(self):
         def f(): return 42
-        assert f() == 42
+        self.assertEquals(f(), 42)
 
     def test_trivial_call2(self):
         def f(): return 1 + 1
-        assert f() == 2
+        self.assertEquals(f(), 2)
 
     def test_print(self):
         import sys
         save = sys.stdout 
-        class Out(object):
+        class Out:
             def __init__(self):
                 self.args = []
             def write(self, *args):
@@ -294,10 +219,14 @@
         try:
             sys.stdout = out
             print 10
-            assert out.args == ['10','\n']
+            self.assertEquals(out.args, ['10','\n'])
         finally:
             sys.stdout = save
 
     def test_identity(self):
         def f(x): return x
-        assert f(666) == 666
+        self.assertEquals(f(666), 666)
+
+
+if __name__ == '__main__':
+    testit.main()

Modified: pypy/branch/avm/pypy/objspace/std/intobject.py
==============================================================================
--- pypy/branch/avm/pypy/objspace/std/intobject.py	(original)
+++ pypy/branch/avm/pypy/objspace/std/intobject.py	Thu Nov  5 20:27:32 2009
@@ -1,153 +1,194 @@
 from pypy.objspace.std.objspace import *
-from pypy.objspace.std.noneobject import W_NoneObject
-from pypy.rlib.rarithmetic import ovfcheck, ovfcheck_lshift, LONG_BIT, r_uint
-from pypy.rlib.rbigint import rbigint
-from pypy.objspace.std.inttype import wrapint
+from inttype import W_IntType
+from noneobject import W_NoneObject
+from restricted_int import r_int, LONG_BIT
 
 """
-In order to have the same behavior running
-on CPython, and after RPython translation we use ovfcheck
-from rarithmetic to explicitly check for overflows,
-something CPython does not do anymore.
+The implementation of integers is a bit difficult,
+since integers are currently undergoing the change to turn
+themselves into longs under overflow circumstances.
+The restricted Python does not overflow or throws
+exceptions.
+The definitions in this file are fine, given that
+restricted Python integers behave that way.
+But for testing, the resticted stuff must be run
+by CPython which has different behavior.
+For that reason, I defined an r_int extension class
+for native integers, which tries to behave as in
+RPython, just for test purposes.
 """
 
 class W_IntObject(W_Object):
-    __slots__ = 'intval'
-
-    _immutable_ = True
-    
-    from pypy.objspace.std.inttype import int_typedef as typedef
+    statictype = W_IntType
     
-    def __init__(w_self, intval):
-        w_self.intval = intval
+    def __init__(w_self, space, intval):
+        W_Object.__init__(w_self, space)
+        w_self.intval = r_int(intval)
 
     def __repr__(w_self):
         """ representation for debugging purposes """
         return "%s(%d)" % (w_self.__class__.__name__, w_self.intval)
 
-    def unwrap(w_self, space):
-        return int(w_self.intval)
-
 
 registerimplementation(W_IntObject)
 
 
-def int_w__Int(space, w_int1):
-    return int(w_int1.intval)
-
-def uint_w__Int(space, w_int1):
-    intval = w_int1.intval
-    if intval < 0:
-        raise OperationError(space.w_ValueError,
-                             space.wrap("cannot convert negative integer to unsigned"))
-    else:
-        return r_uint(intval)
+"""
+XXX not implemented:
+free list
+FromString
+FromUnicode
+print
+"""
 
-def bigint_w__Int(space, w_int1):
-    return rbigint.fromint(w_int1.intval)
+def unwrap__Int(space, w_int1):
+    return int(w_int1.intval)
 
 def repr__Int(space, w_int1):
     a = w_int1.intval
-    res = str(a)
+    res = "%ld" % a
     return space.wrap(res)
 
 str__Int = repr__Int
 
-def declare_new_int_comparison(opname):
-    import operator
-    from pypy.tool.sourcetools import func_with_new_name
-    op = getattr(operator, opname)
-    def f(space, w_int1, w_int2):
-        i = w_int1.intval
-        j = w_int2.intval
-        return space.newbool(op(i, j))
-    name = opname + "__Int_Int"
-    return func_with_new_name(f, name), name
-
-for op in ['lt', 'le', 'eq', 'ne', 'gt', 'ge']:
-    func, name = declare_new_int_comparison(op)
-    globals()[name] = func
+## deprecated
+## we are going to support rich compare, only
 
-def hash__Int(space, w_int1):
-    # unlike CPython, we don't special-case the value -1 in most of our
-    # hash functions, so there is not much sense special-casing it here either.
-    # Make sure this is consistent with the hash of floats and longs.
-    return int__Int(space, w_int1)
-
-# coerce
-def coerce__Int_Int(space, w_int1, w_int2):
-    return space.newtuple([w_int1, w_int2])
+##def int_int_cmp(space, w_int1, w_int2):
+##    i = w_int1.intval
+##    j = w_int2.intval
+##    if i < j:
+##        ret = -1
+##    elif i > j:
+##        ret = 1
+##    else:
+##        ret = 0
+##    return W_IntObject(space, ret)
+##
+##StdObjSpace.cmp.register(int_int_cmp, W_IntObject, W_IntObject)
+
+def lt__Int_Int(space, w_int1, w_int2):
+    i = w_int1.intval
+    j = w_int2.intval
+    return space.newbool( i < j )
+
+def le__Int_Int(space, w_int1, w_int2):
+    i = w_int1.intval
+    j = w_int2.intval
+    return space.newbool( i <= j )
+
+def eq__Int_Int(space, w_int1, w_int2):
+    i = w_int1.intval
+    j = w_int2.intval
+    return space.newbool( i == j )
+
+def ne__Int_Int(space, w_int1, w_int2):
+    i = w_int1.intval
+    j = w_int2.intval
+    return space.newbool( i != j )
+
+def gt__Int_Int(space, w_int1, w_int2):
+    i = w_int1.intval
+    j = w_int2.intval
+    return space.newbool( i > j )
+
+def ge__Int_Int(space, w_int1, w_int2):
+    i = w_int1.intval
+    j = w_int2.intval
+    return space.newbool( i >= j )
+
+STRICT_HASH = True # temporary, to be put elsewhere or removed
+
+def _hash_strict(space, w_int1):
+    #/* XXX If this is changed, you also need to change the way
+    #   Python's long, float and complex types are hashed. */
+    x = w_int1.intval
+    if x == -1:
+        x = -2
+    return W_IntObject(space, x)
+
+def _hash_liberal(space, w_int1):
+    # Armin: unlike CPython we have no need to special-case the value -1
+    return w_int1
+
+# Chris: I'm not yet convinced that we want to make hash()
+# return different values that CPython does.
+# So for the moment, both versions are here,
+# and we might think of some config options
+# or decide to drop compatibility (using pypy-dev).
 
+def hash__Int(space, w_int1):
+    if STRICT_HASH:
+        return _hash_strict(space, w_int1)
+    else:
+        return _hash_liberal(space, w_int1)
 
 def add__Int_Int(space, w_int1, w_int2):
     x = w_int1.intval
     y = w_int2.intval
     try:
-        z = ovfcheck(x + y)
+        z = x + y
     except OverflowError:
         raise FailedToImplement(space.w_OverflowError,
                                 space.wrap("integer addition"))
-    return wrapint(space, z)
+    return W_IntObject(space, z)
 
 def sub__Int_Int(space, w_int1, w_int2):
     x = w_int1.intval
     y = w_int2.intval
     try:
-        z = ovfcheck(x - y)
+        z = x - y
     except OverflowError:
         raise FailedToImplement(space.w_OverflowError,
                                 space.wrap("integer substraction"))
-    return wrapint(space, z)
+    return W_IntObject(space, z)
 
 def mul__Int_Int(space, w_int1, w_int2):
     x = w_int1.intval
     y = w_int2.intval
     try:
-        z = ovfcheck(x * y)
+        z = x * y
     except OverflowError:
         raise FailedToImplement(space.w_OverflowError,
                                 space.wrap("integer multiplication"))
-    return wrapint(space, z)
+    return W_IntObject(space, z)
 
-def floordiv__Int_Int(space, w_int1, w_int2):
+def _floordiv(space, w_int1, w_int2):
     x = w_int1.intval
     y = w_int2.intval
     try:
-        z = ovfcheck(x // y)
+        z = x // y
     except ZeroDivisionError:
         raise OperationError(space.w_ZeroDivisionError,
                              space.wrap("integer division by zero"))
     except OverflowError:
         raise FailedToImplement(space.w_OverflowError,
                                 space.wrap("integer division"))
-    return wrapint(space, z)
-div__Int_Int = floordiv__Int_Int
+    return W_IntObject(space, z)
 
-def truediv__Int_Int(space, w_int1, w_int2):
-    x = float(w_int1.intval)
-    y = float(w_int2.intval)
-    if y == 0.0:
-        raise FailedToImplement(space.w_ZeroDivisionError, space.wrap("float division"))    
-    return space.wrap(x / y)
+def _truediv(space, w_int1, w_int2):
+    # cannot implement, since it gives floats
+    raise FailedToImplement(space.w_OverflowError,
+                            space.wrap("integer division"))
 
 def mod__Int_Int(space, w_int1, w_int2):
     x = w_int1.intval
     y = w_int2.intval
     try:
-        z = ovfcheck(x % y)
+        z = x % y
     except ZeroDivisionError:
         raise OperationError(space.w_ZeroDivisionError,
                              space.wrap("integer modulo by zero"))
     except OverflowError:
         raise FailedToImplement(space.w_OverflowError,
                                 space.wrap("integer modulo"))
-    return wrapint(space, z)
+    return W_IntObject(space, z)
 
 def divmod__Int_Int(space, w_int1, w_int2):
     x = w_int1.intval
     y = w_int2.intval
     try:
-        z = ovfcheck(x // y)
+        z = x // y
     except ZeroDivisionError:
         raise OperationError(space.w_ZeroDivisionError,
                              space.wrap("integer divmod by zero"))
@@ -156,30 +197,41 @@
                                 space.wrap("integer modulo"))
     # no overflow possible
     m = x % y
-    w = space.wrap
-    return space.newtuple([w(z), w(m)])
+    return space.wrap((z,m))
+
+def div__Int_Int(space, w_int1, w_int2):
+    # Select the proper div
+    if 1 / 2 == 1 // 2:
+        return _floordiv(space, w_int1, w_int2)
+    else:
+        return _truediv(space, w_int1, w_int2)
 
+floordiv__Int_Int = _floordiv
 
 # helper for pow()
-def _impl_int_int_pow(space, iv, iw, iz=0):
+def _impl_int_int_pow(space, iv, iw, iz=None):
     if iw < 0:
-        if iz != 0:
+        if iz is not None:
             raise OperationError(space.w_TypeError,
                              space.wrap("pow() 2nd argument "
                  "cannot be negative when 3rd argument specified"))
         ## bounce it, since it always returns float
         raise FailedToImplement(space.w_ValueError,
                                 space.wrap("integer exponentiation"))
+    if iz is not None:
+        if iz == 0:
+            raise OperationError(space.w_ValueError,
+                                    space.wrap("pow() 3rd argument cannot be 0"))
     temp = iv
     ix = 1
     try:
         while iw > 0:
             if iw & 1:
-                ix = ovfcheck(ix*temp)
+                ix = ix*temp
             iw >>= 1   #/* Shift exponent down by 1 bit */
             if iw==0:
                 break
-            temp = ovfcheck(temp*temp) #/* Square the value of temp */
+            temp *= temp   #/* Square the value of temp */
             if iz:
                 #/* If we did a multiplication, perform a modulo */
                 ix = ix % iz;
@@ -189,31 +241,48 @@
     except OverflowError:
         raise FailedToImplement(space.w_OverflowError,
                                 space.wrap("integer exponentiation"))
-    return wrapint(space, ix)
+    return ix
 
+"""
 def pow__Int_Int_Int(space, w_int1, w_int2, w_int3):
     x = w_int1.intval
     y = w_int2.intval
     z = w_int3.intval
-    if z == 0:
-        raise OperationError(space.w_ValueError,
-                             space.wrap("pow() 3rd argument cannot be 0"))
-    return _impl_int_int_pow(space, x, y, z)
+    ret = _impl_int_int_pow(space, x, y, z)
+    return W_IntObject(space, ret)
+"""
+
+def pow__Int_Int_Int(space, w_int1, w_int2, w_int3):
+    x = w_int1.intval
+    y = w_int2.intval
+    z = w_int3.intval
+    ret = _impl_int_int_pow(space, x, y, z)
+    return W_IntObject(space, ret)
 
 def pow__Int_Int_None(space, w_int1, w_int2, w_int3):
     x = w_int1.intval
     y = w_int2.intval
-    return _impl_int_int_pow(space, x, y)
+    ret = _impl_int_int_pow(space, x, y)
+    return W_IntObject(space, ret)
 
 def neg__Int(space, w_int1):
     a = w_int1.intval
     try:
-        x = ovfcheck(-a)
+        x = -a
     except OverflowError:
         raise FailedToImplement(space.w_OverflowError,
                                 space.wrap("integer negation"))
-    return wrapint(space, x)
+    return W_IntObject(space, x)
 
+# pos__Int is supposed to do nothing, unless it has
+# a derived integer object, where it should return
+# an exact one.
+def pos__Int(space, w_int1):
+    #not sure if this should be done this way:
+    if w_int1.__class__ is W_IntObject:
+        return w_int1
+    a = w_int1.intval
+    return W_IntObject(space, a)
 
 def abs__Int(space, w_int1):
     if w_int1.intval >= 0:
@@ -221,13 +290,14 @@
     else:
         return neg__Int(space, w_int1)
 
-def nonzero__Int(space, w_int1):
-    return space.newbool(w_int1.intval != 0)
+def is_true__Int(space, w_int1):
+    ''' note: this must return an UNWRAPPED bool!!! '''
+    return w_int1.intval != 0
 
 def invert__Int(space, w_int1):
     x = w_int1.intval
     a = ~x
-    return wrapint(space, a)
+    return W_IntObject(space, a)
 
 def lshift__Int_Int(space, w_int1, w_int2):
     a = w_int1.intval
@@ -236,16 +306,25 @@
         raise OperationError(space.w_ValueError,
                              space.wrap("negative shift count"))
     if a == 0 or b == 0:
-        return int__Int(space, w_int1)
+        return Int_pos(w_int1)
     if b >= LONG_BIT:
         raise FailedToImplement(space.w_OverflowError,
                                 space.wrap("integer left shift"))
+    ##
+    ## XXX please! have a look into pyport.h and see how to implement
+    ## the overflow checking, using macro Py_ARITHMETIC_RIGHT_SHIFT
+    ## we *assume* that the overflow checking is done correctly
+    ## in the code generator, which is not trivial!
     try:
-        c = ovfcheck_lshift(a, b)
+        c = a << b
+        ## the test in C code is
+        ## if (a != Py_ARITHMETIC_RIGHT_SHIFT(long, c, b)) {
+        ##     if (PyErr_Warn(PyExc_FutureWarning,
+        # and so on
     except OverflowError:
         raise FailedToImplement(space.w_OverflowError,
                                 space.wrap("integer left shift"))
-    return wrapint(space, c)
+    return W_IntObject(space, c)
 
 def rshift__Int_Int(space, w_int1, w_int2):
     a = w_int1.intval
@@ -254,46 +333,59 @@
         raise OperationError(space.w_ValueError,
                              space.wrap("negative shift count"))
     if a == 0 or b == 0:
-        return int__Int(space, w_int1)
+        return Int_pos(w_int1)
     if b >= LONG_BIT:
         if a < 0:
             a = -1
         else:
             a = 0
     else:
+        ## please look into pyport.h, how >> should be implemented!
+        ## a = Py_ARITHMETIC_RIGHT_SHIFT(long, a, b);
         a = a >> b
-    return wrapint(space, a)
+    return W_IntObject(space, a)
 
 def and__Int_Int(space, w_int1, w_int2):
     a = w_int1.intval
     b = w_int2.intval
     res = a & b
-    return wrapint(space, res)
+    return W_IntObject(space, res)
 
 def xor__Int_Int(space, w_int1, w_int2):
     a = w_int1.intval
     b = w_int2.intval
     res = a ^ b
-    return wrapint(space, res)
+    return W_IntObject(space, res)
 
 def or__Int_Int(space, w_int1, w_int2):
     a = w_int1.intval
     b = w_int2.intval
     res = a | b
-    return wrapint(space, res)
+    return W_IntObject(space, res)
+
+# coerce is not wanted
+##
+##static int
+##coerce__Int(PyObject **pv, PyObject **pw)
+##{
+##    if (PyInt_Check(*pw)) {
+##        Py_INCREF(*pv);
+##        Py_INCREF(*pw);
+##        return 0;
+##    }
+##    return 1; /* Can't do it */
+##}
 
-# int__Int is supposed to do nothing, unless it has
-# a derived integer object, where it should return
-# an exact one.
 def int__Int(space, w_int1):
-    if space.is_w(space.type(w_int1), space.w_int):
-        return w_int1
-    a = w_int1.intval
-    return wrapint(space, a)
-pos__Int = int__Int
+    return w_int1
 
-def index__Int(space, w_int1):
-    return int__Int(space, w_int1)
+"""
+# Not registered
+def long__Int(space, w_int1):
+    a = w_int1.intval
+    x = long(a)  ## XXX should this really be done so?
+    return space.newlong(x)
+"""
 
 def float__Int(space, w_int1):
     a = w_int1.intval
@@ -301,13 +393,33 @@
     return space.newfloat(x)
 
 def oct__Int(space, w_int1):
-    return space.wrap(oct(w_int1.intval))
+    x = w_int1.intval
+    if x < 0:
+        ## XXX what about this warning?
+        #if (PyErr_Warn(PyExc_FutureWarning,
+        #           "hex()/oct() of negative int will return "
+        #           "a signed string in Python 2.4 and up") < 0)
+        #    return NULL;
+        pass
+    if x == 0:
+        ret = "0"
+    else:
+        ret = "0%lo" % x
+    return space.wrap(ret)
 
 def hex__Int(space, w_int1):
-    return space.wrap(hex(w_int1.intval))
-
-def getnewargs__Int(space, w_int1):
-    return space.newtuple([wrapint(space, w_int1.intval)])
-
+    x = w_int1.intval
+    if x < 0:
+        ## XXX what about this warning?
+        #if (PyErr_Warn(PyExc_FutureWarning,
+        #           "hex()/oct() of negative int will return "
+        #           "a signed string in Python 2.4 and up") < 0)
+        #    return NULL;
+        pass
+    if x == 0:
+        ret = "0"
+    else:
+        ret = "0x%lx" % x
+    return space.wrap(ret)
 
 register_all(vars())

Modified: pypy/branch/avm/pypy/objspace/std/listobject.py
==============================================================================
--- pypy/branch/avm/pypy/objspace/std/listobject.py	(original)
+++ pypy/branch/avm/pypy/objspace/std/listobject.py	Thu Nov  5 20:27:32 2009
@@ -1,531 +1,536 @@
 from pypy.objspace.std.objspace import *
-from pypy.objspace.std.inttype import wrapint
-from pypy.objspace.std.listtype import get_list_index
-from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice
-
-from pypy.objspace.std import slicetype
-from pypy.interpreter import gateway, baseobjspace
-from pypy.rlib.listsort import TimSort
+from listtype import W_ListType
+from intobject import W_IntObject
+from sliceobject import W_SliceObject
+from tupleobject import W_TupleObject
+
+import slicetype
+from pypy.interpreter import gateway
+from restricted_int import r_int, r_uint
+
 
 class W_ListObject(W_Object):
-    from pypy.objspace.std.listtype import list_typedef as typedef
-    
-    def __init__(w_self, wrappeditems):
-        w_self.wrappeditems = wrappeditems
+    statictype = W_ListType
+
+    def __init__(w_self, space, wrappeditems):
+        W_Object.__init__(w_self, space)
+        w_self.ob_item = []
+        w_self.ob_size = 0
+        newlen = len(wrappeditems)
+        _list_resize(w_self, newlen)
+        w_self.ob_size = newlen
+        items = w_self.ob_item
+        p = newlen
+        while p:
+            p -= 1
+            items[p] = wrappeditems[p]
 
     def __repr__(w_self):
         """ representation for debugging purposes """
-        return "%s(%s)" % (w_self.__class__.__name__, w_self.wrappeditems)
+        reprlist = [repr(w_item) for w_item in w_self.ob_item[:w_self.ob_size]]
+        return "%s(%s)" % (w_self.__class__.__name__, ', '.join(reprlist))
 
-    def unwrap(w_list, space):
-        items = [space.unwrap(w_item) for w_item in w_list.wrappeditems]# XXX generic mixed types unwrap
-        return list(items)
-
-    def append(w_list, w_item):
-        w_list.wrappeditems.append(w_item)
 
 registerimplementation(W_ListObject)
 
 
-EMPTY_LIST = W_ListObject([])
-
-def init__List(space, w_list, __args__):
-    w_iterable, = __args__.parse('list',
-                               (['sequence'], None, None),   # signature
-                               [EMPTY_LIST])                 # default argument
-    #
-    # this is the old version of the loop at the end of this function:
-    #
-    #   w_list.wrappeditems = space.unpackiterable(w_iterable)
-    #
-    # This is commented out to avoid assigning a new RPython list to
-    # 'wrappeditems', which defeats the W_FastSeqIterObject optimization.
-    #
-    items_w = w_list.wrappeditems
-    del items_w[:]
-    if w_iterable is not EMPTY_LIST:
+def unwrap__List(space, w_list):
+    items = [space.unwrap(w_item) for w_item in w_list.ob_item[:w_list.ob_size]]
+    return list(items)
+
+def object_init__List(space, w_list, w_args, w_kwds):
+    if space.is_true(w_kwds):
+        raise OperationError(space.w_TypeError,
+                             space.wrap("no keyword arguments expected"))
+    w_list.ob_size = 0  # XXX think about it later
+    args = space.unpackiterable(w_args)
+    if len(args) == 0:
+        pass   # empty list
+    elif len(args) == 1:
+        w_iterable = args[0]
         w_iterator = space.iter(w_iterable)
         while True:
             try:
                 w_item = space.next(w_iterator)
-            except OperationError, e:
-                if not e.match(space, space.w_StopIteration):
-                    raise
+            except NoValue:
                 break  # done
-            items_w.append(w_item)
+            _ins1(w_list, w_list.ob_size, w_item)
+    else:
+        raise OperationError(space.w_TypeError,
+                             space.wrap("list() takes at most 1 argument"))
 
 def len__List(space, w_list):
-    result = len(w_list.wrappeditems)
-    return wrapint(space, result)
+    result = w_list.ob_size
+    return W_IntObject(space, result)
 
-def getitem__List_ANY(space, w_list, w_index):
-    try:
-        return w_list.wrappeditems[get_list_index(space, w_index)]
-    except IndexError:
+def getitem__List_Int(space, w_list, w_index):
+    items = w_list.ob_item
+    idx = w_index.intval
+    if idx < 0:
+        idx += w_list.ob_size
+    if idx < 0 or idx >= w_list.ob_size:
         raise OperationError(space.w_IndexError,
                              space.wrap("list index out of range"))
+    w_item = items[idx]
+    return w_item
 
 def getitem__List_Slice(space, w_list, w_slice):
-    # XXX consider to extend rlist's functionality?
-    length = len(w_list.wrappeditems)
-    start, stop, step, slicelength = w_slice.indices4(space, length)
+    items = w_list.ob_item
+    length = w_list.ob_size
+    start, stop, step, slicelength = slicetype.indices4(space, w_slice, length)
     assert slicelength >= 0
-    if step == 1 and 0 <= start <= stop:
-        return W_ListObject(w_list.wrappeditems[start:stop])
-    w_res = W_ListObject([None] * slicelength)
-    items_w = w_list.wrappeditems
-    subitems_w = w_res.wrappeditems
+    w_res = W_ListObject(space, [])
+    _list_resize(w_res, slicelength)
+    subitems = w_res.ob_item
     for i in range(slicelength):
-        subitems_w[i] = items_w[start]
+        subitems[i] = items[start]
         start += step
+    w_res.ob_size = slicelength
     return w_res
 
-def getslice__List_ANY_ANY(space, w_list, w_start, w_stop):
-    length = len(w_list.wrappeditems)
-    start, stop = normalize_simple_slice(space, length, w_start, w_stop)
-    return W_ListObject(w_list.wrappeditems[start:stop])
-
-def setslice__List_ANY_ANY_ANY(space, w_list, w_start, w_stop, w_sequence):
-    length = len(w_list.wrappeditems)
-    start, stop = normalize_simple_slice(space, length, w_start, w_stop)
-    _setitem_slice_helper(space, w_list, start, 1, stop-start, w_sequence)
-
-def delslice__List_ANY_ANY(space, w_list, w_start, w_stop):
-    length = len(w_list.wrappeditems)
-    start, stop = normalize_simple_slice(space, length, w_start, w_stop)
-    _delitem_slice_helper(space, w_list, start, 1, stop-start)
-
-def contains__List_ANY(space, w_list, w_obj):
-    # needs to be safe against eq_w() mutating the w_list behind our back
-    i = 0
-    items_w = w_list.wrappeditems
-    while i < len(items_w): # intentionally always calling len!
-        if space.eq_w(items_w[i], w_obj):
-            return space.w_True
-        i += 1
-    return space.w_False
-
 def iter__List(space, w_list):
-    from pypy.objspace.std import iterobject
-    return iterobject.W_FastListIterObject(w_list, w_list.wrappeditems)
+    import iterobject
+    return iterobject.W_SeqIterObject(space, w_list)
 
 def add__List_List(space, w_list1, w_list2):
-    return W_ListObject(w_list1.wrappeditems + w_list2.wrappeditems)
+    w_res = W_ListObject(space, [])
+    newlen = w_list1.ob_size + w_list2.ob_size
+    _list_resize(w_res, newlen)
+    p = 0
+    items = w_res.ob_item
+    src = w_list1.ob_item
+    for i in range(w_list1.ob_size):
+        items[p] = src[i]
+        p += 1
+    src = w_list2.ob_item
+    for i in range(w_list2.ob_size):
+        items[p] = src[i]
+        p += 1
+    w_res.ob_size = p
+    return w_res
 
+def mul__List_Int(space, w_list, w_int):
+    w_res = W_ListObject(space, [])
+    times = w_int.intval
+    src = w_list.ob_item
+    size = w_list.ob_size
+    newlen = size * times  # XXX check overflow
+    _list_resize(w_res, newlen)
+    items = w_res.ob_item
+    p = 0
+    for _ in range(times):
+        for i in range(size):
+            items[p] = src[i]
+            p += 1
+    w_res.ob_size = p
+    return w_res
 
-def inplace_add__List_ANY(space, w_list1, w_iterable2):
-    list_extend__List_ANY(space, w_list1, w_iterable2)
-    return w_list1
-
-def inplace_add__List_List(space, w_list1, w_list2):
-    list_extend__List_List(space, w_list1, w_list2)
-    return w_list1
-
-def mul_list_times(space, w_list, w_times):
-    try:
-        times = space.getindex_w(w_times, space.w_OverflowError)
-    except OperationError, e:
-        if e.match(space, space.w_TypeError):
-            raise FailedToImplement
-        raise
-    return W_ListObject(w_list.wrappeditems * times)
-
-def mul__List_ANY(space, w_list, w_times):
-    return mul_list_times(space, w_list, w_times)
-
-def mul__ANY_List(space, w_times, w_list):
-    return mul_list_times(space, w_list, w_times)
-
-def inplace_mul__List_ANY(space, w_list, w_times):
-    try:
-        times = space.getindex_w(w_times, space.w_OverflowError)
-    except OperationError, e:
-        if e.match(space, space.w_TypeError):
-            raise FailedToImplement
-        raise
-    w_list.wrappeditems *= times
-    return w_list
+def mul__Int_List(space, w_int, w_list):
+    return mul__List_Int(space, w_list, w_int)
 
 def eq__List_List(space, w_list1, w_list2):
-    # needs to be safe against eq_w() mutating the w_lists behind our back
-    items1_w = w_list1.wrappeditems
-    items2_w = w_list2.wrappeditems
-    return equal_wrappeditems(space, items1_w, items2_w)
-
-def equal_wrappeditems(space, items1_w, items2_w):
-    if len(items1_w) != len(items2_w):
+    items1 = w_list1.ob_item
+    items2 = w_list2.ob_item
+    if w_list1.ob_size != w_list2.ob_size:
         return space.w_False
-    i = 0
-    while i < len(items1_w) and i < len(items2_w):
-        if not space.eq_w(items1_w[i], items2_w[i]):
+    for i in range(w_list1.ob_size):
+        if not space.is_true(space.eq(items1[i], items2[i])):
             return space.w_False
-        i += 1
     return space.w_True
 
-def lessthan_unwrappeditems(space, items1_w, items2_w):
-    # needs to be safe against eq_w() mutating the w_lists behind our back
+def _min(a, b):
+    if a < b:
+        return a
+    return b
+
+def lt__List_List(space, w_list1, w_list2):
+    items1 = w_list1.ob_item
+    items2 = w_list2.ob_item
+    ncmp = _min(w_list1.ob_size, w_list2.ob_size)
     # Search for the first index where items are different
-    i = 0
-    while i < len(items1_w) and i < len(items2_w):
-        w_item1 = items1_w[i]
-        w_item2 = items2_w[i]
-        if not space.eq_w(w_item1, w_item2):
-            return space.lt(w_item1, w_item2)
-        i += 1
+    for p in range(ncmp):
+        if not space.is_true(space.eq(items1[p], items2[p])):
+            return space.lt(items1[p], items2[p])
     # No more items to compare -- compare sizes
-    return space.newbool(len(items1_w) < len(items2_w))
+    return space.newbool(w_list1.ob_size < w_list2.ob_size)
 
-def greaterthan_unwrappeditems(space, items1_w, items2_w):
-    # needs to be safe against eq_w() mutating the w_lists behind our back
+def gt__List_List(space, w_list1, w_list2):
+    items1 = w_list1.ob_item
+    items2 = w_list2.ob_item
+    ncmp = _min(w_list1.ob_size, w_list2.ob_size)
     # Search for the first index where items are different
-    i = 0
-    while i < len(items1_w) and i < len(items2_w):
-        w_item1 = items1_w[i]
-        w_item2 = items2_w[i]
-        if not space.eq_w(w_item1, w_item2):
-            return space.gt(w_item1, w_item2)
-        i += 1
+    for p in range(ncmp):
+        if not space.is_true(space.eq(items1[p], items2[p])):
+            return space.gt(items1[p], items2[p])
     # No more items to compare -- compare sizes
-    return space.newbool(len(items1_w) > len(items2_w))
-
-def lt__List_List(space, w_list1, w_list2):
-    return lessthan_unwrappeditems(space, w_list1.wrappeditems,
-        w_list2.wrappeditems)
+    return space.newbool(w_list1.ob_size > w_list2.ob_size)
 
-def gt__List_List(space, w_list1, w_list2):
-    return greaterthan_unwrappeditems(space, w_list1.wrappeditems,
-        w_list2.wrappeditems)
+# upto here, lists are nearly identical to tuples, despite the
+# fact that we now support over-allocation!
 
-def delitem__List_ANY(space, w_list, w_idx):
-    idx = get_list_index(space, w_idx)
-    try:
-        del w_list.wrappeditems[idx]
-    except IndexError:
+def delitem__List_Int(space, w_list, w_idx):
+    i = w_idx.intval
+    if i < 0:
+        i += w_list.ob_size
+    if i < 0 or i >= w_list.ob_size:
         raise OperationError(space.w_IndexError,
                              space.wrap("list deletion index out of range"))
+    _del_slice(w_list, i, i+1)
     return space.w_None
 
-
 def delitem__List_Slice(space, w_list, w_slice):
-    start, stop, step, slicelength = w_slice.indices4(space,
-                                                      len(w_list.wrappeditems))
-    _delitem_slice_helper(space, w_list, start, step, slicelength)
-
-def _delitem_slice_helper(space, w_list, start, step, slicelength):
-    if slicelength==0:
-        return
-
-    if step < 0:
-        start = start + step * (slicelength-1)
-        step = -step
-        
+    start, stop, step, slicelength = slicetype.indices4(space, w_slice, w_list.ob_size)
     if step == 1:
-        assert start >= 0
-        assert slicelength >= 0
-        del w_list.wrappeditems[start:start+slicelength]
-    else:
-        items = w_list.wrappeditems
-        n = len(items)
-        i = start
-
-        for discard in range(1, slicelength):
-            j = i+1
-            i += step
-            while j < i:
-                items[j-discard] = items[j]
-                j += 1
-
-        j = i+1
-        while j < n:
-            items[j-slicelength] = items[j]
-            j += 1
-        start = n - slicelength
-        assert start >= 0 # annotator hint
-        del items[start:]
-
-def setitem__List_ANY_ANY(space, w_list, w_index, w_any):
-    idx = get_list_index(space, w_index)
-    try:
-        w_list.wrappeditems[idx] = w_any
-    except IndexError:
+        return _setitem_slice_helper(space, w_list, w_slice, [], 0)
+
+    # The current code starts from the top, to simplify
+    # coding.  A later optimization could be to start from
+    # the bottom, which would reduce the list motion.
+    # A further later optimization would be to special-case
+    # a step of -1, because this version will perform a LOT
+    # of extra motion for this case.  Anybody with a real-life
+    # use-case for this is welcome to write the special case.
+    r = range(start, stop, step)
+    if step > 0:
+        r.reverse()
+    for i in r:
+        _del_slice(w_list, i, i+1)
+    return space.w_None
+
+def setitem__List_Int_ANY(space, w_list, w_index, w_any):
+    items = w_list.ob_item
+    idx = w_index.intval
+    if idx < 0:
+        idx += w_list.ob_size
+    if idx < 0 or idx >= w_list.ob_size:
         raise OperationError(space.w_IndexError,
                              space.wrap("list index out of range"))
+    items[idx] = w_any
     return space.w_None
 
-def setitem__List_Slice_ANY(space, w_list, w_slice, w_iterable):
-    oldsize = len(w_list.wrappeditems)
-    start, stop, step, slicelength = w_slice.indices4(space, oldsize)
-    _setitem_slice_helper(space, w_list, start, step, slicelength, w_iterable)
-
-def _setitem_slice_helper(space, w_list, start, step, slicelength, w_iterable):
-    if isinstance(w_iterable, W_ListObject):
-        sequence2 = w_iterable.wrappeditems
-    else:
-        sequence2 = space.unpackiterable(w_iterable)
+def setitem__List_Slice_List(space, w_list, w_slice, w_list2):
+    return _setitem_slice_helper(space, w_list, w_slice, w_list2.ob_item, w_list2.ob_size)
+
+def setitem__List_Slice_Tuple(space, w_list, w_slice, w_tuple):
+    t = w_tuple.wrappeditems
+    return _setitem_slice_helper(space, w_list, w_slice, t, len(t))
 
+def _setitem_slice_helper(space, w_list, w_slice, sequence2, len2):
+    start, stop, step, slicelength = slicetype.indices4(space, w_slice, w_list.ob_size)
     assert slicelength >= 0
-    items = w_list.wrappeditems
-    oldsize = len(items)
-    len2 = len(sequence2)
+
     if step == 1:  # Support list resizing for non-extended slices
-        delta = slicelength - len2
-        if delta < 0:
-            delta = -delta
-            newsize = oldsize + delta
-            # XXX support this in rlist!
-            items += [None] * delta
-            lim = start+len2
-            i = newsize - 1
-            while i >= lim:
-                items[i] = items[i-delta]
-                i -= 1
-        elif start >= 0:
-            del items[start:start+delta]
-        else:
-            assert delta==0
+        oldsize = w_list.ob_size
+        delta = len2 - slicelength
+        newsize = oldsize + delta
+        _list_resize(w_list, newsize)
+        w_list.ob_size = newsize
+        r = range(stop+delta, newsize)
+        if delta > 0:
+            r.reverse()
+        items = w_list.ob_item
+        for i in r:
+            items[i] = items[i-delta]
     elif len2 != slicelength:  # No resize for extended slices
         raise OperationError(space.w_ValueError, space.wrap("attempt to "
               "assign sequence of size %d to extended slice of size %d" %
               (len2,slicelength)))
 
+    r = range(len2)
+    items = w_list.ob_item
     if sequence2 is items:
         if step > 0:
             # Always copy starting from the right to avoid
             # having to make a shallow copy in the case where
             # the source and destination lists are the same list.
-            i = len2 - 1
-            start += i*step
-            while i >= 0:
-                items[start] = sequence2[i]
-                start -= step
-                i -= 1
-            return
+            r.reverse()
         else:
             # Make a shallow copy to more easily handle the reversal case
             sequence2 = list(sequence2)
-    for i in range(len2):
-        items[start] = sequence2[i]
-        start += step
-
-app = gateway.applevel("""
-    def listrepr(currently_in_repr, l):
-        'The app-level part of repr().'
-        list_id = id(l)
-        if list_id in currently_in_repr:
-            return '[...]'
-        currently_in_repr[list_id] = 1
-        try:
-            return "[" + ", ".join([repr(x) for x in l]) + ']'
-        finally:
-            try:
-                del currently_in_repr[list_id]
-            except:
-                pass
-""", filename=__file__) 
-
-listrepr = app.interphook("listrepr")
+    for i in r:
+        items[start+i*step] = sequence2[i]
+    return space.w_None
 
 def repr__List(space, w_list):
-    if len(w_list.wrappeditems) == 0:
-        return space.wrap('[]')
-    ec = space.getexecutioncontext()
-    w_currently_in_repr = ec._py_repr
-    if w_currently_in_repr is None:
-        w_currently_in_repr = ec._py_repr = space.newdict()
-    return listrepr(space, w_currently_in_repr, w_list)
-
-def list_insert__List_ANY_ANY(space, w_list, w_where, w_any):
-    where = space.int_w(w_where)
-    length = len(w_list.wrappeditems)
+    w = space.wrap
+    a = space.add
+    reprs_w = map(space.repr, space.unpackiterable(w_list))
+    from pypy.objspace.std.stringtype import W_StringType
+    w_bm = space.getattr(space.wrap(', '), space.wrap('join'))
+    return a(a(w('['), space.call_function(w_bm, space.newlist(reprs_w))), w(']'))
+    return space.newstring([])
+
+def hash__List(space,w_list):
+    raise OperationError(space.w_TypeError,space.wrap("list objects are unhashable"))
+
+# adapted C code
+def _roundupsize(n):
+    nbits = r_uint(0)
+    n2 = n >> 5
+
+##    /* Round up:
+##     * If n <       256, to a multiple of        8.
+##     * If n <      2048, to a multiple of       64.
+##     * If n <     16384, to a multiple of      512.
+##     * If n <    131072, to a multiple of     4096.
+##     * If n <   1048576, to a multiple of    32768.
+##     * If n <   8388608, to a multiple of   262144.
+##     * If n <  67108864, to a multiple of  2097152.
+##     * If n < 536870912, to a multiple of 16777216.
+##     * ...
+##     * If n < 2**(5+3*i), to a multiple of 2**(3*i).
+##     *
+##     * This over-allocates proportional to the list size, making room
+##     * for additional growth.  The over-allocation is mild, but is
+##     * enough to give linear-time amortized behavior over a long
+##     * sequence of appends() in the presence of a poorly-performing
+##     * system realloc() (which is a reality, e.g., across all flavors
+##     * of Windows, with Win9x behavior being particularly bad -- and
+##     * we've still got address space fragmentation problems on Win9x
+##     * even with this scheme, although it requires much longer lists to
+##     * provoke them than it used to).
+##     */
+    while 1:
+        n2 >>= 3
+        nbits += 3
+        if not n2 :
+            break
+    return ((n >> nbits) + 1) << nbits
+
+# before we have real arrays,
+# we use lists, allocated to fixed size.
+# XXX memory overflow is ignored here.
+# See listobject.c for reference.
+
+for_later = """
+#define NRESIZE(var, type, nitems)              \
+do {                                \
+    size_t _new_size = _roundupsize(nitems);         \
+    if (_new_size <= ((~(size_t)0) / sizeof(type)))     \
+        PyMem_RESIZE(var, type, _new_size);     \
+    else                            \
+        var = NULL;                 \
+} while (0)
+"""
+
+def _list_resize(w_list, newlen):
+    if newlen > len(w_list.ob_item):
+        true_size = _roundupsize(newlen)
+        old_items = w_list.ob_item
+        w_list.ob_item = items = [None] * true_size
+        for p in range(len(old_items)):
+            items[p] = old_items[p]
+
+def _ins1(w_list, where, w_any):
+    _list_resize(w_list, w_list.ob_size+1)
+    size = w_list.ob_size
+    items = w_list.ob_item
     if where < 0:
-        where += length
-        if where < 0:
-            where = 0
-    elif where > length:
-        where = length
-    w_list.wrappeditems.insert(where, w_any)
-    return space.w_None
+        where += size
+    if where < 0:
+        where = 0
+    if (where > size):
+        where = size
+    for i in range(size, where, -1):
+        items[i] = items[i-1]
+    items[where] = w_any
+    w_list.ob_size += 1
 
-def list_append__List_ANY(space, w_list, w_any):
-    w_list.wrappeditems.append(w_any)
+def list_insert__List_Int_ANY(space, w_list, w_where, w_any):
+    _ins1(w_list, w_where.intval, w_any)
     return space.w_None
 
-def list_extend__List_List(space, w_list, w_other):
-    w_list.wrappeditems += w_other.wrappeditems
+def list_append__List_ANY(space, w_list, w_any):
+    _ins1(w_list, w_list.ob_size, w_any)
     return space.w_None
 
 def list_extend__List_ANY(space, w_list, w_any):
-    w_list.wrappeditems += space.unpackiterable(w_any)
+    lis = space.unpackiterable(w_any)
+    newlen = w_list.ob_size + len(lis)
+    _list_resize(w_list, newlen)
+    d = w_list.ob_size
+    items = w_list.ob_item
+    for i in range(len(lis)):
+        items[d+i] = lis[i]
+    w_list.ob_size = newlen
     return space.w_None
 
+def _del_slice(w_list, ilow, ihigh):
+    """ similar to the deletion part of list_ass_slice in CPython """
+    if ilow < 0:
+        ilow = 0
+    elif ilow > w_list.ob_size:
+        ilow = w_list.ob_size
+    if ihigh < ilow:
+        ihigh = ilow
+    elif ihigh > w_list.ob_size:
+        ihigh = w_list.ob_size
+    items = w_list.ob_item
+    d = ihigh-ilow
+    # XXX this is done by CPython to hold the elements
+    # to be deleted. I have no idea how to express
+    # this here, but we need to be aware when we write
+    # a compiler.
+    # recycle = [items[i] for i in range(ilow, ihigh)]
+    for i in range(ilow, w_list.ob_size - d):
+        items[i] = items[i+d]
+        items[i+d] = None
+    w_list.ob_size -= d
+
 # note that the default value will come back wrapped!!!
-def list_pop__List_ANY(space, w_list, w_idx=-1):
-    items = w_list.wrappeditems
-    if len(items)== 0:
+def list_pop__List_Int(space, w_list, w_idx=-1):
+    if w_list.ob_size == 0:
         raise OperationError(space.w_IndexError,
                              space.wrap("pop from empty list"))
-    idx = space.int_w(w_idx)
-    try:
-        return items.pop(idx)
-    except IndexError:
+    i = w_idx.intval
+    if i < 0:
+        i += w_list.ob_size
+    if i < 0 or i >= w_list.ob_size:
         raise OperationError(space.w_IndexError,
                              space.wrap("pop index out of range"))
+    w_res = w_list.ob_item[i]
+    _del_slice(w_list, i, i+1)
+    return w_res
 
 def list_remove__List_ANY(space, w_list, w_any):
-    # needs to be safe against eq_w() mutating the w_list behind our back
-    items = w_list.wrappeditems
-    i = 0
-    while i < len(items):
-        if space.eq_w(items[i], w_any):
-            if i < len(items): # if this is wrong the list was changed
-                del items[i]
+    eq = space.eq
+    items = w_list.ob_item
+    for i in range(w_list.ob_size):
+        cmp = eq(items[i], w_any)
+        if space.is_true(cmp):
+            _del_slice(w_list, i, i+1)
             return space.w_None
-        i += 1
-    raise OperationError(space.w_ValueError,
+    raise OperationError(space.w_IndexError,
                          space.wrap("list.remove(x): x not in list"))
 
-def list_index__List_ANY_ANY_ANY(space, w_list, w_any, w_start, w_stop):
-    # needs to be safe against eq_w() mutating the w_list behind our back
-    items = w_list.wrappeditems
-    size = len(items)
-    i = slicetype.adapt_bound(space, size, w_start)
-    stop = slicetype.adapt_bound(space, size, w_stop)
-    while i < stop and i < len(items):
-        if space.eq_w(items[i], w_any):
+def list_index__List_ANY_Int_Int(space, w_list, w_any, w_start, w_stop):
+    eq = space.eq
+    items = w_list.ob_item
+    size = w_list.ob_size
+    start = space.unwrap(w_start)
+    if start < 0:
+        start += size
+    start = min(max(0,start),size)
+    stop = space.unwrap(w_stop)
+    if stop < 0:
+        stop += size
+    stop = min(max(start,stop),size)
+    
+    for i in range(start,stop):
+        cmp = eq(items[i], w_any)
+        if space.is_true(cmp):
             return space.wrap(i)
-        i += 1
     raise OperationError(space.w_ValueError,
                          space.wrap("list.index(x): x not in list"))
 
 def list_count__List_ANY(space, w_list, w_any):
-    # needs to be safe against eq_w() mutating the w_list behind our back
-    count = 0
-    i = 0
-    items = w_list.wrappeditems
-    while i < len(items):
-        if space.eq_w(items[i], w_any):
+    eq = space.eq
+    items = w_list.ob_item
+    count = r_int(0)
+    for i in range(w_list.ob_size):
+        cmp = eq(items[i], w_any)
+        if space.is_true(cmp):
             count += 1
-        i += 1
     return space.wrap(count)
 
+# Reverse a slice of a list in place, from lo up to (exclusive) hi.
+# (also used in sort, later)
+
+def _reverse_slice(lis, lo, hi):
+    hi -= 1
+    while lo < hi:
+        t = lis[lo]
+        lis[lo] = lis[hi]
+        lis[hi] = t
+        lo += 1
+        hi -= 1
+
 def list_reverse__List(space, w_list):
-    w_list.wrappeditems.reverse()
+    if w_list.ob_size > 1:
+        _reverse_slice(w_list.ob_item, 0, w_list.ob_size)
     return space.w_None
 
-# ____________________________________________________________
-# Sorting
+    
 
-# Reverse a slice of a list in place, from lo up to (exclusive) hi.
-# (used in sort)
+# Python Quicksort Written by Magnus Lie Hetland
+# http://www.hetland.org/python/quicksort.html
 
-class KeyContainer(baseobjspace.W_Root):
-    def __init__(self, w_key, w_item):
-        self.w_key = w_key
-        self.w_item = w_item
-
-# NOTE: all the subclasses of TimSort should inherit from a common subclass,
-#       so make sure that only SimpleSort inherits directly from TimSort.
-#       This is necessary to hide the parent method TimSort.lt() from the
-#       annotator.
-class SimpleSort(TimSort):
-    def lt(self, a, b):
-        space = self.space
-        return space.is_true(space.lt(a, b))
-
-class CustomCompareSort(SimpleSort):
-    def lt(self, a, b):
-        space = self.space
-        w_cmp = self.w_cmp
-        w_result = space.call_function(w_cmp, a, b)
-        try:
-            result = space.int_w(w_result)
-        except OperationError, e:
-            if e.match(space, space.w_TypeError):
+# NOTE:  we cannot yet detect that a user comparision
+#        function modifies the list in-place.  The
+#        CPython sort() should be studied to learn how
+#        to implement this functionality.
+
+def _partition(list, start, end, lt):
+    pivot = list[end]                          # Partition around the last value
+    bottom = start-1                           # Start outside the area to be partitioned
+    top = end                                  # Ditto
+
+    done = 0
+    while not done:                            # Until all elements are partitioned...
+
+        while not done:                        # Until we find an out of place element...
+            bottom = bottom+1                  # ... move the bottom up.
+
+            if bottom == top:                  # If we hit the top...
+                done = 1                       # ... we are done.
+                break
+
+            if lt(pivot, list[bottom]):        # Is the bottom out of place?
+                list[top] = list[bottom]       # Then put it at the top...
+                break                          # ... and start searching from the top.
+
+        while not done:                        # Until we find an out of place element...
+            top = top-1                        # ... move the top down.
+            
+            if top == bottom:                  # If we hit the bottom...
+                done = 1                       # ... we are done.
+                break
+
+            if lt(list[top], pivot):           # Is the top out of place?
+                list[bottom] = list[top]       # Then put it at the bottom...
+                break                          # ...and start searching from the bottom.
+
+    list[top] = pivot                          # Put the pivot in its place.
+    return top                                 # Return the split point
+
+
+def _quicksort(list, start, end, lt):
+    if start < end:                            # If there are two or more elements...
+        split = _partition(list, start, end, lt)    # ... partition the sublist...
+        _quicksort(list, start, split-1, lt)        # ... and sort both halves.
+        _quicksort(list, split+1, end, lt)
+
+def list_sort__List_ANY(space, w_list, w_cmp):
+    if w_cmp is space.w_None:
+        def lt(a,b):
+            return space.is_true(space.lt(a,b))
+    else:
+        def lt(a,b):
+            result = space.unwrap(space.call_function(w_cmp, a, b))
+            if not isinstance(result,int):
                 raise OperationError(space.w_TypeError,
-                    space.wrap("comparison function must return int"))
-            raise
-        return result < 0
-
-class CustomKeySort(SimpleSort):
-    def lt(self, a, b):
-        assert isinstance(a, KeyContainer)
-        assert isinstance(b, KeyContainer)
-        space = self.space
-        return space.is_true(space.lt(a.w_key, b.w_key))
-
-class CustomKeyCompareSort(CustomCompareSort):
-    def lt(self, a, b):
-        assert isinstance(a, KeyContainer)
-        assert isinstance(b, KeyContainer)
-        return CustomCompareSort.lt(self, a.w_key, b.w_key)
-
-def list_sort__List_ANY_ANY_ANY(space, w_list, w_cmp, w_keyfunc, w_reverse):
-    has_cmp = not space.is_w(w_cmp, space.w_None)
-    has_key = not space.is_w(w_keyfunc, space.w_None)
-    has_reverse = space.is_true(w_reverse)
-
-    # create and setup a TimSort instance
-    if has_cmp: 
-        if has_key: 
-            sorterclass = CustomKeyCompareSort
-        else: 
-            sorterclass = CustomCompareSort
-    else: 
-        if has_key: 
-            sorterclass = CustomKeySort
-        else: 
-            sorterclass = SimpleSort
-    items = w_list.wrappeditems
-    sorter = sorterclass(items, len(items))
-    sorter.space = space
-    sorter.w_cmp = w_cmp
-
-    try:
-        # The list is temporarily made empty, so that mutations performed
-        # by comparison functions can't affect the slice of memory we're
-        # sorting (allowing mutations during sorting is an IndexError or
-        # core-dump factory, since wrappeditems may change).
-        w_list.wrappeditems = []
-
-        # wrap each item in a KeyContainer if needed
-        if has_key:
-            for i in range(sorter.listlength):
-                w_item = sorter.list[i]
-                w_key = space.call_function(w_keyfunc, w_item)
-                sorter.list[i] = KeyContainer(w_key, w_item)
-
-        # Reverse sort stability achieved by initially reversing the list,
-        # applying a stable forward sort, then reversing the final result.
-        if has_reverse:
-            sorter.list.reverse()
-
-        # perform the sort
-        sorter.sort()
-
-        # reverse again
-        if has_reverse:
-            sorter.list.reverse()
-
-    finally:
-        # unwrap each item if needed
-        if has_key:
-            for i in range(sorter.listlength):
-                w_obj = sorter.list[i]
-                if isinstance(w_obj, KeyContainer):
-                    sorter.list[i] = w_obj.w_item
-
-        # check if the user mucked with the list during the sort
-        mucked = len(w_list.wrappeditems) > 0
-
-        # put the items back into the list
-        w_list.wrappeditems = sorter.list
-
-    if mucked:
-        raise OperationError(space.w_ValueError,
-                             space.wrap("list modified during sort"))
+                         space.wrap("comparison function must return int"))
+            return result < 0
 
+    # XXX Basic quicksort implementation
+    # XXX this is not stable !!
+    _quicksort(w_list.ob_item, 0, w_list.ob_size-1, lt)
     return space.w_None
 
 
-from pypy.objspace.std import listtype
-register_all(vars(), listtype)
+"""
+static PyMethodDef list_methods[] = {
+    {"append",  (PyCFunction)listappend,  METH_O, append_doc},
+    {"insert",  (PyCFunction)listinsert,  METH_VARARGS, insert_doc},
+    {"extend",      (PyCFunction)listextend,  METH_O, extend_doc},
+    {"pop",     (PyCFunction)listpop,     METH_VARARGS, pop_doc},
+    {"remove",  (PyCFunction)listremove,  METH_O, remove_doc},
+    {"index",   (PyCFunction)listindex,   METH_O, index_doc},
+    {"count",   (PyCFunction)listcount,   METH_O, count_doc},
+    {"reverse", (PyCFunction)listreverse, METH_NOARGS, reverse_doc},
+    {"sort",    (PyCFunction)listsort,    METH_VARARGS, sort_doc},
+    {NULL,      NULL}       /* sentinel */
+};
+"""
+
+register_all(vars(), W_ListType)

Modified: pypy/branch/avm/pypy/objspace/std/noneobject.py
==============================================================================
--- pypy/branch/avm/pypy/objspace/std/noneobject.py	(original)
+++ pypy/branch/avm/pypy/objspace/std/noneobject.py	Thu Nov  5 20:27:32 2009
@@ -5,19 +5,17 @@
 """ 
 
 from pypy.objspace.std.objspace import *
+from nonetype import W_NoneType
 
 class W_NoneObject(W_Object):
-    from pypy.objspace.std.nonetype import none_typedef as typedef
-
-    def unwrap(w_self, space):
-        return None
-
+    statictype = W_NoneType
 registerimplementation(W_NoneObject)
 
-W_NoneObject.w_None = W_NoneObject()
+def unwrap__None(space, w_none):
+    return None
 
-def nonzero__None(space, w_none):
-    return space.w_False
+def is_true__None(space, w_none):
+    return False
 
 def repr__None(space, w_none):
     return space.wrap('None')

Modified: pypy/branch/avm/pypy/objspace/std/sliceobject.py
==============================================================================
--- pypy/branch/avm/pypy/objspace/std/sliceobject.py	(original)
+++ pypy/branch/avm/pypy/objspace/std/sliceobject.py	Thu Nov  5 20:27:32 2009
@@ -6,135 +6,37 @@
 """
 
 from pypy.objspace.std.objspace import *
-from pypy.interpreter import gateway
-from pypy.objspace.std.slicetype import _Eval_SliceIndex
+from slicetype import W_SliceType
 
 
 class W_SliceObject(W_Object):
-    from pypy.objspace.std.slicetype import slice_typedef as typedef
+    statictype = W_SliceType
     
-    def __init__(w_self, w_start, w_stop, w_step):
-        assert w_start is not None
-        assert w_stop is not None
-        assert w_step is not None
+    def __init__(w_self, space, w_start, w_stop, w_step):
+        W_Object.__init__(w_self, space)
         w_self.w_start = w_start
         w_self.w_stop = w_stop
         w_self.w_step = w_step
 
-    def unwrap(w_slice, space):
-        return slice(space.unwrap(w_slice.w_start), space.unwrap(w_slice.w_stop), space.unwrap(w_slice.w_step))
+registerimplementation(W_SliceObject)
 
-    def indices3(w_slice, space, length):
-        if space.is_w(w_slice.w_step, space.w_None):
-            step = 1
-        else:
-            step = _Eval_SliceIndex(space, w_slice.w_step)
-            if step == 0:
-                raise OperationError(space.w_ValueError,
-                                     space.wrap("slice step cannot be zero"))
-        if space.is_w(w_slice.w_start, space.w_None):
-            if step < 0:
-                start = length - 1
-            else:
-                start = 0
+
+def getattribute__Slice_ANY(space, w_slice, w_attr):
+    if space.is_true(space.eq(w_attr, space.wrap('start'))):
+        if w_slice.w_start is None:
+            return space.w_None
         else:
-            start = _Eval_SliceIndex(space, w_slice.w_start)
-            if start < 0:
-                start += length
-                if start < 0:
-                    if step < 0:
-                        start = -1
-                    else:
-                        start = 0
-            elif start >= length:
-                if step < 0:
-                    start = length - 1
-                else:
-                    start = length
-        if space.is_w(w_slice.w_stop, space.w_None):
-            if step < 0:
-                stop = -1
-            else:
-                stop = length
+            return w_slice.w_start
+    if space.is_true(space.eq(w_attr, space.wrap('stop'))):
+        if w_slice.w_stop is None:
+            return space.w_None
         else:
-            stop = _Eval_SliceIndex(space, w_slice.w_stop)
-            if stop < 0:
-                stop += length
-                if stop < 0:
-                    stop =-1
-            elif stop > length:
-                stop = length
-        return start, stop, step
-
-    def indices4(w_slice, space, length):
-        start, stop, step = w_slice.indices3(space, length)
-        if (step < 0 and stop >= start) or (step > 0 and start >= stop):
-            slicelength = 0
-        elif step < 0:
-            slicelength = (stop - start + 1) / step + 1
+            return w_slice.w_stop
+    if space.is_true(space.eq(w_attr, space.wrap('step'))):
+        if w_slice.w_step is None:
+            return space.w_None
         else:
-            slicelength = (stop - start - 1) / step + 1
-        return start, stop, step, slicelength
+            return w_slice.w_step
+    raise FailedToImplement(space.w_AttributeError)
 
-registerimplementation(W_SliceObject)
-
-
-def normalize_simple_slice(space, length, w_start, w_stop):
-    """Helper for the {get,set,del}slice multimethod implementations."""
-    # this returns a pair (start, stop) which is usable for slicing
-    # a sequence of the given length in the most friendly way, i.e.
-    # guaranteeing that 0 <= start <= stop <= length.
-    start = space.int_w(w_start)
-    stop = space.int_w(w_stop)
-    assert length >= 0
-    if start < 0:
-        start = 0
-    if stop < start:
-        stop = start
-    if stop > length:
-        stop = length
-        if start > length:
-            start = length
-    return start, stop
-
-
-repr__Slice = gateway.applevel("""
-    def repr__Slice(aslice):
-        return 'slice(%r, %r, %r)' % (aslice.start, aslice.stop, aslice.step)
-""", filename=__file__).interphook("repr__Slice")
-
-def eq__Slice_Slice(space, w_slice1, w_slice2):
-    # We need this because CPython considers that slice1 == slice1
-    # is *always* True (e.g. even if slice1 was built with non-comparable
-    # parameters
-    if space.is_w(w_slice1, w_slice2):
-        return space.w_True
-    if space.eq_w(w_slice1.w_start, w_slice2.w_start) and \
-        space.eq_w(w_slice1.w_stop, w_slice2.w_stop) and \
-        space.eq_w(w_slice1.w_step, w_slice2.w_step):
-        return space.w_True
-    else:
-        return space.w_False
-
-def lt__Slice_Slice(space, w_slice1, w_slice2):
-    if space.is_w(w_slice1, w_slice2):
-        return space.w_False   # see comments in eq__Slice_Slice()
-    if space.eq_w(w_slice1.w_start, w_slice2.w_start):
-        if space.eq_w(w_slice1.w_stop, w_slice2.w_stop):
-            return space.lt(w_slice1.w_step, w_slice2.w_step)
-        else:
-            return space.lt(w_slice1.w_stop, w_slice2.w_stop)
-    else:
-        return space.lt(w_slice1.w_start, w_slice2.w_start)
-
-# indices impl
-
-def slice_indices__Slice_ANY(space, w_slice, w_length):
-    length = space.getindex_w(w_length, space.w_OverflowError)
-    start, stop, step = w_slice.indices3(space, length)
-    return space.newtuple([space.wrap(start), space.wrap(stop),
-                           space.wrap(step)])
-
-# register all methods
-from pypy.objspace.std import slicetype
-register_all(vars(), slicetype)
+register_all(vars())

Modified: pypy/branch/avm/pypy/objspace/std/stringobject.py
==============================================================================
--- pypy/branch/avm/pypy/objspace/std/stringobject.py	(original)
+++ pypy/branch/avm/pypy/objspace/std/stringobject.py	Thu Nov  5 20:27:32 2009
@@ -1,190 +1,211 @@
-# -*- coding: latin-1 -*-
+# -*- Coding: Latin-1 -*-
+"""
+stringobject.py
+
+Synopsis of implemented methods (* marks work in progress)
+
+Py                PyPy
+
+                  def _is_generic(w_self, fun):
+                  def mod__String_ANY(space, w_str, w_item):def mod__String_Tuple(space, w_str, w_tuple):def mod_str_tuple(space, w_format, w_args):
+                  def ord__String(space, w_str):
+                  def string_richcompare(space, w_str1, w_str2, op):
+                  def unwrap__String(space, w_str):
+__add__           def add__String_String(space, w_left, w_right):
+__class__
+__contains__
+__delattr__
+__doc__
+__eq__            def eq__String_String(space, w_str1, w_str2):
+__ge__            def ge__String_String(space, w_str1, w_str2):
+__getattribute__
+__getitem__       def getitem__String_Int(space, w_str, w_int): def getitem__String_Slice(space, w_str, w_slice):
+__getslice__
+__gt__            def gt__String_String(space, w_str1, w_str2):
+__hash__          def hash__String(space, w_str):
+__init__
+__le__            def le__String_String(space, w_str1, w_str2):
+__len__           def len__String(space, w_str):
+__lt__            def lt__String_String(space, w_str1, w_str2):
+__mul__
+__ne__            def ne__String_String(space, w_str1, w_str2):
+__new__
+__reduce__
+__repr__          def repr__String(space, w_str):
+__rmul__
+__setattr__
+__str__           def str__String(space, w_str):
+capitalize        def str_capitalize__String(space, w_self):
+center            def str_center__String_Int(space, w_self):
+count             def str_count__String_String_Int_Int(space, w_self): [optional arguments not supported now]
+decode            !Unicode not supported now
+encode            !Unicode not supported now
+endswith          str_endswith__String_String    [optional arguments not supported now]
+expandtabs        str_expandtabs__String_Int
+find              OK
+index             OK
+isalnum           def str_isalnum__String(space, w_self): def _isalnum(ch):
+isalpha           def str_isalpha__String(space, w_self): def _isalpha(ch):
+isdigit           def str_isdigit__String(space, w_self): def _isdigit(ch):
+islower           def str_islower__String(space, w_self): def _islower(ch):
+isspace           def str_isspace__String(space, w_self): def _isspace(ch):
+istitle           def str_istitle(space, w_self):
+isupper           def str_isupper__String(space, w_self): def _isupper(ch):
+join              def str_join__String_ANY(space, w_self, w_list):
+ljust             def str_ljust__String_ANY(space, w_self, w_arg):
+lower             OK
+lstrip            def str_lstrip__String_String(space, w_self, w_chars):
+replace           OK
+rfind             OK
+rindex            OK
+rjust             def str_rjust__String_ANY(space, w_self, w_arg):
+rstrip            def str_rstrip__String_String(space, w_self, w_chars):
+split             def str_split__String_None_Int(space, w_self, w_none, w_maxsplit=-1):def str_split__String_String_Int(space, w_self, w_by, w_maxsplit=-1):
+splitlines        def str_splitlines__String_String(space, w_self, w_keepends):
+startswith        str_startswith__String_String    [optional arguments not supported now]
+strip             def str_strip__String_String(space, w_self, w_chars):
+swapcase          OK
+title             def str_title__String(space, w_self):
+translate         OK
+upper             def str_upper__String(space, w_self):
+zfill             OK
+"""
 
 from pypy.objspace.std.objspace import *
 from pypy.interpreter import gateway
-from pypy.rlib.rarithmetic import ovfcheck, _hash_string
-from pypy.rlib.objectmodel import we_are_translated
-from pypy.objspace.std.inttype import wrapint
-from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice
-from pypy.objspace.std import slicetype
-from pypy.objspace.std.listobject import W_ListObject
-from pypy.objspace.std.noneobject import W_NoneObject
-from pypy.objspace.std.tupleobject import W_TupleObject
-from pypy.rlib.rstring import StringBuilder
-from pypy.interpreter.buffer import StringBuffer
+from stringtype import W_StringType
+from intobject   import W_IntObject
+from sliceobject import W_SliceObject
+import slicetype
+from listobject import W_ListObject
+from noneobject import W_NoneObject
+from tupleobject import W_TupleObject
 
-from pypy.objspace.std.stringtype import sliced, joined, wrapstr, wrapchar, \
-     stringendswith, stringstartswith, joined2
+# XXX consider reimplementing _value to be a list of characters
+#     instead of a plain string
 
-from pypy.objspace.std.formatting import mod_format
 
 class W_StringObject(W_Object):
-    from pypy.objspace.std.stringtype import str_typedef as typedef
+    statictype = W_StringType
 
-    _immutable_ = True
-    def __init__(w_self, str):
+    def __init__(w_self, space, str):
+        W_Object.__init__(w_self, space)
         w_self._value = str
 
     def __repr__(w_self):
         """ representation for debugging purposes """
         return "%s(%r)" % (w_self.__class__.__name__, w_self._value)
 
-    def unwrap(w_self, space):
-        return w_self._value
 
 registerimplementation(W_StringObject)
 
-W_StringObject.EMPTY = W_StringObject('')
-W_StringObject.PREBUILT = [W_StringObject(chr(i)) for i in range(256)]
-del i
+def _isspace(ch):
+    return ord(ch) in (9, 10, 11, 12, 13, 32)  
 
-def _decode_ascii(space, s):
-    try:
-        return s.decode("ascii")
-    except UnicodeDecodeError:
-        for i in range(len(s)):
-            if ord(s[i]) > 127:
-                raise OperationError(
-                    space.w_UnicodeDecodeError,
-                    space.newtuple([
-                    space.wrap('ascii'),
-                    space.wrap(s),
-                    space.wrap(i),
-                    space.wrap(i+1),
-                    space.wrap("ordinal not in range(128)")]))
-        assert False, "unreachable"
-
-def unicode_w__String(space, w_self):
-    # XXX should this use the default encoding?
-    return _decode_ascii(space, w_self._value)
-
-def _is_generic(space, w_self, fun): 
-    v = w_self._value
+def _isdigit(ch):
+    o = ord(ch)
+    return o >= 48 and o <= 57
+
+def _isalpha(ch):
+    o = ord(ch)
+    return (o>=97 and o<=122) or (o>=65 and o<=90)
+
+def _isalnum(ch):
+    o = ord(ch)
+    return (o>=97 and o<=122) \
+        or (o>=65 and o<=90) \
+        or (o>=48 and o<=57)
+
+def _isupper(ch):
+    o = ord(ch)
+    return (o>=65 and o<=90)
+
+def _islower(ch):   
+    o = ord(ch)
+    return (o>=97 and o<=122)
+
+def _is_generic(w_self, fun): 
+    space = w_self.space   
+    v = space.unwrap(w_self)
     if len(v) == 0:
         return space.w_False
     if len(v) == 1:
         c = v[0]
         return space.newbool(fun(c))
     else:
+        res = 1
         for idx in range(len(v)):
             if not fun(v[idx]):
                 return space.w_False
         return space.w_True
-_is_generic._annspecialcase_ = "specialize:arg(2)"
-
-def _upper(ch):
-    if ch.islower():
-        o = ord(ch) - 32
-        return chr(o)
-    else:
-        return ch
-    
-def _lower(ch):
-    if ch.isupper():
-        o = ord(ch) + 32
-        return chr(o)
-    else:
-        return ch
-
-_isspace = lambda c: c.isspace()
-_isdigit = lambda c: c.isdigit()
-_isalpha = lambda c: c.isalpha()
-_isalnum = lambda c: c.isalnum()
 
 def str_isspace__String(space, w_self):
-    return _is_generic(space, w_self, _isspace)
+    return _is_generic(w_self, _isspace)
 
 def str_isdigit__String(space, w_self):
-    return _is_generic(space, w_self, _isdigit)
+    return _is_generic(w_self, _isdigit)
 
 def str_isalpha__String(space, w_self):
-    return _is_generic(space, w_self, _isalpha)
+    return _is_generic(w_self, _isalpha)
 
 def str_isalnum__String(space, w_self):
-    return _is_generic(space, w_self, _isalnum)
+    return _is_generic(w_self, _isalnum)
 
 def str_isupper__String(space, w_self):
-    """Return True if all cased characters in S are uppercase and there is
-at least one cased character in S, False otherwise."""
-    v = w_self._value
-    if len(v) == 1:
-        c = v[0]
-        return space.newbool(c.isupper())
-    cased = False
-    for idx in range(len(v)):
-        if v[idx].islower():
-            return space.w_False
-        elif not cased and v[idx].isupper():
-            cased = True
-    return space.newbool(cased)
+    return _is_generic(w_self, _isupper)
 
 def str_islower__String(space, w_self):
-    """Return True if all cased characters in S are lowercase and there is
-at least one cased character in S, False otherwise."""
-    v = w_self._value
-    if len(v) == 1:
-        c = v[0]
-        return space.newbool(c.islower())
-    cased = False
-    for idx in range(len(v)):
-        if v[idx].isupper():
-            return space.w_False
-        elif not cased and v[idx].islower():
-            cased = True
-    return space.newbool(cased)
+    return _is_generic(w_self, _islower)
 
 def str_istitle__String(space, w_self):
-    """Return True if S is a titlecased string and there is at least one
-character in S, i.e. uppercase characters may only follow uncased
-characters and lowercase characters only cased ones. Return False
-otherwise."""
-    input = w_self._value
-    cased = False
-    previous_is_cased = False
+    input = space.unwrap(w_self)
+    prev_letter='!'
 
     for pos in range(0, len(input)):
         ch = input[pos]
-        if ch.isupper():
-            if previous_is_cased:
-                return space.w_False
-            previous_is_cased = True
-            cased = True
-        elif ch.islower():
-            if not previous_is_cased:
-                return space.w_False
-            cased = True
-        else:
-            previous_is_cased = False
+        if ch.isalpha():
+            if (prev_letter.isalpha() and ch.isupper()) or \
+               (not prev_letter.isalpha() and  ch.islower()):
+                    return space.w_False
+        prev_letter = ch
 
-    return space.newbool(cased)
+    return space.w_True
 
 def str_upper__String(space, w_self):
-    self = w_self._value
+    self = space.unwrap(w_self)
     res = [' '] * len(self)
     for i in range(len(self)):
         ch = self[i]
-        res[i] = _upper(ch)
+        if _islower(ch):
+            o = ord(ch) - 32
+            res[i] = chr(o)
+        else:
+            res[i] = ch
 
     return space.wrap("".join(res))
 
 def str_lower__String(space, w_self):
-    self = w_self._value
+    self = space.unwrap(w_self)
     res = [' '] * len(self)
     for i in range(len(self)):
         ch = self[i]
-        res[i] = _lower(ch)
+        if _isupper(ch):
+            o = ord(ch) + 32
+            res[i] = chr(o)
+        else:
+            res[i] = ch
 
     return space.wrap("".join(res))
 
 def str_swapcase__String(space, w_self):
-    self = w_self._value
+    self = space.unwrap(w_self)
     res = [' '] * len(self)
     for i in range(len(self)):
         ch = self[i]
-        if ch.isupper():
+        if _isupper(ch):
             o = ord(ch) + 32
             res[i] = chr(o)
-        elif ch.islower():
+        elif _islower(ch):
             o = ord(ch) - 32
             res[i] = chr(o)
         else:
@@ -194,11 +215,11 @@
 
     
 def str_capitalize__String(space, w_self):
-    input = w_self._value
+    input = space.unwrap(w_self)
     buffer = [' '] * len(input)
     if len(input) > 0:
         ch = input[0]
-        if ch.islower():
+        if _islower(ch):
             o = ord(ch) - 32
             buffer[0] = chr(o)
         else:
@@ -206,7 +227,7 @@
 
         for i in range(1, len(input)):
             ch = input[i]
-            if ch.isupper():
+            if _isupper(ch):
                 o = ord(ch) + 32
                 buffer[i] = chr(o)
             else:
@@ -215,330 +236,305 @@
     return space.wrap("".join(buffer))
          
 def str_title__String(space, w_self):
-    input = w_self._value
+    input = space.unwrap(w_self)
     buffer = [' '] * len(input)
     prev_letter=' '
 
     for pos in range(0, len(input)):
         ch = input[pos]
         if not prev_letter.isalpha():
-            buffer[pos] = _upper(ch)
+            buffer[pos] = ch.upper()
         else:
-            buffer[pos] = _lower(ch)
+             buffer[pos] = ch.lower()
 
         prev_letter = buffer[pos]
 
     return space.wrap("".join(buffer))
 
-def str_split__String_None_ANY(space, w_self, w_none, w_maxsplit=-1):
-    maxsplit = space.int_w(w_maxsplit)
-    res_w = []
-    value = w_self._value
-    length = len(value)
-    i = 0
-    while True:
-        # find the beginning of the next word
-        while i < length:
-            if not value[i].isspace():
-                break   # found
-            i += 1
-        else:
-            break  # end of string, finished
-
-        # find the end of the word
-        if maxsplit == 0:
-            j = length   # take all the rest of the string
-        else:
-            j = i + 1
-            while j < length and not value[j].isspace():
-                j += 1
-            maxsplit -= 1   # NB. if it's already < 0, it stays < 0
-
-        # the word is value[i:j]
-        res_w.append(sliced(space, value, i, j, w_self))
-
-        # continue to look from the character following the space after the word
-        i = j + 1
-
-    return space.newlist(res_w)
-
-def str_split__String_String_ANY(space, w_self, w_by, w_maxsplit=-1):
-    maxsplit = space.int_w(w_maxsplit)
-    value = w_self._value
-    by = w_by._value
+def str_split__String_None_Int(space, w_self, w_none, w_maxsplit=-1):
+    res = []
+    inword = 0
+    u = space.unwrap
+    value = u(w_self)
+    maxsplit = u(w_maxsplit)
+    pos = 0
+
+    for ch in value:
+        if ch.isspace():
+            if inword:
+                inword = 0
+        else:
+            if inword:
+                res[-1] += ch
+            else:
+                if maxsplit > -1:
+                    if maxsplit == 0:
+                        res.append(value[pos:])
+                        break
+                    maxsplit = maxsplit - 1
+                res.append(ch)
+                inword = 1
+        pos = pos + 1
+
+    for i in range(len(res)):
+        res[i] = W_StringObject(space, res[i])
+    return W_ListObject(space, res)
+
+def str_split__String_String_Int(space, w_self, w_by, w_maxsplit=-1):
+    u = space.unwrap
+    res = []
+    start = 0
+    value = u(w_self)
+    by = u(w_by)
     bylen = len(by)
-    if bylen == 0:
-        raise OperationError(space.w_ValueError, space.wrap("empty separator"))
+    maxsplit = u(w_maxsplit)
 
-    res_w = []
-    start = 0
-    while maxsplit != 0:
-        next = value.find(by, start)
+    #if maxsplit is default, then you have no limit
+    #of the length of the resulting array
+    if maxsplit == -1:
+        splitcount = 1
+    else:
+        splitcount = maxsplit
+
+    while splitcount:             
+        next = _find(value, by, start, len(value), 1)
+        #next = value.find(by, start)    #of course we cannot use 
+                                         #the find method, 
         if next < 0:
+            res.append(value[start:])
+            start = len(value) + 1      
             break
-        res_w.append(sliced(space, value, start, next, w_self))
+        res.append(value[start:next])
         start = next + bylen
-        maxsplit -= 1   # NB. if it's already < 0, it stays < 0
-    
-    res_w.append(sliced(space, value, start, len(value), w_self))
-    return space.newlist(res_w)
-
-def str_rsplit__String_None_ANY(space, w_self, w_none, w_maxsplit=-1):
-    maxsplit = space.int_w(w_maxsplit)
-    res_w = []
-    value = w_self._value
-    i = len(value)-1
-    while True:
-        # starting from the end, find the end of the next word
-        while i >= 0:
-            if not value[i].isspace():
-                break   # found
-            i -= 1
-        else:
-            break  # end of string, finished
-
-        # find the start of the word
-        # (more precisely, 'j' will be the space character before the word)
-        if maxsplit == 0:
-            j = -1   # take all the rest of the string
-        else:
-            j = i - 1
-            while j >= 0 and not value[j].isspace():
-                j -= 1
-            maxsplit -= 1   # NB. if it's already < 0, it stays < 0
-
-        # the word is value[j+1:i+1]
-        j1 = j + 1
-        assert j1 >= 0
-        res_w.append(sliced(space, value, j1, i+1, w_self))
-
-        # continue to look from the character before the space before the word
-        i = j - 1
-
-    res_w.reverse()
-    return space.newlist(res_w)
-
-def make_rsplit_with_delim(funcname, sliced):
-    from pypy.tool.sourcetools import func_with_new_name
-
-    def fn(space, w_self, w_by, w_maxsplit=-1):
-        maxsplit = space.int_w(w_maxsplit)
-        res_w = []
-        value = w_self._value
-        end = len(value)
-        by = w_by._value
-        bylen = len(by)
-        if bylen == 0:
-            raise OperationError(space.w_ValueError, space.wrap("empty separator"))
-
-        while maxsplit != 0:
-            next = value.rfind(by, 0, end)
-            if next < 0:
-                break
-            res_w.append(sliced(space, value, next+bylen, end, w_self))
-            end = next
-            maxsplit -= 1   # NB. if it's already < 0, it stays < 0
-
-        res_w.append(sliced(space, value, 0, end, w_self))
-        res_w.reverse()
-        return space.newlist(res_w)
-    
-    return func_with_new_name(fn, funcname)
-
-str_rsplit__String_String_ANY = make_rsplit_with_delim('str_rsplit__String_String_ANY',
-                                                       sliced)
+        #decrese the counter only then, when
+        #we don't have default maxsplit
+        if maxsplit > -1:
+            splitcount = splitcount - 1
+
+    if start < len(value):             
+        res.append(value[start:])
+
+    for i in range(len(res)):
+        res[i] = W_StringObject(w_self.space, res[i])
+    return W_ListObject(w_self.space, res)
 
 def str_join__String_ANY(space, w_self, w_list):
-    list_w = space.unpackiterable(w_list)
-    str_w = space.str_w
-    if list_w:
-        self = w_self._value
+    u = space.unwrap
+    list = space.unpackiterable(w_list)
+    if list:
+        self = u(w_self)
+        firstelem = 1
         listlen = 0
-        reslen = 0
-        l = []
-        for i in range(len(list_w)):
-            w_s = list_w[i]
-            if not space.is_true(space.isinstance(w_s, space.w_str)):
-                if space.is_true(space.isinstance(w_s, space.w_unicode)):
-                    w_u = space.call_function(space.w_unicode, w_self)
-                    return space.call_method(w_u, "join", space.newlist(list_w))
-                raise OperationError(
-                    space.w_TypeError,
-                    space.wrap("sequence item %d: expected string, %s "
-                               "found" % (i,
-                                          space.type(w_s).getname(space, '?'))))
-            l.append(space.str_w(w_s))
-        return space.wrap(self.join(l))
+        reslen = 0 
+        #compute the length of the resulting string 
+        for w_item in list:
+            reslen = reslen + len(u(w_item))
+            listlen = listlen + 1
+
+        reslen = reslen + (listlen - 1) * len(self)
+
+        #allocate the string buffer
+        res = [' '] * reslen
+
+        pos = 0
+        #fill in the string buffer
+        for w_item in list:
+            item = u(w_item)
+            if firstelem:
+                for i in range(len(item)):
+                    res[i+pos] = item[i]
+                firstelem = 0
+                pos = pos + len(item)
+            else:
+                for i in range(len(self)):
+                    res[i+pos] = self[i]
+                pos = pos + len(self)
+                 
+                for i in range(len(item)):
+                    res[i+pos] = item[i]
+                pos = pos + len(item)
+
+        return space.wrap("".join(res))
     else:
-        return W_StringObject.EMPTY
+        return space.wrap("")
+
+
+def str_rjust__String_ANY(space, w_self, w_arg):
+    u = space.unwrap
 
-def str_rjust__String_ANY_ANY(space, w_self, w_arg, w_fillchar):
-    u_arg = space.int_w(w_arg)
-    u_self = w_self._value
-    fillchar = space.str_w(w_fillchar)
-    if len(fillchar) != 1:
-        raise OperationError(space.w_TypeError,
-            space.wrap("rjust() argument 2 must be a single character"))
+    u_arg = u(w_arg)
+    u_self = u(w_self)
     
     d = u_arg - len(u_self)
     if d>0:
-        fillchar = fillchar[0]    # annotator hint: it's a single character
-        u_self = d * fillchar + u_self
+        u_self = d * ' ' + u_self
         
     return space.wrap(u_self)
 
 
-def str_ljust__String_ANY_ANY(space, w_self, w_arg, w_fillchar):
-    u_self = w_self._value
-    u_arg = space.int_w(w_arg)
-    fillchar = space.str_w(w_fillchar)
-    if len(fillchar) != 1:
-        raise OperationError(space.w_TypeError,
-            space.wrap("ljust() argument 2 must be a single character"))
+def str_ljust__String_ANY(space, w_self, w_arg):
+    u = space.unwrap
+
+    u_self = u(w_self)
+    u_arg = u(w_arg)
 
     d = u_arg - len(u_self)
     if d>0:
-        fillchar = fillchar[0]    # annotator hint: it's a single character
-        u_self += d * fillchar
+        u_self += d * ' '
         
     return space.wrap(u_self)
 
-def _convert_idx_params(space, w_self, w_sub, w_start, w_end, upper_bound=False):
-    self = w_self._value
-    sub = w_sub._value
-    if upper_bound:
-        start = slicetype.adapt_bound(space, len(self), w_start)
-        end = slicetype.adapt_bound(space, len(self), w_end)
-    else:
-        start = slicetype.adapt_lower_bound(space, len(self), w_start)
-        end = slicetype.adapt_lower_bound(space, len(self), w_end)
+def _convert_idx_params(space, w_self, w_sub, w_start, w_end):
+    u = space.unwrap
+    start = u(w_start)
+    end = u(w_end)
+    self = u(w_self)
+    sub = u(w_sub)
+    if start is None:
+        start = 0
+    if end is None:
+        end = len(self)
+
     return (self, sub, start, end)
-_convert_idx_params._annspecialcase_ = 'specialize:arg(5)'
 
-def contains__String_String(space, w_self, w_sub):
-    self = w_self._value
-    sub = w_sub._value
-    return space.newbool(self.find(sub) >= 0)
 
-def str_find__String_String_ANY_ANY(space, w_self, w_sub, w_start, w_end):
+def str_find__String_String_ANY_ANY(space, w_self, w_sub, w_start=None, w_end=None):
+
     (self, sub, start, end) =  _convert_idx_params(space, w_self, w_sub, w_start, w_end)
-    res = self.find(sub, start, end)
+    res = _find(self, sub, start, end, 1)
     return space.wrap(res)
 
-def str_rfind__String_String_ANY_ANY(space, w_self, w_sub, w_start, w_end):
+def str_rfind__String_String_ANY_ANY(space, w_self, w_sub, w_start=None, w_end=None):
+
     (self, sub, start, end) =  _convert_idx_params(space, w_self, w_sub, w_start, w_end)
-    res = self.rfind(sub, start, end)
+    res = _find(self, sub, start, end, -1)
     return space.wrap(res)
 
-def str_partition__String_String(space, w_self, w_sub):
-    self = w_self._value
-    sub = w_sub._value
-    if not sub:
-        raise OperationError(space.w_ValueError,
-                             space.wrap("empty separator"))
-    pos = self.find(sub)
-    if pos == -1:
-        return space.newtuple([w_self, space.wrap(''), space.wrap('')])
-    else:
-        return space.newtuple([sliced(space, self, 0, pos, w_self),
-                               w_sub,
-                               sliced(space, self, pos+len(sub), len(self),
-                                      w_self)])
-
-def str_rpartition__String_String(space, w_self, w_sub):
-    self = w_self._value
-    sub = w_sub._value
-    if not sub:
-        raise OperationError(space.w_ValueError,
-                             space.wrap("empty separator"))
-    pos = self.rfind(sub)
-    if pos == -1:
-        return space.newtuple([space.wrap(''), space.wrap(''), w_self])
-    else:
-        return space.newtuple([sliced(space, self, 0, pos, w_self),
-                               w_sub,
-                               sliced(space, self, pos+len(sub), len(self), w_self)])
-
+def str_index__String_String_ANY_ANY(space, w_self, w_sub, w_start=None, w_end=None):
 
-def str_index__String_String_ANY_ANY(space, w_self, w_sub, w_start, w_end):
     (self, sub, start, end) =  _convert_idx_params(space, w_self, w_sub, w_start, w_end)
-    res = self.find(sub, start, end)
-    if res < 0:
+    res = _find(self, sub, start, end, 1)
+
+    if res == -1:
         raise OperationError(space.w_ValueError,
                              space.wrap("substring not found in string.index"))
 
     return space.wrap(res)
 
 
-def str_rindex__String_String_ANY_ANY(space, w_self, w_sub, w_start, w_end):
+def str_rindex__String_String_ANY_ANY(space, w_self, w_sub, w_start=None, w_end=None):
+
     (self, sub, start, end) =  _convert_idx_params(space, w_self, w_sub, w_start, w_end)
-    res = self.rfind(sub, start, end)
-    if res < 0:
+    res = _find(self, sub, start, end, -1)
+    if res == -1:
         raise OperationError(space.w_ValueError,
                              space.wrap("substring not found in string.rindex"))
 
     return space.wrap(res)
 
-def _string_replace(space, input, sub, by, maxsplit):
-    if maxsplit == 0:
-        return space.wrap(input)
+
+def str_replace__String_String_String_Int(space, w_self, w_sub, w_by, w_maxsplit=-1):
+    u = space.unwrap
+
+    input = u(w_self)
+    sub = u(w_sub)
+    by = u(w_by)
+    maxsplit = u(w_maxsplit)   #I don't use it now
 
     #print "from replace, input: %s, sub: %s, by: %s" % (input, sub, by)
 
-    if not sub:
-        upper = len(input)
-        if maxsplit > 0 and maxsplit < upper + 2:
-            upper = maxsplit - 1
-            assert upper >= 0
-        substrings_w = [""]
-        for i in range(upper):
-            c = input[i]
-            substrings_w.append(c)
-        substrings_w.append(input[upper:])
-    else:
+    #what do we have to replace?
+    startidx = 0
+    endidx = len(input)
+    indices = []
+    foundidx = _find(input, sub, startidx, endidx, 1)
+    while foundidx > -1 and (maxsplit == -1 or maxsplit > 0):
+        indices.append(foundidx)
+        if len(sub) == 0:
+            #so that we go forward, even if sub is empty
+            startidx = foundidx + 1
+        else: 
+            startidx = foundidx + len(sub)        
+        foundidx = _find(input, sub, startidx, endidx, 1)
+        if maxsplit != -1:
+            maxsplit = maxsplit - 1
+    indiceslen = len(indices)
+    buf = [' '] * (len(input) - indiceslen * len(sub) + indiceslen * len(by))
+    startidx = 0
+
+    #ok, so do it
+    bufpos = 0
+    for i in range(indiceslen):
+        for j in range(startidx, indices[i]):
+            buf[bufpos] = input[j]
+            bufpos = bufpos + 1
+ 
+        for j in range(len(by)):
+            buf[bufpos] = by[j]
+            bufpos = bufpos + 1
+
+        startidx = indices[i] + len(sub)
+
+    for j in range(startidx, len(input)):
+        buf[bufpos] = input[j]
+        bufpos = bufpos + 1 
+    return space.wrap("".join(buf))
+
+def _find(self, sub, start, end, dir):
+
+    length = len(self)
+
+    #adjust_indicies
+    if (end > length):
+        end = length
+    elif (end < 0):
+        end += length
+    if (end < 0):
+        end = 0
+    if (start < 0):
+        start += length
+    if (start < 0):
         start = 0
-        sublen = len(sub)
-        substrings_w = []
 
-        while maxsplit != 0:
-            next = input.find(sub, start)
-            if next < 0:
-                break
-            substrings_w.append(input[start:next])
-            start = next + sublen
-            maxsplit -= 1   # NB. if it's already < 0, it stays < 0
-            
-        substrings_w.append(input[start:])
+    if dir > 0:
+        if len(sub) == 0 and start < end:
+            return start
+
+        end = end - len(sub) + 1
+
+        for i in range(start, end):
+            match = 1
+            for idx in range(len(sub)):
+                if sub[idx] != self[idx+i]:
+                    match = 0
+                    break
+            if match: 
+                return i
+        return -1
+    else:
+        if len(sub) == 0 and start < end:
+            return end
+
+        end = end - len(sub)
+
+        for j in range(end, start-1, -1):
+            match = 1
+            for idx in range(len(sub)):
+                if sub[idx] != self[idx+j]:
+                    match = 0
+                    break
+            if match:
+                return j
+        return -1        
 
-    try:
-        # XXX conservative estimate. If your strings are that close
-        # to overflowing, bad luck.
-        one = ovfcheck(len(substrings_w) * len(by))
-        ovfcheck(one + len(input))
-    except OverflowError:
-        raise OperationError(
-            space.w_OverflowError, 
-            space.wrap("replace string is too long"))
-    
-    return space.wrap(by.join(substrings_w))
-    
-
-def str_replace__String_ANY_ANY_ANY(space, w_self, w_sub, w_by, w_maxsplit):
-    return _string_replace(space, w_self._value, space.buffer_w(w_sub).as_str(),
-                           space.buffer_w(w_by).as_str(),
-                           space.int_w(w_maxsplit))
-
-def str_replace__String_String_String_ANY(space, w_self, w_sub, w_by, w_maxsplit=-1):
-    input = w_self._value
-    sub = w_sub._value
-    by = w_by._value
-    maxsplit = space.int_w(w_maxsplit)
-    return _string_replace(space, input, sub, by, maxsplit)
 
 def _strip(space, w_self, w_chars, left, right):
     "internal function called by str_xstrip methods"
-    u_self = w_self._value
-    u_chars = w_chars._value
+    u_self = space.unwrap(w_self)
+    u_chars = space.unwrap(w_chars)
+    
+    if u_self == None or u_chars == None:
+        return w_self
     
     lpos = 0
     rpos = len(u_self)
@@ -549,113 +545,98 @@
            lpos += 1
        
     if right:
-        while rpos > lpos and u_self[rpos - 1] in u_chars:
+        while rpos > 0 and u_self[rpos - 1] in u_chars:
            rpos -= 1
        
-    assert rpos >= lpos    # annotator hint, don't remove
-    return sliced(space, u_self, lpos, rpos, w_self)
+    return space.wrap(u_self[lpos:rpos])
 
-def _strip_none(space, w_self, left, right):
-    "internal function called by str_xstrip methods"
-    u_self = w_self._value
-    
-    lpos = 0
-    rpos = len(u_self)
-    
-    if left:
-        #print "while %d < %d and -%s- in -%s-:"%(lpos, rpos, u_self[lpos],w_chars)
-        while lpos < rpos and u_self[lpos].isspace():
-           lpos += 1
-       
-    if right:
-        while rpos > lpos and u_self[rpos - 1].isspace():
-           rpos -= 1
-       
-    assert rpos >= lpos    # annotator hint, don't remove
-    return sliced(space, u_self, lpos, rpos, w_self)
 
 def str_strip__String_String(space, w_self, w_chars):
     return _strip(space, w_self, w_chars, left=1, right=1)
 
-def str_strip__String_None(space, w_self, w_chars):
-    return _strip_none(space, w_self, left=1, right=1)
    
 def str_rstrip__String_String(space, w_self, w_chars):
     return _strip(space, w_self, w_chars, left=0, right=1)
 
-def str_rstrip__String_None(space, w_self, w_chars):
-    return _strip_none(space, w_self, left=0, right=1)
-
    
 def str_lstrip__String_String(space, w_self, w_chars):
     return _strip(space, w_self, w_chars, left=1, right=0)
+   
 
-def str_lstrip__String_None(space, w_self, w_chars):
-    return _strip_none(space, w_self, left=1, right=0)
-
-
-
-def str_center__String_ANY_ANY(space, w_self, w_arg, w_fillchar):
-    u_self = w_self._value
-    u_arg  = space.int_w(w_arg)
-    fillchar = space.str_w(w_fillchar)
-    if len(fillchar) != 1:
-        raise OperationError(space.w_TypeError,
-            space.wrap("center() argument 2 must be a single character"))
+def str_center__String_Int(space, w_self, w_arg):
+    u_self = space.unwrap(w_self)
+    u_arg  = space.unwrap(w_arg)
 
     d = u_arg - len(u_self) 
     if d>0:
-        offset = d//2 + (d & u_arg & 1)
-        fillchar = fillchar[0]    # annotator hint: it's a single character
-        u_centered = offset * fillchar + u_self + (d - offset) * fillchar
+        offset = d//2
+        u_centered = offset * ' ' + u_self + (d - offset) * ' ' 
     else:
         u_centered = u_self
 
-    return wrapstr(space, u_centered)
-
+    return W_StringObject(space, u_centered)
+      
+      
 def str_count__String_String_ANY_ANY(space, w_self, w_arg, w_start, w_end): 
-    u_self, u_arg, u_start, u_end = _convert_idx_params(space, w_self, w_arg,
-                                                        w_start, w_end)
-    return wrapint(space, u_self.count(u_arg, u_start, u_end))
-
-def str_endswith__String_String_ANY_ANY(space, w_self, w_suffix, w_start, w_end):
-    (u_self, suffix, start, end) = _convert_idx_params(space, w_self,
-                                                       w_suffix, w_start,
-                                                       w_end, True)
-    return space.newbool(stringendswith(u_self, suffix, start, end))
-
-def str_endswith__String_Tuple_ANY_ANY(space, w_self, w_suffixes, w_start, w_end):
-    (u_self, _, start, end) = _convert_idx_params(space, w_self,
-                                                  space.wrap(''), w_start,
-                                                  w_end, True)
-    for w_suffix in space.viewiterable(w_suffixes):
-        if space.is_true(space.isinstance(w_suffix, space.w_unicode)):
-            w_u = space.call_function(space.w_unicode, w_self)
-            return space.call_method(w_u, "endswith", w_suffixes, w_start,
-                                     w_end)
-        suffix = space.str_w(w_suffix) 
-        if stringendswith(u_self, suffix, start, end):
-            return space.w_True
-    return space.w_False
+    u_self  = space.unwrap(w_self)
+    u_arg   = space.unwrap(w_arg)
+    u_start = space.unwrap(w_start)
+    u_end   = space.unwrap(w_end)
+    
+    
+    if u_end == None: 
+        u_end = len(u_self)
+    elif u_end < 0:
+        u_end += len(u_self)
+    
+    if u_start == None: u_start = 0
+    
+    area =  u_self [u_start:u_end]
+    
+    count = 0  
+
+    pos = -1
+    while 1: 
+       pos = _find(area, u_arg, pos+1, u_end, 1)
+       #pos = area.find(u_arg, pos+1, u_end)
+       if pos == -1:
+          break
+       count += 1
+       
+    return W_IntObject(space, count)
 
-def str_startswith__String_String_ANY_ANY(space, w_self, w_prefix, w_start, w_end):
-    (u_self, prefix, start, end) = _convert_idx_params(space, w_self,
-                                                       w_prefix, w_start,
-                                                       w_end, True)
-    return space.newbool(stringstartswith(u_self, prefix, start, end))
-
-def str_startswith__String_Tuple_ANY_ANY(space, w_self, w_prefixes, w_start, w_end):
-    (u_self, _, start, end) = _convert_idx_params(space, w_self, space.wrap(''),
-                                                  w_start, w_end, True)
-    for w_prefix in space.viewiterable(w_prefixes):
-        if space.is_true(space.isinstance(w_prefix, space.w_unicode)):
-            w_u = space.call_function(space.w_unicode, w_self)
-            return space.call_method(w_u, "startswith", w_prefixes, w_start,
-                                     w_end)
-        prefix = space.str_w(w_prefix)
-        if stringstartswith(u_self, prefix, start, end):
-            return space.w_True
-    return space.w_False
+
+#[optional arguments not supported now]    
+def str_endswith__String_String(space, w_self, w_end): 
+    u_self = space.unwrap(w_self)
+    u_end  = space.unwrap(w_end)
+    
+    found = 0
+    if u_end:
+        endlen = len(u_end)
+        if endlen <= len(u_self):
+           found = (u_end == u_self[-endlen:]) 
+    else:
+        found = 1
+        
+    return W_IntObject(space, found)
+    
+    
+#[optional arguments not supported now]    
+def str_startswith__String_String(space, w_self, w_start): 
+    u_self = space.unwrap(w_self)
+    u_start  = space.unwrap(w_start)
+    
+    found = 0
+    if u_start:
+        startlen = len(u_start)
+        if startlen <= len(u_self):
+           found = (u_start == u_self[:startlen]) 
+    else:
+        found = 1
+        
+    return W_IntObject(space, found)    
+    
     
 def _tabindent(u_token, u_tabsize):
     "calculates distance behind the token to the next tabstop"
@@ -683,13 +664,13 @@
     return distance    
     
     
-def str_expandtabs__String_ANY(space, w_self, w_tabsize):   
-    u_self = w_self._value
-    u_tabsize  = space.int_w(w_tabsize)
+def str_expandtabs__String_Int(space, w_self, w_tabsize):   
+    u_self = space.unwrap(w_self)
+    u_tabsize  = space.unwrap(w_tabsize)
     
     u_expanded = ""
     if u_self:
-        split = u_self.split("\t")
+        split = u_self.split("\t") #XXX use pypy split
         u_expanded =oldtoken = split.pop(0)
 
         for token in split:  
@@ -697,40 +678,37 @@
             u_expanded += " " * _tabindent(oldtoken,u_tabsize) + token
             oldtoken = token
             
-    return wrapstr(space, u_expanded)        
+    return W_StringObject(space, u_expanded)        
  
  
-def str_splitlines__String_ANY(space, w_self, w_keepends):
-    u_keepends  = space.int_w(w_keepends)  # truth value, but type checked
-    data = w_self._value
-    selflen = len(data)
-    strs_w = []
-    i = j = 0
-    while i < selflen:
-        # Find a line and append it
-        while i < selflen and data[i] != '\n' and data[i] != '\r':
-            i += 1
-        # Skip the line break reading CRLF as one line break
-        eol = i
-        i += 1
-        if i < selflen and data[i-1] == '\r' and data[i] == '\n':
-            i += 1
-        if u_keepends:
-            eol = i
-        strs_w.append(sliced(space, data, j, eol, w_self))
-        j = i
-
-    if j < selflen:
-        strs_w.append(sliced(space, data, j, len(data), w_self))
-    return space.newlist(strs_w)
-
-def str_zfill__String_ANY(space, w_self, w_width):
-    input = w_self._value
-    width = space.int_w(w_width)
+def str_splitlines__String_Int(space, w_self, w_keepends):
+    u_self = space.unwrap(w_self)
+    u_keepends  = space.unwrap(w_keepends)
+    selflen = len(u_self)
+    
+    L = []
+    pos = 0
+    while 1:
+        oldpos = pos
+        pos = _find(u_self, '\n', pos, selflen, 1) + 1
+        if pos  > oldpos:
+            w_item = space.wrap(u_self[oldpos:pos])
+            if not u_keepends:
+                w_item = _strip(space, w_item, W_StringObject(space,'\n'), left=0, right=1)
+            L.append(w_item)
+        else:
+            break    
+    return W_ListObject(space, L)
+
+def str_zfill__String_Int(space, w_self, w_width):
+    u = space.unwrap
+    input = u(w_self)
+    width = u(w_width)
 
     if len(input) >= width:
-        # cannot return w_self, in case it is a subclass of str
-        return space.wrap(input)
+        return w_self
+
+    b = width - len(input)
 
     buf = [' '] * width
     if len(input) > 0 and (input[0] == '+' or input[0] == '-'):
@@ -749,256 +727,285 @@
         start = start + 1
     
     return space.wrap("".join(buf))
+    
+    
+def app_str_translate__String_String_String(s, table, deletechars=''):
+    """charfilter - unicode handling is not implemented
+    
+    Return a copy of the string where all characters occurring 
+    in the optional argument deletechars are removed, and the 
+    remaining characters have been mapped through the given translation table, 
+    which must be a string of length 256"""
+
+    if len(table) < 256:
+        raise ValueError("translation table must be 256 characters long")
 
-def str_w__String(space, w_str):
+    L =  [ table[ord(s[i])] for i in range(len(s)) if s[i] not in deletechars ]
+    return ''.join(L)
+
+str_translate__String_String_String = gateway.app2interp(app_str_translate__String_String_String)
+
+    
+def unwrap__String(space, w_str):
     return w_str._value
 
 def hash__String(space, w_str):
-    s = w_str._value
-    if we_are_translated():
-        x = hash(s)            # to use the hash cache in rpython strings
+    return W_IntObject(space, hash(space.unwrap(w_str)))
+
+
+EQ = 1
+LE = 2
+GE = 3
+GT = 4
+LT = 5
+NE = 6
+
+
+def string_richcompare(space, w_str1, w_str2, op):
+    u = space.unwrap
+    str1 = u(w_str1)
+    str2 = u(w_str2)
+
+    if space.is_true(space.is_(w_str1, w_str2)):
+        if op == EQ or op == LE or op == GE:
+            return space.w_True
+        elif op == GT or op == LT or op == NE:
+            return space.w_False
+    if 0:
+        pass
     else:
-        x = _hash_string(s)    # to make sure we get the same hash as rpython
-        # (otherwise translation will freeze W_DictObjects where we can't find
-        #  the keys any more!)
-    return wrapint(space, x)
+        if op == EQ:
+            if len(str1) == len(str2):
+                for i in range(len(str1)):
+                    if ord(str1[i]) != ord(str2[i]):
+                        return space.w_False
+                return space.w_True
+            else:
+                return space.w_False
+        else:
+            if len(str1) > len(str2):
+                min_len = len(str2)
+            else:
+                min_len = len(str1)
+
+            c = 0
+            idx = 0
+            if (min_len > 0):
+                while (c == 0) and (idx < min_len):
+                    c = ord(str1[idx]) - ord(str2[idx])
+                    idx = idx + 1
+            else:
+                c = 0
+
+        if (c == 0):
+            if len(str1) < len(str2):
+                c = -1
+            elif len(str1) > len(str2):
+                c = 1
+            else:
+                c = 0
+
+        if op == LT:
+            return space.newbool(c < 0)
+        elif op == LE:
+            return space.newbool(c <= 0)
+        elif op == NE:
+            return space.newbool(c != 0)
+        elif op == GT:
+            return space.newbool(c > 0)
+        elif op == GE:
+            return space.newbool(c >= 0)
+        else:
+            return NotImplemented
 
 def lt__String_String(space, w_str1, w_str2):
-    s1 = w_str1._value
-    s2 = w_str2._value
-    if s1 < s2:
-        return space.w_True
-    else:
-        return space.w_False    
+    return string_richcompare(space, w_str1, w_str2, LT)
 
 def le__String_String(space, w_str1, w_str2):
-    s1 = w_str1._value
-    s2 = w_str2._value
-    if s1 <= s2:
-        return space.w_True
-    else:
-        return space.w_False
+    return string_richcompare(space, w_str1, w_str2, LE)
 
 def eq__String_String(space, w_str1, w_str2):
-    s1 = w_str1._value
-    s2 = w_str2._value
-    if s1 == s2:
-        return space.w_True
-    else:
-        return space.w_False
+    return string_richcompare(space, w_str1, w_str2, EQ)
 
 def ne__String_String(space, w_str1, w_str2):
-    s1 = w_str1._value
-    s2 = w_str2._value
-    if s1 != s2:
-        return space.w_True
-    else:
-        return space.w_False
+    return string_richcompare(space, w_str1, w_str2, NE)
 
 def gt__String_String(space, w_str1, w_str2):
-    s1 = w_str1._value
-    s2 = w_str2._value
-    if s1 > s2:
-        return space.w_True
-    else:
-        return space.w_False
+    return string_richcompare(space, w_str1, w_str2, GT)
 
 def ge__String_String(space, w_str1, w_str2):
-    s1 = w_str1._value
-    s2 = w_str2._value
-    if s1 >= s2:
-        return space.w_True
-    else:
-        return space.w_False
+    return string_richcompare(space, w_str1, w_str2, GE)
 
-def getitem__String_ANY(space, w_str, w_index):
-    ival = space.getindex_w(w_index, space.w_IndexError, "string index")
-    str = w_str._value
-    slen = len(str)
+def getitem__String_Int(space, w_str, w_int):
+    u = space.unwrap
+    ival = w_int.intval
+    str = u(w_str)
+    slen = len(u(w_str))
     if ival < 0:
         ival += slen
     if ival < 0 or ival >= slen:
         exc = space.call_function(space.w_IndexError,
                                   space.wrap("string index out of range"))
         raise OperationError(space.w_IndexError, exc)
-    return wrapchar(space, str[ival])
+    return W_StringObject(space, str[ival])
 
 def getitem__String_Slice(space, w_str, w_slice):
+    # XXX this is really too slow for slices with no step argument
     w = space.wrap
-    s = w_str._value
-    length = len(s)
-    start, stop, step, sl = w_slice.indices4(space, length)
-    if sl == 0:
-        return W_StringObject.EMPTY
-    elif step == 1:
-        assert start >= 0 and stop >= 0
-        return sliced(space, s, start, stop, w_str)
-    else:
-        str = "".join([s[start + i*step] for i in range(sl)])
-    return wrapstr(space, str)
+    length = len(w_str._value)
+    start, stop, step, sl = slicetype.indices4(space, w_slice, length)
+    r = [space.getitem(w_str, w(start + i*step)) for i in range(sl)]
+    w_r = space.newlist(r)
+    w_empty = space.newstring([])
+    return str_join__String_ANY(space, w_empty, w_r)
+
+def mul__String_Int(space, w_str, w_mul):
+    u = space.unwrap
+    input = u(w_str)
+    mul = u(w_mul)
+
+    buffer = [' '] * (mul*len(input))
+
+    pos = 0
+    for i in range(mul):
+        for j in range(len(input)):
+            buffer[pos] = input[j]
+            pos = pos + 1
 
-def getslice__String_ANY_ANY(space, w_str, w_start, w_stop):
-    s = w_str._value
-    start, stop = normalize_simple_slice(space, len(s), w_start, w_stop)
-    if start == stop:
-        return W_StringObject.EMPTY
-    else:
-        return sliced(space, s, start, stop, w_str)
-
-def mul_string_times(space, w_str, w_times):
-    try:
-        mul = space.getindex_w(w_times, space.w_OverflowError)
-    except OperationError, e:
-        if e.match(space, space.w_TypeError):
-            raise FailedToImplement
-        raise
-    if mul <= 0:
-        return W_StringObject.EMPTY
-    input = w_str._value
-    input_len = len(input)
-    try:
-        buflen = ovfcheck(mul * input_len)
-    except OverflowError:
-        raise OperationError(
-            space.w_OverflowError, 
-            space.wrap("repeated string is too long: %d %d" % (input_len, mul)))
-    # XXX maybe only do this when input has a big length
-    return joined(space, [input] * mul)
-
-def mul__String_ANY(space, w_str, w_times):
-    return mul_string_times(space, w_str, w_times)
-
-def mul__ANY_String(space, w_times, w_str):
-    return mul_string_times(space, w_str, w_times)
+    return space.wrap("".join(buffer))
 
 def add__String_String(space, w_left, w_right):
-    right = w_right._value
-    left = w_left._value
-    return joined2(space, left, right)
+    u = space.unwrap
+    right = u(w_right)
+    left = u(w_left)
+    buf = [' '] * (len(left) + len(right))
+    for i in range(len(left)):
+        buf[i] = left[i]
+    for i in range(len(right)):
+        buf[i+len(left)] = right[i]
+    return space.wrap("".join(buf))
+
+def mod_str_tuple(space, w_format, w_args):
+    # XXX implement me
+    format = space.unwrap(w_format)
+    args = space.unwrap(w_args)
+    try:
+        s = format % args
+    except TypeError, e:
+        raise OperationError(space.w_TypeError, space.wrap(str(e)))
+    except ValueError, e:
+        raise OperationError(space.w_ValueError, space.wrap(str(e)))
+    return space.wrap(s)
 
 def len__String(space, w_str):
-    return space.wrap(len(w_str._value))
+    return space.wrap(len(space.unwrap(w_str)))
 
 def str__String(space, w_str):
-    if type(w_str) is W_StringObject:
-        return w_str
-    return wrapstr(space, w_str._value)
-
-def iter__String(space, w_list):
-    from pypy.objspace.std import iterobject
-    return iterobject.W_SeqIterObject(w_list)
-
-def ord__String(space, w_str):
-    u_str = w_str._value
-    if len(u_str) != 1:
-        raise OperationError(
-            space.w_TypeError,
-            space.wrap("ord() expected a character, but string "
-                       "of length %d found"%(len(w_str._value),)))
-    return space.wrap(ord(u_str))
+    return w_str
 
-def getnewargs__String(space, w_str):
-    return space.newtuple([wrapstr(space, w_str._value)])
 
-def repr__String(space, w_str):
-    s = w_str._value
+def iter__String(space, w_list):
+    import iterobject
+    return iterobject.W_SeqIterObject(space, w_list)
 
-    buf = StringBuilder(50)
 
+def app_repr__String(s):
     quote = "'"
     if quote in s and '"' not in s:
         quote = '"'
 
-    buf.append(quote)
-    startslice = 0
+    repr = quote
 
-    for i in range(len(s)):
-        c = s[i]
-        use_bs_char = False # character quoted by backspace
-
-        if c == '\\' or c == quote:
-            bs_char = c
-            use_bs_char = True
-        elif c == '\t':
-            bs_char = 't'
-            use_bs_char = True
-        elif c == '\r':
-            bs_char = 'r'
-            use_bs_char = True
-        elif c == '\n':
-            bs_char = 'n'
-            use_bs_char = True
+    for c in s:
+        if c == '\\' or c == quote: repr += '\\'+c
+        elif c == '\t': repr += '\\t'
+        elif c == '\r': repr += '\\r'
+        elif c == '\n': repr += '\\n'
         elif not '\x20' <= c < '\x7f':
             n = ord(c)
-            if i != startslice:
-                buf.append_slice(s, startslice, i)
-            startslice = i + 1
-            buf.append('\\x')
-            buf.append("0123456789abcdef"[n>>4])
-            buf.append("0123456789abcdef"[n&0xF])
-
-        if use_bs_char:
-            if i != startslice:
-                buf.append_slice(s, startslice, i)
-            startslice = i + 1
-            buf.append('\\')
-            buf.append(bs_char)
+            repr += '\\x'+"0123456789abcdef"[n>>4]+"0123456789abcdef"[n&0xF]
+        else:
+            repr += c
 
-    if len(s) != startslice:
-        buf.append_slice(s, startslice, len(s))
+    repr += quote
 
-    buf.append(quote)
+    return repr
 
-    return space.wrap(buf.build())
+repr__String = gateway.app2interp(app_repr__String)
 
-   
-def str_translate__String_ANY_ANY(space, w_string, w_table, w_deletechars=''):
-    """charfilter - unicode handling is not implemented
     
-    Return a copy of the string where all characters occurring 
-    in the optional argument deletechars are removed, and the 
-    remaining characters have been mapped through the given translation table, 
-    which must be a string of length 256"""
+def ord__String(space, w_str):
+    return space.wrap(ord(space.unwrap(w_str)))
+
+def mod__String_ANY(space, w_str, w_item):
+    return mod__String_Tuple(space, w_str, space.newtuple([w_item]))
+
+def app_mod__String_ANY(format, values):
+    pieces = []
+    start = 0
+    state = 0
+    i = 0 
+    index = -1
+    len_format = len(format) 
+    while i < len_format: 
+        c = format[i]
+        if state == 0:
+            # just copy constant-pieces of the format
+            if c=='%':
+                pieces.append(format[start:i])
+                state = 1
+        else:
+            if c=='%':
+                pieces.append('%')
+            else:
+                if c == '(':
+                    # read name 
+                    j = format.find(')', i+1)
+                    if j == -1:
+                        raise ValueError, "incomplete format string"
+                    if index >= 0:
+                        raise TypeError, "format string mismatch"
+                    name = format[i+1:j]
+                    value = values[name]
+                    index = -2 
+                    i = j+1
+                    c = format[i]
+                else:
+                    index += 1
+                    if index < 0:
+                        raise TypeError, "format string mismatch"
+                    elif index == 0 and not isinstance(values, tuple):
+                        values = tuple([values])
+                    try:
+                        value = values[index]
+                    except IndexError:
+                        raise TypeError, "not enough arguments for format string"
+                 
+                if c=='s':
+                    pieces.append(str(value)) 
+                elif c=='d':
+                    pieces.append(str(int(value)))
+                elif c=='x':
+                    pieces.append(hex(int(value)))
+                elif c=='r':
+                    pieces.append(repr(value))
+                else:
+                    raise ValueError, "unsupported format character '%s' (%x) at index %d" % (
+                            c, ord(c), i)
+            state = 0
+            start = i+1
+        i += 1
+
+    if state == 1:
+        raise ValueError, "incomplete format"
+    if index >= 0 and index < len(values) - 1:
+        raise TypeError, 'not all arguments converted during string formatting'
+    pieces.append(format[start:])
+    return ''.join(pieces)
+
+mod__String_ANY = gateway.app2interp(app_mod__String_ANY) 
+
+# register all methods 
+register_all(vars(), W_StringType)
+
 
-    # XXX CPython accepts buffers, too, not sure what we should do
-    table = space.str_w(w_table)
-    if len(table) != 256:
-        raise OperationError(
-            space.w_ValueError,
-            space.wrap("translation table must be 256 characters long"))
-
-    string = w_string._value
-    chars = []
-    for char in string:
-        w_char = W_StringObject.PREBUILT[ord(char)]
-        if not space.is_true(space.contains(w_deletechars, w_char)):
-             chars.append(table[ord(char)])
-    return W_StringObject(''.join(chars))
-
-def str_decode__String_ANY_ANY(space, w_string, w_encoding=None, w_errors=None):
-    from pypy.objspace.std.unicodetype import _get_encoding_and_errors, \
-        unicode_from_string, decode_object
-    encoding, errors = _get_encoding_and_errors(space, w_encoding, w_errors)
-    if encoding is None and errors is None:
-        return unicode_from_string(space, w_string)
-    return decode_object(space, w_string, encoding, errors)
-
-def str_encode__String_ANY_ANY(space, w_string, w_encoding=None, w_errors=None):
-    from pypy.objspace.std.unicodetype import _get_encoding_and_errors, \
-        encode_object
-    encoding, errors = _get_encoding_and_errors(space, w_encoding, w_errors)
-    return encode_object(space, w_string, encoding, errors)
-
-# CPython's logic for deciding if  ""%values  is
-# an error (1 value, 0 %-formatters) or not
-# (values is of a mapping type)
-def mod__String_ANY(space, w_format, w_values):
-    return mod_format(space, w_format, w_values, do_unicode=False)
-
-def buffer__String(space, w_string):
-    from pypy.interpreter.buffer import StringBuffer
-    return space.wrap(StringBuffer(w_string._value))
-
-# register all methods
-from pypy.objspace.std import stringtype
-register_all(vars(), stringtype)

Modified: pypy/branch/avm/pypy/objspace/std/test/test_multimethod.py
==============================================================================
--- pypy/branch/avm/pypy/objspace/std/test/test_multimethod.py	(original)
+++ pypy/branch/avm/pypy/objspace/std/test/test_multimethod.py	Thu Nov  5 20:27:32 2009
@@ -1,250 +1,149 @@
-from py.test import raises
+import autopath
 
-from pypy.objspace.std import multimethod
-from pypy.objspace.std.multimethod import FailedToImplement
+from pypy.objspace.std.multimethod import *
+from pypy.tool import testit
 
+BoundMultiMethod.ASSERT_BASE_TYPE = object
 
-class W_Root(object):
-    pass
 
-class W_IntObject(W_Root):
-    pass
-
-class W_BoolObject(W_Root):
-    pass
-
-class W_StringObject(W_Root):
-    pass
-
-def delegate_b2i(space, w_x):
-    assert isinstance(w_x, W_BoolObject)
-    return W_IntObject()
-
-def add__Int_Int(space, w_x, w_y):
-    assert space == 'space'
-    assert isinstance(w_x, W_IntObject)
-    assert isinstance(w_y, W_IntObject)
-    return 'fine'
-
-
-class TestMultiMethod1:
-    Installer = multimethod.InstallerVersion1
-
-    def setup_class(cls):
-        cls.prev_installer = multimethod.Installer
-        multimethod.Installer = cls.Installer
-        add = multimethod.MultiMethodTable(2, root_class=W_Root,
-                                           argnames_before=['space'])
-        add.register(add__Int_Int, W_IntObject, W_IntObject)
-        typeorder = {
-            W_IntObject: [(W_IntObject, None), (W_Root, None)],
-            W_BoolObject: [(W_BoolObject, None), (W_IntObject, delegate_b2i),
-                           (W_Root, None)],
-            W_StringObject: [(W_StringObject, None), (W_Root, None)],
-            }
-        cls.typeorder = typeorder
-        cls.add = add
-        cls.add1 = staticmethod(add.install('__add', [typeorder, typeorder]))
-
-    def teardown_class(cls):
-        multimethod.Installer = cls.prev_installer
-
-    def test_simple(self):
-        space = 'space'
-        w_x = W_IntObject()
-        w_y = W_IntObject()
-        assert self.add1(space, w_x, w_y) == 'fine'
-
-    def test_failtoimplement(self):
-        space = 'space'
-        w_x = W_IntObject()
-        w_s = W_StringObject()
-        raises(FailedToImplement, "self.add1(space, w_x, w_s)")
-        raises(FailedToImplement, "self.add1(space, w_s, w_x)")
-
-    def test_delegate(self):
-        space = 'space'
-        w_x = W_IntObject()
-        w_s = W_StringObject()
-        w_b = W_BoolObject()
-        assert self.add1(space, w_x, w_b) == 'fine'
-        assert self.add1(space, w_b, w_x) == 'fine'
-        assert self.add1(space, w_b, w_b) == 'fine'
-        raises(FailedToImplement, "self.add1(space, w_b, w_s)")
-        raises(FailedToImplement, "self.add1(space, w_s, w_b)")
-
-    def test_not_baked(self):
-        typeorder = self.typeorder
-        add2 = self.add.install('__add2', [typeorder, typeorder],
-                                baked_perform_call=False)
-        assert add2[0] == ['space', 'arg0', 'arg1']
-        if multimethod.Installer is multimethod.InstallerVersion1:
-            assert add2[1] == 'arg0.__add2(space, arg1)'
-        assert isinstance(add2[2], dict)
-        assert not add2[3]
-
-    def test_empty(self):
-        add3_installer = multimethod.Installer(self.add, '__add3', [{},{}])
-        assert add3_installer.is_empty()
-        if multimethod.Installer is multimethod.InstallerVersion1:
-            assert len(add3_installer.to_install) == 1
-            assert add3_installer.to_install[0][0] is None
-
-    def test_empty_direct(self):
-        assert not self.add.install_if_not_empty('__add4', [{},{}])
-
-    def test_empty_not_baked(self):
-        add5_installer = multimethod.Installer(self.add, '__add5', [{},{}],
-                                               baked_perform_call=False)
-        assert add5_installer.is_empty()
-        if multimethod.Installer is multimethod.InstallerVersion1:
-            assert len(add5_installer.to_install) == 0
-        add5 = add5_installer.install()
-        assert add5[0] == ['space', 'arg0', 'arg1']
-        assert add5[1] == 'raiseFailedToImplement()'
-        assert isinstance(add5[2], dict)
-        assert add5[3]
-
-    def test_mmdispatcher(self):
-        typeorder = self.typeorder
-        add2 = multimethod.MMDispatcher(self.add, [typeorder, typeorder])
-        space = 'space'
-        w_x = W_IntObject()
-        w_s = W_StringObject()
-        w_b1 = W_BoolObject()
-        w_b2 = W_BoolObject()
-        assert add2(space, w_x, w_b1) == 'fine'
-        assert add2(space, w_b2, w_x) == 'fine'
-        assert add2(space, w_b1, w_b2) == 'fine'
-        raises(FailedToImplement, "add2(space, w_b2, w_s)")
-        raises(FailedToImplement, "add2(space, w_s, w_b1)")
-
-    def test_forbidden_subclasses(self):
-        mul = multimethod.MultiMethodTable(2, root_class=W_Root,
-                                           argnames_before=['space'])
-        class UserW_StringObject(W_StringObject):
-            pass
-        def mul__Int_String(space, w_x, w_y):
-            assert space == 'space'
-            assert isinstance(w_x, W_IntObject)
-            assert isinstance(w_y, W_StringObject)
-            return 'fine'
-        mul.register(mul__Int_String, W_IntObject, W_StringObject)
-
-        mul1 = mul.install('__mul1', [self.typeorder, self.typeorder])
-        assert mul1('space', W_IntObject(), W_StringObject()) == 'fine'
-        assert mul1('space', W_IntObject(), UserW_StringObject()) == 'fine'
-
-        ext_typeorder = self.typeorder.copy()
-        ext_typeorder[UserW_StringObject] = []
-        mul2 = mul.install('__mul2', [ext_typeorder, ext_typeorder])
-        assert mul2('space', W_IntObject(), W_StringObject()) == 'fine'
-        raises(FailedToImplement,
-               mul2, 'baz', W_IntObject(), UserW_StringObject())
-
-    def test_more_forbidden_subclasses(self):
-        mul = multimethod.MultiMethodTable(2, root_class=W_Root,
-                                           argnames_before=['space'])
-        class UserW_StringObject(W_StringObject):
-            pass
-        def mul__String_String(space, w_x, w_y):
-            assert space == 'space'
-            assert isinstance(w_x, W_StringObject)
-            assert isinstance(w_y, W_StringObject)
-            return 'fine'
-        mul.register(mul__String_String, W_StringObject, W_StringObject)
-
-        ext_typeorder = {W_StringObject: [(W_StringObject, None)],
-                         UserW_StringObject: []}
-        mul2 = mul.install('__mul2', [ext_typeorder, ext_typeorder])
-        assert mul2('space', W_StringObject(), W_StringObject()) == 'fine'
-        raises(FailedToImplement,
-               mul2, 'baz', W_StringObject(), UserW_StringObject())
-        raises(FailedToImplement,
-               mul2, 'baz', UserW_StringObject(), W_StringObject())
-        raises(FailedToImplement,
-               mul2, 'baz', UserW_StringObject(), UserW_StringObject())
-
-    def test_ANY(self):
-        setattr = multimethod.MultiMethodTable(3, root_class=W_Root,
-                                           argnames_before=['space'])
-        def setattr__Int_ANY_ANY(space, w_x, w_y, w_z):
-            assert space == 'space'
-            assert isinstance(w_x, W_IntObject)
-            assert isinstance(w_y, W_Root)
-            assert isinstance(w_z, W_Root)
-            return w_y.__class__.__name__ + w_z.__class__.__name__
-        setattr.register(setattr__Int_ANY_ANY, W_IntObject, W_Root, W_Root)
-        setattr1 = setattr.install('__setattr1', [self.typeorder]*3)
-        for cls1 in self.typeorder:
-            for cls2 in self.typeorder:
-                assert setattr1('space', W_IntObject(), cls1(), cls2()) == (
-                    cls1.__name__ + cls2.__name__)
-
-    def test_all_cases(self):
-        import random
-        space = 'space'
-        w_x = W_IntObject()
-        w_x.expected = [W_IntObject, W_Root]
-        w_s = W_StringObject()
-        w_s.expected = [W_StringObject, W_Root]
-        w_b = W_BoolObject()
-        w_b.expected = [W_BoolObject, W_IntObject, W_Root]
-
-        def test(indices):
-            sub = multimethod.MultiMethodTable(2, root_class=W_Root,
-                                               argnames_before=['space'])
-            def addimpl(cls1, cls2):
-                token = random.random()
-                def sub__cls1_cls2(space, w_x, w_y):
-                    assert space == 'space'
-                    assert isinstance(w_x, cls1)
-                    assert isinstance(w_y, cls2)
-                    return token
-                sub.register(sub__cls1_cls2, cls1, cls2)
-                return token
-
-            def check(w1, w2):
-                try:
-                    res = sub1(space, w1, w2)
-                except FailedToImplement:
-                    res = FailedToImplement
-                for cls1 in w1.expected:
-                    for cls2 in w2.expected:
-                        if (cls1, cls2) in expected:
-                            assert res == expected[cls1, cls2]
-                            return
-                else:
-                    assert res is FailedToImplement
-
-            random.shuffle(indices)
-            expected = {}
-            for index in indices:
-                cls1, cls2 = choices[index]
-                token = addimpl(cls1, cls2)
-                expected[cls1, cls2] = token
-
-            typeorder = self.typeorder
-            sub1 = sub.install('__sub', [typeorder, typeorder])
-            for w1 in [w_x, w_s, w_b]:
-                for w2 in [w_x, w_s, w_b]:
-                    check(w1, w2)
-
-        classes = [W_Root, W_StringObject, W_IntObject, W_BoolObject]
-        choices = [(cls1, cls2) for cls1 in classes
-                                for cls2 in classes]
-        # each choice is a pair of classes which can be implemented or
-        # not by the multimethod 'sub'.  Test all combinations that
-        # involve at most three implemented choices.
-        for i in range(len(choices)):
-            test([i])
-            for j in range(i+1, len(choices)):
-                test([i, j])
-                for k in range(j+1, len(choices)):
-                    test([i, j, k])
-                    #for l in range(k+1, len(choices)):  -- for a 4th choice
-                    #    test([i, j, k, l])              -- (takes a while)
+class X:
+    def __init__(self, value):
+        self.value = value
+    def __repr__(self):
+        return '<X %r>' % self.value
+
+def from_y_to_x(space, yinstance):
+    return X(yinstance)
+
+from_y_to_x.result_class = X
+from_y_to_x.priority = 2
+
+def from_x_to_str(space, xinstance):
+    #if xinstance.value:
+    return w('!' + repr(xinstance.value))
+    #else:
+    #    return []
+
+from_x_to_str.result_class = str
+from_x_to_str.priority = 2
+
+
+class Y:
+    def __init__(self, value):
+        self.value = value
+    def __repr__(self):
+        return '<Y %r>' % self.value
+    def __nonzero__(self):
+        return self.value != 666
+
+
+def add_x_x(space, x1, x2):
+    return "add_x_x", x1, x2
+
+def add_x_y(space, x1, y2):
+    if x1.value < 0:
+        raise FailedToImplement(ValueError, 'not good')
+    return "add_x_y", x1, y2
+
+def add_y_y(space, y1, y2):
+    return "add_y_y", y1, y2
+
+def add_string_string(space, x, y):
+    return "add_string_string", x, y
+
+def add_int_string(space, x, y):
+    return "add_int_string", x, y
+
+def add_int_any(space, y1, o2):
+    return "add_int_any", y1, o2
+
+class FakeObjSpace:
+    add = MultiMethod('+', 2, [])
+    add.register(add_x_x,           X,   X)
+    add.register(add_x_y,           X,   Y)
+    add.register(add_y_y,           Y,   Y)
+    add.register(add_string_string, str, str)
+    add.register(add_int_string,    int, str)
+    add.register(add_int_any,       int, object)
+
+    delegate = DelegateMultiMethod()
+    delegate.register(from_y_to_x,    Y)
+    delegate.register(from_x_to_str,  X)
+    
+    def wrap(self, x):
+        return '<wrapped %r>' % (x,)
+    w_TypeError = 'w_TypeError'
+
+##def w(x, cache={}):
+##    if type(x) in cache:
+##        Stub = cache[type(x)]
+##    else:
+##        Stub = type(type(x))('%s_stub' % type(x).__name__, (type(x),), {})
+##        Stub.dispatchclass = Stub
+##        cache[type(x)] = Stub
+##    return Stub(x)
+
+##X.dispatchclass = X
+##Y.dispatchclass = Y
+
+def w(x):
+    return x
+
+
+class TestMultiMethod(testit.TestCase):
+    def setUp(self):
+        # only run when testing stdobjectspace 
+        #XXX removed: testit.objspace('std')
+        self.space = FakeObjSpace()
+
+    def test_non_delegate(self):
+        space = self.space
+        
+        r = space.add(X(2), X(5))
+        self.assertEquals(repr(r), "('add_x_x', <X 2>, <X 5>)")
+        
+        r = space.add(X(3), Y(4))
+        self.assertEquals(repr(r), "('add_x_y', <X 3>, <Y 4>)")
+
+        r = space.add(Y(0), Y(20))
+        self.assertEquals(repr(r), "('add_y_y', <Y 0>, <Y 20>)")
+
+        r = space.add(w(-3), w([7,6,5]))
+        self.assertEquals(repr(r), "('add_int_any', -3, [7, 6, 5])")
+
+        r = space.add(w(5), w("test"))
+        self.assertEquals(repr(r), "('add_int_string', 5, 'test')")
+
+        r = space.add(w("x"), w("y"))
+        self.assertEquals(repr(r), "('add_string_string', 'x', 'y')")
+        
+    def test_delegate_y_to_x(self):
+        space = self.space
+        r = space.add(Y(-1), X(7))
+        self.assertEquals(repr(r), "('add_x_x', <X <Y -1>>, <X 7>)")
+        
+        r = space.add(Y(1), X(7))
+        self.assertEquals(repr(r), "('add_x_x', <X <Y 1>>, <X 7>)")
+        
+        r = space.add(X(-3), Y(20))
+        self.assertEquals(repr(r), "('add_x_x', <X -3>, <X <Y 20>>)")
+       
+    def test_no_operation_defined(self):
+        space = self.space
+        self.assertRaises(OperationError, space.add, w([3]), w(4))
+        self.assertRaises(OperationError, space.add, w(3.0), w('bla'))
+        #self.assertRaises(OperationError, space.add, X(0), w("spam"))
+        #self.assertRaises(OperationError, space.add, Y(666), w("egg"))
+
+    def test_delegate_x_to_str(self):
+        space = self.space
+        r = space.add(X(42), w("spam"))
+        self.assertEquals(repr(r), "('add_string_string', '!42', 'spam')")
 
+        r = space.add(Y(20), w("egg"))
+        self.assertEquals(repr(r), "('add_string_string', '!<Y 20>', 'egg')")
 
-class TestMultiMethod2(TestMultiMethod1):
-    Installer = multimethod.InstallerVersion2
+
+
+if __name__ == '__main__':
+    testit.main()



More information about the Pypy-commit mailing list