[pypy-svn] r58281 - in pypy/dist: lib-python pypy/annotation pypy/annotation/test pypy/interpreter pypy/interpreter/astcompiler pypy/interpreter/pyparser pypy/interpreter/test pypy/module/__builtin__ pypy/module/__builtin__/test pypy/module/_codecs pypy/module/_file pypy/module/_pickle_support pypy/module/_rawffi pypy/module/_sre pypy/module/_stackless/test pypy/module/marshal pypy/module/posix pypy/module/rctime pypy/module/struct pypy/objspace/flow pypy/objspace/std pypy/rlib pypy/rlib/test pypy/rpython

arigo at codespeak.net arigo at codespeak.net
Sat Sep 20 23:35:42 CEST 2008


Author: arigo
Date: Sat Sep 20 23:35:38 2008
New Revision: 58281

Modified:
   pypy/dist/lib-python/conftest.py
   pypy/dist/pypy/annotation/bookkeeper.py
   pypy/dist/pypy/annotation/listdef.py
   pypy/dist/pypy/annotation/test/test_annrpython.py
   pypy/dist/pypy/interpreter/argument.py
   pypy/dist/pypy/interpreter/astcompiler/ast.py
   pypy/dist/pypy/interpreter/astcompiler/opt.py
   pypy/dist/pypy/interpreter/astcompiler/pyassem.py
   pypy/dist/pypy/interpreter/baseobjspace.py
   pypy/dist/pypy/interpreter/function.py
   pypy/dist/pypy/interpreter/gateway.py
   pypy/dist/pypy/interpreter/interactive.py
   pypy/dist/pypy/interpreter/nestedscope.py
   pypy/dist/pypy/interpreter/pycode.py
   pypy/dist/pypy/interpreter/pyframe.py
   pypy/dist/pypy/interpreter/pyopcode.py
   pypy/dist/pypy/interpreter/pyparser/astbuilder.py
   pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py
   pypy/dist/pypy/interpreter/test/test_objspace.py
   pypy/dist/pypy/module/__builtin__/abstractinst.py
   pypy/dist/pypy/module/__builtin__/compiling.py
   pypy/dist/pypy/module/__builtin__/interp_classobj.py
   pypy/dist/pypy/module/__builtin__/test/test_abstractinst.py
   pypy/dist/pypy/module/_codecs/interp_codecs.py
   pypy/dist/pypy/module/_file/interp_file.py
   pypy/dist/pypy/module/_pickle_support/maker.py
   pypy/dist/pypy/module/_rawffi/interp_rawffi.py
   pypy/dist/pypy/module/_rawffi/structure.py
   pypy/dist/pypy/module/_sre/interp_sre.py
   pypy/dist/pypy/module/_stackless/test/test_frame_chain_reconstruction.py
   pypy/dist/pypy/module/marshal/interp_marshal.py
   pypy/dist/pypy/module/posix/interp_posix.py
   pypy/dist/pypy/module/rctime/interp_time.py
   pypy/dist/pypy/module/struct/interp_struct.py
   pypy/dist/pypy/objspace/flow/objspace.py
   pypy/dist/pypy/objspace/std/iterobject.py
   pypy/dist/pypy/objspace/std/listobject.py
   pypy/dist/pypy/objspace/std/marshal_impl.py
   pypy/dist/pypy/objspace/std/model.py
   pypy/dist/pypy/objspace/std/objspace.py
   pypy/dist/pypy/objspace/std/ropeobject.py
   pypy/dist/pypy/objspace/std/ropeunicodeobject.py
   pypy/dist/pypy/objspace/std/stringobject.py
   pypy/dist/pypy/objspace/std/strsliceobject.py
   pypy/dist/pypy/objspace/std/tupleobject.py
   pypy/dist/pypy/objspace/std/tupletype.py
   pypy/dist/pypy/objspace/std/typeobject.py
   pypy/dist/pypy/objspace/std/typetype.py
   pypy/dist/pypy/objspace/std/unicodeobject.py
   pypy/dist/pypy/rlib/debug.py
   pypy/dist/pypy/rlib/test/test_debug.py
   pypy/dist/pypy/rpython/callparse.py
Log:
issue395 resolved

(fijal for most of the work)

Merge the tuple-nonresizable-395 branch, making sure that some lists are
"non-resizable", i.e. can be translated as a plain array - in
particular the list W_TupleObject.wrappeditems.

 * make_sure_not_resized(): annotator hint to check non-resizability
 * if --no-listcompr, make_sure_not_resized() is disabled and only
     produces a warning (always the case with ootype for now)
 * new method space.viewiterable() returns a non-resizable immutable list
 * space.unpacktuple() is gone, use space.viewiterable()
 * space.viewiterable() and space.unpackiterable() are more efficient
 * space.newtuple() must receive a non-resizable list argument.


Modified: pypy/dist/lib-python/conftest.py
==============================================================================
--- pypy/dist/lib-python/conftest.py	(original)
+++ pypy/dist/lib-python/conftest.py	Sat Sep 20 23:35:38 2008
@@ -166,12 +166,12 @@
 set_argv = app.interphook('set_argv')
 
 def start_intercept(space): 
-    w_suites, w_doctestmodules = space.unpacktuple(intercept_test_support(space))
+    w_suites, w_doctestmodules = space.viewiterable(intercept_test_support(space))
     return w_suites, w_doctestmodules 
 
 def collect_intercept(space, w_suites, w_doctestmodules): 
     w_result = callex(space, collect_intercepted, space, w_suites, w_doctestmodules)
-    w_namemethods, w_doctestlist = space.unpacktuple(w_result) 
+    w_namemethods, w_doctestlist = space.viewiterable(w_result) 
     return w_namemethods, w_doctestlist 
 
 class SimpleRunItem(py.test.collect.Item): 
@@ -240,14 +240,14 @@
 
         # setup {name -> wrapped testcase method}
         for w_item in space.unpackiterable(w_namemethods): 
-            w_name, w_method = space.unpacktuple(w_item) 
+            w_name, w_method = space.viewiterable(w_item) 
             name = space.str_w(w_name) 
             testitem = AppTestCaseMethod(name, parent=self, w_method=w_method) 
             self.name2item[name] = testitem
 
         # setup {name -> wrapped doctest module}
         for w_item in space.unpackiterable(w_doctestlist): 
-            w_name, w_module = space.unpacktuple(w_item) 
+            w_name, w_module = space.viewiterable(w_item) 
             name = space.str_w(w_name) 
             testitem = AppDocTestModule(name, parent=self, w_module=w_module)
             self.name2item[name] = testitem 

Modified: pypy/dist/pypy/annotation/bookkeeper.py
==============================================================================
--- pypy/dist/pypy/annotation/bookkeeper.py	(original)
+++ pypy/dist/pypy/annotation/bookkeeper.py	Sat Sep 20 23:35:38 2008
@@ -737,7 +737,7 @@
             if (expected_length is not None and
                 expected_length != len(s_obj.items)):
                 raise ValueError
-            return s_obj.items
+            return list(s_obj.items)
         if (s_obj.__class__ is SomeObject and
             getattr(s_obj, 'from_ellipsis', False)):    # see newtuple()
             return [Ellipsis]

Modified: pypy/dist/pypy/annotation/listdef.py
==============================================================================
--- pypy/dist/pypy/annotation/listdef.py	(original)
+++ pypy/dist/pypy/annotation/listdef.py	Sat Sep 20 23:35:38 2008
@@ -26,6 +26,7 @@
         self.bookkeeper = bookkeeper
         self.itemof = {}  # set of all ListDefs using this ListItem
         self.read_locations = {}
+        self.dont_resize = False
         if bookkeeper is None:
             self.dont_change_any_more = True
 
@@ -37,7 +38,7 @@
 
     def resize(self):
         if not self.resized:
-            if self.dont_change_any_more:
+            if self.dont_change_any_more or self.dont_resize:
                 raise TooLateForChange
             self.resized = True
 
@@ -62,8 +63,13 @@
                     # things more general
                     self, other = other, self
 
+            if other.dont_resize:
+                if self.resized:                    
+                    raise TooLateForChange()
+                self.dont_resize = True
             if other.mutated: self.mutate()
-            if other.resized: self.resize()
+            if other.resized:
+                self.resize()
             if other.range_step != self.range_step:
                 self.setrangestep(self._step_map[type(self.range_step),
                                                  type(other.range_step)])
@@ -181,6 +187,11 @@
         self.listitem.mutate()
         self.listitem.resize()
 
+    def never_resize(self):
+        if self.listitem.resized:
+            raise TooLateForChange()
+        self.listitem.dont_resize = True
+
 
 MOST_GENERAL_LISTDEF = ListDef(None, SomeObject())
 

Modified: pypy/dist/pypy/annotation/test/test_annrpython.py
==============================================================================
--- pypy/dist/pypy/annotation/test/test_annrpython.py	(original)
+++ pypy/dist/pypy/annotation/test/test_annrpython.py	Sat Sep 20 23:35:38 2008
@@ -10,7 +10,7 @@
 from pypy.translator.translator import graphof as tgraphof
 from pypy.annotation import policy
 from pypy.annotation import specialize
-from pypy.annotation.listdef import ListDef
+from pypy.annotation.listdef import ListDef, TooLateForChange
 from pypy.annotation.dictdef import DictDef
 from pypy.objspace.flow.model import *
 from pypy.rlib.rarithmetic import r_uint, base_int, r_longlong, r_ulonglong
@@ -3040,6 +3040,66 @@
 
         a.build_types(f, [str])
 
