~ubuntu-branches/debian/experimental/nuitka/experimental

« back to all changes in this revision

Viewing changes to nuitka/build/static_src/CompiledGeneratorType.cpp

  • Committer: Package Import Robot
  • Author(s): Kay Hayen
  • Date: 2014-10-05 19:28:20 UTC
  • mfrom: (1.1.30)
  • Revision ID: package-import@ubuntu.com-20141005192820-s06oca9rty517iy8
Tags: 0.5.5+ds-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
69
69
        if ( generator->m_status == status_Unused )
70
70
        {
71
71
            // Prepare the generator context to run.
72
 
            int res = prepareFiber( &generator->m_yielder_context, generator->m_code, (intptr_t)generator );
 
72
            int res = prepareFiber( &generator->m_yielder_context, generator->m_code, (uintptr_t)generator );
73
73
 
74
74
            if ( res != 0 )
75
75
            {
174
174
    return Nuitka_Generator_send( generator, Py_None );
175
175
}
176
176
 
177
 
 
178
 
static PyObject *Nuitka_Generator_close( Nuitka_GeneratorObject *generator, PyObject *args )
 
177
#if PYTHON_VERSION < 340
 
178
static
 
179
#endif
 
180
PyObject *Nuitka_Generator_close( Nuitka_GeneratorObject *generator, PyObject *args )
179
181
{
180
182
    if ( generator->m_status == status_Running )
181
183
    {
272
274
        Py_DECREF( close_result );
273
275
    }
274
276
 
275
 
    assert( Py_REFCNT( generator ) == 1 );
276
 
    Py_REFCNT( generator ) = 0;
277
 
 
278
 
    releaseFiber( &generator->m_yielder_context );
279
 
 
280
 
    // Now it is safe to release references and memory for it.
281
 
    Nuitka_GC_UnTrack( generator );
282
 
 
283
277
    if ( generator->m_weakrefs != NULL )
284
278
    {
285
279
        PyObject_ClearWeakRefs( (PyObject *)generator );
294
288
 
295
289
    Py_XDECREF( generator->m_frame );
296
290
 
 
291
    assert( Py_REFCNT( generator ) == 1 );
 
292
    Py_REFCNT( generator ) = 0;
 
293
 
 
294
    releaseFiber( &generator->m_yielder_context );
 
295
 
 
296
    // Now it is safe to release references and memory for it.
 
297
    Nuitka_GC_UnTrack( generator );
 
298
 
297
299
    PyObject_GC_Del( generator );
298
300
    PyErr_Restore( save_exception_type, save_exception_value, save_exception_tb );
299
301
}
673
675
    return result;
674
676
}
675
677
 
 
678
#if PYTHON_VERSION >= 300
 
679
 
676
680
PyObject *ERROR_GET_STOP_ITERATION_VALUE()
677
681
{
678
682
    assert( PyErr_ExceptionMatches( PyExc_StopIteration ) );
706
710
 
707
711
    return value;
708
712
}
 
713
 
 
714
static void RAISE_GENERATOR_EXCEPTION( Nuitka_GeneratorObject *generator )
 
715
{
 
716
    assertObject( generator->m_exception_type );
 
717
 
 
718
    Py_INCREF( generator->m_exception_type );
 
719
    Py_XINCREF( generator->m_exception_value );
 
720
    Py_XINCREF( generator->m_exception_tb );
 
721
 
 
722
    PyErr_Restore(
 
723
        generator->m_exception_type,
 
724
        generator->m_exception_value,
 
725
        (PyObject *)generator->m_exception_tb
 
726
    );
 
727
 
 
728
    generator->m_exception_type = NULL;
 
729
    generator->m_exception_value = NULL;
 
730
    generator->m_exception_tb = NULL;
 
731
}
 
732
 
 
733
extern PyObject *ERROR_GET_STOP_ITERATION_VALUE();
 
734
extern PyObject *PyGen_Send( PyGenObject *gen, PyObject *arg );
 
735
 
 
736
extern PyObject *const_str_plain_send;
 
737
 
 
738
PyObject *YIELD_FROM( Nuitka_GeneratorObject *generator, PyObject *value )
 
739
{
 
740
    // This is the value, propagated back and forth the sub-generator and the
 
741
    // yield from consumer.
 
742
    PyObject *send_value = Py_None;
 
743
 
 
744
    while( 1 )
 
745
    {
 
746
        // Send iteration value to the sub-generator, which may be a CPython
 
747
        // generator object, something with an iterator next, or a send method,
 
748
        // where the later is only required if values other than "None" need to
 
749
        // be passed in.
 
750
        PyObject *retval;
 
751
 
 
752
        // Exception, was thrown into us, need to send that to sub-generator.
 
753
        if ( generator->m_exception_type )
 
754
        {
 
755
            // The yielding generator is being closed, but we also are tasked to
 
756
            // immediately close the currently running sub-generator.
 
757
            if ( PyErr_GivenExceptionMatches( generator->m_exception_type, PyExc_GeneratorExit ) )
 
758
            {
 
759
                PyObject *close_method = PyObject_GetAttrString( value, (char *)"close" );
 
760
 
 
761
                if ( close_method )
 
762
                {
 
763
                    PyObject *close_value = PyObject_Call( close_method, const_tuple_empty, NULL );
 
764
                    Py_DECREF( close_method );
 
765
 
 
766
                    if (unlikely( close_value == NULL ))
 
767
                    {
 
768
                        return NULL;
 
769
                    }
 
770
 
 
771
                    Py_DECREF( close_value );
 
772
                }
 
773
                else if ( !PyErr_ExceptionMatches( PyExc_AttributeError ) )
 
774
                {
 
775
                    PyErr_WriteUnraisable( (PyObject *)generator );
 
776
                }
 
777
 
 
778
                RAISE_GENERATOR_EXCEPTION( generator );
 
779
                return NULL;
 
780
            }
 
781
 
 
782
            PyObject *throw_method = PyObject_GetAttrString( value, (char *)"throw" );
 
783
 
 
784
            if ( throw_method )
 
785
            {
 
786
                retval = PyObject_CallFunctionObjArgs( throw_method, generator->m_exception_type, generator->m_exception_value, generator->m_exception_tb, NULL );
 
787
                Py_DECREF( throw_method );
 
788
 
 
789
                if (unlikely( send_value == NULL ))
 
790
                {
 
791
                    if ( PyErr_ExceptionMatches( PyExc_StopIteration ) )
 
792
                    {
 
793
                        return ERROR_GET_STOP_ITERATION_VALUE();
 
794
                    }
 
795
 
 
796
                    return NULL;
 
797
                }
 
798
 
 
799
 
 
800
                generator->m_exception_type = NULL;
 
801
                generator->m_exception_value = NULL;
 
802
                generator->m_exception_tb = NULL;
 
803
            }
 
804
            else if ( PyErr_ExceptionMatches( PyExc_AttributeError ) )
 
805
            {
 
806
                PyErr_Clear();
 
807
 
 
808
                RAISE_GENERATOR_EXCEPTION( generator );
 
809
                return NULL;
 
810
            }
 
811
            else
 
812
            {
 
813
                return NULL;
 
814
            }
 
815
 
 
816
        }
 
817
        else if ( PyGen_CheckExact( value ) )
 
818
        {
 
819
            retval = PyGen_Send( (PyGenObject *)value, Py_None );
 
820
        }
 
821
        else if ( send_value == Py_None )
 
822
        {
 
823
            retval = Py_TYPE( value )->tp_iternext( value );
 
824
        }
 
825
        else
 
826
        {
 
827
            // Bug compatibility here, before 3.3 tuples were unrolled in calls, which is what
 
828
            // PyObject_CallMethod does.
 
829
#if PYTHON_VERSION >= 340
 
830
            retval = PyObject_CallMethodObjArgs( value, const_str_plain_send, send_value, NULL );
 
831
#else
 
832
            retval = PyObject_CallMethod( value, (char *)"send", (char *)"O", send_value );
 
833
#endif
 
834
        }
 
835
 
 
836
        // Check the sub-generator result
 
837
        if ( retval == NULL )
 
838
        {
 
839
            if ( !ERROR_OCCURED() )
 
840
            {
 
841
                return INCREASE_REFCOUNT( Py_None ) ;
 
842
            }
 
843
 
 
844
            // The sub-generator has given an exception. In case of
 
845
            // StopIteration, we need to check the value, as it is going to be
 
846
            // the expression value of this "yield from", and we are done. All
 
847
            // other errors, we need to raise.
 
848
            if (likely( PyErr_ExceptionMatches( PyExc_StopIteration ) ))
 
849
            {
 
850
                return ERROR_GET_STOP_ITERATION_VALUE();
 
851
            }
 
852
 
 
853
            return NULL;
 
854
        }
 
855
        else
 
856
        {
 
857
            generator->m_yielded = retval;
 
858
 
 
859
            // Return to the calling context.
 
860
            swapFiber( &generator->m_yielder_context, &generator->m_caller_context );
 
861
 
 
862
            send_value = generator->m_yielded;
 
863
 
 
864
            assertObject( send_value );
 
865
        }
 
866
    }
 
867
}
 
868
 
 
869
#endif
 
870
 
709
871
#endif