[Python-Dev] Memory management in the AST parser & compiler

"Martin v. Löwis" martin at v.loewis.de
Tue Nov 29 01:21:38 CET 2005

Neal Norwitz wrote:
> Hope this helps explain a bit.  Please speak up with how this can be
> improved.  Gotta run.

I would rewrite it as

static PyObject*
ast_for_funcdef(struct compiling *c, const node *n)
     /* funcdef: [decorators] 'def' NAME parameters ':' suite */
     PyObject *name = NULL;
     PyObject *args = NULL;
     PyObject *body = NULL;
     PyObject *decorator_seq = NULL;
     PyObject *result = NULL;
     int name_i;

     REQ(n, funcdef);

     if (NCH(n) == 6) { /* decorators are present */
	decorator_seq = ast_for_decorators(c, CHILD(n, 0));
	if (!decorator_seq)
	    goto error;
	name_i = 2;
     else {
	name_i = 1;

     name = NEW_IDENTIFIER(CHILD(n, name_i));
     if (!name)
	goto error;
     else if (!strcmp(STR(CHILD(n, name_i)), "None")) {
	ast_error(CHILD(n, name_i), "assignment to None");
	goto error;
     args = ast_for_arguments(c, CHILD(n, name_i + 1));
     if (!args)
	goto error;
     body = ast_for_suite(c, CHILD(n, name_i + 3));
     if (!body)
	goto error;

     result = FunctionDef(name, args, body, decorator_seq, LINENO(n));

     return result;

The convention would be that ast_for_* returns new references, which
have to be released regardless of success or failure. FunctionDef
would duplicate all of its parameter references if it succeeds,
and leave them untouched if it fails.

One could develop a checker that verifies that:
a) all PyObject* local variables are initialized to NULL, and
b) all such variables are Py_XDECREF'ed after the error label.
c) result is initialized to NULL, and returned.
Then, "goto error" at any point in the code would be correct
(assuming an exception had been set prior to the goto).

No special release function for the body or the decorators
would be necessary - they would be plain Python lists.


More information about the Python-Dev mailing list