+    def test_listitem_no_mutating(self):
+        from pypy.rlib.debug import check_annotation
+        called = []
+
+        def checker(ann, bk):
+            called.append(True)
+            assert not ann.listdef.listitem.mutated
+            ann.listdef.never_resize()
+        
+        def f():
+            l = [1,2,3]
+            check_annotation(l, checker)
+            return l
+
+        def g():
+            l = f()
+            l.append(4)
+
+        a = self.RPythonAnnotator()
+        py.test.raises(TooLateForChange, a.build_types, g, [])
+        assert called
+
+    def test_listitem_no_mutating2(self):
+        from pypy.rlib.debug import make_sure_not_resized
+        
+        def f():
+            return make_sure_not_resized([1,2,3])
+
+        def g():
+            l = [1,2,3]
+            l.append(4)
+            return l
+
+        def fn(i):
+            if i:
+                func = f
+            else:
+                func = g
+            return func()
+
+        a = self.RPythonAnnotator()
+        a.translator.config.translation.list_comprehension_operations = True
+        py.test.raises(TooLateForChange, a.build_types, fn, [int])
+            
+
+    def test_listitem_never_resize(self):
+        from pypy.rlib.debug import check_annotation
+
+        def checker(ann, bk):
+            ann.listdef.never_resize()
+
+        def f():
+            l = [1,2,3]
+            l.append(4)
+            check_annotation(l, checker)
+
+        a = self.RPythonAnnotator()
+        py.test.raises(TooLateForChange, a.build_types, f, [])
+        
+
 def g(n):
     return [0,1,2,n]
 

Modified: pypy/dist/pypy/interpreter/argument.py
==============================================================================
--- pypy/dist/pypy/interpreter/argument.py	(original)
+++ pypy/dist/pypy/interpreter/argument.py	Sat Sep 20 23:35:38 2008
@@ -136,9 +136,13 @@
                 unfiltered_kwds_w[argname] = w_arg
             assert not space.is_true(data_w_stararg)
         else:
-            args_w = data_args_w[:]
-            for w_stararg in space.unpackiterable(data_w_stararg):
-                args_w.append(w_stararg)
+            stararg_w = space.unpackiterable(data_w_stararg)
+            datalen = len(data_args_w)
+            args_w = [None] * (datalen + len(stararg_w))
+            for i in range(0, datalen):
+                args_w[i] = data_args_w[i]
+            for i in range(0, len(stararg_w)):
+                args_w[i + datalen] = stararg_w[i]
             assert len(args_w) == need_cnt
             
         kwds_w = {}
@@ -267,9 +271,9 @@
             if has_vararg:
                 if upfront > co_argcount:
                     assert extravarargs is not None                    
-                    stararg_w = extravarargs
+                    stararg_w = extravarargs + [None] * self.nargs
                     for i in range(self.nargs):
-                        stararg_w.append(self.frame.peekvalue(self.nargs - 1 - i))
+                        stararg_w[i + len(extravarargs)] = self.frame.peekvalue(self.nargs - 1 - i)
                 else:
                     args_left = co_argcount - upfront                
                     stararg_w = [None] * (avail - co_argcount)
@@ -315,7 +319,10 @@
     def __init__(self, space, args_w, kwds_w=None,
                  w_stararg=None, w_starstararg=None):
         self.space = space
+        assert isinstance(args_w, list)
         self.arguments_w = args_w
+        from pypy.rlib.debug import make_sure_not_resized
+        make_sure_not_resized(self.arguments_w)
         self.kwds_w = kwds_w
         self.w_stararg = w_stararg
         self.w_starstararg = w_starstararg
@@ -360,7 +367,8 @@
         "unpack the *arg and **kwd into w_arguments and kwds_w"
         # --- unpack the * argument now ---
         if self.w_stararg is not None:
-            self.arguments_w += self.space.unpackiterable(self.w_stararg)
+            self.arguments_w = (self.arguments_w +
+                                self.space.unpackiterable(self.w_stararg))
             self.w_stararg = None
         # --- unpack the ** argument now ---
         if self.kwds_w is None:
@@ -405,8 +413,9 @@
         if len(self.arguments_w) > argcount:
             raise ValueError, "too many arguments (%d expected)" % argcount
         if self.w_stararg is not None:
-            self.arguments_w += self.space.unpackiterable(self.w_stararg,
-                                             argcount - len(self.arguments_w))
+            self.arguments_w = (self.arguments_w +
+                                self.space.viewiterable(self.w_stararg,
+                                         argcount - len(self.arguments_w)))
             self.w_stararg = None
         elif len(self.arguments_w) < argcount:
             raise ValueError, "not enough arguments (%d expected)" % argcount
@@ -529,7 +538,7 @@
                     assert extravarargs is not None
                     starargs_w = extravarargs
                     if num_args:
-                        starargs_w.extend(args_w)
+                        starargs_w = starargs_w + args_w
                 elif num_args > args_left:
                     starargs_w = args_w[args_left:]
                 else:

Modified: pypy/dist/pypy/interpreter/astcompiler/ast.py
==============================================================================
--- pypy/dist/pypy/interpreter/astcompiler/ast.py	(original)
+++ pypy/dist/pypy/interpreter/astcompiler/ast.py	Sat Sep 20 23:35:38 2008
@@ -5923,6 +5923,7 @@
             child.accept(self)
 
     def _mutate_list(self, lst):
+        # XXX O(n^2)
         i = 0
         while i < len(lst):
             item = lst[i].mutate(self)

Modified: pypy/dist/pypy/interpreter/astcompiler/opt.py
==============================================================================
--- pypy/dist/pypy/interpreter/astcompiler/opt.py	(original)
+++ pypy/dist/pypy/interpreter/astcompiler/opt.py	Sat Sep 20 23:35:38 2008
@@ -231,11 +231,13 @@
             return self._visitAbstractTest(node, False)
 
         def visitTuple(self, node):
-            consts_w = []
-            for subnode in node.nodes:
+            nodes = node.nodes
+            consts_w = [None] * len(nodes)
+            for i in range(len(nodes)):
+                subnode = nodes[i]
                 if not isinstance(subnode, ast.Const):
                     return node     # not all constants
-                consts_w.append(subnode.value)
+                consts_w[i] = subnode.value
             return ast.Const(self.space.newtuple(consts_w))
 
         def visitFor(self, node):

Modified: pypy/dist/pypy/interpreter/astcompiler/pyassem.py
==============================================================================
--- pypy/dist/pypy/interpreter/astcompiler/pyassem.py	(original)
+++ pypy/dist/pypy/interpreter/astcompiler/pyassem.py	Sat Sep 20 23:35:38 2008
@@ -390,7 +390,7 @@
         l_w = [None] * len(keys_w)
         for w_key in keys_w:
             index = space.int_w(space.getitem(self.w_consts, w_key))
-            w_v = space.unpacktuple(w_key)[0]
+            w_v = space.viewiterable(w_key)[0]
             l_w[index] = w_v
         return l_w
 

Modified: pypy/dist/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/dist/pypy/interpreter/baseobjspace.py	(original)
+++ pypy/dist/pypy/interpreter/baseobjspace.py	Sat Sep 20 23:35:38 2008
@@ -8,6 +8,7 @@
 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
 import os, sys
 
 __all__ = ['ObjSpace', 'OperationError', 'Wrappable', 'W_Root']
@@ -657,16 +658,12 @@
                                    (i, plural))
         return items
 
-    def unpacktuple(self, w_tuple, expected_length=-1):
-        """Same as unpackiterable(), but only for tuples.
-        Only use for bootstrapping or performance reasons."""
-        tuple_length = self.int_w(self.len(w_tuple))
-        if expected_length != -1 and tuple_length != expected_length:
-            raise UnpackValueError("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 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 exception_match(self, w_exc_type, w_check_class):
         """Checks if the given exception type matches 'w_check_class'."""

Modified: pypy/dist/pypy/interpreter/function.py
==============================================================================
--- pypy/dist/pypy/interpreter/function.py	(original)
+++ pypy/dist/pypy/interpreter/function.py	Sat Sep 20 23:35:38 2008
@@ -213,7 +213,7 @@
             w(self.code),
             self.w_func_globals,
             w_closure,
-            nt(self.defs_w),
+            nt(self.defs_w[:]),
             self.w_func_dict,
             self.w_module,
         ]
@@ -244,7 +244,7 @@
         values_w = self.defs_w
         if not values_w:
             return space.w_None
-        return space.newtuple(values_w)
+        return space.newtuple(values_w[:])
 
     def fset_func_defaults(space, self, w_defaults):
         if space.is_w(w_defaults, space.w_None):

Modified: pypy/dist/pypy/interpreter/gateway.py
==============================================================================
--- pypy/dist/pypy/interpreter/gateway.py	(original)
+++ pypy/dist/pypy/interpreter/gateway.py	Sat Sep 20 23:35:38 2008
@@ -207,7 +207,7 @@
                              % (self.scopenext(), self.scopenext()))
 
     def visit_args_w(self, el):
-        self.run_args.append("space.unpacktuple(%s)" % self.scopenext())
+        self.run_args.append("space.viewiterable(%s)" % self.scopenext())
 
     def visit_w_args(self, el):
         self.run_args.append(self.scopenext())
@@ -406,7 +406,7 @@
         #  baseobjspace.W_Root is for wrapped arguments to keep wrapped
         #  baseobjspace.Wrappable subclasses imply interp_w and a typecheck
         #  argument.Arguments is for a final rest arguments Arguments object
-        # 'args_w' for unpacktuple applied to rest arguments
+        # 'args_w' for viewiterable applied to rest arguments
         # 'w_args' for rest arguments passed as wrapped tuple
         # str,int,float: unwrap argument as such type
         # (function, cls) use function to check/unwrap argument of type cls

Modified: pypy/dist/pypy/interpreter/interactive.py
==============================================================================
--- pypy/dist/pypy/interpreter/interactive.py	(original)
+++ pypy/dist/pypy/interpreter/interactive.py	Sat Sep 20 23:35:38 2008
@@ -73,7 +73,7 @@
         words = self.get_words(w_clz)
         try:                
             w_bases = s.getattr(w_clz, s.wrap("__bases__"))             
