[Python-Dev] PyNumber_*() binary operations & coercion

Thomas Wouters thomas@xs4all.net
Thu, 24 Aug 2000 01:15:20 +0200


On Wed, Aug 23, 2000 at 06:28:03PM -0500, Guido van Rossum wrote:

> > Now, I'm not sure how coercion is supposed to work, but I see one
> > problem here: 'v' can be changed by PyNumber_Coerce(), and the new
> > object's tp_as_number pointer could be NULL. I bet it's pretty unlikely
> > that (numeric) coercion of a numeric object and an unspecified object
> > turns up a non-numeric object, but I don't see anything guaranteeing it
> > won't, either.

> I think this currently can't happen because coercions never return
> non-numeric objects, but it sounds like a good sanity check to add.

> Please check this in as a separate patch (not as part of the huge
> augmented assignment patch).

Alright, checking it in after 'make test' finishes. I'm also removing some
redundant PyInstance_Check() calls in PyNumber_Multiply: the first thing in
that function is a BINOP call, which expands to

        if (PyInstance_Check(v) || PyInstance_Check(w)) \
                return PyInstance_DoBinOp(v, w, opname, ropname, thisfunc)

So after the BINOP call, neither argument can be an instance, anyway.


Also, I'll take this opportunity to explain what I'm doing with the
PyNumber_InPlace* functions, for those that are interested. The comment I'm
placing in the code should be enough information:

/* The in-place operators are defined to fall back to the 'normal',
   non in-place operations, if the in-place methods are not in place, and to
   take class instances into account. This is how it is supposed to work:

   - If the left-hand-side object (the first argument) is an
     instance object, let PyInstance_DoInPlaceOp() handle it.  Pass the
     non in-place variant of the function as callback, because it will only
     be used if any kind of coercion has been done, and if an object has
     been coerced, it's a new object and shouldn't be modified in-place.

   - Otherwise, if the object has the appropriate struct members, and they
     are filled, call that function and return the result. No coercion is
     done on the arguments; the left-hand object is the one the operation is
     performed on, and it's up to the function to deal with the right-hand
     object.

   - Otherwise, if the second argument is an Instance, let
     PyInstance_DoBinOp() handle it, but not in-place. Again, pass the
     non in-place function as callback.

   - Otherwise, both arguments are C objects. Try to coerce them and call
     the ordinary (not in-place) function-pointer from the type struct.
     
   - Otherwise, we are out of options: raise a type error.

   */

If anyone sees room for unexpected behaviour under these rules, let me know
and you'll get an XS4ALL shirt! (Sorry, only ones I can offer ;)

-- 
Thomas Wouters <thomas@xs4all.net>

Hi! I'm a .signature virus! copy me into your .signature file to help me spread!