Index: Include/methodobject.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/methodobject.h,v retrieving revision 2.27 diff -c -r2.27 methodobject.h *** Include/methodobject.h 13 Dec 2003 11:26:10 -0000 2.27 --- Include/methodobject.h 11 Jan 2004 10:29:12 -0000 *************** *** 52,57 **** --- 52,59 ---- #define METH_NOARGS 0x0004 #define METH_O 0x0008 + #define METH_CALLING_CONVENTION (METH_VARARGS|METH_KEYWORDS|METH_NOARGS|METH_O) + /* METH_CLASS and METH_STATIC are a little different; these control the construction of methods for a class. These cannot be used for functions in modules. */ *************** *** 64,69 **** --- 66,77 ---- slot like sq_contains. */ #define METH_COEXIST 0x0040 + + /* METH_FAST_ITER gives a method a default keyword argument + 'iter=True' when it is called in a position where we know that + we only need an iterator instead of a full object. */ + #define METH_FAST_ITER 0x0080 + PyAPI_FUNC(int) _Py_CheckIterKeyword(PyObject *); typedef struct PyMethodChain { PyMethodDef *methods; /* Methods of this type */ Index: Include/rangeobject.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/rangeobject.h,v retrieving revision 2.19 diff -c -r2.19 rangeobject.h *** Include/rangeobject.h 12 Aug 2002 07:21:57 -0000 2.19 --- Include/rangeobject.h 11 Jan 2004 10:29:12 -0000 *************** *** 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 } Index: Objects/methodobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/methodobject.c,v retrieving revision 2.48 diff -c -r2.48 methodobject.c *** Objects/methodobject.c 13 Dec 2003 11:26:11 -0000 2.48 --- Objects/methodobject.c 11 Jan 2004 10:29:23 -0000 *************** *** 67,73 **** PyObject *self = PyCFunction_GET_SELF(func); int size; ! switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST)) { case METH_VARARGS: if (kw == NULL || PyDict_Size(kw) == 0) return (*meth)(self, arg); --- 67,73 ---- PyObject *self = PyCFunction_GET_SELF(func); int size; ! switch (PyCFunction_GET_FLAGS(func) & METH_CALLING_CONVENTION) { case METH_VARARGS: if (kw == NULL || PyDict_Size(kw) == 0) return (*meth)(self, arg); *************** *** 115,120 **** --- 115,151 ---- PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments", f->m_ml->ml_name); return NULL; + } + + int + _Py_CheckIterKeyword(PyObject *kwds) + { + int iter = 0; + if (kwds != NULL) { + char *ks; + PyObject *key, *value; + int pos = 0; + while (PyDict_Next(kwds, &pos, &key, &value)) { + /* make sure we only get the 'iter' keyword argument */ + if (!PyString_Check(key)) { + PyErr_SetString(PyExc_TypeError, + "keywords must be strings"); + return -1; + } + ks = PyString_AsString(key); + if (strcmp(ks, "iter")) { + PyErr_Format(PyExc_TypeError, + "'%s' is an invalid keyword " + "argument for this function", + ks); + return -1; + } + iter = PyObject_IsTrue(value); + if (iter < 0) + return -1; + } + } + return iter; } /* Methods (the standard built-in methods, that is) */ Index: Objects/rangeobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/rangeobject.c,v retrieving revision 2.49 diff -c -r2.49 rangeobject.c *** Objects/rangeobject.c 6 Nov 2003 14:06:47 -0000 2.49 --- Objects/rangeobject.c 11 Jan 2004 10:29:24 -0000 *************** *** 235,257 **** 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 * --- 235,264 ---- static PyTypeObject Pyrangeiter_Type; ! PyObject * ! PyRangeIter_New(long start, long step, long len) { 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)->step, + ((rangeobject *)seq)->len); } static PyObject * Index: Python/bltinmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/bltinmodule.c,v retrieving revision 2.307 diff -c -r2.307 bltinmodule.c *** Python/bltinmodule.c 4 Jan 2004 11:00:07 -0000 2.307 --- Python/bltinmodule.c 11 Jan 2004 10:29:26 -0000 *************** *** 1469,1475 **** } static PyObject * ! builtin_range(PyObject *self, PyObject *args) { long ilow = 0, ihigh = 0, istep = 1; long bign; --- 1469,1475 ---- } static PyObject * ! builtin_range(PyObject *self, PyObject *args, PyObject *kwds) { long ilow = 0, ihigh = 0, istep = 1; long bign; *************** *** 1508,1513 **** --- 1508,1523 ---- "range() result has too many items"); return NULL; } + + /* check for the 'iter' keyword argument */ + i = _Py_CheckIterKeyword(kwds); + if (i) { + if (i < 0) + return NULL; + else + return PyRangeIter_New(ilow, istep, n); + } + v = PyList_New(n); if (v == NULL) return NULL; *************** *** 2084,2090 **** {"oct", builtin_oct, METH_O, oct_doc}, {"ord", builtin_ord, METH_O, ord_doc}, {"pow", builtin_pow, METH_VARARGS, pow_doc}, ! {"range", builtin_range, METH_VARARGS, range_doc}, {"raw_input", builtin_raw_input, METH_VARARGS, raw_input_doc}, {"reduce", builtin_reduce, METH_VARARGS, reduce_doc}, {"reload", builtin_reload, METH_O, reload_doc}, --- 2094,2100 ---- {"oct", builtin_oct, METH_O, oct_doc}, {"ord", builtin_ord, METH_O, ord_doc}, {"pow", builtin_pow, METH_VARARGS, pow_doc}, ! {"range", (PyCFunction)builtin_range, METH_VARARGS | METH_KEYWORDS | METH_FAST_ITER, range_doc}, {"raw_input", builtin_raw_input, METH_VARARGS, raw_input_doc}, {"reduce", builtin_reduce, METH_VARARGS, reduce_doc}, {"reload", builtin_reload, METH_O, reload_doc}, Index: Python/ceval.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/ceval.c,v retrieving revision 2.373 diff -c -r2.373 ceval.c *** Python/ceval.c 20 Nov 2003 01:44:58 -0000 2.373 --- Python/ceval.c 11 Jan 2004 10:29:30 -0000 *************** *** 29,35 **** /* Forward declarations */ static PyObject *eval_frame(PyFrameObject *); ! static PyObject *call_function(PyObject ***, int); static PyObject *fast_function(PyObject *, PyObject ***, int, int, int); static PyObject *do_call(PyObject *, PyObject ***, int, int); static PyObject *ext_do_call(PyObject *, PyObject ***, int, int, int); --- 29,35 ---- /* Forward declarations */ static PyObject *eval_frame(PyFrameObject *); ! static PyObject *call_function(PyObject ***, int, unsigned char*); static PyObject *fast_function(PyObject *, PyObject ***, int, int, int); static PyObject *do_call(PyObject *, PyObject ***, int, int); static PyObject *ext_do_call(PyObject *, PyObject ***, int, int, int); *************** *** 2124,2130 **** case CALL_FUNCTION: PCALL(PCALL_ALL); ! x = call_function(&stack_pointer, oparg); PUSH(x); if (x != NULL) continue; --- 2124,2130 ---- case CALL_FUNCTION: PCALL(PCALL_ALL); ! x = call_function(&stack_pointer, oparg, next_instr); PUSH(x); if (x != NULL) continue; *************** *** 3415,3421 **** } static PyObject * ! call_function(PyObject ***pp_stack, int oparg) { int na = oparg & 0xff; int nk = (oparg>>8) & 0xff; --- 3415,3421 ---- } static PyObject * ! call_function(PyObject ***pp_stack, int oparg, unsigned char *next_instr) { int na = oparg & 0xff; int nk = (oparg>>8) & 0xff; *************** *** 3447,3455 **** } else { PyObject *callargs; callargs = load_args(pp_stack, na); ! x = PyCFunction_Call(func, callargs, NULL); ! Py_XDECREF(callargs); } } else { if (PyMethod_Check(func) && PyMethod_GET_SELF(func) != NULL) { --- 3447,3476 ---- } else { PyObject *callargs; + PyObject *kwdict; callargs = load_args(pp_stack, na); ! if (callargs == NULL) ! return NULL; ! if (flags & METH_FAST_ITER && *next_instr == GET_ITER) { ! static PyObject *iterdict = NULL; ! if (iterdict == NULL) { ! /* iterdict = {"iter": True} */ ! iterdict = PyDict_New(); ! if (iterdict == NULL || ! PyDict_SetItemString(iterdict, ! "iter", ! Py_True)) { ! Py_DECREF(callargs); ! return NULL; ! } ! } ! kwdict = iterdict; ! } ! else { ! kwdict = NULL; ! } ! x = PyCFunction_Call(func, callargs, kwdict); ! Py_DECREF(callargs); } } else { if (PyMethod_Check(func) && PyMethod_GET_SELF(func) != NULL) {