*** Python-2.3b1.orig/Python/bltinmodule.c Fri May 9 10:38:36 2003 --- Python-2.3b1/Python/bltinmodule.c Fri May 9 14:10:15 2003 *************** *** 13,18 **** --- 13,36 ---- #include "unixstuff.h" #endif + /* return 1 if the object will only be used for iteration. */ + #include "frameobject.h" + #include "opcode.h" + int Py_IsIterationContext(void) + { + PyFrameObject *frame = PyThreadState_Get()->frame; + if (frame) { + unsigned char *opcode; + PyCodeObject* c = frame->f_code; + _PyCode_GETCODEPTR(c, &opcode); + /*we are always called by a CALL_FUNCTION opcode (1 arg)*/ + if (*(opcode + frame->f_lasti + 3) == GET_ITER) { + return 1; + } + } + return 0; + } + /* The default encoding used by the platform file system APIs Can remain NULL for all platforms that don't have such a concept */ *************** *** 1487,1494 **** long bign; int i, n; - PyObject *v; - if (PyTuple_Size(args) <= 1) { if (!PyArg_ParseTuple(args, "l;range() requires 1-3 int arguments", --- 1505,1510 ---- *************** *** 1520,1538 **** "range() result has too many items"); return NULL; } ! v = PyList_New(n); ! if (v == NULL) ! return NULL; ! for (i = 0; i < n; i++) { ! PyObject *w = PyInt_FromLong(ilow); ! if (w == NULL) { ! Py_DECREF(v); return NULL; } ! PyList_SET_ITEM(v, i, w); ! ilow += istep; } - return v; } PyDoc_STRVAR(range_doc, --- 1536,1563 ---- "range() result has too many items"); return NULL; } ! ! // Avoid the creation of the list object in the really common ! // piece of code "for i in range(N):" ! if (Py_IsIterationContext()) { ! return PyRangeIter_New(ilow, n, istep); ! } ! else { ! PyObject* v = PyList_New(n); ! if (v == NULL) { return NULL; } ! for (i = 0; i < n; i++) { ! PyObject *w = PyInt_FromLong(ilow); ! if (w == NULL) { ! Py_DECREF(v); ! return NULL; ! } ! PyList_SET_ITEM(v, i, w); ! ilow += istep; ! } ! return v; } } PyDoc_STRVAR(range_doc, *** Python-2.3b1.orig/Objects/rangeobject.c Fri May 9 10:38:33 2003 --- Python-2.3b1/Objects/rangeobject.c Fri May 9 14:14:21 2003 *************** *** 226,248 **** static PyTypeObject Pyrangeiter_Type; ! static PyObject * ! range_iter(PyObject *seq) { rangeiterobject *it; - if (!PyRange_Check(seq)) { - PyErr_BadInternalCall(); - return NULL; - } it = PyObject_New(rangeiterobject, &Pyrangeiter_Type); if (it == NULL) return NULL; it->index = 0; ! it->start = ((rangeobject *)seq)->start; ! it->step = ((rangeobject *)seq)->step; ! it->len = ((rangeobject *)seq)->len; ! return (PyObject *)it; } static PyObject * --- 226,256 ---- static PyTypeObject Pyrangeiter_Type; ! PyObject * ! PyRangeIter_New(long start, long len, long step) { rangeiterobject *it; it = PyObject_New(rangeiterobject, &Pyrangeiter_Type); if (it == NULL) return NULL; it->index = 0; ! it->start = start; ! it->step = step; ! it->len = len; ! return (PyObject *)it; ! } ! ! static PyObject * ! range_iter(PyObject *seq) ! { ! if (!PyRange_Check(seq)) { ! PyErr_BadInternalCall(); ! return NULL; ! } ! return PyRangeIter_New(((rangeobject *)seq)->start, ! ((rangeobject *)seq)->len, ! ((rangeobject *)seq)->step); } static PyObject * *** Python-2.3b1.orig/Include/rangeobject.h Fri May 9 10:38:15 2003 --- Python-2.3b1/Include/rangeobject.h Fri May 9 10:40:18 2003 *************** *** 20,25 **** --- 20,26 ---- #define PyRange_Check(op) ((op)->ob_type == &PyRange_Type) PyAPI_FUNC(PyObject *) PyRange_New(long, long, long, int); + PyAPI_FUNC(PyObject *) PyRangeIter_New(long, long, long); #ifdef __cplusplus } *** Python-2.3b1.orig/Lib/test/test_builtin.py Fri May 9 10:38:20 2003 --- Python-2.3b1/Lib/test/test_builtin.py Fri May 9 12:16:10 2003 *************** *** 927,932 **** --- 927,945 ---- self.assertEqual(range(1, 10, 3), [1, 4, 7]) self.assertEqual(range(5, -5, -3), [5, 2, -1, -4]) + # Check special case optimization + def for_range(*args): + r = [] + for i in range(*args): + r.append(i) + return r + self.assertEqual(for_range(3), [0, 1, 2]) + self.assertEqual(for_range(1, 5), [1, 2, 3, 4]) + self.assertEqual(for_range(0), []) + self.assertEqual(for_range(-3), []) + self.assertEqual(for_range(1, 10, 3), [1, 4, 7]) + self.assertEqual(for_range(5, -5, -3), [5, 2, -1, -4]) + # Now test range() with longs self.assertEqual(range(-2**100), []) self.assertEqual(range(0, -2**100), [])