-            bases_w = s.unpacktuple(w_bases)
+            bases_w = s.viewiterable(w_bases)
 
         except error.OperationError:
             return words

Modified: pypy/dist/pypy/interpreter/nestedscope.py
==============================================================================
--- pypy/dist/pypy/interpreter/nestedscope.py	(original)
+++ pypy/dist/pypy/interpreter/nestedscope.py	Sat Sep 20 23:35:38 2008
@@ -202,7 +202,7 @@
         if codeobj.magic >= 0xa0df281:    # CPython 2.5 AST branch merge
             w_freevarstuple = f.popvalue()
             freevars = [f.space.interp_w(Cell, cell)
-                        for cell in f.space.unpacktuple(w_freevarstuple)]
+                        for cell in f.space.viewiterable(w_freevarstuple)]
         else:
             nfreevars = len(codeobj.co_freevars)
             freevars = [f.space.interp_w(Cell, f.popvalue())

Modified: pypy/dist/pypy/interpreter/pycode.py
==============================================================================
--- pypy/dist/pypy/interpreter/pycode.py	(original)
+++ pypy/dist/pypy/interpreter/pycode.py	Sat Sep 20 23:35:38 2008
@@ -11,15 +11,12 @@
 from pypy.interpreter.gateway import NoneNotWrapped 
 from pypy.interpreter.baseobjspace import ObjSpace, W_Root
 from pypy.rlib.rarithmetic import intmask
+from pypy.rlib.debug import make_sure_not_resized
 
 # helper
 
 def unpack_str_tuple(space,w_str_tuple):
-    els = []
-    for w_el in space.unpackiterable(w_str_tuple):
-        els.append(space.str_w(w_el))
-    return els
-
+    return [space.str_w(w_el) for w_el in space.unpackiterable(w_str_tuple)]
 
 # code object contants, for co_flags below
 CO_OPTIMIZED    = 0x0001
@@ -66,7 +63,7 @@
         self.co_stacksize = stacksize
         self.co_flags = flags
         self.co_code = code
-        self.co_consts_w = consts
+        self.co_consts_w = make_sure_not_resized(consts)
         self.co_names_w = [space.new_interned_str(aname) for aname in names]
         self.co_varnames = varnames
         self.co_freevars = freevars
@@ -122,12 +119,13 @@
             This method is called by our compile builtin function.
         """
         assert isinstance(code, types.CodeType)
-        newconsts_w = []
+        newconsts_w = [None] * len(code.co_consts)
+        num = 0
         for const in code.co_consts:
             if isinstance(const, types.CodeType): # from stable compiler
                 const = PyCode._from_code(space, const, hidden_applevel=hidden_applevel)
-
-            newconsts_w.append(space.wrap(const))
+            newconsts_w[num] = space.wrap(const)
+            num += 1
         # stick the underlying CPython magic value, if the code object
         # comes from there
         return PyCode(space, code.co_argcount,
@@ -213,12 +211,14 @@
 
     def _to_code(self):
         """For debugging only."""
-        consts = []
+        consts = [None] * len(self.co_consts_w)
+        num = 0
         for w in self.co_consts_w:
             if isinstance(w, PyCode):
-                consts.append(w._to_code())
+                consts[num] = w._to_code()
             else:
-                consts.append(self.space.unwrap(w))
+                consts[num] = self.space.unwrap(w)
+            num += 1
         return new.code( self.co_argcount,
                          self.co_nlocals,
                          self.co_stacksize,
@@ -321,8 +321,11 @@
                                  space.wrap("code: argcount must not be negative"))
         if nlocals < 0:
             raise OperationError(space.w_ValueError,
-                                 space.wrap("code: nlocals must not be negative"))        
-        consts_w   = space.unpacktuple(w_constants)
+                                 space.wrap("code: nlocals must not be negative"))
+        if not space.is_true(space.isinstance(w_constants, space.w_tuple)):
+            raise OperationError(space.w_TypeError,
+                                 space.wrap("Expected tuple for constants"))
+        consts_w   = space.viewiterable(w_constants)
         names      = unpack_str_tuple(space, w_names)
         varnames   = unpack_str_tuple(space, w_varnames)
         if w_freevars is not None:

Modified: pypy/dist/pypy/interpreter/pyframe.py
==============================================================================
--- pypy/dist/pypy/interpreter/pyframe.py	(original)
+++ pypy/dist/pypy/interpreter/pyframe.py	Sat Sep 20 23:35:38 2008
@@ -152,15 +152,22 @@
             dic_w[key] = w_value
         return dic_w
 
-    def popvalues(self, n):
-        values_w = [None] * n
-        while True:
-            n -= 1
-            if n < 0:
-                break
-            hint(n, concrete=True)
-            values_w[n] = self.popvalue()
-        return values_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
+                hint(n, concrete=True)
+                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

Modified: pypy/dist/pypy/interpreter/pyopcode.py
==============================================================================
--- pypy/dist/pypy/interpreter/pyopcode.py	(original)
+++ pypy/dist/pypy/interpreter/pyopcode.py	Sat Sep 20 23:35:38 2008
@@ -552,7 +552,7 @@
                                      w_compile_flags,
                                      f.space.wrap(f.get_builtin()),
                                      f.space.gettypeobject(PyCode.typedef))
-        w_prog, w_globals, w_locals = f.space.unpacktuple(w_resulttuple, 3)
+        w_prog, w_globals, w_locals = f.space.viewiterable(w_resulttuple, 3)
 
         plain = f.w_locals is not None and f.space.is_w(w_locals, f.w_locals)
         if plain:
@@ -679,7 +679,7 @@
         f.pushvalue(w_tuple)
 
     def BUILD_LIST(f, itemcount, *ignored):
-        items = f.popvalues(itemcount)
+        items = f.popvalues_mutable(itemcount)
         w_list = f.space.newlist(items)
         f.pushvalue(w_list)
 
@@ -905,7 +905,7 @@
     def MAKE_FUNCTION(f, numdefaults, *ignored):
         w_codeobj = f.popvalue()
         codeobj = f.space.interp_w(PyCode, w_codeobj)
-        defaultarguments = f.popvalues(numdefaults)
+        defaultarguments = f.popvalues_mutable(numdefaults)
         fn = function.Function(f.space, codeobj, f.w_globals, defaultarguments)
         f.pushvalue(f.space.wrap(fn))
 

Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py
==============================================================================
--- pypy/dist/pypy/interpreter/pyparser/astbuilder.py	(original)
+++ pypy/dist/pypy/interpreter/pyparser/astbuilder.py	Sat Sep 20 23:35:38 2008
@@ -416,11 +416,12 @@
     if l == 1:
         builder.push(atoms[0])
         return
-    items = []
     token = atoms[1]
     if isinstance(token, TokenObject) and token.name == builder.parser.tokens['COMMA']:
+        items = []
         for i in range(0, l, 2): # this is atoms not 1
             items.append(atoms[i])
+        builder.push(ast.Tuple(items, lineno))
     else:
         # genfor: 'i for i in j'
         # GenExpr(GenExprInner(Name('i'), [GenExprFor(AssName('i', 'OP_ASSIGN'), Name('j'), [])])))]))
@@ -428,20 +429,6 @@
         genexpr_for = parse_genexpr_for(atoms[1:])
         genexpr_for[0].is_outmost = True
         builder.push(ast.GenExpr(ast.GenExprInner(expr, genexpr_for, lineno), lineno))
-        return
-    isConst = True
-    values = []
-    for item in items:
-        if isinstance(item, ast.Const):
-            values.append(item.value)
-        else:
-            isConst = False
-            break
-    if isConst:
-        builder.push(ast.Const(builder.space.newtuple(values), lineno))
-    else:
-        builder.push(ast.Tuple(items, lineno))
-    return
 
 def build_lambdef(builder, nb):
     """lambdef: 'lambda' [varargslist] ':' test"""
@@ -739,21 +726,8 @@
     if len(atoms) <= 2:
         builder.push(atoms[0])
     else:
-        names = []
-        values = []
-        isConst = True
-        for index in range(0, len(atoms), 2):
-            item = atoms[index]
-            names.append(item)
-            if isinstance(item, ast.Const):
-                values.append(item)
-            else:
-                isConst = False
-        if isConst:
-            builder.push(ast.Const(builder.space.newtuple(values), atoms[0].lineno))
-        else:
-            builder.push(ast.Tuple(names, atoms[0].lineno))
-
+        items = [atoms[index] for index in range(0, len(atoms), 2)]
+        builder.push(ast.Tuple(items, atoms[0].lineno))
 
 def build_while_stmt(builder, nb):
     """while_stmt: 'while' test ':' suite ['else' ':' suite]"""

Modified: pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py
==============================================================================
--- pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py	(original)
+++ pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py	Sat Sep 20 23:35:38 2008
@@ -17,9 +17,10 @@
 
     def as_w_tuple(self, space, lineno=False):
         num, value, lineno = self.nodes[0]
-        content = [space.wrap(num), space.wrap(value)]
         if lineno:
-            content.append(space.wrap(lineno))
+            content = [space.wrap(num), space.wrap(value), space.wrap(lineno)]
+        else:
+            content = [space.wrap(num), space.wrap(value)]
         return space.newtuple(content)
 
 
@@ -34,8 +35,8 @@
         return tuple(l)
 
     def as_w_tuple(self, space, lineno=False):
-        l = [space.wrap(self.num)]
-        l += [node.as_w_tuple(space, lineno) for node in self.nodes]
+        l = ([space.wrap(self.num)] +
+             [node.as_w_tuple(space, lineno) for node in self.nodes])
         return space.newtuple(l)
 
 

Modified: pypy/dist/pypy/interpreter/test/test_objspace.py
==============================================================================
--- pypy/dist/pypy/interpreter/test/test_objspace.py	(original)
+++ pypy/dist/pypy/interpreter/test/test_objspace.py	Sat Sep 20 23:35:38 2008
@@ -54,14 +54,14 @@
         raises(ValueError, self.space.unpackiterable, w_l, 3)
         raises(ValueError, self.space.unpackiterable, w_l, 5)
 
-    def test_unpacktuple(self):
+    def test_viewiterable(self):
         w = self.space.wrap
         l = [w(1), w(2), w(3), w(4)]
         w_l = self.space.newtuple(l)
-        assert self.space.unpacktuple(w_l) == l
-        assert self.space.unpacktuple(w_l, 4) == l
-        raises(ValueError, self.space.unpacktuple, w_l, 3)
-        raises(ValueError, self.space.unpacktuple, w_l, 5)
+        assert self.space.viewiterable(w_l) == l
+        assert self.space.viewiterable(w_l, 4) == l
+        raises(ValueError, self.space.viewiterable, w_l, 3)
+        raises(ValueError, self.space.viewiterable, w_l, 5)
 
     def test_exception_match(self):
         assert self.space.exception_match(self.space.w_ValueError,
@@ -203,7 +203,7 @@
 
         w_res = space.call_obj_args(w_f, w_9, Arguments(space, [w_1]))
 
-        w_x, w_y = space.unpacktuple(w_res, 2)
+        w_x, w_y = space.viewiterable(w_res, 2)
         assert w_x is w_9
         assert w_y is w_1
 

Modified: pypy/dist/pypy/module/__builtin__/abstractinst.py
==============================================================================
--- pypy/dist/pypy/module/__builtin__/abstractinst.py	(original)
+++ pypy/dist/pypy/module/__builtin__/abstractinst.py	Sat Sep 20 23:35:38 2008
@@ -79,7 +79,7 @@
 
     # -- case (anything, tuple)
     if space.is_true(space.isinstance(w_klass_or_tuple, space.w_tuple)):
-        for w_klass in space.unpacktuple(w_klass_or_tuple):
+        for w_klass in space.viewiterable(w_klass_or_tuple):
             if abstract_isinstance_w(space, w_obj, w_klass):
                 return True
         return False
@@ -104,7 +104,7 @@
         return True
     w_bases = _get_bases(space, w_derived)
     if w_bases is not None:
-        for w_base in space.unpacktuple(w_bases):
+        for w_base in space.viewiterable(w_bases):
             if _issubclass_recurse(space, w_base, w_top):
                 return True
     return False
@@ -134,7 +134,7 @@
 
     # -- case (class-like-object, tuple-of-classes)
     if space.is_true(space.isinstance(w_klass_or_tuple, space.w_tuple)):
-        for w_klass in space.unpacktuple(w_klass_or_tuple):
+        for w_klass in space.viewiterable(w_klass_or_tuple):
             if abstract_issubclass_w(space, w_derived, w_klass):
                 return True
         return False

Modified: pypy/dist/pypy/module/__builtin__/compiling.py
==============================================================================
--- pypy/dist/pypy/module/__builtin__/compiling.py	(original)
+++ pypy/dist/pypy/module/__builtin__/compiling.py	Sat Sep 20 23:35:38 2008
@@ -67,9 +67,9 @@
                              "<string>", "eval")
         except OperationError, e:
             if e.match(space, space.w_SyntaxError):
-                e_value_w = space.unpacktuple(e.w_value)
+                e_value_w = space.viewiterable(e.w_value)
                 if len(e_value_w) == 2:
-                    e_loc_w = space.unpacktuple(e_value_w[1])
+                    e_loc_w = space.viewiterable(e_value_w[1])
                     e.w_value = space.newtuple([e_value_w[0],
                                                 space.newtuple([space.w_None]+
                                                                e_loc_w[1:])])

Modified: pypy/dist/pypy/module/__builtin__/interp_classobj.py
==============================================================================
--- pypy/dist/pypy/module/__builtin__/interp_classobj.py	(original)
+++ pypy/dist/pypy/module/__builtin__/interp_classobj.py	Sat Sep 20 23:35:38 2008
@@ -35,7 +35,7 @@
 
     # XXX missing: lengthy and obscure logic about "__module__"
         
-    bases_w = space.unpackiterable(w_bases)
+    bases_w = space.viewiterable(w_bases)
     for w_base in bases_w:
         if not isinstance(w_base, W_ClassObject):
             w_metaclass = space.type(w_base)
@@ -78,7 +78,7 @@
             raise OperationError(
                     space.w_TypeError,
                     space.wrap("__bases__ must be a tuple object"))
-        bases_w = space.unpackiterable(w_bases)
+        bases_w = space.viewiterable(w_bases)
         for w_base in bases_w:
             if not isinstance(w_base, W_ClassObject):
                 raise OperationError(space.w_TypeError,
@@ -280,7 +280,7 @@
         if not e.match(space, space.w_TypeError):
             raise
         return [None, None]
-    return space.unpacktuple(w_tup, 2)
+    return space.viewiterable(w_tup, 2)
 
 def descr_instance_new(space, w_type, w_class, w_dict=None):
     # w_type is not used at all

Modified: pypy/dist/pypy/module/__builtin__/test/test_abstractinst.py
==============================================================================
--- pypy/dist/pypy/module/__builtin__/test/test_abstractinst.py	(original)
+++ pypy/dist/pypy/module/__builtin__/test/test_abstractinst.py	Sat Sep 20 23:35:38 2008
@@ -5,7 +5,7 @@
 
     def test_abstract_isclass(self):
         space = self.space
-        w_B1, w_B2, w_B3, w_X, w_Y = space.unpacktuple(space.appexec([], """():
+        w_B1, w_B2, w_B3, w_X, w_Y = space.viewiterable(space.appexec([], """():
             class X(object): pass
             class Y: pass
             B1, B2, B3 = X(), X(), X()
@@ -22,7 +22,7 @@
 
     def test_abstract_getclass(self):
         space = self.space
-        w_x, w_y, w_A, w_MyInst = space.unpacktuple(space.appexec([], """():
+        w_x, w_y, w_A, w_MyInst = space.viewiterable(space.appexec([], """():
             class MyInst(object):
                 def __init__(self, myclass):
                     self.myclass = myclass

Modified: pypy/dist/pypy/module/_codecs/interp_codecs.py
==============================================================================
--- pypy/dist/pypy/module/_codecs/interp_codecs.py	(original)
+++ pypy/dist/pypy/module/_codecs/interp_codecs.py	Sat Sep 20 23:35:38 2008
@@ -35,7 +35,7 @@
                     space.wrap("encoding error handler must return "
                                "(unicode, int) tuple, not %s" % (
                                    space.str_w(space.repr(w_res)))))
-            w_replace, w_newpos = space.unpacktuple(w_res, 2)
+            w_replace, w_newpos = space.viewiterable(w_res, 2)
             newpos = space.int_w(w_newpos)
             if (newpos < 0):
                 newpos = len(input) + newpos

Modified: pypy/dist/pypy/module/_file/interp_file.py
==============================================================================
--- pypy/dist/pypy/module/_file/interp_file.py	(original)
+++ pypy/dist/pypy/module/_file/interp_file.py	Sat Sep 20 23:35:38 2008
@@ -419,7 +419,7 @@
         result.append(space.wrap('\n'))
     if newlines & 4:
         result.append(space.wrap('\r\n'))
-    return space.newtuple(result)
+    return space.newtuple(result[:])
 
 def descr_file_softspace(space, file):
     return space.wrap(file.softspace)

Modified: pypy/dist/pypy/module/_pickle_support/maker.py
==============================================================================
--- pypy/dist/pypy/module/_pickle_support/maker.py	(original)
+++ pypy/dist/pypy/module/_pickle_support/maker.py	Sat Sep 20 23:35:38 2008
@@ -88,15 +88,18 @@
     create a tuple with the object and store
     a tuple with the positions of NULLs as first element.
     """
-    nulls = []
-    tup = [space.w_None]
+    tup = [None] * (len(seq_w) + 1)
     w = space.wrap
-
+    num = 1
+    nulls = [None for i in seq_w if i is None]
+    null_num = 0
     for w_obj in seq_w:
         if w_obj is None:
-            nulls.append(w(len(tup)-1))
+            nulls[null_num] = w(num - 1)
+            null_num += 1
             w_obj = space.w_None
-        tup.append(w_obj)
+        tup[num] = w_obj
+        num += 1
     tup[0] = space.newtuple(nulls)
     return space.newtuple(tup)
 

Modified: pypy/dist/pypy/module/_rawffi/interp_rawffi.py
==============================================================================
--- pypy/dist/pypy/module/_rawffi/interp_rawffi.py	(original)
+++ pypy/dist/pypy/module/_rawffi/interp_rawffi.py	Sat Sep 20 23:35:38 2008
@@ -98,7 +98,7 @@
             resshape = cache.get_array_type(letter2tp(space, letter))
     else:
         letter = 'V'
-        w_shapetype, w_length = space.unpacktuple(w_shape, expected_length=2)
+        w_shapetype, w_length = space.viewiterable(w_shape, expected_length=2)
         from pypy.module._rawffi.structure import W_Structure
         resshape = space.interp_w(W_Structure, w_shapetype)
         ffi_type = resshape.get_ffi_type()
@@ -109,7 +109,7 @@
         letter = space.str_w(w_shape)
         return letter2tp(space, letter)
     else:
-        w_shapetype, w_length = space.unpacktuple(w_shape, expected_length=2)
+        w_shapetype, w_length = space.viewiterable(w_shape, expected_length=2)
         resshape = space.interp_w(W_DataShape, w_shapetype)
         length = space.int_w(w_length)
         size, alignment = resshape._size_alignment()
@@ -148,7 +148,7 @@
         """
         ffi_restype, resshape = unpack_resshape(space, w_restype)
         w = space.wrap
-        argtypes_w = space.unpackiterable(w_argtypes)
+        argtypes_w = space.viewiterable(w_argtypes)
         w_argtypes = space.newtuple(argtypes_w)
         w_key = space.newtuple([w(name), w_argtypes, w(resshape)])
         try:

Modified: pypy/dist/pypy/module/_rawffi/structure.py
==============================================================================
--- pypy/dist/pypy/module/_rawffi/structure.py	(original)
+++ pypy/dist/pypy/module/_rawffi/structure.py	Sat Sep 20 23:35:38 2008
@@ -119,7 +119,7 @@
 
 def descr_new_structure(space, w_type, w_shapeinfo):
     if space.is_true(space.isinstance(w_shapeinfo, space.w_tuple)):
-        w_size, w_alignment = space.unpacktuple(w_shapeinfo, expected_length=2)
+        w_size, w_alignment = space.viewiterable(w_shapeinfo, expected_length=2)
         S = W_Structure(space, None, space.int_w(w_size),
                                      space.int_w(w_alignment))
     else:

Modified: pypy/dist/pypy/module/_sre/interp_sre.py
==============================================================================
--- pypy/dist/pypy/module/_sre/interp_sre.py	(original)
+++ pypy/dist/pypy/module/_sre/interp_sre.py	Sat Sep 20 23:35:38 2008
@@ -95,11 +95,10 @@
         """Creates a tuple of index pairs representing matched groups, a format
         that's convenient for SRE_Match."""
         space = self.space
-        lst = []
-        for value1, value2 in self.create_regs(group_count):
-            lst.append(space.newtuple([space.wrap(value1),
-                                       space.wrap(value2)]))
-        return space.newtuple(lst)
+        return space.newtuple([
+            space.newtuple([space.wrap(value1),
+                            space.wrap(value2)])
+            for value1, value2 in self.create_regs(group_count)])
     w_create_regs.unwrap_spec = ['self', int]
 
     def fget_start(space, self):

Modified: pypy/dist/pypy/module/_stackless/test/test_frame_chain_reconstruction.py
==============================================================================
--- pypy/dist/pypy/module/_stackless/test/test_frame_chain_reconstruction.py	(original)
+++ pypy/dist/pypy/module/_stackless/test/test_frame_chain_reconstruction.py	Sat Sep 20 23:35:38 2008
@@ -92,7 +92,7 @@
         return co, f, g
         """)
 
-        w_co, w_f, w_g = space.unpacktuple(w_res)
+        w_co, w_f, w_g = space.viewiterable(w_res)
 
         ec = space.getexecutioncontext()
         fcode = w_f.code.co_code
@@ -151,7 +151,7 @@
         return co, f, g
         """)
 
-        w_co, w_f, w_g = space.unpacktuple(w_res)
+        w_co, w_f, w_g = space.viewiterable(w_res)
 
         ec = space.getexecutioncontext()
         fcode = w_f.code.co_code
@@ -223,7 +223,7 @@
         return co, f, g
         """)
 
-        w_co, w_f, w_g = space.unpacktuple(w_res)
+        w_co, w_f, w_g = space.viewiterable(w_res)
 
         ec = space.getexecutioncontext()
         fcode = w_f.code.co_code

Modified: pypy/dist/pypy/module/marshal/interp_marshal.py
==============================================================================
--- pypy/dist/pypy/module/marshal/interp_marshal.py	(original)
+++ pypy/dist/pypy/module/marshal/interp_marshal.py	Sat Sep 20 23:35:38 2008
@@ -234,24 +234,16 @@
             self._overflow()
         self.nesting -= 1
 
-    # this function is inlined below
-    def put_list_w(self, list_w, lng):
-        self.nesting += 1
-        self.put_int(lng)
-        idx = 0
-        while idx < lng:
-            self.put_w_obj(list_w[idx])
-            idx += 1
-        self.nesting -= 1
-
-    def put_list_w(self, list_w, lng):
+    def put_tuple_w(self, typecode, lst_w):
         self.nesting += 1
+        self.start(typecode)
+        lng = len(lst_w)
         self.put_int(lng)
         idx = 0
         space = self.space
         if self.nesting < MAX_MARSHAL_DEPTH:
             while idx < lng:
-                w_obj = list_w[idx]
+                w_obj = lst_w[idx]
                 self.space.marshal_w(w_obj, self)
                 idx += 1
         else:
@@ -443,18 +435,6 @@
         lng = self.get_lng()
         return self.get(lng)
 
-    # this function is inlined below
-    def get_list_w(self):
-        self.nesting += 1
-        lng = self.get_lng()
-        res_w = [None] * lng
-        idx = 0
-        while idx < lng:
-            res_w[idx] = self.get_w_obj(False)
-            idx += 1
-        self.nesting -= 1
-        return res_w
-
     def get_w_obj(self, allow_null):
         self.nesting += 1
         space = self.space
@@ -471,7 +451,7 @@
         return w_ret
 
     # inlined version to save a nesting level
-    def get_list_w(self):
+    def get_tuple_w(self):
         self.nesting += 1
         lng = self.get_lng()
         res_w = [None] * lng
@@ -494,6 +474,9 @@
         self.nesting -= 1
         return res_w
 
+    def get_list_w(self):
+        return self.get_tuple_w()[:]
+
     def _overflow(self):
         self.raise_exc('object too deeply nested to unmarshal')
 

Modified: pypy/dist/pypy/module/posix/interp_posix.py
==============================================================================
--- pypy/dist/pypy/module/posix/interp_posix.py	(original)
+++ pypy/dist/pypy/module/posix/interp_posix.py	Sat Sep 20 23:35:38 2008
@@ -97,7 +97,7 @@
         FIELDS = PORTABLE_STAT_FIELDS
     else:
         FIELDS = STAT_FIELDS    # also when not translating at all
-    lst = []
+    lst = [None] * ll_os_stat.N_INDEXABLE_FIELDS
     w_keywords = space.newdict()
     for i, (name, TYPE) in FIELDS:
         value = getattr(st, name)
@@ -105,7 +105,7 @@
         #    value = int(value)   # rounded to an integer for indexed access
         w_value = space.wrap(value)
         if i < ll_os_stat.N_INDEXABLE_FIELDS:
-            lst.append(w_value)
+            lst[i] = w_value
         else:
             space.setitem(w_keywords, space.wrap(name), w_value)
 

Modified: pypy/dist/pypy/module/rctime/interp_time.py
==============================================================================
--- pypy/dist/pypy/module/rctime/interp_time.py	(original)
+++ pypy/dist/pypy/module/rctime/interp_time.py	Sat Sep 20 23:35:38 2008
@@ -166,17 +166,16 @@
     return rffi.r_time_t(seconds)
 
 def _tm_to_tuple(space, t):
-    time_tuple = []
-
-    time_tuple.append(space.wrap(rffi.getintfield(t, 'c_tm_year') + 1900))
-    time_tuple.append(space.wrap(rffi.getintfield(t, 'c_tm_mon') + 1)) # want january == 1
-    time_tuple.append(space.wrap(rffi.getintfield(t, 'c_tm_mday')) )
-    time_tuple.append(space.wrap(rffi.getintfield(t, 'c_tm_hour')) )
-    time_tuple.append(space.wrap(rffi.getintfield(t, 'c_tm_min')) )
-    time_tuple.append(space.wrap(rffi.getintfield(t, 'c_tm_sec')) )
-    time_tuple.append(space.wrap((rffi.getintfield(t, 'c_tm_wday') + 6) % 7)) # want monday == 0
-    time_tuple.append(space.wrap(rffi.getintfield(t, 'c_tm_yday') + 1)) # want january, 1 == 1
-    time_tuple.append(space.wrap(rffi.getintfield(t, 'c_tm_isdst')) )
+    time_tuple = [
+        space.wrap(rffi.getintfield(t, 'c_tm_year') + 1900),
+        space.wrap(rffi.getintfield(t, 'c_tm_mon') + 1), # want january == 1
+        space.wrap(rffi.getintfield(t, 'c_tm_mday')),
+        space.wrap(rffi.getintfield(t, 'c_tm_hour')),
+        space.wrap(rffi.getintfield(t, 'c_tm_min')),
+        space.wrap(rffi.getintfield(t, 'c_tm_sec')),
+        space.wrap((rffi.getintfield(t, 'c_tm_wday') + 6) % 7), # want monday == 0
+        space.wrap(rffi.getintfield(t, 'c_tm_yday') + 1), # want january, 1 == 1
+        space.wrap(rffi.getintfield(t, 'c_tm_isdst'))]
     
     w_struct_time = _get_module_object(space, 'struct_time')
     w_time_tuple = space.newtuple(time_tuple)

Modified: pypy/dist/pypy/module/struct/interp_struct.py
==============================================================================
--- pypy/dist/pypy/module/struct/interp_struct.py	(original)
+++ pypy/dist/pypy/module/struct/interp_struct.py	Sat Sep 20 23:35:38 2008
@@ -33,5 +33,5 @@
         fmtiter.interpret(format)
     except StructError, e:
         raise e.at_applevel(space)
-    return space.newtuple(fmtiter.result_w)
+    return space.newtuple(fmtiter.result_w[:])
 unpack.unwrap_spec = [ObjSpace, str, 'bufferstr']

Modified: pypy/dist/pypy/objspace/flow/objspace.py
==============================================================================
--- pypy/dist/pypy/objspace/flow/objspace.py	(original)
+++ pypy/dist/pypy/objspace/flow/objspace.py	Sat Sep 20 23:35:38 2008
@@ -202,7 +202,7 @@
             # the simple case
             return ObjSpace.exception_match(self, w_exc_type, w_check_class)
         # checking a tuple of classes
-        for w_klass in self.unpacktuple(w_check_class):
+        for w_klass in self.viewiterable(w_check_class):
             if ObjSpace.exception_match(self, w_exc_type, w_klass):
                 return True
         return False
@@ -264,12 +264,7 @@
         checkgraph(graph)
         return graph
 
-    def unpacktuple(self, w_tuple, expected_length=None):
-##        # special case to accept either Constant tuples
-##        # or real tuples of Variables/Constants
-##        if isinstance(w_tuple, tuple):
-##            result = w_tuple
-##        else:
+    def viewiterable(self, w_tuple, expected_length=None):
         unwrapped = self.unwrap(w_tuple)
         result = tuple([Constant(x) for x in unwrapped])
         if expected_length is not None and len(result) != expected_length:
@@ -286,26 +281,6 @@
         if isinstance(w_iterable, Variable) and expected_length is None:
             raise UnwrapException, ("cannot unpack a Variable iterable"
                                     "without knowing its length")
-##            # XXX TEMPORARY HACK XXX TEMPORARY HACK XXX TEMPORARY HACK
-##            print ("*** cannot unpack a Variable iterable "
-##                   "without knowing its length,")
-##            print "    assuming a list or tuple with up to 7 items"
-##            items = []
-##            w_len = self.len(w_iterable)
-##            i = 0
-##            while True:
-##                w_i = self.wrap(i)
-##                w_cond = self.eq(w_len, w_i)
-##                if self.is_true(w_cond):
-##                    break  # done
-##                if i == 7:
-##                    # too many values
-##                    raise OperationError(self.w_AssertionError, self.w_None)
-##                w_item = self.do_operation('getitem', w_iterable, w_i)
-##                items.append(w_item)
-##                i += 1
-##            return items
-##            # XXX TEMPORARY HACK XXX TEMPORARY HACK XXX TEMPORARY HACK
         elif expected_length is not None:
             w_len = self.len(w_iterable)
             w_correct = self.eq(w_len, self.wrap(expected_length))

Modified: pypy/dist/pypy/objspace/std/iterobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/iterobject.py	(original)
+++ pypy/dist/pypy/objspace/std/iterobject.py	Sat Sep 20 23:35:38 2008
@@ -16,16 +16,34 @@
         w_self.w_seq = w_seq
         w_self.index = index
 
+    def getlength(self, space):
+        if self.w_seq is None:
+            return space.wrap(0)
+        index = self.index
+        w_length = space.len(self.w_seq)
+        w_len = space.sub(w_length, space.wrap(index))
+        if space.is_true(space.lt(w_len,space.wrap(0))):
+            w_len = space.wrap(0)
+        return w_len
+
 class W_SeqIterObject(W_AbstractSeqIterObject):
     """Sequence iterator implementation for general sequences."""
 
-class W_FastSeqIterObject(W_AbstractSeqIterObject):
-    """Sequence iterator specialized for lists or tuples, accessing
+class W_FastListIterObject(W_AbstractSeqIterObject):
+    """Sequence iterator specialized for lists, accessing
     directly their RPython-level list of wrapped objects.
     """
     def __init__(w_self, w_seq, wrappeditems):
         W_AbstractSeqIterObject.__init__(w_self, w_seq)
-        w_self.wrappeditems = wrappeditems
+        w_self.listitems = wrappeditems
+
+class W_FastTupleIterObject(W_AbstractSeqIterObject):
+   """Sequence iterator specialized for tuples, accessing
+   directly their RPython-level list of wrapped objects.
+   """ 
+   def __init__(w_self, w_seq, wrappeditems):
+        W_AbstractSeqIterObject.__init__(w_self, w_seq)
+        w_self.tupleitems = wrappeditems
 
 class W_ReverseSeqIterObject(W_Object):
     from pypy.objspace.std.itertype import reverse_iter_typedef as typedef
@@ -37,7 +55,8 @@
 
 
 registerimplementation(W_SeqIterObject)
-registerimplementation(W_FastSeqIterObject)
+registerimplementation(W_FastListIterObject)
+registerimplementation(W_FastTupleIterObject)
 registerimplementation(W_ReverseSeqIterObject)
 
 def iter__SeqIter(space, w_seqiter):
@@ -57,40 +76,47 @@
     return w_item
 
 def len__SeqIter(space,  w_seqiter):
-    if w_seqiter.w_seq is None:
-        return space.wrap(0)
+    return w_seqiter.getlength(space)
+
+
+def iter__FastTupleIter(space, w_seqiter):
+    return w_seqiter
+
+def next__FastTupleIter(space, w_seqiter):
+    if w_seqiter.tupleitems is None:
+        raise OperationError(space.w_StopIteration, space.w_None)
     index = w_seqiter.index
-    w_length = space.len(w_seqiter.w_seq)
-    w_len = space.sub(w_length, space.wrap(index))
-    if space.is_true(space.lt(w_len,space.wrap(0))):
-        w_len = space.wrap(0)
-    return w_len
+    try:
+        w_item = w_seqiter.tupleitems[index]
+    except IndexError:
+        w_seqiter.tupleitems = None
+        w_seqiter.w_seq = None
+        raise OperationError(space.w_StopIteration, space.w_None) 
+    w_seqiter.index = index + 1
+    return w_item
 
+def len__FastTupleIter(space, w_seqiter):
+    return w_seqiter.getlength(space)
 
-def iter__FastSeqIter(space, w_seqiter):
+
+def iter__FastListIter(space, w_seqiter):
     return w_seqiter
 
-def next__FastSeqIter(space, w_seqiter):
-    if w_seqiter.wrappeditems is None:
+def next__FastListIter(space, w_seqiter):
+    if w_seqiter.listitems is None:
         raise OperationError(space.w_StopIteration, space.w_None)
     index = w_seqiter.index
     try:
-        w_item = w_seqiter.wrappeditems[index]
+        w_item = w_seqiter.listitems[index]
     except IndexError:
-        w_seqiter.wrappeditems = None
+        w_seqiter.listitems = None
         w_seqiter.w_seq = None
         raise OperationError(space.w_StopIteration, space.w_None) 
     w_seqiter.index = index + 1
     return w_item
 
-def len__FastSeqIter(space, w_seqiter):
-    if w_seqiter.wrappeditems is None:
-        return space.wrap(0)
-    totallength = len(w_seqiter.wrappeditems)
-    remaining = totallength - w_seqiter.index
-    if remaining < 0:
-        remaining = 0
-    return space.wrap(remaining)
+def len__FastListIter(space, w_seqiter):
+    return w_seqiter.getlength(space)
 
 
 def iter__ReverseSeqIter(space, w_seqiter):

Modified: pypy/dist/pypy/objspace/std/listobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/listobject.py	(original)
+++ pypy/dist/pypy/objspace/std/listobject.py	Sat Sep 20 23:35:38 2008
@@ -2,13 +2,11 @@
 from pypy.objspace.std.inttype import wrapint
 from pypy.objspace.std.listtype import get_list_index
 from pypy.objspace.std.sliceobject import W_SliceObject
-from pypy.objspace.std.tupleobject import W_TupleObject
 
 from pypy.objspace.std import slicetype
 from pypy.interpreter import gateway, baseobjspace
 from pypy.rlib.listsort import TimSort
 
-
 class W_ListObject(W_Object):
     from pypy.objspace.std.listtype import list_typedef as typedef
     
@@ -26,7 +24,6 @@
     def append(w_list, w_item):
         w_list.wrappeditems.append(w_item)
 
-
 registerimplementation(W_ListObject)
 
 
@@ -95,7 +92,7 @@
 
 def iter__List(space, w_list):
     from pypy.objspace.std import iterobject
-    return iterobject.W_FastSeqIterObject(w_list, w_list.wrappeditems)
+    return iterobject.W_FastListIterObject(w_list, w_list.wrappeditems)
 
 def add__List_List(space, w_list1, w_list2):
     return W_ListObject(w_list1.wrappeditems + w_list2.wrappeditems)
@@ -253,10 +250,6 @@
     l = w_list2.wrappeditems
     return _setitem_slice_helper(space, w_list, w_slice, l, len(l))
 
-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__List_Slice_ANY(space, w_list, w_slice, w_iterable):
     l = space.unpackiterable(w_iterable)
     return _setitem_slice_helper(space, w_list, w_slice, l, len(l))

Modified: pypy/dist/pypy/objspace/std/marshal_impl.py
==============================================================================
--- pypy/dist/pypy/objspace/std/marshal_impl.py	(original)
+++ pypy/dist/pypy/objspace/std/marshal_impl.py	Sat Sep 20 23:35:38 2008
@@ -87,8 +87,7 @@
 put_int(int)                puts an integer
 put_pascal(s)               puts a short string
 put_w_obj(w_obj)            puts a wrapped object
-put_list_w(list_w, lng)     puts a list of lng wrapped objects
-
+put_tuple_w(TYPE, tuple_w)  puts tuple_w, an unwrapped list of wrapped objects
 """
 
 handled_by_any = []
@@ -314,19 +313,17 @@
 register(TYPE_STRINGREF, unmarshal_stringref)
 
 def marshal_w__Tuple(space, w_tuple, m):
-    m.start(TYPE_TUPLE)
     items = w_tuple.wrappeditems
-    m.put_list_w(items, len(items))
+    m.put_tuple_w(TYPE_TUPLE, items)
 
 def unmarshal_Tuple(space, u, tc):
-    items_w = u.get_list_w()
+    items_w = u.get_tuple_w()
     return space.newtuple(items_w)
 register(TYPE_TUPLE, unmarshal_Tuple)
 
 def marshal_w__List(space, w_list, m):
-    m.start(TYPE_LIST)
-    items = w_list.wrappeditems
-    m.put_list_w(items, len(items))
+    items = w_list.wrappeditems[:]
+    m.put_tuple_w(TYPE_LIST, items)
 
 def unmarshal_List(space, u, tc):
     items_w = u.get_list_w()
@@ -346,7 +343,7 @@
 def marshal_w__DictMulti(space, w_dict, m):
     m.start(TYPE_DICT)
     for w_tuple in w_dict.implementation.items():
-        w_key, w_value = space.unpacktuple(w_tuple, 2)
+        w_key, w_value = space.viewiterable(w_tuple, 2)
         m.put_w_obj(w_key)
         m.put_w_obj(w_value)
     m.atom(TYPE_NULL)
@@ -379,8 +376,7 @@
     m.put_int(x.co_stacksize)
     m.put_int(x.co_flags)
     m.atom_str(TYPE_STRING, x.co_code)
-    m.start(TYPE_TUPLE)
-    m.put_list_w(x.co_consts_w, len(x.co_consts_w))
+    m.put_tuple_w(TYPE_TUPLE, x.co_consts_w)
     m.atom_strlist(TYPE_TUPLE, TYPE_INTERNED, [space.str_w(w_name) for w_name in x.co_names_w])
     m.atom_strlist(TYPE_TUPLE, TYPE_INTERNED, x.co_varnames)
     m.atom_strlist(TYPE_TUPLE, TYPE_INTERNED, x.co_freevars)
@@ -423,7 +419,8 @@
     flags       = u.get_int()
     code        = unmarshal_str(u)
     u.start(TYPE_TUPLE)
-    consts_w    = u.get_list_w()
+    consts_w    = u.get_tuple_w()
+    # copy in order not to merge it with anything else
     names       = unmarshal_strlist(u, TYPE_TUPLE)
     varnames    = unmarshal_strlist(u, TYPE_TUPLE)
     freevars    = unmarshal_strlist(u, TYPE_TUPLE)
@@ -460,46 +457,38 @@
 register(TYPE_UNICODE, unmarshal_Unicode)
 
 app = gateway.applevel(r'''
-    def set_to_list(theset):
-        return [item for item in theset]
-
-    def list_to_set(datalist, frozen=False):
+    def tuple_to_set(datalist, frozen=False):
         if frozen:
             return frozenset(datalist)
         return set(datalist)
 ''')
 
-set_to_list = app.interphook('set_to_list')
-list_to_set = app.interphook('list_to_set')
+tuple_to_set = app.interphook('tuple_to_set')
 
 # not directly supported:
 def marshal_w_set(space, w_set, m):
-    w_lis = set_to_list(space, w_set)
     # cannot access this list directly, because it's
     # type is not exactly known through applevel.
-    lis_w = space.unpackiterable(w_lis)
-    m.start(TYPE_SET)
-    m.put_list_w(lis_w, len(lis_w))
+    lis_w = space.viewiterable(w_set)
+    m.put_tuple_w(TYPE_SET, lis_w)
 
 handled_by_any.append( ('set', marshal_w_set) )
 
 # not directly supported:
 def marshal_w_frozenset(space, w_frozenset, m):
-    w_lis = set_to_list(space, w_frozenset)
-    lis_w = space.unpackiterable(w_lis)
-    m.start(TYPE_FROZENSET)
-    m.put_list_w(lis_w, len(lis_w))
+    lis_w = space.viewiterable(w_frozenset)
+    m.put_tuple_w(TYPE_FROZENSET, lis_w)
 
 handled_by_any.append( ('frozenset', marshal_w_frozenset) )
 
 def unmarshal_set_frozenset(space, u, tc):
-    items_w = u.get_list_w()
+    items_w = u.get_tuple_w()
     if tc == TYPE_SET:
         w_frozen = space.w_False
     else:
         w_frozen = space.w_True
-    w_lis = space.newlist(items_w)
-    return list_to_set(space, w_lis, w_frozen)
+    w_tup = space.newtuple(items_w)
+    return tuple_to_set(space, w_tup, w_frozen)
 register(TYPE_SET + TYPE_FROZENSET, unmarshal_set_frozenset)
 
 # dispatching for all not directly dispatched types

Modified: pypy/dist/pypy/objspace/std/model.py
==============================================================================
--- pypy/dist/pypy/objspace/std/model.py	(original)
+++ pypy/dist/pypy/objspace/std/model.py	Sat Sep 20 23:35:38 2008
@@ -103,7 +103,8 @@
             longobject.W_LongObject: [],
             noneobject.W_NoneObject: [],
             iterobject.W_SeqIterObject: [],
-            iterobject.W_FastSeqIterObject: [],
+            iterobject.W_FastListIterObject: [],
+            iterobject.W_FastTupleIterObject: [],
             iterobject.W_ReverseSeqIterObject: [],
             unicodeobject.W_UnicodeObject: [],
             dictproxyobject.W_DictProxyObject: [],

Modified: pypy/dist/pypy/objspace/std/objspace.py
==============================================================================
--- pypy/dist/pypy/objspace/std/objspace.py	(original)
+++ pypy/dist/pypy/objspace/std/objspace.py	Sat Sep 20 23:35:38 2008
@@ -8,6 +8,7 @@
 from pypy.interpreter.pyopcode import unrolling_compare_dispatch_table, \
      BytecodeCorruption
 from pypy.rlib.objectmodel import instantiate
+from pypy.rlib.debug import make_sure_not_resized
 from pypy.interpreter.gateway import PyPyCacheDir
 from pypy.tool.cache import Cache 
 from pypy.tool.sourcetools import func_with_new_name
@@ -378,7 +379,7 @@
             space = self
             # too early for unpackiterable as well :-(
             name  = space.unwrap(space.getitem(w_args, space.wrap(0)))
-            bases = space.unpacktuple(space.getitem(w_args, space.wrap(1)))
+            bases = space.viewiterable(space.getitem(w_args, space.wrap(1)))
             dic   = space.unwrap(space.getitem(w_args, space.wrap(2)))
             dic = dict([(key,space.wrap(value)) for (key, value) in dic.items()])
             bases = list(bases)
@@ -563,6 +564,7 @@
     def newtuple(self, list_w):
         from pypy.objspace.std.tupletype import wraptuple
         assert isinstance(list_w, list)
+        make_sure_not_resized(list_w)
         return wraptuple(self, list_w)
 
     def newlist(self, list_w):
@@ -627,12 +629,32 @@
         return instance
     allocate_instance._annspecialcase_ = "specialize:arg(1)"
 
-    def unpacktuple(self, w_tuple, expected_length=-1):
-        assert isinstance(w_tuple, self.TupleObjectCls)
-        t = w_tuple.getitems()
-        if expected_length != -1 and expected_length != len(t):
-            raise ValueError, "got a tuple of length %d instead of %d" % (
-                len(t), expected_length)
+    # two following functions are almost identical, but in fact they
+    # have different return type. First one is a resizable list, second
+    # one is not
+
+    def unpackiterable(self, w_obj, expected_length=-1):
+        if isinstance(w_obj, W_TupleObject):
+            t = w_obj.wrappeditems[:]
+        elif isinstance(w_obj, W_ListObject):
+            t = w_obj.wrappeditems[:]
+        else:
+            return ObjSpace.unpackiterable(self, w_obj, expected_length)
+        if expected_length != -1 and len(t) != expected_length:
+            raise ValueError("Expected length %d, got %d" % (expected_length, len(t)))
+        return t
+
+    def viewiterable(self, w_obj, expected_length=-1):
+        """ Fast paths
+        """
+        if isinstance(w_obj, W_TupleObject):
+            t = w_obj.wrappeditems
+        elif isinstance(w_obj, W_ListObject):
+            t = w_obj.wrappeditems[:]
+        else:
+            return ObjSpace.viewiterable(self, w_obj, expected_length)
+        if expected_length != -1 and len(t) != expected_length:
+            raise ValueError("Expected length %d, got %d" % (expected_length, len(t)))
         return t
 
     def sliceindices(self, w_slice, w_length):

Modified: pypy/dist/pypy/objspace/std/ropeobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/ropeobject.py	(original)
+++ pypy/dist/pypy/objspace/std/ropeobject.py	Sat Sep 20 23:35:38 2008
@@ -533,7 +533,7 @@
 def str_endswith__Rope_Tuple_ANY_ANY(space, w_self, w_suffixes, w_start, w_end):
     (self, _, start, end) = _convert_idx_params(space, w_self,
                                                   W_RopeObject.EMPTY, w_start, w_end)
-    for w_suffix in space.unpacktuple(w_suffixes):
+    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,
@@ -552,7 +552,7 @@
 def str_startswith__Rope_Tuple_ANY_ANY(space, w_self, w_prefixes, w_start, w_end):
     (self, _, start, end) = _convert_idx_params(space, w_self, W_RopeObject.EMPTY,
                                                   w_start, w_end)
-    for w_prefix in space.unpacktuple(w_prefixes):
+    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,

Modified: pypy/dist/pypy/objspace/std/ropeunicodeobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/ropeunicodeobject.py	(original)
+++ pypy/dist/pypy/objspace/std/ropeunicodeobject.py	Sat Sep 20 23:35:38 2008
@@ -485,7 +485,7 @@
 def unicode_startswith__RopeUnicode_Tuple_ANY_ANY(space, w_unistr, w_prefixes,
                                               w_start, w_end):
     unistr, start, end = _convert_idx_params(space, w_unistr, w_start, w_end)
-    for w_prefix in space.unpacktuple(w_prefixes):
+    for w_prefix in space.viewiterable(w_prefixes):
         prefix = ropeunicode_w(space, w_prefix)
         if rope.startswith(unistr, prefix, start, end):
             return space.w_True
@@ -494,7 +494,7 @@
 def unicode_endswith__RopeUnicode_Tuple_ANY_ANY(space, w_unistr, w_suffixes,
                                             w_start, w_end):
     unistr, start, end = _convert_idx_params(space, w_unistr, w_start, w_end)
-    for w_suffix in space.unpacktuple(w_suffixes):
+    for w_suffix in space.viewiterable(w_suffixes):
         suffix = ropeunicode_w(space, w_suffix)
         if rope.endswith(unistr, suffix, start, end):
             return space.w_True

Modified: pypy/dist/pypy/objspace/std/stringobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/stringobject.py	(original)
+++ pypy/dist/pypy/objspace/std/stringobject.py	Sat Sep 20 23:35:38 2008
@@ -593,7 +593,7 @@
 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)
-    for w_suffix in space.unpacktuple(w_suffixes):
+    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,
@@ -611,7 +611,7 @@
 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)
-    for w_prefix in space.unpacktuple(w_prefixes):
+    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,

Modified: pypy/dist/pypy/objspace/std/strsliceobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/strsliceobject.py	(original)
+++ pypy/dist/pypy/objspace/std/strsliceobject.py	Sat Sep 20 23:35:38 2008
@@ -141,7 +141,7 @@
 def str_endswith__StringSlice_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)
-    for w_suffix in space.unpacktuple(w_suffixes):
+    for w_suffix in space.viewiterable(w_suffixes):
         suffix = space.str_w(w_suffix) 
         if stringendswith(u_self, suffix, start, end):
             return space.w_True
@@ -155,7 +155,7 @@
 def str_startswith__StringSlice_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)
-    for w_prefix in space.unpacktuple(w_prefixes):
+    for w_prefix in space.viewiterable(w_prefixes):
         prefix = space.str_w(w_prefix)
         if stringstartswith(u_self, prefix, start, end):
             return space.w_True

Modified: pypy/dist/pypy/objspace/std/tupleobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/tupleobject.py	(original)
+++ pypy/dist/pypy/objspace/std/tupleobject.py	Sat Sep 20 23:35:38 2008
@@ -3,11 +3,13 @@
 from pypy.rlib.rarithmetic import intmask
 from pypy.objspace.std.sliceobject import W_SliceObject
 from pypy.interpreter import gateway
+from pypy.rlib.debug import make_sure_not_resized
 
 class W_TupleObject(W_Object):
     from pypy.objspace.std.tupletype import tuple_typedef as typedef
     
     def __init__(w_self, wrappeditems):
+        make_sure_not_resized(wrappeditems)
         w_self.wrappeditems = wrappeditems   # a list of wrapped values
 
     def __repr__(w_self):
@@ -19,9 +21,6 @@
         items = [space.unwrap(w_item) for w_item in w_tuple.wrappeditems] # XXX generic mixed types unwrap
         return tuple(items)
 
-    def getitems(self):
-        return self.wrappeditems
-
 registerimplementation(W_TupleObject)
 
 
@@ -62,7 +61,7 @@
 
 def iter__Tuple(space, w_tuple):
     from pypy.objspace.std import iterobject
-    return iterobject.W_FastSeqIterObject(w_tuple, w_tuple.wrappeditems)
+    return iterobject.W_FastTupleIterObject(w_tuple, w_tuple.wrappeditems)
 
 def add__Tuple_Tuple(space, w_tuple1, w_tuple2):
     items1 = w_tuple1.wrappeditems

Modified: pypy/dist/pypy/objspace/std/tupletype.py
==============================================================================
--- pypy/dist/pypy/objspace/std/tupletype.py	(original)
+++ pypy/dist/pypy/objspace/std/tupletype.py	Sat Sep 20 23:35:38 2008
@@ -13,7 +13,7 @@
           space.is_w(space.type(w_sequence), space.w_tuple)):
         return w_sequence
     else:
-        tuple_w = space.unpackiterable(w_sequence)
+        tuple_w = space.viewiterable(w_sequence)
     w_obj = space.allocate_instance(space.TupleObjectCls, w_tupletype)
     space.TupleObjectCls.__init__(w_obj, tuple_w)
     return w_obj

Modified: pypy/dist/pypy/objspace/std/typeobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/typeobject.py	(original)
+++ pypy/dist/pypy/objspace/std/typeobject.py	Sat Sep 20 23:35:38 2008
@@ -545,10 +545,10 @@
         if not space.is_w(w_where, space.w_type):
             w_mro_meth = space.get(w_mro_func, w_self)
             w_mro = space.call_function(w_mro_meth)
-            w_self.mro_w = space.unpackiterable(w_mro)
+            w_self.mro_w = space.viewiterable(w_mro)
             # do some checking here
             return    # done
-    w_self.mro_w = w_self.compute_default_mro()
+    w_self.mro_w = w_self.compute_default_mro()[:]
 
 # ____________________________________________________________
 

Modified: pypy/dist/pypy/objspace/std/typetype.py
==============================================================================
--- pypy/dist/pypy/objspace/std/typetype.py	(original)
+++ pypy/dist/pypy/objspace/std/typetype.py	Sat Sep 20 23:35:38 2008
@@ -11,7 +11,7 @@
 
     w_typetype = _precheck_for_new(space, w_typetype)
     
-    bases_w = space.unpackiterable(w_bases)
+    bases_w = space.viewiterable(w_bases)
 
     w_winner = w_typetype
     for base in bases_w:
@@ -115,7 +115,7 @@
                                         " to %s.__bases__, not %s"%
                                     (w_type.name,
                                      space.type(w_value).getname(space, '?'))))
-    newbases_w = space.unpackiterable(w_value)
+    newbases_w = space.viewiterable(w_value)
     if len(newbases_w) == 0:
         raise OperationError(space.w_TypeError,
                              space.wrap("can only assign non-empty tuple"

Modified: pypy/dist/pypy/objspace/std/unicodeobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/unicodeobject.py	(original)
+++ pypy/dist/pypy/objspace/std/unicodeobject.py	Sat Sep 20 23:35:38 2008
@@ -474,7 +474,7 @@
 def unicode_startswith__Unicode_Tuple_ANY_ANY(space, w_unistr, w_prefixes,
                                               w_start, w_end):
     unistr, start, end = _convert_idx_params(space, w_unistr, w_start, w_end)
-    for w_prefix in space.unpacktuple(w_prefixes):
+    for w_prefix in space.viewiterable(w_prefixes):
         prefix = space.unicode_w(w_prefix)
         if _check_startswith_substring(unistr, prefix, start, end):
             return space.w_True
@@ -483,7 +483,7 @@
 def unicode_endswith__Unicode_Tuple_ANY_ANY(space, w_unistr, w_suffixes,
                                             w_start, w_end):
     unistr, start, end = _convert_idx_params(space, w_unistr, w_start, w_end)
-    for w_suffix in space.unpacktuple(w_suffixes):
+    for w_suffix in space.viewiterable(w_suffixes):
         suffix = space.unicode_w(w_suffix)
         if _check_endswith_substring(unistr, suffix, start, end):
             return space.w_True

Modified: pypy/dist/pypy/rlib/debug.py
==============================================================================
--- pypy/dist/pypy/rlib/debug.py	(original)
+++ pypy/dist/pypy/rlib/debug.py	Sat Sep 20 23:35:38 2008
@@ -64,7 +64,7 @@
     callable which checks if annotation is as expected,
     arguments passed are (current annotation, bookkeeper)
     """
-    pass
+    return arg
 
 class Entry(ExtRegistryEntry):
     _about_ = check_annotation
@@ -80,3 +80,27 @@
         hop.exception_cannot_occur()
         return hop.inputarg(hop.args_r[0], arg=0)
 
+def make_sure_not_resized(arg):
+    """ Function checking whether annotation of SomeList is never resized,
+    useful for debugging. Does nothing when run directly
+    """
+    return arg
+
+class Entry(ExtRegistryEntry):
+    _about_ = make_sure_not_resized
+
+    def compute_result_annotation(self, s_arg):
+        from pypy.annotation.model import SomeList
+        assert isinstance(s_arg, SomeList)
+        # the logic behind it is that we try not to propagate
+        # make_sure_not_resized, when list comprehension is not on
+        if self.bookkeeper.annotator.translator.config.translation.list_comprehension_operations:
+            s_arg.listdef.never_resize()
+        else:
+            from pypy.annotation.annrpython import log
+            log.WARNING('make_sure_not_resized called, but has no effect since list_comprehension is off')
+        return s_arg
+    
+    def specialize_call(self, hop):
+        hop.exception_cannot_occur()
+        return hop.inputarg(hop.args_r[0], arg=0)

Modified: pypy/dist/pypy/rlib/test/test_debug.py
==============================================================================
--- pypy/dist/pypy/rlib/test/test_debug.py	(original)
+++ pypy/dist/pypy/rlib/test/test_debug.py	Sat Sep 20 23:35:38 2008
@@ -1,6 +1,6 @@
 
 import py
-from pypy.rlib.debug import check_annotation
+from pypy.rlib.debug import check_annotation, make_sure_not_resized
 from pypy.rpython.test.test_llinterp import interpret
 
 def test_check_annotation():
@@ -27,3 +27,12 @@
 
     py.test.raises(Error, "interpret(g, [3])")
 
+def test_make_sure_not_resized():
+    from pypy.annotation.listdef import TooLateForChange
+    def f():
+        result = [1,2,3]
+        make_sure_not_resized(result)
+        result.append(4)
+        return len(result)
+
+    py.test.raises(TooLateForChange, interpret, f, [])

Modified: pypy/dist/pypy/rpython/callparse.py
==============================================================================
--- pypy/dist/pypy/rpython/callparse.py	(original)
+++ pypy/dist/pypy/rpython/callparse.py	Sat Sep 20 23:35:38 2008
@@ -176,7 +176,7 @@
             if (expected_length is not None and
                 expected_length != len(items)):
                 raise ValueError
-            return items
+            return list(items)
         raise CallPatternTooComplex, "'*' argument must be a tuple"
 
     def is_w(self, one, other):



More information about the Pypy-commit mailing list