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)); error: Py_XDECREF(name); Py_XDECREF(args); Py_XDECREF(body); Py_XDECREF(decorator_seq); 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. Regards, Martin _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com