summaryrefslogtreecommitdiffstats
path: root/Include/funcobject.h
diff options
context:
space:
mode:
authorArmin Rigo <arigo@tunes.org>2004-10-28 16:32:00 (GMT)
committerArmin Rigo <arigo@tunes.org>2004-10-28 16:32:00 (GMT)
commit89a39461bff04b80bb4857790350e1ab30ff2df9 (patch)
tree54bc00a9ad30e8e49849874cfbca8543de62fa58 /Include/funcobject.h
parent063e1e846dc5c3fe593cef5b14cc429369dcd2c2 (diff)
downloadcpython-89a39461bff04b80bb4857790350e1ab30ff2df9.zip
cpython-89a39461bff04b80bb4857790350e1ab30ff2df9.tar.gz
cpython-89a39461bff04b80bb4857790350e1ab30ff2df9.tar.bz2
Wrote down the invariants of some common objects whose structure is
exposed in header files. Fixed a few comments in these headers. As we might have expected, writing down invariants systematically exposed a (minor) bug. In this case, function objects have a writeable func_code attribute, which could be set to code objects with the wrong number of free variables. Calling the resulting function segfaulted the interpreter. Added a corresponding test.
Diffstat (limited to 'Include/funcobject.h')
-rw-r--r--Include/funcobject.h35
1 files changed, 26 insertions, 9 deletions
diff --git a/Include/funcobject.h b/Include/funcobject.h
index 758c76d..59c19bb 100644
--- a/Include/funcobject.h
+++ b/Include/funcobject.h
@@ -7,17 +7,34 @@
extern "C" {
#endif
+/* Function objects and code objects should not be confused with each other:
+ *
+ * Function objects are created by the execution of the 'def' statement.
+ * They reference a code object in their func_code attribute, which is a
+ * purely syntactic object, i.e. nothing more than a compiled version of some
+ * source code lines. There is one code object per source code "fragment",
+ * but each code object can be referenced by zero or many function objects
+ * depending only on how many times the 'def' statement in the source was
+ * executed so far.
+ */
+
typedef struct {
PyObject_HEAD
- PyObject *func_code;
- PyObject *func_globals;
- PyObject *func_defaults;
- PyObject *func_closure;
- PyObject *func_doc;
- PyObject *func_name;
- PyObject *func_dict;
- PyObject *func_weakreflist;
- PyObject *func_module;
+ PyObject *func_code; /* A code object */
+ PyObject *func_globals; /* A dictionary (other mappings won't do) */
+ PyObject *func_defaults; /* NULL or a tuple */
+ PyObject *func_closure; /* NULL or a tuple of cell objects */
+ PyObject *func_doc; /* The __doc__ attribute, can be anything */
+ PyObject *func_name; /* The __name__ attribute, a string object */
+ PyObject *func_dict; /* The __dict__ attribute, a dict or NULL */
+ PyObject *func_weakreflist; /* List of weak references */
+ PyObject *func_module; /* The __module__ attribute, can be anything */
+
+ /* Invariant:
+ * func_closure contains the bindings for func_code->co_freevars, so
+ * PyTuple_Size(func_closure) == PyCode_GetNumFree(func_code)
+ * (func_closure may be NULL if PyCode_GetNumFree(func_code) == 0).
+ */
} PyFunctionObject;
PyAPI_DATA(PyTypeObject) PyFunction_Type;