[Compiler-sig] Error checking macros

Neal Norwitz neal@metaslash.com
Fri, 19 Apr 2002 09:36:50 -0400


Skip Montanaro wrote:
> 
>     Neal> I don't know if others have seen the following technique before.
>     Neal> Eric and I have used it to greatly reduce lines of code for error
>     Neal> checking.
> 
> This looks like it would be okay as long as you only call it when you hold
> no references to Python objects.  In Python code you frequently can't just
> return NULL, but have to DECREF some Python objects first.  I don't know if
> this problem will arise here (I don't see a lot of context in your example -
> is it just for NULL checking input args?), but I assume it might.

In this case, yes, I am only talking about checking input args.
This is for generated code which is very regular.  It's used
to store AST info.

Here's a bit more context.  I actually wrote code to test this.
The old code for a function looked like this:

stmt_ty
ClassDef(identifier name, asdl_seq * bases, asdl_seq * body)
{
        stmt_ty p;
        if (!name) {
                PyErr_SetString(PyExc_ValueError,
                                "field name is required for ClassDef");
                return NULL;
        }
        if (!bases) {
                PyErr_SetString(PyExc_ValueError,
                                "field bases is required for ClassDef");
                return NULL;
        }
        if (!body) {
                PyErr_SetString(PyExc_ValueError,
                                "field body is required for ClassDef");
                return NULL;
        }
        p = (stmt_ty)malloc(sizeof(*p));
        if (!p) {
                PyErr_SetString(PyExc_MemoryError, "no memory");
                return NULL;
        }
        p->kind = ClassDef_kind;
        p->v.ClassDef.name = name;
        p->v.ClassDef.bases = bases;
        p->v.ClassDef.body = body;
        return p;
}



The new code looks like this:

stmt_ty
ClassDef(identifier name, asdl_seq * bases, asdl_seq * body)
{
        stmt_ty p;
        ERR_NULL_CHECK(name, "ClassDef");
        ERR_NULL_CHECK(bases, "ClassDef");
        ERR_NULL_CHECK(body, "ClassDef");
        CHECK_MALLOC(p, stmt_ty);

        p->kind = ClassDef_kind;
        p->v.ClassDef.name = name;
        p->v.ClassDef.bases = bases;
        p->v.ClassDef.body = body;
        return p;
}