[Python-checkins] python/dist/src/Objects funcobject.c,2.55,2.56

jhylton@users.sourceforge.net jhylton@users.sourceforge.net
Thu, 11 Jul 2002 11:30:30 -0700


Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv2891/Objects

Modified Files:
	funcobject.c 
Log Message:
Extend function() to support an optional closure argument.

Also, simplify some ref counting for other optional arguments.


Index: funcobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/funcobject.c,v
retrieving revision 2.55
retrieving revision 2.56
diff -C2 -d -r2.55 -r2.56
*** funcobject.c	14 Jun 2002 20:41:15 -0000	2.55
--- funcobject.c	11 Jul 2002 18:30:27 -0000	2.56
***************
*** 268,291 ****
  
  PyDoc_STRVAR(func_doc,
! "function(code, globals[, name[, argdefs]])\n\
  \n\
  Create a function object from a code object and a dictionary.\n\
  The optional name string overrides the name from the code object.\n\
! The optional argdefs tuple specifies the default argument values.");
  
  static PyObject *
  func_new(PyTypeObject* type, PyObject* args, PyObject* kw)
  {
! 	PyObject *code;
  	PyObject *globals;
  	PyObject *name = Py_None;
  	PyObject *defaults = Py_None;
  	PyFunctionObject *newfunc;
  
! 	if (!PyArg_ParseTuple(args, "O!O!|OO!:function",
  			      &PyCode_Type, &code,
  			      &PyDict_Type, &globals,
! 			      &name,
! 			      &PyTuple_Type, &defaults))
  		return NULL;
  	if (name != Py_None && !PyString_Check(name)) {
--- 268,303 ----
  
  PyDoc_STRVAR(func_doc,
! "function(code, globals[, name[, argdefs[, closure]]])\n\
  \n\
  Create a function object from a code object and a dictionary.\n\
  The optional name string overrides the name from the code object.\n\
! The optional argdefs tuple specifies the default argument values.\n\
! The optional closure tuple supplies the bindings for free variables.");
! 
! /* func_new() maintains the following invariants for closures.  The
!    closure must correspond to the free variables of the code object.
!    
!    if len(code.co_freevars) == 0: 
!            closure = NULL
!    else:
!            len(closure) == len(code.co_freevars)
!    for every elt in closure, type(elt) == cell
! */
  
  static PyObject *
  func_new(PyTypeObject* type, PyObject* args, PyObject* kw)
  {
! 	PyCodeObject *code;
  	PyObject *globals;
  	PyObject *name = Py_None;
  	PyObject *defaults = Py_None;
+ 	PyObject *closure = Py_None;
  	PyFunctionObject *newfunc;
+ 	int nfree, nclosure;
  
! 	if (!PyArg_ParseTuple(args, "O!O!|OOO:function",
  			      &PyCode_Type, &code,
  			      &PyDict_Type, &globals,
! 			      &name, &defaults, &closure))
  		return NULL;
  	if (name != Py_None && !PyString_Check(name)) {
***************
*** 294,311 ****
  		return NULL;
  	}
  
! 	newfunc = (PyFunctionObject *)PyFunction_New(code, globals);
  	if (newfunc == NULL)
  		return NULL;
! 
  	if (name != Py_None) {
! 		Py_XINCREF(name);
! 		Py_XDECREF(newfunc->func_name);
  		newfunc->func_name = name;
  	}
  	if (defaults != Py_None) {
! 		Py_XINCREF(defaults);
! 		Py_XDECREF(newfunc->func_defaults);
  		newfunc->func_defaults  = defaults;
  	}
  
--- 306,364 ----
  		return NULL;
  	}
+ 	if (defaults != Py_None && !PyTuple_Check(defaults)) {
+ 		PyErr_SetString(PyExc_TypeError,
+ 				"arg 4 (defaults) must be None or tuple");
+ 		return NULL;
+ 	}
+ 	nfree = PyTuple_GET_SIZE(code->co_freevars);
+ 	if (!PyTuple_Check(closure)) {
+ 		if (nfree && closure == Py_None) {
+ 			PyErr_SetString(PyExc_TypeError,
+ 					"arg 5 (closure) must be tuple");
+ 			return NULL;
+ 		}
+ 		else if (closure != Py_None) {
+ 			PyErr_SetString(PyExc_TypeError,
+ 				"arg 5 (closure) must be None or tuple");
+ 			return NULL;
+ 		}
+ 	}
  
! 	/* check that the closure is well-formed */
! 	nclosure = closure == Py_None ? 0 : PyTuple_GET_SIZE(closure);
! 	if (nfree != nclosure)
! 		return PyErr_Format(PyExc_ValueError,
! 				    "%s requires closure of length %d, not %d",
! 				    PyString_AS_STRING(code->co_name),
! 				    nfree, nclosure);
! 	if (nclosure) {
! 		int i;
! 		for (i = 0; i < nclosure; i++) {
! 			PyObject *o = PyTuple_GET_ITEM(closure, i);
! 			if (!PyCell_Check(o)) {
! 				return PyErr_Format(PyExc_TypeError,
! 				    "arg 5 (closure) expected cell, found %s",
! 						    o->ob_type->tp_name);
! 			}
! 		}
! 	}
! 	
! 	newfunc = (PyFunctionObject *)PyFunction_New((PyObject *)code, 
! 						     globals);
  	if (newfunc == NULL)
  		return NULL;
! 	
  	if (name != Py_None) {
! 		Py_INCREF(name);
! 		Py_DECREF(newfunc->func_name);
  		newfunc->func_name = name;
  	}
  	if (defaults != Py_None) {
! 		Py_INCREF(defaults);
  		newfunc->func_defaults  = defaults;
+ 	}
+ 	if (closure != Py_None) {
+ 		Py_INCREF(closure);
+ 		newfunc->func_closure = closure;
  	}