Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Generated code for Python source for module '__main__'
- // This code is in part copyright Kay Hayen, license GPLv3. This has the consequence that
- // your must either obtain a commercial license or also publish your original source code
- // under the same license unless you don't distribute this source or its binary.
- #ifdef __NUITKA_NO_ASSERT__
- #define NDEBUG
- #endif
- // Include the Python C/API header files
- #include "Python.h"
- #include "methodobject.h"
- #include "frameobject.h"
- #include <stdio.h>
- #include <string>
- // An idea I first saw used with Cython, hint the compiler about branches that are more or
- // less likely to be taken. And hint the compiler about things that we assume to be
- // normally true. If other compilers can do similar, I would be grateful for howtos.
- #ifdef __GNUC__
- #define likely(x) __builtin_expect(!!(x), 1)
- #define unlikely(x) __builtin_expect(!!(x), 0)
- #else
- #define likely(x) (x)
- #define unlikely(x) (x)
- #endif
- // An idea to reduce the amount of exported symbols, esp. as we are using C++ and classes
- // do not allow to limit their visibility normally.
- #ifdef __GNUC__
- #define NUITKA_MODULE_INIT_FUNCTION PyMODINIT_FUNC __attribute__((visibility( "default" )))
- #else
- #define NUITKA_MODULE_INIT_FUNCTION PyMODINIT_FUNC
- #endif
- static PyObject *_expression_temps[100];
- static PyObject *_eval_globals_tmp;
- static PyObject *_eval_locals_tmp;
- // From CPython, to allow us quick access to the dictionary of an module.
- typedef struct {
- PyObject_HEAD
- PyObject *md_dict;
- } PyModuleObject;
- // We unstream some constant objects using the "cPickle" module function "loads"
- static PyObject *_module_cPickle = NULL;
- static PyObject *_module_cPickle_function_loads = NULL;
- // Sentinel PyObject to be used for all our call iterator endings. It will become
- // a PyCObject pointing to NULL. TODO: Hopefully that is unique enough.
- static PyObject *_sentinel_value = NULL;
- static PyObject *_python_bool_False = NULL;
- static PyObject *_python_bool_True = NULL;
- static PyObject *_python_dict_empty = NULL;
- static PyObject *_python_int_0 = NULL;
- static PyObject *_python_int_pos_1 = NULL;
- static PyObject *_python_int_pos_2 = NULL;
- static PyObject *_python_str_angle_hello__genexpr = NULL;
- static PyObject *_python_str_angle_module = NULL;
- static PyObject *_python_str_digest_8d35108ffe2ad173a697734a3e9938e1 = NULL;
- static PyObject *_python_str_empty = NULL;
- static PyObject *_python_str_plain___doc__ = NULL;
- static PyObject *_python_str_plain___file__ = NULL;
- static PyObject *_python_str_plain___module__ = NULL;
- static PyObject *_python_str_plain_all = NULL;
- static PyObject *_python_str_plain_hello__genexpr = NULL;
- static PyObject *_python_str_plain_i = NULL;
- static PyObject *_python_str_plain_int = NULL;
- static PyObject *_python_str_plain_math = NULL;
- static PyObject *_python_str_plain_num_primes = NULL;
- static PyObject *_python_str_plain_sqrt = NULL;
- static PyObject *_python_str_plain_xrange = NULL;
- static PyObject *_python_tuple_empty = NULL;
- static PyObject *_python_tuple_int_pos_2_int_pos_500000 = NULL;
- static PyObject *_unstreamConstant( char const *buffer, int size )
- {
- PyObject *temp = PyString_FromStringAndSize( buffer, size );
- PyObject *result = PyObject_CallFunctionObjArgs( _module_cPickle_function_loads, temp, NULL );
- assert( result );
- Py_DECREF( temp );
- return result;
- }
- static PyModuleObject *_module_builtin = NULL;
- static int _initConstants()
- {
- if ( _sentinel_value == NULL )
- {
- _sentinel_value = PyCObject_FromVoidPtr( NULL, NULL );
- assert( _sentinel_value );
- _module_builtin = (PyModuleObject *)PyImport_ImportModule( "__builtin__" );
- assert( _module_builtin );
- _module_cPickle = PyImport_ImportModule( "cPickle" );
- assert( _module_cPickle );
- _module_cPickle_function_loads = PyObject_GetAttrString( _module_cPickle, "loads" );
- assert( _module_cPickle_function_loads );
- _python_bool_False = _unstreamConstant( R"raw(I00)raw" "\n" R"raw(.)raw", 5 );
- _python_bool_True = _unstreamConstant( R"raw(I01)raw" "\n" R"raw(.)raw", 5 );
- _python_dict_empty = _unstreamConstant( R"raw((dp1)raw" "\n" R"raw(.)raw", 6 );
- _python_int_0 = PyInt_FromLong( 0 );
- _python_int_pos_1 = PyInt_FromLong( 1 );
- _python_int_pos_2 = PyInt_FromLong( 2 );
- _python_str_angle_hello__genexpr = PyString_FromStringAndSize( R"raw(<hello__genexpr>)raw", 16 );
- assert( PyString_Size( _python_str_angle_hello__genexpr ) == 16 );
- _python_str_angle_module = PyString_FromStringAndSize( R"raw(<module>)raw", 8 );
- assert( PyString_Size( _python_str_angle_module ) == 8 );
- _python_str_digest_8d35108ffe2ad173a697734a3e9938e1 = PyString_FromStringAndSize( R"raw(hello.py)raw", 8 );
- assert( PyString_Size( _python_str_digest_8d35108ffe2ad173a697734a3e9938e1 ) == 8 );
- _python_str_empty = PyString_FromStringAndSize( R"raw()raw", 0 );
- assert( PyString_Size( _python_str_empty ) == 0 );
- _python_str_plain___doc__ = PyString_FromStringAndSize( R"raw(__doc__)raw", 7 );
- assert( PyString_Size( _python_str_plain___doc__ ) == 7 );
- _python_str_plain___file__ = PyString_FromStringAndSize( R"raw(__file__)raw", 8 );
- assert( PyString_Size( _python_str_plain___file__ ) == 8 );
- _python_str_plain___module__ = PyString_FromStringAndSize( R"raw(__module__)raw", 10 );
- assert( PyString_Size( _python_str_plain___module__ ) == 10 );
- _python_str_plain_all = PyString_FromStringAndSize( R"raw(all)raw", 3 );
- assert( PyString_Size( _python_str_plain_all ) == 3 );
- _python_str_plain_hello__genexpr = PyString_FromStringAndSize( R"raw(hello__genexpr)raw", 14 );
- assert( PyString_Size( _python_str_plain_hello__genexpr ) == 14 );
- _python_str_plain_i = PyString_FromStringAndSize( R"raw(i)raw", 1 );
- assert( PyString_Size( _python_str_plain_i ) == 1 );
- _python_str_plain_int = PyString_FromStringAndSize( R"raw(int)raw", 3 );
- assert( PyString_Size( _python_str_plain_int ) == 3 );
- _python_str_plain_math = PyString_FromStringAndSize( R"raw(math)raw", 4 );
- assert( PyString_Size( _python_str_plain_math ) == 4 );
- _python_str_plain_num_primes = PyString_FromStringAndSize( R"raw(num_primes)raw", 10 );
- assert( PyString_Size( _python_str_plain_num_primes ) == 10 );
- _python_str_plain_sqrt = PyString_FromStringAndSize( R"raw(sqrt)raw", 4 );
- assert( PyString_Size( _python_str_plain_sqrt ) == 4 );
- _python_str_plain_xrange = PyString_FromStringAndSize( R"raw(xrange)raw", 6 );
- assert( PyString_Size( _python_str_plain_xrange ) == 6 );
- _python_tuple_empty = _unstreamConstant( R"raw((t.)raw", 3 );
- _python_tuple_int_pos_2_int_pos_500000 = _unstreamConstant( R"raw((I2)raw" "\n" R"raw(I500000)raw" "\n" R"raw(tp1)raw" "\n" R"raw(.)raw", 17 );
- }
- }
- template<typename... P>
- static void PRINT_ITEMS( bool new_line, PyObject *file, P...eles );
- static PyObject *INCREASE_REFCOUNT( PyObject *object );
- static int _current_line = -1;
- static char *_current_file = NULL;
- class _PythonException
- {
- public:
- _PythonException()
- {
- this->line = _current_line;
- this->_importFromPython();
- }
- _PythonException( PyObject *exception )
- {
- assert( exception );
- assert( exception->ob_refcnt > 0 );
- this->line = _current_line;
- Py_INCREF( exception );
- this->exception_type = exception;
- this->exception_value = NULL;
- this->exception_tb = NULL;
- }
- _PythonException( PyObject *exception, PyTracebackObject *traceback )
- {
- assert( exception );
- assert( exception->ob_refcnt > 0 );
- assert( traceback );
- assert( traceback->ob_refcnt > 0 );
- this->line = _current_line;
- this->exception_type = exception;
- this->exception_value = NULL;
- this->exception_tb = (PyObject *)traceback;
- }
- _PythonException( PyObject *exception, PyObject *value, float unused )
- {
- assert( exception );
- assert( value );
- assert( exception->ob_refcnt > 0 );
- assert( value->ob_refcnt > 0 );
- this->line = _current_line;
- Py_INCREF( exception );
- Py_INCREF( value );
- this->exception_type = exception;
- this->exception_value = value;
- this->exception_tb = NULL;
- }
- _PythonException( PyObject *exception, PyObject *value, PyTracebackObject *traceback )
- {
- assert( exception );
- assert( value );
- assert( traceback );
- assert( exception->ob_refcnt > 0 );
- assert( value->ob_refcnt > 0 );
- assert( traceback->ob_refcnt > 0 );
- this->line = _current_line;
- this->exception_type = exception;
- this->exception_value = value;
- this->exception_tb = (PyObject *)traceback;
- }
- _PythonException( const _PythonException &other )
- {
- this->line = other.line;
- this->exception_type = other.exception_type;
- this->exception_value = other.exception_value;
- this->exception_tb = other.exception_tb;
- Py_XINCREF( this->exception_type );
- Py_XINCREF( this->exception_value );
- Py_XINCREF( this->exception_tb );
- }
- void operator=( const _PythonException &other )
- {
- Py_XINCREF( other.exception_type );
- Py_XINCREF( other.exception_value );
- Py_XINCREF( other.exception_tb );
- Py_XDECREF( this->exception_type );
- Py_XDECREF( this->exception_value );
- Py_XDECREF( this->exception_tb );
- this->line = other.line;
- this->exception_type = other.exception_type;
- this->exception_value = other.exception_value;
- this->exception_tb = other.exception_tb;
- }
- ~_PythonException()
- {
- Py_XDECREF( this->exception_type );
- Py_XDECREF( this->exception_value );
- Py_XDECREF( this->exception_tb );
- }
- inline void _importFromPython()
- {
- PyErr_Fetch( &this->exception_type, &this->exception_value, &this->exception_tb );
- assert( this->exception_type );
- // PyErr_NormalizeException( &this->exception_type, &this->exception_value, &this->exception_tb );
- PyErr_Clear();
- }
- inline int getLine() const
- {
- return this->line;
- }
- inline bool matches( PyObject *exception ) const
- {
- return PyErr_GivenExceptionMatches( this->exception_type, exception ) || PyErr_GivenExceptionMatches( this->exception_value, exception );;
- }
- inline void toPython()
- {
- PyErr_Restore( this->exception_type, this->exception_value, this->exception_tb );
- PyThreadState *thread_state = PyThreadState_GET();
- assert( this->exception_type == thread_state->curexc_type );
- assert( thread_state->curexc_type );
- this->exception_type = NULL;
- this->exception_value = NULL;
- this->exception_tb = NULL;
- }
- inline void toExceptionHandler()
- {
- // Restore only sets the current exception to the interpreter.
- PyThreadState *thread_state = PyThreadState_GET();
- PyObject *old_type = thread_state->exc_type;
- PyObject *old_value = thread_state->exc_value;
- PyObject *old_tb = thread_state->exc_traceback;
- thread_state->exc_type = this->exception_type;
- thread_state->exc_value = this->exception_value;
- thread_state->exc_traceback = this->exception_tb;
- Py_INCREF( thread_state->exc_type );
- Py_XINCREF( thread_state->exc_value );
- Py_XINCREF( thread_state->exc_traceback );
- Py_XDECREF( old_type );
- Py_XDECREF( old_value );
- Py_XDECREF( old_tb );
- PySys_SetObject( (char *)"exc_type", thread_state->exc_type );
- PySys_SetObject( (char *)"exc_value", thread_state->exc_value );
- PySys_SetObject( (char *)"exc_traceback", thread_state->exc_traceback );
- }
- inline PyObject *getType()
- {
- if ( this->exception_value == NULL )
- {
- PyErr_NormalizeException( &this->exception_type, &this->exception_value, &this->exception_tb );
- }
- return this->exception_type;
- }
- inline PyObject *getTraceback() const
- {
- return this->exception_tb;
- }
- inline PyObject *setTraceback( PyTracebackObject *traceback )
- {
- assert( traceback );
- assert( traceback->ob_refcnt > 0 );
- // printf( "setTraceback %d\n", traceback->ob_refcnt );
- // Py_INCREF( traceback );
- this->exception_tb = (PyObject *)traceback;
- }
- inline bool hasTraceback() const
- {
- return this->exception_tb != NULL;
- }
- void setType( PyObject *exception_type )
- {
- Py_XDECREF( this->exception_type );
- this->exception_type = exception_type;
- }
- inline PyObject *getObject()
- {
- PyErr_NormalizeException( &this->exception_type, &this->exception_value, &this->exception_tb );
- return this->exception_value;
- }
- void dump() const
- {
- PRINT_ITEMS( true, NULL, this->exception_type );
- }
- protected:
- PyObject *exception_type, *exception_value, *exception_tb;
- int line;
- };
- class _PythonExceptionKeeper
- {
- public:
- _PythonExceptionKeeper()
- {
- empty = true;
- }
- ~_PythonExceptionKeeper()
- {
- if ( this->empty == false)
- {
- delete this->saved;
- }
- }
- void save( const _PythonException &e )
- {
- this->saved = new _PythonException( e );
- empty = false;
- }
- void rethrow()
- {
- if (empty == false)
- {
- throw *this->saved;
- }
- }
- bool isEmpty() const
- {
- return this->empty;
- }
- protected:
- bool empty;
- _PythonException *saved;
- };
- class ContinueException
- {
- };
- class BreakException
- {
- };
- // Helper functions for reference count handling in the fly.
- static PyObject *INCREASE_REFCOUNT( PyObject *object )
- {
- assert( object->ob_refcnt > 0 );
- Py_INCREF( object );
- return object;
- }
- static PyObject *DECREASE_REFCOUNT( PyObject *object )
- {
- Py_DECREF( object );
- return object;
- }
- // Helper functions for print. Need to play nice with Python softspace behaviour.
- static void PRINT_ITEM_TO( PyObject *file, PyObject *object )
- {
- PyObject *str = PyObject_Str( object );
- PyObject *print;
- bool softspace;
- if ( str == NULL )
- {
- PyErr_Clear();
- print = object;
- softspace = false;
- }
- else
- {
- char *buffer;
- Py_ssize_t length;
- int status = PyString_AsStringAndSize( str, &buffer, &length );
- assert( status != -1 );
- softspace = length > 0 && buffer[length - 1 ] == '\t';
- print = str;
- }
- // Check for soft space indicator, need to hold a reference to the file
- // or else __getattr__ may release "file" in the mean time.
- if ( PyFile_SoftSpace( file, !softspace ) )
- {
- if (unlikely( PyFile_WriteString( " ", file ) == -1 ))
- {
- Py_DECREF( file );
- Py_DECREF( str );
- throw _PythonException();
- }
- }
- if ( unlikely( PyFile_WriteObject( print, file, Py_PRINT_RAW ) == -1 ))
- {
- Py_XDECREF( str );
- throw _PythonException();
- }
- Py_XDECREF( str );
- if ( softspace )
- {
- PyFile_SoftSpace( file, !softspace );
- }
- }
- static void PRINT_NEW_LINE_TO( PyObject *file )
- {
- if (unlikely( PyFile_WriteString( "\n", file ) == -1))
- {
- throw _PythonException();
- }
- PyFile_SoftSpace( file, 0 );
- }
- template<typename... P>
- static void PRINT_ITEMS( bool new_line, PyObject *file, P...eles )
- {
- int size = sizeof...(eles);
- if ( file == NULL || file == Py_None )
- {
- file = PySys_GetObject((char *)"stdout");
- }
- // Need to hold a reference for the case that the printing somehow removes
- // the last reference to "file" while printing.
- Py_INCREF( file );
- PyObject *elements[] = {eles...};
- for( int i = 0; i < size; i++ )
- {
- PRINT_ITEM_TO( file, elements[ i ] );
- }
- if ( new_line )
- {
- PRINT_NEW_LINE_TO( file );
- }
- // TODO: Use of PyObjectTemporary should be possible, this won't be
- // exception safe otherwise
- Py_DECREF( file );
- }
- static void PRINT_NEW_LINE( void )
- {
- PyObject *stdout = PySys_GetObject((char *)"stdout");
- if (unlikely( stdout == NULL ))
- {
- PyErr_Format( PyExc_RuntimeError, "problem with stdout" );
- throw _PythonException();
- }
- PRINT_NEW_LINE_TO( stdout );
- }
- static void RAISE_EXCEPTION( PyObject *exception, PyTracebackObject *traceback )
- {
- if ( PyExceptionClass_Check( exception ) )
- {
- throw _PythonException( exception, traceback );
- }
- else if ( PyExceptionInstance_Check( exception ) )
- {
- throw _PythonException( INCREASE_REFCOUNT( PyExceptionInstance_Class( exception ) ), exception, traceback );
- }
- else
- {
- PyErr_Format( PyExc_TypeError, "exceptions must be old-style classes or derived from BaseException, not %s", exception->ob_type->tp_name );
- throw _PythonException();
- }
- }
- static void RAISE_EXCEPTION( PyObject *exception_type, PyObject *value, PyTracebackObject *traceback )
- {
- // TODO: Check traceback
- if ( PyExceptionClass_Check( exception_type ) )
- {
- PyErr_NormalizeException( &exception_type, &value, (PyObject **)&traceback );
- }
- throw _PythonException( exception_type, value, traceback );
- }
- static inline void RAISE_EXCEPTION( PyObject *exception_type, PyObject *value, PyObject *traceback )
- {
- RAISE_EXCEPTION( exception_type, value, (PyTracebackObject *)traceback );
- }
- static bool CHECK_IF_TRUE( PyObject *object )
- {
- assert( object != NULL );
- assert( object->ob_refcnt > 0 );
- int status = PyObject_IsTrue( object );
- if (unlikely( status == -1 ))
- {
- throw _PythonException();
- }
- return status == 1;
- }
- static bool CHECK_IF_FALSE( PyObject *object )
- {
- assert( object != NULL );
- assert( object->ob_refcnt > 0 );
- int status = PyObject_Not( object );
- if (unlikely( status == -1 ))
- {
- throw _PythonException();
- }
- return status == 1;
- }
- static PyObject *BOOL_FROM( bool value )
- {
- return value ? _python_bool_True : _python_bool_False;
- }
- static PyObject *UNARY_NOT( PyObject *object )
- {
- int result = PyObject_Not( object );
- if (unlikely( result == -1 ))
- {
- throw _PythonException();
- }
- return BOOL_FROM( result == 1 );
- }
- typedef PyObject *(binary_api)( PyObject *, PyObject * );
- static PyObject *BINARY_OPERATION( binary_api api, PyObject *operand1, PyObject *operand2 )
- {
- int line = _current_line;
- PyObject *result = api( operand1, operand2 );
- if (unlikely (result == NULL))
- {
- _current_line = line;
- throw _PythonException();
- }
- return result;
- }
- typedef PyObject *(unary_api)( PyObject * );
- static PyObject *UNARY_OPERATION( unary_api api, PyObject *operand )
- {
- PyObject *result = api( operand );
- if (unlikely (result == NULL))
- {
- throw _PythonException();
- }
- return result;
- }
- static PyObject *POWER_OPERATION( PyObject *operand1, PyObject *operand2 )
- {
- PyObject *result = PyNumber_Power( operand1, operand2, Py_None );
- if (unlikely (result == NULL))
- {
- throw _PythonException();
- }
- return result;
- }
- static PyObject *POWER_OPERATION_INPLACE( PyObject *operand1, PyObject *operand2 )
- {
- PyObject *result = PyNumber_InPlacePower( operand1, operand2, Py_None );
- if (unlikely (result == NULL))
- {
- throw _PythonException();
- }
- return result;
- }
- static PyObject *RICH_COMPARE( int opid, PyObject *operand2, PyObject *operand1 )
- {
- int line = _current_line;
- PyObject *result = PyObject_RichCompare( operand1, operand2, opid );
- if (unlikely (result == NULL))
- {
- _current_line = line;
- throw _PythonException();
- }
- return result;
- }
- static bool RICH_COMPARE_BOOL( int opid, PyObject *operand2, PyObject *operand1 )
- {
- int line = _current_line;
- int result = PyObject_RichCompareBool( operand1, operand2, opid );
- if (unlikely( result == -1 ))
- {
- _current_line = line;
- throw _PythonException();
- }
- return result == 1;
- }
- static PyObject *SEQUENCE_CONTAINS( PyObject *sequence, PyObject *element)
- {
- int result = PySequence_Contains( sequence, element );
- if (unlikely( result == -1 ))
- {
- throw _PythonException();
- }
- return BOOL_FROM( result == 1 );
- }
- static PyObject *SEQUENCE_CONTAINS_NOT( PyObject *sequence, PyObject *element)
- {
- int result = PySequence_Contains( sequence, element );
- if (unlikely( result == -1 ))
- {
- throw _PythonException();
- }
- return BOOL_FROM( result == 0 );
- }
- // Helper functions to debug the compiler operation.
- static void PRINT_REFCOUNT( PyObject *object )
- {
- PyObject *stdout = PySys_GetObject((char *)"stdout");
- if (unlikely( stdout == NULL ))
- {
- PyErr_Format( PyExc_RuntimeError, "problem with stdout" );
- throw _PythonException();
- }
- char buffer[1024];
- sprintf( buffer, " refcnt %d ", object->ob_refcnt );
- if (unlikely( PyFile_WriteString(buffer, stdout) == -1 ))
- {
- throw _PythonException();
- }
- }
- static PyObject *CALL_FUNCTION( PyObject *named_args, PyObject *positional_args, PyObject *function_object )
- {
- assert( function_object != NULL );
- assert( function_object->ob_refcnt > 0 );
- assert( positional_args != NULL );
- assert( positional_args->ob_refcnt > 0 );
- assert( named_args == NULL || named_args->ob_refcnt > 0 );
- int line = _current_line;
- PyObject *result = PyObject_Call( function_object, positional_args, named_args );
- if (unlikely (result == NULL))
- {
- _current_line = line;
- throw _PythonException();
- }
- return result;
- }
- static PyObject *TO_TUPLE( PyObject *seq_obj )
- {
- PyObject *result = PySequence_Tuple( seq_obj );
- if (unlikely (result == NULL))
- {
- throw _PythonException();
- }
- return result;
- }
- template<typename... P>
- static PyObject *MAKE_TUPLE( P...eles )
- {
- int size = sizeof...(eles);
- if ( size > 0 )
- {
- PyObject *elements[] = {eles...};
- for ( Py_ssize_t i = 0; i < size; i++ )
- {
- assert (elements[ i ] != NULL);
- assert (elements[ i ]->ob_refcnt > 0);
- }
- PyObject *result = PyTuple_New( size );
- if (unlikely (result == NULL))
- {
- throw _PythonException();
- }
- for ( Py_ssize_t i = 0; i < size; i++ )
- {
- PyTuple_SET_ITEM( result, i, INCREASE_REFCOUNT( elements[ size - 1 - i ] ));
- }
- assert( result->ob_refcnt == 1 );
- return result;
- }
- else
- {
- return INCREASE_REFCOUNT( _python_tuple_empty );
- }
- }
- template<typename... P>
- static PyObject *MAKE_LIST( P...eles )
- {
- PyObject *elements[] = {eles...};
- int size = sizeof...(eles);
- PyObject *result = PyList_New( size );
- if (unlikely (result == NULL))
- {
- throw _PythonException();
- }
- for (Py_ssize_t i = 0; i < size; i++ )
- {
- assert (elements[ i ] != NULL);
- assert (elements[ i ]->ob_refcnt > 0);
- PyList_SET_ITEM( result, i, elements[ size - 1 - i ] );
- }
- assert( result->ob_refcnt == 1 );
- return result;
- }
- template<typename... P>
- static PyObject *MAKE_DICT( P...eles )
- {
- PyObject *elements[] = {eles...};
- int size = sizeof...(eles);
- assert (size % 2 == 0);
- PyObject *result = PyDict_New();
- if (unlikely (result == NULL))
- {
- throw _PythonException();
- }
- for( int i = 0; i < size; i += 2 )
- {
- int status = PyDict_SetItem( result, elements[i], elements[i+1] );
- if (unlikely( status == -1 ))
- {
- throw _PythonException();
- }
- }
- return result;
- }
- static PyObject *MERGE_DICTS( PyObject *dict_a, PyObject *dict_b, bool allow_conflict )
- {
- PyObject *result = PyDict_Copy( dict_a );
- if (unlikely (result == NULL))
- {
- throw _PythonException();
- }
- int status = PyDict_Merge( result, dict_b, 1 );
- if (unlikely( status == -1 ))
- {
- throw _PythonException();
- }
- if ( allow_conflict == false && PyDict_Size( dict_a ) + PyDict_Size( dict_b ) != PyDict_Size( result ))
- {
- Py_DECREF( result );
- PyErr_Format( PyExc_TypeError, "got multiple values for keyword argument" );
- throw _PythonException();
- }
- return result;
- }
- static void DICT_SET_ITEM( PyObject *dict, PyObject *key, PyObject *value )
- {
- int status = PyDict_SetItem( dict, key, value );
- if (unlikely( status == -1))
- {
- throw _PythonException();
- }
- }
- template<typename... P>
- static PyObject *MAKE_SET( P...eles )
- {
- PyObject *tuple = MAKE_TUPLE( eles... );
- PyObject *result = PySet_New( tuple );
- Py_DECREF( tuple );
- if (unlikely (result == NULL))
- {
- throw _PythonException();
- }
- return result;
- }
- static PyObject *MAKE_STATIC_METHOD( PyObject *method )
- {
- PyObject *attempt = PyStaticMethod_New( method );
- if ( attempt )
- {
- return attempt;
- }
- else
- {
- PyErr_Clear();
- return method;
- }
- }
- static PyObject *SEQUENCE_ELEMENT( PyObject *sequence, Py_ssize_t element )
- {
- PyObject *result = PySequence_GetItem( sequence, element );
- if (unlikely (result == NULL))
- {
- throw _PythonException();
- }
- return result;
- }
- static PyObject *MAKE_ITERATOR( PyObject *iterated )
- {
- PyObject *result = PyObject_GetIter( iterated );
- if (unlikely (result == NULL))
- {
- throw _PythonException();
- }
- return result;
- }
- // Return the next item of an iterator. Avoiding any exception for end of iteration, callers must
- // deal with NULL return as end of iteration, but will know it wasn't an Python exception, that will show as a thrown exception.
- static PyObject *ITERATOR_NEXT( PyObject *iterator )
- {
- assert( iterator != NULL );
- assert( iterator->ob_refcnt > 0 );
- int line = _current_line;
- PyObject *result = PyIter_Next( iterator );
- if (unlikely (result == NULL))
- {
- if ( PyErr_Occurred() != NULL )
- {
- _current_line = line;
- throw _PythonException();
- }
- }
- else
- {
- assert( result->ob_refcnt > 0 );
- }
- return result;
- }
- static inline PyObject *UNPACK_NEXT( PyObject *iterator, int seq_size_so_far )
- {
- assert( iterator != NULL );
- assert( iterator->ob_refcnt > 0 );
- PyObject *result = PyIter_Next( iterator );
- if (unlikely (result == NULL))
- {
- if ( seq_size_so_far == 1 )
- {
- PyErr_Format( PyExc_ValueError, "need more than 1 value to unpack" );
- }
- else
- {
- PyErr_Format( PyExc_ValueError, "need more than %d values to unpack", seq_size_so_far );
- }
- throw _PythonException();
- }
- assert( result->ob_refcnt > 0 );
- return result;
- }
- static inline void UNPACK_ITERATOR_CHECK( PyObject *iterator )
- {
- PyObject *attempt = PyIter_Next( iterator );
- if (likely( attempt == NULL ))
- {
- PyErr_Clear();
- }
- else
- {
- Py_DECREF( attempt );
- PyErr_Format( PyExc_ValueError, "too many values to unpack" );
- throw _PythonException();
- }
- }
- static PyObject *SELECT_IF_TRUE( PyObject *object )
- {
- assert( object != NULL );
- assert( object->ob_refcnt > 0 );
- if ( CHECK_IF_TRUE( object ) )
- {
- return object;
- }
- else
- {
- Py_DECREF( object );
- return NULL;
- }
- }
- static PyObject *SELECT_IF_FALSE( PyObject *object )
- {
- assert( object != NULL );
- assert( object->ob_refcnt > 0 );
- if ( CHECK_IF_FALSE( object ) )
- {
- return object;
- }
- else
- {
- Py_DECREF( object );
- return NULL;
- }
- }
- static PyObject *LOOKUP_SUBSCRIPT( PyObject *source, PyObject *subscript )
- {
- assert (source);
- assert (source->ob_refcnt > 0);
- assert (subscript);
- assert (subscript->ob_refcnt > 0);
- PyObject *result = PyObject_GetItem( source, subscript );
- if (unlikely (result == NULL))
- {
- throw _PythonException();
- }
- return result;
- }
- static bool HAS_KEY( PyObject *source, PyObject *key )
- {
- assert (source);
- assert (source->ob_refcnt > 0);
- assert (key);
- assert (key->ob_refcnt > 0);
- return PyMapping_HasKey( source, key ) != 0;
- }
- static PyObject *LOOKUP_VARS( PyObject *source )
- {
- assert (source);
- assert (source->ob_refcnt > 0);
- static PyObject *dict_str = PyString_FromString( "__dict__" );
- PyObject *result = PyObject_GetAttr( source, dict_str );
- if (unlikely (result == NULL))
- {
- throw _PythonException();
- }
- return result;
- }
- static void SET_SUBSCRIPT( PyObject *target, PyObject *subscript, PyObject *value )
- {
- assert (target);
- assert (target->ob_refcnt > 0);
- assert (subscript);
- assert (subscript->ob_refcnt > 0);
- assert (value);
- assert (value->ob_refcnt > 0);
- int status = PyObject_SetItem( target, subscript, value );
- if (unlikely( status == -1 ))
- {
- throw _PythonException();
- }
- }
- static void DEL_SUBSCRIPT( PyObject *target, PyObject *subscript )
- {
- assert (target);
- assert (target->ob_refcnt > 0);
- assert (subscript);
- assert (subscript->ob_refcnt > 0);
- int status = PyObject_DelItem( target, subscript );
- if (unlikely( status == -1 ))
- {
- throw _PythonException();
- }
- }
- static PyObject *LOOKUP_SLICE( PyObject *source, Py_ssize_t lower, Py_ssize_t upper )
- {
- assert (source);
- assert (source->ob_refcnt > 0);
- PyObject *result = PySequence_GetSlice( source, lower, upper);
- if (unlikely (result == NULL))
- {
- throw _PythonException();
- }
- return result;
- }
- static void SET_SLICE( PyObject *target, Py_ssize_t lower, Py_ssize_t upper, PyObject *value )
- {
- assert (target);
- assert (target->ob_refcnt > 0);
- assert (value);
- assert (value->ob_refcnt > 0);
- int status = PySequence_SetSlice( target, lower, upper, value );
- if (unlikely( status == -1 ))
- {
- throw _PythonException();
- }
- }
- static Py_ssize_t CONVERT_TO_INDEX( PyObject *value );
- static void DEL_SLICE( PyObject *target, PyObject *lower, PyObject *upper )
- {
- assert (target);
- assert (target->ob_refcnt > 0);
- if ( target->ob_type->tp_as_sequence && target->ob_type->tp_as_sequence->sq_ass_slice )
- {
- int status = PySequence_DelSlice( target, lower != Py_None ? CONVERT_TO_INDEX( lower ) : 0, upper != Py_None ? CONVERT_TO_INDEX( upper ) : PY_SSIZE_T_MAX );
- if (unlikely( status == -1 ))
- {
- throw _PythonException();
- }
- }
- else
- {
- PyObject *slice = PySlice_New( lower, upper, NULL );
- if (slice == NULL)
- {
- throw _PythonException();
- }
- int status = PyObject_DelItem( target, slice );
- Py_DECREF( slice );
- if (unlikely( status == -1 ))
- {
- throw _PythonException();
- }
- }
- }
- static PyObject *MAKE_SLICEOBJ( PyObject *start, PyObject *stop, PyObject *step )
- {
- assert (start);
- assert (start->ob_refcnt > 0);
- assert (stop);
- assert (stop->ob_refcnt > 0);
- assert (step);
- assert (step->ob_refcnt > 0);
- PyObject *result = PySlice_New( start, stop, step );
- if (unlikely (result == NULL))
- {
- throw _PythonException();
- }
- return result;
- }
- static Py_ssize_t CONVERT_TO_INDEX( PyObject *value )
- {
- assert (value);
- assert (value->ob_refcnt > 0);
- if ( PyInt_Check( value ) )
- {
- return PyInt_AS_LONG( value );
- }
- else if ( PyIndex_Check( value ) )
- {
- Py_ssize_t result = PyNumber_AsSsize_t( value, NULL );
- if (unlikely( result == -1 && PyErr_Occurred() ))
- {
- throw _PythonException();
- }
- return result;
- }
- else
- {
- PyErr_Format( PyExc_TypeError, "slice indices must be integers or None or have an __index__ method" );
- throw _PythonException();
- }
- }
- static PyObject *LOOKUP_ATTRIBUTE( PyObject *source, PyObject *attr_name )
- {
- assert (source);
- assert (source->ob_refcnt > 0);
- assert (attr_name);
- assert (attr_name->ob_refcnt > 0);
- PyObject *result = PyObject_GetAttr( source, attr_name );
- if (unlikely (result == NULL))
- {
- throw _PythonException();
- }
- assert( result->ob_refcnt > 0 );
- return result;
- }
- static void SET_ATTRIBUTE( PyObject *target, PyObject *attr_name, PyObject *value )
- {
- assert (target);
- assert (target->ob_refcnt > 0);
- assert (attr_name);
- assert (attr_name->ob_refcnt > 0);
- assert (value);
- assert (value->ob_refcnt > 0);
- int status = PyObject_SetAttr( target, attr_name, value );
- if (unlikely( status == -1 ))
- {
- throw _PythonException();
- }
- }
- static void DEL_ATTRIBUTE( PyObject *target, PyObject *attr_name )
- {
- assert (target);
- assert (target->ob_refcnt > 0);
- assert (attr_name);
- assert (attr_name->ob_refcnt > 0);
- int status = PyObject_DelAttr( target, attr_name );
- if (unlikely( status == -1 ))
- {
- throw _PythonException();
- }
- }
- static void APPEND_TO_LIST( PyObject *list, PyObject *item)
- {
- int status = PyList_Append( list, item );
- if (unlikely( status == -1 ))
- {
- throw _PythonException();
- }
- }
- static PyObject *SEQUENCE_CONCAT( PyObject *seq1, PyObject *seq2 )
- {
- PyObject *result = PySequence_Concat( seq1, seq2 );
- if (unlikely (result == NULL))
- {
- throw _PythonException();
- }
- return result;
- }
- // Helper class to be used when PyObject * are provided as parameters where they
- // are not consumed, but not needed anymore after the call and and need a release
- // as soon as possible.
- class PyObjectTemporary {
- public:
- explicit PyObjectTemporary( PyObject *object )
- {
- assert( object );
- assert( object->ob_refcnt > 0 );
- this->object = object;
- }
- PyObjectTemporary( const PyObjectTemporary &object ) = delete;
- ~PyObjectTemporary()
- {
- Py_DECREF( this->object );
- }
- PyObject *asObject()
- {
- assert( this->object->ob_refcnt > 0 );
- return this->object;
- }
- void assign( PyObject *object )
- {
- Py_DECREF( this->object );
- assert( object );
- assert( object->ob_refcnt > 0 );
- this->object = object;
- }
- void checkSanity( char const *message ) const
- {
- if ( this->object->ob_refcnt <= 0 )
- {
- puts( message );
- assert( false );
- }
- }
- private:
- PyObject *object;
- };
- class PyObjectLocalDictVariable {
- public:
- explicit PyObjectLocalDictVariable( PyObject *storage, PyObject *var_name, PyObject *object = NULL )
- {
- this->storage = storage;
- this->var_name = var_name;
- if ( object != NULL )
- {
- int status = PyDict_SetItem( this->storage, this->var_name, object );
- assert( status == 0 );
- }
- }
- PyObject *asObject() const
- {
- // TODO: Dictionary quick access code could be used here too.
- PyObject *result = PyDict_GetItem( this->storage, this->var_name );
- if (unlikely (result == NULL))
- {
- PyErr_Format( PyExc_UnboundLocalError, "local variable '%s' referenced before assignment", PyString_AsString( this->var_name ) );
- throw _PythonException();
- }
- assert( result->ob_refcnt > 0 );
- return result;
- }
- void operator=( PyObject *object )
- {
- assert( object );
- assert( object->ob_refcnt > 0 );
- int status = PyDict_SetItem( this->storage, this->var_name, object );
- assert( status == 0 );
- }
- bool isInitialized() const
- {
- return PyDict_Contains( this->storage, this->var_name ) == 1;
- }
- void del()
- {
- int status = PyDict_DelItem( this->storage, this->var_name );
- if (unlikely( status == -1 ))
- {
- // TODO: Probably an error should be raised?
- PyErr_Clear();
- }
- }
- PyObject *getVariableName() const
- {
- return this->var_name;
- }
- private:
- PyObject *storage;
- PyObject *var_name;
- };
- class PyObjectLocalVariable {
- public:
- explicit PyObjectLocalVariable( PyObject *var_name, PyObject *object = NULL, bool free_value = true )
- {
- this->var_name = var_name;
- this->object = object;
- this->free_value = free_value;
- }
- explicit PyObjectLocalVariable() {
- this->var_name = NULL;
- this->object = NULL;
- this->free_value = false;
- }
- ~PyObjectLocalVariable()
- {
- if ( this->free_value )
- {
- // TODO: Why would free_value be true if this->object were NULL.
- Py_XDECREF( this->object );
- }
- }
- void setVariableName( PyObject *var_name )
- {
- assert( var_name );
- assert( var_name->ob_refcnt > 0 );
- assert( this->var_name == NULL);
- this->var_name = var_name;
- }
- void operator=( PyObject *object )
- {
- assert( object );
- assert( object->ob_refcnt > 0 );
- PyObject *old_object = this->free_value ? this->object : NULL;
- this->object = object;
- this->free_value = true;
- // Free old value if any available and owned.
- Py_XDECREF( old_object );
- }
- PyObject *asObject() const
- {
- if ( this->object == NULL && this->var_name != NULL )
- {
- PyErr_Format( PyExc_UnboundLocalError, "local variable '%s' referenced before assignment", PyString_AsString( this->var_name ) );
- throw _PythonException();
- }
- assert( this->object );
- assert( this->object->ob_refcnt > 0 );
- return this->object;
- }
- bool isInitialized() const
- {
- return this->object != NULL;
- }
- void del()
- {
- if ( this->object == NULL )
- {
- PyErr_Format( PyExc_UnboundLocalError, "local variable '%s' referenced before assignment", PyString_AsString( this->var_name ) );
- throw _PythonException();
- }
- if ( this->free_value )
- {
- Py_DECREF( this->object );
- }
- this->object = NULL;
- this->free_value = true;
- }
- PyObject *getVariableName() const
- {
- return this->var_name;
- }
- private:
- PyObject *var_name;
- PyObject *object;
- bool free_value;
- };
- class PyObjectSharedStorage
- {
- public:
- explicit PyObjectSharedStorage( PyObject *var_name, PyObject *object, bool free_value )
- {
- assert( object == NULL || object->ob_refcnt > 0 );
- this->var_name = var_name;
- this->object = object;
- this->free_value = free_value;
- this->ref_count = 1;
- }
- ~PyObjectSharedStorage()
- {
- if ( this->free_value )
- {
- Py_XDECREF( this->object );
- }
- }
- void operator=( PyObject *object )
- {
- assert( object );
- assert( object->ob_refcnt > 0 );
- PyObject *old_object = this->free_value ? this->object : NULL;
- this->object = object;
- this->free_value = true;
- // Free old value if any available and owned.
- Py_XDECREF( old_object );
- }
- PyObject *var_name;
- PyObject *object;
- bool free_value;
- int ref_count;
- };
- class PyObjectSharedLocalVariable
- {
- public:
- explicit PyObjectSharedLocalVariable( PyObject *var_name, PyObject *object = NULL, bool free_value = true )
- {
- this->storage = new PyObjectSharedStorage( var_name, object, free_value );
- }
- explicit PyObjectSharedLocalVariable()
- {
- this->storage = NULL;
- }
- ~PyObjectSharedLocalVariable()
- {
- if ( this->storage )
- {
- assert( this->storage->ref_count > 0 );
- this->storage->ref_count -= 1;
- if (this->storage->ref_count == 0)
- {
- delete this->storage;
- }
- }
- }
- void setVariableName( PyObject *var_name )
- {
- assert( this->storage == NULL );
- this->storage = new PyObjectSharedStorage( var_name, NULL, false );
- }
- void shareWith( const PyObjectSharedLocalVariable &other )
- {
- assert(this->storage == NULL);
- assert(other.storage != NULL);
- this->storage = other.storage;
- this->storage->ref_count += 1;
- }
- void operator=( PyObject *object )
- {
- this->storage->operator=( object );
- }
- PyObject *asObject() const
- {
- assert( this->storage );
- if ( this->storage->object == NULL )
- {
- PyErr_Format( PyExc_UnboundLocalError, "free variable '%s' referenced before assignment in enclosing scope", PyString_AsString( this->storage->var_name ) );
- throw _PythonException();
- }
- if ( (this->storage->object)->ob_refcnt == 0 )
- {
- PyErr_Format( PyExc_UnboundLocalError, "free variable '%s' referenced after its finalization in enclosing scope", PyString_AsString( this->storage->var_name ) );
- throw _PythonException();
- }
- return this->storage->object;
- }
- bool isInitialized() const
- {
- return this->storage->object != NULL;
- }
- PyObject *getVariableName() const
- {
- return this->storage->var_name;
- }
- private:
- PyObjectSharedLocalVariable( PyObjectSharedLocalVariable & );
- PyObjectSharedStorage *storage;
- };
- static PyDictEntry *GET_PYDICT_ENTRY( PyModuleObject *module, PyStringObject *key )
- {
- // Idea similar to LOAD_GLOBAL in CPython. Because the variable name is a string, we
- // can shortcut much of the dictionary code by using its hash and dictionary knowledge
- // here. Only improvement would be to identify how to ensure that the hash is computed
- // already. Calling hash early on could do that potentially.
- long hash = key->ob_shash;
- if ( hash == -1 )
- {
- hash = PyString_Type.tp_hash( (PyObject *)key );
- }
- PyDictObject *dict = (PyDictObject *)(module->md_dict);
- assert( PyDict_CheckExact( dict ));
- PyDictEntry *entry = dict->ma_lookup( dict, (PyObject *)key, hash );
- // The "entry" cannot be NULL, it can only be empty for a string dict lookup, but at
- // least assert it.
- assert( entry != NULL );
- return entry;
- }
- class PyObjectGlobalVariable
- {
- public:
- explicit PyObjectGlobalVariable( PyObject **module_ptr, PyObject **var_name )
- {
- assert( module_ptr );
- assert( var_name );
- this->module_ptr = (PyModuleObject **)module_ptr;
- this->var_name = (PyStringObject **)var_name;
- }
- PyObject *asObject() const
- {
- PyDictEntry *entry = GET_PYDICT_ENTRY( *this->module_ptr, *this->var_name );
- if (likely( entry->me_value != NULL ))
- {
- return INCREASE_REFCOUNT( entry->me_value );
- }
- entry = GET_PYDICT_ENTRY( _module_builtin, *this->var_name );
- if (likely( entry->me_value != NULL ))
- {
- return INCREASE_REFCOUNT( entry->me_value );
- }
- PyErr_Format( PyExc_NameError, "global name %s is not defined", PyString_AsString( (PyObject *)*this->var_name ) );
- throw _PythonException();
- }
- PyObject *asObject( PyObject *dict ) const
- {
- if ( PyDict_Contains( dict, (PyObject *)*this->var_name ) )
- {
- return PyDict_GetItem( dict, (PyObject *)*this->var_name );
- }
- else
- {
- return this->asObject();
- }
- }
- void assign( PyObject *value ) const
- {
- PyDictEntry *entry = GET_PYDICT_ENTRY( *this->module_ptr, *this->var_name );
- // Values are more likely set than not set, in that case speculatively try the
- // quickest access method.
- if (likely( entry->me_value != NULL ))
- {
- PyObject *old = entry->me_value;
- entry->me_value = value;
- Py_DECREF( old );
- }
- else
- {
- DICT_SET_ITEM( (*this->module_ptr)->md_dict, (PyObject *)*this->var_name, value );
- Py_DECREF( value );
- }
- }
- void assign0( PyObject *value ) const
- {
- DICT_SET_ITEM( (*this->module_ptr)->md_dict, (PyObject *)*this->var_name, value );
- }
- void del() const
- {
- int status = PyDict_DelItem( (*this->module_ptr)->md_dict, (PyObject *)*this->var_name );
- if (unlikely( status == -1 ))
- {
- PyErr_Format( PyExc_NameError, "name '%s' is not defined", PyString_AsString( (PyObject *)*this->var_name ) );
- throw _PythonException();
- }
- }
- bool isInitialized() const
- {
- PyDictEntry *entry = GET_PYDICT_ENTRY( *this->module_ptr, *this->var_name );
- if (likely( entry->me_value != NULL ))
- {
- return true;
- }
- entry = GET_PYDICT_ENTRY( _module_builtin, *this->var_name );
- return entry->me_value != NULL;
- }
- private:
- PyModuleObject **module_ptr;
- PyStringObject **var_name;
- };
- static PyObject *MAKE_LOCALS_DICT( void )
- {
- return MAKE_DICT();
- }
- template<typename T>
- static void FILL_LOCALS_DICT( PyObject *dict, T variable )
- {
- if ( variable->isInitialized() )
- {
- int status = PyDict_SetItem( dict, variable->getVariableName(), variable->asObject() );
- if (unlikely( status == -1 ))
- {
- throw _PythonException();
- }
- }
- }
- template<typename T, typename... P>
- static void FILL_LOCALS_DICT( PyObject *dict, T variable, P... variables )
- {
- if ( variable->isInitialized() )
- {
- int status = PyDict_SetItem( dict, variable->getVariableName(), variable->asObject() );
- if (unlikely( status == -1 ))
- {
- throw _PythonException();
- }
- }
- FILL_LOCALS_DICT( dict, variables... );
- }
- template<typename... P>
- static PyObject *MAKE_LOCALS_DICT( P...variables )
- {
- PyObject *result = MAKE_LOCALS_DICT();
- FILL_LOCALS_DICT( result, variables... );
- return result;
- }
- static PyObject *MAKE_LOCALS_DIR( void )
- {
- return MAKE_LIST();
- }
- template<typename T>
- static void FILL_LOCALS_DIR( PyObject *list, T variable )
- {
- if ( variable->isInitialized() )
- {
- int status = PyList_Append( list, variable->getVariableName() );
- if (unlikely( status == -1 ))
- {
- throw _PythonException();
- }
- }
- }
- template<typename T, typename... P>
- static void FILL_LOCALS_DIR( PyObject *list, T variable, P... variables )
- {
- if ( variable->isInitialized() )
- {
- int status = PyList_Append( list, variable->getVariableName() );
- if (unlikely( status == -1 ))
- {
- throw _PythonException();
- }
- }
- FILL_LOCALS_DIR( list, variables... );
- }
- template<typename... P>
- static PyObject *MAKE_LOCALS_DIR( P...variables )
- {
- PyObject *result = MAKE_LOCALS_DIR();
- FILL_LOCALS_DIR( result, variables... );
- return result;
- }
- static PyObject *TUPLE_COPY( PyObject *tuple )
- {
- assert( tuple != NULL );
- assert( tuple->ob_refcnt > 0 );
- assert( PyTuple_CheckExact( tuple ) );
- Py_ssize_t size = PyTuple_GET_SIZE( tuple );
- PyObject *result = PyTuple_New( size );
- if (unlikely (result == NULL))
- {
- throw _PythonException();
- }
- for ( Py_ssize_t i = 0; i < size; i++ )
- {
- PyTuple_SET_ITEM( result, i, INCREASE_REFCOUNT( PyTuple_GET_ITEM( tuple, i ) ) );
- }
- return result;
- }
- static PyObject *LIST_COPY( PyObject *list )
- {
- assert( list != NULL );
- assert( list->ob_refcnt > 0 );
- assert( PyList_CheckExact( list ) );
- Py_ssize_t size = PyList_GET_SIZE( list );
- PyObject *result = PyList_New( size );
- if (unlikely (result == NULL))
- {
- throw _PythonException();
- }
- for ( Py_ssize_t i = 0; i < size; i++ )
- {
- PyList_SET_ITEM( result, i, INCREASE_REFCOUNT( PyList_GET_ITEM( list, i ) ) );
- }
- return result;
- }
- class PythonBuiltin
- {
- public:
- explicit PythonBuiltin( char const *name )
- {
- this->name = name;
- this->value = NULL;
- }
- PyObject *asObject()
- {
- if ( this->value == NULL )
- {
- // TODO: Use GET_PYDICT_ENTRY here too.
- this->value = PyObject_GetAttrString( (PyObject *)_module_builtin, this->name );
- }
- assert( this->value != NULL );
- return this->value;
- }
- private:
- char const *name;
- PyObject *value;
- };
- static PythonBuiltin _python_builtin_compile( "compile" );
- static PyObject *COMPILE_CODE( PyObject *source_code, PyObject *file_name, PyObject *mode, int flags )
- {
- // May be a source, but also could already be a compiled object, in which case this
- // should just return it.
- if ( PyCode_Check( source_code ) )
- {
- return INCREASE_REFCOUNT( source_code );
- }
- // Workaround leading whitespace causing a trouble to compile builtin, but not eval builtin
- PyObject *source;
- if ( ( PyString_Check( source_code ) || PyUnicode_Check( source_code ) ) && strcmp( PyString_AsString( mode ), "exec" ) != 0 )
- {
- static PyObject *strip_str = PyString_FromString( "strip" );
- // TODO: There is an API to call a method, use it instead.
- source = LOOKUP_ATTRIBUTE( source_code, strip_str );
- source = PyObject_CallFunctionObjArgs( source, NULL );
- assert( source );
- }
- else if ( PyFile_Check( source_code ) && strcmp( PyString_AsString( mode ), "exec" ) == 0 )
- {
- static PyObject *read_str = PyString_FromString( "read" );
- // TODO: There is an API to call a method, use it instead.
- source = LOOKUP_ATTRIBUTE( source_code, read_str );
- source = PyObject_CallFunctionObjArgs( source, NULL );
- assert( source );
- }
- else
- {
- source = source_code;
- }
- PyObject *future_flags = PyInt_FromLong( flags );
- PyObject *result = PyObject_CallFunctionObjArgs(
- _python_builtin_compile.asObject(),
- source,
- file_name,
- mode,
- future_flags, // flags
- _python_bool_True, // dont_inherit
- NULL
- );
- Py_DECREF( future_flags );
- if (unlikely (result == NULL))
- {
- throw _PythonException();
- }
- return result;
- }
- static PythonBuiltin _python_builtin_open( "open" );
- static PyObject *OPEN_FILE( PyObject *file_name, PyObject *mode, PyObject *buffering )
- {
- PyObject *result = PyObject_CallFunctionObjArgs(
- _python_builtin_open.asObject(),
- file_name,
- mode,
- buffering,
- NULL
- );
- if (unlikely (result == NULL))
- {
- throw _PythonException();
- }
- return result;
- }
- static PyObject *EVAL_CODE( PyObject *code, PyObject *globals, PyObject *locals )
- {
- if ( PyDict_Check( globals ) == 0 )
- {
- PyErr_Format( PyExc_TypeError, "exec: arg 2 must be a dictionary or None" );
- throw _PythonException();
- }
- if ( locals == NULL || locals == Py_None )
- {
- locals = globals;
- }
- if ( PyMapping_Check( locals ) == 0 )
- {
- PyErr_Format( PyExc_TypeError, "exec: arg 3 must be a mapping or None" );
- throw _PythonException();
- }
- // Set the __builtin__ in globals, it is expected to be present.
- if ( PyMapping_HasKeyString( globals, (char *)"__builtins__" ) == 0 )
- {
- if ( PyMapping_SetItemString( globals, (char *)"__builtins__", (PyObject *)_module_builtin ) == -1 )
- {
- throw _PythonException();
- }
- }
- PyObject *result = PyEval_EvalCode( (PyCodeObject *)code, globals, locals );
- if (unlikely (result == NULL))
- {
- throw _PythonException();
- }
- return result;
- }
- static PyObject *empty_code = PyBuffer_FromMemory( NULL, 0 );
- static PyCodeObject *MAKE_CODEOBJ( PyObject *filename, PyObject *function_name, int line )
- {
- // TODO: Potentially it is possible to create a line2no table that will allow to use
- // only one code object per function, this could then be cached and presumably be much
- // faster, because it could be reused.
- assert( PyString_Check( filename ));
- assert( PyString_Check( function_name ));
- assert( empty_code );
- // printf( "MAKE_CODEOBJ code object %d\n", empty_code->ob_refcnt );
- PyCodeObject *result = PyCode_New (
- 0, 0, 0, 0, // argcount, locals, stacksize, flags
- empty_code, //
- _python_tuple_empty,
- _python_tuple_empty,
- _python_tuple_empty,
- _python_tuple_empty,
- _python_tuple_empty,
- filename,
- function_name,
- line,
- _python_str_empty
- );
- if (unlikely( result == NULL ))
- {
- throw _PythonException();
- }
- return result;
- }
- static PyFrameObject *MAKE_FRAME( PyObject *module, PyObject *filename, PyObject *function_name, int line )
- {
- PyCodeObject *code = MAKE_CODEOBJ( filename, function_name, line );
- PyFrameObject *result = PyFrame_New(
- PyThreadState_GET(),
- code,
- ((PyModuleObject *)module)->md_dict,
- NULL // No locals yet
- );
- Py_DECREF( code );
- if (unlikely( result == NULL ))
- {
- throw _PythonException();
- }
- result->f_lineno = line;
- return result;
- }
- static PyTracebackObject *MAKE_TRACEBACK_START( PyFrameObject *frame, int line )
- {
- PyTracebackObject *result = PyObject_GC_New( PyTracebackObject, &PyTraceBack_Type );
- result->tb_next = NULL;
- Py_INCREF( frame );
- result->tb_frame = frame;
- result->tb_lasti = 0;
- result->tb_lineno = line;
- PyObject_GC_Track( result );
- return result;
- }
- static void ADD_TRACEBACK( PyObject *module, PyObject *filename, PyObject *function_name, int line )
- {
- // TODO: The frame object really might deserve a longer life that this, it is
- // relatively expensive to create.
- PyFrameObject *frame = MAKE_FRAME( module, filename, function_name, line );
- // Inlining PyTraceBack_Here may be faster
- PyTraceBack_Here( frame );
- Py_DECREF( frame );
- }
- #ifdef _NUITKA_EXE
- static bool FIND_EMBEDDED_MODULE( char const *name );
- #endif
- static PyObject *IMPORT_MODULE( PyObject *module_name, PyObject *import_name )
- {
- #ifdef _NUITKA_EXE
- // First try our own package resistent form of frozen modules if we have
- // them embedded. And avoid recursion here too, in case of cyclic dependencies.
- if ( !HAS_KEY( PySys_GetObject( (char *)"modules" ), module_name ) )
- {
- if ( FIND_EMBEDDED_MODULE( PyString_AsString( module_name ) ) )
- {
- return LOOKUP_SUBSCRIPT( PySys_GetObject( (char *)"modules" ), import_name );
- }
- }
- #endif
- int line = _current_line;
- PyObject *result = PyImport_ImportModuleEx( PyString_AsString( module_name ), NULL, NULL, NULL );
- if (unlikely( result == NULL ))
- {
- _current_line = line;
- throw _PythonException();
- }
- // Release the reference returned from the __import__ call, we don't trust it, because
- // it doesn't work well with packages. Look up in sys.modules instead.
- Py_DECREF( result );
- return LOOKUP_SUBSCRIPT( PySys_GetObject( (char *)"modules" ), import_name );
- }
- static void IMPORT_MODULE_STAR( PyObject *target, bool is_module, PyObject *module_name )
- {
- PyObject *module = IMPORT_MODULE( module_name, module_name );
- // IMPORT_MODULE would raise exception already
- assert( module != NULL );
- PyObject *iter;
- bool all_case;
- if ( PyObject *all = PyMapping_GetItemString( module, (char *)"__all__" ) )
- {
- iter = MAKE_ITERATOR( all );
- all_case = true;
- }
- else
- {
- PyErr_Clear();
- iter = MAKE_ITERATOR( PyModule_GetDict( module ) );
- all_case = false;
- }
- while ( PyObject *item = PyIter_Next( iter ) )
- {
- assert( PyString_Check( item ) );
- // TODO: Not yet clear, what happens with __all__ and "_" of its contents.
- if ( all_case == false )
- {
- if ( PyString_AS_STRING( item )[0] == '_' )
- {
- continue;
- }
- }
- // TODO: Check if the reference is handled correctly
- if ( is_module )
- {
- SET_ATTRIBUTE( target, item, LOOKUP_ATTRIBUTE( module, item ) );
- }
- else
- {
- SET_SUBSCRIPT( target, item, LOOKUP_ATTRIBUTE( module, item ) );
- }
- Py_DECREF( item );
- }
- if ( PyErr_Occurred() )
- {
- throw _PythonException();
- }
- }
- // *** Nuitka_Function type begin
- typedef void (*releaser)( void * );
- // The Nuitka_FunctionObject is the storage associated with a compiled function instance
- // of which there can be many for each code.
- typedef struct {
- PyObject_HEAD
- PyObject *m_name;
- void *m_context;
- releaser m_cleanup;
- PyObject *m_module;
- PyObject *m_doc;
- void *m_code;
- bool m_has_args;
- PyObject *m_dict;
- PyObject *m_weakrefs;
- long m_counter;
- } Nuitka_FunctionObject;
- // tp_descr_get slot, bind a function to an object.
- static PyObject *Nuitka_Function_descr_get( PyObject *function, PyObject *object, PyObject *klass )
- {
- return PyMethod_New( function, object == Py_None ? NULL : object, klass );
- }
- // tp_repr slot, decide how a function shall be output
- static PyObject *Nuitka_Function_repr( Nuitka_FunctionObject *object )
- {
- return PyString_FromFormat( "<compiled function %s at %p>", PyString_AsString( object->m_name ), object );
- }
- static PyObject *Nuitka_Function_tp_call( Nuitka_FunctionObject *function, PyObject *args, PyObject *kw )
- {
- if ( function->m_has_args )
- {
- return ((PyCFunctionWithKeywords)function->m_code)( (PyObject *)function->m_context, args, kw );
- }
- else
- {
- return ((PyNoArgsFunction)function->m_code)( (PyObject *)function->m_context );
- }
- }
- static long Nuitka_Function_tp_traverse( PyObject *function, visitproc visit, void *arg )
- {
- // TODO: Identify the impact of not visiting owned objects and/or if it could be NULL
- // instead. The methodobject visits its self and module. I understand this is probably
- // so that back references of this function to its upper do not make it stay in the
- // memory. A specific test if that works might be needed.
- return 0;
- }
- static int Nuitka_Function_tp_compare( Nuitka_FunctionObject *a, Nuitka_FunctionObject *b )
- {
- if ( a->m_counter == b->m_counter )
- {
- return 0;
- }
- else
- {
- return a->m_counter < b->m_counter ? -1 : 1;
- }
- }
- static long Nuitka_Function_tp_hash( Nuitka_FunctionObject *function )
- {
- return function->m_counter;
- }
- static PyObject *Nuitka_Function_get_name( Nuitka_FunctionObject *object )
- {
- return INCREASE_REFCOUNT( object->m_name );
- }
- static int Nuitka_Function_set_name( Nuitka_FunctionObject *object, PyObject *value )
- {
- if (value == NULL || PyString_Check( value ) == 0)
- {
- PyErr_Format( PyExc_TypeError, "__name__ must be set to a string object" );
- return -1;
- }
- PyObject *old = object->m_name;
- Py_DECREF( old );
- object->m_name = INCREASE_REFCOUNT( value );
- return 0;
- }
- static PyObject *Nuitka_Function_get_doc( Nuitka_FunctionObject *object )
- {
- return INCREASE_REFCOUNT( object->m_doc );
- }
- static int Nuitka_Function_set_doc( Nuitka_FunctionObject *object, PyObject *value )
- {
- if ( value == Py_None || value == NULL )
- {
- object->m_doc = Py_None;
- }
- else if ( PyString_Check( value ) == 0 )
- {
- PyErr_Format( PyExc_TypeError, "__name__ must be set to a string object" );
- return -1;
- }
- else
- {
- object->m_doc = INCREASE_REFCOUNT( value );
- }
- return 0;
- }
- static PyObject *Nuitka_Function_get_dict( Nuitka_FunctionObject *object )
- {
- if ( object->m_dict == NULL )
- {
- object->m_dict = PyDict_New();
- }
- return INCREASE_REFCOUNT( object->m_dict );
- }
- static int Nuitka_Function_set_dict( Nuitka_FunctionObject *object, PyObject *value )
- {
- if (value == NULL)
- {
- PyErr_Format( PyExc_TypeError, "function's dictionary may not be deleted");
- return -1;
- }
- if ( PyDict_Check(value) )
- {
- PyObject *old = object->m_dict;
- object->m_dict = INCREASE_REFCOUNT( value );
- Py_DECREF( object->m_dict );
- }
- else
- {
- PyErr_SetString( PyExc_TypeError, "setting function's dictionary to a non-dict" );
- return -1;
- }
- }
- static int Nuitka_Function_set_globals( Nuitka_FunctionObject *object, PyObject *value )
- {
- PyErr_Format( PyExc_TypeError, "readonly attribute" );
- return -1;
- }
- static PyObject *Nuitka_Function_get_globals( Nuitka_FunctionObject *object )
- {
- return INCREASE_REFCOUNT( PyModule_GetDict( object->m_module ) );
- }
- static int Nuitka_Function_set_module( Nuitka_FunctionObject *object, PyObject *value )
- {
- if ( object->m_dict == NULL )
- {
- object->m_dict = PyDict_New();
- }
- return PyDict_SetItemString( object->m_dict, (char * )"__module__", value );
- }
- static PyObject *Nuitka_Function_get_module( Nuitka_FunctionObject *object )
- {
- if ( object->m_dict )
- {
- PyObject *result = PyDict_GetItemString( object->m_dict, (char * )"__module__" );
- if ( result != NULL )
- {
- return INCREASE_REFCOUNT( result );
- }
- }
- int res = Nuitka_Function_set_module( object, PyString_FromString( PyModule_GetName( object->m_module ) ) );
- assert( res == 0 );
- return PyDict_GetItemString( object->m_dict, (char * )"__module__" );
- }
- static PyGetSetDef Nuitka_Function_getset[] =
- {
- { (char *)"func_name", (getter)Nuitka_Function_get_name, (setter)Nuitka_Function_set_name, NULL },
- { (char *)"__name__" , (getter)Nuitka_Function_get_name, (setter)Nuitka_Function_set_name, NULL },
- { (char *)"func_doc", (getter)Nuitka_Function_get_doc, (setter)Nuitka_Function_set_doc, NULL },
- { (char *)"__doc__" , (getter)Nuitka_Function_get_doc, (setter)Nuitka_Function_set_doc, NULL },
- { (char *)"func_dict", (getter)Nuitka_Function_get_dict, (setter)Nuitka_Function_set_dict, NULL },
- { (char *)"__dict__", (getter)Nuitka_Function_get_dict, (setter)Nuitka_Function_set_dict, NULL },
- { (char *)"func_globals", (getter)Nuitka_Function_get_globals, (setter)Nuitka_Function_set_globals, NULL },
- { (char *)"__globals__", (getter)Nuitka_Function_get_globals, (setter)Nuitka_Function_set_globals, NULL },
- { (char *)"__module__", (getter)Nuitka_Function_get_module, (setter)Nuitka_Function_set_module, NULL },
- { NULL }
- };
- static void Nuitka_Function_tp_dealloc( Nuitka_FunctionObject *function )
- {
- _PyObject_GC_UNTRACK( function );
- if ( function->m_weakrefs != NULL )
- {
- PyObject_ClearWeakRefs( (PyObject *)function );
- }
- Py_DECREF( function->m_name );
- Py_XDECREF( function->m_dict );
- if ( function->m_context )
- {
- function->m_cleanup( function->m_context );
- }
- PyObject_GC_Del( function );
- }
- static PyTypeObject Nuitka_Function_Type =
- {
- PyVarObject_HEAD_INIT(&PyType_Type, 0)
- "compiled_function_or_method", // tp_name
- sizeof(Nuitka_FunctionObject), // tp_basicsize
- 0, // tp_itemsize
- (destructor)Nuitka_Function_tp_dealloc, // tp_dealloc
- 0, // tp_print
- 0, // tp_getattr
- 0, // tp_setattr
- (cmpfunc)Nuitka_Function_tp_compare, // tp_compare
- (reprfunc)Nuitka_Function_repr, // tp_repr
- 0, // tp_as_number
- 0, // tp_as_sequence
- 0, // tp_as_mapping
- (hashfunc)Nuitka_Function_tp_hash, // tp_hash
- (ternaryfunc)Nuitka_Function_tp_call, // tp_call
- 0, // tp_str
- PyObject_GenericGetAttr, // tp_getattro
- 0, // tp_setattro
- 0, // tp_as_buffer
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags
- 0, // tp_doc
- (traverseproc)Nuitka_Function_tp_traverse, // tp_traverse
- 0, // tp_clear
- 0, // tp_richcompare
- offsetof( Nuitka_FunctionObject, m_weakrefs ), // tp_weaklistoffset
- 0, // tp_iter
- 0, // tp_iternext
- 0, // tp_methods
- 0, // tp_members
- Nuitka_Function_getset, // tp_getset
- 0, // tp_base
- 0, // tp_dict
- Nuitka_Function_descr_get, // tp_descr_get
- 0, // tp_descr_set
- offsetof( Nuitka_FunctionObject, m_dict ), // tp_dictoffset
- 0, // tp_init
- 0, // tp_alloc
- 0, // tp_new
- 0, // tp_free
- 0, // tp_is_gc
- 0, // tp_bases
- 0, // tp_mro
- 0, // tp_cache
- 0, // tp_subclasses
- 0, // tp_weaklist
- 0, // tp_del
- };
- static inline PyObject *make_kfunction( void *code, PyObject *name, PyObject *module, PyObject *doc, bool has_args, void *context, releaser cleanup )
- {
- Nuitka_FunctionObject *result = PyObject_GC_New( Nuitka_FunctionObject, &Nuitka_Function_Type );
- if ( result == NULL )
- {
- PyErr_Format( PyExc_RuntimeError, "cannot create function %s", PyString_AsString( name ) );
- throw _PythonException();
- }
- result->m_code = code;
- result->m_has_args = has_args;
- result->m_name = INCREASE_REFCOUNT( name );
- result->m_context = context;
- result->m_cleanup = cleanup;
- result->m_module = module;
- result->m_doc = doc;
- result->m_dict = NULL;
- result->m_weakrefs = NULL;
- static long Nuitka_Function_counter = 0;
- result->m_counter = Nuitka_Function_counter++;
- _PyObject_GC_TRACK( result );
- return (PyObject *)result;
- }
- // Make a function without context.
- static PyObject *Nuitka_Function_New( PyCFunctionWithKeywords code, PyObject *name, PyObject *module, PyObject *doc )
- {
- return make_kfunction( (void *)code, name, module, doc, true, NULL, NULL );
- }
- // Make a function with context.
- static PyObject *Nuitka_Function_New( PyCFunctionWithKeywords code, PyObject *name, PyObject *module, PyObject *doc, void *context, releaser cleanup )
- {
- return make_kfunction( (void *)code, name, module, doc, true, context, cleanup );
- }
- // Make a function that is only a yielder, no args.
- static PyObject *Nuitka_Function_New( PyNoArgsFunction code, PyObject *name, PyObject *module, PyObject *doc, void *context, releaser cleanup )
- {
- return make_kfunction( (void *)code, name, module, doc, false, context, cleanup );
- }
- // *** KFunction type end
- // *** Nuitka_Generator/Nuitka_Genexpr shared begin
- enum class Generator_Status {
- status_Unused, // Not used so far
- status_Running, // Running, used but didn't stop yet
- status_Finished // Stoped, no more values to come
- };
- // *** Nuitka_Generator type begin
- #include <ucontext.h>
- // The Nuitka_GeneratorObject is the storage associated with a compiled generator object
- // instance of which there can be many for each code.
- typedef struct {
- PyObject_HEAD
- PyObject *m_name;
- ucontext_t m_yielder_context;
- ucontext_t m_caller_context;
- void *m_context;
- releaser m_cleanup;
- // TODO: Clarify if weakrefs are supported for generator objects in CPython.
- PyObject *m_weakrefs;
- bool m_running;
- void *m_code;
- PyObject *m_yielded;
- PyObject *m_exception_type, *m_exception_value, *m_exception_tb;
- // Was it ever used, is it still running, or already finished.
- Generator_Status m_status;
- } Nuitka_GeneratorObject;
- static PyObject *Nuitka_Generator_tp_repr( Nuitka_GeneratorObject *generator )
- {
- return PyString_FromFormat( "<compiled generator object %s at %p>", PyString_AsString( generator->m_name ), generator );
- }
- static long Nuitka_Generator_tp_traverse( PyObject *function, visitproc visit, void *arg )
- {
- // TODO: Identify the impact of not visiting owned objects and/or if it could be NULL
- // instead. The methodobject visits its self and module. I understand this is probably
- // so that back references of this function to its upper do not make it stay in the
- // memory. A specific test if that works might be needed.
- return 0;
- }
- static PyObject *Nuitka_Generator_send( Nuitka_GeneratorObject *generator, PyObject *value )
- {
- if ( generator->m_status == Generator_Status::status_Unused && value != NULL && value != Py_None )
- {
- PyErr_Format( PyExc_TypeError, "can't send non-None value to a just-started generator" );
- return NULL;
- }
- if ( generator->m_status != Generator_Status::status_Finished )
- {
- if ( generator->m_running )
- {
- PyErr_Format( PyExc_ValueError, "generator already executing" );
- return NULL;
- }
- if ( generator->m_status == Generator_Status::status_Unused )
- {
- generator->m_status = Generator_Status::status_Running;
- // Prepare the generator context to run. TODO: Make stack size rational.
- generator->m_yielder_context.uc_stack.ss_size = 1024*1024;
- generator->m_yielder_context.uc_stack.ss_sp = malloc( generator->m_yielder_context.uc_stack.ss_size );
- getcontext( &generator->m_yielder_context );
- makecontext( &generator->m_yielder_context, (void (*)())generator->m_code, 1, generator );
- }
- generator->m_yielded = value;
- generator->m_running = true;
- // Continue the yielder function.
- swapcontext( &generator->m_caller_context, &generator->m_yielder_context );
- generator->m_running = false;
- if ( generator->m_yielded == NULL )
- {
- generator->m_status = Generator_Status::status_Finished;
- return NULL;
- }
- else
- {
- return generator->m_yielded;
- }
- }
- else
- {
- PyErr_SetNone( PyExc_StopIteration );
- return NULL;
- }
- }
- static PyObject *Nuitka_Generator_tp_iternext( Nuitka_GeneratorObject *generator )
- {
- return Nuitka_Generator_send( generator, Py_None );
- }
- static PyObject *Nuitka_Generator_close( Nuitka_GeneratorObject *generator, PyObject *args )
- {
- if ( generator->m_status != Generator_Status::status_Finished )
- {
- generator->m_exception_type = PyExc_GeneratorExit;
- generator->m_exception_value = NULL;
- generator->m_exception_tb = NULL;
- PyObject *result = Nuitka_Generator_send( generator, Py_None );
- if (!( result == NULL || PyErr_ExceptionMatches( PyExc_StopIteration ) || PyErr_ExceptionMatches( PyExc_GeneratorExit )))
- {
- Py_XDECREF( result );
- PyErr_Format( PyExc_RuntimeError, "generator refused GeneratorExit" );
- return NULL;
- }
- PyErr_Clear();
- }
- return INCREASE_REFCOUNT( Py_None );
- }
- static void Nuitka_Generator_tp_dealloc( Nuitka_GeneratorObject *generator )
- {
- assert( generator->ob_refcnt == 0 );
- generator->ob_refcnt = 1;
- PyObject *close_result = Nuitka_Generator_close( generator, NULL );
- Py_XDECREF( close_result );
- assert( generator->ob_refcnt == 1 );
- generator->ob_refcnt = 0;
- free( generator->m_yielder_context.uc_stack.ss_sp );
- // Now it is safe to release references and memory for it.
- _PyObject_GC_UNTRACK( generator );
- if ( generator->m_weakrefs != NULL )
- {
- PyObject_ClearWeakRefs( (PyObject *)generator );
- }
- if ( generator->m_context )
- {
- generator->m_cleanup( generator->m_context );
- }
- Py_DECREF( generator->m_name );
- PyObject_GC_Del( generator );
- }
- static PyObject *Nuitka_Generator_throw( Nuitka_GeneratorObject *generator, PyObject *args )
- {
- generator->m_exception_value = NULL;
- generator->m_exception_tb = NULL;
- int res = PyArg_UnpackTuple( args, "throw", 1, 3, &generator->m_exception_type, &generator->m_exception_value, &generator->m_exception_tb );
- if ( res == 0 )
- {
- generator->m_exception_type = NULL;
- return NULL;
- }
- if ( generator->m_status != Generator_Status::status_Finished )
- {
- return Nuitka_Generator_send( generator, Py_None );
- }
- else
- {
- return Py_None;
- }
- }
- static PyObject *Nuitka_Generator_get_name( Nuitka_GeneratorObject *generator )
- {
- return INCREASE_REFCOUNT( generator->m_name );
- }
- static PyGetSetDef Nuitka_Generator_getsetlist[] =
- {
- { (char * )"__name__", (getter)Nuitka_Generator_get_name, NULL, NULL },
- { NULL }
- };
- static PyMethodDef Nuitka_Generator_methods[] =
- {
- { "send", (PyCFunction)Nuitka_Generator_send, METH_O, NULL },
- {"throw", (PyCFunction)Nuitka_Generator_throw, METH_VARARGS, NULL },
- {"close", (PyCFunction)Nuitka_Generator_close, METH_NOARGS, NULL },
- { NULL }
- };
- static PyTypeObject Nuitka_Generator_Type =
- {
- PyVarObject_HEAD_INIT(&PyType_Type, 0)
- "compiled_generator", // tp_name
- sizeof(Nuitka_GeneratorObject), // tp_basicsize
- 0, // tp_itemsize
- (destructor)Nuitka_Generator_tp_dealloc, // tp_dealloc
- 0, // tp_print
- 0, // tp_getattr
- 0, // tp_setattr
- // TODO: Compare should be easy, check the benefit of doing it.
- 0, // tp_compare
- (reprfunc)Nuitka_Generator_tp_repr, // tp_repr
- 0, // tp_as_number
- 0, // tp_as_sequence
- 0, // tp_as_mapping
- 0, // tp_hash
- 0, // tp_call
- 0, // tp_str
- PyObject_GenericGetAttr, // tp_getattro
- 0, // tp_setattro
- 0, // tp_as_buffer
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags
- 0, // tp_doc
- (traverseproc)Nuitka_Generator_tp_traverse, // tp_traverse
- 0, // tp_clear
- 0, // tp_richcompare
- offsetof( Nuitka_GeneratorObject, m_weakrefs ), // tp_weaklistoffset
- PyObject_SelfIter, // tp_iter
- (iternextfunc)Nuitka_Generator_tp_iternext, // tp_iternext
- Nuitka_Generator_methods, // tp_methods
- 0, // tp_members
- Nuitka_Generator_getsetlist, // tp_getset
- 0, // tp_base
- 0, // tp_dict
- 0, // tp_descr_get
- 0, // tp_descr_set
- 0, // tp_dictoffset
- 0, // tp_init
- 0, // tp_alloc
- 0, // tp_new
- 0, // tp_free
- 0, // tp_is_gc
- 0, // tp_bases
- 0, // tp_mro
- 0, // tp_cache
- 0, // tp_subclasses
- 0, // tp_weaklist
- 0 // tp_del
- };
- typedef void (*yielder_func)( Nuitka_GeneratorObject * );
- static PyObject *Nuitka_Generator_New( yielder_func code, PyObject *name, void *context, releaser cleanup )
- {
- Nuitka_GeneratorObject *result = PyObject_GC_New( Nuitka_GeneratorObject, &Nuitka_Generator_Type );
- if ( result == NULL )
- {
- PyErr_Format( PyExc_RuntimeError, "cannot create genexpr %s", PyString_AsString( name ) );
- throw _PythonException();
- }
- result->m_code = (void *)code;
- result->m_name = INCREASE_REFCOUNT( name );
- result->m_context = context;
- result->m_cleanup = cleanup;
- result->m_weakrefs = NULL;
- result->m_status = Generator_Status::status_Unused;
- result->m_running = false;
- result->m_yielder_context.uc_stack.ss_sp = NULL;
- result->m_yielder_context.uc_link = NULL;
- result->m_exception_type = NULL;
- _PyObject_GC_TRACK( result );
- return (PyObject *)result;
- }
- static void CHECK_EXCEPTION( Nuitka_GeneratorObject *generator )
- {
- if ( generator->m_exception_type )
- {
- Py_INCREF( generator->m_exception_type );
- Py_XINCREF( generator->m_exception_value );
- Py_XINCREF( generator->m_exception_tb );
- PyErr_Restore( generator->m_exception_type, generator->m_exception_value, generator->m_exception_tb );
- generator->m_exception_type = NULL;
- throw _PythonException();
- }
- }
- static PyObject *YIELD_VALUE( Nuitka_GeneratorObject *generator, PyObject *value )
- {
- generator->m_yielded = value;
- swapcontext( &generator->m_yielder_context, &generator->m_caller_context );
- CHECK_EXCEPTION( generator );
- return generator->m_yielded;
- }
- // *** Nuitka_Generator type end
- // *** Nuitka_Genexpr type begin
- // TODO: Could optimize it through a compile time determination.
- const int MAX_ITERATOR_COUNT = 20;
- // The Nuitka_GenexprObject is the storage associated with a compiled generator object
- // instance of which there can be many for each code.
- typedef struct {
- PyObject_HEAD
- PyObject *m_name;
- void *m_context;
- releaser m_cleanup;
- PyObject *m_weakrefs;
- bool m_running;
- void *m_code;
- // Was it ever used, is it still running, or already finished.
- Generator_Status m_status;
- // Store the iterator provided at creation time here.
- PyObject *iterators[ MAX_ITERATOR_COUNT ];
- int iterator_level;
- } Nuitka_GenexprObject;
- typedef PyObject * (*producer)( Nuitka_GenexprObject * );
- static PyObject *Nuitka_Genexpr_tp_repr( Nuitka_GenexprObject *generator )
- {
- return PyString_FromFormat( "<compiled generator object <%s> at %p>", PyString_AsString( generator->m_name ), generator );
- }
- static long Nuitka_Genexpr_tp_traverse( PyObject *function, visitproc visit, void *arg )
- {
- // TODO: Identify the impact of not visiting owned objects and/or if it could be NULL
- // instead. The methodobject visits its self and module. I understand this is probably
- // so that back references of this function to its upper do not make it stay in the
- // memory. A specific test if that works might be needed.
- return 0;
- }
- static void Nuitka_Genexpr_tp_dealloc( Nuitka_GenexprObject *generator )
- {
- // Now it is safe to release references and memory for it.
- _PyObject_GC_UNTRACK( generator );
- if ( generator->m_weakrefs != NULL )
- {
- PyObject_ClearWeakRefs( (PyObject *)generator );
- }
- if ( generator->m_context )
- {
- generator->m_cleanup( generator->m_context );
- }
- Py_DECREF( generator->m_name );
- for( int i = 0; i <= generator->iterator_level; i++ )
- {
- if ( generator->iterators[ i ] )
- {
- Py_DECREF( generator->iterators[ i ] );
- }
- }
- PyObject_GC_Del( generator );
- }
- static PyObject *Nuitka_Genexpr_tp_iternext( Nuitka_GenexprObject *generator )
- {
- if ( generator->m_status != Generator_Status::status_Finished )
- {
- if ( generator->m_running )
- {
- PyErr_Format( PyExc_ValueError, "generator already executing" );
- return NULL;
- }
- generator->m_running = true;
- // Query the next value
- PyObject *result = ((producer)(generator->m_code))( generator );
- generator->m_running = false;
- if ( result == _sentinel_value )
- {
- generator->m_status = Generator_Status::status_Finished;
- PyErr_SetNone( PyExc_StopIteration );
- return NULL;
- }
- else
- {
- if ( result )
- {
- generator->m_status = Generator_Status::status_Running;
- }
- else
- {
- generator->m_status = Generator_Status::status_Finished;
- }
- return result;
- }
- }
- else
- {
- PyErr_SetNone( PyExc_StopIteration );
- return NULL;
- }
- }
- static PyObject *Nuitka_Genexpr_send( Nuitka_GenexprObject *generator, PyObject *value )
- {
- if ( generator->m_status == Generator_Status::status_Unused && value != NULL && value != Py_None )
- {
- PyErr_Format( PyExc_TypeError, "can't send non-None value to a just-started generator" );
- return NULL;
- }
- return Nuitka_Genexpr_tp_iternext( generator );
- }
- static PyObject *Nuitka_Genexpr_close( Nuitka_GenexprObject *generator, PyObject *args )
- {
- generator->m_status = Generator_Status::status_Finished;
- return INCREASE_REFCOUNT( Py_None );
- }
- static PyObject *Nuitka_Genexpr_throw( Nuitka_GenexprObject *generator, PyObject *args )
- {
- PyObject *exception_type, *exception_value, *exception_tb;
- int res = PyArg_UnpackTuple( args, "throw", 1, 3, &exception_type, &exception_value, &exception_tb );
- if ( res == 0 )
- {
- return NULL;
- }
- PyErr_Restore( exception_type, exception_value, exception_tb );
- generator->m_status = Generator_Status::status_Finished;
- return NULL;
- }
- static PyObject *Nuitka_Genexpr_get_name( Nuitka_GenexprObject *generator )
- {
- return INCREASE_REFCOUNT( generator->m_name );
- }
- static PyGetSetDef Nuitka_Genexpr_getsetlist[] =
- {
- { (char * )"__name__", (getter)Nuitka_Genexpr_get_name, NULL, NULL },
- { NULL }
- };
- static PyMethodDef Nuitka_Genexpr_methods[] =
- {
- { "send", (PyCFunction)Nuitka_Genexpr_send, METH_O, NULL },
- {"throw", (PyCFunction)Nuitka_Genexpr_throw, METH_VARARGS, NULL },
- {"close", (PyCFunction)Nuitka_Genexpr_close, METH_NOARGS, NULL },
- { NULL }
- };
- static PyTypeObject Nuitka_Genexpr_Type =
- {
- PyVarObject_HEAD_INIT(&PyType_Type, 0)
- "compiled_generator", // tp_name
- sizeof(Nuitka_GenexprObject), // tp_basicsize
- 0, // tp_itemsize
- (destructor)Nuitka_Genexpr_tp_dealloc, // tp_dealloc
- 0, // tp_print
- 0, // tp_getattr
- 0, // tp_setattr
- // TODO: Compare should be easy, check the benefit of doing it.
- 0, // tp_compare
- (reprfunc)Nuitka_Genexpr_tp_repr, // tp_repr
- 0, // tp_as_number
- 0, // tp_as_sequence
- 0, // tp_as_mapping
- 0, // tp_hash
- 0, // tp_call
- 0, // tp_str
- PyObject_GenericGetAttr, // tp_getattro
- 0, // tp_setattro
- 0, // tp_as_buffer
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags
- 0, // tp_doc
- (traverseproc)Nuitka_Genexpr_tp_traverse, // tp_traverse
- 0, // tp_clear
- 0, // tp_richcompare
- offsetof( Nuitka_GenexprObject, m_weakrefs ), // tp_weaklistoffset
- PyObject_SelfIter, // tp_iter
- (iternextfunc)Nuitka_Genexpr_tp_iternext, // tp_iternext
- Nuitka_Genexpr_methods, // tp_methods
- 0, // tp_members
- Nuitka_Genexpr_getsetlist, // tp_getset
- 0, // tp_base
- 0, // tp_dict
- 0, // tp_descr_get
- 0, // tp_descr_set
- 0 , // tp_dictoffset
- 0, // tp_init
- 0, // tp_alloc
- 0, // tp_new
- 0, // tp_free
- 0, // tp_is_gc
- 0, // tp_bases
- 0, // tp_mro
- 0, // tp_cache
- 0, // tp_subclasses
- 0, // tp_weaklist
- 0 // tp_del
- };
- static PyObject *Nuitka_Genexpr_New( producer code, PyObject *name, PyObject *iterated, int iterator_count, void *context, releaser cleanup )
- {
- Nuitka_GenexprObject *result = PyObject_GC_New( Nuitka_GenexprObject, &Nuitka_Genexpr_Type );
- if ( result == NULL )
- {
- PyErr_Format( PyExc_RuntimeError, "cannot create genexpr %s", PyString_AsString( name ) );
- throw _PythonException();
- }
- result->m_code = (void *)code;
- result->m_name = INCREASE_REFCOUNT( name );
- result->m_context = context;
- result->m_cleanup = cleanup;
- result->m_weakrefs = NULL;
- result->m_status = Generator_Status::status_Unused;
- result->m_running = false;
- // Store the iterator information provided at creation time here.
- assert( iterator_count < MAX_ITERATOR_COUNT );
- result->iterator_level = 0;
- result->iterators[ 0 ] = MAKE_ITERATOR( iterated );
- for( int i = 1; i < iterator_count; i++ )
- {
- result->iterators[ i ] = NULL;
- }
- _PyObject_GC_TRACK( result );
- return (PyObject *)result;
- }
- // *** Nuitka_Genexpr type end
- // The _module___main__ is a Python object pointer of module type.
- // Note: For full compatability with CPython, every module variable access needs to go
- // through it except for cases where the module cannot possibly have changed in the mean
- // time.
- static PyObject *_module___main__;
- // The module level variables.
- static PyObjectGlobalVariable _mvar___main_____doc__( &_module___main__, &_python_str_plain___doc__ );
- static PyObjectGlobalVariable _mvar___main_____file__( &_module___main__, &_python_str_plain___file__ );
- static PyObjectGlobalVariable _mvar___main___all( &_module___main__, &_python_str_plain_all );
- static PyObjectGlobalVariable _mvar___main___i( &_module___main__, &_python_str_plain_i );
- static PyObjectGlobalVariable _mvar___main___int( &_module___main__, &_python_str_plain_int );
- static PyObjectGlobalVariable _mvar___main___math( &_module___main__, &_python_str_plain_math );
- static PyObjectGlobalVariable _mvar___main___num_primes( &_module___main__, &_python_str_plain_num_primes );
- static PyObjectGlobalVariable _mvar___main___xrange( &_module___main__, &_python_str_plain_xrange );
- // The module function declarations.
- static PyObject *MAKE_FUNCTION_genexpr_1_of_module_hello( PyObject *iterator );
- // The module function definitions.
- // This structure is for attachment as self of genexpr_1_of_module_hello.
- // It is allocated at the time the genexpr object is created.
- struct _context_genexpr_1_of_module_hello_t
- {
- // The generator expression can access a read-only closure of the creator.
- PyObjectLocalVariable python_var_j;
- PyObjectLocalVariable python_var_i;
- };
- static void _context_genexpr_1_of_module_hello_destructor( void *context_voidptr )
- {
- _context_genexpr_1_of_module_hello_t *_python_context = (struct _context_genexpr_1_of_module_hello_t *)context_voidptr;
- delete _python_context;
- }
- // The function that is iterated over during generator expression execution. It is supposed to yield the next
- // value as a return value.
- static PyObject *genexpr_1_of_module_hello( Nuitka_GenexprObject *generator )
- {
- // The context of the genexpr.
- struct _context_genexpr_1_of_module_hello_t *_python_context = (struct _context_genexpr_1_of_module_hello_t *)generator->m_context;
- _current_line = 5;
- try
- {
- while ( generator->iterator_level != -1 && generator->iterator_level < 1 )
- {
- if ( generator->iterators[ generator->iterator_level ] == NULL )
- {
- switch( generator->iterator_level )
- {
- case 0:
- assert( false );
- break;
- }
- }
- // Need to construct the iterators except level 0 here and create their iterator
- // if it is NULL
- PyObject *_python_genexpr_iter_value = ITERATOR_NEXT( generator->iterators[ generator->iterator_level ] );
- if ( _python_genexpr_iter_value == NULL )
- {
- Py_DECREF( generator->iterators[ generator->iterator_level ] );
- generator->iterators[ generator->iterator_level ] = NULL;
- generator->iterator_level -= 1;
- }
- else
- {
- bool condition;
- switch( generator->iterator_level )
- {
- case 0:
- _python_context->python_var_j = INCREASE_REFCOUNT( _python_genexpr_iter_value );
- condition = true;
- break;
- }
- // plug condition here, just don't increase if it mismatches
- if ( condition )
- {
- generator->iterator_level += 1;
- }
- }
- }
- if ( generator->iterator_level == -1 )
- {
- return _sentinel_value;
- }
- else
- {
- generator->iterator_level = 1 - 1;
- // Actual expressions generated.
- return BINARY_OPERATION( PyNumber_Remainder, PyObjectTemporary( _mvar___main___i.asObject() ).asObject(), _python_context->python_var_j.asObject() );
- }
- }
- catch ( _PythonException &_exception )
- {
- _exception.toPython();
- ADD_TRACEBACK( _module___main__, _python_str_digest_8d35108ffe2ad173a697734a3e9938e1, _python_str_angle_hello__genexpr, _exception.getLine() );
- return NULL;
- }
- }
- static PyObject *MAKE_FUNCTION_genexpr_1_of_module_hello( PyObject *iterated )
- {
- struct _context_genexpr_1_of_module_hello_t *_python_context = new _context_genexpr_1_of_module_hello_t;
- // Copy the closure values over.
- PyObject *result = Nuitka_Genexpr_New( genexpr_1_of_module_hello, _python_str_plain_hello__genexpr, iterated, 1, _python_context, _context_genexpr_1_of_module_hello_destructor );
- return result;
- }
- // The exported interface to CPython. On import of the module, this function gets called. It has have that exact function
- // name.
- static PyTracebackObject *MAKE_TRACEBACK___main__( int line )
- {
- PyFrameObject *frame = MAKE_FRAME( _module___main__, _python_str_digest_8d35108ffe2ad173a697734a3e9938e1, _python_str_angle_module, line );
- PyTracebackObject *result = MAKE_TRACEBACK_START( frame, line );
- Py_DECREF( frame );
- assert( result );
- return result;
- }
- NUITKA_MODULE_INIT_FUNCTION init__main__(void)
- {
- // puts( "in init__main__" );
- // Create the module object first. There are no methods initially, all are added
- // dynamically in actual code only. Also no __doc__ is initially set, as it could not
- // contain 0 this way, added early in actual code. No self for modules, we have no
- // use for it.
- _module___main__ = Py_InitModule4(
- "__main__", // Module Name
- NULL, // No methods initially, all are added dynamically in actual code only.
- NULL, // No __doc__ is initially set, as it could not contain 0 this way, added early in actual code.
- NULL, // No self for modules, we don't use it.
- PYTHON_API_VERSION
- );
- assert( _module___main__ );
- // Initialize the constant values used.
- _initConstants();
- // Initialize the compiled types of Nuitka.
- PyType_Ready( &Nuitka_Function_Type );
- PyType_Ready( &Nuitka_Genexpr_Type );
- // Initialize the standard module attributes.
- _mvar___main_____doc__.assign0( Py_None );
- _mvar___main_____file__.assign0( _python_str_digest_8d35108ffe2ad173a697734a3e9938e1 );
- // Module code
- bool traceback = false;
- try
- {
- _current_line = 1;
- _mvar___main___math.assign( IMPORT_MODULE( _python_str_plain_math, _python_str_plain_math ) );
- _current_line = 3;
- _mvar___main___num_primes.assign( INCREASE_REFCOUNT( _python_int_0 ) );
- _current_line = 4;
- {
- PyObjectTemporary _python_for_loop_iterator_1( MAKE_ITERATOR( PyObjectTemporary( CALL_FUNCTION( NULL, _python_tuple_int_pos_2_int_pos_500000, PyObjectTemporary( _mvar___main___xrange.asObject() ).asObject() ) ).asObject() ) );
- while( true )
- {
- _current_line = 4;
- PyObject *_python_for_loop_itervalue_1 = ITERATOR_NEXT( _python_for_loop_iterator_1.asObject() );
- // Check if end of iterator is reached
- if ( _python_for_loop_itervalue_1 == NULL )
- {
- break;
- }
- {
- PyObjectTemporary _python_tmp_itertemp_1( _python_for_loop_itervalue_1 );
- _mvar___main___i.assign( INCREASE_REFCOUNT( _python_tmp_itertemp_1.asObject() ) );
- }
- _current_line = 5;
- if ( CHECK_IF_TRUE( PyObjectTemporary( CALL_FUNCTION( NULL, PyObjectTemporary( MAKE_TUPLE( PyObjectTemporary( MAKE_FUNCTION_genexpr_1_of_module_hello( PyObjectTemporary( CALL_FUNCTION( NULL, PyObjectTemporary( MAKE_TUPLE( PyObjectTemporary( BINARY_OPERATION( PyNumber_Add, PyObjectTemporary( CALL_FUNCTION( NULL, PyObjectTemporary( MAKE_TUPLE( PyObjectTemporary( CALL_FUNCTION( NULL, PyObjectTemporary( MAKE_TUPLE( PyObjectTemporary( _mvar___main___i.asObject() ).asObject() ) ).asObject(), PyObjectTemporary( LOOKUP_ATTRIBUTE( PyObjectTemporary( _mvar___main___math.asObject() ).asObject(), _python_str_plain_sqrt ) ).asObject() ) ).asObject() ) ).asObject(), PyObjectTemporary( _mvar___main___int.asObject() ).asObject() ) ).asObject(), _python_int_pos_1 ) ).asObject(), _python_int_pos_2 ) ).asObject(), PyObjectTemporary( _mvar___main___xrange.asObject() ).asObject() ) ).asObject() ) ).asObject() ) ).asObject(), PyObjectTemporary( _mvar___main___all.asObject() ).asObject() ) ).asObject() ) )
- {
- _current_line = 6;
- {
- PyObjectTemporary value( _mvar___main___num_primes.asObject() );
- PyObject *result = BINARY_OPERATION( PyNumber_InPlaceAdd, value.asObject(), _python_int_pos_1 );
- if ( result != value.asObject() )
- {
- _mvar___main___num_primes.assign( INCREASE_REFCOUNT( result ) );
- }
- Py_DECREF( result );
- }
- }
- }
- }
- _current_line = 7;
- PRINT_ITEMS( true, NULL, PyObjectTemporary( _mvar___main___num_primes.asObject() ).asObject() );
- }
- catch ( _PythonException &_exception )
- {
- _exception.toPython();
- if ( traceback == false )
- {
- ADD_TRACEBACK( _module___main__, _python_str_digest_8d35108ffe2ad173a697734a3e9938e1, _python_str_angle_module, _exception.getLine() );
- }
- }
- }
- // The main program for C++. It needs to prepare the interpreter and then calls the
- // initialization code of the __main__ module.
- static struct _inittab _module_inittab[] =
- {
- NULL, NULL
- };
- static bool FIND_EMBEDDED_MODULE( char const *name )
- {
- struct _inittab *current = _module_inittab;
- while (current->name)
- {
- if ( strcmp( name, current->name ) == 0 )
- {
- current->initfunc();
- if ( PyErr_Occurred() )
- {
- throw _PythonException();
- }
- return true;
- }
- current++;
- }
- return false;
- }
- int main( int argc, char *argv[] )
- {
- // Register the initialization functions for modules included in the binary if any
- int res = PyImport_ExtendInittab( _module_inittab );
- assert( res != -1 );
- Py_Initialize();
- PySys_SetArgv( argc, argv );
- init__main__();
- if ( PyErr_Occurred() )
- {
- PyErr_Print();
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment