[Cython] Problem with multiple assignment

Robert Bradshaw robertwb at math.washington.edu
Wed Jul 23 09:15:44 CEST 2008


On Jul 22, 2008, at 1:29 AM, Dag Sverre Seljebotn wrote:

> From: Stefan Behnel <stefan_ml at behnel.de>
> Date: Tuesday, Jul 22, 2008 7:41 am
> Subject: Re: [Cython] Problem with multiple assignment
> To: cython-dev at codespeak.netReply-To: cython-dev at codespeak.net
>
> Hi,
>>
>> thanks for the report.

Yes, very interesting.

>>
>> Marc Christiansen wrote:
>> I'm not sure if multiple assignment is the right name, but have a  
>> look
>> at this code:
>>
>> cdef f1():
>>     cdef char a, b
>>
>>     a = b = False
>>
>> Cython 0.9.8 creates this:
>>
>> [...]
>>  *
>>  *     a = b = False             # <<<<<<<<<<<<<<
>>  */
>>   __pyx_1 = __pyx_PyInt_char(Py_False); if (unlikely((__pyx_1 ==  
>> (char)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0];  
>> __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L1;}
>>   __pyx_v_a = __pyx_1;
>>   __pyx_1 = __pyx_PyInt_char(Py_False); if (unlikely((__pyx_1 ==  
>> (char)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0];  
>> __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L1;}
>>   __pyx_v_b = __pyx_1;
>>
>> [...]
>>
>> If I write a = b = 0 (or a = False; b = False), the result is the  
>> expected
>>   __pyx_v_a = 0;
>>   __pyx_v_b = 0;
>>
>> This is not really a problem, more of a missing optimisation for a  
>> case that's handled differently internally. It sounds like it  
>> could go away with Dag's work on the assignment handling anyway. Dag?
>>
>
> The way I visioned it it would turn into
>
> cdef object tmp
> ..
> tmp = False
> a = tmp
> b = tmp

This is in fact exactly what it turns into, though perhaps more  
implicitly then you are thinking of doing, so you are right that some  
special casing may be needed here. However, I think a better  
optimization is that (as has been hinted) True and False start as  
bints, and then get coerced to PyObjects as needed....that was easy.

Now we have

  *     a = b = False             # <<<<<<<<<<<<<<
  *
  */
   __pyx_v_a = 0;
   __pyx_v_b = 0;


as desired. Note that for Python objects

  *     x = False             # <<<<<<<<<<<<<<
  *
  */
   __pyx_1 = __Pyx_PyBool_FromLong(0); if (unlikely(!__pyx_1))  
{__pyx_filename = __pyx_f[0]; __pyx_lineno = 16; __pyx_clineno =  
__LINE__; goto __pyx_L1;}
   Py_DECREF(__pyx_v_x);
   __pyx_v_x = __pyx_1;

Where most of this gets optimized away as

#define __Pyx_PyBool_FromLong(b) ((b) ? (Py_INCREF(Py_True),  
Py_True) : (Py_INCREF(Py_False), Py_False))

(though it perhaps could be made to look prettier).

- Robert





More information about the Cython-dev mailing list