[Python-Dev] Re: [Python-checkins] CVS: python/dist/src/Objects abstract.c,2.50,2.51

Guido van Rossum guido@beopen.com
Fri, 01 Sep 2000 12:10:35 -0500


> On Thu, Aug 31, 2000 at 07:39:03PM -0700, Guido van Rossum wrote:
> 
> > Add parens suggested by gcc -Wall.

Thomas replied:

> No! This groups the checks wrong. HASINPLACE(v) *has* to be true for any of
> the other tests to happen. I apologize for botching the earlier 2 versions
> and failing to check them, I've been a bit swamped in work the past week :P
> I've checked them in the way they should be. (And checked, with gcc -Wall,
> this time. The error is really gone.)

Doh!  Good catch.  But after looking at the code, I understand why
it's so hard to get right: it's indented wrong, and it's got very
convoluted logic.

Suggestion: don't try to put so much stuff in a single if expression!
I find the version below much clearer, even though it may test for
f==NULL a few extra times.  Thomas, can you verify that I haven't
changed the semantics this time?  You can check it in if you like it,
or you can have me check it in.

PyObject *
PyNumber_InPlaceAdd(PyObject *v, PyObject *w)
{
	PyObject * (*f)(PyObject *, PyObject *) = NULL;
	PyObject *x;

	if (PyInstance_Check(v)) {
		if (PyInstance_HalfBinOp(v, w, "__iadd__", &x,
					 PyNumber_Add, 0) <= 0)
			return x;
	}
	else if (HASINPLACE(v)) {
		if (v->ob_type->tp_as_sequence != NULL)
			f = v->ob_type->tp_as_sequence->sq_inplace_concat;
		if (f == NULL && v->ob_type->tp_as_number != NULL)
			f = v->ob_type->tp_as_number->nb_inplace_add;
		if (f != NULL)
			return (*f)(v, w);
	}

	BINOP(v, w, "__add__", "__radd__", PyNumber_Add);

	if (v->ob_type->tp_as_sequence != NULL) {
		f = v->ob_type->tp_as_sequence->sq_concat;
		if (f != NULL)
			return (*f)(v, w);
	}
	if (v->ob_type->tp_as_number != NULL) {
		if (PyNumber_Coerce(&v, &w) != 0)
			return NULL;
		if (v->ob_type->tp_as_number != NULL) {
			f = v->ob_type->tp_as_number->nb_add;
			if (f != NULL)
				x = (*f)(v, w);
		}
		Py_DECREF(v);
		Py_DECREF(w);
		if (f != NULL)
			return x;
	}

	return type_error("bad operand type(s) for +=");
}

--Guido van Rossum (home page: http://www.pythonlabs.com/~guido/)